第2章 连杆与关节:link & joint 详解

进阶必修 本章我们深入 URDF 的核心——link 和 joint。你想想看,机器人模型说白了就是一堆刚体(连杆)加上关节把它们串起来。我刚开始接触 URDF 时,总觉得这俩标签很简单,直到在项目里因为惯性参数写错导致仿真翻车……嗯,细节里全是坑。

URDF 连杆 & 关节 link 连杆 惯性 · 碰撞 · 视觉 joint 关节 固定 · 旋转 · 棱柱 视觉 mesh/几何 碰撞简化 惯性矩阵 坐标系定义 每个 link 有且仅有一个视觉/碰撞/惯性;joint 决定运动副与坐标系

2.1 link 标签:机器人的骨骼

每个 <link> 代表一个刚体。我个人习惯把 link 想象成「一块铁疙瘩」——它有形状、质量、碰撞边界,还有长得什么样(视觉)。URDF 里 link 必须包含三个子模块:visual、collision、inertial。缺一个可能不报错,但仿真时出幺蛾子。

🔹 视觉属性 (visual) – 决定你「看到」的机器人长啥样。可以用 <geometry> 定义基本体(box, cylinder, sphere)或引用 <mesh> 文件。我记得有一次偷懒没给视觉加材质,结果在 Rviz 里一片惨白……加个 <material> 标签立马精神了。
<link name="arm_link">
  <visual>
    <geometry>
      <cylinder length="0.4" radius="0.05"/>
    </geometry>
    <origin xyz="0 0 0.2" rpy="0 0 0"/>
    <material name="blue">
      <color rgba="0.2 0.4 0.9 1.0"/>
    </material>
  </visual>
</link>
💡 我的经验: 视觉 mesh 尽量用 STL 或 Collada,文件别超过 2MB。之前团队有人用 20MB 的精细模型,Gazebo 直接卡成 PPT。另外,<origin> 的偏移量一定要和关节坐标系对齐,否则模型会「飘」起来。

2.2 碰撞属性 (collision) —— 别让机器人「穿模」

碰撞几何体是给物理引擎用的。说白了,它不需要精细,但必须可靠。我建议碰撞体尽量用基本几何体或简化后的凸包。你想想看,一个复杂的机械爪用 mesh 做碰撞,每帧算几百个三角形,CPU 直接冒烟。

<collision>
  <geometry>
    <box size="0.1 0.1 0.4"/>
  </geometry>
  <origin xyz="0 0 0.2" rpy="0 0 0"/>
</collision>
⚠️ 我曾经踩过的坑: 碰撞体的 <origin> 和视觉体不一致,导致 Rviz 里看着没碰,实际仿真里已经「嵌」进去了。一定要保持两者坐标系统一,或者至少碰撞体完全包裹住视觉部分。

2.3 惯性属性 (inertial) —— 物理仿真的灵魂

没有惯性,机器人就像在太空中飘。每个 link 必须指定质量 <mass> 和惯性张量 <inertia>。很多人直接抄网上的数值,结果机器人一跑就翻。我习惯用 SolidWorks 或 Fusion 360 导出惯量,或者用 urdf_sim_tutorial 里的脚本估算。

参数含义典型值(连杆)
mass质量 (kg)0.5 ~ 5.0
ixx, iyy, izz主惯性矩0.001 ~ 0.1
ixy, ixz, iyz惯性积通常设为 0(对称)
<inertial>
  <mass value="1.2"/>
  <inertia ixx="0.01" ixy="0" ixz="0" iyy="0.01" iyz="0" izz="0.005"/>
</inertial>

2.4 joint 标签:让机器人动起来

关节连接两个 link,并定义它们的相对运动。URDF 支持六种类型,但最常用的是 fixed、revolute(旋转)和 prismatic(棱柱/平移)。

  • fixed – 焊死,两个 link 之间无相对运动。适合机架、摄像头支架。
  • revolute – 绕轴旋转,像人的肘关节。必须设置 <limit> 和 <axis>。
  • prismatic – 沿轴平移,比如伸缩臂、滑台。
🔧 关节坐标系定义: 每个 joint 都有一个 <origin>,它表示子 link 坐标系相对于父 link 的位姿。我见过很多新手把 xyz 和 rpy 搞反,结果机器人拧成麻花。记住:rpy="0 0 1.57" 是绕 Z 轴转 90°,不是绕 X 轴。
<joint name="shoulder" type="revolute">
  <parent link="base_link"/>
  <child link="arm_link"/>
  <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>
📌 个人习惯: 固定关节我通常不写 <axis> 和 <limit>,但旋转关节一定要给合理的限位。有一次我忘了设 upper,仿真时电机直接转到了 1000 弧度……嗯,模型直接飞了。

2.5 坐标系与树形结构

URDF 本质是一棵树,根节点是 base_link。每个 joint 的 <origin> 定义了子 link 坐标系相对于父 link 的位置和姿态。你想想看,整个机器人就是靠这些相对变换串联起来的。我调试时最喜欢在 Rviz 里打开「显示坐标系」,一眼就能看出哪个关节偏移错了。

最后说一句:fixed 关节也会产生坐标系变换,即使两个 link 焊在一起,它们之间依然有一个 <origin>。别问我为什么知道——我曾经把一个传感器的坐标系焊反了,折腾了两天才发现是 fixed 关节的 rpy 写成了 1.57 0 0 而不是 0 1.57 0。