2. 无人机与MAVLink基础

在开始用 MAVSDK 编写控制程序之前,必须先弄清楚一个根本问题:你的代码到底在和谁说话,通过什么方式说话。MAVSDK 并不是直接驱动电机或舵机的库,它是一套面向 MAVLink 协议的高层封装。因此,理解无人机系统的物理组成、飞控与地面站的角色分工,以及 MAVLink 的消息帧结构与通信模式,是后续所有任务开发的地基。

一、无人机系统的组成

一架典型的多旋翼无人机可以划分为四个层次:机架与动力系统(机架、电机、电调、螺旋桨、电池)、感知与执行系统(IMU、磁力计、气压计、GPS、光流、云台、相机)、飞控系统(运行 PX4 或 ArduPilot 的飞行控制器)、通信与任务系统(数传电台、Wi-Fi、4G 链路、地面站、机载计算机)。

其中飞控是整机的“小脑与脊髓”:它以数百赫兹的频率读取传感器,运行姿态估计与位置控制回路,输出 PWM/DShot 信号驱动电调。而地面站或机载计算机是“大脑”:负责航线规划、任务调度、载荷控制与数据回传。MAVSDK 运行在“大脑”一侧,通过 MAVLink 与飞控的“小脑”交互。

关键认知:MAVSDK 不参与底层姿态稳定,它发送的是“意图”(起飞、飞往某点、切换模式),飞控负责把意图翻译成电机转速。

二、飞控与地面站的角色分工

飞控(Flight Controller)承担实时性要求最高的职责:传感器融合、姿态控制、位置控制、失效保护(返航、降落、解锁检查)。地面站(GCS)承担人机交互与任务管理职责:显示遥测、上传航线、修改参数、触发动作。二者通过 MAVLink 双向通信。

在 MAVSDK 开发中,你的程序实际上扮演了一个“自动化地面站”的角色。它既可以是运行在笔记本上的 Python 脚本,也可以是运行在机载计算机(如树莓派、Jetson)上的服务。理解这一点后,很多 API 设计就顺理成章了:action.arm() 对应地面站上的“解锁”按钮,mission.upload_mission() 对应“上传航线”。

三、MAVLink 协议原理与消息帧结构

MAVLink(Micro Air Vehicle Link)是一种轻量级、二进制、面向消息的通信协议。它不依赖特定传输介质,可以跑在串口、UDP、TCP 之上。其核心设计目标是:低带宽、可校验、可扩展、跨平台。

MAVLink 2 的消息帧由以下字段依次构成:

字段长度作用
STX1 字节帧起始标志,固定为 0xFD
LEN1 字节载荷长度
SEQ1 字节发送序号,用于丢包检测
SYSID1 字节系统 ID,标识发送方
COMPID1 字节组件 ID,如飞控、相机、云台
MSGID3 字节消息类型编号,如 0 为心跳
PAYLOAD0~255 字节实际数据,按消息定义排列
CHECKSUM2 字节CRC 校验,保证数据完整性

最常见的消息是 HEARTBEAT(MSGID=0),它周期性地广播系统类型、飞控状态、当前模式。地面站和 MAVSDK 都靠心跳判断对方是否在线。另一个高频消息是 GLOBAL_POSITION_INT,携带经纬度、高度、速度。

# 典型 MAVLink 心跳消息(伪代码表示)
msg = HEARTBEAT(
    type=MAV_TYPE_QUADROTOR,
    autopilot=MAV_AUTOPILOT_PX4,
    base_mode=MAV_MODE_FLAG_CUSTOM_MODE_ENABLED,
    custom_mode=4,          # PX4 中 4 通常对应 AUTO.MISSION
    system_status=MAV_STATE_ACTIVE
)

四、通信模式与连接拓扑

MAVLink 支持多种通信模式,常见的有:

  • 串口直连:飞控 TELEM 口接数传电台,地面站通过串口读取。
  • UDP 广播:飞控通过 Wi-Fi 或以太网发送 UDP 包,多个地面站可同时监听。
  • TCP 连接:适合机载计算机与飞控之间的可靠通信。
  • 多机通信:通过 SYSID 区分不同无人机,实现编队控制。

在 MAVSDK 中,连接字符串直接体现这些模式:

# 通过 UDP 连接(常见于 SITL 仿真)
drone = await System.connect("udp://:14540")

# 通过串口连接
drone = await System.connect("serial:///dev/ttyUSB0:57600")

# 通过 TCP 连接
drone = await System.connect("tcp://192.168.1.10:5760")
SITL(软件在环仿真)默认使用 UDP 14540 端口,MAVSDK 连接该端口即可与虚拟飞控通信,无需真实硬件。

五、案例场景:从地面站到 MAVSDK 的迁移

假设你过去用 QGroundControl 手动执行一次巡检任务:连接飞控、检查 GPS 状态、上传航线、解锁、起飞、执行任务、返航。现在要用 MAVSDK 自动化,代码结构几乎一一对应:

await drone.action.arm()                    # 对应“解锁”
await drone.mission.upload_mission(plan)    # 对应“上传航线”
await drone.action.takeoff()                # 对应“起飞”
await drone.mission.start_mission()         # 对应“开始任务”
await drone.action.return_to_launch()       # 对应“返航”

这说明 MAVSDK 并没有发明新概念,而是把地面站的操作抽象成 API。理解地面站与飞控的交互逻辑,就能快速推断出 MAVSDK 的调用顺序。

六、常见误区与复盘

误区一:认为 MAVSDK 直接控制电机。实际上它只发送 MAVLink 消息,飞控决定如何执行。
误区二:忽略心跳与超时。如果飞控没有收到心跳,MAVSDK 会认为连接断开,所有命令可能被拒绝。
误区三:混淆 SYSID 与 COMPID。多机场景下必须正确设置目标系统 ID,否则命令会发错飞机。
误区四:在未解锁状态下发送起飞命令。飞控会返回错误,程序应捕获异常并检查前置条件。

复盘建议:每次调试时先确认三件事——连接是否建立、心跳是否收到、当前飞行模式是否允许该操作。这三步能排除大部分“命令无响应”的问题。

无人机系统组成与 MAVLink 通信链路 机架与动力系统 电机 / 电调 / 螺旋桨 电池 / 机架 感知与执行系统 IMU / 磁力计 / GPS 云台 / 相机 / 光流 飞控系统 PX4 / ArduPilot 姿态估计 / 位置控制 失效保护 / 模式管理 通信链路 数传 / Wi-Fi / 4G / 串口 地面站 / 机载计算机 QGC / MAVSDK 程序 任务规划 / 载荷控制 遥测显示 / 数据回传 PWM/DShot 传感器数据 MAVLink 消息 遥测 / 命令 双向通信 MAVLink 帧结构: STX LEN SEQ SYSID COMPID MSGID PAYLOAD CHECKSUM MAVSDK 通过 MAVLink 消息与飞控交互,不直接控制电机;心跳消息用于判断链路是否在线。

掌握本节内容后,你应当能够回答:MAVSDK 程序在系统中处于什么位置、它发送的消息长什么样、飞控如何响应这些消息。这些认知将直接决定你后续调试任务时的排查方向。