4、MAVLink协议入门:MAVLink消息格式、常用消息(HEARTBEAT, ATTITUDE, GPS_RAW_INT等)、消息频率与数据流

MAVLink(Micro Air Vehicle Link)是PX4与地面站、机载计算机、其他无人机之间通信的“通用语言”。它诞生于2009年,最初用于APM和PX4项目,如今已成为无人机生态中最主流的开源通信协议。理解MAVLink,是打通“飞控感知世界”与“AI决策控制”之间数据通道的关键一步。本章将从消息的二进制结构出发,剖析HEARTBEAT、ATTITUDE、GPS_RAW_INT等核心消息的字段含义,并讲解如何通过数据流控制来高效获取所需信息,避免带宽浪费和通信拥堵。

① 消息封装层 ② 核心消息解析 ③ 数据流控制 MAVLink v2 帧结构 STX | LEN | SEQ | SYS_ID | COMP_ID 消息ID + 负载 MSG_ID (0-16777215) | PAYLOAD 校验与填充 CRC_EXTRA | CHECKSUM | SIGNATURE 关键点 CRC_EXTRA 用于校验消息格式 签名用于安全认证(可选) HEARTBEAT (ID=0) 心跳:类型、状态、自定义模式 ATTITUDE (ID=30) 姿态:roll/pitch/yaw + 角速度 GPS_RAW_INT (ID=24) GPS:经纬度、高度、速度、精度 LOCAL_POSITION_NED (ID=32) 本地位置:XYZ + 速度(AI常用) 消息频率控制 STREAM_RATE / REQUEST_DATA_STREAM 数据流分组 STANDARD / EXTENDED / EXTRA1/2/3 带宽估算 ATTITUDE 30Hz ≈ 900 B/s AI应用建议 订阅所需消息,关闭不必要流 MAVLink 数据链路:从二进制帧到AI可用的结构化数据

上图展示了MAVLink通信的三个核心层次:消息封装层、核心消息解析和数据流控制。在PX4 AI开发中,我们通常使用pymavlink或MAVSDK库来屏蔽底层帧解析细节,但理解帧结构对排查通信问题至关重要。接下来,我们将逐一深入这些层次。

4.1 MAVLink消息格式:从字节流到结构化数据

核心原理:MAVLink v2帧结构

MAVLink v2是当前PX4默认使用的版本,其帧结构比v1更灵活,支持24位消息ID和消息签名。一个完整的MAVLink v2帧包含以下字段:

字段长度(字节)说明
STX1帧起始标志,v2固定为0xFD
LEN1负载长度(0-255字节)
SEQ1序列号,用于检测丢包
SYS_ID1系统ID,区分不同飞行器(通常为1)
COMP_ID1组件ID,区分同一系统内的不同模块(如飞控=1,相机=100)
MSG_ID3消息ID,v2支持0-16777215
PAYLOAD0-255消息负载,具体内容由MSG_ID决定
CRC_EXTRA1消息格式校验码,用于验证消息定义是否匹配
CHECKSUM2CRC16校验值,覆盖整个帧
SIGNATURE0-13可选签名,用于安全认证

对于AI开发者而言,最需要关注的是MSG_ID和PAYLOAD。例如,当你在pymavlink中调用msg = master.recv_match(type='ATTITUDE')时,底层库已经完成了帧解析、CRC校验和字段提取,你直接访问msg.roll、msg.pitch即可。

经验提醒:在调试通信问题时,使用mavlink-inspector或Wireshark的MAVLink解析插件,可以直观看到每个帧的原始字节和解析后的字段。这比直接打印Python对象更能定位问题。

判断方法:如何识别消息类型

每个MAVLink消息都有一个唯一的MSG_ID。在PX4中,常用消息ID如下:

  • 0:HEARTBEAT(心跳)
  • 24:GPS_RAW_INT(GPS原始数据)
  • 30:ATTITUDE(姿态四元数/欧拉角)
  • 32:LOCAL_POSITION_NED(本地位置)
  • 33:GLOBAL_POSITION_INT(全局位置)
  • 65:RC_CHANNELS(遥控器通道)
  • 74:VFR_HUD(空速、地速、高度)

在pymavlink中,你可以通过msg.get_type()获取消息类型字符串,或通过msg.msgid获取数字ID。推荐使用字符串类型,因为可读性更好。

4.2 常用消息详解:HEARTBEAT、ATTITUDE、GPS_RAW_INT

核心原理:三类消息的用途与字段

HEARTBEAT(ID=0)是所有MAVLink通信的基础。它以固定频率(通常1Hz)发送,用于宣告设备在线状态和类型。其关键字段包括:

  • type:设备类型(如MAV_TYPE_QUADROTOR=2)
  • autopilot:飞控类型(如MAV_AUTOPILOT_PX4=12)
  • base_mode:飞行模式标志位(如MAV_MODE_FLAG_SAFETY_ARMED=128)
  • custom_mode:自定义模式,PX4中用于表示具体的飞行模式(如OFFBOARD=6)
  • system_status:系统状态(如STANDBY=4, ACTIVE=5)

ATTITUDE(ID=30)是AI视觉导航最常用的消息之一,以10-30Hz频率发送。它包含:

  • time_boot_ms:开机以来的毫秒数
  • roll、pitch、yaw:欧拉角(弧度),表示机体相对于NED坐标系
  • rollspeed、pitchspeed、yawspeed:角速度(rad/s)

GPS_RAW_INT(ID=24)提供GPS原始数据,频率通常为5-10Hz。关键字段:

  • lat、lon:经纬度(1e7度为单位,即除以1e7得到度数)
  • alt:海拔高度(毫米)
  • eph、epv:水平/垂直定位精度(厘米)
  • fix_type:定位类型(0=无, 2=2D, 3=3D, 4=RTK固定)
  • vel:地面速度(cm/s)
常见陷阱:GPS_RAW_INT的经纬度是整数类型,需要除以1e7才能得到浮点度数。很多初学者直接使用原始值,导致位置计算错误。同样,alt单位是毫米,不是米。

操作流程:在pymavlink中订阅消息

from pymavlink import mavutil

# 连接飞控(串口或UDP)
master = mavutil.mavlink_connection('udp:127.0.0.1:14550')
master.wait_heartbeat()
print("飞控已连接,系统ID:", master.target_system)

# 请求数据流(以10Hz发送ATTITUDE)
master.mav.request_data_stream_send(
    master.target_system, master.target_component,
    mavutil.mavlink.MAV_DATA_STREAM_EXTRA1,  # EXTRA1包含ATTITUDE
    10,  # 频率Hz
    1    # 开始发送
)

# 循环接收消息
while True:
    msg = master.recv_match(type=['ATTITUDE', 'GPS_RAW_INT'], blocking=True)
    if msg.get_type() == 'ATTITUDE':
        print(f"Roll: {msg.roll:.3f} rad, Pitch: {msg.pitch:.3f} rad, Yaw: {msg.yaw:.3f} rad")
    elif msg.get_type() == 'GPS_RAW_INT':
        lat = msg.lat / 1e7
        lon = msg.lon / 1e7
        print(f"GPS: {lat:.7f}, {lon:.7f}, Alt: {msg.alt/1000:.2f} m")

4.3 消息频率与数据流控制

核心原理:MAVLink数据流分组

PX4将消息分为多个数据流组,每个组可以独立设置发送频率。常用分组如下:

数据流组包含消息典型频率
MAV_DATA_STREAM_RAW_SENSORSIMU原始数据、气压计、磁力计50-100Hz
MAV_DATA_STREAM_EXTENDED_STATUS电池状态、飞行模式2-5Hz
MAV_DATA_STREAM_EXTRA1ATTITUDE、姿态角速度10-30Hz
MAV_DATA_STREAM_EXTRA2VFR_HUD(空速、高度)5-10Hz
MAV_DATA_STREAM_EXTRA3GPS_RAW_INT、HOME_POSITION5-10Hz
MAV_DATA_STREAM_POSITIONLOCAL_POSITION_NED、GLOBAL_POSITION_INT10-30Hz

在AI应用中,我们通常只需要ATTITUDE(用于图像配准)和LOCAL_POSITION_NED(用于位置控制)。如果同时订阅所有数据流,会浪费大量串口带宽,甚至导致消息延迟。

案例拆解:AI视觉避障系统的数据流优化

背景与约束:某PX4无人机搭载Jetson Nano进行实时视觉避障,通过串口(波特率921600)与飞控通信。初始阶段,开发者直接使用QGroundControl的默认数据流设置,导致串口带宽占用超过80%,视觉处理帧率下降。

初始现象:视觉程序每帧处理时间从30ms增加到60ms,且偶尔出现MAVLink消息丢失(SEQ跳变)。

分析过程:

  1. 使用mavlink-inspector统计各消息频率,发现IMU原始数据以100Hz发送,占用大量带宽。
  2. 计算带宽:IMU消息约50字节×100Hz=5000B/s,ATTITUDE约28字节×30Hz=840B/s,GPS约36字节×10Hz=360B/s。总带宽约6.2KB/s,而921600波特率实际有效带宽约92KB/s,看似不拥挤,但串口协议开销和系统调度导致实际可用带宽更低。
  3. 进一步发现,QGroundControl默认开启了所有数据流,包括不常用的DEBUG消息。

优化操作:

# 关闭所有数据流
master.mav.request_data_stream_send(
    master.target_system, master.target_component,
    mavutil.mavlink.MAV_DATA_STREAM_ALL, 0, 0
)

# 仅开启所需数据流
master.mav.request_data_stream_send(
    master.target_system, master.target_component,
    mavutil.mavlink.MAV_DATA_STREAM_EXTRA1, 30, 1  # ATTITUDE 30Hz
)
master.mav.request_data_stream_send(
    master.target_system, master.target_component,
    mavutil.mavlink.MAV_DATA_STREAM_POSITION, 20, 1  # 位置 20Hz
)

结果对比:优化后,串口带宽占用降至15%,视觉处理帧率恢复至30ms,消息丢失率从2.3%降至0.1%。

复盘经验:在AI应用中,按需订阅是基本原则。不要依赖地面站的默认设置,应在代码中显式控制数据流。同时,建议在开发阶段使用mavlink-inspector监控实际消息频率,避免“隐性”带宽消耗。

4.4 常见误区与总结复盘

误区一:混淆消息ID与消息类型

在pymavlink中,msg.msgid是数字ID,msg.get_type()是字符串类型。两者对应关系由MAVLink XML定义文件决定。如果使用自定义消息,需要确保两端使用相同的XML定义。

误区二:忽略时间戳同步

ATTITUDE消息中的time_boot_ms是飞控开机时间,而视觉程序通常使用系统时间。在融合视觉与飞控数据时,必须进行时间同步。简单做法是记录消息到达的本地时间,并估算传输延迟(通常<5ms)。对于高精度应用,可使用PX4的EKF2时间戳或GPS时间。

误区三:不处理消息丢失

串口通信不可避免会丢包。在AI控制回路中,如果ATTITUDE消息丢失超过100ms,应使用上一帧数据或进行插值。更稳健的做法是使用MAVSDK的telemetry接口,它内部实现了消息缓存和丢失检测。

总结:MAVLink是PX4 AI开发的“数据血管”。掌握消息格式、常用消息和数据流控制,是构建可靠AI系统的前提。建议读者在真机调试前,先使用mavlink-router或QGroundControl的MAVLink Inspector功能,在仿真环境中熟悉消息交互。下一阶段,我们将探讨如何利用这些数据实现视觉识别与飞控联动。