4. GPS/RTK信号丢失与异常

各位同学,咱们今天聊一个飞控系统里最让人头疼的问题——GPS信号丢了怎么办。我做了这么多年飞控,说实话,GPS出问题的概率比电机烧毁高得多。你想想看,一架无人机在天上飞,突然GPS信号没了,或者位置数据开始乱跳,那感觉就像你开车时导航突然黑屏一样。

但无人机比汽车更麻烦。汽车没导航还能靠眼睛看路,无人机没了GPS,姿态不稳、位置漂移,分分钟炸机。所以,这一章我们重点解决三个问题:怎么检测GPS信号丢失、怎么处理GPS漂移和跳变、以及在没有GPS的情况下如何靠惯性导航撑住局面。

GPS/RTK信号丢失与异常处理知识体系 GPS信号异常处理 信号丢失检测 卫星颗数 < 8 HDOP > 2.0 漂移与跳变处理 速度阈值检测 位置突变过滤 INS辅助定位 IMU + 磁力计 卡尔曼滤波融合 应急悬停策略 位置保持模式 高度优先控制

4.1 GPS信号丢失检测

先说检测。GPS信号好不好,我一般看两个指标:卫星颗数和HDOP值。卫星颗数少于8颗,或者HDOP大于2.0,基本就可以判定信号不行了。但这里有个坑——卫星颗数多不代表信号就好。我记得有一次在山区测试,卫星显示12颗,但HDOP飙到了3.5,结果飞机直接飘了20米。

核心检测逻辑:

  • 卫星颗数阈值: 低于8颗触发警告,低于6颗强制切换
  • HDOP阈值: 大于2.0触发警告,大于3.0强制切换
  • 连续失效计数: 连续5帧数据异常才判定丢失,避免误触发

我个人习惯在代码里加一个滑动窗口滤波器。什么意思呢?就是取最近10帧的GPS数据做平均,如果当前帧和平均值的偏差超过3倍标准差,我就认为这帧数据有问题。这样能有效过滤掉偶尔的跳变。

// GPS信号质量检测伪代码
bool check_gps_quality(gps_data_t *gps) {
    // 卫星颗数检查
    if (gps->satellites < 6) {
        return false;  // 信号太差
    }
    
    // HDOP检查
    if (gps->hdop > 3.0) {
        return false;  // 精度太差
    }
    
    // 滑动窗口一致性检查
    static float history[10];
    static int idx = 0;
    history[idx % 10] = gps->position;
    idx++;
    
    if (idx >= 10) {
        float mean = 0, std = 0;
        for (int i = 0; i < 10; i++) mean += history[i];
        mean /= 10;
        for (int i = 0; i < 10; i++) std += pow(history[i] - mean, 2);
        std = sqrt(std / 10);
        
        if (fabs(gps->position - mean) > 3 * std) {
            return false;  // 数据跳变
        }
    }
    
    return true;
}

我的经验: 别只依赖GPS模块自带的状态标志。有些模块明明信号很差,还给你报"定位有效"。我一般会同时检查卫星信噪比(SNR),低于30dBHz的卫星直接排除。

4.2 GPS漂移与跳变处理

GPS漂移是最隐蔽的问题。它不像信号丢失那么明显,但危害更大。你想想看,飞机明明在悬停,GPS位置却在慢慢飘,飞控以为自己在移动,就会反向修正,结果越修越乱。

怎么处理?我总结了三道防线:

  1. 速度阈值检测: 如果GPS计算出的地速超过物理极限(比如固定翼超过100m/s,多旋翼超过20m/s),直接丢弃这帧数据。
  2. 位置突变过滤: 相邻两帧位置差超过5米(10Hz更新率下),判定为跳变。
  3. 加速度一致性检查: 用IMU的加速度积分出的位移和GPS位移做对比,偏差太大就说明GPS有问题。

注意: 我曾经遇到过一种情况——GPS在低空(10米以下)时,多径效应导致位置缓慢漂移。这种漂移速度很慢,速度阈值检测根本抓不到。后来我加了一个"长时间静止检测":如果IMU检测到飞机没动,但GPS位置在缓慢变化,就判定为漂移。

说白了,GPS漂移处理的核心就是"交叉验证"。用IMU验证GPS,用磁力计验证航向,用气压计验证高度。任何一个传感器都不能完全相信。

4.3 惯性导航(INS)辅助定位

GPS挂了怎么办?靠INS(惯性导航系统)撑住。INS说白了就是利用IMU(加速度计+陀螺仪)推算位置。但INS有个致命缺点——误差会随时间累积。你想想看,加速度计积分一次得到速度,再积分一次得到位置,任何微小的偏差都会被放大。

所以,INS只能作为短时替代方案。我个人建议:GPS丢失后,INS纯推算时间不要超过30秒。超过这个时间,位置误差可能已经大到无法接受。

INS辅助定位的关键技术:

  • 卡尔曼滤波融合: 在GPS正常时,用GPS校正INS的累积误差;GPS丢失后,用最后一次校正后的INS状态继续推算。
  • 磁力计辅助航向: 陀螺仪的航向漂移很快,需要用磁力计做长期校正。但磁力计容易受干扰,我一般会加一个"磁力计健康检测"。
  • 气压计辅助高度: GPS高度不可靠时,用气压计替代。气压计的短时精度其实比GPS好。
// INS辅助定位简化模型
typedef struct {
    vec3_t position;      // 位置
    vec3_t velocity;      // 速度
    quaternion_t attitude; // 姿态
} ins_state_t;

void ins_predict(ins_state_t *state, imu_data_t *imu, float dt) {
    // 加速度积分得到速度
    state->velocity += imu->accel * dt;
    // 速度积分得到位置
    state->position += state->velocity * dt;
    // 陀螺仪积分得到姿态
    state->attitude *= quaternion_from_gyro(imu->gyro, dt);
}

void ins_update_with_gps(ins_state_t *state, gps_data_t *gps) {
    // 卡尔曼增益计算(简化)
    float k = 0.1;  // 实际应用中需要动态计算
    // 用GPS校正位置和速度
    state->position += k * (gps->position - state->position);
    state->velocity += k * (gps->velocity - state->velocity);
}

避坑指南: 我曾经在INS初始化时犯过一个错误——没有等待IMU充分预热就直接开始积分。结果前10秒的加速度数据有零偏,导致后续所有位置推算都偏了。现在我的代码里一定会加一个"IMU预热检测":连续采集100帧数据,计算零偏并补偿。

4.4 应急悬停策略

当GPS彻底失效,INS也撑不住的时候,最后的保命手段就是应急悬停。但这里的"悬停"不是真的悬停——因为没有GPS,飞控不知道自己的绝对位置。所以,应急悬停的本质是"姿态保持+高度保持"。

具体怎么做?

  • 姿态模式: 切换到纯姿态模式,用陀螺仪和加速度计保持水平。这时候飞机不会漂移太远,但会随风飘。
  • 高度锁定: 用气压计锁定高度。注意气压计受温度影响很大,我一般会加一个温度补偿算法。
  • 限速保护: 限制最大倾斜角度(比如15度),防止飞机在姿态模式下失控。
  • 自动降落: 如果GPS丢失超过30秒,或者电池电量不足,直接触发自动降落。别犹豫,保飞机要紧。

重要提醒: 应急悬停不是万能的。如果风大,飞机照样会被吹走。我见过最惨的一次,飞机在5级风中GPS丢失,应急悬停模式下被吹出去200多米,最后撞树上了。所以,应急悬停只是争取时间,真正的解决方案是尽快恢复GPS信号或者手动干预。

嗯,这里要注意一点:应急悬停的触发条件不能太灵敏。我见过有些飞控,GPS信号稍微波动一下就切到应急模式,结果飞机频繁切换模式,反而更危险。我的建议是:连续5秒以上GPS不可用,再触发应急悬停。

好了,这一章的内容就这些。GPS信号处理是个系统工程,从检测到处理再到应急,每一步都不能马虎。下一章我们会聊更刺激的话题——传感器故障与冗余切换。到时候见。


专注资料整理