第2章:机器人模型URDF——从零编写URDF文件,理解link与joint,在仿真中显示机器人

说实话,URDF(Unified Robot Description Format)是每个机器人工程师的入门必修课。我当年第一次接触它时,觉得不就是个XML文件嘛,有什么难的?结果真到自己写的时候,link和joint的关系绕得我头晕。今天咱们就把它彻底捋清楚。

2.1 URDF到底是什么?

URDF说白了就是机器人的「身份证」。它用XML格式描述机器人长什么样、关节怎么动、传感器装在哪。你想想看,仿真器不认识你的机器人,你得用URDF告诉它:这里有个轮子,那里有个手臂,它们之间怎么连接。

我个人习惯把URDF看作机器人的「骨架」——link是骨头,joint是关节。骨头本身不会动,关节决定了骨头之间怎么相对运动。

核心概念:

  • link:刚体部件,有质量、惯性、视觉形状、碰撞形状
  • joint:连接两个link,定义运动类型和相对位置

2.2 从零写一个最简单的URDF

咱们先别整复杂的。我带你写一个只有两个link和一个joint的「哑铃」模型。嗯,就是一根杆子两头各一个球。

<?xml version="1.0"?>
<robot name="dumbbell">
  <!-- 第一个球 -->
  <link name="left_ball">
    <visual>
      <geometry>
        <sphere radius="0.1"/>
      </geometry>
      <origin xyz="0 0 0" rpy="0 0 0"/>
    </visual>
  </link>

  <!-- 第二个球 -->
  <link name="right_ball">
    <visual>
      <geometry>
        <sphere radius="0.1"/>
      </geometry>
      <origin xyz="0 0 0" rpy="0 0 0"/>
    </visual>
  </link>

  <!-- 连接杆 -->
  <link name="bar">
    <visual>
      <geometry>
        <cylinder length="0.5" radius="0.02"/>
      </geometry>
      <origin xyz="0 0 0" rpy="0 0 0"/>
    </visual>
  </link>

  <!-- 固定关节:左球到杆 -->
  <joint name="left_joint" type="fixed">
    <parent link="bar"/>
    <child link="left_ball"/>
    <origin xyz="-0.25 0 0" rpy="0 0 0"/>
  </joint>

  <!-- 固定关节:右球到杆 -->
  <joint name="right_joint" type="fixed">
    <parent link="bar"/>
    <child link="right_ball"/>
    <origin xyz="0.25 0 0" rpy="0 0 0"/>
  </joint>
</robot>

这里有个坑,我当年踩过:joint的origin是相对于parent link的坐标系。也就是说,左球在杆的左边0.25米处,右球在右边0.25米处。如果你搞反了parent和child,机器人会直接「散架」。

2.3 link的视觉与碰撞模型

你可能注意到了,上面只写了<visual>。但在真机迁移时,<collision>才是关键。为什么?

视觉模型只负责「看起来像」,碰撞模型才负责「物理上撞到」。我在做AGV小车时,为了好看把视觉模型做得很精细,结果碰撞模型没更新,仿真里小车直接穿墙而过……嗯,那场面挺尴尬的。

我的建议:

  • 视觉模型可以用复杂mesh,好看就行
  • 碰撞模型尽量用基本几何体(box、cylinder、sphere),计算效率高
  • 如果必须用mesh做碰撞,记得简化顶点数

2.4 joint的六种类型

joint类型决定了自由度。我整理了一张表,你直接拿去用:

类型 自由度 典型应用
fixed 0 底盘与传感器支架
revolute 1(旋转) 机械臂关节、轮子
prismatic 1(平移) 升降台、滑轨
continuous 1(无限旋转) 全向轮、转台
planar 2(平面运动) AGV全向移动
floating 6(全自由) 无人机、水下机器人

你想想看,如果选错了类型,仿真里关节要么卡死,要么乱飞。我见过有人把机械臂的旋转关节写成prismatic,结果一启动手臂直接「伸长」了半米……

2.5 在仿真中显示你的机器人

写好了URDF,怎么看到它?最直接的方式是用robot_state_publisher + joint_state_publisher + Rviz。

# 1. 启动robot_state_publisher,它会解析URDF并发布tf
ros2 launch robot_state_publisher robot_state_publisher.launch.py \
  urdf_file:=/path/to/your/dumbbell.urdf

# 2. 启动joint_state_publisher(如果有可动关节)
ros2 run joint_state_publisher joint_state_publisher

# 3. 打开Rviz,添加RobotModel显示
rviz2

在Rviz中,记得把Fixed Frame设为你的根link(比如上面的"bar")。我第一次做的时候忘了设,结果机器人模型在屏幕外飘着,找了半天……

注意:URDF中必须有一个根link,且所有joint最终都要连接到这个根上。否则Rviz会报错「No transform from ... to ...」。

2.6 知识体系结构图

下面这张图帮你理清URDF的核心逻辑。我画了好几次才满意,你仔细看看:

URDF知识体系结构 robot link visual collision inertial joint parent child origin link定义「有什么」,joint定义「怎么连」

2.7 避坑指南:我踩过的三个坑

  1. 坐标系搞反:我曾经把parent和child写反,结果机器人关节反向旋转。检查方法很简单——在Rviz里手动拖动joint,看运动方向对不对。
  2. 惯性参数缺失:Gazebo仿真时,如果link没有<inertial>,物理引擎会报错。我建议用urdf_to_graphiz工具检查完整性。
  3. 文件名编码问题:URDF里引用的mesh文件路径不要有中文或空格。我在Windows上写路径时吃过这个亏,ROS直接不认。

实用工具推荐:

  • check_urdf:检查URDF语法错误
  • urdf_to_graphiz:生成机器人结构图
  • rviz + robot_state_publisher:实时可视化调试

好了,URDF的基础就这些。你写的时候记住一句话:link是零件,joint是装配关系。把这个想明白,后面学xacro、学MoveIt都会轻松很多。

可可精品资料库