--- title: "酒店场景室内建模与物理验证项目详细实施计划(续)" date: 2026-05-20 draft: false tags: ["规划", "酒店场景", "物理"] categories: ["HotelScene"] --- # 酒店场景室内建模与物理验证项目详细实施计划(续) ## 七、数据管理与存储架构(续) ### 7.2 数据库设计 ```sql -- 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 数据存储方案 ```yaml 存储层级: 热数据(频繁访问): - 存储: 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 数据版本控制 ```yaml 使用DVC(Data 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 点云精度评测 ```python 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 渲染质量评测 ```python 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 语义理解评测 ```python 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 IoU(Intersection 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) # 计算AP(11点插值) 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 物理交互评测 ```python 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 综合评测基准 ```yaml 评测套件: 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个月) ```mermaid 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 人力资源配置 ```yaml 团队组成(建议): 项目负责人(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 | |