2. 姿态表示方法:欧拉角、旋转矩阵、四元数

姿态表示,说白了就是怎么描述飞行器「脑袋朝哪、肚皮朝哪」。我刚开始做飞控时,觉得这玩意儿不就是三个角度嘛,有啥好讲的?结果第一次调参,飞机在天上翻了个跟头——嗯,就是那个著名的「万向锁」问题。从那以后,我再也不敢小看姿态表示了。

这一节,咱们把三种主流表示方法掰开揉碎讲清楚。你不需要一次性全记住,但得知道它们各自擅长什么、坑在哪。

2.1 欧拉角:最直观,也最危险

欧拉角就是三个角度:俯仰(Pitch)、横滚(Roll)、偏航(Yaw)。你可以想象成飞机先绕自己的X轴转(横滚),再绕Y轴转(俯仰),最后绕Z轴转(偏航)。

核心公式(绕ZYX顺序):

R = Rz(yaw) * Ry(pitch) * Rx(roll)

注意:乘法顺序是从右往左读,先转的放右边。

欧拉角的好处是物理意义清晰。你看到 pitch = 30°,就知道机头抬了30度。调试时用欧拉角看数据,一眼就能发现问题。

但欧拉角有个致命缺陷——万向锁(Gimbal Lock)。当俯仰角接近 ±90° 时,横滚和偏航会「锁死」在一起,丢失一个自由度。我在项目中遇到过一架固定翼,做筋斗动作时姿态解算突然炸了,就是因为俯仰过了90度,欧拉角直接跳变。

避坑指南:我曾经在PX4的日志里看到欧拉角突然从 (0, 89, 0) 跳到 (180, 91, 180),以为是传感器坏了。后来才发现是万向锁导致的数值跳变。所以,做全姿态机动时,千万别只用欧拉角做内部运算。

特性 欧拉角
直观性 ★★★★★ 非常直观
计算效率 ★★★☆☆ 中等(有三角函数)
奇异性 有(万向锁)
插值 困难(角度跳变)
适用场景 人机交互、数据显示、小角度运动

2.2 旋转矩阵:数学上完美,但太「重」

旋转矩阵是一个 3×3 的正交矩阵,列向量代表机体坐标系在参考系中的投影。说白了,它把「旋转」这件事变成了矩阵乘法。

个人习惯:我一般在做坐标变换时用旋转矩阵。比如把机体加速度转换到导航系,直接一个矩阵乘法搞定,逻辑清晰,不容易出错。

旋转矩阵没有万向锁问题,可以表示任意姿态。但它有9个参数,而且必须满足正交约束(矩阵的逆等于转置)。每次更新后还得重新正交化,否则误差会累积。

// 旋转矩阵更新(陀螺仪积分)
R_new = R_old * exp(ω * dt)

// 正交化(Gram-Schmidt)
R = R * (R^T * R)^(-1/2)  // 近似做法

你想想看,每次迭代都要做矩阵乘法和正交化,计算量不小。在STM32F4这种级别的芯片上,跑100Hz的姿态解算,旋转矩阵方案能把CPU吃掉一大半。

特性 旋转矩阵
直观性 ★★☆☆☆ 不直观
计算效率 ★★☆☆☆ 较慢(9参数+正交化)
奇异性 无
插值 困难(需矩阵指数)
适用场景 坐标变换、理论推导

2.3 四元数:飞控界的「万金油」

四元数是一个超复数:q = w + xi + yj + zk,其中 w 是实部,(x, y, z) 是虚部。它用4个参数表示旋转,没有奇异性,计算效率高。

为什么飞控都用四元数?原因很简单:它既没有万向锁,计算量又小。更新姿态时只需要做四元数乘法,比旋转矩阵快得多。

四元数更新公式(陀螺仪积分):

q_new = q_old * exp(0.5 * ω * dt)
// 或者用一阶近似:
q_new = q_old + 0.5 * q_old * ω * dt

我个人习惯用四元数做姿态解算的核心。在PX4、ArduPilot这些主流飞控里,内部运算全是四元数,只在输出给地面站时才转成欧拉角。

注意:四元数必须保持单位模长(w² + x² + y² + z² = 1)。数值误差会导致模长漂移,所以每次更新后都要归一化。我曾经见过一个新手,忘了归一化,结果飞机姿态越飞越偏,最后直接翻掉。

特性 四元数
直观性 ★★☆☆☆ 不直观
计算效率 ★★★★★ 很快(4参数)
奇异性 无
插值 容易(球面线性插值SLERP)
适用场景 姿态解算、控制、滤波

2.4 三种方法对比总结

下面这张表,我建议你存下来。调参时遇到姿态问题,先看看自己用的是哪种表示方法,再对症下药。

对比项 欧拉角 旋转矩阵 四元数
参数数量 3 9 4
约束条件 无(但角度有范围) 正交性 单位模长
奇异性 有(万向锁) 无 无
计算量(更新) 低 高 低
插值平滑性 差 差 好
人机交互 好 差 差
飞控首选 ❌ ❌ ✅

2.5 知识体系:姿态表示方法全景图

下面这张图,帮你理清三种方法的关系和各自定位。红色是「不推荐用于飞控内部」,绿色是「推荐」,蓝色是「过渡桥梁」。

姿态表示方法全景图 欧拉角 (Pitch, Roll, Yaw) 旋转矩阵 (3×3 正交矩阵) 四元数 (w, x, y, z) ⚠ 万向锁 俯仰±90°时奇异 ⚠ 计算量大 9参数+正交化 ⚠ 需归一化 模长漂移 ✅ 飞控首选 ❌ 仅用于显示 转换关系:欧拉角 ↔ 旋转矩阵 ↔ 四元数(可互相转换) 实际飞控:四元数做核心运算 → 转欧拉角输出给地面站 欧拉角→四元数:q = q_yaw * q_pitch * q_roll 四元数→旋转矩阵:R = f(q) (有标准公式)

我的建议:新手先从欧拉角入手理解姿态概念,但写代码时直接用四元数。等你把四元数用熟了,再回头看看旋转矩阵的理论推导,会有更深的理解。