Rigid body motion

**刚体运动(rigid body motion,刚性变换)**保持所有点之间的距离不变。在三维空间中,它由一个旋转和一个平移组成,而表示它的数学结构——SO(3)SO(3)SE(3)SE(3)——在SLAM中处于核心地位:相机位姿本身就是 SE(3)SE(3) 的一个元素。

旋转的表示方法

欧拉角(Euler angles)。 一个旋转可以由三个角度 (ϕ,θ,ψ)(\phi, \theta, \psi) 参数化,表示绕固定轴或绕体坐标轴依次进行的旋转;12 种可能的约定(ZYX、XYZ 等)各自给出不同的角度序列。**万向锁(gimbal lock)**问题发生在两个旋转轴对齐时,使得有效自由度降为 2。欧拉角在显示时很直观,但在数值上存在问题——在迭代优化中应避免使用。

旋转矩阵(Rotation matrices)。 旋转矩阵满足 RTR=IR^TR = Idet(R)=+1\det(R) = +1。所有这样的矩阵构成特殊正交群(Special Orthogonal Group)

SO(3)={RR3×3RTR=I, det(R)=+1}SO(3) = \{R \in \mathbb{R}^{3\times3} \mid R^TR = I,\ \det(R) = +1\}

旋转矩阵是用于计算的首选表示方式:矩阵乘法即是复合运算,而逆运算只需简单地取转置。

四元数(Quaternions)。 单位四元数 q=w+xi+yj+zkq = w + xi + yj + zk(满足 w2+x2+y2+z2=1w^2+x^2+y^2+z^2 = 1)表示绕轴 [x,y,z]T/sin(θ/2)[x,y,z]^T/\sin(\theta/2) 旋转角度 θ=2arccos(w)\theta = 2\arccos(w)。它们很紧凑(4 个数字对比 9 个),没有万向锁问题,并通过哈密顿积(Hamilton product)进行复合。请注意其双重覆盖性质:qqq-q 表示同一个旋转。

从四元数转换为旋转矩阵:

R=[12(y2+z2)2(xywz)2(xz+wy)2(xy+wz)12(x2+z2)2(yzwx)2(xzwy)2(yz+wx)12(x2+y2)]R = \begin{bmatrix} 1 - 2(y^2+z^2) & 2(xy - wz) & 2(xz + wy) \\ 2(xy + wz) & 1 - 2(x^2+z^2) & 2(yz - wx) \\ 2(xz - wy) & 2(yz + wx) & 1 - 2(x^2+y^2) \end{bmatrix}

一个快速的 NumPy 检验,用于确认某矩阵是否为合法的旋转矩阵:

import numpy as np
# R is a rotation iff R^T R = I and det(R) = +1
print(np.allclose(R.T @ R, np.eye(3)), np.isclose(np.linalg.det(R), 1.0))

齐次变换:TSE(3)T \in SE(3)

刚体运动将旋转 RR 和平移 t\mathbf{t} 组合成一个作用于齐次坐标的 4×44\times4 矩阵:

T=[Rt0T1]SE(3),T[X1]=[RX+t1]T = \begin{bmatrix} R & \mathbf{t} \\ \mathbf{0}^T & 1 \end{bmatrix} \in SE(3), \qquad T\begin{bmatrix}\mathbf{X}\\1\end{bmatrix} = \begin{bmatrix} R\mathbf{X} + \mathbf{t} \\ 1 \end{bmatrix}

复合运算即为矩阵乘法,其中旋转和平移相互交织:

T1T2=[R1R2R1t2+t10T1]T_1 T_2 = \begin{bmatrix} R_1R_2 & R_1\mathbf{t}_2 + \mathbf{t}_1 \\ \mathbf{0}^T & 1 \end{bmatrix}

——注意 t2\mathbf{t}_2 会被 R1R_1 旋转,这也是为什么链式变换的平移量不会简单地相加。其逆运算有闭合形式:

T1=[RTRTt0T1]T^{-1} = \begin{bmatrix} R^T & -R^T\mathbf{t} \\ \mathbf{0}^T & 1 \end{bmatrix}

齐次坐标来自投影空间(projective space):在点坐标后添加 1(或在方向向量后添加 0),使得一个矩阵就能同时表达旋转和平移。在投影几何中,三维空间里平行的直线会在图像中相交于一个消失点(vanishing point)——这在人造环境中的旋转估计中是一个有用的线索,也提醒我们成像过程是投影性的,而非欧几里得式的。

保持坐标系清晰

最有效的习惯是采用一种能够自我检查复合运算的下标约定:令 TABT_{AB} 表示把坐标从坐标系 BB 映射到坐标系 AA。那么

TAC=TABTBC,XA=TABXBT_{AC} = T_{AB}\,T_{BC}, \qquad \mathbf{X}_A = T_{AB}\,\mathbf{X}_B

相邻的下标必须像单位一样能够”相消”。如果不能相消,那么这个表达式就是错的——这一点能一眼看出相当大比例的位姿运算错误。要明确地说明所存储的”相机位姿”到底指的是 Tworld,camT_{world,cam}(从相机到世界的变换,即相机在世界中的位置)还是它的逆 Tcam,worldT_{cam,world}(投影中所使用的外参);这两种约定在各代码库中都很常见。

常见陷阱

对SLAM的意义

每一个SLAM系统本质上都是在估计一条由 SE(3)SE(3) 元素构成的轨迹。链式组合相对运动(Tworld,cam=Tworld,kfTkf,camT_{world,cam} = T_{world,kf}\,T_{kf,cam})、求变换的逆,以及在四元数(紧凑存储、ROS 消息)与旋转矩阵(计算)之间相互转换,都是日常操作。正确处理坐标系约定——一个变换是从哪个坐标系映射到哪个坐标系——是新手最常见的 bug 来源,因此在继续学习之前务必把这一点搞清楚。

相关条目