2. XML模型基础
好,我们正式开始动手了。这一章的目标很简单——搭一个静态场景:地面加一个小球。别小看这个例子,它背后是MuJoCo整个XML模型体系的骨架。你把这个搞懂了,后面搭四足机器人就是往上添零件的事。
2.1 MuJoCo的XML模型长什么样?
MuJoCo用XML文件描述整个世界。说白了,就是一个树状结构,根节点叫 mujoco,下面挂各种子节点。我个人习惯把这种结构想象成一棵倒着长的树——根在最上面,枝叶往下展开。
核心结构速览:
mujoco— 根节点,整个模型的容器worldbody— 世界本体,所有物体的“家”body— 刚体,可以嵌套,构成运动链geom— 几何体,定义物体的形状和外观
下面这张图把关系画清楚了,你一看就懂:
2.2 四个核心元素,一个一个说清楚
2.2.1 mujoco — 模型的根
每个MuJoCo XML文件必须有且只有一个 mujoco 根节点。它就像房子的地基,所有东西都长在上面。你可以在里面设置编译器选项、默认参数,但初学者先别管那些,留空就行。
2.2.2 worldbody — 世界的容器
worldbody 是场景的根刚体。它代表“世界坐标系”,所有物体都挂在这个坐标系下。注意,worldbody 本身没有质量、没有惯性,它只是一个空间参考点。
我的习惯:把 worldbody 想象成舞台的地板。地板本身不动,但所有演员(物体)都站在上面。
2.2.3 body — 刚体,物体的“骨架”
body 定义了一个刚体。它有位置、朝向,可以嵌套子 body 形成运动链。每个 body 可以挂多个 geom,也可以挂关节、传感器等。
嗯,这里要注意:body 本身是不可见的。你看到的是它下面挂的 geom。所以 body 更像是一个坐标系,geom 才是你眼睛看到的东西。
2.2.4 geom — 几何体,物体的“皮肉”
geom 定义了物体的形状、大小、颜色、摩擦系数等。MuJoCo支持多种几何类型:
| 类型 | 说明 | 常用参数 |
|---|---|---|
plane |
无限大平面,适合做地面 | size 定义半长宽 |
sphere |
球体 | size 定义半径 |
box |
长方体 | size 定义半边长 |
cylinder |
圆柱体 | size 定义半径和半高 |
mesh |
自定义网格 | 需要外部 STL 文件 |
我曾经踩过的坑:初学者容易把 geom 直接挂在 worldbody 下,忘了包一层 body。虽然MuJoCo允许这样写,但后续加关节、加传感器时会非常麻烦。我的建议是——哪怕只有一个物体,也给它套一个 body。养成好习惯,后面省大事。
2.3 动手:搭一个“地面+小球”场景
理论说完了,直接上代码。下面这个XML文件,就是我们要的静态场景:
<mujoco model="ground_and_ball">
<worldbody>
<!-- 地面 -->
<body name="ground">
<geom name="floor" type="plane" size="2 2 0.1" rgba="0.8 0.8 0.8 1"/>
</body>
<!-- 小球 -->
<body name="ball" pos="0 0 0.5">
<geom name="sphere" type="sphere" size="0.2" rgba="1 0 0 1"/>
</body>
</worldbody>
</mujoco>
来,一行一行拆开看:
model="ground_and_ball"— 给模型起个名字,方便识别body name="ground"— 地面的刚体,位置默认在原点geom type="plane" size="2 2 0.1"— 一个平面,半长宽2米,厚度0.1米(平面其实无限大,size只影响碰撞检测范围)rgba="0.8 0.8 0.8 1"— 浅灰色,不透明body name="ball" pos="0 0 0.5"— 小球刚体,位置在 (0, 0, 0.5),也就是地面以上半米geom type="sphere" size="0.2"— 半径0.2米的球体rgba="1 0 0 1"— 红色,不透明
一个小技巧:MuJoCo的坐标系统是右手系,Z轴向上。所以 pos="0 0 0.5" 表示小球在地面以上0.5米。如果你把Z改成负数,小球就钻到地底下去了——我刚开始学的时候就干过这事,仿真一运行,球直接消失,我还以为代码写错了。
2.4 怎么运行这个模型?
你有两种方式:
- 用MuJoCo自带的可视化工具:把上面的XML保存成
scene.xml,然后在终端运行simulate scene.xml。你会看到一个灰色地面,上面飘着一个红球。 - 用Python加载:如果你装了
mujocoPython包,可以这样写:
import mujoco
import mujoco.viewer
# 加载模型
xml = """
<mujoco model="ground_and_ball">
<worldbody>
<body name="ground">
<geom name="floor" type="plane" size="2 2 0.1" rgba="0.8 0.8 0.8 1"/>
</body>
<body name="ball" pos="0 0 0.5">
<geom name="sphere" type="sphere" size="0.2" rgba="1 0 0 1"/>
</body>
</worldbody>
</mujoco>
"""
model = mujoco.MjModel.from_xml_string(xml)
data = mujoco.MjData(model)
with mujoco.viewer.launch_passive(model, data) as viewer:
mujoco.mj_step(model, data)
viewer.sync()
input("按回车退出...")
运行后,你会看到一个3D窗口,地面和小球都显示出来了。你可以用鼠标拖拽视角,从各个方向观察。
2.5 参数调一调,理解更深
光看还不够,我建议你动手改几个参数,看看效果:
| 参数 | 修改建议 | 你会看到什么 |
|---|---|---|
pos="0 0 0.5" |
改成 0 0 1.0 |
小球飞得更高了 |
size="0.2" |
改成 0.5 |
小球变大 |
rgba="1 0 0 1" |
改成 0 1 0 1 |
小球变绿 |
type="sphere" |
改成 box,size 改成 0.2 0.2 0.2 |
小球变成立方体 |
你想想看,改一个参数,场景就变了。这就是MuJoCo XML模型的魅力——用文本描述世界,改几行字就能创造不同的物理场景。
本章核心要点:
- MuJoCo的XML模型是树状结构,根节点是
mujoco worldbody是世界的容器,所有物体都在里面body是刚体,geom是几何体,两者配合使用- 每个
geom必须有type和size参数 - 颜色用
rgba控制,四个值分别是红绿蓝透明度