摘要:本文从 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 时保留详细注释,方便后续维护和团队协作。
Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐