运动学基础(一):刚体运动描述、旋转矩阵、欧拉角与四元数
各位同学,欢迎来到第二章。
人形机器人要动起来,第一步是什么?不是写代码,不是调PID。是描述它怎么动。你得先能用数学语言,把机器人的每一个关节、每一块肢体在空间中的位置和姿态说清楚。这就是运动学基础。
我刚开始做机器人那会儿,觉得这玩意儿就是纯理论,没啥用。直到有一次,我给一个六轴机械臂做正运动学解算,算出来的末端位置跟实际差了十几厘米。查了三天,最后发现是旋转矩阵乘反了。嗯,从那以后,我再也不敢小看这些基础了。
核心概念:刚体在三维空间中的运动 = 位置(平移)+ 姿态(旋转)。本章我们重点攻克姿态描述。
1. 刚体运动:位置 + 姿态
人形机器人的躯干、大腿、小腿、手臂,都可以看作刚体。刚体就是受力不变形的理想物体。
描述一个刚体在空间中的状态,需要6个自由度:
- 3个平移自由度:决定刚体在空间中的位置(x, y, z)。
- 3个旋转自由度:决定刚体的朝向(绕x轴、y轴、z轴的转动)。
说白了,你告诉机器人“你的手在坐标(1,2,3)处,并且手掌朝前”,这就是一个完整的位姿描述。
2. 旋转矩阵:最直观,但最啰嗦
旋转矩阵是描述姿态最基础的工具。它是一个3x3的矩阵,列向量分别代表刚体坐标系在参考坐标系下的三个轴方向。
// 绕Z轴旋转θ角的旋转矩阵
R_z(θ) = [
[cosθ, -sinθ, 0],
[sinθ, cosθ, 0],
[0, 0, 1]
]
旋转矩阵有三个重要性质:
- 正交性:RT = R-1,矩阵的逆等于它的转置。
- 行列式为+1:保证是纯旋转,不包含缩放或镜像。
- 可组合:连续旋转可以用矩阵乘法表示。R = R1 · R2 · R3
我的经验:调试时,检查旋转矩阵是否正交是最快的排错方法。如果R·RT ≠ I,那你的矩阵一定有问题。我曾经在代码里把矩阵转置写成了元素转置,结果整个机械臂的轨迹都飞了。
旋转矩阵的缺点也很明显:9个元素描述3个自由度,冗余信息太多。而且人眼很难从一堆数字里看出姿态是什么。这就引出了更紧凑的表达方式。
3. 欧拉角:直观但容易翻车
欧拉角用三个角度来描述旋转。最常见的是ZYX欧拉角(也叫RPY角):
- Roll(横滚):绕X轴旋转
- Pitch(俯仰):绕Y轴旋转
- Yaw(偏航):绕Z轴旋转
你想想看,飞机飞行员用的就是这套。说“机头偏左30度”,比说一个3x3矩阵方便多了。
避坑指南:欧拉角有一个致命问题——万向锁(Gimbal Lock)。当Pitch角达到±90°时,Roll和Yaw的旋转轴会重合,丢失一个自由度。我曾经在做人形机器人腰部姿态控制时,因为用了欧拉角,导致机器人弯腰到90度后,转身动作完全失控。那场面,嗯,挺尴尬的。
另外,欧拉角的旋转顺序也很重要。ZYX和XYZ得到的结果完全不同。所以用欧拉角时,一定要在注释里写清楚旋转顺序。
4. 四元数:工业界的标准答案
四元数是什么?说白了,它是一个没有奇点、计算稳定、插值平滑的姿态描述方式。
四元数由四个数组成:q = (w, x, y, z)。其中w是实部,(x,y,z)是虚部。它满足:w² + x² + y² + z² = 1(单位四元数)。
为什么工业界都用四元数?三个理由:
- 无万向锁:任何姿态都能平滑表示。
- 插值方便:用球面线性插值(SLERP)可以在两个姿态之间生成平滑轨迹。
- 计算高效:组合旋转只需要一次乘法,比矩阵快。
// 四元数乘法(组合旋转)
q_result = q1 * q2
// 公式(简化版):
// w = w1*w2 - x1*x2 - y1*y2 - z1*z2
// x = w1*x2 + x1*w2 + y1*z2 - z1*y2
// y = w1*y2 - x1*z2 + y1*w2 + z1*x2
// z = w1*z2 + x1*y2 - y1*x2 + z1*w2
我的习惯:在代码里,我永远用四元数做内部计算。只在需要人看的时候,才转成欧拉角显示。这样既避免了万向锁,又保留了可读性。
5. 三种方法的对比
| 特性 | 旋转矩阵 | 欧拉角 | 四元数 |
|---|---|---|---|
| 参数数量 | 9个 | 3个 | 4个 |
| 奇点问题 | 无 | 有(万向锁) | 无 |
| 直观性 | 差 | 好 | 中等 |
| 插值平滑性 | 差 | 差 | 好(SLERP) |
| 计算效率 | 低 | 高 | 高 |
| 工业应用 | 底层计算 | 人机交互 | 核心算法 |
6. 知识体系总览
下面这张图,把本章的核心逻辑串起来了。你可以把它当作一个思维导图来看。
7. 实战建议
学完理论,怎么落地?我建议你按这个顺序来:
- 先写一个旋转矩阵类:实现绕X/Y/Z轴的旋转,验证正交性。
- 再实现欧拉角 ↔ 旋转矩阵的转换:注意ZYX和XYZ顺序的区别。
- 最后实现四元数类:包括乘法、归一化、到旋转矩阵的转换。
- 写一个SLERP插值函数:在两个四元数之间生成10个中间姿态,验证平滑性。
重要提醒:四元数一定要归一化!非单位四元数会导致姿态扭曲。我见过有人把四元数当普通向量用,结果机器人转了一圈后,姿态回不到原点。排查了两天,最后发现是四元数模长变成了0.98。