第3章 Link详解:视觉、碰撞、惯性
兄弟们,今天咱们来啃一块硬骨头——<link> 标签。你想想看,一个机器人模型里最核心的零件就是这些连杆。没有它们,关节连个屁啊。我刚开始学URDF的时候,以为link就是个几何壳子,后来被物理仿真狠狠教育了一顿……嗯,这一章咱们就把视觉、碰撞、惯性这三个属性彻底聊透。
3.1 视觉属性 —— 让机器人“有模有样”
<visual> 说白了就是给机器人穿衣服。你模型再漂亮,没有视觉标签,在Rviz里就是一团灰。我个人习惯把视觉几何和碰撞几何分开写,这样调试的时候能快速定位问题。
<link name="base_link">
<visual>
<origin xyz="0 0 0" rpy="0 0 0"/>
<geometry>
<box size="0.4 0.3 0.1"/>
</geometry>
<material name="blue">
<color rgba="0 0.4 0.8 1.0"/>
</material>
</visual>
</link>
这里 <origin> 控制视觉网格相对于link坐标系的偏移。我记得有一次把视觉原点设错了,机器人看起来在漂移,查了半天才发现是rpy写成了“0.1 0 0”——差之毫厘,谬以千里。
3.2 碰撞属性 —— 物理引擎的“硬边界”
碰撞模型决定了你的机器人在Gazebo里会不会卡进地板,或者两个连杆能不能互相穿透。你想想看,如果碰撞模型比视觉模型还精细,仿真性能会直线下降。我建议碰撞几何尽量用简单形状:盒子、圆柱、球体。
<collision>
<origin xyz="0 0 0" rpy="0 0 0"/>
<geometry>
<cylinder radius="0.05" length="0.3"/>
</geometry>
</collision>
注意:碰撞属性里的 <origin> 和视觉里的可以不同。比如你视觉模型是个复杂的L形支架,但碰撞模型可以用两个盒子拼起来。这样做既保证视觉真实,又让物理计算轻快。
3.3 惯性属性 —— 动力学计算的灵魂
惯性参数是URDF里最容易被忽略、但影响最大的部分。没有惯性数据,机器人就像在太空中飘——关节一动就飞了。惯性矩阵 <inertia> 包含 ixx, ixy, ixz, iyy, iyz, izz 六个分量。
<mass> 必须大于0,惯性矩阵必须正定。我曾经见过有人把ixx写成0,结果仿真直接崩溃。如果你不确定惯性值,可以用urdf_to_graphviz配合check_urdf做初步验证。
<inertial>
<origin xyz="0 0 0" rpy="0 0 0"/>
<mass value="1.5"/>
<inertia ixx="0.01" ixy="0" ixz="0"
iyy="0.01" iyz="0"
izz="0.01"/>
</inertial>
对于简单几何体,你可以用公式估算惯性。比如一个实心圆柱绕中心轴的惯量是 ½ m r²。我个人习惯先用SolidWorks或Fusion360导出惯性值,再手动微调。但如果你只是做移动底盘,用近似值也问题不大。
3.4 三个属性的协作关系
一个完整的link通常同时包含visual、collision、inertial。它们各自独立,但共同决定了机器人的“长相、碰撞、手感”。我见过很多新手只写visual,结果一进Gazebo就穿模。记住:仿真看collision,显示看visual,动力学看inertial。
| 属性 | 主要用途 | 性能影响 | 推荐做法 |
|---|---|---|---|
| visual | Rviz显示、视觉反馈 | 低(仅渲染) | 可用复杂mesh |
| collision | 物理碰撞、接触检测 | 高(每帧计算) | 用简单几何体 |
| inertial | 动力学、力矩计算 | 中(影响控制) | 尽量精确 |
我的经验: 在项目初期,我会把collision和visual设成一样,快速验证运动学。等进入动力学调试阶段,再单独优化collision和inertial。这样迭代效率最高。
3.5 一个完整的link示例
下面是一个机器人手臂连杆的完整定义。注意origin在不同属性里可以不同——比如视觉里把模型稍微旋转一点,但碰撞保持标准姿态。
<link name="arm_link">
<visual>
<origin xyz="0 0 0.15" rpy="0 0 0"/>
<geometry>
<mesh filename="package://robot_description/meshes/arm.stl"/>
</geometry>
<material name="gray"/>
</visual>
<collision>
<origin xyz="0 0 0.15" rpy="0 0 0"/>
<geometry>
<box size="0.08 0.08 0.3"/>
</geometry>
</collision>
<inertial>
<origin xyz="0 0 0.15" rpy="0 0 0"/>
<mass value="0.8"/>
<inertia ixx="0.003" ixy="0" ixz="0"
iyy="0.003" iyz="0"
izz="0.001"/>
</inertial>
</link>
看到没?三个属性的origin完全一致,这样质心、视觉中心、碰撞中心都在同一个点。但如果你有特殊需求,比如视觉模型需要偏移,完全可以单独调。只是别搞混了坐标系。
check_urdf 命令可以快速检查link是否缺少必要属性。我每次写完URDF都会跑一遍,避免低级错误。