3. XML 模型结构入门:根节点、worldbody、geom、body
好,咱们正式开始动手写模型了。MuJoCo 的模型文件说白了就是一个 XML 文本,后缀是 .xml。你想想看,一个机器人或者一个场景,在 MuJoCo 里就是由这些标签堆出来的。我第一次看这玩意儿的时候,觉得它跟 HTML 长得真像,但每个标签都有严格的物理含义,乱写是会报错的。
这一章,我就带你拆开这个 XML 文件,看看最核心的几个零件:根节点、worldbody、body 和 geom。搞懂这四个东西,你就能搭出一个能跑起来的简单模型了。
3.1 根节点:mujoco 标签
每个模型文件最外层,必须包一个 <mujoco> 标签。这就是根节点,告诉解析器“我是 MuJoCo 模型”。
我个人习惯,在根节点里加上 model 属性,给模型起个名字。方便后面调试时区分不同版本。
<mujoco model="my_first_robot">
<!-- 所有内容都写在这里面 -->
</mujoco>
<mujoco>,解析器会直接报错退出。我曾经在合并文件时犯过这个错,找了半天才发现是多了一个根标签。
3.2 worldbody:世界的起点
<worldbody> 是场景的根坐标系。你可以把它理解成“大地”或者“世界原点”。所有不依附于其他物体的东西,比如地面、固定支架,都直接放在 worldbody 里。
说白了,worldbody 就是一张白纸,你在上面画什么,什么就存在于这个世界里。它本身没有质量,没有碰撞,只是一个参考系。
<mujoco model="ground_example">
<worldbody>
<!-- 地面和固定物体放这里 -->
</worldbody>
</mujoco>
3.3 geom:几何体,看得见摸得着
<geom> 是 MuJoCo 里最基础的视觉和碰撞单元。一个 geom 就是一个几何形状:盒子、球、圆柱、平面等等。它决定了物体的外观和碰撞体积。
每个 geom 必须指定 type 和 size。type 选形状,size 填尺寸。比如一个边长为 0.1 米的立方体:
<geom type="box" size="0.05 0.05 0.05" />
这里 size 的三个值分别对应 x、y、z 方向的半边长。嗯,要注意,MuJoCo 里 size 给的是半边长,不是全长。我第一次用的时候直接填了 0.1,结果盒子比预期大了一倍。
| type 值 | 形状 | size 参数含义 |
|---|---|---|
plane |
无限平面 | 无(或忽略) |
box |
长方体 | 半长 x, 半长 y, 半长 z |
sphere |
球体 | 半径 |
cylinder |
圆柱体 | 半径, 半高 |
capsule |
胶囊体 | 半径, 半高(不含半球) |
把 geom 放在 worldbody 里,它就固定不动了。比如做一个地面:
<worldbody>
<geom type="plane" size="0 0 0" />
</worldbody>
平面不需要尺寸,MuJoCo 会自动生成一个无限大的地面。你想想看,这多方便。
3.4 body:关节和连杆的容器
光有 geom 还不够,因为 geom 是死的,不能动。要让物体动起来,你需要 <body>。body 是一个容器,它可以包含 geom、关节(joint)、以及子 body。
每个 body 都有自己的局部坐标系。你可以在 body 里放一个 geom,然后移动 body,geom 就会跟着动。这就是机器人连杆的基本结构。
<body pos="0 0 0.1">
<geom type="box" size="0.05 0.05 0.05" />
</body>
上面这段代码,在 world 坐标系 (0, 0, 0.1) 的位置创建了一个 body,里面放了一个立方体 geom。body 的位置就是 geom 的位置。
3.5 把它们组合起来:一个完整的简单模型
现在我们把上面几个东西拼起来,做一个最简单的模型:一个固定在地面上的盒子。
<mujoco model="simple_box">
<worldbody>
<!-- 地面 -->
<geom type="plane" size="0 0 0" />
<!-- 一个悬浮的盒子 -->
<body pos="0 0 0.1">
<geom type="box" size="0.05 0.05 0.05" />
</body>
</worldbody>
</mujoco>
这个模型加载后,你会看到一个地面,上面有一个盒子。盒子不会动,因为没加关节。但至少,它有了视觉和碰撞。
我刚开始学的时候,就是从这个模型起步的。然后慢慢加关节、加驱动、加传感器。你想想看,再复杂的机器人,底层也是这些 body 和 geom 堆出来的。
3.6 知识结构图:XML 模型骨架
下面这张图,帮你理清这四个核心元素的关系。我建议你把它存下来,写模型时对照着看。
3.7 避坑指南:我踩过的几个坑
- geom 重叠: 两个 geom 放在同一个位置,仿真时会出现剧烈抖动。我曾经把两个盒子叠在一起,结果仿真一开始它们就弹飞了。解决办法是确保 geom 之间有微小间隙,或者用
contype和conaffinity控制碰撞组。 - body 嵌套层级混乱: 子 body 的位置是相对于父 body 的。如果你把子 body 的 pos 写成了世界坐标,整个运动学链就乱了。我建议你画个树状图,标清楚每个 body 的父子关系。
- 忘记加地面: 没有地面,物体直接掉出世界,仿真器会报 "object out of bounds" 错误。嗯,这个我犯过不止一次。
3.8 本章小结
这一章我们拆解了 MuJoCo XML 模型的四个核心元素:
- 根节点
<mujoco>:模型的入口,所有内容都包在里面。 <worldbody>:世界坐标系,固定物体的家。<geom>:几何体,负责视觉和碰撞。<body>:连杆容器,是运动学链的基本单元。