4. 机器人建模基础:URDF文件格式、关节与连杆定义、惯性参数设置

做机器人仿真,第一步就是得把机器人“说”给仿真器听。用什么说?URDF,全称是 Unified Robot Description Format。说白了,就是一个 XML 文件,里面描述了机器人长什么样、胳膊腿怎么连、每个部件有多重。

我记得刚入行那会儿,觉得 URDF 不就是个配置文件嘛,随便写写就行。结果第一次把模型丢进 Gazebo,机器人直接瘫在地上,跟面条似的。后来才发现,惯性参数没设对。嗯,从那以后我再也不敢小看这个文件了。

4.1 URDF 文件的核心结构

URDF 的核心就两个东西:连杆(link)和关节(joint)。连杆是刚体,关节是连接方式。一个机器人就是由连杆和关节交替组成的运动链。

来看一个最简单的 URDF 骨架:

<robot name="simple_arm">
  <link name="base_link">
    <visual>
      <geometry>
        <box size="0.2 0.2 0.1"/>
      </geometry>
    </visual>
  </link>

  <joint name="joint1" 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"/>
  </joint>

  <link name="arm_link">
    <visual>
      <geometry>
        <cylinder length="0.3" radius="0.02"/>
      </geometry>
    </visual>
  </link>
</robot>

这个例子定义了一个底座加一个旋转关节带一根手臂。你想想看,每个关节必须指定父连杆和子连杆,这样仿真器才知道运动链怎么走。

关键点:URDF 要求机器人结构必须是一棵树,不能有闭环。如果你要做并联机构或者四足机器人,URDF 本身搞不定,得用 xacro 或者直接上 SDF 格式。

4.2 连杆定义:视觉、碰撞与惯性

每个 link 可以包含三个子块:visual、collision 和 inertial。很多人只写 visual,觉得能看见就行。但仿真器真正用的是 collision 和 inertial。

4.2.1 visual —— 看着像就行

visual 只负责显示。你可以用 box、cylinder、sphere 或者 mesh 导入 STL 文件。我个人习惯在调试阶段用简单几何体,最后再替换成精细的 mesh 文件,不然每次加载都卡半天。

4.2.2 collision —— 仿真器真正撞的是这个

collision 的几何体决定了碰撞检测的边界。你可以让它和 visual 一样,也可以简化。比如一个复杂的机械爪,visual 用精细 mesh,collision 用一个长方体包起来就行。这样碰撞计算快很多。

我的经验:collision 几何体尽量用凸包或者基本几何体。凹面体或者太复杂的 mesh 会导致碰撞检测不稳定,机器人会莫名其妙地弹飞。我曾经被这个问题坑了整整两天。

4.2.3 inertial —— 最容易被忽略,也最致命

inertial 块定义质量、质心和惯性张量。格式如下:

<inertial>
  <mass value="1.5"/>
  <origin xyz="0 0 0.02" rpy="0 0 0"/>
  <inertia ixx="0.01" ixy="0.0" ixz="0.0"
            iyy="0.01" iyz="0.0"
            izz="0.005"/>
</inertial>

这里 origin 是质心相对于连杆坐标系的位置。inertia 是 3x3 惯性张量的六个独立分量。为什么是六个?因为矩阵是对称的,ixy = iyx,以此类推。

警告:千万不要把惯性张量全设成 0!ROS 和 Gazebo 会直接报错,或者给你一个诡异的默认值。我见过有人把 ixx/iyy/izz 设成 0.001 这种极小值,结果机器人一跑就疯狂抖动。惯性参数必须和几何体尺寸、质量匹配。

4.3 关节定义:类型与运动轴

URDF 支持六种关节类型。我整理了一个表格,方便你对照:

类型 自由度 典型用途 注意事项
revolute 1 旋转 肩关节、肘关节 必须设置 limit
continuous 1 旋转 车轮、无限旋转关节 不需要 limit
prismatic 1 平移 线性滑轨、伸缩臂 必须设置 limit
fixed 0 固定连接、传感器支架 不需要 limit
floating 6 自由漂浮基座(无人机) ROS 2 中支持更好
planar 3 平面移动(AGV 简化) 较少使用

关节的 origin 定义了子连杆相对于父连杆的初始位置和姿态。axis 定义了运动轴的方向。对于 revolute 关节,轴的方向就是旋转轴;对于 prismatic 关节,轴的方向就是平移方向。

举个例子,人形机器人的髋关节通常是 revolute 类型,轴指向 Z 方向(左右旋转)或者 Y 方向(前后摆动)。写的时候一定要想清楚坐标系方向,不然机器人走路姿势会很奇怪。

4.4 惯性参数设置:理论与实操

惯性参数是 URDF 里最让人头疼的部分。理论上,对于一个均匀密度的长方体,惯性张量有公式可以算。但实际中,你的连杆可能是异形件,或者是从 CAD 导出的 mesh。

我推荐两种做法:

  1. 用 CAD 软件算:SolidWorks、Fusion 360 都能自动计算惯性张量。导出 URDF 时直接带上。
  2. 用近似几何体估算:把复杂零件近似成几个基本几何体的组合,分别算惯性再叠加。

下面是一个均匀密度圆柱体的惯性张量计算公式(圆柱轴线沿 Z 轴):

ixx = iyy = (1/12) * m * (3 * r^2 + h^2)
izz = (1/2) * m * r^2
ixy = ixz = iyz = 0

其中 m 是质量,r 是半径,h 是高度。如果你懒得算,网上有现成的惯性计算器,搜 "moment of inertia calculator" 就能找到。

避坑指南:我曾经给一个六轴机械臂写 URDF,五个关节的惯性参数都是估算的,跑仿真看起来没问题。结果一做力矩控制,第三个关节的力矩曲线全是毛刺。查了两天才发现是惯性张量里 ixy 设成了 0.01,但实际应该是 0。这种非对角项会让动力学方程多出耦合项,控制器根本扛不住。

4.5 本章知识体系

下面这张图帮你理清 URDF 建模的核心脉络:

URDF 建模知识体系 URDF 建模核心知识体系 URDF 文件 link(连杆) joint(关节) visual(视觉) collision(碰撞) inertial(惯性) type(类型) origin(位姿) axis(运动轴) 质量 / 质心 / 惯性张量 核心原则 连杆与关节交替构成运动链,结构必须是一棵树 惯性参数必须与几何尺寸和质量匹配,不可省略或随意填写

4.6 实操建议:从零搭建一个 URDF

如果你刚开始写 URDF,我建议按这个顺序来:

  1. 先画草图:在纸上画出机器人的连杆和关节拓扑,标出每个关节的类型和运动轴方向。
  2. 写固定关节的骨架:先用 fixed 关节把所有连杆串起来,验证 visual 和 collision 的几何体是否正确。
  3. 替换活动关节:把 fixed 改成 revolute 或 prismatic,加上 limit 和 axis。
  4. 补惯性参数:最后再填 inertial 块。用 CAD 算或者用公式估,别空着。
  5. 用 check_urdf 验证:ROS 自带的 check_urdf 工具能帮你检查语法错误和结构问题。

小技巧:在终端运行 urdf_to_graphiz 可以把 URDF 转成一张拓扑图,一眼就能看出关节父子关系对不对。我每次写完都会跑一下这个命令,比盯着 XML 看快多了。

URDF 是机器人仿真的地基。地基没打好,后面做运动学、动力学、控制都会出问题。花点时间把模型写扎实,后面能省你十倍的时间。