4. MAVLink协议与地面站通信
MAVLink 是 ArduPilot 与地面站、机载伴飞计算机、云台、遥控链路之间最核心的通信协议。它是一套轻量级的二进制消息协议,采用“帧头 + 载荷 + 校验”的结构,在低带宽数传链路上也能稳定传输飞控状态、参数、任务和指令。理解 MAVLink 的消息格式与几类关键协议,是后续调参、日志分析和二次开发的基础。
MAVLink 消息格式
MAVLink 目前主流使用 v2.0,同时兼容 v1.0。一帧 MAVLink v2 消息由以下字段顺序组成:起始标志 0xFD、载荷长度、不兼容标志、兼容标志、序列号、系统 ID(SysID)、组件 ID(CompID)、24 位消息 ID(MsgID)、最多 255 字节的载荷,以及末尾 2 字节 CRC 校验。v1.0 的帧头为 0xFE,消息 ID 只有 8 位。CRC 计算时会在消息定义中附加一个“CRC 种子”,用于区分不同消息,防止错误解析。
载荷字段按小端序排列,并按字段长度从大到小重排(字段重排是 MAVLink 的规范,用于对齐)。例如 HEARTBEAT 消息载荷包含:custom_mode(uint32)、type(uint8)、autopilot(uint8)、base_mode(uint8)、system_status(uint8)、mavlink_version(uint8)。理解字段类型和顺序,才能正确用 pymavlink 解析或构造消息。
心跳包与系统状态
HEARTBEAT(消息 ID 0)是 MAVLink 的“生命信号”,飞控以约 1 Hz 频率广播。它携带 type(载具类型,如四旋翼为 2)、autopilot(ArduPilot 为 3)、base_mode(解锁、手动/自动等标志位)、custom_mode(ArduPilot 自定义飞行模式)、system_status(如 STANDBY、ACTIVE、CRITICAL)。地面站通过心跳判断链路是否在线、飞控是否解锁、当前处于何种飞行模式。若地面站长时间收不到心跳,会提示“No heartbeat”并禁止解锁。
参数协议
参数读写使用 PARAM_REQUEST_LIST、PARAM_REQUEST_READ、PARAM_SET 和 PARAM_VALUE 四条消息。地面站连接后通常先请求全部参数列表,飞控逐条回传 PARAM_VALUE,其中包含参数名(16 字节)、参数值(float)、参数类型和索引。修改参数时发送 PARAM_SET,飞控写入后回传新的 PARAM_VALUE 作为确认。调参时常见的 ATC_RAT_RLL_P、WPNAV_SPEED 等都属于这一协议。
任务协议
任务(Mission)协议用于上传、下载和清空航线。核心消息包括 MISSION_COUNT、MISSION_REQUEST_INT、MISSION_ITEM_INT、MISSION_ACK。典型上传流程是:地面站发送 MISSION_COUNT 告知航点总数,飞控逐条请求,地面站逐条发送 MISSION_ITEM_INT(含经纬度、高度、命令类型、参数 1~4),最后飞控回 MISSION_ACK 表示接收完成。任务协议还支持 MISSION_CLEAR_ALL 清空当前任务。
Mission Planner 与 QGroundControl 连接
Mission Planner 运行在 Windows 上,连接方式通常选择右上角下拉框中的 COM 口(USB 直连)或 UDP。使用数传时,飞控通过串口连接数传电台,地面端电台以 USB 转串口接入电脑,选择对应 COM 口、波特率 57600 即可。若通过 MAVProxy 转发,可在 Mission Planner 中选择 UDP,端口 14550。连接成功后,飞行数据页会显示姿态、GPS、电压等实时信息,参数页可加载全部参数。
QGroundControl 跨平台,连接逻辑类似:在“通信设置”中添加串口或 UDP 链路。默认 UDP 监听端口为 14550。连接后可在“参数”页搜索并修改参数,在“计划”页绘制航线并上传。两者都遵循同一套 MAVLink 协议,因此同一飞控可被任一地面站控制,但不要同时用两个地面站写参数,以免冲突。
使用 MAVProxy 与 pymavlink 收发自定义消息
MAVProxy 是命令行地面站,适合脚本化和转发。启动示例:
mavproxy.py --master=/dev/ttyUSB0 --baud=57600 --out=udp:127.0.0.1:14550
该命令从串口读取飞控数据,并转发到本机 UDP 14550,供 Mission Planner 或 QGC 使用。在 MAVProxy 交互界面中,可用 status 查看状态,param show ATC_RAT_RLL_P 查看参数,module load graph 加载绘图模块。
pymavlink 是 Python 库,适合编写自定义收发程序。下面示例连接 UDP 14550,等待心跳,并发送一条自定义 STATUSTEXT 消息:
from pymavlink import mavutil
master = mavutil.mavlink_connection('udp:127.0.0.1:14550')
master.wait_heartbeat()
print("Heartbeat from system", master.target_system)
master.mav.statustext_send(
mavutil.mavlink.MAV_SEVERITY_INFO,
b"Hello from pymavlink"
)
while True:
msg = master.recv_match(blocking=True)
if msg and msg.get_type() == 'HEARTBEAT':
print("mode:", msg.custom_mode, "armed:", msg.base_mode & 128)
若要发送自定义消息,可在 MAVLink 消息定义中新增一条消息,重新生成 Python 库,或使用 master.mav.send() 构造 MAVLink_message。更常见的做法是使用 DEBUG_VECT、NAMED_VALUE_FLOAT 或 STATUSTEXT 这类通用消息承载自定义数据,避免修改协议定义。
mavlink_connection 的 recv_match 打印消息类型,确认链路正常;再逐步加入参数读写和任务上传。若收不到心跳,检查波特率、端口和防火墙。PARAM_VALUE 回传确认,不要连续快速写入同一参数。掌握消息格式、心跳、参数和任务四类协议后,就能用地面站完成日常调参,也能用 MAVProxy 和 pymavlink 构建自动化测试与自定义数据链路,为后续深入开发打下基础。