Files
worldmodel/plans/hotel_scene_implementation_plan_part2.md
T

22 KiB
Raw Blame History

酒店场景室内建模与物理验证项目详细实施计划(续)

七、数据管理与存储架构(续)

7.2 数据库设计

-- PostgreSQL + PostGIS空间数据库

-- 场景表
CREATE TABLE scenes (
    scene_id SERIAL PRIMARY KEY,
    scene_type VARCHAR(50),  -- 'lobby', 'corridor', 'room', 'bathroom'
    hotel_name VARCHAR(100),
    floor_number INTEGER,
    capture_date TIMESTAMP,
    sensor_config JSONB,
    bbox_min GEOMETRY(POINTZ, 4326),
    bbox_max GEOMETRY(POINTZ, 4326),
    metadata JSONB
);

-- 物体实例表
CREATE TABLE object_instances (
    instance_id SERIAL PRIMARY KEY,
    scene_id INTEGER REFERENCES scenes(scene_id),
    label VARCHAR(100),
    category VARCHAR(50),
    centroid GEOMETRY(POINTZ, 4326),
    bbox_min GEOMETRY(POINTZ, 4326),
    bbox_max GEOMETRY(POINTZ, 4326),
    volume FLOAT,
    mesh_path TEXT,
    semantic_features VECTOR(512),  -- CLIP特征,使用pgvector扩展
    attributes JSONB,  -- {material, color, state, affordance}
    confidence FLOAT
);

-- 空间关系表
CREATE TABLE spatial_relations (
    relation_id SERIAL PRIMARY KEY,
    source_instance_id INTEGER REFERENCES object_instances(instance_id),
    target_instance_id INTEGER REFERENCES object_instances(instance_id),
    relation_type VARCHAR(50),  -- 'supported_by', 'inside', 'next_to', 'above'
    confidence FLOAT,
    metadata JSONB
);

-- 重建模型表
CREATE TABLE reconstruction_models (
    model_id SERIAL PRIMARY KEY,
    scene_id INTEGER REFERENCES scenes(scene_id),
    model_type VARCHAR(50),  -- '3dgs', 'nerf', 'mesh'
    file_path TEXT,
    quality_metrics JSONB,  -- {psnr, ssim, lpips}
    training_config JSONB,
    created_at TIMESTAMP
);

-- 物理属性表
CREATE TABLE physics_properties (
    property_id SERIAL PRIMARY KEY,
    instance_id INTEGER REFERENCES object_instances(instance_id),
    mass FLOAT,
    friction_static FLOAT,
    friction_dynamic FLOAT,
    restitution FLOAT,
    is_articulated BOOLEAN,
    joint_type VARCHAR(50),  -- 'revolute', 'prismatic', 'fixed'
    joint_params JSONB
);

-- 创建空间索引
CREATE INDEX idx_scenes_bbox ON scenes USING GIST(bbox_min);
CREATE INDEX idx_instances_centroid ON object_instances USING GIST(centroid);
CREATE INDEX idx_instances_semantic ON object_instances USING ivfflat(semantic_features vector_cosine_ops);

7.3 数据存储方案

存储层级:
  热数据(频繁访问):
    - 存储: NVMe SSD RAID 10
    - 容量: 4TB
    - 内容: 
      - 当前处理中的原始数据
      - 训练好的3DGS/NeRF模型
      - 数据库文件
    - 备份: 每日增量备份
  
  温数据(偶尔访问):
    - 存储: SATA HDD RAID 6
    - 容量: 20TB
    - 内容:
      - 历史原始数据
      - 中间处理结果
      - 渲染缓存
    - 备份: 每周全量备份
  
  冷数据(归档):
    - 存储: 对象存储(MinIO/S3
    - 容量: 无限扩展
    - 内容:
      - 完成项目的完整数据集
      - 多版本模型
      - 实验日志
    - 备份: 异地容灾

对象存储结构:
  bucket: hotel-reconstruction
  ├── raw-data/
  │   └── {hotel_name}/{scene_type}/{date}/
  ├── processed/
  │   └── {hotel_name}/{scene_type}/{version}/
  ├── models/
  │   └── {model_type}/{scene_id}/{checkpoint}/
  └── exports/
      └── {format}/{scene_id}/

7.4 数据版本控制

使用DVCData Version Control:
  
  初始化:
    $ dvc init
    $ dvc remote add -d storage s3://hotel-reconstruction
  
  跟踪大文件:
    $ dvc add data/rooms/room_301/raw/
    $ git add data/rooms/room_301/raw/.dvc
    $ git commit -m "Add room 301 raw data"
  
  版本切换:
    $ git checkout v1.0
    $ dvc checkout
  
  数据管道:
    # dvc.yaml
    stages:
      slam:
        cmd: python scripts/run_slam.py
        deps:
          - data/raw/
          - scripts/run_slam.py
        outs:
          - data/processed/slam/
      
      3dgs_training:
        cmd: python scripts/train_3dgs.py
        deps:
          - data/processed/slam/
          - scripts/train_3dgs.py
        outs:
          - models/3dgs/
        metrics:
          - metrics/3dgs_quality.json

八、评测基准与验证方案

8.1 几何重建质量评测

8.1.1 点云精度评测

class GeometryEvaluator:
    def __init__(self, ground_truth_mesh, reconstructed_pointcloud):
        self.gt_mesh = ground_truth_mesh
        self.recon_pc = reconstructed_pointcloud
        
    def compute_chamfer_distance(self):
        """Chamfer距离(双向最近点距离)"""
        # GT mesh采样点云
        gt_pc = self.gt_mesh.sample_points_uniformly(100000)
        
        # 重建点云 → GT点云
        dist_recon_to_gt = self.nearest_neighbor_distance(
            self.recon_pc, gt_pc
        )
        
        # GT点云 → 重建点云
        dist_gt_to_recon = self.nearest_neighbor_distance(
            gt_pc, self.recon_pc
        )
        
        chamfer = (dist_recon_to_gt.mean() + dist_gt_to_recon.mean()) / 2
        
        return {
            'chamfer_distance': chamfer,
            'recon_to_gt_mean': dist_recon_to_gt.mean(),
            'gt_to_recon_mean': dist_gt_to_recon.mean(),
            'recon_to_gt_std': dist_recon_to_gt.std()
        }
    
    def compute_accuracy_completeness(self, threshold=0.05):
        """准确率与完整性(阈值:5cm"""
        gt_pc = self.gt_mesh.sample_points_uniformly(100000)
        
        dist_recon_to_gt = self.nearest_neighbor_distance(
            self.recon_pc, gt_pc
        )
        dist_gt_to_recon = self.nearest_neighbor_distance(
            gt_pc, self.recon_pc
        )
        
        # 准确率:重建点中有多少在GT附近
        accuracy = (dist_recon_to_gt < threshold).mean()
        
        # 完整性:GT点中有多少被重建覆盖
        completeness = (dist_gt_to_recon < threshold).mean()
        
        # F-score
        f_score = 2 * accuracy * completeness / (accuracy + completeness + 1e-8)
        
        return {
            'accuracy': accuracy,
            'completeness': completeness,
            'f_score': f_score
        }
    
    def compute_normal_consistency(self):
        """法线一致性"""
        # 估计重建点云的法线
        recon_normals = self.estimate_normals(self.recon_pc)
        
        # 对于每个重建点,找到GT mesh上最近的面
        closest_faces = self.find_closest_faces(self.recon_pc, self.gt_mesh)
        gt_normals = self.gt_mesh.face_normals[closest_faces]
        
        # 计算法线夹角
        dot_products = np.abs((recon_normals * gt_normals).sum(axis=1))
        normal_consistency = dot_products.mean()
        
        return normal_consistency

8.1.2 渲染质量评测

class RenderingEvaluator:
    def __init__(self, model, test_cameras, ground_truth_images):
        self.model = model
        self.test_cameras = test_cameras
        self.gt_images = ground_truth_images
        
    def evaluate_all_metrics(self):
        results = {
            'psnr': [],
            'ssim': [],
            'lpips': [],
            'rendering_time': []
        }
        
        for cam, gt_img in zip(self.test_cameras, self.gt_images):
            # 渲染
            start_time = time.time()
            rendered_img = self.model.render(cam)
            render_time = time.time() - start_time
            
            # 计算指标
            psnr = self.compute_psnr(rendered_img, gt_img)
            ssim = self.compute_ssim(rendered_img, gt_img)
            lpips = self.compute_lpips(rendered_img, gt_img)
            
            results['psnr'].append(psnr)
            results['ssim'].append(ssim)
            results['lpips'].append(lpips)
            results['rendering_time'].append(render_time)
        
        # 统计
        summary = {
            'psnr_mean': np.mean(results['psnr']),
            'psnr_std': np.std(results['psnr']),
            'ssim_mean': np.mean(results['ssim']),
            'lpips_mean': np.mean(results['lpips']),
            'fps': 1.0 / np.mean(results['rendering_time'])
        }
        
        return summary
    
    def compute_psnr(self, img1, img2):
        """峰值信噪比"""
        mse = np.mean((img1 - img2) ** 2)
        if mse == 0:
            return float('inf')
        return 20 * np.log10(1.0 / np.sqrt(mse))
    
    def compute_ssim(self, img1, img2):
        """结构相似性"""
        from skimage.metrics import structural_similarity
        return structural_similarity(
            img1, img2, 
            multichannel=True,
            data_range=1.0
        )
    
    def compute_lpips(self, img1, img2):
        """感知相似性(使用预训练网络)"""
        import lpips
        loss_fn = lpips.LPIPS(net='alex')
        
        # 转换为tensor
        img1_t = torch.from_numpy(img1).permute(2, 0, 1).unsqueeze(0)
        img2_t = torch.from_numpy(img2).permute(2, 0, 1).unsqueeze(0)
        
        return loss_fn(img1_t, img2_t).item()

8.2 语义理解评测

class SemanticEvaluator:
    def __init__(self, predicted_instances, ground_truth_instances):
        self.pred = predicted_instances
        self.gt = ground_truth_instances
        
    def compute_3d_iou(self):
        """3D IoUIntersection over Union"""
        ious = []
        
        for pred_inst in self.pred:
            best_iou = 0
            
            for gt_inst in self.gt:
                if pred_inst['label'] != gt_inst['label']:
                    continue
                
                # 计算3D包围盒IoU
                intersection = self.bbox_intersection(
                    pred_inst['bbox'], gt_inst['bbox']
                )
                union = self.bbox_union(
                    pred_inst['bbox'], gt_inst['bbox']
                )
                
                iou = intersection / (union + 1e-8)
                best_iou = max(best_iou, iou)
            
            ious.append(best_iou)
        
        return np.mean(ious)
    
    def compute_map_3d(self, iou_threshold=0.5):
        """3D目标检测的mAP"""
        # 按类别分组
        categories = set([inst['label'] for inst in self.gt])
        
        aps = []
        for category in categories:
            pred_cat = [p for p in self.pred if p['label'] == category]
            gt_cat = [g for g in self.gt if g['label'] == category]
            
            # 按置信度排序
            pred_cat = sorted(pred_cat, key=lambda x: x['confidence'], reverse=True)
            
            # 计算precision-recall
            tp = np.zeros(len(pred_cat))
            fp = np.zeros(len(pred_cat))
            
            matched_gt = set()
            
            for i, pred in enumerate(pred_cat):
                best_iou = 0
                best_gt_idx = -1
                
                for j, gt in enumerate(gt_cat):
                    if j in matched_gt:
                        continue
                    
                    iou = self.compute_iou_3d(pred['bbox'], gt['bbox'])
                    if iou > best_iou:
                        best_iou = iou
                        best_gt_idx = j
                
                if best_iou >= iou_threshold:
                    tp[i] = 1
                    matched_gt.add(best_gt_idx)
                else:
                    fp[i] = 1
            
            # 累积
            tp_cumsum = np.cumsum(tp)
            fp_cumsum = np.cumsum(fp)
            
            recalls = tp_cumsum / len(gt_cat)
            precisions = tp_cumsum / (tp_cumsum + fp_cumsum + 1e-8)
            
            # 计算AP11点插值)
            ap = self.compute_ap(recalls, precisions)
            aps.append(ap)
        
        return np.mean(aps)
    
    def evaluate_scene_graph(self, pred_graph, gt_graph):
        """场景图评测"""
        # 节点准确率
        node_precision = len(set(pred_graph.nodes) & set(gt_graph.nodes)) / len(pred_graph.nodes)
        node_recall = len(set(pred_graph.nodes) & set(gt_graph.nodes)) / len(gt_graph.nodes)
        
        # 边准确率
        edge_precision = len(set(pred_graph.edges) & set(gt_graph.edges)) / len(pred_graph.edges)
        edge_recall = len(set(pred_graph.edges) & set(gt_graph.edges)) / len(gt_graph.edges)
        
        return {
            'node_precision': node_precision,
            'node_recall': node_recall,
            'edge_precision': edge_precision,
            'edge_recall': edge_recall
        }

8.3 物理交互评测

class PhysicsEvaluator:
    def __init__(self, simulator, world_model):
        self.sim = simulator
        self.model = world_model
        
    def evaluate_prediction_accuracy(self, test_scenarios):
        """评估物理预测准确性"""
        results = []
        
        for scenario in test_scenarios:
            # 初始状态
            initial_state = scenario['initial_state']
            action = scenario['action']
            
            # 真实仿真结果
            self.sim.set_state(initial_state)
            self.sim.apply_action(action)
            self.sim.step(n_steps=100)
            true_final_state = self.sim.get_state()
            
            # 世界模型预测
            predicted_final_state = self.model.predict(
                initial_state, action, n_steps=100
            )
            
            # 计算误差
            position_error = np.linalg.norm(
                true_final_state['positions'] - predicted_final_state['positions']
            )
            
            velocity_error = np.linalg.norm(
                true_final_state['velocities'] - predicted_final_state['velocities']
            )
            
            results.append({
                'scenario': scenario['name'],
                'position_error': position_error,
                'velocity_error': velocity_error
            })
        
        return results
    
    def evaluate_robot_task_success(self, tasks):
        """评估机器人任务成功率"""
        success_count = 0
        
        for task in tasks:
            # 执行任务
            success = self.execute_task_with_model(task)
            
            if success:
                success_count += 1
        
        success_rate = success_count / len(tasks)
        
        return {
            'success_rate': success_rate,
            'total_tasks': len(tasks),
            'successful_tasks': success_count
        }
    
    def evaluate_zero_shot_generalization(self, novel_scenarios):
        """评估零样本泛化能力"""
        # 在未见过的物体/场景上测试
        results = []
        
        for scenario in novel_scenarios:
            # 使用世界模型进行规划
            plan = self.model.plan(scenario['goal'])
            
            # 执行并评估
            success = self.execute_plan(plan, scenario)
            
            results.append({
                'scenario': scenario['name'],
                'success': success,
                'plan_length': len(plan)
            })
        
        return results

8.4 综合评测基准

评测套件: HotelScene-Bench

子基准1_几何重建:
  数据集: 10个酒店场景(公共区域 + 客房 + 卫生间)
  指标:
    - Chamfer Distance < 3cm
    - Accuracy@5cm > 95%
    - Completeness@5cm > 90%
    - Normal Consistency > 0.85
  
子基准2_渲染质量:
  测试视角: 每场景100个新视角
  指标:
    - PSNR > 28 dB
    - SSIM > 0.85
    - LPIPS < 0.15
    - FPS > 30 @ 1080p
  
子基准3_语义理解:
  标注物体: 500+实例
  指标:
    - 3D mAP@0.5 > 70%
    - 场景图节点F1 > 0.80
    - 场景图边F1 > 0.65
    - 开放词表检测准确率 > 60%
  
子基准4_物理交互:
  任务类型:
    - 导航(10个场景)
    - 物体操作(50个任务)
    - 铰接物体交互(30个任务)
  指标:
    - 导航成功率 > 85%
    - 抓取成功率 > 75%
    - 开门/拉抽屉成功率 > 80%
    - 物理预测误差 < 10cm
  
子基准5_卫生间专项:
  场景: 5个高反光卫生间
  指标:
    - 镜面几何恢复准确率 > 80%
    - 玻璃透明物体检测率 > 70%
    - 水龙头操作成功率 > 75%

九、项目实施时间规划

9.1 总体时间线(12个月)

gantt
    title 酒店场景建模项目甘特图
    dateFormat YYYY-MM-DD
    
    section 准备阶段
    硬件采购与到货           :p1, 2026-06-01, 30d
    传感器标定与测试         :p2, after p1, 14d
    软件环境搭建             :p3, 2026-06-01, 21d
    
    section 数据采集
    公共区域采集             :d1, after p2, 14d
    客房采集(5间)          :d2, after d1, 21d
    卫生间采集               :d3, after d2, 14d
    
    section 算法开发
    SLAM建图模块             :a1, after p3, 30d
    3DGS训练流程             :a2, after a1, 21d
    语义理解模块             :a3, after a2, 30d
    Ref-NeRF实现             :a4, after a3, 21d
    
    section 系统集成
    场景图构建               :i1, after a3, 21d
    物理仿真集成             :i2, after i1, 30d
    M-JEPA训练               :i3, after i2, 45d
    
    section 验证与优化
    评测基准构建             :v1, after i2, 21d
    机器人实验               :v2, after i3, 30d
    系统优化迭代             :v3, after v2, 30d
    
    section 成果输出
    论文撰写                 :o1, after v2, 60d
    开源准备                 :o2, after v3, 21d
    文档编写                 :o3, after o2, 14d

9.2 详细里程碑

月份 里程碑 关键交付物 验收标准
M1 项目启动 硬件到位、环境搭建完成 传感器标定误差 < 5mm
M2 数据采集完成 3个场景原始数据 数据完整性 > 95%
M3 SLAM建图验证 公共区域点云地图 闭环误差 < 0.5%
M4 3DGS训练完成 实时渲染模型 PSNR > 26 dB
M5 语义理解集成 场景图数据库 mAP@0.5 > 60%
M6 卫生间模块完成 Ref-NeRF模型 镜面恢复准确率 > 75%
M7 物理仿真就绪 Isaac Sim场景 可交互物体 > 50个
M8 M-JEPA训练完成 世界模型权重 预测误差 < 15cm
M9 机器人实验 任务成功率报告 综合成功率 > 70%
M10 系统优化 优化后模型 性能提升 > 20%
M11 论文投稿 会议论文 投稿至顶会
M12 开源发布 GitHub仓库、数据集 文档完整度 100%

9.3 人力资源配置

团队组成(建议):
  
  项目负责人(PI)× 1:
    - 职责: 总体把控、对外合作、论文指导
    - 投入: 20% 时间
  
  算法工程师 × 2:
    - 职责: SLAM、3DGS、NeRF算法实现与优化
    - 技能: C++/Python、CUDA、计算机视觉
    - 投入: 100% 时间
  
  机器学习工程师 × 1:
    - 职责: M-JEPA训练、语义理解模块
    - 技能: PyTorch、Transformer、强化学习
    - 投入: 100% 时间
  
  机器人工程师 × 1:
    - 职责: Isaac Sim集成、机器人实验
    - 技能: ROS2、物理仿真、机械臂控制
    - 投入: 100% 时间
  
  数据工程师 × 1:
    - 职责: 数据采集、标注、数据库管理
    - 技能: 传感器操作、SQL、数据处理
    - 投入: 80% 时间(前6个月100%
  
  研究助理 × 2:
    - 职责: 实验辅助、评测、文档编写
    - 投入: 50% 时间

十、风险管理与应对策略

10.1 技术风险

风险项 概率 影响 应对策略
卫生间高反光重建失败 1. 提前进行小规模测试
2. 准备备选方案(手动建模)
3. 与偏振相机厂商技术支持
3DGS训练不收敛 1. 使用成熟的开源实现
2. 调整学习率和初始化
3. 分块训练降低难度
M-JEPA物理预测不准确 1. 增加仿真数据量
2. 引入物理先验约束
3. 降低预测时长要求
实时性能不达标 1. 使用LOD技术
2. 模型剪枝与量化
3. 升级GPU硬件
语义分割精度低 1. 人工标注补充训练
2. 使用更大的基础模型
3. 多模型集成

10.2 工程风险

风险项 概率 影响 应对策略
硬件故障或延期 1. 提前2周下单
2. 准备备用设备
3. 建立供应商备选清单
数据采集权限受限 1. 提前与酒店沟通协议
2. 准备数据脱敏方案
3. 考虑使用公开数据集
存储空间不足 1. 实时监控存储使用
2. 及时清理中间文件
3. 扩展云存储
团队成员离职 1. 代码文档化
2. 知识定期分享
3. 关键模块双人备份

10.3 进度风险

风险项 概率 影响 应对策略
数据采集超时 1. 预留20%缓冲时间
2. 并行采集多个场景
3. 简化采集流程
算法调试周期长 1. 使用小规模数据快速迭代
2. 设置阶段性目标
3. 及时调整技术路线
论文被拒需返工 1. 提前内部审稿
2. 准备多个投稿目标
3. 持续改进实验

十一、预算估算

11.1 硬件设备预算

类别 项目 数量 单价(万元) 小计(万元)
传感器 Livox Mid-360 LiDAR 1 1.5 1.5
Azure Kinect DK 2 0.3 0.6
偏振相机 Lucid Phoenix 1 3.0 3.0
高分辨率相机 Sony α7R IV 1 2.0 2.0
IMU Xsens MTi-630 1 1.2 1.2
平台 移动采集小车(定制) 1 2.0 2.0
Matterport Pro3(可选) 1 4.0 0
计算 工作站(2×RTX 4090 2 4.0 8.0
NVIDIA Jetson AGX Orin 1 1.0 1.0