4、姿态解算:基于四元数的姿态更新算法,从传感器数据到姿态角的计算流程

各位同学,欢迎来到第四章。

这一章,我们聊聊姿态解算。说白了,就是回答一个问题:飞控板上的陀螺仪、加速度计、磁力计,这些传感器读出来的原始数据,怎么变成我们需要的横滚角、俯仰角、偏航角?

我个人习惯把姿态解算比作「搭积木」。传感器数据是零散的积木块,而四元数算法就是那个能把积木拼成完整模型的图纸。今天,我们就来拆解这张图纸。

4.1 为什么不用欧拉角?

很多初学者会问:欧拉角不是更直观吗?横滚、俯仰、偏航,多好理解。

嗯,这里要注意。欧拉角有个致命问题——万向锁。当俯仰角接近±90°时,横滚和偏航会失去一个自由度。你想想看,飞机在做筋斗动作时,如果姿态解算突然卡住,那后果……

我在项目中遇到过类似情况。早期用欧拉角做姿态解算,调试时一切正常,结果一上天,飞机做大机动动作,姿态直接崩了。后来换成四元数,问题迎刃而解。

四元数没有奇点,计算效率也高。所以,现代飞控几乎清一色用四元数。

4.2 四元数是什么?

四元数,你可以理解为一个「超复数」。它有一个实部和三个虚部:

q = w + x*i + y*j + z*k

其中,w是实部,x、y、z是虚部。i、j、k满足:

i² = j² = k² = i*j*k = -1

是不是看着有点眼熟?没错,和复数很像。只不过复数用一个虚部表示旋转,四元数用三个虚部表示三维空间旋转。

核心理解:四元数描述的是「绕某个轴旋转多少角度」。这个轴是三维空间中的任意方向向量,角度是绕该轴旋转的大小。

举个例子。绕单位向量 u = (ux, uy, uz) 旋转 θ 角度,对应的四元数是:

q = cos(θ/2) + (ux*sin(θ/2))*i + (uy*sin(θ/2))*j + (uz*sin(θ/2))*k

这个公式,就是整个姿态解算的基石。

4.3 姿态更新:从陀螺仪数据到四元数

陀螺仪输出的是角速度,单位是 rad/s。我们要做的,就是把这些角速度积分,得到姿态变化。

具体流程是这样的:

  1. 读取陀螺仪数据:得到三轴角速度 ωx、ωy、ωz
  2. 构建角速度四元数
ω_q = 0 + ωx*i + ωy*j + ωz*k
  1. 四元数微分方程
dq/dt = 0.5 * q ⊗ ω_q

这里的 ⊗ 表示四元数乘法。别怕,代码实现时就是几个乘法和加法。

  1. 离散化更新
q_new = q_old + dq/dt * Δt

或者用更精确的龙格-库塔法。我个人习惯用一阶龙格-库塔,简单够用。

避坑指南:我曾经在更新四元数后忘记归一化,结果姿态越飘越远。记住,每次更新完四元数,一定要做归一化:q = q / ||q||。否则,四元数的模长会慢慢偏离1,导致姿态失真。

4.4 从四元数到欧拉角

虽然我们用四元数做计算,但最终输出给控制算法时,还是需要欧拉角。毕竟PID控制器不认识四元数。

转换公式如下:

欧拉角计算公式
横滚角 φφ = atan2(2*(w*x + y*z), 1 - 2*(x² + y²))
俯仰角 θθ = asin(2*(w*y - z*x))
偏航角 ψψ = atan2(2*(w*z + x*y), 1 - 2*(y² + z²))

注意,atan2 是四象限反正切函数,能正确处理角度范围。asin 的值域是 [-π/2, π/2],刚好对应俯仰角的物理范围。

4.5 传感器融合:为什么需要加速度计和磁力计?

你可能会问:只用陀螺仪不行吗?

不行。陀螺仪有零偏漂移。时间一长,积分出来的姿态就会跑偏。我做过测试,纯陀螺仪积分,10秒后姿态误差就能到5°以上。

所以,我们需要用加速度计和磁力计来「修正」陀螺仪的误差。

  • 加速度计:测量重力方向。在静止或匀速运动时,它能提供横滚角和俯仰角的参考。
  • 磁力计:测量地磁场方向。它能提供偏航角的参考。

融合方法有很多,比如互补滤波、卡尔曼滤波。这里我推荐一种简单实用的方法——Mahony互补滤波

4.6 Mahony互补滤波算法流程

这个算法是我个人非常喜欢的。它简单、高效、鲁棒性好。我在多个飞控项目里都用它。

核心思想:用加速度计和磁力计的测量值,计算出一个「误差」,然后用PI控制器修正陀螺仪的角速度。

// 伪代码示例
// 1. 从加速度计得到重力方向参考
g_ref = [0, 0, 1];  // 地理坐标系下的重力方向

// 2. 用当前四元数将重力方向转到机体坐标系
g_body = q * g_ref * q_conj;

// 3. 计算误差:加速度计测量值与g_body的叉积
error_acc = acc_meas × g_body;

// 4. 类似地,用磁力计计算偏航误差
// ...(略,原理相同)

// 5. PI控制器修正角速度
omega_corrected = omega_gyro + Kp * error + Ki * ∫error dt;

// 6. 用修正后的角速度更新四元数
// ...(同4.3节步骤)

注意:加速度计不能修正偏航角。因为绕重力轴旋转时,重力方向不变。所以偏航角的修正必须依赖磁力计。如果你的环境磁场干扰严重,偏航角会飘。我曾经在室内飞无人机,旁边有根钢筋柱子,偏航角直接偏了30°。

4.7 完整计算流程图

下面这张图,把整个流程串起来了。从传感器数据输入,到姿态角输出,一目了然。

姿态解算完整流程图 陀螺仪 (ωx, ωy, ωz) 加速度计 (ax, ay, az) 磁力计 (mx, my, mz) 预处理:去零偏、低通滤波、单位转换 Mahony互补滤波融合 计算误差 → PI修正 → 修正角速度 四元数更新:dq/dt = 0.5 * q ⊗ ω_q 输出:横滚角、俯仰角、偏航角 归一化反馈

4.8 代码实现要点

最后,我分享几个代码实现时的关键点:

  • 四元数乘法:别自己手写,容易出错。用现成的库函数,或者写一个经过充分测试的函数。
  • 归一化:每次更新后必须做。我习惯在更新函数末尾加一行 q = q_normalize(q);
  • PI参数整定:Kp 决定收敛速度,Ki 决定稳态误差。我一般先调 Kp,等姿态能快速跟踪了,再加一点 Ki 消除静差。
  • 传感器同步:陀螺仪和加速度计的数据时间戳要对齐。否则融合出来的姿态会有延迟。

个人经验:调试姿态解算时,先把飞控放在桌面上静止,看姿态角是否稳定在0°附近。如果漂移,检查零偏补偿。如果抖动,检查滤波参数。如果偏航角不准,检查磁力计校准。

好了,这一章的内容就到这里。姿态解算是飞控的核心,理解了四元数更新和传感器融合,你就掌握了飞控的「大脑」。


公众号:蓝海资料掘金营,微信deep3321