1. 通信协议总览:MAVLink协议简介、uORB消息总线、QGC地面站架构、通信链路拓扑图

好,咱们开始第一章。这一章说白了就是给整个课程搭个骨架。你得先知道PX4飞控和QGC地面站之间到底是怎么说话的,用了什么“语言”,走了什么“路”。我见过不少新手,上来就调参、改代码,结果通信断了抓瞎半天——其实就是没搞懂底层这几条链路。

核心一句话:PX4内部用uORB总线传消息,对外用MAVLink协议打包,通过串口或UDP发给QGC。QGC收到后解包,再通过内部插件分发显示。

1.1 MAVLink协议简介

MAVLink,全称Micro Air Vehicle Link。说白了就是无人机界的“普通话”。它定义了飞控和地面站之间所有消息的格式——心跳、姿态、GPS坐标、遥控指令,全得按这个规矩来。

我个人习惯把MAVLink分成两代:

  • MAVLink v1: 消息长度8字节,简单粗暴,适合老式8位单片机。但扩展性差,现在基本淘汰了。
  • MAVLink v2: 消息长度最大255字节,支持签名认证、消息扩展。PX4和QGC现在默认都用v2。

一个典型的MAVLink数据包长这样:

| 起始标志(0xFD) | 长度 | 不兼容标志 | 兼容标志 | 序列号 | 系统ID | 组件ID | 消息ID | 载荷 | 校验和 |

嗯,这里要注意:系统ID和组件ID是区分设备的关键。飞控的系统ID通常是1,QGC是255。组件ID则区分飞控内部的GPS、IMU等模块。我在项目中遇到过两台飞控同时连一个地面站,结果指令串了——就是因为系统ID没改。

避坑指南:我曾经调试时发现QGC收不到心跳包,折腾半天发现是串口波特率设成了9600,而飞控默认是57600。MAVLink的波特率必须两端一致,否则连不上。

1.2 uORB消息总线

uORB是PX4内部的消息总线。你可以把它想象成飞控的“内部快递系统”。传感器数据、控制指令、状态信息,全通过uORB在模块之间传递。

为什么要有uORB?你想想看,PX4里有几十个模块——姿态估计、位置控制、GPS驱动、RC输入……如果每个模块都直接调用对方的函数,代码就乱成一锅粥了。uORB让它们解耦:发布者只管发,订阅者只管收,谁都不认识谁。

常用的uORB消息主题:

主题名称 发布者 订阅者 内容
sensor_accel 加速度计驱动 姿态估计、EKF 三轴加速度数据
vehicle_attitude 姿态估计模块 位置控制、QGC 四元数、欧拉角
vehicle_gps_position GPS驱动 位置估计、导航 经纬度、海拔、速度
actuator_controls 混控器 PWM输出驱动 电机/舵机控制量

uORB的工作流程很简单:

  1. 发布者调用orb_advertise()注册主题
  2. 发布者循环调用orb_publish()发送数据
  3. 订阅者调用orb_subscribe()订阅主题
  4. 订阅者调用orb_copy()获取最新数据

注意:uORB是飞控内部机制,QGC完全看不到它。飞控内部把uORB消息转换成MAVLink包后,才发到外部。反过来,QGC发来的MAVLink指令,飞控也要先解包,再通过uORB投递给对应模块。

1.3 QGC地面站架构

QGC(QGroundControl)不是个简单的显示界面。它的架构分三层:

  • 通信层: 负责收发MAVLink包。支持串口、UDP、TCP。我建议调试时用UDP,方便抓包分析。
  • 核心层: 解析MAVLink消息,维护无人机状态。比如心跳超时检测、参数同步、航点管理。
  • UI层: 用Qt Quick写的界面。显示地图、仪表盘、参数表。说白了就是给人看的。

QGC内部有个MAVLink协议栈,它维护着所有连接设备的状态。每个设备有一个Vehicle对象,里面存着它的系统ID、组件列表、当前模式、电池电量等等。

我记得有一次,QGC显示“连接已断开”,但飞控明明还在飞。后来发现是QGC的心跳超时阈值默认设了5秒,而飞控因为CPU负载高,心跳偶尔延迟到6秒。把阈值调到10秒就解决了。

1.4 通信链路拓扑图

下面这张图展示了从传感器到地面站的完整数据流。我特意把uORB和MAVLink的分界画清楚了。

PX4飞控 ↔ QGC地面站 通信链路拓扑图 PX4 飞控内部 传感器驱动 (GPS/IMU/磁力计) uORB 消息总线 姿态估计 (EKF) 位置控制 (L1/PID) MAVLink 打包/解包 串口/UART (物理连接) UDP/TCP (网络连接) 双向 MAVLink QGC 地面站内部 串口/UART (物理连接) UDP/TCP (网络连接) MAVLink 协议栈 核心层 (Vehicle管理/参数同步/航点) UI层 (地图/仪表盘/参数表) 💡 数据流方向: 传感器 → uORB → 飞控模块 → MAVLink → 物理链路 → QGC

从图上你能看到:数据从传感器驱动出发,经过uORB总线分发给各个飞控模块,模块处理完后交给MAVLink层打包,再通过串口或UDP发出去。QGC那边反过来:物理层收到数据,MAVLink协议栈解包,核心层更新无人机状态,UI层刷新显示。

这个链路里最容易出问题的环节,我个人经验是物理链路和MAVLink版本不匹配。串口线太长、USB转串口芯片质量差、或者飞控用v2而QGC配置成v1,都会导致通信失败。

调试小技巧:用mavlink-router或者mavproxy抓包看原始MAVLink数据。我习惯在飞控和QGC之间串一个mavproxy,既能转发又能录日志。出问题时回放日志,一眼就能看出是飞控没发数据,还是QGC没解析对。

好了,这一章把整个通信骨架搭起来了。后面我们会深入每个环节——MAVLink消息怎么定义、uORB怎么用代码发布订阅、QGC的插件怎么开发。有了这个总览图,后面学起来就不会迷路。