4、连杆标签<link>(上):<link>标签的结构、name属性的重要性、惯性属性<inertial>的组成
好,我们正式开始拆解URDF里最核心的零件——<link>标签。
你可以把link想象成机器人的每一块骨头。没有骨头,肌肉(joint)往哪儿连?所以,link是URDF的基石。今天我们先讲上半部分:标签结构、name属性的坑,以及惯性属性怎么配。
4.1 <link>标签的基本结构
一个完整的link标签,长这样:
<link name="base_link">
<inertial>
<origin xyz="0 0 0" rpy="0 0 0"/>
<mass value="10.0"/>
<inertia ixx="0.1" ixy="0" ixz="0"
iyy="0.1" iyz="0"
izz="0.1"/>
</inertial>
<visual>
<!-- 视觉模型 -->
</visual>
<collision>
<!-- 碰撞模型 -->
</collision>
</link>
嗯,这里要注意:inertial、visual、collision这三个子标签,顺序可以调换,但name属性必须写。我见过有人把name写成注释,结果Gazebo死活不认——那叫一个憋屈。
核心原则:每个link必须有且只有一个name,且在整个URDF文件中唯一。
4.2 name属性的重要性——别小看这个名字
name属性说白了就是link的身份证。你想想看,机器人可能有几十个link,如果没有唯一的名字,joint怎么知道它连的是哪块骨头?
我个人习惯用层级命名法:
base_link—— 底盘arm_1_link—— 手臂第一节arm_2_link—— 手臂第二节gripper_left_finger—— 左夹爪
我曾经在一个项目里,把两个link都叫link_1,结果ROS启动时直接报错:Duplicate link name。排查了半小时才发现是复制粘贴忘了改名字。所以,命名规范一定要从一开始就定好。
避坑指南:name中不要使用空格、中文、特殊符号(如@、#、$)。ROS底层用的是XML解析器,这些字符会导致解析失败。我曾经见过一个团队用中文命名,结果在rviz里显示乱码,最后全部重写。
4.3 惯性属性<inertial>的组成
惯性属性是link里最容易出错的地方。很多初学者直接抄网上的例子,结果机器人仿真时要么飞上天,要么原地打转。为什么会这样?因为惯性参数不对。
<inertial>包含三个子元素:
| 子标签 | 作用 | 必填 | 常见错误 |
|---|---|---|---|
| <origin> | 惯性坐标系相对于link坐标系的偏移 | 是 | 忘记设置,默认在原点,导致质心偏移 |
| <mass> | 质量,单位kg | 是 | 写0或负数,Gazebo直接崩溃 |
| <inertia> | 惯性张量矩阵的6个独立分量 | 是 | ixx/iyy/izz太小或太大,仿真抖动 |
4.3.1 <origin>——质心位置
这个标签定义的是惯性坐标系的原点,也就是质心(Center of Mass, CoM)的位置。默认情况下,惯性坐标系和link坐标系重合。如果你的零件形状不对称,就必须手动调整。
<!-- 假设一个长杆,质心在杆的中心偏右一点 -->
<origin xyz="0.05 0 0" rpy="0 0 0"/>
我建议:尽量把link坐标系的原点设在质心位置,这样origin就可以写成xyz="0 0 0",省心不少。但如果你是从CAD导出的模型,质心位置通常已经算好了,直接填就行。
4.3.2 <mass>——质量
这个最简单,就是一个数字。但要注意:单位是千克,不是克,也不是磅。
<mass value="2.5"/> <!-- 2.5kg -->
我曾经接手过一个项目,对方把所有质量都写成了克,结果仿真时机器人轻得像纸片,一碰就飞。所以,一定要确认单位。
4.3.3 <inertia>——惯性张量
这是最复杂、也最容易出错的部分。惯性张量是一个3x3的对称矩阵,URDF里只需要填写6个独立分量:
<inertia ixx="0.1" ixy="0" ixz="0"
iyy="0.1" iyz="0"
izz="0.1"/>
这6个分量的物理意义:
- ixx、iyy、izz:绕X、Y、Z轴的转动惯量(主对角线)
- ixy、ixz、iyz:惯性积(非对角线),表示质量分布的不对称性
对于简单几何体,可以用公式估算:
| 形状 | ixx | iyy | izz |
|---|---|---|---|
| 实心球(半径r,质量m) | 0.4 * m * r² | 0.4 * m * r² | 0.4 * m * r² |
| 实心圆柱(半径r,高h,质量m) | 0.5 * m * r² | m * (3r² + h²) / 12 | m * (3r² + h²) / 12 |
| 长方体(长a,宽b,高c,质量m) | m * (b² + c²) / 12 | m * (a² + c²) / 12 | m * (a² + b²) / 12 |
小技巧:如果你不确定惯性参数,可以用SolidWorks、Fusion 360等CAD软件导出。它们会自动计算准确的惯性张量。我个人的习惯是:复杂零件用CAD算,简单零件用手算。
4.4 知识结构图:<link>标签的惯性属性
下面这张图帮你理清inertial标签的内部结构:
4.5 实战案例:为一个简单的连杆配置惯性
假设我们有一个长0.5m、半径0.05m、质量2kg的实心圆柱,作为机器人的小臂。我们来手算惯性参数。
根据上面的表格,实心圆柱的公式:
- ixx = 0.5 * m * r² = 0.5 * 2 * 0.05² = 0.0025
- iyy = m * (3r² + h²) / 12 = 2 * (3*0.05² + 0.5²) / 12 = 2 * (0.0075 + 0.25) / 12 = 2 * 0.2575 / 12 ≈ 0.0429
- izz = iyy ≈ 0.0429(因为圆柱绕Y和Z轴对称)
- ixy = ixz = iyz = 0(对称形状,惯性积为0)
最终代码:
<link name="forearm_link">
<inertial>
<origin xyz="0 0 0" rpy="0 0 0"/>
<mass value="2.0"/>
<inertia ixx="0.0025" ixy="0" ixz="0"
iyy="0.0429" iyz="0"
izz="0.0429"/>
</inertial>
<visual>
<geometry>
<cylinder length="0.5" radius="0.05"/>
</geometry>
</visual>
<collision>
<geometry>
<cylinder length="0.5" radius="0.05"/>
</geometry>
</collision>
</link>
重要提醒:ixx、iyy、izz的值不能为0,也不能太小。我曾经见过有人把ixx写成0.000001,结果仿真时这个link像果冻一样疯狂抖动。一般来说,ixx/iyy/izz至少大于1e-6,否则数值不稳定。
4.6 本章小结
今天我们拆解了<link>标签的上半部分:
- name属性是link的唯一标识,必须唯一、规范、无特殊字符
- <inertial>包含origin、mass、inertia三个子标签,缺一不可
- 惯性张量的6个分量要合理计算,不能随意填写