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 三条消息的协作流程

这三条消息在航线执行过程中是怎么配合的?我画了一张图帮你理解:

MISSION_ITEM / MISSION_CURRENT / MISSION_REACHED 协作流程 地面站 (QGC) 飞控 (PX4/ArduPilot) ① 上传航线 MISSION_COUNT + MISSION_ITEM 批量上传 ② 开始执行 MISSION_CURRENT { seq: 0 } ③ 飞向航点 0 飞控内部状态:正在飞向 seq=0 ④ 到达航点 0 MISSION_REACHED { seq: 0 } ⑤ 切换到下一航点 MISSION_CURRENT { seq: 1 } ⑥ 重复③~⑤ 直到 seq == total-1,最后一条 MISSION_CURRENT { seq: 2 } 表示结束 关键:MISSION_CURRENT 是「正在执行」,MISSION_REACHED 是「已经到达」,两者 seq 可能不同步

3.5 日志定位实战:如何用这三条消息排查问题

在实际的 QGC 日志分析中,我一般按以下步骤排查航线执行问题:

  1. 检查 MISSION_ITEM 是否完整上传:看日志里有没有 MISSION_COUNT 和对应数量的 MISSION_ITEM。如果数量对不上,说明上传阶段就出了问题。
  2. 检查 MISSION_CURRENT 的 seq 变化:正常情况是 0→1→2→...→total-1。如果 seq 跳跃(比如从 2 直接跳到 5),说明飞控跳过了某些航点。
  3. 检查 MISSION_REACHED 是否及时发出:如果 MISSION_CURRENT 已经变成 5,但 MISSION_REACHED 一直没收到 seq=4 的到达确认,说明飞机可能没到达第 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