4、MAVLink协议基础:消息结构、常见类型与uORB关系
做SITL仿真联调,绕不开MAVLink。说白了,它就是无人机和地面站之间的“通用语言”。我最早接触MAVLink时,觉得不就是个通信协议嘛,后来踩了几个坑才明白——不理解消息结构,你连日志都读不懂。
这一节,我们就把MAVLink的底裤扒开看看。消息怎么组装的?心跳包长什么样?GPS数据怎么塞进去的?还有那个uORB,它和MAVLink到底是什么关系?
4.1 MAVLink消息结构:一个数据包的解剖
MAVLink的消息结构其实很简洁。每个数据包都遵循固定格式,就像快递包裹一样——有包裹单、有内容、有校验码。
我习惯把MAVLink v1的消息结构画成一张表,这样一眼就能看明白每个字节的用途:
| 字节偏移 | 字段名 | 长度(字节) | 说明 |
|---|---|---|---|
| 0 | STX(起始标志) | 1 | 固定值0xFE(v1版本) |
| 1 | LEN(负载长度) | 1 | 后面payload的字节数 |
| 2 | SEQ(序列号) | 1 | 每个组件独立计数,检测丢包用 |
| 3 | SYS ID(系统ID) | 1 | 标识是哪个无人机/设备 |
| 4 | COMP ID(组件ID) | 1 | 标识是飞控、GPS还是相机 |
| 5 | MSG ID(消息ID) | 1 | 标识消息类型,比如心跳是0 |
| 6 ~ 6+LEN-1 | Payload(负载) | LEN | 真正的数据内容 |
| 6+LEN | CKA(校验码低字节) | 1 | CRC校验,保证数据完整性 |
| 7+LEN | CKB(校验码高字节) | 1 | 同上 |
我的小经验:调试时如果地面站收不到数据,先看STX对不对。0xFE是v1,0xFD是v2。我曾经花了一下午排查,结果发现是v1和v2混用了——地面站用v2解析v1的包,直接丢掉了。
嗯,这里要注意:MAVLink v2比v1多了个“不签名标志”和“签名”字段,但核心结构没变。你搞SITL仿真时,默认用的就是v2,兼容v1。
4.2 常见消息类型:心跳、GPS和姿态
MAVLink定义了上百种消息类型。但说实话,日常仿真联调,你打交道最多的就那几种。我挑三个最核心的讲。
4.2.1 HEARTBEAT(心跳包)
心跳包是MAVLink的“我在呢”信号。飞控每隔1秒发一次,告诉地面站:我还活着,模式是什么,有没有问题。
它的MSG ID是0。payload里最关键的是这几个字段:
- type:飞行器类型,比如MAV_TYPE_QUADROTOR(四旋翼)
- autopilot:飞控类型,比如MAV_AUTOPILOT_PX4
- base_mode:飞行模式,比如是否上锁、是否在自动模式
- system_status:系统状态,比如STANDBY、ACTIVE、EMERGENCY
你看,就这4个字段,地面站就能判断无人机当前的状态。我调试时,第一件事就是看心跳包有没有——如果心跳断了,后面所有数据都不用看了。
4.2.2 GPS_RAW_INT(原始GPS数据)
这个MSG ID是24。它把GPS信息打包成整数发送,节省带宽。payload里包含:
- lat / lon:纬度、经度,单位是度×10^7(整数)
- alt:海拔高度,单位是毫米
- eph / epv:水平/垂直定位精度,单位是厘米
- fix_type:定位类型,0=无定位,1=无GPS,2=2D,3=3D
- satellites_visible:可见卫星数
避坑指南:我曾经在仿真里发现GPS数据一直显示0,查了半天,原来是SITL启动时没设置GPS模拟参数。默认情况下,SITL的GPS是关闭的。记得加 --gps 参数,或者用 param set 把GPS使能。
4.2.3 ATTITUDE(姿态数据)
MSG ID是30。这个包告诉你飞机当前“怎么躺的”。payload包含:
- roll / pitch / yaw:横滚角、俯仰角、偏航角,单位是弧度
- rollspeed / pitchspeed / yawspeed:角速度,单位是弧度/秒
- time_boot_ms:从启动到现在的毫秒数
你想想看,地面站画的那个小飞机模型,就是靠这个数据转来转去的。我调试姿态控制时,经常盯着这个包看——如果roll突然跳变,说明传感器或者滤波器出问题了。
4.3 uORB与MAVLink的关系:内部总线 vs 外部协议
这个问题,很多初学者搞混。我直接说结论:uORB是PX4飞控内部的消息总线,MAVLink是飞控和外部通信的协议。
它们的关系,可以用一张图说清楚:
你看这张图就明白了:
- uORB:飞控内部各个模块之间“喊话”用的。比如GPS驱动发布了
sensor_gps主题,姿态估计模块订阅它,然后发布vehicle_attitude主题。 - MAVLink:飞控和地面站“打电话”用的。mavlink模块订阅uORB上的数据,然后打包成MAVLink消息,通过串口或UDP发出去。
注意:uORB和MAVLink的消息ID不是一回事。uORB的主题名是字符串(比如 sensor_gps),MAVLink的消息ID是数字(比如24对应GPS_RAW_INT)。mavlink模块负责做这个“翻译”工作。
我刚开始学PX4时,总以为改MAVLink消息要改uORB。其实不是——你只需要在mavlink模块里加一个订阅和打包函数就行。uORB那边完全不用动。
4.4 实战:在SITL里抓一个MAVLink包看看
光说不练假把式。我们启动SITL,然后用 mavlink 命令行工具抓个包看看。
先启动SITL(假设你已经配好了环境):
make px4_sitl gazebo
等飞控启动后,另开一个终端,用 mavlink 工具监听:
mavlink receive udp:127.0.0.1:14550
你会看到类似这样的输出:
MAVLink: received 1 messages
#0: HEARTBEAT (type=2, autopilot=12, base_mode=81, system_status=3)
MAVLink: received 1 messages
#1: GPS_RAW_INT (lat=473825000, lon=85000000, alt=488000, fix_type=3, satellites_visible=10)
MAVLink: received 1 messages
#2: ATTITUDE (roll=0.01, pitch=-0.02, yaw=1.57, rollspeed=0.00, pitchspeed=0.00, yawspeed=0.00)
嗯,这就是飞控在“说话”。你看心跳包的 base_mode=81,表示飞控已经解锁并处于自动模式。fix_type=3 表示3D定位成功。yaw=1.57 大约是90度,说明飞机朝东。
调试技巧:如果你不想装mavlink工具,也可以用 netcat 直接看原始字节流。不过那玩意是人眼不可读的——全是十六进制。我建议还是用 mavlink 或者 mavproxy,它们会自动解析消息。
4.5 小结:记住这三句话
这一节内容不少,但核心就三句话:
- MAVLink消息结构:起始标志 + 长度 + 序列号 + 系统/组件ID + 消息ID + 负载 + 校验码。就这么简单。
- 常见消息类型:HEARTBEAT(心跳,MSG ID=0)、GPS_RAW_INT(原始GPS,MSG ID=24)、ATTITUDE(姿态,MSG ID=30)。这三个包覆盖了无人机90%的调试需求。
- uORB与MAVLink的关系:uORB是内部总线,MAVLink是外部协议。mavlink模块是“翻译官”,把uORB主题翻译成MAVLink消息发出去。