URDF vs MJCF vs SDF:三大机器人模型格式完全指南
URDF、MJCF、SDF 是机器人仿真三大模型描述格式。本文深入对比三者的结构差异、表达能力、适用场景,并给出格式选择决策表与互转工具链实操命令。
在机器人开发里,无论你用的是 RViz、Gazebo、MuJoCo、PyBullet 还是 Isaac Sim,第一件要做的事都是把机器人"喂"给仿真器——告诉它:连杆长什么样、关节怎么连、质量怎么分布、有没有闭环、用什么执行器。这件事的载体就是机器人模型描述格式。
如今生态里事实上并存的三大格式是:
- URDF:ROS 社区的老牌 XML 格式,覆盖最广
- MJCF:MuJoCo 的原生格式,为快速接触式仿真而生
- SDF:OSRF/Gazebo 的格式,目标是补齐 URDF 的全部短板
理解三者的设计取舍,是机器人仿真这条路上走得长远的第一步。
URDF(Unified Robot Description Format)
URDF 是 ROS 社区提出的一种 XML 格式,用来描述机器人的运动学与质量属性。它本质上只定义三件事:
- Link(连杆):质量、惯性张量、视觉模型、碰撞模型
- Joint(关节):连接两个 link,声明类型(revolute / prismatic / continuous / fixed 等)、轴向、限位
- Material:视觉模型的颜色或纹理
一份最小可用的 URDF 长这样(两连杆 + 一个旋转关节,带完整惯性参数):
<?xml version="1.0"?>
<robot name="two_link">
<link name="base_link">
<inertial>
<mass value="1.0"/>
<inertia ixx="0.001" ixy="0" ixz="0" iyy="0.001" iyz="0" izz="0.001"/>
</inertial>
<visual>
<geometry><box size="0.1 0.1 0.1"/></geometry>
</visual>
</link>
<link name="link1">
<inertial>
<mass value="0.5"/>
<inertia ixx="0.0005" ixy="0" ixz="0" iyy="0.0005" iyz="0" izz="0.0005"/>
</inertial>
<visual>
<geometry><cylinder length="0.2" radius="0.02"/></geometry>
</visual>
</link>
<joint name="joint1" type="revolute">
<parent link="base_link"/>
<child link="link1"/>
<origin xyz="0 0 0.1" rpy="0 0 0"/>
<axis xyz="0 0 1"/>
<limit lower="-3.14" upper="3.14" effort="10" velocity="1.0"/>
</joint>
</robot>URDF 的优势:
- 生态最广:ROS、RViz、MoveIt、Gazebo、PyBullet、Pinocchio、Drake 都能直接读 URDF
- 厂商官方支持:Franka、UR、KUKA、Boston Dynamics 等都会发布官方 URDF,例如 Franka Panda、UR5
- 简单上手:XML 结构清晰,新手半小时就能跑通
URDF 的硬伤:
- 只能描述树状拓扑——闭环机构(四足的平行连杆、Delta、Stewart 平台)写不出来
- 没有仿真参数——摩擦系数、接触模型、执行器、传感器都不在 URDF 标准里
- 不支持
<include>——大机器人必须拆成 xacro(一种宏语言)来组织
MJCF(MuJoCo XML Format)
MJCF 是 MuJoCo 仿真器的原生格式。和 URDF 不同,它从第一天起就是为快速、可微、接触丰富的物理仿真服务的——它把"几何 + 关节 + 执行器 + 传感器 + 仿真器配置"全部塞进同一个文件,本质上是一个"完整可仿真系统"的描述。
一份最小 MJCF(两连杆 + 一个执行器,含 timestep 与 gravity):
<?xml version="1.0"?>
<mujoco model="two_link">
<option timestep="0.002" gravity="0 0 -9.81"/>
<worldbody>
<body name="base" pos="0 0 0">
<geom type="box" size="0.05 0.05 0.05" mass="1"/>
<body name="link1" pos="0 0 0.1">
<joint name="joint1" type="hinge" axis="0 0 1" range="-3.14 3.14"/>
<geom type="capsule" fromto="0 0 0 0 0 0.2" size="0.02" mass="0.5"/>
</body>
</body>
</worldbody>
<actuator>
<motor joint="joint1" gear="1"/>
</actuator>
</mujoco>MJCF 的优势:
- 闭环、约束、软接触是一等公民——
<equality>、<tendon>、<contact>直接写进文件 - 执行器、传感器内置——
<motor>、<position>、<velocity>、<sensor>开箱即用 - 加载极快——MuJoCo 解析 + 编译只需毫秒级,比 SDF 快一两个数量级
- 可微 + GPU 加速——MuJoCo XLA(MJX)天然支持,强化学习首选
MJCF 的缺点:
- MuJoCo 专属——拿到 ROS / Drake / Isaac 里需要转换
- 调参文化重——同一台机器人可以写出"卡顿版"也可以写出"丝滑版",例如 Unitree G1 在 mujoco_menagerie 里的 MJCF 就是人工精调过的
SDF(Simulation Description Format)
SDF 是 OSRF(Open Source Robotics Foundation)提出的格式,设计目标直指 URDF 的全部短板:支持闭环、支持完整世界、支持 include、语义版本化。从 Gazebo Fortress 起(即"Ignition Gazebo"),SDF(SDFormat)成为 Gazebo 的默认格式。
一份最小 SDF(两连杆,含 model / sdf version 头):
<?xml version="1.0"?>
<sdf version="1.9">
<model name="two_link">
<link name="base_link">
<inertial>
<mass>1.0</mass>
<inertial>
<ixx>0.001</ixx><ixy>0</ixy><ixz>0</ixz>
<iyy>0.001</iyy><iyz>0</iyz><izz>0.001</izz>
</inertial>
</inertial>
<collision name="col">
<geometry><box><size>0.1 0.1 0.1</size></box></geometry>
</collision>
</link>
<link name="link1">
<inertial>
<mass>0.5</mass>
<inertial>
<ixx>0.0005</ixx><ixy>0</ixy><ixz>0</ixz>
<iyy>0.0005</iyy><iyz>0</iyz><izz>0.0005</izz>
</inertial>
</inertial>
</link>
<joint name="joint1" type="revolute">
<parent>base_link</parent>
<child>link1</child>
<axis>
<xyz>0 0 1</xyz>
<limit><lower>-3.14</lower><upper>3.14</upper></limit>
</axis>
</joint>
</model>
</sdf>SDF 的优势:
- 支持闭环与并列约束——
<joint>可以连任意两个 link,不限于父子树 - 完整仿真世界——
<world>里可放光照、地面、多个机器人、传感器 - 支持
<include>和嵌套模型——模块化复用,告别 xacro 黑魔法 - 语义版本化——
<sdf version="1.9">,解析器可按版本兼容
SDF 的缺点:
- 生态相对绑定 Gazebo——ROS 2 + Gazebo Fortress 之后才全面切到 SDFormat
- 文档与社区规模比 URDF 小
- 加载比 MJCF 慢——SDF 世界描述很重,启动一个大世界要几秒到十几秒
三大格式对比表
| 特性 | URDF | MJCF | SDF |
|---|---|---|---|
| 拓扑结构 | 仅树状 | 树 + 闭环 + 约束 | 树 + 闭环 + 约束 |
| 闭环支持 | ❌ 需 hack | ✅ 一等公民 | ✅ 一等公民 |
| 仿真参数(摩擦/接触) | ❌ 靠扩展标签 | ✅ 原生 | ✅ 原生 |
| 执行器 / 传感器 | ❌ 不在标准 | ✅ 内置 | ✅ 内置 |
| 世界 / 环境描述 | ❌ 仅机器人 | ⚠️ worldbody 简单 | ✅ 完整世界(光照/地面) |
| include 支持 | ❌ 需 xacro | ✅ <include> | ✅ <include> + 嵌套 |
| 仿真器生态 | ROS / PyBullet / Drake | MuJoCo / MJX | Gazebo / Ignition |
| 加载速度 | 快 | 极快(毫秒级) | 较慢 |
| 可微仿真 | ❌ | ✅ MJX | ❌ |
| 社区规模 | 最大 | RL 圈最大 | Gazebo 圈 |
何时用哪个?决策表
| 场景 | 推荐格式 | 原因 |
|---|---|---|
| ROS / MoveIt 控制 | URDF | MoveIt 强依赖 URDF + SRDF |
| MuJoCo / MJX 强化学习 | MJCF | 充分利用接触模型与执行器 |
| Gazebo 多机器人仿真世界 | SDF | SDF 原生支持 <world> |
| 四足 / Delta / 闭环机构 | MJCF 或 SDF | URDF 表达不了闭环 |
| PyBullet 仿真 | URDF | PyBullet 原生支持 URDF |
| Sim-to-real 可微仿真 | MJCF | MuJoCo MJX 提供梯度 |
| Isaac Sim 仿真 | URDF | Isaac Sim 自带 URDF 转换器 |
| 工业机械臂(树状) | URDF | 厂商直接给,省事 |
经验法则:ROS 生态优先 URDF,RL 训练优先 MJCF,Gazebo 多机器人世界优先 SDF。
格式互转工具链
三种格式并非无损等价,转换时常会丢信息——尤其是惯性参数、关节限位、接触参数、执行器增益。下面是常用命令:
# URDF -> MJCF:用 MuJoCo 自带的 mjxml 模块
python -m mujoco.mjxml --input=robot.urdf --output=robot.xml
# 或者直接用 MuJoCo 的 compile 工具(带 GUI 预览)
python -m mujoco --xml=robot.urdf
# URDF -> SDF:用 Gazebo 工具链(gz / ign)
gz sdf -p robot.urdf -o robot.sdf
# 老版本(Ignition / Gazebo Classic):
ign sdf -p robot.urdf -o robot.sdf
# SDF -> URDF:同样用 gz sdf,加 --export-urdf
gz sdf -p robot.sdf --export-urdf -o robot.urdf
# MJCF -> URDF:没有官方工具,社区脚本 + 手工修补
# 参考 mujoco_menagerie 里的人工导出经验:
git clone https://github.com/google-deepmind/mujoco_menagerie重要提示:转换几乎总是有损的。常见丢失项:
- URDF → MJCF:默认摩擦/接触参数可能不合理,需要手动调
<default>- URDF → SDF:惯性与碰撞几何通常保留,但传感器/插件需要重写
- MJCF → URDF:闭环约束、tendon、equality constraint 全部丢失(URDF 表达不了)
推荐工作流:URDF 作为 single source of truth,用 build 脚本(xacro + mjxml + gz sdf)导出到各仿真器,转换结果用 MuJoCo viewer 或 Gazebo 验证后再提交。
mujoco_menagerie 是 Google DeepMind 维护的官方 MJCF 模型仓库,覆盖了 Unitree G1、Unitree H1、ANYmal C、Franka Panda 等热门机器人——做 RL 训练时强烈建议优先用它,而不是自己从 URDF 转。
实战建议
1. URDF 作为单一真源(Single Source of Truth)
中型团队最稳的做法是:以 URDF(+ xacro)为唯一手写源,CI 里跑 build 脚本自动导出 MJCF / SDF,保证三种格式同步。这样厂商提供的 URDF、ROS 工具链、训练代码都能复用同一份几何。
2. 大型模型组织
- URDF:用 xacro 宏语言组织——把腿、手臂抽成可参数化的宏
- SDF:用
<include>+ 嵌套模型——例如一条腿存成单独的.sdf,主模型 include 进来 - MJCF:用
<include>把执行器、传感器拆到子文件
3. 转换结果必须验证
- MJCF:
python -m mujoco.viewer --mjcf=robot.xml,检查惯性、限位、接触 - SDF / URDF:在 Gazebo 或 RViz 里加载,肉眼比对视觉模型和碰撞模型
- 如果导出后机器人"软得像面条"或"硬得像石头",八成是惯性或默认摩擦出问题了
小结
URDF、MJCF、SDF 不是竞争关系,而是互补:
- URDF 是控制与生态的通用语,覆盖最广但表达力最弱
- MJCF 是接触式仿真与可微 RL 的王者,但绑死 MuJoCo
- SDF 是完整仿真世界的载体,Gazebo 多机器人场景的默认选择
理解三者各自的设计取舍——URDF 求广、MJCF 求快求准、SDF 求全——是在机器人仿真工程上做对决策的关键。