在我们指挥机器人完成任何任务之前,首先需要解决一个最基本的问题:如何用一种精确、无歧义的数学语言,告诉机器人(或者让机器人告诉我们)某个物体在空间中的位置 和姿态?
本章的目标,就是让你彻底掌握这个机器人学中最核心的工具------齐次变换矩阵。把它想象成机器人学的"世界语言",一旦掌握,你就能描述机器人世界里的一切。
1.1 核心问题:如何描述"姿态"?
想象一下,你桌上放着一部手机。它不仅仅在桌子的某个位置 上,更关键的是,它还可能平放、竖放,或是45度角斜着放。这个"摆放的朝向",就是我们所说的姿态 (Attitude / Orientation)。
对于人类来说,"手机是竖着放的"这句话足够了。但对于需要精确执行任务的机器人来说,这是一个非常模糊的描述。我们需要一种 unambiguous (无歧义) 的数学语言来精确定义这个"姿态"。
解决方案是什么呢?我们想象在手机上"粘"了一个它自己的、独一无二的坐标系 {Phone}。这个坐标系的x轴可能沿着手机的短边,y轴沿着长边,z轴垂直于屏幕向上。
现在,描述手机的姿态,就转化成了一个数学问题:如何描述 {Phone} 坐标系相对于我们房间 {World} 坐标系的旋转关系?
1.1.1 旋转矩阵 (SO(3)SO(3)SO(3))
关键知识点
描述姿态最经典、最基础的方法,就是使用旋转矩阵 (Rotation Matrix)。它是一个3x3的矩阵,用9个数字,就完美地描述了两个坐标系之间的相对旋转。
别被"矩阵"这个词吓到,它的物理意义极其直观。我们通过一个例子来构建它。
场景构建:一步步理解旋转矩阵
-
定义我们的参考坐标系 {World}:
X_w轴:指向你的右方。Y_w轴:指向你的正前方。Z_w轴:垂直向上,指向天花板。
-
摆放手机 :
现在,你将手机平放在桌面上,然后逆时针旋转90度。
-
分析手机坐标系 {Phone} 的朝向 :
手机旋转后,它自己的坐标轴现在指向哪里了(用我们 {World} 的视角来看)?
- 手机的 x轴 (
X_p) 原本指向右,现在指向了前方 。在 {World} 坐标系里,这个方向是(0, 1, 0)。 - 手机的 y轴 (
Y_p) 原本指向前方,现在指向了左方 。在 {World} 坐标系里,这个方向是(-1, 0, 0)。 - 手机的 z轴 (
Z_p) 垂直于屏幕,它仍然指向上方 。在 {World} 坐标系里,这个方向是(0, 0, 1)。
- 手机的 x轴 (
-
构建旋转矩阵 :
我们把刚才分析出的三个向量,作为列向量 ,按顺序拼起来,就得到了这个姿态对应的旋转矩阵 RWPR_W^PRWP (从World到Phone的旋转):
RWP=[⋮⋮⋮XpYpZp⋮⋮⋮]inW=[0−10100001] R_W^P = \begin{bmatrix} \vdots & \vdots & \vdots \\ X_p & Y_p & Z_p \\ \vdots & \vdots & \vdots \end{bmatrix}_{in W} = \begin{bmatrix} 0 & -1 & 0 \\ 1 & 0 & 0 \\ 0 & 0 & 1 \end{bmatrix} RWP= ⋮Xp⋮⋮Yp⋮⋮Zp⋮ inW= 010−100001
旋转矩阵的定义与解读:
- 它的三列 :就是新坐标系 {Phone} 的 X, Y, Z 三个轴,在旧坐标系 {World} 下的坐标(投影/分量)表示。这是理解旋转矩阵最核心的一点!
- 它的三行 :(可以推导出)是旧坐标系 {World} 的 X, Y, Z 三个轴,在新坐标系 {Phone} 下的坐标(投影/分量)表示。
旋转矩阵的两个"黄金定律":
为什么这9个数字如此特别?因为它必须遵守两个保证其物理意义正确的铁律。
-
正交性 (Orthogonality) : 矩阵的每一列(或每一行)都是一个单位向量 ,并且任意两列(或两行)之间都相互垂直(点积为0)。
- 直观理解: 这保证了坐标系自身的"刚性"。手机的三个轴永远是互相垂直的,长度也永远是1。旋转这个动作不会把你的手机"压扁"或者"拉伸"。
- 数学性质 : RTR=IR^T R = IRTR=I (矩阵的转置等于其逆)。求一个旋转的"反向旋转",只需要对矩阵做一个转置就行了,计算上非常方便。
-
行列式为1 (Determinant = 1):
- 直观理解: 这保证了坐标系仍然遵循"右手定则"(从x轴到y轴的旋转方向,由右手大拇指指向z轴)。它确保你的手机没有被"镜像翻转"成一个左手坐标系。
满足这两个条件的3x3矩阵集合,在数学上被称为特殊正交群 SO(3)SO(3)SO(3) (Special Orthogonal Group of degree 3)。
1.1.2 核心用途:变换点的坐标 (改变视角)**
旋转矩阵最强大的用途,是回答这个问题:"一个点在手机坐标系下的坐标是 P_p,那么从我房间的世界坐标系来看,这个点的坐标 P_w 是多少?"
答案是:左乘旋转矩阵。
Pw=RWP⋅Pp P_w = R_W^P \cdot P_p Pw=RWP⋅Pp
例: 假设手机屏幕上有一个微小的瑕疵,在 {Phone} 坐标系下,它的坐标是 Pp=(3,2,0)P_p = (3, 2, 0)Pp=(3,2,0)。(即从手机原点出发,沿手机x轴走3个单位,再沿手机y轴走2个单位)。
从我们 {World} 的视角看,这个瑕疵在哪里?
Pw=[0−10100001][320]=[(0⋅3)+(−1⋅2)+(0⋅0)(1⋅3)+(0⋅2)+(0⋅0)(0⋅3)+(0⋅2)+(1⋅0)]=[−230] P_w = \begin{bmatrix} 0 & -1 & 0 \\ 1 & 0 & 0 \\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} 3 \\ 2 \\ 0 \end{bmatrix} = \begin{bmatrix} (0 \cdot 3) + (-1 \cdot 2) + (0 \cdot 0) \\ (1 \cdot 3) + (0 \cdot 2) + (0 \cdot 0) \\ (0 \cdot 3) + (0 \cdot 2) + (1 \cdot 0) \end{bmatrix} = \begin{bmatrix} -2 \\ 3 \\ 0 \end{bmatrix} Pw= 010−100001 320 = (0⋅3)+(−1⋅2)+(0⋅0)(1⋅3)+(0⋅2)+(0⋅0)(0⋅3)+(0⋅2)+(1⋅0) = −230
计算结果 Pw=(−2,3,0)P_w = (-2, 3, 0)Pw=(−2,3,0) 告诉我们,要找到这个瑕疵,需要从房间原点出发,向左走2个单位,再向前走3个单位。这完全符合我们对手机旋转90度后的直觉。
1.2 核心问题:如何同时描述"位置"与"姿态"?
在上一节中,我们成功地用旋转矩阵描述了手机的"朝向"------也就是姿态 。但现实中的机器人手臂末端(我们称之为"末端执行器"),不仅有姿态,它还必然处于空间中的某个位置。
我们现在有两个独立的工具:
- 旋转矩阵 R (3x3): 描述姿态。
- 平移向量 P (3x1): 描述位置 (例如,从世界坐标系原点到手机坐标系原点的向量)。
将它们分开处理当然可以,但非常繁琐。每当你想计算一个点在世界坐标系中的最终位置时,你都需要分两步操作:
- 先用旋转矩阵 RRR 旋转这个点:Protated=R⋅PlocalP_{rotated} = R \cdot P_{local}Protated=R⋅Plocal
- 再用平移向量 PPP 平移这个点:Pworld=Protated+PP_{world} = P_{rotated} + PPworld=Protated+P
这不够优雅,也难以进行复杂的连续变换(想象一下机械臂的七八个关节!)。我们需要一个更强大的工具,能把平移 (Translation) 和 旋转 (Rotation) 封装在一个数学对象里,用一次运算 就解决所有问题。这个物体的完整状态,我们称之为位姿 (Pose)。
1.2.1 齐次变换矩阵 (SE(3)SE(3)SE(3))
关键知识点
齐次变换矩阵 (Homogeneous Transformation Matrix) 就是解决位姿描述的最终答案。它是一个巧妙的4x4矩阵,它将3x3的旋转矩阵和3x1的平移向量完美地"粘合"在了一起。
场景构建:一步步理解齐次变换矩阵
让我们继续使用桌上的手机。在1.1节中,它位于世界坐标系的原点,只是做了一个旋转。现在,我们把这个旋转后的手机,从原点平移走。
-
定义手机的完整位姿 (Pose):
- 姿态 (Rotation) : 和之前一样,手机仍然是逆时针旋转90度 。我们已经知道它的旋转矩阵是:
RWP=[0−10100001] R_W^P = \begin{bmatrix} 0 & -1 & 0 \\ 1 & 0 & 0 \\ 0 & 0 & 1 \end{bmatrix} RWP= 010−100001 - 位置 (Position) : 现在,我们将手机的中心(其坐标系 {Phone} 的原点)移动到世界坐标系下的
(5, 4, 0)点。这意味着,要找到手机,你需要从房间原点{World}出发,向右(X_w)走5个单位,再向前(Y_w)走4个单位。这个平移向量是:
PW,Porg=[540] P_{W,P_{org}} = \begin{bmatrix} 5 \\ 4 \\ 0 \end{bmatrix} PW,Porg= 540
- 姿态 (Rotation) : 和之前一样,手机仍然是逆时针旋转90度 。我们已经知道它的旋转矩阵是:
-
组装齐次变换矩阵 :
现在,我们把这两个信息"组装"到一个4x4的"容器"里。规则如下:
- 左上角的3x3空间,留给旋转矩阵 R。
- 右上角的3x1空间,留给平移向量 P。
- 左下角,用
[0, 0, 0]填充。 - 右下角,用
1填充。(这看似奇怪的最后一行是实现数学技巧的关键)
于是,描述手机当前位姿的齐次变换矩阵 TWPT_W^PTWP (从World到Phone的变换) 就诞生了:
TWP=[0−101000015400001]=[r11r12r13pxr21r22r23pyr31r32r33pz0001] T_W^P = \begin{bmatrix} \begin{matrix} 0 & -1 & 0 \\ 1 & 0 & 0 \\ 0 & 0 & 1 \end{matrix} & \begin{matrix} 5 \\ 4 \\ 0 \end{matrix} \\ \begin{matrix} 0 & 0 & 0 \end{matrix} & 1 \end{bmatrix} = \begin{bmatrix} r_{11} & r_{12} & r_{13} & p_x \\ r_{21} & r_{22} & r_{23} & p_y \\ r_{31} & r_{32} & r_{33} & p_z \\ 0 & 0 & 0 & 1 \end{bmatrix} TWP= 010−1000010005401 = r11r21r310r12r22r320r13r23r330pxpypz1
1.2.2 核心用途:用一次乘法完成旋转和平移
这个4x4矩阵最强大的地方,就是它可以通过一次矩阵乘法 ,直接回答这个问题:"一个点在手机坐标系下的坐标是 PpP_pPp,那么从我房间的世界坐标系来看,这个点的坐标 PwP_wPw 是多少?"
为了让4x4的矩阵能够与一个3维点 (x, y, z) 相乘,我们需要一个小技巧:把这个点扩展成4维的齐次坐标 (Homogeneous Coordinate) ,方法很简单,就是在末尾加一个"1"。
例如,点 Pp=(3,2,0)P_p = (3, 2, 0)Pp=(3,2,0) 的齐次坐标就是 Pphom=(3,2,0,1)P_{p_{hom}} = (3, 2, 0, 1)Pphom=(3,2,0,1)。
现在,让我们来计算1.1节中的那个瑕疵(在手机坐标系下坐标为 Pp=(3,2,0)P_p = (3, 2, 0)Pp=(3,2,0))现在在世界坐标系中的位置:
Pwhom=TWP⋅Pphom P_{w_{hom}} = T_W^P \cdot P_{p_{hom}} Pwhom=TWP⋅Pphom
xwywzw1\]=\[0−105100400100001\]\[3201\]=\[(0⋅3)+(−1⋅2)+(0⋅0)+(5⋅1)(1⋅3)+(0⋅2)+(0⋅0)+(4⋅1)(0⋅3)+(0⋅2)+(1⋅0)+(0⋅1)(0⋅3)+(0⋅2)+(0⋅0)+(1⋅1)\]=\[3701\] \\begin{bmatrix} x_w \\\\ y_w \\\\ z_w \\\\ 1 \\end{bmatrix} = \\begin{bmatrix} 0 \& -1 \& 0 \& 5 \\\\ 1 \& 0 \& 0 \& 4 \\\\ 0 \& 0 \& 1 \& 0 \\\\ 0 \& 0 \& 0 \& 1 \\end{bmatrix} \\begin{bmatrix} 3 \\\\ 2 \\\\ 0 \\\\ 1 \\end{bmatrix} = \\begin{bmatrix} (0 \\cdot 3) + (-1 \\cdot 2) + (0 \\cdot 0) + (5 \\cdot 1) \\\\ (1 \\cdot 3) + (0 \\cdot 2) + (0 \\cdot 0) + (4 \\cdot 1) \\\\ (0 \\cdot 3) + (0 \\cdot 2) + (1 \\cdot 0) + (0 \\cdot 1) \\\\ (0 \\cdot 3) + (0 \\cdot 2) + (0 \\cdot 0) + (1 \\cdot 1) \\end{bmatrix} = \\begin{bmatrix} 3 \\\\ 7 \\\\ 0 \\\\ 1 \\end{bmatrix} xwywzw1 = 0100−100000105401 3201 = (0⋅3)+(−1⋅2)+(0⋅0)+(5⋅1)(1⋅3)+(0⋅2)+(0⋅0)+(4⋅1)(0⋅3)+(0⋅2)+(1⋅0)+(0⋅1)(0⋅3)+(0⋅2)+(0⋅0)+(1⋅1) = 3701 计算结果是 `(3, 7, 0, 1)`。去掉末尾的1,我们得到世界坐标 Pw=(3,7,0)P_w = (3, 7, 0)Pw=(3,7,0)。 **直观验证**:这个结果对吗? * 首先,手机的原点被移动到了 `(5, 4, 0)`。 * 然后,瑕疵相对于手机原点的局部矢量 `(3, 2, 0)`,因为手机旋转了90度,这个矢量在世界坐标系下变成了 `(-2, 3, 0)`(1.1节的计算结果)。 * 所以,瑕疵的最终世界坐标 = 手机原点的世界坐标 + 瑕疵旋转后的矢量 = `(5, 4, 0) + (-2, 3, 0) = (3, 7, 0)`。 * 结果完全一致!齐次变换矩阵通过一次运算就完成了旋转和平移的叠加,这正是它的威力所在。 满足这种结构的4x4矩阵集合,在数学上被称为**特殊欧几里得群 SE(3)SE(3)SE(3)** (Special Euclidean Group of degree 3)。 *** ** * ** *** #### 1.2.3 变换的链式法则-求逆 掌握齐次变换矩阵,意味着你掌握了机器人运动学中最核心的两个"超能力": **1. 变换的链式法则 (Composition)** 这是齐次变换矩阵最强大的地方。它让我们可以像串珠子一样,把机器人各个关节的位姿串联起来。 想象一个简单的两关节机械臂: * 你知道"连杆1相对于基座"的位姿变换,Tbaselink1T_{base}\^{link1}Tbaselink1。 * 你也知道"连杆2(末端)相对于连杆1"的位姿变换,Tlink1link2T_{link1}\^{link2}Tlink1link2。 那么,"连杆2(末端)相对于基座"的最终位姿是什么?你只需要将矩阵**依次相乘** : Tbaselink2=Tbaselink1⋅Tlink1link2T_{base}\^{link2} = T_{base}\^{link1} \\cdot T_{link1}\^{link2}Tbaselink2=Tbaselink1⋅Tlink1link2 这个规则可以无限延伸,构成整个机械臂的**运动学链 (Kinematic Chain)**。通过简单的矩阵乘法,我们就能精确知道机器人末端在世界中的任何位置和姿态。 **2. 变换的求逆 (Inversion)** 掌握齐次变换矩阵的求逆,在物理意义上就是学会如何\*\*"掉转视角"\*\*。这在机器人应用中极为常见。我们通过一个具体的场景来理解何时需要正向变换,何时需要逆向变换。 **场景设定:** 一个机器人手臂末端抓着一个相机。 * 我们通过正向运动学(将在后续章节学习)很容易知道"机器人手相对于世界"的位姿,记为 TworldhandT_{world}\^{hand}Tworldhand。 * 相机安装在手上,其相对位置是固定的,因此"相机相对于机器人手"的位姿 ThandcameraT_{hand}\^{camera}Thandcamera 是一个已知的设计参数。 **场景一:将"相机看到的东西"转换到"世界坐标" (不需要求逆)** 这是你提出的场景,也是最常见的"正向"应用。 假设相机在其视野里发现了一个物体(例如一个待抓取的螺丝),并通过图像处理得到了这个螺丝在**相机坐标系** 下的坐标 PcameraP_{camera}Pcamera。 我们的问题是:这个螺丝在**世界坐标系** 中的位置 PworldP_{world}Pworld 是哪里?只有知道了世界坐标,我们才能规划整个机器人去抓取它。 要回答这个问题,我们需要一个能将点从`{camera}`坐标系变换到`{world}`坐标系的变换矩阵,也就是 TworldcameraT_{world}\^{camera}Tworldcamera。我们可以通过之前提到的**链式法则**得到它: Tworldcamera=Tworldhand⋅ThandcameraT_{world}\^{camera} = T_{world}\^{hand} \\cdot T_{hand}\^{camera}Tworldcamera=Tworldhand⋅Thandcamera 有了这个变换矩阵,我们就可以直接计算螺丝的世界坐标: Pworld=Tworldcamera⋅PcameraP_{world} = T_{world}\^{camera} \\cdot P_{camera}Pworld=Tworldcamera⋅Pcamera **结论** :在这个场景中,我们的目标是"从相机视角转到世界视角",而 TworldcameraT_{world}\^{camera}Tworldcamera 这个矩阵的物理意义正是描述"相机在世界中的位姿",所以直接使用它即可,**无需进行求逆运算**。 **场景二:将"世界中的物体"转换到"相机坐标" (需要求逆)** 现在,我们换一个问题。假设我们从另一处得知,世界坐标系中有一个障碍物,其坐标是 PworldP_{world}Pworld。机器人需要判断:**这个障碍物是否会出现在我的相机视野里?它在相机画面中的坐标 PcameraP_{camera}Pcamera 是什么?** 要回答这个问题,我们需要将一个世界坐标系下的点,转换到相机坐标系下来观察。也就是说,我们需要一个能将点从`{world}`坐标系变换到`{camera}`坐标系的变换矩阵,即 TcameraworldT_{camera}\^{world}Tcameraworld。 这个变换,正好与我们已知的 TworldcameraT_{world}\^{camera}Tworldcamera 视角相反。因此,这才是**求逆运算**大显身手的时刻: Tcameraworld=(Tworldcamera)−1T_{camera}\^{world} = (T_{world}\^{camera})\^{-1}Tcameraworld=(Tworldcamera)−1 得到这个逆矩阵后,我们就可以计算出障碍物在相机坐标系下的坐标: Pcamera=Tcameraworld⋅PworldP_{camera} = T_{camera}\^{world} \\cdot P_{world}Pcamera=Tcameraworld⋅Pworld **求逆公式** 幸运的是,齐次变换矩阵的求逆有一个非常高效的固定公式,而不需要进行复杂的通用矩阵求逆计算: (TAB)−1=TBA=\[(RAB)T−(RAB)T⋅PA,Borg0001\] (T_A\^B)\^{-1} = T_B\^A = \\begin{bmatrix} (R_A\^B)\^T \& -(R_A\^B)\^T \\cdot P_{A,B_{org}} \\\\ \\begin{matrix} 0 \& 0 \& 0 \\end{matrix} \& 1 \\end{bmatrix} (TAB)−1=TBA=\[(RAB)T000−(RAB)T⋅PA,Borg1
- 直观理解 :
- 旋转部分
(R_A^B)^T: 将原本的旋转"反向",这通过对旋转矩阵求转置来实现。 - 平移部分
-(R_A^B)^T \cdot P_{A,B_{org}}: 从新的视角(B的视角)去看旧的原点(A的原点)在哪里。它首先将旧的平移向量 PA,BorgP_{A,B_{org}}PA,Borg (在A视角下B原点的位置) 通过反向旋转(R_A^B)^T转换到B坐标系下,然后取负号,就得到了"A原点在B坐标系下的位置"。
- 旋转部分
1.3 旋转的"快捷方式":欧拉角及其陷阱
到目前为止,我们已经知道,一个3x3的旋转矩阵可以完美、无歧义地描述任何姿态。那么,我们为什么还要寻找其他方法呢?
原因很简单:旋转矩阵对计算机很友好,但对人类不友好。
- 不直观 :看着一个由9个小数组成的矩阵
R,你能立刻想象出手机是怎么摆放的吗?非常困难。 - 冗余:一个三维旋转只有3个自由度(你可以想象成绕X, Y, Z三个轴的独立旋转),但旋转矩阵却用了9个数字来描述,这在存储和网络传输时是一种浪费。
我们自然会想:有没有一种更符合人类直觉、更紧凑的方式来描述旋转呢?
1.3.1 人类最习惯的方式:欧拉角 (Euler Angles)
答案是有的,这就是欧拉角 。它的核心思想是:任何复杂的空间旋转,都可以分解为绕着某个坐标系(例如世界坐标系 {W})的三个基本轴(X, Y, Z)进行的三次连续旋转。
最著名的欧拉角系统就是飞行器和无人机领域常用的 偏航角(Yaw) - 俯仰角(Pitch) - 滚转角(Roll)。
- 偏航 (Yaw):绕Z轴旋转,如同你水平摇头。
- 俯仰 (Pitch):绕Y轴旋转,如同你上下点头。
- 滚转 (Roll):绕X轴旋转,如同你左右歪头。
回到我们的手机例子:
之前我们描述的"手机平放,逆时针旋转90度"的姿态,如果用欧拉角(特别是先绕Z轴旋转的顺序)来描述,会变得极其简单:
- 绕Z轴旋转 (偏航): +90度
- 绕Y轴旋转 (俯仰): 0度
- 绕X轴旋转 (滚转): 0度
我们只需要 (0, 0, 90) 这三个数字,就能清晰地表达这个姿态。这比记忆一个9个元素的矩阵要容易得多。在很多机器人控制或3D建模软件的用户界面上,让你直接输入的就是这三个角度值,而不是一个矩阵。
1.3.2 致命的缺陷:万向节死锁 (Gimbal Lock)
既然欧拉角如此直观又紧凑,为什么不干脆用它完全取代旋转矩阵呢?因为它存在一个灾难性的数学缺陷------万向节死锁。
一个直观的例子:
想象你有一个可以三轴旋转的手机云台:一个底座环(控制左右摇头,即偏航角 Yaw ),中间一个环(控制上下点头,即俯仰角 Pitch ),最里面一个夹子(控制手机自身的翻滚,即滚转角 Roll)。
- 初始情况:三个环的转轴互相垂直,你可以让手机朝向空间中的任何方向。
- 发生死锁 :现在,你控制云台向上"点头"90度(即 Pitch = 90° ),让手机垂直朝向天花板。此时,你会惊奇地发现:
- 底座环的"摇头"轴(Yaw 轴)。
- 手机夹子的"翻滚"轴(Roll 轴)。
...它们现在指向了同一个方向 (都垂直于地面)!它们的旋转轴发生了重合。
- 后果 :在这种姿态下,无论你是想"摇头"(转动Yaw轴)还是"翻滚"(转动Roll轴),产生的效果都是完全一样的------让手机绕着那个垂直轴"水平打转"。你失去了一个维度的旋转能力(在这个例子里,你无法改变手机镜头朝向左右两侧的墙壁)。
这就是万向节死锁------系统丢失了一个旋转自由度。
这个现象在机器人、无人机和3D动画中是灾难性的,它会导致控制失灵和运动轨迹的突变。因此,欧拉角可以作为人机交互的接口,但通常不用于内部的核心计算。
那么,有没有一种方法,既能比旋转矩阵更紧凑,又能完美地避免万向节死锁问题呢?答案就是四元数。
1.4 更高效的旋转表示:四元数 (Quaternion)
四元数 (Quaternion) 是一种更先进、更紧凑的数学工具,它能完美地解决上述所有问题。它使用4个数字来表示一个3D旋转,通常记为 q=(w,x,y,z)q = (w, x, y, z)q=(w,x,y,z)。
1.4.1 核心思想:轴-角表示法 (Axis-Angle Representation)
四元数最直观的理解方式是,任何一个三维旋转,都可以等价于"绕着空间中某个任意的单位向量轴 n^=(nx,ny,nz)\hat{n} = (n_x, n_y, n_z)n^=(nx,ny,nz) 旋转一个角度 θ\thetaθ"。
四元数的四个分量,正是由这个旋转轴和旋转角构成的:
q=(w,x,y,z)=(cos(θ2),sin(θ2)nx,sin(θ2)ny,sin(θ2)nz) q = (w, x, y, z) = (\cos(\frac{\theta}{2}), \sin(\frac{\theta}{2})n_x, \sin(\frac{\theta}{2})n_y, \sin(\frac{\theta}{2})n_z) q=(w,x,y,z)=(cos(2θ),sin(2θ)nx,sin(2θ)ny,sin(2θ)nz)
- www 分量(实部)代表旋转的"量",与旋转角度 θ\thetaθ 相关。
- (x,y,z)(x, y, z)(x,y,z) 分量(虚部)构成一个矢量,代表了旋转轴的方向。
示例:回到我们的手机
让我们用四元数来描述1.1节中那个"手机逆时针旋转90度"的姿态。
-
确定旋转轴和角度:
- 这个旋转是绕着 {World} 坐标系的 Z 轴进行的。所以,旋转轴 n^=(0,0,1)\hat{n} = (0, 0, 1)n^=(0,0,1)。
- 旋转角度 θ=90∘=π2\theta = 90^\circ = \frac{\pi}{2}θ=90∘=2π 弧度。
-
计算四元数分量:
- w=cos(θ2)=cos(π/22)=cos(π4)=22≈0.707w = \cos(\frac{\theta}{2}) = \cos(\frac{\pi/2}{2}) = \cos(\frac{\pi}{4}) = \frac{\sqrt{2}}{2} \approx 0.707w=cos(2θ)=cos(2π/2)=cos(4π)=22 ≈0.707
- x=sin(θ2)nx=sin(π4)⋅0=0x = \sin(\frac{\theta}{2})n_x = \sin(\frac{\pi}{4}) \cdot 0 = 0x=sin(2θ)nx=sin(4π)⋅0=0
- y=sin(θ2)ny=sin(π4)⋅0=0y = \sin(\frac{\theta}{2})n_y = \sin(\frac{\pi}{4}) \cdot 0 = 0y=sin(2θ)ny=sin(4π)⋅0=0
- z=sin(θ2)nz=sin(π4)⋅1=22≈0.707z = \sin(\frac{\theta}{2})n_z = \sin(\frac{\pi}{4}) \cdot 1 = \frac{\sqrt{2}}{2} \approx 0.707z=sin(2θ)nz=sin(4π)⋅1=22 ≈0.707
-
得到四元数 :
所以,这个姿态可以用四元数 q≈(0.707,0,0,0.707)q \approx (0.707, 0, 0, 0.707)q≈(0.707,0,0,0.707) 来精确表示。
1.4.2 我们现在需要知道的
- 为何存在: 它在计算上更高效,并且能完美避免万向节死锁问题。
- 应用场景: 在几乎所有的现代3D图形学、航空航天和机器人软件库(包括我们之后要用的ROS)中,底层的旋转计算都默认使用四元数。它在两个姿态之间进行平滑插值(称为SLERP)时也特别有用。
- 如何看待 : 你暂时不需要深入理解四元数的复杂乘法规则。把它看作一个"黑盒子",并学会使用软件库(如Python的
scipy.spatial.transform.Rotation或ROS的tfquaternion)来帮助你在旋转矩阵、欧拉角和四元数之间自由转换。
实践中的使用
python
from scipy.spatial.transform import Rotation as R
import numpy as np
# 从我们熟悉的旋转矩阵创建
rot_matrix = np.array([
[0, -1, 0],
[1, 0, 0],
[0, 0, 1]
])
r = R.from_matrix(rot_matrix)
# 转换为四元数 (scipy的格式是 x, y, z, w)
quat = r.as_quat()
print(f"对应的四元数为 (x,y,z,w): {quat}") # 输出 [0. 0. 0.70710678 0.70710678]
# 从轴-角创建
r_axis_angle = R.from_rotvec([0, 0, np.pi/2]) # 旋转向量:轴*角度
quat_from_axis = r_axis_angle.as_quat()
print(f"从轴角得到的四元数: {quat_from_axis}") # 输出 [0. 0. 0.70710678 0.70710678]
本章小结
恭喜你,你已经掌握了机器人学的核心语言!
- 要描述姿态 (Orientation) ,我们用旋转矩阵 (SO(3)SO(3)SO(3))。它的列向量就是新坐标系的基轴在旧坐标系下的表示。
- 要同时描述位置 (Position) 和姿态 (Attitude) ,即位姿 (Pose) ,我们用齐次变换矩阵 (SE(3)SE(3)SE(3)),它将旋转与平移封装在了一个统一的4x4矩阵中。
- 矩阵乘法 让我们能够像链条一样连接不同的坐标系(Tbaseend=Tbaselink1⋅Tlink1endT_{base}^{end} = T_{base}^{link1} \cdot T_{link1}^{end}Tbaseend=Tbaselink1⋅Tlink1end),这是整个机器人运动学的基础。
- 矩阵求逆 让我们能够反转视角,从一个坐标系去看另一个(TBA=(TAB)−1T_{B}^{A} = (T_{A}^{B})^{-1}TBA=(TAB)−1)。
- 欧拉角 是一种直观但存在万向节死锁问题的姿态表示。
- 四元数是一种更紧凑、更高效且能避免死锁的姿态表示方法,是现代机器人软件的底层核心。
有了这些基础,你就为理解下一章的"运动学"(即机械臂如何运动)铺平了道路。你已经准备好将这些抽象的矩阵,应用到真实的机器人连杆上了