905 字
5 分钟
高精度 IMU 姿态解算:基于 ICM-20602 的四元数与梯度下降滤波实现

1. 姿态解算概述#

姿态解算(Attitude Algorithm)是平衡车、无人机及穿戴式设备的核心。ICM-20602 是一款高性能的 6 轴运动跟踪器件,包含三轴陀螺仪和三轴加速度计。

单纯依靠陀螺仪积分会产生累积误差,而单纯依靠加速度计则在高频振动下极其不稳定。本程序采用四元数算法融合两者数据,并引入**梯度下降法(Steepest Descent)**进行预处理滤波,以获得平滑且精准的欧拉角(Pitch, Roll, Yaw)。


2. 算法核心步骤#

  1. 数据采集与去零偏:校准陀螺仪静态漂移。
  2. 梯度下降滤波:针对陀螺仪噪声进行最速下降法优化,寻找最优数据点。
  3. 四元数更新:利用角速度对四元数进行微分方程积分。
  4. 互补纠正:利用加速度计重力向量纠正陀螺仪的积分漂移。
  5. 欧拉角转换:将四元数转换为直观的角度值。

3. 核心代码实现#

3.1 零偏校正 (Gyro Offset)#

在系统启动时保持静止,采集 500 次数据求平均值,这是后续积分不漂移的基础。

#define OFFSET_COUNT 500
void IMU_offset(GYRO_VAR *gyro_var) {
int64_t temp[6] = {0};
for (uint32_t i = 0; i < OFFSET_COUNT; i++) {
icm20602_get_data(gyro_var);
systick_delay_ms(2);
temp[0] += gyro_var->orig.acc.x; // ... 累加六轴数据
// ... (省略重复累加代码)
}
gyro_var->fiter.gyro_offset.x = temp[3] / OFFSET_COUNT;
gyro_var->fiter.offset_flag = 1; // 校准完成标志
}

3.2 快速平方根算法 (InvSqrt)#

姿态解算中需要大量的归一化计算,使用经典的 0x5f3759df 魔法数算法可极大节省单片机算力。

float my_sqrt(float number) {
long i;
float x, y;
x = number * 0.5F;
y = number;
i = *(long*)&y;
i = 0x5f3759df - (i >> 1); // 经典的雷神之锤快速平方根倒数算法
y = *(float*)&i;
y = y * (1.5F - (x * y * y)); // 牛顿迭代法
return number * y;
}

3.3 四元数姿态融合 (Mahony 简化版)#

通过加速度计补偿陀螺仪的积分误差,确保静态工况下的绝对精度。

void Q_IMUupdata(GYRO_VAR *gyro_var) {
static float q0 = 1, q1 = 0, q2 = 0, q3 = 0;
float acc_length;
_xyz_f_st acc_norm, vec_err;
// 1. 加速度归一化
acc_length = my_sqrt(pow(acc.x,2) + pow(acc.y,2) + pow(acc.z,2));
acc_norm.x = acc.x / acc_length;
// ... (处理 y, z)
// 2. 提取四元数中的重力分量 (z轴向量)
_xyz_f_st z_vec = { 2*(q1*q3 - q0*q2), 2*(q2*q3 + q0*q1), 1-2*(q1*q1 + q2*q2) };
// 3. 向量外积计算误差(重力向量与加速度计向量的偏差)
vec_err.x = acc_norm.y * z_vec.z - z_vec.y * acc_norm.z;
// ... (处理 y, z)
// 4. 利用 PI 控制器融合误差并更新四元数
// d_angle = (Gyro + Kp * vec_err + Ki * vec_err_i) * dT / 2
// ... (更新四元数 q0-q3)
// 5. 欧拉角转换
gyro_var->euler.pit = asin(2 * q1 * q3 - 2 * q0 * q2) * 57.3f;
gyro_var->euler.roll = atan2(2 * q2 * q3 + 2 * q0 * q1, -2 * q1 * q1 - 2 * q2 * q2 + 1) * 57.3f;
}

4. 调试经验总结#

  1. 采样频率:姿态解算的周期(dT)必须恒定。建议放在定时器中断中运行(如 200Hz 或 500Hz)。
  2. 加速度计限幅:在设备剧烈震动时,加速度计数据不可信,应通过 limit_filter 减小其权重,防止干扰姿态。
  3. 安装方向:注意传感器的坐标系()与设备坐标系的一致性,否则 atan2 计算出的 Roll 和 Pitch 会反向。

5. 开源建议#

本项目代码已在 STM32F4/F1 系列及 K60 开发板上验证通过。如果您在调试过程中发现 Yaw 轴漂移严重,请检查是否引入了磁力计(HMC5883L 等)进行航向校正。

高精度 IMU 姿态解算:基于 ICM-20602 的四元数与梯度下降滤波实现
https://hw.rscclub.website/posts/icm20602/
作者
杨月昌
发布于
2017-01-23
许可协议
CC BY-NC-SA 4.0