1. 项目背景与协同理念:为什么要把“看”和“干”拆开
无人机集群协同这两年越来越热,但很多人一开始的理解就是“多飞几台飞机”。真正跑过项目的人都知道,如果只是让几台无人机各自飞各自的航线,那充其量算“并行作业”,和“协同”二字没什么关系。我最早接触这类需求,是在一个农业植保的项目里:一大片农田需要先识别病虫害区域,再有针对性地喷洒,而不是整片地无差别打药。传统做法是一台无人机先飞一遍拍图,人回来分析半天,再规划航线让另一台去作业,整个流程下来光数据中转就浪费大半天。
后来我们把流程改成了“侦察-作业”双机协同:一架无人机负责低空勘察、实时识别目标区域,另一架(或者几架)跟在后面,按前机实时传回的目标坐标直接过去作业。这个改动看着简单,实际跑通却涉及目标识别、坐标换算、任务分配、机间通信、动态避障等一系列问题。这个系统的核心思想就一句话:把“发现目标”和“处理目标”两件事交给不同角色去做,侦察端负责广域感知和决策,作业端负责精确执行,两者通过实时链路配合。这样做的优势很明显,一个侦察机可以引导多台作业机,作业机不需要挂载昂贵的感知设备,成本降低,整体效率也上去了。
这套架构能用的场景不止农业。电力巡检里,一台侦察机发现绝缘子发热异常,作业机就可以带着检修工具或清洁装置精准飞过去处理;应急搜救里,侦察机发现被困人员,作业机就能投送物资或引导地面救援;环保监测里,侦察机定位污染源,作业机就过去采样。可以说,凡是“先找后干”的无人机作业场景,都可以套这个协同框架。
这篇内容我会从系统设计的角度,把整个集群侦察-作业协同系统的原理、架构和实现细节完整拆开。包括四层架构怎么搭、侦察端的定位误差怎么控制、多机任务怎么分配、通信链路怎么设计、从仿真到真机部署要踩哪些坑。适合正在做无人机集群项目、或者想从单机作业往集群协同方向转型的开发者参考。不管你用的是PX4还是ArduPilot,这套思路基本都能迁移。
2. 系统总体架构设计:四层结构里的职责边界
2.1 从感知到执行的完整链路
我习惯把整个协同系统拆成四层:感知层、通信层、决策层、执行层。这个分层不是拍脑袋定的,而是踩过单机程序改集群的坑之后总结出来的。如果你一开始就往一台飞机的代码里堆逻辑,后面加第二台、第三台的时候,代码耦合会把你折磨到怀疑人生。分层的目的只有一个:让每一层只关心自己的事,层与层之间通过定义好的接口交互。
感知层:侦察机上搭载的可见光/多光谱相机、激光雷达、RTK定位模块。这一层的核心是把原始传感器数据变成“有意义的信息”——比如“前方50米有一片病虫害区域,边界坐标是这些”。
通信层:负责机间和机地之间的数据交换。包括数传链路(传输位置、状态、任务指令)和图传链路(传输实时图像)。这个层经常被低估,实际却是整个系统的命脉。
决策层:跑在机载边缘计算单元或者地面站上。负责接收感知层的信息,做任务分配、路径规划、冲突消解。这一层的算法逻辑决定了集群的“智能程度”。
执行层:作业机的飞控和作业载荷,比如喷洒系统、抛投器、机械臂。这层只干一件事:飞到指定坐标,执行指定动作。
四层之间是单向依赖的关系:感知层向上报告,决策层向下指令,通信层是中间的血管。这样设计的最大好处是,你想换更好的侦察相机、换更快的计算板、甚至换一套飞控系统,都只动某一层,其他层不用跟着翻工。
2.2 集中式决策和分布式决策怎么选
集群协同的决策架构,业内争论了很多年。集中式是一台地面站(或者一台领航机)收集所有飞机的位置和目标信息,统一算完任务分配再下发给每台飞机。分布式是每台飞机自己算,通过通信链路互相协商。这两个方案我都实际跑过,各自的坑很清楚。
集中式的优势是全局最优,所有信息都在一个节点里,分配算法容易收敛。缺点是单点故障风险大,地面站一挂,全集群傻眼。另一个隐藏问题是通信压力:所有飞机都要把状态高频上报,节点多了之后,地面站那边的数据吞吐量会涨得很快。
分布式的好处是没有中心节点,单机挂了不影响整体,扩展性好。坏处是,你要处理“分布式一致性”这个老大难问题。两架飞机同时发现一个目标,该谁去?多架飞机同时算出来的分配方案不一致怎么办?这些都要靠协议去兜底。
我们最终采用的是“集中式为主、分布式兜底”的混合方案:正常情况下,地面站做全局决策;一旦通信链路恶化,飞机自动切换成本地协同模式,相邻飞机之间用小范围协商继续完成任务。这套机制的核心是状态机切换,地面站接口连续超时超过一定阈值,各机自动进入分布式模式。代价是会损失一部分全局最优性,但至少不会整个任务崩掉。
3. 核心模块与关键技术实现:每一环都是坑
3.1 侦察端的实时目标检测与地理定位
侦察端的核心任务是“看得见,还说得清在哪”。图像目标检测部分,现在主流做法是用YOLO系列模型跑在机载边缘计算上(比如NVIDIA Jetson Orin)。选型上,YOLOv8-s或者YOLOv8-m在算力和精度之间比较平衡,实测在Jetson Orin Nano上能跑到30FPS左右,满足实时性要求。要注意的是,模型训练数据的质量直接决定识别率,建议用目标区域的实地拍摄数据做数据增强,单纯用公开数据集,换一个光照条件效果就崩。
比“看见”更难的是“说清在哪”。这里要做像素坐标到地理坐标的换算。简化模型下,无人机悬停或者平飞时,目标的地理坐标可以近似为:
lon_t = lon_u + (x_c - W/2) * GSD / (111320 * cos(lat_u)) lat_t = lat_u + (H/2 - y_c) * GSD / 110540其中lon_u、lat_u是无人机当前经纬度,x_c、y_c是目标在图像中的像素坐标,W、H是图像宽高,GSD(地面采样距离)由飞行高度和相机视场角计算:
GSD = H_flight * pixel_size / focal_length如果用的是带云台的相机,还非得把云台的俯仰角和航向角加进去做旋转矩阵变换,否则误差会大得离谱。实测经验是:在60米高度,用24mm焦距镜头,定位误差能控制在3-5米内;如果相机有俯仰角不矫正,误差会直接飙到20米以上,作业机飞过去什么都干不了。
这里有个很容易忽略的细节:侦察机在运动过程中拍照,目标的实时坐标会随着侦察机的移动而变化。所以发给作业机的目标坐标必须带时间戳,作业机要根据目标的运动趋势做外推预测。如果是静态目标(比如病虫害区域),这个时间戳主要用来判断信息的新鲜度;如果是移动目标,就需要加卡尔曼滤波做轨迹预测。
3.2 多机任务分配:从匈牙利算法到市场机制
任务分配是整个协同系统的“大脑决策”。经典做法是建一个代价矩阵,用匈牙利算法求指派问题的最优解。代价函数可以写成:
C(i, j) = w1 * distance(i, j) + w2 * time_unspent(j) + w3 * priority(j)其中distance(i, j)是作业机i到任务j的距离,time_unspent(j)是任务j已经等待的时间,priority(j)是任务优先级,w1、w2、w3是权重系数。这样设计的目的很直白:让飞机优先处理“离得近的”“等得久的”“重要的”任务。
匈牙利算法适合任务数和飞机数都固定的静态场景。但实际任务中,目标是一个个被侦察出来的,任务列表随时在变,每次重新跑一遍匈牙利算法计算量不小。所以我后来更倾向用市场机制(Auction-Based)做分配:每架飞机根据自己到候选任务的距离报一个“价格”,任务管理器选价格最低的飞机去执行。这个方案是分布式的,支持动态加任务,实现起来也不复杂。
权重系数怎么定?我建议用仿真去整定,不要拍脑袋。我们在Gazebo里搭了仿真环境,用随机生成的任务场景反复跑,观察不同权重下“平均任务完成时间”和“总飞行里程”两个指标。经验值是:距离权重w1取0.6,等待时间w2取0.25,优先级w3取0.15。这个组合在日常农业场景下表现比较稳,但你需要根据自己场景调。
3.3 作业端的路径规划与动态避障
作业机收到目标坐标之后,要做两件事:规划一条安全的航线过去,然后在飞行过程中避免撞上侦察机或者其他作业机。路径规划这块,A算法在二维栅格地图上很好使,但无人机是三维运动,要扩展成3D A,或者用RRT系列做快速探索。实际项目中,大范围转移用Dubins曲线(考虑无人机最小转弯半径),末端进场用3D A*避障,两层结合比较实用。
机间避障是集群项目特有的一道坎。单机避障只需要考虑静态障碍物,多机还要考虑相互之间的位置关系。最简单的方案是做“优先权避让”:每架飞机有唯一的ID,当两架飞机距离小于安全阈值时,ID小的飞机保持航线,ID大的飞机主动绕飞。这个规则在通信正常时很有效,但要是通信延迟高,飞机之间会反复横跳,产生振荡。
更稳的方法是速度障碍法(Velocity Obstacle, VO),把对方飞机当成一个动态障碍物,在当前速度空间里划出一个“会发生碰撞的速度集合”,然后从安全速度集合里选一个最接近期望速度的方向飞。这个方法在理论上是完备的,实机部署的时候要注意把VO的解算频率和飞控控制频率对齐。我们当时用MAVLink的SET_POSITION_TARGET_LOCAL_NED接口做速度控制,VO在板载计算机上跑10Hz,实测集群5架飞机在20米空域里协同飞行,没有发生过碰撞。
4. 通信与协同机制:集群的神经系统
4.1 机间自组网方案选型
通信是集群项目里最容易被忽视、又最容易出问题的环节。很多团队一开始用WiFi点对点,试飞5分钟内必出幺蛾子:延迟抖动大、丢包率高、抗干扰差。WiFi为了高吞吐设计,对移动性和低延迟天然不友好。我们后来换成了自组网模块,基于Mesh协议做动态路由,频率选在900MHz或者1.4GHz频段,优点是穿透性好、绕射能力强,在城市和山地环境下表现稳定,代价是带宽不高,传不了高清图传。
所以实际的方案是双链路:一条自组网窄带链路负责传输位置、状态、任务指令这些关键数据(数据量小,但对实时性和可靠性要求高);一条单独的5.8G图传链路负责传视频(带宽高,允许一定的延迟和丢包)。分开走之后,两条链路互不拖累,关键指令不会因为视频流量大被挤掉。
链路设计里有个核心参数:心跳包和超时阈值。我们用的心跳频率是1Hz,也就是每台飞机每秒广播一次自身状态。超时阈值设在3秒,超过3秒没收到某台飞机的心跳,就判定它失联。这个值不能太短,否则短时丢包就会误触发失联逻辑;也不能太长,否则真正失联时反应太慢,容易酿成事故。
4.2 状态同步与任务握手协议
集群协同有一个容易被忽略的细节:各机对“当前任务集合”的认知必须一致。如果不做一致性控制,就会出“两架飞机争一个任务”或者“一个任务没人处理”的乱象。我们设计了一套轻量级的任务握手协议,流程是这样的:
- 侦察机发现目标,广播一条
TASK_PROPOSE消息(带目标ID、坐标、优先级、时间戳)。 - 任务管理器(集中式模式下是地面站,分布式模式下是各机协商)根据当前负载和代价矩阵,发送
TASK_ASSIGN给选中的作业机。 - 作业机收到后回
TASK_ACK,表示接受任务。 - 任务管理器收到ACK后,广播
TASK_CONFIRM,通知所有节点这个任务已有人认领。 - 其他节点收到CONFIRM后,把这个任务标记为“已分配”,不再参与竞争。
为了保证不丢消息,还要给这套协议加超时重发机制。发TASK_ASSIGN后3秒没收到ACK,任务管理器就换一架作业机重新分配。加了这套机制之后,多机抢任务的问题基本绝迹。
状态同步方面,我们用了简单的全量广播+本地快照的方式。每台飞机本地维护一个状态表,记录其他飞机的最新位置、速度、任务状态。收到心跳包就更新对应条目。这个方案在节点数少于10时够用,节点再多就要考虑做分区域广播或者利用地面站中转,不然全网广播风暴很快把链路带宽吃满。
5. 实操过程:从仿真验证到真机联调
5.1 仿真环境搭建:Gazebo + PX4 SITL
我强烈建议,任何集群项目都先在仿真里把逻辑跑通,不要直接上真机。不是说仿真万能,而是集群出问题的时候排查成本太高——6台飞机同时在天上,任何一台失控都可能伤及另外几台,地面人员的安全也受影响。仿真里把所有边界情况都磨一遍,上真机就只是处理“仿真和现实的差异”。
我们用的仿真组合是Gazebo作为物理环境,PX4软件的仿真模式(SITL)跑飞控,机载决策算法跑在独立的ROS 2节点里。PX4 SITL的好处是,飞控代码和真实飞行的代码完全一致,只是不接硬件,所以从仿真切到真机,飞控参数不用动。每台飞机是一个独立的Gazebo模型,有自己的SITL实例和MAVLink通道。
启动流程不再赘述,关键在于验证场景的设计。我们做了三类用例:
- 单侦察机发现5个静态目标,2台作业机分工处理,验证任务分配逻辑。
- 侦察机连续飞行时动态上报目标,作业机一边执行一边接收新任务,验证动态任务插入。
- 故意切断某一台机器的通信,观察集群是否能自动完成分布式模式切换。
这三个用例基本覆盖了日常能遇到的绝大多数问题。
5.2 关键参数整定,从仿真到真机的修正项
仿真跑通之后,直接照搬参数上真机是行不通的,有几个参数必须实机重调。
第一个是任务分配代价函数里的权重。仿真里我们用的是上文说的0.6/0.25/0.15,真机测试发现,实际飞行中飞机的转弯能耗比仿真大不少,所以distance权重调高到了0.7,否则无人机频繁在小范围内转来转去,电量掉得非常快。
第二个是机间安全距离。我们仿真设定的一架飞机周围3米为安全半径,但真机受GPS精度和飞控响应延迟影响,实际定位误差叠加可能超过3米。最终我们把安全距离加到了8米,并且把速度障碍法的避让触发距离从10米增加到了15米。
第三个是侦察定位误差的补偿。仿真里我们假设目标定位误差为0,真机上侦察机RTK定位精度能到厘米级,但相机标定的误差、云台姿态角误差仍然存在。我们实测每架飞机都要做一次“目标定位校准”:让飞机飞到已知坐标的地面标记点上方,拍照解算,算出该机的系统误差偏移量,然后在坐标解算时加上补偿。不同飞机这个偏移量还不一样,必须逐机标定。
5.3 真机联调流程与现场注意事项
真机联调我总结了一套固定流程,每次按这个流程走,出问题的概率大大降低:
- 静态联调:所有飞机不开桨,只通电,检查地面站能不能收到所有飞机的状态数据,通信链路是否正常。用地面站发送任务指令,观察机载端是否正确收到并在日志里打印。
- 单机起飞测试:先只起飞一架飞机,手动控制绕着场地飞一圈,确认飞控参数、RTK信号、链路稳定性都正常。
- 双机协同测试:加一架侦察机,做一次完整的“发现目标-定位-分配-作业”流程,记录端到端延迟和定位误差。
- 逐步扩编:每次增加一架飞机,观察集群稳定性和通信负载。不要一口气从2架加到6架,出了问题很难定位。
现场还有一些只有飞了才能体会的细节。比如,多台无人机同时启动的时候,电磁干扰会很严重,GPS信号可能跳变。我们在实践中把起飞间隔拉长了至少10秒,等上一台的位置和航向完全锁定之后再起飞下一台。再比如,场地周围如果有金属围栏或者高压线,RTK信号和多路径效应会受到很大影响,这类区域的测试要格外谨慎。
还有一件很重要的事:集群飞行前,一定在地面站软件里设置好电子围栏和返航逻辑。真机上我们设置了双重保护:一旦某台飞机偏离预设任务区超过50米,或者通信断开超过5秒,自动触发返航,飞行高度先爬升到安全高度再飞回起降点。
6. 常见问题与排查技巧实录
集群协同系统调试期间,踩坑是家常便饭。我把最有代表性的几个问题整理成了速查表,基本覆盖了所有新团队会遇到的高频故障。
| 症状 | 根因 | 排查思路和解决办法 |
|---|---|---|
| 作业机飞到的位置和目标偏差大于10米 | 侦察端云台姿态未校正 | 检查云台俯仰角和航向角补偿矩阵,做地面靶标标定,逐机修正系统误差偏移 |
| 多架作业机同时飞向同一个目标 | 任务握手协议的CONFIRM消息丢失 | 检查TASK_ASSIGN超时重发机制,确认所有节点心跳正常;核查任务状态表的本地更新逻辑 |
| 两架飞机在避让时反复横跳 | 通信延迟导致速度障碍法振荡 | 增大避让触发距离;给速度指令加低通滤波;在通信连续超时场景下切换为优先权避让模式 |
| 机载目标检测帧率骤降 | 边缘计算单元过热降频 | 检查散热措施,Jetson系列长时间高负载必须主动散热;适当降低输入图像分辨率可以减少算力消耗 |
| 集群模式下地图界面卡死 | 全网广播风暴 | 节点超过8个时改用分区域广播或地面站中转;降低状态广播频率到2Hz,任务指令独立通道传输 |
| GPS信号不稳定,位置跳变 | 多机电磁干扰或周边金属结构多路径效应 | 拉长起飞间隔;检查GPS天线布局;在已知强干扰区域改用视觉里程计辅助定位 |
还有一个排查经验值得单独说。机间通信偶尔丢包,但不确定是设备问题还是环境问题的时候,我们会在现场布置一台频谱分析仪,记录整个测试时段内相关频段的底噪和干扰信号特征。排查过一次才发现干扰源是场地旁边的安防雷达,频率恰好落在我们数传频段附近。后来换了频点,问题立刻消失。所以我建议,固定测试场地的团队,花点时间做一次电磁环境摸底,把测试场地周边的频段占用情况记录下来,能省掉后面很多莫名其妙的故障排查时间。
另外一个常见认知误区是,目标检测模型在仿真里准确率很高,上真机就拉胯。原因大多数是训练数据的分布和实际场景差异太大。比如你用网络公开的农田病虫害数据集训练,拿到某个具体区域去用,光照角度、作物品种、土壤背景都不一样,模型自然失准。解决办法是预留至少一天时间,用侦察机实地采集一批目标区域图像,人工标注后做增量训练。这个步骤建议作为项目流程的一部分写进计划,不要等现场出了问题才补。
机间避让的振荡问题,在真机上比仿真严重得多。仿真里通信延迟是固定的,真机上却是波动的。我们最后的解决方案是把速度障碍法的计算频率降到5Hz,同时把输出速度做了一阶低通滤波,时间常数设0.5秒。这样避让动作会“迟钝”一些,但换来了稳定。集群系统里,追求每个时刻的理论最优解不如保证整体系统不发散——这个理念在调参后期越来越深地刻进我的脑子里。
再说一个小细节。侦察机和作业机如果型号不同,它们的最大飞行速度、转弯半径、刹车距离都不一样。任务分配代价函数里如果不考虑这些差异,就会出现侦察机把目标信息传过来,作业机因为飞太慢根本追不上,或者转弯半径太大飞不过去的情况。我们在代价函数里加了一个“机动能力匹配度”的惩罚项,把每架飞机的最大速度和最小转弯半径作为约束加进去,宁可多飞一点距离,也要派一架能真正飞到位执行任务的飞机。
最后聊聊项目节奏。如果一个团队之前没有做过集群项目,我建议把时间按“仿真40%、参数整定20%、真机联调40%”的比例来分配。很多团队喜欢在仿真里磨很久,觉得逻辑完美了再上真机,但实际上真机能暴露的问题是仿真完全模拟不了的。反过来,如果仿真没做扎实就直接上真机,一个简单的消息协议bug就可能摔一架飞机。用我的经验来说,仿真阶段至少要把任务分配、避让、通信中断这三个核心逻辑跑到“连续运行2小时无异常”,这算是一个比较靠谱的放行标准。
我们后来在这个架构上继续扩展,加入了第三类角色——充电保障机。当作业机电量低于阈值时,保障机飞到它附近,用无线充电板或者直接更换电池模块给它续能。这个扩展只改了任务分配环节的约束条件,其他层几乎没动。这让我再次感慨,前期把系统分层做清楚,后面的迭代成本能省下太多。