姿态解算算法中卡尔曼滤波的应用

你有没有遇到过这种情况:无人机飞着飞着突然“歪头”,AR眼镜里的画面开始晃动,或者手环记步时误判成你在跑步?🤔
背后的原因,往往不是传感器坏了,而是—— 姿态算错了

在现代智能设备里,我们靠IMU(惯性测量单元)感知运动。它就像设备的“内耳”,由加速度计、陀螺仪和磁力计组成。但这些传感器生来就不完美:陀螺仪积分会漂,加速度计怕动,磁力计见铁就乱……那怎么办?

答案是: 融合它们,并用数学“擦亮眼睛” 。而在这场多传感器的协奏曲中, 卡尔曼滤波 就是那个指挥家 🎼。


想象一下,你在黑暗中走路,手里拿着一个会慢慢偏离方向的指南针(陀螺仪),偶尔抬头看星星确认方位(加速度计和磁力计)。卡尔曼滤波做的,就是聪明地决定——什么时候该相信指南针,什么时候该抬头看天。

它的核心思想其实很朴素:

“我先猜一下你现在在哪(预测),再拿传感器数据看看猜得对不对(更新),然后微调我的判断。”

这个过程不断循环,每一步都只依赖上一步的结果,非常适合嵌入式系统实时运行 ✅。

对于线性系统,标准卡尔曼滤波已经足够优雅。但姿态解算是个典型的 非线性问题 ——四元数、旋转、角速度之间的关系可不是直线能描述的。于是,我们请出了两位明星选手:

  • EKF(扩展卡尔曼滤波) :把非线性函数局部线性化,用一阶泰勒展开“假装它是直的”。简单有效,工业界最爱。
  • UKF(无迹卡尔曼滤波) :不求导!通过选取一组“Sigma点”来近似分布,精度更高,尤其适合强非线性场景。

虽然UKF更准,但在STM32这类MCU上跑起来有点吃力 😓。所以大多数实际项目还是选择EKF,在性能与精度之间取得平衡。


来看看EKF是怎么工作的吧!

整个流程分为两步: 预测 → 更新

预测阶段:我来推一把

我们用陀螺仪测到的角速度推动状态前进。假设当前姿态用四元数表示 $ \mathbf{q} = [q_0, q_1, q_2, q_3] $,那么它的变化率由以下方程驱动:

$$
\dot{\mathbf{q}} = \frac{1}{2} \mathbf{q} \otimes \begin{bmatrix} 0 \ \omega_x \ \omega_y \ \omega_z \end{bmatrix}
$$

这玩意儿不能直接积分,得离散化处理。代码里通常这样写:

// 简化版预测步骤
float wx = gx - bgx;  // 减去偏置
float wy = gy - bgy;
float wz = bgz - bgz;

// 四元数微分
dq0 = 0.5f * (-wx*q1 - wy*q2 - wz*q3);
dq1 = 0.5f * ( wx*q0 - wy*q3 + wz*q2);
dq2 = 0.5f * ( wx*q3 + wy*q0 - wz*q1);
dq3 = 0.5f * (-wx*q2 + wy*q1 + wz*q0);

// 欧拉积分
q0 += dq0 * dt;
q1 += dq1 * dt;
q2 += dq2 * dt;
q3 += dq3 * dt;

// 别忘了归一化!
float norm = sqrt(q0*q0 + q1*q1 + q2*q2 + q3*q3);
q0 /= norm; q1 /= norm; q2 /= norm; q3 /= norm;

同时还要维护协方差矩阵 $ P $,反映我们对估计的信心程度。预测时它会变大——因为越猜越没底 😬。

过程噪声协方差 $ Q $ 是关键参数之一。设得太小,系统反应迟钝;设得太大,又容易被噪声带偏。建议结合Allan方差分析标定真实噪声特性。

更新阶段:传感器来“纠错”

接下来轮到加速度计和磁力计登场了。

加速度计:告诉我“哪边是下”

当设备静止或匀速运动时,加速度计主要感受重力。我们可以从当前四元数反推出理论上的加速度方向:

// 从四元数计算预期加速度(机体坐标系下)
float ex = 2*(q1*q3 - q0*q2);  // x轴分量
float ey = 2*(q0*q1 + q2*q3);  // y轴分量
float ez = q0*q0 - q1*q1 - q2*q2 + q3*q3; // z轴分量

然后和实际读数比较,得到残差 $ \mathbf{r} = \mathbf{z} - \mathbf{h}(\hat{\mathbf{x}}) $。接着构造观测雅可比矩阵 $ H $,计算卡尔曼增益 $ K $,最后修正状态。

这里有个工程技巧:可以动态调整观测噪声 $ R_{acc} $。比如检测到高加速度(如碰撞),就临时提高 $ R $,降低加速度计权重,避免误校正。

磁力计:找北靠你了

类似地,磁力计提供地磁场方向,用于修正偏航角。但我们必须小心!

室内环境常有电磁干扰(手机、电源线、钢筋结构),导致磁场扭曲。一个实用做法是加入 磁场一致性检测

float mag_norm = sqrt(mx*mx + my*my + mz*mz);
if (fabs(mag_norm - B0) > threshold) {
    // 磁场强度异常,可能是干扰
    skip_mag_update();  // 跳过本次更新
}

还可以结合水平面上的磁场投影方向,与地理北对比,估算磁偏角并补偿。


整个系统的架构通常是这样的:

[IMU] → [I²C/SPI采集] → [去噪+温补+校准]
              ↓
       [EKF核心:预测+更新]
              ↓
   [输出四元数/欧拉角] → [飞控/渲染/算法]

常见平台如 STM32、ESP32、nRF52 都能胜任。如果使用 RTOS(比如 FreeRTOS),记得给姿态任务分配合适优先级,保证定时执行。

初始化也很重要!开机时最好保持静止几秒:

  • 用加速度计平均值确定重力方向;
  • 用磁力计初值估计初始航向;
  • 归一化后作为初始四元数。

否则一开始就会“歪掉”,后续很难拉回来。


相比传统的互补滤波(固定比例融合),卡尔曼滤波最大的优势在于—— 它是自适应的

互补滤波像是一个固执的人:“我永远信陀螺仪70%,信加速度计30%。”
而卡尔曼滤波像个理性决策者:“这次加速度计抖得厉害?那我少信点;现在很平稳?那就多参考它。”

这种动态调节能力让它在复杂动态环境中表现更稳健 💪。

当然,天下没有免费午餐。EKF需要计算雅可比矩阵,涉及不少浮点运算。7×7的协方差矩阵要存49个float,在资源紧张的MCU上得精打细算。推荐使用CMSIS-DSP库做矩阵运算优化,或者手动展开小矩阵乘法提升速度。


说到这里,不得不提几个实战中的坑 ⚠️:

  • 四元数奇异性?不存在的 :选四元数而不是欧拉角,就是为了避开万向节死锁。放心大胆用!
  • 时间同步很重要 :不同传感器采样频率不同,要有时间戳对齐机制,必要时插值。
  • 温度影响不可忽视 :陀螺仪零偏随温度漂移明显,最好做温补实验,建立查表模型。
  • 安装误差也要校准 :三个传感器轴未必完全正交,需进行空间对准标定。

还有一个隐藏挑战: 数值稳定性 。协方差矩阵理论上应始终对称正定,但由于浮点误差累积,可能变得奇异。解决方案包括:
- 定期强制对称化: P = (P + P') / 2
- 使用平方根滤波(如SR-EKF),维护 $ P = S S^T $ 的形式,数值更稳定


最终效果如何?举个例子 👇

场景 表现
无人机悬停 姿态波动 < 0.5°,长时间无明显漂移
AR头部追踪 头部快速转动时无撕裂感,延迟 < 10ms
可穿戴设备步行监测 步态周期识别准确率 > 95%

这些都离不开卡尔曼滤波背后的默默支撑。


总结一下,为什么我们要在姿态解算中用卡尔曼滤波?

因为它不只是个“滤波器”,更是一个 基于概率推理的状态估计框架 。它让我们能在不确定的世界里,做出最合理的判断。

在未来,随着边缘AI的发展,我们可能会看到更多进阶玩法:
- 自适应噪声建模(NN在线估计 $ Q/R $)
- 多状态耦合滤波(联合估计姿态+位置+速度)
- 甚至用神经网络替代部分滤波模块(Learning to Filter)

但无论如何演进,卡尔曼滤波的思想—— 预测 + 观测 + 融合 ——仍将是传感器融合领域的灯塔 🌟。

所以,下次当你看到一架稳稳飞行的无人机,或一副流畅响应的VR眼镜,请记住:背后有一位“数学魔术师”正在悄然工作。🎩✨

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐