3. 刚体变换与位姿表示:旋转矩阵、欧拉角、四元数、齐次变换矩阵

做手眼标定,说白了就是在解一个数学题——怎么用数字精确描述一个刚体在空间里又转又挪。我刚开始接触这行时,总觉得旋转矩阵、四元数这些概念太抽象,直到有一次在产线上调试六轴机器人,发现标定结果总是差那么几毫米,最后查出来是欧拉角万向锁搞的鬼。嗯,从那以后我再也不敢轻视这些数学工具了。

这一章,我们就来把刚体位姿的几种数学表示法彻底捋清楚。

3.1 刚体位置与姿态:两个基本问题

一个刚体在三维空间里,有6个自由度——3个平移 + 3个旋转。位置好办,一个三维向量 [x, y, z]T 就搞定了。但姿态呢?麻烦就麻烦在这里。

我个人习惯把姿态理解成:刚体自身的坐标系,相对于世界坐标系是怎么转的。你想想看,一个相机装在机器人末端,它朝哪个方向看,完全取决于这个旋转关系。

核心概念: 刚体位姿 = 位置向量 + 姿态表示。位置是平移,姿态是旋转,两者合在一起就是完整的6自由度描述。

3.2 旋转矩阵:最直观,但最啰嗦

旋转矩阵是一个 3×3 的正交矩阵,行列式为 +1。它的每一列,就是刚体坐标系各轴在世界坐标系中的方向余弦。

R = [ r11  r12  r13 ]
    [ r21  r22  r23 ]
    [ r31  r32  r33 ]

性质:
- R^T * R = I  (正交性)
- det(R) = +1  (右手系)
- 9个元素,但只有3个自由度

优点: 没有奇异点,可以连续旋转。做矩阵乘法就能合成旋转,非常方便。

缺点: 9个参数太冗余,而且不直观。你看着一个旋转矩阵,能一眼看出它转了30度还是45度吗?反正我不能。

我的经验: 在代码里做旋转矩阵乘法时,一定要小心浮点数误差累积。我曾经遇到过连续旋转几十次后,矩阵不再正交,导致标定结果发散。解决办法是定期做 Gram-Schmidt 正交化。

3.3 欧拉角:直观但危险

欧拉角用三个角度来描述旋转:绕 X 轴转 α(滚转)、绕 Y 轴转 β(俯仰)、绕 Z 轴转 γ(偏航)。听起来很直观对吧?但这里有个大坑——万向锁。

当中间轴(比如 Y 轴)旋转到 ±90° 时,第一个轴和第三个轴会变得共线,丢失一个自由度。这时候你无论怎么调那两个角度,都转不出某些方向了。

表示法 参数数量 优点 缺点
旋转矩阵 9 无奇异,可组合 冗余,不直观
欧拉角 3 直观,参数少 万向锁,插值困难
四元数 4 无奇异,可插值 不够直观
轴角 4 物理意义明确 有奇异点
避坑指南: 我曾经在写手眼标定程序时,直接用欧拉角做优化变量。结果标定结果时好时坏,查了两天才发现是万向锁导致雅可比矩阵奇异。后来我改用四元数做优化变量,问题立刻解决。所以——做优化时千万别用欧拉角。

3.4 四元数:标定中的王牌

四元数是一个超复数:q = w + xi + yj + zk,其中 w² + x² + y² + z² = 1(单位四元数)。它用4个参数表示旋转,没有奇异点,而且可以做球面线性插值(SLERP)。

为什么手眼标定里四元数这么香?因为:

  • 无万向锁——随便你怎么转,不会丢自由度
  • 计算稳定——乘法、求逆都很简单
  • 适合优化——作为优化变量时,约束条件就是模长为1,比旋转矩阵的9个正交约束简单多了
// 四元数乘法(旋转合成)
q_result = q1 * q2

// 用四元数旋转向量 v
v_rotated = q * v * q_conj

// 四元数到旋转矩阵(常用转换)
// 这个转换在手眼标定代码里几乎天天用
我的习惯: 在代码里,我通常用四元数做内部计算和优化,只在最后输出结果时才转成欧拉角给人看。这样既保证了计算稳定性,又方便调试时理解。

3.5 齐次变换矩阵:把旋转和平移打包

齐次变换矩阵是一个 4×4 的矩阵,把旋转矩阵和平移向量整合在一起:

T = [ R    t ]
    [ 0^T  1 ]

其中:
- R: 3×3 旋转矩阵
- t: 3×1 平移向量
- 0^T: 1×3 零向量

这个矩阵的好处是——可以用一个矩阵乘法完成旋转+平移。在手眼标定中,我们经常要串联多个变换:

T_cam_to_base = T_robot_to_base * T_ee_to_robot * T_cam_to_ee

你看,一个矩阵乘法就把整个链路的位姿关系算清楚了。这就是齐次变换矩阵的魅力。

3.6 知识结构总览

下面这张图,把刚体位姿的几种表示法以及它们之间的关系画清楚了:

刚体位姿表示法知识结构 刚体位姿 (6-DOF) 位置向量 [x,y,z] 姿态表示 (3-DOF) 旋转矩阵 (3×3) 欧拉角 (α,β,γ) 四元数 (w,x,y,z) 轴角 (θ, u) 齐次变换矩阵 T (4×4) 应用:手眼标定、机器人运动学、SLAM 💡 核心建议: 内部计算用四元数,与人交互用欧拉角,串联变换用齐次矩阵。别混用,别偷懒。

3.7 实际应用中的选择建议

说了这么多,到底该用哪种?我根据多年经验,给你一个实用清单:

  • 做手眼标定优化时 → 用四元数作为旋转变量的参数化形式,配合李代数做扰动模型
  • 写机器人运动学正解时 → 用齐次变换矩阵串联各个关节
  • 调试可视化时 → 把四元数转成欧拉角,方便人眼理解
  • 做姿态插值时 → 用四元数的 SLERP,别用欧拉角线性插值
再强调一次: 千万别在优化变量里直接用欧拉角。我见过太多人在这上面栽跟头了。万向锁不是理论问题,是实实在在会让你的标定程序崩溃的工程问题。