3. 任务指令集深度解析:NAV_CMD与DO_CMD的区别、常用DO指令

任务规划里最让人头疼的,就是搞不清导航指令和动作指令到底有什么区别。我见过不少新手,甚至一些老手,在写航线时把DO指令当NAV指令用,结果飞机飞到目标点后直接悬停,该做的动作一个没做。

说白了,NAV_CMD是让飞机“去哪里”,DO_CMD是让飞机“做什么”。一个管移动,一个管动作。今天我们就彻底把它掰开揉碎。

核心原则:NAV_CMD控制飞行器的位置和航向,DO_CMD控制机载设备的动作。两者可以独立执行,也可以组合使用。

3.1 NAV_CMD vs DO_CMD:本质区别

先看一张对比表,这样更直观:

对比维度 NAV_CMD(导航指令) DO_CMD(动作指令)
核心功能 控制飞行器位置、高度、航向 控制机载设备(舵机、云台、相机等)
执行时机 到达航点后立即执行 到达当前航点后、或与NAV指令并行执行
是否影响飞行 直接影响飞行轨迹 不影响飞行轨迹
典型指令 NAV_WAYPOINT, NAV_LOITER, NAV_RETURN_TO_LAUNCH DO_SET_SERVO, DO_MOUNT_CONTROL, DO_SET_CAM_TRIGG_DIST
参数数量 通常7个参数(位置+姿态+时间) 通常7个参数(设备编号+值+模式)

你可能会问:“为什么DO指令有7个参数,但很多参数都是0?” 嗯,这里要注意——DO指令的参数定义是通用的,但具体到每个指令,只有前几个参数有意义。比如DO_SET_SERVO,只有参数1(舵机编号)和参数2(PWM值)有用,其他参数填0就行。

3.2 常用DO指令详解

我个人在实际项目中用得最多的,就是下面这几个DO指令。每个都有它的脾气,用错了轻则设备不工作,重则炸机。

3.2.1 DO_SET_SERVO:控制舵机

这个指令用来控制舵机角度。比如农业无人机喷洒阀门、测绘无人机的投放机构,都靠它。

// 示例:设置舵机1到PWM 1900(约90度)
// 参数1: 舵机编号(1-8)
// 参数2: PWM值(1000-2000)
// 参数3-7: 保留,填0

DO_SET_SERVO, 1, 1900, 0, 0, 0, 0, 0

避坑指南:我曾经在农业项目中,把舵机编号写成了0。结果飞机起飞后,舵机纹丝不动。后来查了PX4源码才发现,舵机编号从1开始,不是0。这个坑我踩过,你别再踩了。

3.2.2 DO_MOUNT_CONTROL:控制云台

云台控制是航测和巡检的刚需。DO_MOUNT_CONTROL可以设置云台的俯仰、偏航和横滚角度。

// 示例:设置云台俯仰-45度,偏航0度,横滚0度
// 参数1: 俯仰角(度,负值向下)
// 参数2: 横滚角(度)
// 参数3: 偏航角(度)
// 参数4: 控制模式(0=角度,1=速度)
// 参数5-7: 保留

DO_MOUNT_CONTROL, -45, 0, 0, 0, 0, 0, 0

这里有个细节:云台的控制模式参数4,0表示绝对角度,1表示相对速度。我习惯用绝对角度,因为更直观。但如果你需要云台持续转动(比如全景拍摄),就用速度模式。

3.2.3 DO_SET_CAM_TRIGG_DIST:相机触发距离

航测任务中,相机需要按距离触发拍照。这个指令就是干这个的。

// 示例:每5米触发一次相机快门
// 参数1: 触发距离(米)
// 参数2-7: 保留

DO_SET_CAM_TRIGG_DIST, 5, 0, 0, 0, 0, 0, 0

注意:触发距离设置得太小,会导致照片重叠率过高,浪费存储空间;设置得太大,重叠率不够,后期建模会失败。我一般根据飞行高度和相机焦距计算,公式是:触发距离 = 飞行高度 × 相机焦距系数。具体系数可以查相机参数表。

3.2.4 DO_SET_ROI:设置兴趣点

这个指令让云台始终指向一个固定点。比如巡检时,让相机一直盯着某个塔架。

// 示例:设置兴趣点(纬度、经度、高度)
// 参数1: 纬度(度)
// 参数2: 经度(度)
// 参数3: 高度(米,相对起飞点)
// 参数4-7: 保留

DO_SET_ROI, 31.2304, 121.4737, 50, 0, 0, 0, 0

说实话,这个指令在PX4里有点“娇气”。如果GPS信号不好,ROI会飘。我在一个山区项目里吃过亏,云台一直对着错误的方向转,最后只能切回手动模式。

3.3 指令组合实战:一个完整的任务片段

光讲理论没意思。我们来看一个真实的任务片段:农业喷洒无人机,飞到田头后打开阀门,然后转弯,再关闭阀门。

// 任务片段:喷洒作业
1. NAV_WAYPOINT, 31.2300, 121.4700, 10  // 飞到田头A点
2. DO_SET_SERVO, 1, 1900, 0, 0, 0, 0, 0  // 打开喷洒阀门(PWM 1900)
3. NAV_WAYPOINT, 31.2310, 121.4710, 10  // 飞到田头B点(喷洒中)
4. DO_SET_SERVO, 1, 1100, 0, 0, 0, 0, 0  // 关闭喷洒阀门(PWM 1100)
5. NAV_WAYPOINT, 31.2320, 121.4720, 10  // 飞到下一个作业点

你看,DO指令夹在NAV指令之间。飞机到达A点后,先执行DO_SET_SERVO打开阀门,然后才飞往B点。到达B点后,再执行DO_SET_SERVO关闭阀门。

关键点:DO指令的执行时机是“到达当前航点后,飞往下一个航点前”。所以如果你在NAV_WAYPOINT后面紧跟着DO指令,飞机会在航点悬停,执行完DO指令后再继续飞行。

3.4 知识体系图:指令执行流程

下面这张图,帮你理清NAV_CMD和DO_CMD在任务执行中的关系:

NAV_CMD与DO_CMD执行流程 任务指令执行流程 任务开始 读取下一条指令 指令类型? NAV_CMD DO_CMD 飞往目标点 执行设备动作 还有指令? 是 任务结束 说明:NAV_CMD控制飞行,DO_CMD控制设备。两者独立执行,互不阻塞。

3.5 常见问题与避坑

最后,分享几个我踩过的坑,希望能帮你省点时间:

  • DO指令不执行? 检查一下指令编号是否正确。PX4的DO指令编号和ArduPilot不一样,比如DO_SET_SERVO在PX4里是183,不是180。我一开始也搞混过。
  • 舵机不动? 确认舵机供电是否正常。有些飞控的AUX口输出电流有限,带不动大舵机。我建议用独立的BEC供电。
  • 云台角度不对? 检查坐标系。PX4的云台控制用的是NED坐标系(北东地),俯仰角负值向下。如果你用正值,云台会朝天。
  • 相机不触发? 确认触发线接对了。PX4的相机触发默认是FMU的AUX5口,别接到其他口上。

我的习惯:每次写任务前,我都会在QGroundControl的“任务规划”页面先模拟一遍。把每个DO指令的参数都填好,然后看预览效果。虽然不能完全模拟实际飞行,但至少能发现参数填错这种低级错误。

好了,NAV_CMD和DO_CMD的区别,以及常用DO指令的使用场景,就讲到这里。记住一句话:NAV管飞,DO管做。下次写任务时,先想清楚这个动作是让飞机动,还是让设备动,再选指令。