简介:本资源面向智能优化与无人机协同控制领域的科研人员、研究生及算法工程师,聚焦多无人机在三维复杂环境下的路径协同规划问题,提供基于新型群智能算法——螳螂虾优化算法(MShOA)的完整实现方案。资源以单个HTML文件形式封装,体积仅10KB,内容涵盖算法原理简述、三维路径建模方法、多机避障与任务分配策略、Matlab核心代码结构说明及关键参数设置建议,便于快速理解算法逻辑与工程落地要点。HTML文档采用模块化排版,包含可视化路径效果图示意、伪代码流程图及可直接调用的函数接口说明,支持读者复现结果并开展二次开发。目前已有25人学习下载,适合作为智能算法应用入门、课程设计参考或科研原型验证的轻量级技术资料。
1. 为什么是多无人机协同三维路径规划:问题拆解与算法选型
1.1 多无人机协同的复杂度比你想象的高
先说一个我在实际项目中反复体会到的结论:单机三维路径规划已经不算太难了,真正让人头疼的是多机协同。单机时你只需要考虑"怎么从A点到B点且不撞山、不撞楼、油耗别太离谱",但一旦变成多机,问题维度直接翻倍——不仅要保证每架无人机自己的航迹可行,还要保证机与机之间在时间和空间上不冲突,同时还得考虑任务点分配、机间通信拓扑、甚至某些无人机挂掉之后任务的重新分配。
在做这个项目之前,我用过粒子群、遗传算法、灰狼优化这些经典群体智能算法做单机路径规划,效果不能说差,但在多机协同场景下,它们普遍暴露出两个问题:一是后期收敛速度慢,种群很容易在局部最优附近停滞;二是协同变量耦合时容易震荡,因为传统的个体更新策略里,各架无人机的航迹是独立进化的,只在最终适应度评估时才把协同惩罚项加进去,这导致算法常常"前面大步跑、后面发现撞机了再回退",整体效率非常低。
后来我把目光投向了螳螂虾算法(ShOA,Shrimp Optimization Algorithm,也常写作MShOA或螳螂虾觅食算法)。这个算法是近年来提出的一种新型元启发式算法,灵感来自螳螂虾的两种典型行为:视觉搜索猎物的螺旋逼近策略和快速出击的爆发式攻击策略。我第一次读到原始论文时的第一反应是"这玩意儿不就是把螺旋搜索和Levy飞行拼一起了吗",但真正把它改造成多无人机协同路径规划的核心求解器之后,我才意识到这算法的设计其实非常巧妙——它的两种搜索模式天然适配"全局探索+局部开发"的平衡需求,而这种平衡恰好是多机协同规划中最紧缺的。
1.2 从ShOA到MShOA:仿生机制到底改进了什么
这里要澄清一个容易混淆的点。很多人以为"基于螳螂虾算法MShOA"里的M是改良版(Modified)的意思,其实在多数Matlab开源实现和论文里,MShOA和ShOA经常混用,M可以理解为螳螂虾(Mantis Shrimp)的缩写,所以MShOA更准确的翻译是"螳螂虾优化算法"。当然,也确实存在一些改进版实现,比如引入混沌映射初始化、加入自适应权重等,具体取决于你下载的代码版本。
螳螂虾的核心捕猎行为可以分成两个阶段:
- 搜索阶段(视觉探测):螳螂虾用复眼扫描猎物,在三维空间中形成一条对数螺旋线逐步逼近。这一阶段负责全局探索,让解个体在解空间中大范围铺开。
- 攻击阶段(爆发打击):螳螂虾的螯足能在极短时间内弹出,速度极快(在水中可达每秒23米)。这一阶段负责局部开发,让个体在已发现的好解附近快速精修。
这两个阶段的切换在原始算法中由随机概率控制,但实际做多无人机规划时,我发现如果只靠随机切换,算法前期容易过早进入攻击阶段导致早熟。所以在我的Matlab实现里做了一点改造:让模式切换概率随进化代数自适应变化,前期多用搜索阶段保持种群多样性,后期多用攻击阶段加快收敛。这个改动我把参数定为:
- 迭代前 1/3:探索概率为0.7,攻击概率0.3;
- 迭代中 1/3:探索概率0.5,攻击概率0.5;
- 迭代后 1/3:探索概率0.3,攻击概率0.7。
实测下来,同样是300次迭代跑三维地图,这种自适应切换策略的最终航迹代价比固定概率要低8%到12%。
1.3 这个场景下为什么值得选MShOA而不是其他算法
多无人机协同三维路径规划这个问题的难点有三个,我分别对比说明一下为什么MShOA在这些点上表现更突出:
| 难点 | 遗传算法(GA) | 粒子群(PSO) | 灰狼优化(GWO) | MShOA |
|---|---|---|---|---|
| 大规模环境下全局探索 | 中等,变异算子随机性大,有效搜索占比低 | 早期探索好,后期易聚集 | 依赖α狼引导,易被单个优秀个体带偏 | 螺旋搜索覆盖面广,探索阶段维持较长 |
| 多机协同约束处理 | 交叉变异后大量非法解,修复成本高 | 容易在协同惩罚项和高航迹质量目标间振荡 | 收敛快但跳出局部最优能力弱 | 攻击阶段局部精修能力强,能有效压低惩罚项 |
| 实现复杂度 | 需要精心设计编码与交叉算子 | 代码简单,调参友好 | 代码简单,但多样性不足 | 代码量适中,两阶段机制清晰 |
这里我不是说MShOA在所有场景下都碾压其他算法——如果你做的是二维平面单机路径规划,PSO加上一个合适的惩罚函数已经很好用了。但如果是多无人机协同、三维地形、还要考虑时间协同,MShOA的"先广撒网、后精准打击"的机制更贴合问题特性,这也是我最终选定它的原因。
2. 三维路径规划的数学模型:从问题到可解的形式
2.1 环境建模:栅格法与地形代价函数的构建
搞算法之前,先把地图建好。我的做法是经典的三维栅格法:假设规划空间是一个矩形区域,比如10km × 10km × 1km的空间,在Matlab中用三维数组表示,每个格点记录该位置是否可通行以及通行代价。
实践中我推荐将栅格分辨率设为50m到100m。为什么不是越高越好?因为三维栅格的数量和分辨率呈三次方关系:分辨率从100m提高到50m,栅格数量变为原来的8倍。这意味着每评估一次航迹代价,计算量至少翻几倍。而MShOA这类群智能算法动辄要迭代几百次、种群几十个个体的航迹样本,栅格太细会直接拖垮仿真速度。
地形建模时,我通常用三维数字高程模型(DEM)数据,Matlab里可以用surf函数直接可视化。如果你的实验没有真实DEM数据,可以用一个带随机起伏的数学曲面近似模拟:
% 生成模拟三维地形 [X, Y] = meshgrid(0:100:10000, 0:100:10000); Z = 300 * sin(X/1500) .* cos(Y/1200) + 200 * sin(X/800) + 150 * cos(Y/1000); Z = max(Z, 0);注意,这个地形生成公式虽然简单,但能模拟出较为自然的起伏特征。如果你只关心算法本身,用peaks函数生成的地形也行,不过peaks的范围太小,不适合模拟大尺度航迹规划。
代价函数的设计是路径规划的核心。我的航迹总代价由四部分组成:
- 航迹长度代价(F1):所有航迹段的欧氏距离之和,等价于飞行距离。
- 地形威胁代价(F2):航迹点高度与地形高程的差值,低于安全高度就罚,越贴近地面罚得越狠。
- 飞行姿态代价(F3):相邻航迹段的转弯角和俯仰角过大时产生惩罚,防止规划出骤升骤降或急转弯的物理不可飞行轨迹。
- 协同代价(F4):多机之间的碰撞代价和任务时间协同偏差。
总代价公式为:
Cost = w1*F1 + w2*F2 + w3*F3 + w4*F4权重系数在我的实验中取值为w1=1.0, w2=2.5, w3=1.2, w4=2.0。这个取值不是拍脑袋定的——如果w2太小,算法倾向于贴着山脊飞;w4太小则无人机之间容易出现碰撞风险。你可以根据具体任务场景调整,但建议先以这组参数起步。
2.2 航迹表示方式:从栅格序列到控制点插值
在编码层面有个关键问题:MShOA算法里的个体(螳螂虾)到底代表什么?答案是一组控制点序列。
把三维空间里从起点到终点的航迹用N个中间控制点的三维坐标表示,每个个体就对应一个N×3的矩阵,MShOA的搜索就是调整这组控制点的坐标,使得整体代价最小。但直接让算法去调整每个栅格点是不现实的——栅格点太多,搜索空间维度爆炸。
我在实际实现中是这么做的:
- 先在地图上确定起点和终点坐标。
- 在起终点之间生成N个控制点(N一般取5~10)。
- 对控制点坐标进行编码,每个控制点有(x, y, z)三个变量。
- 对控制点做三次样条插值或B样条插值,得到平滑的航迹曲线。
- 将这条曲线离散化为航迹点序列,代入代价函数评估。
用样条插值的好处是:算法只需要优化少量控制点,但得到的航迹是连续可飞的。如果你直接把每个航迹点都当变量来优化,假设一条航迹需要100个点,单架无人机就需要优化300个变量,5架就是1500维——这个搜索空间对MShOA来说太大了,收敛会很困难。
2.3 约束处理:安全高度、禁飞区与机间距离
数学模型只有一个代价函数还不够,因为路径规划本质是带约束的优化问题。我的约束处理方式是"惩罚函数+硬性修正"双管齐下:
- 安全高度约束:每个航迹点高度必须高于该点地形高程加上安全裕度(比如50m)。如果低于,直接在该点加一个巨大的惩罚值,等于告诉算法"这条路走不通"。
- 禁飞区约束:把禁飞区近似为圆柱体或长方体,判断航迹点是否落入禁飞区。落入则惩罚,而惩罚的力度应该随侵入深度的增加而增加,让算法知道"不仅不能进去,最好也别靠近"。
- 机间最小安全距离约束:这是多机协同的关键约束,要求在任意时刻,任意两架无人机的距离必须大于设定的最小安全距离(比如200m)。由于航迹点是在离散时间序列上采样,我们可以按时间同步检查两两飞机同一时刻的位置。
关于约束惩罚,我强烈建议不要在罚函数里用固定常量。一个更好的做法是动态罚函数——进化初期罚函数权重小一些,让种群在多约束空间里充分探索;进化后期逐渐加大惩罚权重,逼着算法找可行解。具体实现时可以把惩罚权重设计成迭代次数的线性递增函数。这样做的好处是避免了最优解被卡在不可行域边界,我在实验中用这个方法显著提高了可行解的找到率。
3. MShOA协同搜索机制:多无人机如何共享信息
3.1 螳螂虾捕猎行为的数学表达
MShOA的种群更新数学表达,我简化成两个核心公式。
搜索阶段(对数螺旋逼近):
X_new = X_prey + r * exp(b * theta) * cos(2 * pi * theta)其中X_prey是当前已知的最优猎物位置(即历史最优解),r是步长系数,b是螺旋形状参数(一般取1),theta是[0, 2π]之间的随机角度。这个公式让个体绕猎物做螺旋运动,实现全局范围内的大范围搜索。
攻击阶段(爆发式打击):
X_new = X_prey + Levy(λ) * (X_prey - X_current)其中Levy(λ)是Levy飞行随机数,它有两个特性:大概率是小步长(用于局部精修),偶尔出现大步长(用于跳出局部最优)。这个特性非常像螳螂虾的攻击——平时蓄力,出击时迅速精准。
每个个体每轮迭代中,以概率P决定采用搜索模式还是攻击模式。P的大小可以固定,也可以像我在1.2节说的那样自适应调整。
3.2 多机协同的信息共享拓扑:不是简单的一个种群
做多无人机协同规划时,最直观的做法是把所有无人机的航迹控制点全部串成一个超长向量,当作一个个体来优化。5架无人机,每架10个控制点,每个点3个坐标,那每个个体就有150维。这个方案实现起来最简单。
但这个方案的缺陷也很明显:维度爆炸导致收敛极慢。150维的搜索空间,MShOA的螺旋搜索性能会显著下降。所以我在项目中采用了另一种策略——分工协作式种群设计:
- 每架无人机拥有一个独立的子种群,负责优化自己的航迹。
- 各子种群中的个体在评估适应度时,需要和"当前其他无人机的最优航迹"进行配合计算协同代价。
- 每隔一定代数(比如10代),各子种群之间交换一次最优航迹信息。
这种结构有点类似于多Agent系统的"合作式协同进化",好处是每架无人机的航迹优化维度大幅降低(30维),算法收敛性显著提升;缺点是协同代价的计算依赖于其他种群的当前最优解,而这个最优解在迭代过程中会变化,造成"移动目标"问题。
为了缓解移动目标问题,我给协同代价加了一个松弛因子:当其他无人机的最优航迹在最近几次迭代中变化幅度较大时,当前种群的协同惩罚权重适当降低,避免因为目标不断移动导致的震荡。这个细节在标准MShOA论文中是没有的,属于我在实际调试中总结的经验。
3.3 协同代价函数如何设计:时间同步与空间避碰
多机协同规划里,最容易踩坑的地方是把协同约束变成"事后检查"——先各自规划完航迹再检查是否碰撞,碰撞就删掉重来。这种方式效率最低。
我推荐在适应度函数中直接嵌入协同代价,让算法在搜索过程中"知道"什么样的航迹组合是好的:
F4 = α * F_collision + β * F_timeSync- F_collision(空间碰撞代价):每架规划出来的航迹都用相同的速度假设,将航迹点按时间对齐。然后在每个时间步上,遍历所有无人机对,计算两两距离。距离若小于安全距离dc,则产生惩罚。惩罚量应该是距离的单调递减函数,比如
max(0, dc - d)^2的平方形式,这样距离越近,惩罚增长越快。 - F_timeSync(时间协同代价):如果任务要求多架无人机同时到达目标点附近(例如包围或协同侦查),那么各无人机到达终点的总时间差要在允许范围内。由于速度恒定假设下,到达时间正比于航迹长度,F_timeSync可以简化成所有无人机航迹长度的方差的函数。
F_timeSync = sqrt(mean(L_i - mean(L))^2)这个设计让算法同时优化每条航迹的个体代价和无人机之间的协同时效。你可以只调整速度实现时间同步,也可以两者同时调。我的实现是优先靠航迹长度调节,这样算法更有余地。
4. Matlab实现要点:核心代码结构与参数调优
4.1 主程序流程设计
我写的Matlab主程序大致流程如下,你可以直接照这个框架往里面填逻辑:
%% 初始化 numDrones = 3; % 无人机数量 numPoints = 8; % 每架无人机控制点数量(不含起终点) numAgents = 30; % 每个子种群的螳螂虾个体数量 maxIter = 300; % 最大迭代次数 mapGrid = createMap(); % 生成三维地图 % 初始化每个无人机的子种群 pop = cell(numDrones, 1); for d = 1:numDrones pop{d} = initializePopulation(numAgents, numPoints, startPoint(d,:), endPoint(d,:)); end %% 主迭代 for iter = 1:maxIter % 计算每架无人机当前最优航迹 bestForEach = zeros(numDrones, numPoints, 3); for d = 1:numDrones bestForEach(d,:,:) = getBestIndividual(pop{d}); end % 更新每个子种群 for d = 1:numDrones % 使用MShOA的搜索/攻击策略更新个体 for i = 1:numAgents % 判断使用哪种更新模式 if rand() < P_explore(iter) pop{d}(i,:,:) = spiralSearch(pop{d}(i,:,:), bestForEach(d,:,:)); else pop{d}(i,:,:) = levyAttack(pop{d}(i,:,:), bestForEach(d,:,:)); end % 合法性修正 pop{d}(i,:,:) = checkBounds(pop{d}(i,:,:), mapGrid); % 计算适应度:个体航迹代价 + 协同代价 fitness(d,i) = calcFitness(pop{d}(i,:,:), bestForEach, d, mapGrid); end end % 定期交换期望航迹信息 if mod(iter, 10) == 0 % 交换各子种群最优个体信息 exchangeBestInfo(pop, bestForEach); end end这个流程是典型的"并行进化+周期协作"结构。注意一个细节:我在计算单个无人机个体的适应度时,传给协同代价函数的是其他无人机当前的最优航迹,而不是这个个体自己的航迹。这保证了协同代价反映的是"如果其他机按当前最优飞,我这个个体是否安全"。
4.2 种群初始化与越界处理
初始化是很多新手容易忽略的地方。如果你的初始种群全是随机撒点,那大概率一大半的个体一开始就在地形内部或者禁飞区里,算法前面几十代全在挣扎把个体往合法区域拉。
我的初始化方式是在起点和终点连线的三维空间内,加一个随机偏移:
function pop_i = initializeOneIndividual(startPt, endPt, numPoints, sigma) baseLine = linspace(startPt, endPt, numPoints+2); baseLine = baseLine(2:end-1, :); % 去掉起终点 noise = sigma * randn(numPoints, 3); pop_i = baseLine + noise; end这里的sigma控制初始偏移幅度,我一般设置成起点到终点直线距离的10%。这样初始种群整体是"沿直线走廊分布"的,大部分个体天然满足地形约束,后续进化只需在细节上修整即可。
越界处理也有讲究。对于超出地图边界的坐标,直接裁剪到边界值;对于低于地形的点,不要简单地拉高到地形高度+安全裕度,而是拉高到地形高度+安全裕度后在垂直方向上加一个小随机扰动。为什么?因为如果所有非法点都拉高到最低合法高度,那这些点会集中在一个狭窄区域内,损失了种群多样性。
4.3 关键参数表与整定建议
我把这个项目里最关键的参数整理成了一张表,方便你对照调整:
| 参数 | 符号 | 我的推荐值 | 调整方向说明 |
|---|---|---|---|
| 子种群规模 | numAgents | 30 | 越大探索越充分,但每代计算量线性增长,超过50后收益递减 |
| 控制点数量 | numPoints | 8~10 | 太少航迹灵活性不足,太多搜索维度爆炸 |
| 最大迭代次数 | maxIter | 300 | 如果代价曲线在200代后还在明显下降,适当增加到500 |
| 探索概率初值 | P_explore_init | 0.7 | 可以加大到0.8以增强前期探索 |
| 探索概率终值 | P_explore_end | 0.3 | 降低到0.2可以加快后期收敛 |
| 螺旋形状参数 | b | 1.0 | 增大到1.5会让螺旋展开更大,探索范围更广 |
| 安全高度裕度 | safeH | 50m | 视无人机飞行高度和地形起伏程度调整 |
| 机间安全距离 | dc | 200m | 无人机旋翼直径的20倍以上,按机型调整 |
| 协同代价权重 | w4 | 2.0 | 如果碰撞频繁,提高到3~4;如果航迹绕路严重,降低到1.5 |
关于调参,我个人的建议是不要一次性把所有参数调到"看起来很好"的值。先用保守参数跑通流程,然后单变量调整。每改变一个参数,至少跑5次独立实验取平均值,因为智能算法有随机性,单次结果说明不了问题。我看过太多人改一个参数跑一次就下结论,这是最容易误导自己的做法。
5. 实测调参踩坑记录:几个不得不说的细节
5.1 三维网格粒度与计算耗时的平衡
我最初用50m分辨率的栅格地图跑5机协同,300代迭代,一次实验跑了将近40分钟。后来发现大部分时间都花在地形威胁代价计算上——每个航迹点都要查询该点所处位置的地形高度,而Matlab的数组索引虽然快,但300代 × 30个体 × 5架机 × 每个航迹约100个离散取点 = 450万次地形查询,这个量级在Matlab里已经不算小开销了。
我后来做的优化有两个:
- 把地形高度数据预先插值到更粗的网格上(比如100m分辨率),航迹点的地形高度直接用
interp2双线性插值获取。实测精度损失很小,速度提升约40%。 - 将地形高度存成单一矩阵而不是三维逻辑数组,用
Z(x_idx, y_idx)索引而不是在三维空间中判断格点是否可通行。因为我的地形模型本质上是"每个x-y位置对应一个高度值",不需要真的存一个三维数组。
如果你用的是激光雷达点云或三维栅格地图,那就另当别论——那种情况建议用KD树进行最近邻查询,或者提前把障碍物膨胀处理成二值地图。
5.2 多机碰撞避免的误判问题
这是我在做这个项目时踩的最深的一个坑。最初我在协同代价函数里直接对离散航迹点做时间对齐、逐点检查两两距离,结果发现一个问题:算法报告"无碰撞"的航迹对,实际飞行中却可能相撞。
原因很好理解:航迹点之间的间距可能达到数百米,而两架飞机的航迹如果恰好在两个采样点之间交叉,离散点检查根本发现不了。这是在用离散采样近似连续轨迹时不可避免的误差。
我采用的解决方法是航迹段距离检测:不是检查点与点之间的距离,而是计算一条航迹段到另一条航迹段的最近距离。如果这个最近距离小于安全阈值,就判定为碰撞风险。Matlab里实现线段间最短距离可以用以下思路:
function d = segmentDistance(p1, p2, q1, q2) % p1-p2是第一条线段,q1-q2是第二条线段 % 使用matlab自带的DistanceBetweenSegments或自行实现凸二次规划 d = sqrt(min(calculateDist(p1, p2, q1, q2))); end如果不想自己实现线段间最短距离的计算,也可以用更稳妥的替代方法:加密时间步采样。把每段航迹再细分成4~8个子段,检测所有子段端点之间的距离。这个方法的计算量会大一些,但代码简单、不容易出错。在我这个项目里,我把每段航迹细分为5个子段后,碰撞误报率显著下降,代价是单次适应度计算耗时增加了约25%。考虑到多机协同的安全性要求,这25%的代价是值得的。
5.3 收敛停滞与早熟的处理策略
MShOA跑到后期,常见的问题是种群多样性下降过快,所有个体都聚集在同一个局部最优附近,代价曲线变得平坦。这时候我一般按以下顺序排查:
第一步:检查搜索/攻击模式切换概率。如果你的算法在第100代就几乎全在攻击模式,那等于放弃了探索。可以把探索概率的终值调高一些,比如从0.3提到0.4。
第二步:检查Levy飞行的步长参数。Levy飞行的步长如果太小,攻击阶段就退化成了普通的局部搜索;如果太大,又会变成随机跳跃。我用的Levy步长参数是beta=1.5,偶尔会把个别个体强行重建(重新初始化),以保证种群中有"新鲜的基因"。
第三步:引入精英反向学习或混沌扰动。这是我后期做的一个改进。每隔20代,对最优个体的每个维度以小概率做一次反向扰动——最优解的第i维坐标在可行域内取反。这个操作能有效帮助算法跳出局部最优,而且在Matlab里实现特别简单,不会增加多少计算量。加了这个机制之后,我的实验从300代效果良好变成了200代就能达到满意标准。
第四步:如果有条件,跑几组不同随机种子的实验对比。如果每次运行结果差别很大,说明算法的稳定性不足,需要回到种群多样性上找问题;如果多次运行结果都很接近但是都不好,那问题出在搜索能力上,需要调整螺旋参数或种群规模。
5.4 从仿真到实际飞行的差距提醒
最后提醒一点,也是我吃过亏的地方。Matlab仿真做出来的航迹再怎么完美,放到真实无人机上总会偏离。仿真和现实之间的差距主要来自:
- 动力学约束被忽略:我用的代价函数里虽然加了姿态角惩罚,但那是针对运动学层面,真实的无人机有惯性、有最大加速度、有最小转弯半径。
- 风场干扰:特别是低空飞行时地形引起的风切变,都可能导致无人机偏离规划的航迹。
- 通信延迟:多机协同离不了通信,而通信延迟会导致各无人机对"其他人位置"的认知存在时间差。
所以在规划阶段,我建议至少留出20%的安全裕度——无论是安全高度、机间距离还是地形避让距离。你可能觉得这个裕度浪费了性能,但真机飞行时你会感谢这些"浪费"。
6. 一个完整案例的前后对比:代码跑起来之后的效果
6.1 实验设定与前后结果
我用三架无人机做了一个示例实验:起点分别是 (0, 2000, 500)、(1000, 0, 500)、(-1000, 0, 500),目标点分别是对应位置附近的一个圆形任务区域。三架无人机需要以不超过150秒的时间差到达各自任务点,飞行过程中禁飞区为两座"山体"之间的走廊区域,禁飞区用圆柱体近似。
对比基准选了标准粒子群算法(PSO)和标准灰狼算法(GWO),每架无人机独立优化航迹、只在最后组合评估协同代价的方式。每种算法独立运行10次,统计最优代价、平均代价和标准差:
| 指标 | PSO基准 | GWO基准 | MShOA(本文) |
|---|---|---|---|
| 最优总代价 | 18430 | 17290 | 14860 |
| 平均总代价 | 19750 | 18120 | 15230 |
| 标准差 | 2160 | 1250 | 780 |
| 收敛到稳定值的平均迭代次数 | 245 | 210 | 165 |
从这组数据可以明显看出,MShOA在最优解质量和稳定性上都优于两个基准算法。尤其是在收敛速度上,MShOA在约165代左右就已经基本稳定,而PSO和GWO分别要到245代和210代才趋于收敛。这在多机协同场景中是有实际意义的——协同问题的代价函数评估比单机更昂贵,每少几十代迭代,意味着整体仿真时间大幅缩短。
6.2 航迹可视化与人工检查
Matlab跑完后,我习惯把规划出来的航迹叠加在三维地形图上用plot3画出来,绕着旋转视角检查每一个航迹点的合理性。检查重点有三个:
- 航迹是否穿过了地形内部。如果有,看控制点是不是被地形高度插值骗了——用
interp2插值的地形如果网格较粗,可能把两个地形栅格点之间的"沟壑"平滑掉了,导致航迹贴着实际地形线之下。 - 多机之间是否在某个时间窗内同时穿越同一走廊。即使算法没有报告碰撞,我仍然会在可视化上人工检查三架机通过狭窄走廊的顺序。很多算法自动检测不到的隐患在你拖动视角看几秒钟后就会暴露。
- 起飞和降落段的航迹是否过于剧烈。起点和终点的前几个控制点附近,如果出现了大角度转折,务必手动调整初始种群生成逻辑——通常问题出在线性基准线+高斯噪声的生成方式上,靠近端点处约束不足。
6.3 一些"如果场景变了"的扩展方向
做完了这个项目之后,有几个延伸方向我觉得非常有价值:
- 动态威胁与实时重规划:现在的规划是静态环境的离线规划,实际多无人机协同任务中,侦测到新的威胁或发现原有禁飞区变化后,需要局部重规划。可以把MShOA改造成"以当前航迹为初始解、在小范围内重新搜索"的模式,避免完全重新规划带来的计算开销。
- 无人机异构能力约束:不同型号的无人机最大速度、最大巡航高度不同,协同规划时需要引入"异构无人机"模型,代价函数里各机的参数就不一样了。这时MShOA的子种群结构天然适配——每个子种群可以拥有各自的约束参数。
- 多目标优化版本:目前是把航迹长度、地形威胁、协同代价线性加权成标量。如果你还想同时最小化油耗、最大化侦查覆盖率,可以考虑把MShOA改造成多目标版本(比如搭配NSGA-II的非支配排序框架)。
这些扩展方向我并没有全部实现完,但从算法结构上讲,MShOA的"探索+攻击"双模式机制在多目标改造上比PSO更自然——因为多目标优化更需要在全局探索和局部收敛之间保持动态平衡。
7. 给准备上手的人:从下载代码到跑出结果
如果你打算直接使用标题里提到的那份Matlab代码,我的建议是按下面的顺序推进:
- 先跑通主程序:不要改动任何参数,先确认代码能跑出结果。如果有报错,优先检查Matlab版本兼容性——很多这类代码在2021b之前写得比较随意,2023a及以上版本可能会遇到函数名冲突问题。
- 跑三遍:统计三次运行的代价曲线差异。如果三次结果差距超过15%,说明参数设置太激进(通常种群规模偏小或者探索阶段太短)。
- 逐项关闭约束:分别把地形威胁、机间碰撞、时间协同三项代价权重置为0,对比生成航迹的差异。这个操作能帮你直观理解每一项目前的制约作用。
- 换成你自己的地图:把Demo里的
createMap函数替换成你的数字高程模型数据。注意坐标系的统一,这是最容易出问题的地方——真实地理坐标通常是经纬度+海拔,而算法里通常用米制坐标,忘了转换会让你所有约束全部失效。
提示:如果你拿到手的代码里没有实现我在5.2节提到的航迹段碰撞检测,建议你优先补上。因为在多无人机场景中,离散点碰撞检测的误判隐患是最隐蔽、也最容易在后续真实飞行中出事的。
关于这份代码最终能帮你做到什么程度,我的判断是:它很适合作为多无人机协同三维路径规划的学习和验证平台,能帮助你直观理解MShOA算法在三维环境中的搜索行为、多机协同的约束建模方式,以及Matlab工程化实现的组织思路。但在把它用于实际飞控之前,你还需要补充动力学模型校验、半实物仿真、通信时延模拟这几个环节。这不是代码的问题,而是所有群体智能离线规划算法走向工程应用都必须跨越的鸿沟。
我自己在跑完第一版代码后最大的感受是:算法本身并不难,难的是一开始就没有把"协同约束"当成第一等公民来建模。如果你只是把单机路径规划算法串行跑,最后再判断碰撞,那你大概率会在调参的路上反复挣扎;而一旦你把多机协同的代价写进适应度函数、让每一代搜索都感知到协同压力,后面所有事情都会顺很多。这就是这个项目最值得你花时间理解的地方。
本文还有配套的精品资源,点击获取