1. 姿态解算基础概念与iNav实现概述
姿态解算是无人机飞控系统的核心算法之一,它通过处理来自多种传感器的数据,实时计算出飞行器在三维空间中的姿态角度(横滚、俯仰、偏航)。iNavFlight飞控采用的DCM(方向余弦矩阵)算法本质上是对Mahony算法的优化实现,主要融合了以下传感器数据:
- 陀螺仪:提供角速度信息,用于短期姿态预测
- 加速度计:测量重力向量,用于校正横滚和俯仰角
- 磁力计:感知地磁场方向,用于校正偏航角(航向)
- GPS:提供地面航向(COG)和地磁偏角信息,作为磁力计的补充
在实际飞行中,这些传感器各有优缺点:陀螺仪短期精度高但存在漂移;加速度计在静态时准确但易受机动加速度干扰;磁力计易受电磁干扰;GPS航向在高速时可靠但低速时噪声大。iNav通过智能加权融合策略,使系统在不同飞行状态下都能获得稳定的姿态估计。
关键设计思想:DCM算法通过构建机体坐标系与地球坐标系之间的旋转矩阵,将不同传感器的测量值转换到统一参考系进行比较和校正,这种思路比直接处理欧拉角更稳定,避免了万向节锁问题。
2. 姿态解算代码架构解析
2.1 主循环与任务调度
姿态解算在1ms周期的PID任务中执行,这是飞控实时性的关键保证。代码结构如下:
c复制[TASK_PID] = {
.taskName = "PID",
.taskFunc = taskMainPidLoop, // 主控制循环
.desiredPeriod = TASK_PERIOD_US(1000), // 1ms周期
.staticPriority = TASK_PRIORITY_REALTIME, // 实时优先级
},
在taskMainPidLoop函数中,姿态解算主要涉及三个关键步骤:
c复制gyroFilter(); // 陀螺仪数据滤波
imuUpdateAccelerometer(); // 加速度计数据更新
imuUpdateAttitude(currentTimeUs); // 姿态解算核心
这种分层处理体现了传感器数据处理的典型模式:原始数据滤波→物理量转换→算法融合。
2.2 姿态解算核心流程
imuUpdateAttitude函数完成以下工作:
- 计算时间间隔dT(用于积分运算)
- 获取陀螺仪角速度(rad/s)和加速度(cm/s²)
- 调用
imuCalculateEstimatedAttitude进行传感器融合
特别值得注意的是振动检测环节imuCheckVibrationLevels(),它通过分析加速度计数据的高频成分来评估飞行器振动水平,这对多旋翼的飞行稳定性至关重要。
3. 多传感器融合算法深度解析
3.1 传感器数据预处理
在进入融合算法前,各传感器数据需要统一到机体坐标系:
c复制gyroGetMeasuredRotationRate(&imuMeasuredRotationBF); // 机体坐标系角速度
accGetMeasuredAcceleration(&imuMeasuredAccelBF); // 机体坐标系加速度
对于磁力计数据,还需要考虑硬铁和软铁校准:
c复制fpVector3_t measuredMagBF = {.v = {mag.magADC[X], mag.magADC[Y], mag.magADC[Z]}};
3.2 Mahony算法实现细节
imuMahonyAHRSupdate是融合算法的核心,采用分步校正策略:
偏航角校正(Yaw Correction)
c复制// 磁力计校正
quaternionRotateVectorInv(&vMag, magBF, &orientation); // 机体→地球系
vMag.z = 0; // 忽略磁倾角
vectorCrossProduct(&vMagErr, &vMag, &vCorrectedMagNorth); // 计算误差
// GPS航向校正
fpVector3_t vCoG = {.v = {-cos_approx(courseOverGround), sin_approx(courseOverGround), 0}};
vectorCrossProduct(&vCoGErr, &vCoG, &vHeadingEF); // GPS航向误差
校正权重根据传感器可靠性动态调整:
- 磁力计权重受磁场强度影响(
bellCurve函数) - GPS权重与速度成正比(低速时权重降低)
横滚/俯仰校正(Roll/Pitch Correction)
c复制quaternionRotateVector(&vEstGravity, &vGravity, &orientation); // 地球→机体系
vectorCrossProduct(&vErr, &vAcc, &vEstGravity); // 加速度计误差
加速度计权重考虑了两个因素:
- 接近静态条件(
imuCalculateAccelerometerWeightNearness) - 机动加速度影响(
imuCalculateAccelerometerWeightRateIgnore)
陀螺仪偏差补偿
采用PI控制器消除陀螺仪零偏:
c复制// 比例项
vectorScale(&vErr, &vErr, imuRuntimeConfig.dcm_kp_mag * magWScaler);
// 积分项
vectorScale(&vTmp, &vErr, imuRuntimeConfig.dcm_ki_mag * magWScaler * dt);
vectorAdd(&vGyroDriftEstimate, &vGyroDriftEstimate, &vTmp);
积分项设有抗饱和限制(Anti wind-up),防止过度累积:
c复制float i_limit = DEGREES_TO_RADIANS(2.0f) * (imuRuntimeConfig.dcm_kp_acc + imuRuntimeConfig.dcm_kp_mag) / 2.0f;
vGyroDriftEstimate.x = constrainf(vGyroDriftEstimate.x, -i_limit, i_limit);
3.3 四元数更新与归一化
校正后的角速度用于更新四元数:
c复制vectorScale(&vTheta, &vRotation, 0.5f * dt); // 角速度积分
quaternionInitFromVector(&deltaQ, &vTheta); // 构造增量四元数
// 小角度近似(泰勒展开)
if (thetaMagnitudeSq < fast_fsqrtf(24.0f * 1e-6f)) {
quaternionScale(&deltaQ, &deltaQ, 1.0f - thetaMagnitudeSq/6.0f);
deltaQ.q0 = 1.0f - thetaMagnitudeSq/2.0f;
} else {
// 标准四元数更新
quaternionScale(&deltaQ, &deltaQ, sin_approx(thetaMagnitude)/thetaMagnitude);
deltaQ.q0 = cos_approx(thetaMagnitude);
}
quaternionMultiply(&orientation, &orientation, &deltaQ); // 四元数乘法
quaternionNormalize(&orientation, &orientation); // 归一化
4. 姿态数据输出与应用
4.1 欧拉角计算
通过旋转矩阵计算横滚、俯仰、偏航角:
c复制attitude.values.roll = RADIANS_TO_DECIDEGREES(atan2_approx(rMat[2][1], rMat[2][2]));
attitude.values.pitch = RADIANS_TO_DECIDEGREES((0.5f * M_PIf) - acos_approx(-rMat[2][0]));
attitude.values.yaw = RADIANS_TO_DECIDEGREES(-atan2_approx(rMat[1][0], rMat[0][0]));
4.2 旋转矩阵计算
从四元数到旋转矩阵的转换:
c复制rMat[0][0] = 1.0f - 2.0f * q2q2 - 2.0f * q3q3;
rMat[0][1] = 2.0f * (q1q2 + -q0q3);
rMat[0][2] = 2.0f * (q1q3 - -q0q2);
// ... 其他矩阵元素
4.3 与APM的姿态表示对比
虽然iNav和APM使用相同的算法核心,但存在以下差异:
- 俯仰角符号:iNav地面站显示时对原始数据取反
- 坐标系定义:需注意不同飞控对机体坐标系的定义可能不同
- 传感器融合策略:iNav对GPS航向的融合权重处理更为精细
5. 实战经验与调优建议
5.1 参数调优指南
关键参数在imuRuntimeConfig结构中:
c复制typedef struct {
float dcm_kp_acc; // 加速度计比例增益
float dcm_ki_acc; // 加速度计积分增益
float dcm_kp_mag; // 磁力计比例增益
float dcm_ki_mag; // 磁力计积分增益
uint8_t inertia_comp_method; // 离心力补偿方法
} imuRuntimeConfig_t;
调参建议:
- 默认值启动:先使用默认参数测试基本性能
- 比例增益调整:
- 增大
dcm_kp_acc可增强加速度计校正力度,但过高会导致振动敏感 dcm_kp_mag通常设为dcm_kp_acc的1/5到1/10
- 增大
- 积分增益调整:
dcm_ki_acc用于消除陀螺仪零偏,典型值0.001-0.01- 磁力计积分项
dcm_ki_mag通常更小
5.2 常见问题排查
问题1:飞行中偏航角漂移
- 检查磁力计校准质量
- 确认飞行环境无强电磁干扰
- 适当增加
dcm_kp_mag和dcm_ki_mag
问题2:快速机动时姿态异常
- 检查加速度计动态范围设置
- 调整
imuCalculateAccelerometerWeightRateIgnore参数 - 考虑启用离心力补偿(
inertia_comp_method)
问题3:振动导致姿态抖动
- 改进机械减震
- 检查
imuCheckVibrationLevels()输出 - 适当降低
dcm_kp_acc
5.3 性能优化技巧
-
计算优化:
- 使用快速近似函数(如
sin_approx、cos_approx) - 避免实时计算中的动态内存分配
- 利用STM32的FPU和DSP指令
- 使用快速近似函数(如
-
传感器时序:
- 确保陀螺仪和加速度计数据时间对齐
- 对于SPI接口的IMU,使用突发模式读取
-
异常处理:
- 实现四元数有效性检查(
imuCheckAndResetOrientationQuaternion) - 添加传感器失效检测和故障恢复机制
- 实现四元数有效性检查(
6. 算法理论延伸与比较
6.1 DCM与四元数的关系
DCM算法虽然名称涉及方向余弦矩阵,但在iNav实现中实际使用四元数表示姿态,因为:
- 四元数只有4个参数,比DCM的9个更高效
- 避免了欧拉角的万向节锁问题
- 插值和更新运算更简单
旋转矩阵rMat是从四元数派生的,主要用于:
- 欧拉角计算
- 坐标转换
- 控制算法中的力矩分配
6.2 与其他算法的对比
Mahony vs Madgwick:
- Mahony(iNav采用):基于PI补偿,参数物理意义明确
- Madgwick:梯度下降法,计算量略低
互补滤波 vs 卡尔曼滤波:
- iNav的DCM属于互补滤波,计算量小,适合资源受限平台
- 卡尔曼滤波(如PX4的EKF2)更复杂但能处理传感器不确定性
6.3 地磁处理进阶
iNav对地磁数据的特殊处理包括:
- 磁倾角忽略:
vMag.z = 0简化了北向计算 - 硬铁补偿:通过校准消除固定磁场偏差
- 动态权重:根据磁场强度和变化率调整可信度
对于高纬度地区飞行,可能需要修改磁倾角处理策略。