XML 格式机器人建模入门:URDF 与 MJCF 格式详解及实战对比
摘要:本文从 XML 基础语法出发,系统讲解机器人建模中两种主流描述格式:ROS 中的 URDF 与 MuJoCo 引擎的 MJCF。通过完整代码示例和组件拆解,帮助读者理解连杆、关节、几何体、执行器等核心概念,掌握两种格式的适用场景与选择方法。
前置条件与环境说明
在开始学习 URDF 和 MJCF 之前,建议先准备好以下环境:
- 操作系统:Ubuntu 20.04 或 22.04(ROS 官方支持最好)
- ROS 版本:Noetic(Ubuntu 20.04)或 Humble(Ubuntu 22.04)
- MuJoCo:2.3.0 及以上版本,可从官方 GitHub 仓库下载
- 可视化工具:RViz(ROS 自带)和 MuJoCo Viewer
本文所有示例均基于上述环境验证,代码可直接复制运行。
1. XML 格式简介
如果说 HTML 是为了“在网页上展示数据”,那么 XML 就是为了“在不同系统之间传输和存储数据”。它本身不执行任何操作,也不规定数据长什么样,而是让你自己定义一套“标签”来描述数据。
1.1 基本格式
<> 内为标签,数据分为元素方式与属性方式:
- 元素方式:
<price>23.00</price>(推荐,结构更清晰,方便扩展) - 属性方式:
<book id="101">(通常用于标识符、状态等简短的元数据)
2. XML 在机器人领域的应用
XML 是基础语法,在此基础上,在 ROS 中使用 URDF 格式描述机器人的“静态物理结构”。注意,URDF 只负责描述“机器人长什么样”,不负责描述“机器人怎么动”或“周围的世界是什么样的”。它不包含电机控制参数、摩擦力、风阻等复杂的物理仿真规则。
MJCF 是 MuJoCo 引擎自定义的一种 XML 格式,它是“骨架 + 肌肉 + 世界”。除了包含 URDF 的所有结构信息外,MJCF 还能定义整个仿真环境,包括物理引擎参数、接触控制、执行器和传感器等。
3. URDF 格式讲解
URDF(Unified Robot Description Format,统一机器人描述格式)是 ROS 中专门用于描述机器人硬件结构的 XML 格式文件。它的核心逻辑是将机器人的硬件结构拆分为连杆(Link,即刚体)和关节(Joint,即连接/运动),再组合成完整的模型。
3.1 完整示例
以下面的 URDF 为例:
<?xml version="1.0"?>
<robot name="simple_arm">
<!-- 1. 定义底座连杆 -->
<link name="base_link">
<visual>
<origin xyz="0 0 0" rpy="0 0 0"/>
<geometry>
<box size="0.2 0.2 0.08"/> <!-- 长宽高 -->
</geometry>
<material name="gray">
<color rgba="0.4 0.4 0.4 1"/> <!-- 灰色 -->
</material>
</visual>
<collision>
<geometry><box size="0.2 0.2 0.08"/></geometry>
</collision>
<inertial>
<mass value="0.8"/>
<inertia ixx="0.002" ixy="0" ixz="0" iyy="0.002" iyz="0" izz="0.001"/>
</inertial>
</link>
<!-- 2. 定义机械臂连杆 -->
<link name="arm_link">
<visual>
<origin xyz="0 0 0" rpy="0 0 0"/>
<geometry>
<cylinder radius="0.05" length="0.5"/> <!-- 半径和高度 -->
</geometry>
<material name="red">
<color rgba="1 0 0 1"/> <!-- 红色 -->
</material>
</visual>
<collision>
<geometry><cylinder radius="0.05" length="0.5"/></geometry>
</collision>
<inertial>
<mass value="2"/>
<inertia ixx="0.1" ixy="0" ixz="0" iyy="0.1" iyz="0" izz="0.1"/>
</inertial>
</link>
<!-- 3. 定义连接两者的关节 -->
<joint name="base_to_arm" type="fixed">
<parent link="base_link"/> <!-- 父级:底座 -->
<child link="arm_link"/> <!-- 子级:机械臂 -->
<origin xyz="0 0 0.14" rpy="0 0 0"/> <!-- 机械臂安装在底座上方 -->
</joint>
</robot>
3.2 URDF 的组件
| 类别 | 标签 | 说明 |
|---|---|---|
| 根节点 | <robot> |
整个模型的顶层容器,所有连杆和关节必须包含在内。name 属性是机器人的唯一标识。 |
| 连杆(刚体) | <link> |
机器人的独立零件(如底座、机械臂)。包含三大核心属性:外观、碰撞、惯性。 |
| ↳ 外观 | <visual> |
定义零件的“长相”(形状、颜色),仅用于 RViz 等工具的可视化显示,不参与物理计算。 |
| ↳ 碰撞 | <collision> |
定义零件的“碰撞边界”,供物理引擎(如 Gazebo)进行碰撞检测计算。 |
| ↳ 惯性 | <inertial> |
定义零件的质量(<mass>)和转动惯量(<inertia>),是动力学仿真中模型不“飘”起来的关键。 |
| 关节(连接) | <joint> |
零件之间的“连接器”,定义两个 Link 之间的运动关系和约束。 |
| ↳ 类型 | type 属性 |
fixed(固定)、revolute(旋转带限位)、continuous(无限旋转)、prismatic(线性滑动)等。 |
| ↳ 连接关系 | <parent> / <child> |
明确指定该关节连接的两个连杆,确立运动学树形结构的父子关系。 |
| ↳ 位姿与轴线 | <origin> / <axis> |
<origin> 定义子连杆相对于父连杆的安装位置;<axis> 定义关节的旋转或滑动轴线。 |
| ↳ 运动约束 | <limit> |
定义关节的运动极限,包括最大/最小角度、最大速度和最大扭矩。 |
| 辅助扩展 | <material> |
定义零件的颜色或纹理,支持全局定义并在 Link 中引用,避免重复编写。 |
| ↳ 仿真配置 | <gazebo> |
Gazebo 仿真专用标签,用于设置材料属性、摩擦力或加载 Gazebo 插件。 |
注意:URDF 模型必须是开环的树形结构,不允许存在闭环(即不支持并联机器人结构)。
4. MJCF 格式讲解
MJCF(MuJoCo XML Format)是专为高精度物理仿真设计的模型描述格式,专用于 MuJoCo 引擎。
4.1 完整示例
以下面的 MJCF 为例:
<!-- 1. 根节点:整个 MJCF 文件的唯一顶层元素 -->
<mujoco model="reference_robot">
<!-- 2. 编译选项:控制 MuJoCo 如何解析这个 XML 文件 -->
<!-- 可省略:MuJoCo 会使用默认的编译设置 -->
<compiler
angle="radian" <!-- 关节角度单位:radian(弧度) 或 degree(角度) -->
meshdir="assets" <!-- 外部 3D 网格文件(.stl/.obj)的相对路径 -->
autolimits="true" <!-- 如果未写 <limit>,是否根据关节范围自动生成限位 -->
balanceinertia="true" <!-- 自动调整惯性矩阵,防止物理仿真时出现 NaN 错误 -->
/>
<!-- 3. 物理引擎选项:定义整个仿真世界的物理法则 -->
<!-- 可省略:使用引擎默认的积分器和重力设置 -->
<option
timestep="0.002" <!-- 仿真时间步长(秒)。越小越精确,但计算越慢 -->
gravity="0 0 -9.81" <!-- 全局重力加速度向量 -->
integrator="Euler" <!-- 积分器类型:Euler(快) 或 RK4(精确但慢) -->
impratio="1" <!-- 摩擦锥阻抗比。大于1可防止物体在接触时滑动 -->
/>
<!-- 4. 默认属性组:类似于 CSS,用于提取公共属性,避免代码冗余 -->
<!-- 可省略:但强烈建议保留,能让模型代码极其整洁 -->
<default>
<!-- 定义一个名为 "robot_arm" 的默认类 -->
<default class="robot_arm">
<geom rgba="0.8 0.2 0.2 1" friction="0.8 0.02 0.001"/> <!-- 默认红色,带摩擦 -->
<joint damping="0.5" armature="0.01"/> <!-- 默认关节阻尼和转子惯量 -->
</default>
</default>
<!-- 5. 资产库:集中管理所有外部资源 -->
<!-- 可省略:如果不使用外部网格或纹理 -->
<asset>
<!-- 加载外部 3D 模型 -->
<mesh name="base_mesh" file="base.stl" scale="1 1 1"/>
<!-- 定义材质(可被多个 geom 复用) -->
<material name="metal" rgba="0.9 0.9 0.9 1" shininess="1" specular="1"/>
</asset>
<!-- 6. 世界主体:定义仿真场景中的所有刚体、几何体和光源 -->
<!-- 不可省略:这是构建运动学树的核心 -->
<worldbody>
<!-- 添加一盏平行光,照亮场景 -->
<!-- 可省略:MuJoCo 有默认光源,但自定义效果更好 -->
<light directional="true" pos="0 0 5" dir="0 0 -1"/>
<!-- 场景中的静态物体(如地面) -->
<!-- 不可省略(对于仿真):没有地面,机器人会无限自由落体 -->
<geom name="floor" type="plane" size="5 5 0.1" material="metal"/>
<!-- 6.1 机器人的根连杆 -->
<!-- 不可省略:代表一个刚体,嵌套的 body 构成运动学树 -->
<body name="base_link" pos="0 0 0.5">
<!-- 6.1.1 惯性属性 -->
<!-- 不可省略:没有质量,物体在物理引擎中会“飞天”或报错 -->
<inertial mass="10.0" pos="0 0 0" diaginertia="0.1 0.1 0.1"/>
<!-- 6.1.2 几何体 (Geom) -->
<!-- 不可省略:定义物体的“外观”和“碰撞边界” -->
<geom name="base_visual" type="box" size="0.2 0.2 0.1" class="robot_arm"/>
<!-- 6.1.3 关节 (Joint) -->
<!-- 可省略:如果不写 joint,该 body 默认与父级 rigidly fixed (刚性固定) -->
<joint name="joint_1" type="hinge" axis="0 1 0" range="-1.57 1.57"/>
<!-- 6.1.4 传感器锚点 (Site) -->
<!-- 可省略:纯标记点,无质量、不参与碰撞,常用于挂载传感器或 IK 目标 -->
<site name="end_effector" pos="0 0 0.5" rgba="0 1 0 1"/>
<!-- 6.2 子连杆(通过嵌套表达父子关系,无需像 URDF 那样写 parent/child) -->
<body name="arm_link" pos="0 0 0.5">
<inertial mass="2.0" pos="0 0 0.25" diaginertia="0.05 0.05 0.01"/>
<geom type="cylinder" size="0.05 0.25" class="robot_arm"/>
<joint name="joint_2" type="hinge" axis="0 1 0" damping="1.0"/>
</body>
</body>
</worldbody>
<!-- 7. 接触控制:精细管理哪些物体之间可以发生碰撞 -->
<!-- 可省略:默认情况下,所有 geom 都会参与碰撞检测 -->
<contact>
<!-- 忽略 base_link 和 arm_link 之间的碰撞(防止自己碰自己) -->
<exclude body1="base_link" body2="arm_link"/>
</contact>
<!-- 8. 执行器 (Actuator):机器人的“肌肉”,用于驱动关节 -->
<!-- 可省略:如果不写,仿真中无法通过代码控制机器人 -->
<actuator>
<!-- 力矩电机:直接控制关节扭矩 -->
<motor name="motor_1" joint="joint_1" gear="100" ctrlrange="-50 50"/>
<!-- 位置控制器:内置 PID,控制关节到达指定角度 -->
<position name="pos_ctrl_2" joint="joint_2" kp="100" kv="10"/>
</actuator>
<!-- 9. 传感器 (Sensor):机器人的“五官”,用于获取环境或自身状态 -->
<!-- 可省略:如果不需要读取反馈数据 -->
<sensor>
<!-- 读取关节1的当前角度 -->
<jointpos name="enc_1" joint="joint_1"/>
<!-- 读取末端执行器的三维加速度 -->
<accelerometer name="imu_acc" site="end_effector"/>
</sensor>
<!-- 10. 关键帧 (Keyframe):保存特定的初始状态快照 -->
<!-- 可省略:常用于强化学习或回放,保存特定的 qpos 和 ctrl -->
<keyframe>
<key name="home_pose" qpos="0 0" ctrl="0 0"/>
</keyframe>
</mujoco>
4.2 快速理解 MJCF 文件
- 看
<worldbody>:通过<body>的缩进和嵌套,直接在脑海中画出机器人的“骨骼树”。 - 找
<geom>:它是肉,决定了机器人长什么样、哪里会撞。 - 找
<joint>:它是骨头间的软骨,决定了哪里能动、怎么动。 - 看
<actuator>和<sensor>:它们是神经和肌肉,决定了你怎么控制它,以及它能感知什么。
5. URDF 与 MJCF 对比总结
| 对比维度 | URDF | MJCF |
|---|---|---|
| 所属生态 | ROS / Gazebo | MuJoCo 引擎 |
| 核心定位 | 描述机器人静态物理结构 | 描述机器人结构 + 完整仿真环境 |
| 父子关系 | 通过 <parent> / <child> 显式声明 |
通过 <body> 嵌套隐式表达 |
| 物理仿真 | 需借助 Gazebo 插件扩展 | 原生支持,内置物理引擎参数 |
| 闭环支持 | 不支持(必须树形结构) | 支持(可定义接触约束) |
| 适用场景 | ROS 机器人建模、导航、MoveIt | 强化学习、高精度物理仿真 |
6. 总结与避坑提示
本文从 XML 基础语法出发,系统讲解了 URDF 和 MJCF 两种机器人建模格式。URDF 适合 ROS 生态下的机器人建模与导航,MJCF 则更适合 MuJoCo 引擎下的高精度物理仿真和强化学习。
在实际使用中,建议注意以下几点:
- 惯性参数不能省略:URDF 中缺少
<inertial>会导致动力学仿真异常,MJCF 中缺少<inertial>会导致物体“飞天”或报错。 - URDF 不支持闭环:并联机器人结构无法用 URDF 描述,可考虑改用 MJCF 或 SDF 格式。
- MJCF 的
<compiler>和<option>建议保留:虽然可省略,但显式配置能避免默认参数带来的意外行为。 - 代码中的注释是理解模型的关键:建议在编写 URDF 和 MJCF 时保留详细注释,方便后续维护和团队协作。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)