4. MAVLink协议基础:消息结构与定位相关消息

说到MAVLink,很多刚接触飞控的朋友会觉得它很神秘。其实说白了,它就是无人机和地面站之间沟通的“语言”。我最早接触MAVLink是在一次野外试飞中,飞机在天上飘,地面站数据却死活不对。后来一查,原来是消息解析出了问题。从那以后,我就把MAVLink协议翻了个底朝天。

这一章,我们就来聊聊MAVLink的消息结构,以及和定位漂移排查最相关的三条消息:GPS_RAW_INT、GLOBAL_POSITION_INT、VISION_POSITION_ESTIMATE。

4.1 MAVLink消息结构

MAVLink的消息结构其实不复杂。每个消息就是一个数据包,里面装着各种字段。我习惯把它想象成一个快递包裹:有包裹头、包裹体、还有校验码。

标准的MAVLink v2消息结构如下:

| 起始标志 | 负载长度 | 不兼容标志 | 兼容标志 | 序列号 | 系统ID | 组件ID | 消息ID | 负载数据 | 校验和 |
|  0xFD   |   1字节  |   1字节   |   1字节  | 1字节  | 1字节  |  1字节  |  3字节  | 0-255字节| 2字节  |

嗯,这里要注意几个关键字段:

  • 起始标志:0xFD表示MAVLink v2,0xFE表示v1。我建议新项目直接用v2,兼容性更好。
  • 消息ID:3字节,范围0~16777215。每个消息类型都有唯一的ID。比如GPS_RAW_INT的ID是24。
  • 负载数据:就是消息体,里面装着具体的数据字段。
  • 校验和:用于检测数据是否被篡改或损坏。
我的小技巧:排查定位漂移时,我经常先看校验和。如果校验和频繁出错,说明通信链路有问题,数据本身可能已经损坏。这时候别急着分析定位数据,先修通信。

4.2 常用定位相关消息

在定位漂移排查中,有三条消息我几乎每次都会看。它们分别来自不同的传感器源,对比着看,问题往往一目了然。

4.2.1 GPS_RAW_INT(原始GPS数据)

这条消息直接来自GPS模块。它包含最原始的GPS观测值,未经飞控融合处理。

字段名 类型 说明
lat int32_t 纬度,单位:度×10^7
lon int32_t 经度,单位:度×10^7
alt int32_t 海拔高度,单位:毫米
eph uint16_t 水平定位精度(HDOP×100),越小越好
epv uint16_t 垂直定位精度(VDOP×100),越小越好
fix_type uint8_t 定位类型:0=无,1=无定位,2=2D,3=3D,4=RTK浮点,5=RTK固定
satellites_visible uint8_t 可见卫星数

我个人排查漂移时,第一步就是看fix_type和satellites_visible。如果fix_type小于3,或者卫星数少于8颗,GPS本身就不靠谱。这时候漂移是正常的,不漂才怪。

注意:lat和lon的单位是度×10^7。比如纬度39.9087度,在消息里是399087000。解析时别忘了除以10^7,否则位置会飞到天上去。我曾经见过一个新手,忘了转换单位,结果飞机显示在非洲,实际在北京。

4.2.2 GLOBAL_POSITION_INT(飞控融合后的位置)

这条消息是飞控融合了GPS、IMU、磁力计等传感器后的结果。它比GPS_RAW_INT更平滑,也更常用。

字段名 类型 说明
lat int32_t 纬度,单位:度×10^7
lon int32_t 经度,单位:度×10^7
alt int32_t 海拔高度,单位:毫米
relative_alt int32_t 相对起飞点高度,单位:毫米
vx int16_t X方向速度(cm/s),通常指向北
vy int16_t Y方向速度(cm/s),通常指向东
vz int16_t Z方向速度(cm/s),向下为正
hdg uint16_t 航向角,单位:度×100(0~35999)

为什么我强调要看这条消息?因为它反映了飞控“认为”飞机在哪里。如果GLOBAL_POSITION_INT和GPS_RAW_INT差异很大,说明飞控的融合算法可能有问题,或者IMU数据有漂移。

举个例子:有一次我排查一架飞机的悬停漂移问题。日志里GPS_RAW_INT的eph只有0.5米,精度很好。但GLOBAL_POSITION_INT却在缓慢漂移。后来发现是加速度计零偏没校准好,融合算法把IMU的误差当成了真实运动。

4.2.3 VISION_POSITION_ESTIMATE(视觉定位数据)

这条消息来自视觉里程计(VO)或视觉惯性里程计(VIO)系统。它通常由机载计算机(如NVIDIA Jetson)发布,飞控接收后用于辅助定位。

字段名 类型 说明
usec uint64_t 时间戳,单位:微秒
x float X方向位置,单位:米(通常指向北)
y float Y方向位置,单位:米(通常指向东)
z float Z方向位置,单位:米(向下为正)
covariance float[21] 协方差矩阵的上三角部分,用于表示不确定性
关键点:视觉定位数据是局部坐标系,不是全球坐标系。飞控需要把它和GPS对齐,才能融合使用。如果对齐参数(如视觉位置偏移)设置不对,漂移会非常明显。

我遇到过最头疼的一次漂移,就是视觉定位的坐标系和GPS坐标系没对齐。飞机在视觉定位下看起来稳稳的,但GPS位置却在乱跳。后来发现是视觉里程计初始化时,起始位置和GPS差了2米。飞控融合时,两个位置互相拉扯,结果就是漂移。

4.3 三条消息的对比与使用场景

为了让你更清楚它们的区别,我整理了一个对比表:

消息 数据来源 坐标系 主要用途 漂移排查中的角色
GPS_RAW_INT GPS模块 全球坐标系(WGS84) 原始GPS观测 判断GPS本身是否可靠
GLOBAL_POSITION_INT 飞控融合 全球坐标系(WGS84) 飞控输出的最终位置 判断飞控融合是否正常
VISION_POSITION_ESTIMATE 视觉里程计 局部坐标系 视觉辅助定位 判断视觉定位是否漂移

你想想看,如果GPS本身没问题(GPS_RAW_INT正常),但飞控输出的位置在漂移(GLOBAL_POSITION_INT异常),那问题大概率出在IMU或融合算法上。反过来,如果GPS本身就不准,那再怎么调融合算法也没用。

4.4 知识体系图

下面这张图展示了MAVLink定位消息在飞控系统中的位置和关系。我建议你把它保存下来,排查漂移时对照着看。

MAVLink定位消息关系图 MAVLink定位消息关系图 GPS模块 原始卫星数据 IMU(加速度计+陀螺仪) 惯性测量数据 视觉里程计 相机图像数据 GPS_RAW_INT 消息ID: 24 GLOBAL_POSITION_INT 消息ID: 33 VISION_POSITION_ESTIMATE 消息ID: 102 飞控EKF融合算法 融合GPS + IMU + 视觉 最终位置输出 用于控制、导航、日志记录 排查漂移时 对比这三条消息 定位问题源

从这张图你可以看到:GPS模块输出GPS_RAW_INT,IMU数据被飞控内部使用(不直接通过MAVLink输出),视觉里程计输出VISION_POSITION_ESTIMATE。这三路数据进入飞控的EKF融合算法,最终输出GLOBAL_POSITION_INT。

排查漂移时,我的习惯是:先看GPS_RAW_INT的fix_type和eph,确认GPS是否可靠。然后看VISION_POSITION_ESTIMATE的协方差,判断视觉定位是否稳定。最后对比GLOBAL_POSITION_INT和GPS_RAW_INT,看融合结果是否合理。

避坑指南:我曾经遇到过VISION_POSITION_ESTIMATE的时间戳和飞控时间不同步,导致融合结果剧烈抖动。排查了三天才发现是时间戳单位搞错了——视觉里程计用的是毫秒,飞控期望的是微秒。所以,检查时间戳单位也是排查漂移的重要一步。