给机械臂套上"泡泡膜":Genesis 里用凸分解跑通 URDF 抓取仿真
【免费下载链接】genesis-worldSimulation platform for general-purpose robotics & embodied AI learning.项目地址: https://gitcode.com/GitHub_Trending/genesi/genesis-world
这是 Genesis(通用机器人与具身 AI 仿真平台)的凸分解实战教程。它帮你把 URDF、MJCF 模型里的非凸网格拆成一组凸包,让碰撞检测不再拖垮帧率。适合第一次把复杂模型塞进物理仿真、被卡顿困扰的开发者。
为什么需要它
想象这样一个场景:你下载了一个细节完整的咖啡杯 OBJ 模型,扔进仿真里让机械臂去抓。结果两件事同时发生——第一步scene.step()卡了几十秒,因为引擎要对几千个三角形做接触求解;第二,杯子边缘的"钩子"让机械臂指尖莫名其妙地滑开或者穿透,因为非凸表面的接触点在每一步都在跳。
Genesis 的默认策略是自动凸分解:给刚体实体(RigidEntity)加进场景时,convexify参数默认为True(见genesis/options/morphs.py),引擎先算整个网格的凸包,如果凸包体积和原网格体积差得太多(超过decompose_object_error_threshold,默认 0.15),就调用 CoACD 算法把网格切成多个凸块。你不用写一行分解代码,但要理解它在做什么,才能在参数不合适时救场。
想亲眼看看分解结果?给实体加一个vis_mode="collision"参数,视角里显示的就是碰撞网格而不是外观网格——examples/rigid/convex_decomposition.py就是这么展示一排水杯、甜甜圈被拆成什么形状的。
先建立心智模型
把凸分解理解成"给石头套泡泡膜":你没法直接对一块不规则石头算精确的接触力,但可以用几个泡泡(凸包)把石头表面贴住。泡泡是光滑凸的,物理引擎对凸体 vs 凸体求接触又快又稳。贴一个泡泡不够贴合,就贴十个。
Genesis 里的分工是这样的:
两个关键机制值得记住。第一,先试单凸包:如果网格本身近似凸(比如一个圆柱杆),凸包误差小于阈值就直接用一个,省掉最贵的分解步骤。第二,磁盘缓存:分解结果按网格顶点和参数存成.cvx文件(genesis/utils/mesh.py里的get_cvx_cache),同一个资产被场景复用几十次时,只有第一次付分解的钱。
动手:从零跑通
1. 安装并初始化 Genesis
pip install genesis-simimport genesis as gs gs.init(backend=gs.gpu, precision="32", seed=0) # CPU 换 gs.cpu scene = gs.Scene(rigid_options=gs.options.RigidOptions(dt=0.01), show_viewer=True)这一步创建仿真后端和一个带刚体求解器的场景,dt=0.01表示每步推进 10 毫秒。
2. 加载一个非凸模型并看它的碰撞网格
scene.add_entity( gs.morphs.Mesh(file="meshes/tank.obj", scale=5.0, fixed=True), vis_mode="collision", # 关键:显示碰撞网格而非外观网格 )vis_mode="collision"就是"掀开外观看里面"的开关,跑起来你会看到坦克被拆成了几块凸的"泡泡"。
3. 用阈值参数控制分解行为
mug = gs.morphs.URDF( file="my_mug.urdf", convexify=True, # 刚体默认就是 True decompose_object_error_threshold=0.15, # 凸包体积误差超过 15% 才分解 ) scene.add_entity(mug, vis_mode="collision")三个参数各管一件事:convexify决定要不要凸处理;decompose_object_error_threshold决定普通物体的分解灵敏度(0.0 强制分解,float("inf")彻底禁用);decompose_robot_error_threshold只针对多关节机器人,默认inf即默认不分解,因为机器人通常按 link 自带简单碰撞体,一般不用动。
4. 调 CoACD 分解算法本身的旋钮
mug = gs.morphs.URDF( file="my_mug.urdf", coacd_options=gs.options.CoacdOptions( threshold=0.1, # 主精度参数,见下表 max_convex_hull=12, ), )coacd_options只在真的触发分解时生效。注意它内部用 MCTS(蒙特卡洛树搜索)挑切割面,所以分解过程本身要跑一会儿,这是首次加载慢的正常现象。
5. 跑起来
scene.build() for _ in range(2000): scene.step()看窗口:凸块贴合得紧不紧、物体是稳稳落下还是抖动穿透,答案都写在碰撞网格里。完整可运行版本直接看examples/rigid/convex_decomposition.py。
参数调优速查表
这些参数都在genesis/options/morphs.py和genesis/options/misc.py里,默认值直接取自源码。
| 参数名 | 默认值 | 作用 | 调整建议 |
|---|---|---|---|
convexify | 刚体为True | 是否对实体做凸包/分解处理 | 纯装饰物设False可省掉全部计算 |
decompose_object_error_threshold | 0.15 | 普通物体:凸包体积误差超过该比例才触发分解 | 物体总被一个"大方块"包住 → 调小如0.05;加载慢 → 调大或设inf |
decompose_robot_error_threshold | inf | 同上,但只管多关节机器人 | 一般保持不动,机器人碰撞体多在 URDF 里显式定义 |
CoacdOptions.threshold | 0.1 | 分解精度主参数 | 源码注释写明:阈值减半约使凸包数量翻倍 |
CoacdOptions.max_convex_hull | -1(不限) | 凸包数量上限 | 复杂物体建议给个上限(如 12)防止爆炸 |
CoacdOptions.max_ch_vertex | 256 | 单个凸包最多顶点数 | 越大越贴合,内存和求解开销越大 |
decimate_face_num | 500 | 碰撞网格减面目标面数 | 高模拖慢加载时可放心调低 |
CoacdOptions.pca | False | 是否启用 PCA 预处理 | 别开:上游 CoACD 有 bug,设True会直接报错 |
踩坑现场
现象:换个 scale 重新加载同一个模型,又等了半天分解。原因是分解缓存按"归一化顶点 + 面 + coacd 参数"做 key,但如果你改的只是场景里的摆放位姿,缓存本该命中。真正失效的常见原因是你悄悄改了某个CoacdOptions字段——参数参与 key,变了就重新算。想复用结果就保持参数一致,分解结果存成.cvx文件后,同目录下的重复实体会直接读缓存。
现象:杯子抓的时候指尖老从把手上滑过,像是"穿模"。这是凸包太粗的典型症状:把手是个凹陷结构,一个凸包直接把它"抹平"了,碰撞体上没有把手。修复方式是把decompose_object_error_threshold调到0.0(强制分解)或把CoacdOptions.threshold从0.1降到0.05,再用vis_mode="collision"确认把手位置出现了独立的凸块。
现象:物体加载出来形状歪了或者分解结果不对称。先检查CoacdOptions.pca是不是被设成了True——Genesis 会直接抛异常拒绝,因为上游 CoACD 的 PCA 变换没有逆变换回分解结果(源码里有明确的 FIXME 注释)。另外确认网格法线朝向一致:genesis/utils/mesh.py里对非一致 winding 的网格会拒绝分解并给出报错,这种情况得先回 DCC 工具修法线。
延伸去处
- 示例代码:examples/rigid/convex_decomposition.py,带
-v参数可开可视化,-g切 GPU 后端 - 非凸网格对照实验:examples/rigid/nonconvex_mesh.py
- 凸分解核心实现:genesis/utils/mesh.py(
convex_decompose与postprocess_collision_geoms两个函数) - 参数定义:genesis/options/morphs.py(实体级参数)与 genesis/options/misc.py(
CoacdOptions) - 刚体实体消费这些参数的入口:genesis/engine/entities/rigid_entity/rigid_entity.py
- 项目主文档:README.md
【免费下载链接】genesis-worldSimulation platform for general-purpose robotics & embodied AI learning.项目地址: https://gitcode.com/GitHub_Trending/genesi/genesis-world
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考