一、controlFusionModes() 职责
controlFusionModes() 是 EKF 中所有传感器融合的调度中心,在每步 IMU 预测后调用,负责:
- 检查各传感器 RingBuffer 是否有延迟时刻的新数据
- 判断是否满足融合前提条件(传感器健康、EKF 初始化完成等)
- 执行新息检验,决定接受或拒绝测量
- 调用具体融合函数(
aid_sources/*)执行卡尔曼更新
1 2 3 4 5 6 7 8 9 10 11 12 13
| void Ekf::controlFusionModes(const imuSample &imu_sample) { controlGpsFusion(imu_sample); controlGpsYawFusion(imu_sample); controlMagFusion(); controlHeightFusion(imu_sample); controlBaroFusion(); controlRangeFinderFusion(); controlEvFusion(); controlOpticalFlowFusion(imu_sample); controlAuxVelFusion(); controlAirspeedFusion(); controlDragFusion(); }
|
二、GPS 融合详解 controlGpsFusion()
以 GPS 为例,说明融合流程:
2.1 GPS 使能条件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| bool EKF::controlGpsFusion() { if (!_params.gnss_vel_use && !_params.gnss_pos_use) return;
gnssSample gps_sample; if (!_gps_buffer.pop_first_older_than(_time_delayed_us, &gps_sample)) return;
if (!gpsIsHealthy(gps_sample)) { stopGpsFusion(); return; }
if (_params.gnss_pos_use) { fuseGnssPos(gps_sample, _aid_src_gnss_pos); } if (_params.gnss_vel_use) { fuseGnssVel(gps_sample, _aid_src_gnss_vel); } }
|
2.2 新息检验(Innovation Gate)
在 fuseGnssPos() 内部执行新息一致性检验:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| Vector2f innov = gps_pos_local - _state.pos.xy();
Vector2f innov_var = { P(6,6) + sq(gps_sample.hacc), P(7,7) + sq(gps_sample.hacc), };
float test_ratio = (innov(0)*innov(0)/innov_var(0) + innov(1)*innov(1)/innov_var(1)) / 2.0f;
if (test_ratio > sq(_params.gps_pos_innov_gate)) { _aid_src_gnss_pos.innovation_rejected = true; if (consecutive_rejections > GPS_RESET_THRESHOLD) { resetPositionToGnss(); } return; }
measurementUpdate(_aid_src_gnss_pos, H_pos, innov, innov_var);
|
Gate 参数意义:EKF2_GPS_P_GATE = 5.0(默认)表示:若 GPS 新息超过 5σ,则拒绝该测量。调大可接受更差的 GPS,调小则对 GPS 质量要求更严。
三、高度融合仲裁 controlHeightFusion()
高度是最复杂的融合场景,需要在多个高度源之间进行仲裁和降级切换:
1 2 3 4 5 6 7 8 9 10 11 12
| flowchart TD Start["controlHeightFusion"] --> CheckAcc["checkVerticalAccelHealth<br/>检查垂直加速度健康"] CheckAcc --> GndEff["controlGroundEffect<br/>地面效应补偿"] GndEff --> BaroCtrl["controlBaroHeightFusion<br/>气压计高度"] BaroCtrl --> GnssCtrl["controlGnssHeightFusion<br/>GPS高度"] GnssCtrl --> RngCtrl["controlRangeHeightFusion<br/>测距仪高度"] RngCtrl --> EvCtrl["controlEvHeightFusion<br/>外部视觉高度"] EvCtrl --> Fallback["checkHeightSensorRefFallback<br/>高度参考自动切换"] Fallback --> CheckRef{"主参考源<br/>是否有效?"} CheckRef -->|有效| Done("[继续使用主参考]") CheckRef -->|失效| Switch["按优先级切换:<br/>1.EV → 2.测距仪 → 3.GPS → 4.气压计"] Switch --> Done
|
3.1 高度参考优先级
默认优先级(EKF2_HGT_REF 参数控制):
| 优先级 |
传感器 |
典型场景 |
| 1 |
外部视觉(EV) |
室内精确定位 |
| 2 |
测距仪 |
低空悬停/降落(<10 m) |
| 3 |
GPS 高度 |
室外绝对高度 |
| 4(默认) |
气压计 |
通用场景回退 |
3.2 地面效应补偿
近地面时旋翼下洗流导致气压计读数偏低(压力增大 → 高度显示偏低):
1 2 3 4 5 6 7
| void Ekf::controlGroundEffect() { if (_rng_sample.rng < 1.0f && _in_air) { _baro_noise_var_compensated = sq(_params.baro_noise * _params.gnd_effect_baro_scaler); } }
|
四、磁力计融合 controlMagFusion()
磁力计融合的工作模式由 EKF2_MAG_TYPE 参数控制:
| 模式 |
值 |
说明 |
| 自动 |
0 |
室外用 3D 磁场融合,室内/干扰大时切换为仅航向 |
| 仅航向 |
1 |
仅约束 yaw,不估计地球磁场矢量 |
| 3D 磁场 |
2 |
完整估计地球磁场(NED)+ 机体磁偏差 |
| 无磁力计 |
5 |
依赖双天线 GPS 或外部视觉提供航向 |
室外飞行时,3D 磁场融合同时约束:
- 航向 yaw(主要贡献)
- 地球磁场方向估计(提高后续磁力计一致性)
- 机体磁偏差(校准磁铁干扰)
五、外部视觉(EV)融合
controlEvFusion() 支持 4 种信息的独立融合:
| 子函数 |
话题字段 |
融合内容 |
controlEvPosFusion() |
pos |
本地 NED 位置(MoCap/VIO) |
controlEvVelFusion() |
vel |
机体或 NED 速度 |
controlEvHeightFusion() |
pos.z |
高度 |
controlEvYawFusion() |
yaw(从 q 提取) |
航向角 |
EV 数据(vehicle_visual_odometry)延迟通常较大(EKF2_EV_DELAY 默认 175 ms),因此 RingBuffer 需要设置较大深度。
六、小结
control.cpp 是 EKF 的决策层,其核心逻辑:
- 多传感器异步调度:各传感器按各自频率独立触发,互不阻塞
- 新息门检验:统一的 NIS 检验机制,异常测量自动拒绝
- 状态重置:连续拒绝超过阈值时执行状态跳变,防止长期漂移
- 高度源仲裁:优先级驱动的自动降级,保证高度估计在任意传感器失效时的鲁棒性
这一层的参数调优(各 *_GATE 参数、EKF2_HGT_REF、EKF2_MAG_TYPE)直接影响飞行稳定性和故障恢复能力。
上一篇:协方差矩阵预测
下一篇:高度融合与多源仲裁
系列总目录:PX4 v1.16 源码解读总目录