3、机器人URDF模型构建:URDF语法、link与joint定义、xacro宏优化、模型可视化

说到机器人仿真,第一步就是得有个“身体”。这个身体就是URDF模型。我刚开始接触ROS那会儿,觉得URDF不就是个XML文件嘛,写起来应该不难。结果第一次搭一个六轴机械臂,光是对关节坐标就折腾了一整天。嗯,这里面的门道其实不少。

URDF全称是Unified Robot Description Format,说白了就是ROS用来描述机器人长什么样的标准语言。它用link定义刚体部件,用joint定义连接关系。你想想看,一个机器人就是一堆铁疙瘩通过关节串起来,URDF就是把这些信息写成机器能读懂的格式。

核心要点:URDF只适用于串联结构的机器人。如果你要做并联机器人或者移动底盘带悬挂,URDF会力不从心,得用SDF或者xacro配合其他工具。我在项目里吃过这个亏,一开始没注意,后来仿真时轮子死活不接地。

3.1 URDF语法基础

URDF基于XML,标签不多,但每个都有讲究。最核心的就是<robot>根标签,里面包着<link>和<joint>。

一个link长这样:

<link name="base_link">
  <visual>
    <geometry>
      <box size="0.4 0.3 0.1"/>
    </geometry>
    <origin xyz="0 0 0" rpy="0 0 0"/>
    <material name="blue">
      <color rgba="0 0 1 1"/>
    </material>
  </visual>
  <collision>
    <geometry>
      <box size="0.4 0.3 0.1"/>
    </geometry>
  </collision>
  <inertial>
    <mass value="1.0"/>
    <inertia ixx="0.01" ixy="0" ixz="0"
              iyy="0.01" iyz="0"
              izz="0.01"/>
  </inertial>
</link>

这里有三块内容:visual是显示用的,collision是碰撞检测用的,inertial是动力学计算用的。我见过很多新手只写visual,结果一跑MoveIt规划,碰撞检测直接失效。记住,collision必须写,而且形状最好简化,别用太精细的网格。

joint的定义更关键,它决定了机器人怎么动:

<joint name="joint1" type="revolute">
  <parent link="base_link"/>
  <child link="arm_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>

type有六种:revolute(旋转)、prismatic(平移)、fixed(固定)、floating(浮动)、planar(平面)、continuous(连续旋转)。实际项目里90%用revolute和fixed。我曾经在做一个协作机器人时,把肩关节设成了continuous,结果仿真时手臂转个不停,线缆都拧成麻花了。

个人习惯:我一般把origin的xyz和rpy分开写注释,方便后面调参。尤其是rpy,很多人搞不清旋转顺序,URDF用的是固定轴XYZ顺序,也就是先绕X转,再绕Y,最后绕Z。

3.2 link与joint的坐标变换

这是URDF里最容易出bug的地方。每个joint的origin定义了子link相对于父link的变换。说白了,就是子link的坐标系原点在父link坐标系下的位置和姿态。

我画了一张图帮你理解:

父link (base_link) X Z 子link (arm_link1) X Z joint origin: xyz="0.3 0 -0.02" rpy="0 0 0" 子link的坐标系原点 = 父link坐标系下的 (0.3, 0, -0.02) 处

坐标变换搞错了,机器人看起来就像被拧断了胳膊。我调试时最常用的命令是tf_echo和view_frames,能直观看到每个link的坐标系位置。如果发现某个link飞出去了,八成是origin写错了。

3.3 xacro宏优化

写URDF最痛苦的是什么?重复劳动。一个六轴机械臂,六个关节的limit参数差不多,但得复制六遍。这时候xacro就派上用场了。

xacro是URDF的增强版,支持变量、数学运算、宏定义。说白了就是给URDF加了编程能力。

先看变量和数学运算:

<?xml version="1.0"?>
<robot xmlns:xacro="http://www.ros.org/wiki/xacro" name="my_robot">
  <xacro:property name="arm_length" value="0.4"/>
  <xacro:property name="arm_radius" value="0.05"/>
  
  <link name="arm_link">
    <visual>
      <geometry>
        <cylinder length="${arm_length}" radius="${arm_radius}"/>
      </geometry>
    </visual>
  </link>
</robot>

宏定义才是xacro的杀手锏。我习惯把重复的link和joint封装成宏:

<xacro:macro name="simple_arm_segment" params="name parent length radius">
  <link name="${name}_link">
    <visual>
      <geometry>
        <cylinder length="${length}" radius="${radius}"/>
      </geometry>
      <origin xyz="0 0 ${length/2}" rpy="0 0 0"/>
    </visual>
  </link>
  
  <joint name="${name}_joint" type="revolute">
    <parent link="${parent}"/>
    <child link="${name}_link"/>
    <origin xyz="0 0 ${length}" rpy="0 0 0"/>
    <axis xyz="0 0 1"/>
  </joint>
</xacro:macro>

调用的时候一行搞定:

<xacro:simple_arm_segment name="segment1" parent="base_link" length="0.3" radius="0.04"/>
<xacro:simple_arm_segment name="segment2" parent="segment1_link" length="0.25" radius="0.035"/>

注意:xacro文件不能直接被ROS解析,需要先转换成纯URDF。命令是rosrun xacro xacro.py model.xacro > model.urdf。我见过有人直接把.xacro文件丢给MoveIt,结果报错半天找不到原因。

3.4 模型可视化与调试

模型写好了,怎么看对不对?ROS提供了几个好用的工具。

1. 使用check_urdf做语法检查

这是第一步,也是最简单的一步:

$ check_urdf my_robot.urdf

它会告诉你有没有缺失的link、joint类型是否合法、坐标系是否连续。我每次改完URDF都会跑一遍,就像写代码要编译一样。

2. 使用urdf_to_graphiz生成结构图

这个命令会把URDF转换成一张树状图,直观展示link之间的父子关系:

$ urdf_to_graphiz my_robot.urdf

它会生成.gv和.pdf文件。打开PDF一看,哪个关节连哪个link一目了然。如果发现树结构有环,那肯定是joint的parent-child关系写反了。

3. 在RViz中实时查看

最终验证还是得靠RViz。启动方式很简单:

$ roslaunch urdf_tutorial display.launch model:=my_robot.urdf

在RViz里,你可以旋转、缩放、查看每个link的坐标系。我习惯把RobotModel和TF两个显示模块都打开,这样既能看模型外观,又能看坐标系方向。

避坑指南:我曾经在RViz里看到一个link的坐标系歪了45度,查了半天发现是rpy的单位搞错了。URDF里角度单位是弧度,不是度。3.14弧度才是180度,你要是写成45,那坐标系就歪到姥姥家了。

3.5 实战建议

说了这么多,总结几条我自己的经验:

  • 先画草图再写代码:拿张纸画出机器人的关节位置和坐标系方向,标出每个link的尺寸。我见过太多人直接上手写URDF,写到一半发现关节对不齐。
  • link命名要有规律:比如base_link、shoulder_link、upper_arm_link,别用link1、link2这种,后面调试TF时根本分不清。
  • 惯性参数别乱填:如果只是做运动学仿真,惯性参数可以给个近似值。但要做动力学仿真,最好用CAD软件算出来。我有个项目就是因为惯性参数差了10倍,仿真出来的力矩曲线完全不对。
  • 版本控制:URDF文件建议用Git管理,每次修改都commit。我改模型时经常改着改着就改坏了,回退版本能救命。

URDF是机器人仿真的基石。模型建得好,后面的MoveIt配置、运动学求解、碰撞检测都会顺风顺水。反过来,模型里埋了坑,后面每一步都会踩雷。嗯,花时间把URDF吃透,值。