4. GPS_RAW_INT 消息深度解析:从结构到实战

GPS_RAW_INT 这条消息,可以说是 MAVLink 里最常用的定位数据源之一。我做了这么多年无人机,调试定位问题时第一件事就是看它。说白了,它就是飞控从 GPS 模块拿到原始数据后,打包发给地面站的那一帧信息。

今天咱们就把它拆开,看看每个字段到底在说什么。

4.1 消息 ID 与结构体

GPS_RAW_INT 的消息 ID 是 24(0x18)。你想想看,MAVLink 协议里几百条消息,ID 24 能排到这么靠前,说明它有多基础。

它的 C 语言结构体长这样:

typedef struct __mavlink_gps_raw_int_t {
    uint64_t time_usec;          // 时间戳(微秒)
    int32_t  lat;                // 纬度(度 * 1e7)
    int32_t  lon;                // 经度(度 * 1e7)
    int32_t  alt;                // 海拔高度(毫米)
    uint16_t eph;                // 水平定位精度(厘米)
    uint16_t epv;                // 垂直定位精度(厘米)
    uint16_t vel;                // 地面速度(厘米/秒)
    uint16_t cog;                // 地面航向(度 * 100)
    uint8_t  fix_type;           // 定位类型
    uint8_t  satellites_visible; // 可见卫星数
} mavlink_gps_raw_int_t;

嗯,这里要注意:lat 和 lon 的单位是 1e7 度,不是度。我见过不少新手直接拿这个数当经纬度用,结果飞机定位到太平洋中间去了。

我的习惯:收到 lat/lon 后,先除以 1e7 再使用。比如 lat = 373774000,实际纬度是 37.3774000°。

4.2 核心字段含义

咱们一个一个来过。这些字段我当年调试 Pixhawk 时,几乎天天盯着看。

4.2.1 fix_type —— 定位类型

这个字段告诉你 GPS 当前的锁定状态。它是个枚举值:

值 含义 说明
0 未定位 GPS 还没找到自己
1 无定位 有信号但解算失败
2 2D 定位 只有水平位置,没高度
3 3D 定位 水平 + 高度,最常用
4 DGPS 定位 差分 GPS,精度更高
5 RTK 浮点解 厘米级,但还不稳定
6 RTK 固定解 厘米级,稳定可用

我在项目中遇到过一件事:有一次飞机在楼群间飞,fix_type 在 2 和 3 之间来回跳。后来发现是卫星数不够,3D 解算不稳定。所以我现在看 fix_type,一定结合 satellites_visible 一起看。

4.2.2 satellites_visible —— 可见卫星数

这个字段告诉你当前有多少颗卫星被 GPS 模块捕获到。一般来说:

  • ≥ 12 颗:信号很好,可以放心飞
  • 8 - 11 颗:正常水平,大多数场景够用
  • 5 - 7 颗:勉强能用,但容易丢星
  • ≤ 4 颗:别飞了,等信号好了再说
避坑指南:我曾经遇到过卫星数显示 15 颗,但 fix_type 还是 1 的情况。后来发现是 GPS 模块的固件版本太老,卫星信号虽然收到了,但解算算法有问题。所以卫星数多 ≠ 定位好,一定要看 fix_type。

4.2.3 eph 与 epv —— 水平与垂直精度

eph 是水平定位精度(Horizontal Position Error),单位是厘米。epv 是垂直定位精度(Vertical Position Error),单位也是厘米。

这两个值越小越好。我个人的经验阈值:

  • eph ≤ 100 cm:优秀,可以执行高精度任务
  • eph 100 - 300 cm:良好,普通飞行没问题
  • eph 300 - 500 cm:一般,建议谨慎操作
  • eph > 500 cm:差,定位不可靠

你想想看,如果 eph 是 500 厘米,意味着你的飞机实际位置可能偏离 GPS 显示位置 5 米。在狭窄空间里,这足以撞墙。

4.2.4 vel —— 地面速度

vel 是地面速度(Ground Speed),单位是厘米/秒。注意,它是水平速度,不是垂直速度。

换算很简单:vel 值除以 100 就是米/秒。比如 vel = 1500,就是 15 m/s,大约 54 km/h。

我记得有一次调试,地面站显示速度一直在 0 附近跳,但飞机明明在飞。后来发现是 GPS 模块的航向更新率太低,导致速度计算不准。所以 vel 的可靠性,很大程度上取决于 GPS 的更新频率。

4.2.5 cog —— 地面航向

cog 是地面航向(Course Over Ground),单位是度 × 100。比如 cog = 4500,就是 45.00°,也就是东北方向。

这个值很重要,尤其是做航点导航时。它告诉你飞机实际在往哪个方向移动,而不是机头指向哪个方向。机头指向和实际移动方向可能不一样——有风的时候,飞机会侧着飞。

我的习惯:在日志分析时,我会把 cog 和飞机的偏航角(yaw)画在同一张图上。如果两者偏差超过 30°,说明侧风很大,需要检查导航算法。

4.3 定位质量评估

光知道每个字段的含义还不够,你得会综合评估定位质量。我总结了一个简单的评估流程:

  1. 先看 fix_type:必须 ≥ 3(3D 定位),否则后面都不用看
  2. 再看 satellites_visible:≥ 8 颗才算可靠
  3. 然后看 eph:≤ 200 cm 是安全阈值
  4. 最后看 epv:≤ 300 cm 可以接受

如果这四个条件都满足,定位质量基本没问题。如果有一个不满足,就得警惕了。

实战案例:有一次在山区测试,fix_type 一直是 3,卫星数 10 颗,但 eph 高达 800 cm。我一开始没在意,结果飞机在返航时偏离航线 6 米,差点撞树。后来分析日志发现,是因为山谷遮挡导致多路径效应严重,虽然卫星数够,但定位精度很差。从那以后,我再也不只看卫星数了。

4.4 知识体系总览

下面这张图,把 GPS_RAW_INT 的核心逻辑串起来了。你可以把它当作调试时的检查清单:

GPS_RAW_INT 定位质量评估流程 GPS_RAW_INT 消息 fix_type ≥ 3 ? (3D 定位才可用) satellites_visible ≥ 8 ? (卫星数够不够) eph ≤ 200 cm ? (水平精度够不够) epv ≤ 300 cm ? (垂直精度够不够) 定位质量合格 评估要点 • 四个条件逐级检查 • 任一不满足即告警 • 结合 vel/cog 辅助判断

这张图的核心逻辑是:逐级检查,一票否决。任何一个环节不满足,定位质量就不可靠。我建议你在写日志分析脚本时,也按这个顺序来过滤数据。

4.5 实战建议

最后,分享几个我在实际项目中总结的经验:

  • 不要只看 fix_type:3D 定位不代表精度好,一定要看 eph/epv
  • 卫星数会骗人:高楼、山谷、电磁干扰都会导致卫星数虚高但精度差
  • vel 和 cog 要联动看:如果 vel 很大但 cog 乱跳,说明 GPS 航向不稳定
  • 记录原始数据:我习惯把 GPS_RAW_INT 的所有字段都记到日志里,方便事后分析
重要提醒:GPS_RAW_INT 里的 alt 是海拔高度,不是相对高度。如果你用这个值做高度控制,一定要先减去起飞点的海拔。我曾经见过有人直接用 alt 做定高,结果飞机在坡地上越飞越高。

好了,GPS_RAW_INT 的核心内容就这些。你只要把 fix_type、satellites_visible、eph、epv、vel、cog 这六个字段吃透,定位数据的分析能力就能上一个台阶。