3. 航线任务数据结构:理解 MAVLink 协议中的 MISSION_ITEM、MISSION_CURRENT、MISSION_REACHED
航线执行出问题,说白了就是飞机不知道「下一步该去哪」,或者地面站不知道「飞机现在到哪了」。要定位这类问题,你必须读懂 MAVLink 协议里那三个核心消息:MISSION_ITEM、MISSION_CURRENT 和 MISSION_REACHED。
我个人习惯把这三条消息比作「航线剧本」、「当前读到第几页」和「这一页演完了」。下面我们逐个拆解。
3.1 MISSION_ITEM:航线里的每一帧画面
MISSION_ITEM 是航线任务的基本单元。每一条航点、每一个动作,都对应一条 MISSION_ITEM 消息。QGC 上传航线时,就是一条一条地把这些消息塞给飞控。
它的核心字段长这样:
| 字段 | 含义 | 我踩过的坑 |
|---|---|---|
seq |
航点序号,从 0 开始 | 序号不连续?飞控直接拒绝航线 |
frame |
坐标系(MAV_FRAME_GLOBAL / MAV_FRAME_LOCAL_NED 等) | 坐标系搞错,飞机飞到天上去 |
command |
命令编号(MAV_CMD_NAV_WAYPOINT、MAV_CMD_DO_CHANGE_SPEED 等) | 命令编号写错,飞控直接跳过 |
current |
是否为当前航点(0/1/2) | 2 表示航线结束,很多人漏掉 |
autocontinue |
是否自动进入下一航点 | 设为 0 时飞机会悬停等待 |
param1~param4 |
命令参数(停留时间、转弯半径等) | 参数含义因 command 而异,查表! |
x / y / z |
经纬度 / 高度 | z 的单位取决于 frame,别搞混 |
关键点:MISSION_ITEM 的 current 字段只有 0、1、2 三种值。0 表示普通航点,1 表示当前正在执行的航点,2 表示航线结束。我在项目中遇到过有人把 current 写成 3,结果飞控直接报错「无效航点」。
3.2 MISSION_CURRENT:飞控的「书签」
MISSION_CURRENT 是飞控主动发给地面站的消息,告诉你「我现在正在执行第几个航点」。它的结构极其简单:
MISSION_CURRENT {
seq: uint16_t // 当前正在执行的航点序号
total: uint16_t // 航线总航点数(部分协议版本包含)
}
嗯,这里要注意:seq 是飞控内部维护的「当前指针」。QGC 收到这条消息后,就会在地图上把对应航点高亮显示。
我曾经遇到一个案例:飞机明明已经飞过第 5 个航点,但 QGC 上一直显示第 3 个航点高亮。查日志发现,MISSION_CURRENT 的 seq 一直卡在 3 没变。后来定位到是飞控的航点跳转逻辑有 bug,导致指针没更新。
调试技巧:在 QGC 的 MAVLink Inspector 里过滤 MISSION_CURRENT 消息,观察 seq 的变化节奏。正常情况下,每到达一个航点,seq 就应该 +1。如果 seq 跳跃或卡住,说明航点切换逻辑有问题。
3.3 MISSION_REACHED:航点到达的「确认信号」
MISSION_REACHED 是飞控到达某个航点后发出的确认消息。它的结构更简单:
MISSION_REACHED {
seq: uint16_t // 刚刚到达的航点序号
}
你可能会问:MISSION_CURRENT 和 MISSION_REACHED 有什么区别?
区别大了。MISSION_CURRENT 是「正在执行」,MISSION_REACHED 是「已经到达」。举个例子:
- 飞机飞向第 3 个航点的途中,MISSION_CURRENT.seq = 3,MISSION_REACHED 不发
- 飞机到达第 3 个航点,MISSION_REACHED.seq = 3 发出
- 飞机开始飞向第 4 个航点,MISSION_CURRENT.seq = 4
说白了,MISSION_REACHED 是「过去时」,MISSION_CURRENT 是「现在进行时」。
避坑指南:我曾经遇到一个 bug,飞控在到达航点后发了 MISSION_REACHED,但紧接着又发了一条 MISSION_CURRENT 指向同一个航点。QGC 以为飞机还没离开,导致航线进度显示异常。后来发现是飞控的航点到达判定阈值设得太小,飞机在航点附近来回震荡,反复触发到达事件。
3.4 三条消息的协作流程
这三条消息在航线执行过程中是怎么配合的?我画了一张图帮你理解:
3.5 日志定位实战:如何用这三条消息排查问题
在实际的 QGC 日志分析中,我一般按以下步骤排查航线执行问题:
- 检查 MISSION_ITEM 是否完整上传:看日志里有没有 MISSION_COUNT 和对应数量的 MISSION_ITEM。如果数量对不上,说明上传阶段就出了问题。
- 检查 MISSION_CURRENT 的 seq 变化:正常情况是 0→1→2→...→total-1。如果 seq 跳跃(比如从 2 直接跳到 5),说明飞控跳过了某些航点。
- 检查 MISSION_REACHED 是否及时发出:如果 MISSION_CURRENT 已经变成 5,但 MISSION_REACHED 一直没收到 seq=4 的到达确认,说明飞机可能没到达第 4 个航点就超时跳过了。
- 对比时间戳:把 MISSION_CURRENT 和 MISSION_REACHED 的时间戳对齐,看每个航点的「到达时间」和「切换时间」是否合理。
实战案例:有一次用户反馈飞机在航线中途突然悬停不动。我翻日志发现,MISSION_CURRENT 的 seq 停在 7 不动了,但 MISSION_REACHED 已经发出了 seq=7 的到达确认。这说明飞控认为已经到达第 7 个航点,但不知道什么原因没有切换到第 8 个。后来定位到是第 8 个航点的 MAV_CMD 命令编号写错了,飞控无法识别,直接卡住。
3.6 常见问题速查表
| 现象 | 可能原因 | 日志证据 |
|---|---|---|
| 航线无法上传 | MISSION_ITEM 的 seq 不连续或 current 值错误 | 飞控回复 MISSION_ACK 错误码 |
| QGC 显示航点不更新 | MISSION_CURRENT 的 seq 卡住 | 日志中 MISSION_CURRENT 长时间不变 |
| 飞机跳过某些航点 | MISSION_CURRENT 的 seq 跳跃 | seq 从 N 直接跳到 N+2 |
| 飞机到达航点后不停留 | MISSION_ITEM 的 autocontinue=1 且 param1(停留时间)=0 | MISSION_REACHED 发出后立即收到下一个 MISSION_CURRENT |
| 飞机在航点附近来回飞 | 到达判定阈值太小,反复触发 MISSION_REACHED | 短时间内多次 MISSION_REACHED 指向同一 seq |