2. 坐标系与刚体运动:世界坐标系、IMU坐标系、相机坐标系、刚体旋转与平移、四元数与李代数基础

说实话,做VIO初始化,最绕不开的就是坐标系。我见过不少新手,代码写了大半年,最后发现IMU和相机之间的外参标定反了,整个系统直接崩掉。所以这一章,咱们把坐标系和刚体运动的基础打扎实。

2.1 三个核心坐标系

VIO系统里,我们天天跟三个坐标系打交道。你想想看,IMU在动,相机在拍,世界坐标系是锚点。这三者之间的关系,就是VIO要解的核心问题。

2.1.1 世界坐标系 (World Frame, W)

世界坐标系是固定的。我习惯把它定义在IMU启动时的位置,或者某个已知的地面点。它提供绝对参考,重力方向通常对齐Z轴向下。嗯,这里要注意:不同数据集的定义可能不同,比如EuRoC数据集和TUM数据集,重力方向就不一样。

2.1.2 IMU坐标系 (Body Frame, B)

IMU坐标系跟着传感器走。它的三轴定义通常是:X向前,Y向左,Z向上(右手系)。但实际硬件不一定按这个来。我在项目中遇到过一款IMU,它的Z轴是向下的,结果加速度计读数全是反的。所以拿到新硬件,第一件事就是确认坐标系定义。

2.1.3 相机坐标系 (Camera Frame, C)

相机坐标系的原点在光心,Z轴指向相机前方(也就是拍摄方向)。X向右,Y向下。这个坐标系跟图像像素坐标之间的转换,就是内参矩阵的事。说白了,相机坐标系是连接3D世界和2D图像的桥梁。

核心关系: VIO初始化要解的就是:
PW = RWB · PB + tWB
其中RWB和tWB就是IMU在世界坐标系下的位姿。

2.2 刚体旋转与平移

刚体运动,说白了就是物体在空间里又转又移,但形状不变。旋转和平移是分开处理的,因为旋转是非线性的,处理起来比平移麻烦得多。

2.2.1 旋转矩阵

旋转矩阵R是一个3x3的正交矩阵,行列式为+1。它把向量从一个坐标系转到另一个坐标系。比如vB = RBC · vC,就是把相机坐标系下的向量转到IMU坐标系下。

我刚开始做SLAM时,总搞混旋转矩阵的转置和逆。其实对于旋转矩阵,RT = R-1。这个性质在代码里经常用到,比如从世界到IMU的旋转,反过来就是转置一下。

2.2.2 平移向量

平移就简单多了,就是三个方向的位移。但要注意:平移向量通常是在目标坐标系下表达的。比如tWB表示IMU原点在世界坐标系下的位置。

我的习惯: 在代码里,我统一用T_W_B表示世界到IMU的变换矩阵。这样看代码时,一眼就知道坐标系关系。

2.3 四元数

四元数?很多人一听就头大。其实它就是个更紧凑的旋转表示方式。一个四元数q = [w, x, y, z],其中w是实部,x,y,z是虚部。它没有万向锁问题,插值也平滑,所以VIO里几乎都用它。

我记得第一次手写四元数乘法时,把顺序搞反了,结果旋转方向全错了。四元数乘法不满足交换律,q1 * q2q2 * q1结果不同。这个坑,我踩过。

2.3.1 四元数到旋转矩阵

转换公式长这样:

R = | 1-2(y²+z²)   2(xy-wz)     2(xz+wy)   |
    | 2(xy+wz)     1-2(x²+z²)   2(yz-wx)   |
    | 2(xz-wy)     2(yz+wx)     1-2(x²+y²) |

嗯,不用硬背。Eigen库里有现成的.toRotationMatrix()方法。但理解原理很重要,调试时能帮你快速定位问题。

2.4 李代数基础

李代数?听起来高大上。其实它解决的是旋转的求导问题。旋转矩阵是正交的,直接求导很麻烦。李代数把旋转映射到三维向量空间,求导就变成了普通的向量微积分。

2.4.1 so(3)与SE(3)

so(3)对应旋转,是三维向量。SE(3)对应刚体变换,是六维向量(三维旋转+三维平移)。在VIO初始化里,我们经常用SE(3)来表示相机或IMU的位姿。

李代数到李群的指数映射:R = exp(φ^),其中φ是so(3)向量,φ^是它的反对称矩阵。这个映射把旋转向量变成了旋转矩阵。

我曾经踩过的坑: 李代数的加法不直接对应旋转的加法。两个旋转的合成要用指数映射的BCH公式近似。在优化时,我们通常是在李代数上做增量更新,而不是直接加旋转矩阵。

2.5 知识体系总览

下面这张图,是我自己总结的坐标系与刚体运动的知识结构。每次带新人,我都会先让他们看这个图,建立整体认知。

坐标系与刚体运动知识体系 世界坐标系 (W) 固定参考系 重力方向对齐Z轴 IMU坐标系 (B) 传感器本体 加速度+角速度 相机坐标系 (C) 光心为原点 Z轴指向前方 刚体运动表示 旋转矩阵 R 3x3正交矩阵 四元数 q 无万向锁 平移向量 t 三维位移 变换矩阵 T 4x4齐次 李代数基础 so(3) → 旋转 SE(3) → 刚体变换 指数映射 exp(φ^)

2.6 实践中的坐标系管理

说了这么多理论,来点实际的。我在写VIO代码时,会遵循几条铁律:

  1. 统一命名规范:所有坐标系变换都用R_AB表示从B到A的旋转。比如R_WB是IMU到世界。
  2. 外参标定文件:IMU到相机的变换T_BC,一定要单独存一个文件。我见过有人写死在代码里,换硬件就崩。
  3. 单元测试:写一个测试函数,验证坐标系变换的一致性。比如把一个点从相机转到世界,再转回来,看是否回到原点。
避坑指南: 我曾经在初始化阶段,把IMU的加速度计读数直接当成了世界坐标系下的值。结果重力方向反了,整个系统发散。正确的做法是:先用旋转矩阵把IMU读数转到世界坐标系,再减去重力。

好了,坐标系和刚体运动的基础就这些。这些概念会贯穿整个VIO初始化过程。下一节我们聊IMU的测量模型和预积分,到时候你会看到,坐标系变换无处不在。


专注资料整理