Files
worldmodel/plans/physics_engine_implementation.md

21 KiB
Raw Permalink Blame History

title, date, draft, tags, categories, description
title date draft tags categories description
WorldModel 物理引擎集成方案 2026-05-28 false
worldmodel
physics-engine
PRISM
技术方案
plans
为WorldModel室内场景添加物理引擎的完整技术方案,包括引擎选型、3D重建网格碰撞准备、PRISM空间记忆融合与实施路线图。

WorldModel 物理引擎集成方案 (v1.0)

1. 背景与动机

WorldModel的核心数据流(RoomPlan/ZED2i -> PRISM空间记忆)已覆盖"看见并记住"室内环境。要完成闭环,还需要让机器人在数字环境中能够与物体进行物理交互验证。这要求:

  1. 碰撞检测: 机器人在虚拟酒店房间中运动时,不会穿墙、撞翻物体
  2. 对象操作模拟: 开门、推拉椅子等动作可以在仿真环境中验证可行性
  3. 物理属性学习: 机器人通过交互获取"这个物体推得动还是推不动"的经验,反哺L4语义记忆
  4. 合成数据生成: 为视觉模型/行为克隆策略提供带物理标签的训练样本

2. 引擎选型对比

Bullet / PyBullet NVIDIA PhysX (Isaac Sim) Unity Physics (Jolt) Unreal Engine 5 Chaos MuJoCo
许可证 MIT 开源 Apache-2.0 (PhysX) / NVIDIA专有(EZG) MIT/Jolt-2.0 Apache-2.0 (Chaos SDK部分可用) 开源研究用
GPU加速 CUDA/OpenCL插件可选 (cuBullet) 原生硬件级(PhysX GPU CPU为主,GPU开发中 GPU RayTracing/Physics 纯CPU物理步
ROS集成 pybullet-ros, ros_control封装成熟 Isaac ROS生态(需NVIDIA硬件) 间接(ROS2 Bridge) ROS2 Bridge存在但较新 需自定义wrapper
机器人动力学 KUKA/PR2模型现成,RBD引擎支持全身控制 Robot Assets库丰富(nvidia-isaac-sim/robots) 需手动配置 Skeletal + Rigid body MPC/整体制动强但仅运动学、无对象操作
网格碰撞精度 ConcaveMesh(BVH)+Convex Decomposition工具链完整 USDZ原生支持,ConvNv扩展做convex decomposition OBJ->FBX需转换、材质丢失风险高 支持OBJ/FBX/GLTF但PBR物理参数需手动调 仅支持convex primitives(Box/Sphere/Capsule)
室内重建网格兼容性 OBJ/STL直接加载,pymeshlab+pybullet-convex-decomp处理 最佳(USDZ是NVIDIA生态标准) OBJ->FBX需转换,材质丢失风险高 支持OBJ/FBX/GLTF但PBR物理参数需手动调 OBJ->convex approximation(自动)
团队熟悉度 Python为主(Robotics生态已有) 需学习Isaac Sim专用框架+CUDA工具链 Unity C#简单但物理系统相对新 UE5蓝图+CPP双栈,生态庞大 研究友好、功能受限(纯刚体)
性能(帧率) 中等精度~10-30fps@中大型房间 GPU并行,百万级物体(最快) ~30fps @中型场景 高(GPU加速但需UE5渲染管线) 最快可达10kHz+物理步,但仅刚体无网格碰撞

推荐方案:主从双引擎架构

主引擎: PyBullet + Bullet Physics Server(实时感知与操作层) 理由:

  • PRISM tools已有Python环境,PyBullet提供纯Python API无缝衔接ROS生态
  • Mesh碰撞处理工具链最完整(pybullet_convex_decomp, pymeshlab脚本可复用)
  • 轻量独立,不依赖NVIDIA GPU

辅助引擎: NVIDIA Isaac Sim(高保真合成数据层) 理由:

  • 需要生成带精确物理标签的训练集时(如物体形变、流体交互),Isaac Sim是业界标杆
  • 与RoomPlan的USDZ格式天然兼容(NVIDIA生态)

备选快速验证: MuJoCo + MJCF (原型阶段) 理由:确定PRISM-L4语义层需要哪些物理属性时,MuJoCo可以快速搭建"物体->可操作参数"的原型验证环境

3. PRISM x 物理引擎融合架构

数据层映射:PRISM四层如何承载"物体物理状态"

| PRISM层级 | 传统内容 | 新增物理字段

| L1感知缓冲(~30Hz) | ZED2i当前帧点云/图像流 | 实时碰撞体包围盒(BVH)生成、接触力反馈(触觉传感器输入)| | L2度量地图 | 3D体素网格+语义标签 | Mesh碰撞几何(每类家具->Bullet ConvexHull)、静摩擦系数mu_s、动摩擦系数mu_k、质量m | | L3拓扑图 | Graph(Room->Corridor->Room),边权=距离/通行概率 | 边权重加入物理约束: "这个门需要开门空间>=0.8m"、通道净宽 | | L4语义场 | Object属性查询("这把椅子是木质的")+LLM可问答性 | 物理交互标签: "movable": true, "push_force_estimate_N":[15.0, 45.0], "friction":"medium";LLM可推理"这个物体重吗?推得动吗?"|

核心模块:Physics-PRISM Bridge (PPB)

                    +-------------+     碰撞几何      +-----------+
RoomPlan/ZED2i --> | Mesh Processor| -------------->  |Bullet Server| <-- robot_control_loop
   (3D重建)       +-------------+                   ^(pybullet)      |
                      ^                               +-----------+   V|
                     || 物理属性注入              (10Hz状态更新)      |Collision/Force Feedback|
                     ||                                              vPRISM L1写入         +---> PRISM L1
              PPB      |<----------------------------------------------(碰撞事件写入L1缓冲)    物理状态推送|
              Manager--|---> PRISM L2-L4更新: "椅子被撞了0.3m"
             (ROS Node)|<----  "这扇门现在半开(角度120度)"
              +--------+
                  |
           ROS Topic: /prism/physics_state

**PPB 关键职责:**1. 从PRISM L4语义场拉取物体属性 ->为每个对象在Bullet中创建刚体 2. 将碰撞检测结果写回PRISM L1/L2 ->实时物理事件进入空间记忆3. 维护"已知交互历史" ->L4中积累物体操作经验(LLM可查询)

新增PRISM管线:Pipeline E -- "物理巩固"在现有四个管线的第四个(记忆巩固 Pipeline D)之后,追加:

Pipeline E: 物理知识巩固 (Physics Consolidation)

  • 触发:每次有意义的物体交互(推门成功/失败、拿取物品)
  • 数据源: Bullet仿真 ->实际传感器验证对比差异(仿真到现实 gap度量)
  • 写入目标:L4语义场,更新物体的交互标签(摩擦力、重量估计修正)
  • 频率:非实时事件驱动,~1Hz或交互后批量写入

4. Mesh -> Physics几何转换管线

流程:3D重建网格 --> Bullet碰撞体RoomPlan USDZ/OBJ ---> OpenUSD/Pymeshlab处理->Convex Decomposition(BVPY/ICME) -> Bullet ConcaveMesh / ConvexHulls (静态几何: 每帧更新+动态刚体:可交互对象)

4.1 RoomPlan USDZ -> OBJ/Ply转换

  • Apple RoomPlan输出USDZ格式,NVIDIA Omniverse USD Python API可直接解析(pxr.Sdf, usdGeom.Mesh)
  • 对于非NVIDIA路径:使用opensubdiv + trimesh做 USDZ ->OBJ/Ply导出

4.2 Mesh简化与碰撞体生成- 静态物体(墙壁、地板): Bullet ConcaveMesh (BVH树) -- 不需要convex decomposition

  • 可交互物体(椅子、门把手): Convex Decomposition ->分解为~5-20个convex hulls
    • 推荐工具:pybullet_convex_decomp(Bullet官方Python wrapper,支持GPU加速)
    • 替代:V-HACD (Virtual Hi-Arcade Convex Decomposition,精度最优但较慢)
    • 快速方案:pymeshlab的convex_decomposition filter

4.3 Mesh质量要求- 精度:静态墙壁/地板<2mm偏差(L1感知缓冲中ZED2i提供)- 性能:每个可交互对象<10个convex hulls(Bullet BVH查询在~1ms内)

  • 更新频率:房间结构(墙壁)只在离线建图时构建一次;家具在"差异检测管线"(PRISM Pipeline C)触发时才重建

5. PRISM L4语义场扩展字段草案 (JSON Schema)在现有L4的"物体属性查询结构"中新增物理交互标签:

{  "object_id": "chair_room_102_A",        // L4语义场中的唯一标识
  "category": ["furniture","seat"],       // RoomPlan类别(现有)  "physics"{    // NEW: 物理交互标签

```jsonc
{
  "object_id": "chair_room_102_A",        // L4语义场中的唯一标识
  "category": ["furniture","seat"],       // RoomPlan类别(现有)

    "// --- NEW: Physical Interaction Tags --""",
    
      "physics":{"mass_estimate_kg":6.2,               // kg可由PPB的convex hull+材料估计
    "friction":{"static":0.45,                      // mu_s: 静摩擦系数
      "dynamic":0.32                      //mu_k:动摩擦系数    },    
    "mass_estimate_kg":6.2,               // kg可由PPB的convex hull+材料估计
"friction":{"static":0.45,                      // mu_s: 静摩擦系数
  "dynamic":0.32                    }},"movable":true,                       // 是否可移动(门、椅子为true,墙/地板为false
"movable_method":["push",,"pull"],     // 支持的操作类型(推/拉/提)
"push_force_range":[15.0, 45.0],       // N:推启动力和可接受上限力
"stability":{"is_stable_unassisted":true,         // 不推就自己不会倒
  "toppling_force_Nm":12.5            // N·cm:翻倒阈值
},

  "interaction_history":[               // LLM可查询的交互经验        {          "timestamp":"2026-05-30T14:22",
        "action":"push",                   // 操作类型          "object_from_location_xyz":[1.2,-0.5,0.78], // 移动前位置(L2度量坐标)
      "object_to_location_xyz":[1.8,-0.5,0.78],   // 移动后位置
      "force_applied_N":25.3,            //实际施加力
"success",true                      // push成功false=卡住了/推不动        }
  ]    "sim2real_gap_stats":{               //PPB仿真与现实对比的统计
    "position_drift_m":0.023,          //平均位置偏差(仿真-->现实)        "friction_bias":-0.12,             //摩擦系数偏差(仿真比现实高/低多少)
    "last_updated":"2026-05-31"         //最后一次校准时间      }

"// --- NEW: Interaction History (Pipeline E写入) --""",

"interaction_history":[               // LLM可查询的交互经验        {          "timestamp":"2026-05-30T14:22",            "action":"push",                   // 操作类型          "object_from_location_xyz":[1.2,-0.5,0.78], // 移动前位置(L2度量坐标)
        "object_to_location_xyz":[1.8,-0.5,0.78],   // 移动后位置
        "force_applied_N":25.3,            //实际施加力          "success",true                      // push成功 / false=卡住了/推不动        }
  ]

"// --- NEW: Simulation-Reality Gap (Pipeline E) --""",

  "sim2real_gap_stats":{               //PPB仿真与现实对比的统计        "position_drift_m":0.023,          //平均位置偏差(仿真-->现实)        "friction_bias":-0.12,             //摩擦系数偏差(仿真比现实高/低多少)        "last_updated":"2026-05-31"         //最后一次校准时间      }

"// --- NEW: Interaction History (Pipeline E写入) --""",

"interaction_history":[               //LLM可查询的交互经验        {          "timestamp":"2026-05-30T14:22",            "action":"push",                   // 操作类型          "object_from_location_xyz":[1.2,-0.5,0.78], // 移动前位置(L2度量坐标)            "object_to_location_xyz":[1.8,-0.5,0.78],   // 移动后位置
        "force_applied_N":25.3,            //实际施加力          "success",true                      // push成功 / false=卡住了/推不动        }
  ]    "sim2real_gap_stats":{               //PPB仿真与现实对比的统计        "position_drift_m":0.023,          //平均位置偏差(仿真-->现实)        "friction_bias":-0.12,             //摩擦系数偏差(仿真比现实高/低多少)
    "last_updated":"2026-05-31"         //最后一次校准时间
  }

},}

    "碰撞事件":   collision.force_magnitude > threshold_N,  #有意义的接触(如门撞到墙壁)
    "物体位移":   abs(translation_delta_m)> threshold,     #可移动对象被显著推动
    "交互完成":   action.success == true/false,             #如开门/关门完成
    "时间周期":  every_30_minutes                         //定期同步仿真状态与现实(校准)
]

### Pipeline E执行流程:1. **读取**:从 PRISM L4语义场 ->获取该物体的当前物理属性
2. **对比**simulation_position(PyBullet中) vs actual_sensor_position (ZED2i/IMU实际测量位置)
3. **校准**:如果 drift > tolerance -->更新L4物理属性(摩擦力、质量估计)
4. **日志**interaction_history追加记录 ->L4语义场永久存储5. **通知**:向L3拓扑发送"通道通行性变更"(如果物体移动导致了新障碍)

```python
class PhysicsConsolidationPipeline:    """PRISM Pipeline E:物理知识巩固       触发条件= collision detected / interaction complete/periodic sync    """    def trigger(self, event: Union[CollisionEvent] | InteractionComplete]) -> None:
        self.log(event)        
       prism_l4_object = prisms_semantic_layer.query_by_name(event.object_id))
        # Step 1: Read L4物理属性(仿真状态)      sim_mass = prism_l4_object.physics.mass_estimate_kg        friction_estimated=self.estimate_friction_from_force_sensor(event.contact_force)
        
    # Step 2: Read ZED2i/IMU真实测量(现实状态)        actual_position=self.zed_2i_camera.get_object_pose(event.object_id))
        
    # Step 3: Compute gap(仿真 -->现实)        sim_position=self.get_simulated_object_pose(event.object_id))

    # Step 4: Update L4语义场
        if sim2real_gap> tolerance:            self.update_prism_l4_physics(event.object_id,friction_estimated)

7. PPB ROS消息定义草案 (prism_msgs/PrismPhysicsState.msg)

# 每帧发布: /prism/l1/collision_events (30Hz)std_msgs/Header header
# 当前帧碰撞事件列表(可为空CollisionEvent[] collisions

message CollisionEvent {
  string object_a        # PRISM L4语义名称,如 "chair_01"
  string object_b        # PRISM L4语义名称,如 "wall_kitchen_east"
  geometry_msgs/Vector3 contact_point    # WGS坐标系中的碰撞点(L2度量)
  geometry_msgs/Vector3 contact_normal   #法线方向  float64 penetration_depth    #穿透深度(mm), <0表示分离距离
  geometry_msgs/Wrench contact_force     #L1力觉反馈:力和扭矩}

#每50ms发布: /prism/l2/physics_mesh_state (20Hz)
std_msgs/Header header#所有动态刚体的当前位姿(用于L2度量地图中的物体定位)DynamicBodyState[] dynamic_bodies

message DynamicBodyState {
  string body_name             # PRISM L4语义名称,如 "door_hallway_02"  geometry_msgs/Pose pose       #6DoF位姿(位置+四元数)
  float32 mass                   #kg, L4语义场中的物理属性查询结果}

#按需请求: /prism/l2/get_physics_properties (ROS Service)
---string object_name           # 请求: L4语义名称(如 "chair_01")
---#响应:该物体的物理属性 (L4语义场中的值)string description           #"可推动,木质框架"float32 friction_mu_static   #静摩擦系数 mu_s \in [0.1, 1.5]float32 friction_mu_dynamic  #动摩擦系数mu_k \in [0.1, 1.2]
float32 mass                  #kg:"中等重量,约5kg" \to 6.0bool is_movable              #true/false: "椅子可以被搬走" \to truefloat32 push_force_min        #启动推力估计(N)

8. Phase实现路线图(四阶段)### Phase 0:原型验证 (2周) **目标: "PyBullet能跑起一间酒店客房吗?步骤1产 产出物0.2读取一个RoomPlan样例(USDZ或OBJ),用trimesh导出为PLYphysics/demo/load_room.py) + screenshot

    "0.3在PyBullet中加载房间几何为静态刚体,机器人URDF模型进入
    "0.4加入一个动态物体(椅子),实现简单的推拽交互|Bullet仿真截图 + 操作日志
    "0.5写一份README记录踩坑和经验教训|/plans/physics_engine_implementation.md#phase0的完成checklist和known issues

交付: 一个可以在终端跑的Python脚本,加载房间网格+URDF机器人,可视化窗口中可操作

Phase 1: Mesh处理管线 (3周) 目标: "从任意RoomPlan/ZED2i场景自动构建碰撞几何"

| 步骤 | 内容 ---### Phase1.2 Mesh简化工具(减少三角面到collision-ready级别)| 使用pyfqmr或gptoolbox做mesh simplification

Phase1.3 Convex Decomposition pipeline: V-HACD + pybullet_convex_decomp| 配置JSON支持自定义convex hull上限参数(每个对象max_hulls=10)

Phase 1.4自动标注"静态 vs 动态"对象(基于RoomPlan语义层)| RoomPlan输出包含category: wall/furniture/door/cabinet标签,自动分类

Phase 1.5集成测试: PRISM Pipeline A的输出(离线3D重建) -> PPB自动创建Bullet世界|端到端Pipeline测试脚本physics/test_e2e_pipeline.py+报告

Phase 2: PRISM Bridge (4周) 目标: "物理引擎数据进入PRISM四层记忆,形成闭环"

| 步骤 | PRISM对接点 ---### Phase2.1 PPB ROS Node: /prism/physics_state | 定义ROS消息类型PrismPhysicsState.msg(包含所有碰撞体位姿)

Phase 2.2 L1写入:将Bullet接触/碰撞事件推送至L1感知缓冲| topic /prism/l1/collision_events,格式: {frame_id, object_a,object_b, contact_force}

Phase2.3 L4读写:将PPB从PRISM拉取的物体属性+写回的交互经验| ROS service GetPhysicsProperties / UpdateInteractionHistory,使用prism_ros_bridge的现有topic

Phase2.4差异检测集成: PRISM Pipeline C触发时,对比当前物理状态与L2度量地图中存储的"理想几何"| 输出差异报告: physics_consolidation_report.json(哪些物体位置变了、被移动了)

Phase2.5 L3拓扑图更新:物理约束影响通行性评估(半开门导致通道变窄)|L3 edge weight更新: passability_score=base_passability x(1 - collision_risk_penalty)### Phase3.2合成数据标注管线:从PyBullet世界随机采样物体位置/光照 -->渲染图像+ground truth标签| physics/synthesis/generate_episode.py,输出: RGB图像, depth图, semantic segmentation mask, object bounding boxes

Phase3.3数据格式: ONNX-compatible dataset(与HuggingFace Hub集成)| HFDataset定义 + upload脚本 physics/synthesis/upload_to_hf.py

Phase3.4机器人策略验证: PyBullet + ROS Control中的RL agent在仿真中学习"开门/推椅"|集成stable-baselines3(RLlib) + pybullet-ros,训练简单的push/grasp policy

Phase 3.5合成数据质量验证:与真实场景对比分布差异(MMD / Fréchet Inception Distance) | physics/synthesis/evaluate_fidelity.py

9. 技术栈清单(新增依赖)### Python核心

opensubdiv>=3.6            #OpenUSD/USDZ解析(非NVIDIA路径)pyfqmr                     #快速网格简化到collision-ready级别
trimesh>=4.0               #Mesh格式转换(USDZ/OBJ/PLY/FBX)
pybullet_convex_decomp     #GPU加速凸分解(需要CUDA 12+)```### ROS生态
`textros-noetic-robot-base    #URDF/RViz支持(ROS1 Noetic)
ros-humble-robot-base     # ROS2 Humble对应包(备选/未来路径)
pybullet_ros              # PyBullet与ROS通信bridge(如可用则集成,否则自建)
```### 辅助工具`textopensimplex              #合成数据中的随机扰动生成(放置物体位置)huggingface_hub           #合成数据集发布到HFDataset Hub```### GPU依赖(可选,Phase 1-2之后评估是否需要)
`text# NVIDIA CUDA 12.4+ + cuBLAS/cuSPARSE(用于cuBullet或pybullet_convex_decomp的GPU加速)
# Jetson Orin / RTX 4090(桌面测试环境)```

## 10. PRISM L4语义场LLM查询示例(集成后能力)

用户/策略模块可以向PRISM L4语义场发起LLM查询:> "房间102中,哪些椅子可以被搬动?"

→从L4语义场返回: "chair_A(可推,mus=0.45), chair_B (固定在地) -->只有一把可以移动"

" hallway走廊的通行性怎么样?">PRISM从L3拓扑+ L1最近碰撞事件回答: "当前通行概率72% -- 一把椅子被推到了走廊中央(见L1事件#34),移除后可以恢复95%"

"如果我把桌子向右推2米,会撞到门吗?">PRISM调用PyBullet执行虚拟操作: "模拟结果显示不会碰撞。桌子最右边缘与门框距离0.4m(安全)"

"这个房间里有哪些物体是半开着的,可能阻碍通行?">L1/L2碰撞检测返回: "门_厨房东(角度=45度), 窗柜抽屉拉出10cm"


## Appendix A. PyBullet + PRISM 集成架构代码框架### `physics/engine/bullet_server.py` -- Bullet Server(ROS Node)

```python
import pybullet as pclass PhysicsServer:    """PyBullet服务端,作为独立的ROS Node运行"""
    
     def __init__(self):        p.connect(p.GUI)  # GUI可选;headless用p.connect(p.DIRECT)
        p.setGravity(0, 0, -9.81)

    def load_room_mesh(self, room_usdz_path: str):        """从RoomPlan/ZED2i的3D重建文件加载房间"""
```python
    
     def load_room_mesh(self, room_usdz_path: str):        """从RoomPlan/ZED2i的3D重建文件加载房间"""    
    def load_robot_urdf(self, robot_usdz_path: str):  #修正:URDF文件        """加载移动机器人基座(带轮子/机械臂)"""

    def set_object_interactivity(self, object_name: strmovable_bool) -> None):        """控制PPB将PyBullet刚体标记为dynamic/static"""    def get_collision_events(self) -> List[CollisionEvent]:        """读取当前帧所有碰撞检测结果"""    def sync_state_to_prism(self, prism_topic: str) -> None        """将当前物理状态写入PRISM L1/L2 topic"""  ```

### PRIMS --> PyBullet状态注入当PRISM Pipeline C(在线感知)检测到场景变化时,更新PyBullet中的碰撞体位姿:

```python
def on_prism_perception_update(self, updated_objects: List[PrismL4Object]):
    """PRISM感知更新 -->驱动PyBullet刚体状态修改"""