第1章:坐标系与姿态表示

做IMU融合这些年,我最大的体会就是——坐标系搞不清楚,后面全是白搭。你想想看,传感器输出的数据是相对于它自己的,而你要控制的是整个载体的运动。这两者之间怎么对齐?这就是本章要解决的问题。

1.1 导航坐标系与载体坐标系

先说两个最基础的坐标系。我个人习惯把它们比作「世界地图」和「手机屏幕」。

导航坐标系(n系),也叫世界坐标系。它固定在地面上,通常取北-东-地(NED)或者东-北-天(ENU)。我最早做无人机项目时用的就是NED,因为飞控算法里重力方向是正Z,用起来很直观。

载体坐标系(b系),固定在运动物体上。原点在载体质心,X轴指向载体前方,Y轴指向右侧,Z轴指向下方。说白了,就是「我坐在飞机里,往前看的方向就是X」。

嗯,这里要注意:两个坐标系之间的转换,就是姿态估计的核心任务。

核心关系:

  • IMU输出的加速度、角速度 → 载体坐标系
  • 我们需要的导航信息(位置、速度) → 导航坐标系
  • 姿态矩阵 Cbn 就是连接两者的桥梁

我曾经在标定一个六轴IMU时,发现数据总是对不上。折腾了两天,最后发现是坐标系定义反了——我把载体坐标系的Z轴朝上了,而算法里默认朝下。这种低级错误,犯过一次就再也不会忘了。

1.2 欧拉角:俯仰、横滚、偏航

欧拉角是描述姿态最直观的方式。说白了就是三个角度:

  • 俯仰角(Pitch, θ):绕Y轴旋转,抬头低头
  • 横滚角(Roll, φ):绕X轴旋转,左右倾斜
  • 偏航角(Yaw, ψ):绕Z轴旋转,左右转向

旋转顺序我建议用Z-Y-X(偏航→俯仰→横滚),这是航空航天领域的标准。为什么是这个顺序?因为偏航角变化最频繁,放在最后旋转可以减少耦合。

⚠️ 万向锁问题:

当俯仰角接近±90°时,横滚和偏航的旋转轴会重合,导致自由度丢失。我在做云台控制时就踩过这个坑——相机垂直朝下时,航向角突然跳变。所以,如果你要做全姿态运动,别只用欧拉角。

欧拉角的微分方程也很重要:

// 欧拉角速率与角速度的关系
// ω = [p, q, r]^T 是载体坐标系下的角速度
// [φ̇, θ̇, ψ̇]^T 是欧拉角速率

φ̇ = p + q·sinφ·tanθ + r·cosφ·tanθ
θ̇ = q·cosφ - r·sinφ
ψ̇ = (q·sinφ + r·cosφ) / cosθ

你看,当θ接近90°时,cosθ趋近于0,ψ̇会变得无穷大。这就是万向锁的数学本质。

1.3 旋转矩阵

旋转矩阵是一个3×3的正交矩阵,它把一个向量从一个坐标系旋转到另一个坐标系。我习惯用Rbn表示「从载体坐标系到导航坐标系的旋转」。

单次旋转的矩阵很简单:

// 绕X轴旋转φ角
R_x(φ) = [1,    0,     0;
          0,  cosφ, -sinφ;
          0,  sinφ,  cosφ]

// 绕Y轴旋转θ角
R_y(θ) = [cosθ,  0,  sinθ;
          0,     1,     0;
         -sinθ,  0,  cosθ]

// 绕Z轴旋转ψ角
R_z(ψ) = [cosψ, -sinψ,  0;
          sinψ,  cosψ,  0;
          0,     0,     1]

完整的旋转矩阵就是三个矩阵的乘积(Z-Y-X顺序):

R = R_z(ψ) · R_y(θ) · R_x(φ)

💡 实用技巧:

旋转矩阵的逆等于它的转置(因为它是正交矩阵)。这意味着从n系到b系的旋转,直接取转置就行:Rnb = (Rbn)T。这个性质在代码里非常有用,省去了求逆的麻烦。

1.4 四元数基础

说实话,我刚开始接触四元数时也觉得头大。但用久了你会发现,它比欧拉角和旋转矩阵都好用。为什么?

  • 没有万向锁
  • 计算量小(只有4个参数)
  • 插值平滑(做姿态平滑时特别有用)

四元数可以理解为「绕一个单位向量n旋转θ角」的数学表示:

q = [cos(θ/2), n_x·sin(θ/2), n_y·sin(θ/2), n_z·sin(θ/2)]^T
   = [q0, q1, q2, q3]^T

其中q0是标量部分,[q1, q2, q3]是矢量部分。注意,四元数必须是单位四元数(模长为1),否则旋转会带缩放。

四元数的乘法(用于组合旋转):

q = q1 ⊗ q2

q0 = q1_0·q2_0 - q1_1·q2_1 - q1_2·q2_2 - q1_3·q2_3
q1 = q1_0·q2_1 + q1_1·q2_0 + q1_2·q2_3 - q1_3·q2_2
q2 = q1_0·q2_2 - q1_1·q2_3 + q1_2·q2_0 + q1_3·q2_1
q3 = q1_0·q2_3 + q1_1·q2_2 - q1_2·q2_1 + q1_3·q2_0

嗯,这个公式看着复杂,但写成代码就是几行乘法加法。我建议你直接封装成函数,别每次都手算。

1.5 三种表示方法的对比

特性 欧拉角 旋转矩阵 四元数
参数数量 3 9 4
直观性 ★★★★★ ★★☆☆☆ ★★☆☆☆
万向锁 有 无 无
计算效率 高 低 高
插值平滑 差 一般 好
适用场景 人机交互、显示 坐标变换 姿态解算、滤波

我个人在实际项目中,通常这样搭配使用:

  • 算法内部用四元数做姿态解算和滤波
  • 需要显示或记录时,转成欧拉角
  • 做坐标变换时,转成旋转矩阵

🔑 本章核心要点:

  1. 导航坐标系和载体坐标系是姿态估计的「两个世界」
  2. 欧拉角直观但有万向锁,适合人机交互
  3. 旋转矩阵适合坐标变换,但计算量大
  4. 四元数是姿态解算的首选,没有奇点
  5. 三种表示方法可以互相转换,要熟练掌握

最后分享一个我踩过的坑:有一次做IMU标定,我用了欧拉角做姿态更新,结果在俯仰角接近90°时,数据直接炸了。从那以后,我所有IMU融合算法都改用四元数。你想想看,一个万向锁就能让整个系统崩溃,这代价太大了。

坐标系与姿态表示知识体系 导航坐标系 (n系) NED / ENU,固定在地面 载体坐标系 (b系) 固定在运动物体上 欧拉角 俯仰 / 横滚 / 偏航 ⚠️ 有万向锁 旋转矩阵 3×3 正交矩阵 9个参数,计算量大 四元数 q₀ + q₁i + q₂j + q₃k 无奇点,适合滤波 人机交互 / 显示 欧拉角最直观 坐标变换 旋转矩阵最方便 姿态解算 / 滤波 四元数首选 三种表示方法可互相转换,根据场景灵活选用

可可精品资料库