3、URDF模型构建:从零搭建一个6轴机械臂的URDF模型

URDF,全称是 Unified Robot Description Format。说白了,它就是机器人的「身份证」加「骨架说明书」。你要让仿真环境认识你的机械臂,就得用 URDF 把它的关节、连杆、尺寸、颜色,一五一十地告诉系统。

我记得刚入行那会儿,总觉得 URDF 就是个 XML 文件,随便写写就行。结果第一次加载模型,机械臂的关节全拧成了麻花。嗯,从那以后,我再也不敢小看这个文件了。

3.1 URDF 的核心结构

一个完整的 URDF 模型,由两个基本元素组成:link(连杆)和 joint(关节)。

  • link:描述机械臂的刚体部分,包括几何形状、尺寸、颜色、惯性参数。
  • joint:描述两个 link 之间的连接关系,包括类型、父级、子级、运动范围。

你想想看,6 轴机械臂就是 6 个 joint 加上 7 个 link(基座 + 6 个连杆)。关节把连杆串起来,就成了一整条运动链。

关键原则:URDF 的坐标系是树状结构。基座是根节点,每个 joint 只能有一个父 link 和一个子 link。不能有环,不能有分叉。

3.2 从基座开始:第一个 link

我个人习惯,先从基座写起。基座是整条链的根,它没有父关节,只有子关节。

<robot name="my_6axis_arm">
  <link name="base_link">
    <visual>
      <geometry>
        <cylinder length="0.1" radius="0.08"/>
      </geometry>
      <origin rpy="0 0 0" xyz="0 0 0"/>
      <material name="base_color">
        <color rgba="0.2 0.5 0.8 1.0"/>
      </material>
    </visual>
  </link>
</robot>

这里我用了圆柱体作为基座。origin 表示几何中心相对于 link 坐标原点的偏移。rpy 是绕 X、Y、Z 轴的旋转角度。嗯,这里要注意:visual 只负责显示,不影响碰撞检测。如果你要做物理仿真,还得加一个 collision 块。

我的经验:visual 和 collision 尽量用相同的几何体。如果不一样,仿真时会出现「看着没撞上,实际撞上了」的诡异情况。我踩过这个坑,调试了整整一个下午。

3.3 添加关节:让机械臂动起来

基座写好了,接下来加第一个关节。6 轴机械臂的关节类型,绝大多数是 revolute(旋转关节)。

<joint name="joint1" type="revolute">
  <parent link="base_link"/>
  <child link="link1"/>
  <origin rpy="0 0 0" xyz="0 0 0.05"/>
  <axis xyz="0 0 1"/>
  <limit lower="-3.14" upper="3.14" effort="10" velocity="1.0"/>
</joint>

这里 axis 定义了旋转轴。xyz="0 0 1" 表示绕 Z 轴旋转。limit 里的 lower 和 upper 是弧度制的关节限位。effort 是最大力矩,velocity 是最大速度。

为什么会这样设计?因为实际电机就有这些限制。仿真里不设限位,关节就会无限旋转,跟现实完全脱节。

3.4 完整的 6 轴机械臂 URDF 骨架

下面是一个简化版的 6 轴 URDF 骨架。每个关节都绕 Z 轴旋转,连杆长度依次递增。

<robot name="six_axis_arm">
  <!-- 基座 -->
  <link name="base_link">
    <visual>
      <geometry><cylinder length="0.1" radius="0.08"/></geometry>
      <origin rpy="0 0 0" xyz="0 0 0"/>
      <material name="blue"><color rgba="0.2 0.5 0.8 1.0"/></material>
    </visual>
  </link>

  <!-- 关节1 -->
  <joint name="joint1" type="revolute">
    <parent link="base_link"/>
    <child link="link1"/>
    <origin rpy="0 0 0" xyz="0 0 0.05"/>
    <axis xyz="0 0 1"/>
    <limit lower="-3.14" upper="3.14" effort="10" velocity="1.0"/>
  </joint>

  <link name="link1">
    <visual>
      <geometry><box size="0.05 0.05 0.3"/></geometry>
      <origin rpy="0 0 0" xyz="0 0 0.15"/>
      <material name="red"><color rgba="0.8 0.2 0.2 1.0"/></material>
    </visual>
  </link>

  <!-- 关节2 ~ 关节6 结构类似,依次连接 -->
  <joint name="joint2" type="revolute">
    <parent link="link1"/>
    <child link="link2"/>
    <origin rpy="0 0 0" xyz="0 0 0.3"/>
    <axis xyz="0 0 1"/>
    <limit lower="-3.14" upper="3.14" effort="10" velocity="1.0"/>
  </joint>

  <link name="link2">
    <visual>
      <geometry><box size="0.04 0.04 0.25"/></geometry>
      <origin rpy="0 0 0" xyz="0 0 0.125"/>
      <material name="green"><color rgba="0.2 0.8 0.2 1.0"/></material>
    </visual>
  </link>

  <!-- 后续关节和连杆省略,结构完全一致 -->
</robot>

避坑指南:origin 的 xyz 偏移量,是子 link 坐标系原点相对于父 joint 原点的位置。不是子 link 几何中心的位置。我曾经把这两个搞混,结果机械臂的连杆全飞到了天上。

3.5 知识体系总览

下面这张图,把 URDF 构建的核心逻辑串起来了。你可以把它当作写 URDF 时的检查清单。

URDF 模型构建知识体系 URDF 文件 link(连杆) joint(关节) visual(视觉) collision(碰撞) inertial(惯性) type(类型) origin(偏移) axis(旋转轴) revolute(旋转) lower/upper effort velocity 核心原则:树状结构,无环无分叉;每个 joint 只有一个父 link 和一个子 link 6轴机械臂 = 6个 joint + 7个 link(基座 + 6个连杆)

3.6 参数对比:不同关节类型的适用场景

URDF 支持多种关节类型。6 轴机械臂主要用 revolute,但其他类型也有用武之地。比如夹爪的平移,就用 prismatic。

关节类型 运动方式 典型应用 6轴机械臂使用频率
revolute 绕轴旋转(有限角度) 肩关节、肘关节、腕关节 ★★★★★
continuous 绕轴旋转(无限角度) 末端执行器旋转 ★★☆☆☆
prismatic 沿轴平移 夹爪开合、升降机构 ★☆☆☆☆
fixed 无运动 传感器支架、固定连接 ★★★☆☆
floating 6自由度自由运动 移动基座、无人机 ☆☆☆☆☆

我的建议:刚开始写 URDF,先用 revolute 和 fixed 两种类型就够了。等模型能在 Rviz 里正常显示、关节能正常转动,再考虑加其他类型。一口吃不成胖子,URDF 也是。

3.7 验证模型:用 check_urdf 工具

写完了 URDF,别急着加载到仿真里。先用 ROS 自带的工具检查一下语法。

# 安装工具
sudo apt install liburdfdom-tools

# 检查 URDF 文件
check_urdf my_6axis_arm.urdf

如果输出类似下面这样,说明模型结构正确:

robot name is: my_6axis_arm
---------- Successfully Parsed XML ---------------
root link: base_link has 1 child(ren)
    child(1):  link1
        child(1):  link2
            ...

如果有错误,工具会告诉你哪个关节的 parent 或 child 找不到。嗯,我遇到过最蠢的错误——把 link 名字拼错了,大小写不一致。URDF 是大小写敏感的,base_link 和 Base_link 是两个完全不同的连杆。

避坑指南:URDF 文件编码必须用 UTF-8,不要带 BOM。Windows 下用记事本编辑容易踩这个坑。我曾经从 Windows 拷了一个 URDF 到 Ubuntu,加载时一直报 XML 解析错误,折腾了半天才发现是 BOM 的问题。

3.8 本章小结

URDF 模型构建,说白了就是搭积木。link 是积木块,joint 是连接销。你只要把每个积木的位置、大小、颜色定义清楚,再把连接销的类型、范围、轴线设置好,一个完整的机械臂模型就出来了。

我个人习惯,每写完一个关节,就用 check_urdf 验证一次。不要等到全部写完再查错,那样定位问题会非常痛苦。你想想看,6 个关节 7 个连杆,如果最后一个关节的 origin 写错了,你得从头排查到尾巴。