3. joint 标签详解

关节 —— 机器人模型的灵魂。没有关节,link 就是一堆孤立的铁块。今天咱们把 joint 标签拆开揉碎,从类型到坐标系,从原点到旋转轴,一次讲透。

joint 标签核心要素 关节类型 父子坐标系 origin & axis continuous · revolute prismatic · fixed · floating planar parent → child 坐标变换树 TF 广播 xyz / rpy 偏移 旋转轴向量 (x y z) 归一化

3.1 关节类型 —— 选对类型,少走弯路

URDF 里一共定义了六种关节类型。我最早做机械臂时,把 revolute 和 continuous 搞混过,结果仿真时关节一直转圈停不下来…… 你想想看,这俩到底差在哪?

类型运动方式典型用途
continuous无限旋转(无角度限制)车轮、转台
revolute旋转,有角度限位关节臂、舵机
prismatic直线滑动,有限位伸缩杆、升降台
fixed完全固定,无自由度传感器支架、装饰件
floating6自由度浮动无人机、自由体(很少用)
planar平面运动(2平移+1旋转)全向轮平台(不常见)
我个人习惯:只要关节需要限位,就用 revolute 或 prismatic。车轮用 continuous,省得设限位麻烦。

3.2 父子坐标系 —— 谁是谁的爹?

每个 joint 连接两个 link:parent 和 child。说白了,子 link 的坐标原点是根据父 link 算出来的。ROS 的 TF 树就是靠这个搭起来的。

我见过有人把 parent 和 child 写反,结果机器人模型拧成一团。记住:parent 是靠近基座的,child 是末端。

示例: 一个轮式底盘,base_link 是 parent,left_wheel_link 是 child。关节类型 continuous。

3.3 origin —— 位置和姿态,差一点都不行

<origin xyz="x y z" rpy="roll pitch yaw" /> 定义子关节相对于父关节的偏移。rpy 的单位是弧度。

我调试 AGV 时,因为 origin 的 z 偏移少了 2 毫米,轮子悬空,导航死活不走路。后来才发现…… 嗯,细节是魔鬼。

<joint name="left_wheel_joint" type="continuous">
    <parent link="base_link"/>
    <child link="left_wheel_link"/>
    <origin xyz="0.2 0.4 -0.05" rpy="0 0 0"/>
    <axis xyz="0 1 0"/>
</joint>

3.4 axis —— 旋转轴或滑动方向

<axis xyz="x y z" /> 定义关节的运动轴。对于旋转关节,就是旋转轴;对于 prismatic,就是滑动方向。向量会被归一化,所以 (1,0,0) 和 (2,0,0) 效果一样。

我曾经犯过一个错:给 revolute 关节的 axis 写了 (0,0,0),结果 ROS 直接报错,模型加载不出来。轴向量不能为零向量!

常见的轴:

  • 1 0 0 — 绕 X 轴旋转(横滚)
  • 0 1 0 — 绕 Y 轴旋转(俯仰)
  • 0 0 1 — 绕 Z 轴旋转(偏航)

对于滑动关节,比如升降台,用 0 0 1 表示上下运动。

3.5 避坑指南 & 个人经验

  • 限位别忘写:revolute 和 prismatic 必须加 <limit lower="..." upper="..." effort="..." velocity="..."/>,否则 Gazebo 会罢工。
  • fixed 关节也要写 origin:就算不动,偏移量也得对,不然视觉上 link 会错位。
  • joint 命名别用中文或特殊符号:ROS 底层不支持,老老实实用小写+下划线。
我习惯在 joint 名称里带上父/子 hint,比如 base_to_left_wheel,这样看 TF 树时一目了然。

3.6 完整 joint 示例(revolute 带限位)

<joint name="arm_shoulder" type="revolute">
    <parent link="base_link"/>
    <child link="upper_arm_link"/>
    <origin xyz="0.0 0.0 0.15" rpy="0 0 0"/>
    <axis xyz="0 0 1"/>
    <limit lower="-3.14" upper="3.14" effort="30" velocity="1.5"/>
</joint>

这个关节让机械臂在水平面旋转 ±180°,电机扭矩 30 N·m,最大转速 1.5 rad/s。实际项目中,限位要根据物理样机调,别照搬。

核心总结:joint 就是机器人的“关节软骨”。类型决定运动模式,父子坐标系搭建 TF 树,origin 和 axis 决定具体位置和运动方向。把这四点吃透,URDF 建模就稳了一半。