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通信的三个核心层次:消息封装层、核心消息解析和数据流控制。在PX4 AI开发中,我们通常使用pymavlink或MAVSDK库来屏蔽底层帧解析细节,但理解帧结构对排查通信问题至关重要。接下来,我们将逐一深入这些层次。
4.1 MAVLink消息格式:从字节流到结构化数据
核心原理:MAVLink v2帧结构
MAVLink v2是当前PX4默认使用的版本,其帧结构比v1更灵活,支持24位消息ID和消息签名。一个完整的MAVLink v2帧包含以下字段:
| 字段 | 长度(字节) | 说明 |
|---|---|---|
| STX | 1 | 帧起始标志,v2固定为0xFD |
| LEN | 1 | 负载长度(0-255字节) |
| SEQ | 1 | 序列号,用于检测丢包 |
| SYS_ID | 1 | 系统ID,区分不同飞行器(通常为1) |
| COMP_ID | 1 | 组件ID,区分同一系统内的不同模块(如飞控=1,相机=100) |
| MSG_ID | 3 | 消息ID,v2支持0-16777215 |
| PAYLOAD | 0-255 | 消息负载,具体内容由MSG_ID决定 |
| CRC_EXTRA | 1 | 消息格式校验码,用于验证消息定义是否匹配 |
| CHECKSUM | 2 | CRC16校验值,覆盖整个帧 |
| SIGNATURE | 0-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)
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_SENSORS | IMU原始数据、气压计、磁力计 | 50-100Hz |
| MAV_DATA_STREAM_EXTENDED_STATUS | 电池状态、飞行模式 | 2-5Hz |
| MAV_DATA_STREAM_EXTRA1 | ATTITUDE、姿态角速度 | 10-30Hz |
| MAV_DATA_STREAM_EXTRA2 | VFR_HUD(空速、高度) | 5-10Hz |
| MAV_DATA_STREAM_EXTRA3 | GPS_RAW_INT、HOME_POSITION | 5-10Hz |
| MAV_DATA_STREAM_POSITION | LOCAL_POSITION_NED、GLOBAL_POSITION_INT | 10-30Hz |
在AI应用中,我们通常只需要ATTITUDE(用于图像配准)和LOCAL_POSITION_NED(用于位置控制)。如果同时订阅所有数据流,会浪费大量串口带宽,甚至导致消息延迟。
案例拆解:AI视觉避障系统的数据流优化
背景与约束:某PX4无人机搭载Jetson Nano进行实时视觉避障,通过串口(波特率921600)与飞控通信。初始阶段,开发者直接使用QGroundControl的默认数据流设置,导致串口带宽占用超过80%,视觉处理帧率下降。
初始现象:视觉程序每帧处理时间从30ms增加到60ms,且偶尔出现MAVLink消息丢失(SEQ跳变)。
分析过程:
- 使用
mavlink-inspector统计各消息频率,发现IMU原始数据以100Hz发送,占用大量带宽。 - 计算带宽:IMU消息约50字节×100Hz=5000B/s,ATTITUDE约28字节×30Hz=840B/s,GPS约36字节×10Hz=360B/s。总带宽约6.2KB/s,而921600波特率实际有效带宽约92KB/s,看似不拥挤,但串口协议开销和系统调度导致实际可用带宽更低。
- 进一步发现,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-router或QGroundControl的MAVLink Inspector功能,在仿真环境中熟悉消息交互。下一阶段,我们将探讨如何利用这些数据实现视觉识别与飞控联动。