2. 运动学基础:刚体变换、齐次坐标、旋转矩阵、欧拉角与四元数

好,咱们正式开始啃运动学这块硬骨头。

说实话,我刚入行那会儿,觉得运动学就是一堆矩阵乘法,枯燥得很。直到有一次调试机械臂,末端执行器死活对不准目标点,折腾了两天,最后发现是旋转顺序搞反了。嗯,从那以后,我再也不敢小看这些基础概念了。

这一节,咱们把刚体变换、齐次坐标、旋转矩阵、欧拉角、四元数这几个东西彻底捋清楚。你想想看,机械臂的每一个关节都在动,末端执行器在空间里又平移又旋转,怎么描述它?怎么计算它?就是靠这些东西。

2.1 刚体变换:位置 + 姿态

一个刚体在三维空间里,有6个自由度——3个平移,3个旋转。说白了,就是「它在哪」和「它朝哪」。

我个人习惯把刚体变换拆成两步看:
第一步,把坐标系挪过去(平移);
第二步,把坐标系转过去(旋转)。

用数学表达就是:

P' = R * P + t

其中 P 是物体在自身坐标系下的坐标,R 是旋转矩阵,t 是平移向量,P' 是它在世界坐标系下的坐标。

我的小经验: 调试时如果发现机械臂末端位置对但姿态不对,十有八九是旋转矩阵算错了。先检查旋转,再检查平移,这个顺序能省不少时间。

2.2 齐次坐标:把平移和旋转统一起来

你可能会问:为什么非要用齐次坐标?直接用 P' = R*P + t 不行吗?

行,但麻烦。因为连续变换时,你要不停地加平移、乘旋转,写起来又长又容易错。齐次坐标的妙处在于——它把平移也塞进了矩阵里。

看这个:

| P' |   | R   t |   | P |
| 1  | = | 0   1 | * | 1 |

这样一来,多次变换就变成了矩阵连乘。我当年第一次看懂这个的时候,觉得这设计真漂亮——干净、统一、好算。

核心要点: 齐次坐标用4维向量表示3维点,用4x4矩阵表示刚体变换。最后一个分量是1,表示点;是0,表示方向向量。

2.3 旋转矩阵:绕轴转的数学表达

旋转矩阵是3x3的正交矩阵,行列式为+1。绕X、Y、Z轴旋转的矩阵长这样:

绕X轴转θ:
| 1    0       0   |
| 0  cosθ  -sinθ  |
| 0  sinθ   cosθ  |

绕Y轴转θ:
| cosθ   0   sinθ  |
| 0      1    0    |
| -sinθ  0   cosθ  |

绕Z轴转θ:
| cosθ  -sinθ  0  |
| sinθ   cosθ  0  |
| 0      0     1  |

我在项目中遇到过一个问题:两个旋转矩阵相乘,结果怎么都不对。后来发现,矩阵乘法不满足交换律——先绕X转再绕Y转,和先绕Y转再绕X转,结果完全不同。这个坑,踩过一次就记住了。

注意: 旋转矩阵虽然直观,但参数有冗余(9个元素,实际只有3个自由度),而且容易产生数值误差。连续乘很多次后,矩阵可能不再是正交的,需要重新正交化。

2.4 欧拉角:直观但容易出问题

欧拉角用三个角度表示旋转,比如滚转、俯仰、偏航。听起来很直观对吧?

但问题来了——旋转顺序怎么定?是先绕X再绕Y再绕Z?还是先绕Z再绕Y再绕X?不同的顺序,结果天差地别。

我曾经在仿真里用欧拉角控制机械臂,结果在某个角度附近,机械臂突然「抽搐」了一下。查了半天,发现是万向锁——当俯仰角接近90度时,滚转和偏航就分不清了,丢失了一个自由度。

避坑指南: 欧拉角适合给人看,不适合给机器算。如果你要在代码里做插值或连续旋转,别用欧拉角,用四元数。

2.5 四元数:旋转的终极方案

四元数,说白了就是一个实部加三个虚部:q = w + xi + yj + zk。它用4个参数表示旋转,没有冗余,没有万向锁,插值平滑。

绕单位向量 u = (ux, uy, uz) 转 θ 角的四元数是:

q = (cos(θ/2), ux*sin(θ/2), uy*sin(θ/2), uz*sin(θ/2))

用四元数旋转一个向量 v:

v' = q * v * q_conjugate

嗯,这里要注意,四元数乘法不交换,顺序很重要。

我的习惯: 在代码里,我统一用四元数做内部计算,只在显示给用户看时转成欧拉角。这样既避免了万向锁,又保留了直观性。

2.6 知识体系总览

下面这张图,把这一节的核心逻辑串起来了:

运动学基础:知识体系 刚体变换 (6自由度) 位置 (平移) 姿态 (旋转) 旋转矩阵 (3x3) 欧拉角 (3个角度) 四元数 (w,x,y,z) 齐次坐标 (4x4矩阵)

2.7 它们之间的转换

在实际工程中,这几个表示方法经常要互相转换。我整理了一张对照表,方便你查阅:

转换方向 方法 注意事项
旋转矩阵 → 欧拉角 根据矩阵元素反解角度 注意万向锁,当cosθ接近0时需特殊处理
欧拉角 → 旋转矩阵 按顺序乘三个基本旋转矩阵 必须明确旋转顺序(如ZYX、XYZ)
旋转矩阵 → 四元数 从矩阵迹和元素计算 注意数值稳定性,选最大的分量做分母
四元数 → 旋转矩阵 用四元数元素构造矩阵 确保四元数是单位四元数
欧拉角 → 四元数 先转矩阵,再转四元数 或者直接用角度构造四元数乘法
重要提醒: 不同库(如ROS、Eigen、MATLAB)对欧拉角的定义可能不同。有的用ZYX顺序,有的用XYZ顺序。我在项目里吃过这个亏——两个模块用的顺序不一样,结果机械臂乱转。一定要在接口文档里写清楚!

2.8 实战建议

说了这么多,给你几条实在的建议:

  • 做仿真时:用四元数做内部计算,用欧拉角做调试输出。
  • 做标定时:用旋转矩阵,因为它便于做最小二乘优化。
  • 做插值时:用四元数的球面线性插值(SLERP),平滑无抖动。
  • 做可视化时:用欧拉角,人看着直观。

我个人习惯在代码里写一个转换工具类,把旋转矩阵、欧拉角、四元数之间的转换都封装好。这样不管外部接口用什么格式,内部统一用四元数,省心。

一个小技巧: 调试时,把旋转矩阵打印出来,看看行列式是不是接近1,逆矩阵是不是等于转置。这两个条件不满足,说明你的旋转矩阵已经「坏」了。

好了,运动学基础就聊到这儿。这些东西看着抽象,但你在仿真里跑几次机械臂,遇到几次对不准的问题,自然就理解了。下一节咱们聊正运动学——怎么从关节角度算出末端位姿。


可可精品资料库