2. 无人机与MAVLink基础
在开始用 MAVSDK 编写控制程序之前,必须先弄清楚一个根本问题:你的代码到底在和谁说话,通过什么方式说话。MAVSDK 并不是直接驱动电机或舵机的库,它是一套面向 MAVLink 协议的高层封装。因此,理解无人机系统的物理组成、飞控与地面站的角色分工,以及 MAVLink 的消息帧结构与通信模式,是后续所有任务开发的地基。
一、无人机系统的组成
一架典型的多旋翼无人机可以划分为四个层次:机架与动力系统(机架、电机、电调、螺旋桨、电池)、感知与执行系统(IMU、磁力计、气压计、GPS、光流、云台、相机)、飞控系统(运行 PX4 或 ArduPilot 的飞行控制器)、通信与任务系统(数传电台、Wi-Fi、4G 链路、地面站、机载计算机)。
其中飞控是整机的“小脑与脊髓”:它以数百赫兹的频率读取传感器,运行姿态估计与位置控制回路,输出 PWM/DShot 信号驱动电调。而地面站或机载计算机是“大脑”:负责航线规划、任务调度、载荷控制与数据回传。MAVSDK 运行在“大脑”一侧,通过 MAVLink 与飞控的“小脑”交互。
二、飞控与地面站的角色分工
飞控(Flight Controller)承担实时性要求最高的职责:传感器融合、姿态控制、位置控制、失效保护(返航、降落、解锁检查)。地面站(GCS)承担人机交互与任务管理职责:显示遥测、上传航线、修改参数、触发动作。二者通过 MAVLink 双向通信。
在 MAVSDK 开发中,你的程序实际上扮演了一个“自动化地面站”的角色。它既可以是运行在笔记本上的 Python 脚本,也可以是运行在机载计算机(如树莓派、Jetson)上的服务。理解这一点后,很多 API 设计就顺理成章了:action.arm() 对应地面站上的“解锁”按钮,mission.upload_mission() 对应“上传航线”。
三、MAVLink 协议原理与消息帧结构
MAVLink(Micro Air Vehicle Link)是一种轻量级、二进制、面向消息的通信协议。它不依赖特定传输介质,可以跑在串口、UDP、TCP 之上。其核心设计目标是:低带宽、可校验、可扩展、跨平台。
MAVLink 2 的消息帧由以下字段依次构成:
| 字段 | 长度 | 作用 |
|---|---|---|
| STX | 1 字节 | 帧起始标志,固定为 0xFD |
| LEN | 1 字节 | 载荷长度 |
| SEQ | 1 字节 | 发送序号,用于丢包检测 |
| SYSID | 1 字节 | 系统 ID,标识发送方 |
| COMPID | 1 字节 | 组件 ID,如飞控、相机、云台 |
| MSGID | 3 字节 | 消息类型编号,如 0 为心跳 |
| PAYLOAD | 0~255 字节 | 实际数据,按消息定义排列 |
| CHECKSUM | 2 字节 | 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")
五、案例场景:从地面站到 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 会认为连接断开,所有命令可能被拒绝。
误区三:混淆 SYSID 与 COMPID。多机场景下必须正确设置目标系统 ID,否则命令会发错飞机。
误区四:在未解锁状态下发送起飞命令。飞控会返回错误,程序应捕获异常并检查前置条件。
复盘建议:每次调试时先确认三件事——连接是否建立、心跳是否收到、当前飞行模式是否允许该操作。这三步能排除大部分“命令无响应”的问题。
掌握本节内容后,你应当能够回答:MAVSDK 程序在系统中处于什么位置、它发送的消息长什么样、飞控如何响应这些消息。这些认知将直接决定你后续调试任务时的排查方向。