1. URDF 入门:什么是 URDF、它在仿真中的作用、文件基本结构

各位同学,欢迎来到这门课的第一章。咱们先不急着写代码,先把 URDF 这个家伙搞清楚。说白了,URDF 就是机器人的「身份证」加「骨架说明书」。

我刚开始接触机器人仿真时,也以为 URDF 是什么高深莫测的东西。后来踩了不少坑才明白——它其实就是一堆描述机器人长什么样、关节怎么动的 XML 文本。嗯,咱们今天就把这事聊透。

1.1 什么是 URDF?

URDF 全称是 Unified Robot Description Format,统一机器人描述格式。它是 ROS 生态里用来描述机器人模型的标准化语言。

你可以把它理解成机器人的「乐高拼装说明书」:

  • 每个零件(连杆)长什么形状、多大尺寸、多重
  • 零件之间怎么连接(关节)
  • 关节能怎么动(旋转、平移、固定)
  • 零件之间的相对位置和朝向

我个人习惯把 URDF 文件比作机器人的「骨骼」——它不包含大脑(控制逻辑),也不包含肌肉(驱动代码),但它定义了所有运动的基础框架。

核心要点: URDF 只描述机器人的几何结构和运动学关系,不涉及动力学参数、传感器数据处理或控制算法。

1.2 URDF 在机器人仿真中的作用

你可能会问:我直接在 CAD 里画好模型,导入 Gazebo 不行吗?

行,但不够灵活。URDF 在仿真中扮演了三个关键角色:

作用 说明 我的经验
可视化 在 RViz 或 Gazebo 中显示机器人外观 我曾经用纯几何体拼了一个六轴机械臂,调试时一眼就能看出关节是否装反
运动学计算 定义关节类型和运动范围,让仿真器知道机器人能怎么动 有一次忘记设置关节限位,仿真时机械臂直接「转圈圈」飞出去了
碰撞检测 告诉仿真器哪些部分不能互相穿透 这个特别重要,后面我会专门讲避坑

说白了,没有 URDF,Gazebo 就不知道你造了个什么东西。它只能看到一个空荡荡的世界。

小提示: URDF 也是 ROS 中很多功能包的输入接口。比如 moveit 做运动规划、gazebo_ros_control 做仿真控制,都需要 URDF 作为基础。

1.3 URDF 文件的基本结构

URDF 文件本质上是一个 XML 文档。它的根元素是 <robot>,里面包含两大类核心元素:link(连杆)和 joint(关节)。

我给大家画了一张结构图,先看整体再拆细节:

URDF 文件基本结构 <robot> link(连杆) visual(视觉) collision(碰撞) inertial(惯性) joint(关节) parent(父连杆) child(子连杆) origin(原点) 一个 <robot> 下可以有多个 link 和 joint link 和 joint 通过 parent/child 关系形成树状结构

好,结构看完了。咱们来拆一个最简单的例子——一个两连杆的机械臂:

<?xml version="1.0" encoding="utf-8"?>
<robot name="simple_arm">

  <!-- 第一个连杆:基座 -->
  <link name="base_link">
    <visual>
      <geometry>
        <box size="0.2 0.2 0.1"/>
      </geometry>
      <origin xyz="0 0 0" rpy="0 0 0"/>
    </visual>
  </link>

  <!-- 第二个连杆:手臂 -->
  <link name="arm_link">
    <visual>
      <geometry>
        <cylinder length="0.4" radius="0.05"/>
      </geometry>
      <origin xyz="0 0 0.2" rpy="0 0 0"/>
    </visual>
  </link>

  <!-- 连接基座和手臂的旋转关节 -->
  <joint name="arm_joint" type="revolute">
    <parent link="base_link"/>
    <child link="arm_link"/>
    <origin xyz="0 0 0.05" rpy="0 0 0"/>
    <axis xyz="0 0 1"/>
    <limit lower="-1.57" upper="1.57" effort="10" velocity="1.0"/>
  </joint>

</robot>

这段代码虽然短,但包含了 URDF 最核心的要素。我来逐一说一下:

1.4 link 详解

每个 <link> 代表机器人上的一个刚体部件。它有三个子元素:

  • visual:定义外观,用于显示。可以是一个盒子、圆柱、球体,或者导入的 STL 网格文件。
  • collision:定义碰撞形状。我建议尽量用简单几何体代替复杂网格,仿真效率会高很多。
  • inertial:定义质量、质心和惯性张量。Gazebo 做物理仿真时必须要有这个,否则仿真会崩。
注意: 我曾经在项目里只写了 visual 忘了写 collision,结果 Gazebo 里两个连杆直接「穿模」了。仿真器默认没有碰撞形状时,是不会做碰撞检测的。

1.5 joint 详解

<joint> 定义了连杆之间的连接关系。常用的关节类型有:

类型 说明 典型用途
fixed 固定连接,不能运动 传感器支架、摄像头安装座
revolute 旋转关节,有角度限制 机械臂关节、轮子转向
continuous 连续旋转,无角度限制 车轮、转台
prismatic 平移关节,直线运动 伸缩臂、滑轨

每个关节必须指定 parent 和 child,形成树状结构。注意:URDF 不允许有闭环结构,比如四足机器人的腿不能直接写成闭环,需要特殊处理。

我的习惯: 写 URDF 时,我会先画一个树状图,标清楚每个 link 和 joint 的父子关系。这样写出来的文件结构清晰,不容易出错。

1.6 坐标系与原点

URDF 里每个 link 和 joint 都有自己的坐标系。这里有个容易混淆的点:

  • link 的 origin:相对于 link 自身坐标系的偏移。比如圆柱体的几何中心默认在原点,如果你想让它「长」在基座上面,就需要调整 origin。
  • joint 的 origin:相对于 parent link 坐标系的偏移。它定义了 child link 从哪「长」出来。

我记得刚学的时候,经常搞混这两个 origin。后来我总结了一个口诀:「link 管自己长什么样,joint 管它长在哪」。

1.7 本章小结

咱们今天聊了 URDF 的三个核心问题:

  1. 是什么——机器人的 XML 描述文件,定义结构和运动学
  2. 有什么用——让 Gazebo 和 RViz 知道机器人长什么样、能怎么动
  3. 怎么写——link 定义部件,joint 定义连接,形成树状结构