第4章 关节与运动学:joint标签详解、固定关节与旋转关节、坐标变换基础
这一章我们聊聊关节。说白了,关节就是让机器人动起来的关键。没有关节,你的URDF模型就是一坨静态的雕塑,动不了。我刚开始学URDF的时候,以为关节就是随便写个标签完事,结果模型在Rviz里要么散架,要么乱转。后来踩了不少坑,才慢慢摸清楚里面的门道。
今天咱们就把 <joint> 标签彻底讲透。固定关节、旋转关节、坐标变换,一个一个来。你跟着我走一遍,保证以后写关节不再发怵。
4.1 joint标签的核心结构
每个关节都连接两个连杆:一个父连杆(parent),一个子连杆(child)。关节定义了它们之间的相对运动关系。我习惯把关节想象成「铰链」——它告诉机器人,子连杆相对于父连杆能怎么动。
一个标准的关节长这样:
<joint name="joint_1" type="fixed">
<parent link="base_link"/>
<child link="link_1"/>
<origin xyz="0 0 0.2" rpy="0 0 0"/>
<axis xyz="0 0 1"/>
</joint>
这里 name 是关节的名字,必须唯一。type 决定了关节的运动类型。剩下的 parent、child、origin、axis 是每个关节的标配。嗯,这里要注意:origin 描述的是子连杆相对于父连杆的初始位置,而 axis 定义旋转轴的方向。
joint_父_子 的格式,比如 joint_base_arm。这样一眼就能看出谁连谁,调试的时候特别省心。
4.2 固定关节(fixed)—— 最老实的关节
固定关节,顾名思义,两个连杆之间没有任何相对运动。焊死了。你想想看,机器人的底盘和机身之间,或者摄像头支架和头部之间,通常就用固定关节。
我在项目中遇到过一个问题:有个学生把固定关节的 origin 写错了,结果子连杆直接穿模到地底下。其实固定关节虽然不动,但它的 origin 依然决定了子连杆的初始位姿。千万别以为固定关节就可以随便写坐标。
- 底盘与主体框架
- 传感器支架(如激光雷达安装板)
- 装饰件或不可动外壳
- 任何「焊死」的连接
4.3 旋转关节(revolute / continuous)—— 让机器人动起来
旋转关节是机器人里最常见的关节。轮子、关节臂、舵机,基本都是旋转关节。URDF 里旋转关节有两种:revolute 和 continuous。
revolute 有角度限制,比如你的机械臂肘关节只能转 0° 到 180°。而 continuous 没有限制,可以一直转圈,比如轮子。
看个例子:
<joint name="joint_wheel_left" type="continuous">
<parent link="base_link"/>
<child link="left_wheel"/>
<origin xyz="-0.3 0.5 0" rpy="0 0 0"/>
<axis xyz="0 1 0"/>
</joint>
这里 axis xyz="0 1 0" 表示绕 Y 轴旋转。轮子嘛,绕 Y 轴转就是向前滚动。我曾经犯过一个低级错误:把轮子的轴设成了 Z 轴,结果轮子在地上「画圈」而不是滚动。你想想看,那画面多滑稽。
| 关节类型 | 运动方式 | 角度限制 | 典型用途 |
|---|---|---|---|
| fixed | 无运动 | — | 固定连接 |
| revolute | 旋转 | 有(limit标签) | 关节臂、舵机 |
| continuous | 旋转 | 无 | 轮子、转台 |
| prismatic | 平移 | 有 | 伸缩杆、滑轨 |
| planar | 平面运动 | 有 | 全向轮平台(少见) |
| floating | 6自由度 | 无 | 无人机、仿真调试 |
revolute 关节设置 limit 时,忘了写 effort 和 velocity。结果 Gazebo 里关节完全动不了,卡得死死的。记住,limit 里 lower、upper、effort、velocity 四个参数缺一不可。
4.4 坐标变换基础 —— origin 与 axis 的几何意义
坐标变换是关节的灵魂。每个关节的 origin 定义了一个局部坐标系,子连杆就活在这个坐标系里。说白了,origin 的 xyz 是平移,rpy 是旋转(Roll, Pitch, Yaw)。
举个例子:如果 origin xyz="0.5 0 0" rpy="0 0 1.57",表示子连杆相对于父连杆先沿 X 轴移动 0.5 米,再绕 Z 轴旋转 90°。这个顺序是固定的:先平移,后旋转。我刚开始总搞反,结果模型歪七扭八。
axis 则定义了旋转轴的方向。对于旋转关节,axis xyz="0 0 1" 就是绕 Z 轴转。对于平移关节(prismatic),axis 表示移动方向。记住,axis 是一个单位向量,URDF 会自动归一化,但你最好自己写规范。
origin xyz→ 子连杆相对于父连杆的平移量(米)origin rpy→ 子连杆相对于父连杆的旋转量(弧度)axis xyz→ 关节运动轴的方向向量- 所有变换都是相对于父连杆坐标系
我个人习惯在写 origin 之前,先在纸上画个简图。标出父连杆坐标系,然后想清楚子连杆应该在哪。别偷懒,画图真的能避免 80% 的坐标错误。
4.5 实战小练习:搭建一个单关节摆臂
光说不练假把式。咱们写一个最简单的旋转关节模型:一个底座加一个摆臂,摆臂可以绕 Z 轴旋转。
<robot name="simple_arm">
<link name="base">
<visual>
<geometry><box size="0.2 0.2 0.1"/></geometry>
</visual>
</link>
<link name="arm">
<visual>
<geometry><box size="0.05 0.05 0.4"/></geometry>
<origin xyz="0 0 0.2"/>
</visual>
</link>
<joint name="joint_base_arm" type="revolute">
<parent link="base"/>
<child link="arm"/>
<origin xyz="0 0 0.1"/>
<axis xyz="0 0 1"/>
<limit lower="-1.57" upper="1.57" effort="10" velocity="1.0"/>
</joint>
</robot>
把这个保存成 simple_arm.urdf,然后用 check_urdf 命令检查一下。我保证,当你看到摆臂在 Rviz 里乖乖旋转的时候,你会觉得一切都值了。
Joint State Publisher 插件手动拖动关节角度。如果关节不动,八成是 limit 写错了或者 axis 方向反了。我曾经花了一下午才发现 axis 少写了一个负号。
好了,关节和运动学的基础就这些。固定关节让你焊死,旋转关节让你动起来,坐标变换让你摆对位置。下一章咱们会把这些关节组合起来,构建一个真正的多连杆机器人。嗯,到时候你会看到关节之间如何协同工作。