做城市无人机三维路径规划时,最让人头疼的一点是:你搜出来的每条路径都必须在航程、安全、能耗、可飞性之间反复权衡。单目标优化只会给你一条“最短”的路,可它在高楼之间乱钻、转弯率过大,飞行器根本压不住。这也是我最近把注意力放到高维多目标优化上的原因,尤其是一种叫NMOPSO的多目标粒子群优化算法。2025年大家在城市场景无人机航迹规划里讨论比较多的高维多目标方向,用Matlab复现一套完整实验流程,其实比想象中要清晰得多——核心不在于代码量,而在于把目标函数、约束和算法细节对齐。这个项目就是围绕无人机三维路径规划来做的,导航变量就是路径点坐标序列,优化目标不止两个三个,而是直接干到了五个。下面我从建模、算法到实现,把整条链路拆开讲一遍。
1. 项目概述与核心问题
1.1 这个项目到底解决什么问题
无人机在城市环境里飞行,和空旷郊区完全是两码事。城市里有大量建筑物、塔吊、临时障碍物,地形起伏不大但空间被割得很碎。三维路径规划的目的,是给无人机找一条从起点到终点的、满足各种飞行约束的安全轨迹。
传统做法一般是最短路径搜索,或者带少量约束的A*、RRT变种。这些方法在城市三维场景里有个通病:只盯着“路径短”这个指标,结果绕过了高楼却发现转弯半径不够,或者为了躲避威胁把高度拉得过高,能耗爆表。真实飞行中,航程短、威胁小、高度变化平稳、转弯角度缓和、能耗可控,这些需求是同时存在的,而且彼此冲突。
所以这个项目不是单纯“找一条路”,而是“找一批折衷解”。它把无人机三维路径规划当成一个多目标优化问题来求解,决策变量是路径点坐标,也就是标题里说的“导航变量”。每一个粒子代表一条完整路径,通过粒子群的迭代搜索,最终输出一组分布在Pareto前沿上的备选路径,用户可以根据任务需求从中挑一条。这个定位,决定了后续所有建模和算法设计的方向。
1.2 高维多目标比传统多目标难在哪
很多人把多目标优化等同于“两个目标”“三个目标”。三个目标以内,Pareto前沿可视化方便,算法也相对好调。一旦目标超过四个,问题性质就变了,业内专门叫High-dimensional Multi-objective Optimization或Many-objective Optimization。这个项目直接上了五个目标,就属于高维范畴。
高维带来的第一个问题是支配关系变稀疏。五个目标下,两个解之间经常是你这目标好一点、我那目标好一点,谁也无法支配谁,外部档案很快就塞满了互不支配的解,选择压力下降。第二个问题是可视化困难,三个目标还能画三维散点,五个目标没法直观判断前沿是否均匀。第三个问题是收敛和多样性矛盾加剧,传统拥挤距离在低维很好用,到高维之后欧氏距离的区分度下降,删解时容易误杀。
这也就是为什么不能拿一个普通的双目标MOPSO套上去就跑。这个项目里的NMOPSO,需要专门处理高维场景下的外部档案维护、全局最优引导和变异策略,而不是只把目标函数从两个改成五个那么简单。
1.3 为什么选粒子群作为基础算法
路径规划可以用的元启发式算法很多,遗传算法、差分进化、蚁群都能做。但粒子群在这个场景里有几个天然优势。第一,收敛速度明显更快。粒子群没有交叉变异那套复杂算子,只靠速度更新和位置更新,每一代的计算开销小,迭代几百次就能看出前沿雏形。第二,实现简单,Matlab里向量化写起来很顺手。第三,粒子群天然适合连续变量优化,而无人机三维路径点坐标就是连续值,不需要像遗传算法那样做编码解码。
当然,粒子群也有缺陷,容易早熟、种群多样性维持能力一般。因此NMOPSO基本都会引入外部档案、动态惯性权重、变异机制来弥补。这个项目里的做法也是在这个框架上做改进,具体机制我会在第三节展开。
2. 问题建模:五个目标函数与约束设计
2.1 目标函数怎么定才有物理意义
目标函数是多目标优化的第一步,也是最重要的一步。函数定错了,算法再牛也只是在错误的方向上瞎忙。我基于城市场景的实际情况,设计了五个目标,每一个都对应无人机真实飞行中的一个考量维度。
第一个目标是总航程代价。就是把路径上所有相邻路径点之间的欧氏距离加起来,一条路径越长,这个值越大。这是最基础的指标,也最容易理解。第二个目标是威胁代价。城市里的建筑可以膨胀成一个带安全半径的障碍物,路径如果贴着或者穿过这些膨胀区域,威胁代价就会升高。实现时可以沿每条航段均匀采样若干点,计算采样点到最近障碍物的距离,小于安全距离就累计惩罚值。
第三个目标是高度变化代价。无人机频繁爬升和下降不仅费电,还会增加姿态调整的难度,甚至影响任务载荷的稳定性。这个目标统计所有相邻节点之间的高度差的绝对值之和。第四个目标是转弯角代价。路径每经过一个节点就有一个转向角,转向角越小说明转弯越剧烈,对飞行控制要求越高。把这个角度相对180度的偏差累加起来,偏差越大代价越高。第五个目标是坡度代价,也就是每个航段的爬升角或俯冲角的绝对值之和,用于限制纵向姿态的剧烈变化。
这五个目标之间有明显的冲突关系:想航程短,往往要穿越建筑密集区,威胁代价就高;想躲开建筑,只能绕行,航程和转弯角又会上升;想高度稳定,遇到高楼就必须提前爬升或者干脆绕远。正是这种冲突,让多目标优化有了意义,也逼着算法去寻找一组折衷解而不是单一最优解。
2.2 为什么是五个目标而不是更多
目标数量不是越多越好。有些人喜欢把目标拆得很细,什么雷达暴露度、风速影响、通信质量全塞进去,结果目标维度一下子冲到十个以上。这时候Pareto支配关系极度稀疏,几乎每个解都互不支配,外部档案里全是解,选择压力彻底消失,优化过程会退化成随机搜索。
五个目标属于一个相对平衡的点。既能覆盖城市飞行最核心的安全、经济、可飞性维度,又不至于让支配关系完全失效。在做这个项目时,我也试过把五个目标中的“高度变化代价”和“坡度代价”合并成一个“能耗指标”,经过对比后发现,合并之后生成的路径确实更倾向于剧烈转弯以换取低坡度,说明这两个目标各自携带了不同的信息,分开建模更合理。
不过需要提醒一点,如果你的场景里确实有更多互相独立的目标需求,比如同时要优化通信链路质量和噪声覆盖,那建议不要强行并进NMOPSO,而是考虑基于参考点的算法思路,比如NSGA-III那类处理高维目标更稳的框架。NMOPSO更适合目标数在四到七之间的场景,这个项目正好落在这个区间。
2.3 约束条件与罚函数处理
城市场景里的约束条件几乎都是硬性的。路径必须在地图边界内,飞行高度不能低于某个安全下限,不能高于空域上限,转角不能太急,最重要的是路径不能穿过建筑物。这些约束如果不处理,算法生成一堆看似前沿优秀但物理上飞不了的路径,毫无意义。
我的做法是罚函数法加可行性优先。具体来说,每个目标函数在计算完原始值之后,如果路径不满足约束,就加上一个大的惩罚项。这样不可行解的目标值会变得很差,在非支配排序时自然被淘汰。但和硬过滤相比,罚函数法的好处是让粒子在早期还能从不可行区域学到信息,不至于一碰墙就被扔出搜索空间,导致种群多样性和收敛速度双降。
转弯角约束和碰撞约束的处理方式略有不同。碰撞约束我给每个建筑物做了一层安全半径膨胀,检测距离小于安全半径就算碰撞,惩罚值设得很大。转弯角约束则相对温和,超过阈值时按超出比例叠加惩罚。用户如果想把算法移植到自己的场景,建议把罚函数系数单独提出来作为配置参数,方便调节安全性和搜索效率之间的平衡。
3. NMOPSO算法核心机制拆解
3.1 从标准PSO到多目标PSO
标准粒子群优化的速度位置更新公式大家都熟悉:
% 粒子群核心更新公式 V = w * V + c1 * rand(size(V)) .* (pbest - X) + c2 * rand(size(V)) .* (gbest - X); X = X + V;w是惯性权重,c1和c2是学习因子,pbest是粒子自身历史最优,gbest是全局最优。单目标问题里,pbest和gbest都很明确,比较一下好坏就行。到了多目标问题,最大的变化就是“好坏”无法唯一确定了。
NMOPSO处理这个问题的思路是:用Pareto支配关系来更新pbest。如果新解支配了原来的pbest,就替换;如果互不支配,按概率保留,或者用拥挤距离决定。gbest则不再是一个全局唯一解,而是从外部档案里选出来的引导者。选谁、怎么选,直接决定了种群往哪个方向搜索,这是多目标粒子群和单目标粒子群最本质的区别。
3.2 外部档案与拥挤距离在高维下的应用
外部档案是一个专门存放非支配解的集合,规模可以给定上限,比如80或100。每代更新时,先把当前种群里的非支配解放进档案,然后做两件事:一是用支配关系清理掉被新解支配的旧解,二是如果档案超容量,得删掉一部分解,腾出空间给新解。
删哪些解,是算法质量的分水岭。一般MOPSO用拥挤距离,也就是看某个解周围相邻解有多密。最密集区域里的解优先删,这样保留下来的解能尽量均匀地覆盖前沿。但在五个目标的高维空间里,直接算欧氏距离效果不好,因为不同目标的量纲不一样,航程是公里级,威胁代价可能是个位数,直接算距离会被大尺度目标主导。
我在这个项目里先对目标值做Min-Max归一化,再计算拥挤距离,并且采用了“排序距离”而不是原始距离。把每个目标上的邻居间隔做标准化之后再加总,这样每个目标对拥挤度的贡献是均衡的。这个小改动看起来不起眼,但在高维下对前沿分布均匀性的改善非常明显。
3.3 NMOPSO的完整流程
整个算法流程可以概括成十步,每一步都有明确的输入输出:
第一步初始化种群,随机生成N个粒子,每个粒子代表一条路径,也就是一组路径点坐标序列。第二步计算每个粒子的五个目标值,同时检查约束并施加罚函数。第三步做非支配排序,找出当前种群中的非支配解,存入外部档案。第四步为每个粒子初始化pbest,就是它自己。第五步从外部档案中为每个粒子选择gbest,这步优先选拥挤距离大的稀疏区域解。第六步按速度位置更新公式进行迭代。第七步计算新解的目标值,用支配关系判断是否需要更新pbest。第八步把新解里的非支配解并入外部档案并清理支配关系。第九步处理档案超容量问题,走拥挤距离裁剪。第十步按一定概率做变异扰动,避免早熟,然后回到第六步循环直到达到最大迭代次数。
这十步看起来不复杂,但每一步都有细节。尤其要注意的是选择gbest这一步,如果每次都选同一个稀疏解,种群会快速向那个区域聚集,反而造成新的拥挤。所以我在实际代码里用的是锦标赛选择,先随机抽几个档案成员,在其中挑拥挤距离最大的作为gbest,这样既偏向稀疏区,又保留了一定随机性。
3.4 惯性权重与变异策略的调整
基础粒子群的惯性权重是常数,NMOPSO里我做了动态调整。迭代前期用较大的w,比如0.9,保证全局探索能力,让粒子敢于飞向未知区域。随着迭代进行,w线性降到0.4左右,搜索逐渐从探索转向开发,粒子围绕局部最优精细调整路径点坐标。这个技术在单目标粒子群里很成熟,放在多目标场景同样有效,而且对稳定收敛的帮助比想象中更大。
变异策略是另一个关键点。多目标粒子群的一大问题是容易过早聚集在某些局部前沿区域,出不来。所以我给每代种群施加一定概率的变异,做法是随机选取若干个粒子的某些维度,施加一个高斯扰动。变异概率在迭代初期设得高一些,大约0.2,后期降到0.03左右,防止最后阶段还在乱跳。
一点经验:如果你发现外部的Pareto前沿长期不更新,或者档案里的解总集中在一个小角落,优先检查变异概率是不是被设成了0,而不是急着怀疑支配关系或拥挤距离写错了。这是我调试中最常遇到的情况之一。
4. 城市场景三维路径规划:从环境建模到代码实现
4.1 三维仿真环境怎么搭
这个项目采用仿真环境而不是真实地图数据,因为研究重点在算法本身。我在Matlab里搭了一个1000m乘1000m的城区范围,垂直方向限制在200m以内。建筑物用矩形棱柱近似,每栋楼给一个中心坐标、长宽尺寸和高度,数量可以设成十几个到几十个不等。城市建筑数量越多,可行走廊越窄,路径规划难度越大。
环境搭建的关键是障碍物数据结构。我用的是一个矩阵,每行代表一栋建筑,列依次是中心x坐标、中心y坐标、半长、半宽、高度。这样的结构在目标函数里遍历起来非常方便。为了让场景不过于简单,我还会让建筑高度随机分布,比如30到120米之间随机取,这样无人机在不同高度飞行面临的威胁情况是不一样的,低空穿行危险但航程短,高空绕飞安全但能耗大。
仿真区域的起点和终点分别放在场景的两侧。比如起点在西南角(100,100),终点在东北角(900,900),起始高度都设为50米左右。这个起终点设置会让路径必须横穿整个城区,中间自然会遇到建筑群,算法才有足够空间去生成有差异的路径。
4.2 路径表示与粒子维度设计
路径表达方式直接决定粒子维度。如果把路径离散成N个控制点,每个点有x、y、z三个坐标,那么粒子的维度就是3N。控制点太少,路径表达能力不足,复杂绕行画不出来;控制点太多,维度膨胀,搜索空间急剧增大,粒子群很容易发散。
这个项目里我选择中间点7个,加上起终点一共9个节点,粒子维度27。27维在粒子群算法里不算高,但对于路径规划已经能表达比较复杂的绕行轨迹。同时我加了一个处理策略:路径点生成后做线性插值,把每个航段加密成多个子路径点。这样做的目的不是增大优化维度,而是让碰撞检测和转弯角计算更精细。换句话说,决策变量是9个节点坐标,但目标函数评估是在加密后的轨迹上做的。
有一个细节要注意:x和y维度可以直接随机初始化,但z维度不能完全随机,否则大量粒子一开始就在天花板高度,搜索效率很低。我把z初始化控制在最低安全高度和建筑平均高度之间,给粒子一个比较合理的起点。
4.3 目标函数的核心代码实现
路径长度计算很直接,威胁代价稍微复杂一点。这里给出我常用的两个函数片段,一个是路径长度,一个是碰撞威胁检测:
% 路径长度目标 function f1 = pathLength(points) seg = diff(points, 1, 1); f1 = sum(sqrt(sum(seg.^2, 2))); end威胁代价计算时,我沿每条航段做插值采样,然后判断采样点是否落在某个建筑物膨胀后的范围内,落在里面就累计惩罚。膨胀半径按无人机安全距离设置,比如5米:
% 威胁代价目标 function f2 = threatCost(points, buildings, safe_radius) f2 = 0; for i = 1:size(points,1)-1 t = linspace(0, 1, 10)'; seg_pts = points(i,:) + t * (points(i+1,:) - points(i,:)); for j = 1:size(seg_pts,1) for k = 1:size(buildings,1) dx = abs(seg_pts(j,1) - buildings(k,1)) - buildings(k,3); dy = abs(seg_pts(j,2) - buildings(k,2)) - buildings(k,4); if dx < safe_radius && dy < safe_radius && seg_pts(j,3) < buildings(k,5) f2 = f2 + 1; end end end end end这只是一个基础版本,循环较多,Matlab里跑起来稍慢。实际项目里我对建筑物的遍历做了向量化处理,先判断水平和垂直条件全为真的采样点,再只需要统计数量,速度能提升好几倍。对于想跑大场景的朋友,建议一开始就写成向量化版本,后面能省很多时间。
4.4 主循环代码框架
NMOPSO主循环的核心是速度位置更新、边界处理和档案更新。代码如下:
for iter = 1:max_iter w = w_max - (w_max - w_min) * iter / max_iter; for i = 1:pop_size r1 = rand(dim,1); r2 = rand(dim,1); V(i,:) = w * V(i,:) + c1 * r1' .* (pbest(i,:) - X(i,:)) ... + c2 * r2' .* (gbest(i,:) - X(i,:)); X(i,:) = X(i,:) + V(i,:); % 边界处理 X(i,:) = min(max(X(i,:), lb), ub); end % 计算目标值、更新pbest、更新外部档案(省略详细代码) % 档案裁剪、变异扰动 end边界处理这里用了一个比较粗的方式:直接截断到边界。如果希望更精细,可以用反射法或者随机重建,但就这个项目而言,截断法配合罚函数已经能稳定收敛,而且实现简单得多。真正需要谨慎的是gbest的更新节奏,我建议每隔几代再重新从档案中为粒子分配gbest,而不是每代都换,不然粒子群容易震荡。
4.5 结果可视化
多目标路径规划项目不做可视化,等于没有完成。我至少会画三张图:第一张是三维路径图,把所有建筑画成立方体,然后用蓝色线条画出几条从档案中选出的代表路径;第二张是Pareto前沿图,选其中两个目标做二维散点,或者用三维散点同时展示三个目标;第三张是收敛曲线,观察外部档案的非支配解数量以及某个指标比如超体积值随迭代的变化。
三维路径图在Matlab里用plot3就可以,建筑用patch或者rectangle加高度拉伸都可以实现。需要注意的是,如果路径数量太多,三维图会非常杂乱,建议从档案里挑三到五个有代表性的解来展示,比如航程最短的、威胁最小的、两者折衷的,这样读者一眼就能看出多目标优化的价值。
5. 实验结果解读与参数调优
5.1 实验参数设置
我用的参数组合如下:种群规模100,最大迭代次数400,外部档案容量80,惯性权重从0.9线性降到0.4,学习因子c1和c2都取1.8,初始变异概率0.2,最终变异概率0.03。这个组合不是一次调出来的,是跑了多组对比之后确定的,适用于大多数城市规模在1平方公里左右的仿真场景。
有个参数容易被忽视,就是外部档案容量。容量太小,Pareto前沿覆盖不完整;容量太大,拥挤距离裁剪的计算开销上升而且选择压力降低。80到120这个区间是五目标问题比较常用的选择。如果场景复杂、建筑多,我会倾向于取100以上,保证前沿的完整性。
另外,粒子群算法对随机种子很敏感。同一个参数,换一个随机种子,得到的前沿会有可见的差异。为了实验可复现,我在代码里固定了随机种子,并且在写项目总结时也建议别人固定。这不是为了让结果好看,而是不同参数之间的比较必须保证初始化一致,否则没法判断因素究竟是算法改进还是随机差异。
5.2 Pareto前沿与路径特征的对应关系
跑完算法后,外部档案里是一批非支配路径。我观察到一个很有意思的现象:航程最短的那条路径,几乎总是走建筑群的缝隙,威胁代价很高;威胁代价为0的路径,航程普遍多出500米以上,而且转弯角代价也更高。这是符合直觉的,也恰恰说明五个目标之间的冲突是真实的。
从Pareto前沿的分布形状能读出很多信息。如果前沿在某个目标维度上特别窄,说明这个目标和其他目标的冲突不大,怎么选都差不多。如果前沿在某个方向上有明显缺口,说明搜索没有覆盖到那一区域,可以考虑增加对应方向的变异扰动或调整初始种群分布。我实际检查这个项目的结果时,发现高度变化代价和坡度代价的前沿分布高度相关,但并没有完全重合,这就验证了前面把它们拆开建模的判断。
5.3 惯性权重和变异概率怎么调
参数调优的优先级我认为是:变异概率大于惯性权重,惯性权重大于学习因子。多目标问题里,种群多样性是生命线,变异概率直接决定多样性,所以它最敏感。我把变异概率从0降到0.1再升到0.2,分别实验,发现0时算法很快收敛到一个很窄的前沿,跑出来的路径形态都比较接近,这在多目标场景里几乎是灾难。
学习因子c1和c2的影响相对小一些。c1和c2都等于1.8时,收敛速度和多样性比较均衡。如果c2过大,种群会过度追赶全局最优,档案多样性下降。如果c1过大,种群会各自为政,收敛太慢,400代跑不出清晰前沿。固定w和变异概率后,c1和c2在1.5到2.0的范围内做细微调节就够了。
5.4 和单目标优化结果对比的启发
为了验证多目标建模的价值,我把同一个场景拿来跑单目标PSO,目标只设航程最短。结果非常典型:单目标解一路贴着两栋楼的缝隙穿过去,路径确实短了将近20%,但威胁计算显示它在多处贴近安全边界,如果任务中有任何扰动,这条路径基本无法执行。而NMOPSO给出的折衷解,虽然航程变长,但威胁代价大幅下降,同时还保留了低转弯角、缓坡度等飞行友好特征。
这个对比很能说明问题:多目标优化不是“锦上添花”,而是“从不可行到可行”的转变。很多研究者和工程师觉得多目标算法跑得慢、解集又麻烦,不如单目标简单直接。但一旦场景约束复杂起来,单目标解往往是被罚函数硬拽出来的“假最优”,真实任务里很难落地。这也是我在做这个项目之后更坚定的一点:路径规划这类问题,本质上是多目标问题,不应该被简化为单目标。
6. 常见问题与避坑指南
6.1 路径穿墙但目标函数没报威胁
这是我遇到最多的Bug。原因几乎都出在碰撞检测的采样密度上。如果一条航段只在起点和终点做障碍物判断,那么一条从建筑物中间斜穿的线段很可能被漏检,因为起终点都不在建筑内部,但线段从建筑体内经过。解决方法是把每条航段插值加密,我一般每段取10到20个采样点,并且根据航段长度动态调整采样数量,越长越密。
另一个相关问题是建筑物膨胀半径太小。如果安全半径设成0,路径贴着建筑边缘也算“无碰撞”,实际飞行中一个小的气流扰动就可能撞上。建议安全半径至少等于无人机翼展的一半,我习惯取5米左右。安全半径也不是越大越好,太大之后可行走廊变窄,算法收敛会明显变慢。
6.2 粒子维度太高导致搜索发散
如果路径节点取得太多,比如中间点超过15个,粒子维度就接近50维。粒子群在50维连续空间里的搜索效率很差,经常出现迭代几百代路径仍然不规则、像锯齿一样乱抖的情况。这不是算法写错了,而是维度过高带来的本质困难。
我的建议是路径节点控制在7到12个之间。如果城市环境特别复杂,12个节点还不够表达绕行,那不要急着加节点,而是改用两阶段策略:先做粗粒度的路径规划找出可行走廊,再在走廊内部用NMOPSO做精细化优化。粗粒度可以用传统的栅格搜索,把走廊约束住之后,NMOPSO只需要在这个子空间里搜索,效率和效果都明显更好。
6.3 外部档案里全是解或者没有解
外部档案空,说明一代代迭代下来,种群产生的非支配解一个都没保留住。原因通常是两个方向:一是所有粒子都被罚函数压得不可行,整个种群没有一个真正可行的路径,那自然没有非支配解;二是pbest更新逻辑有问题,新解总是被旧解支配,档案一直没有新成员加入。
如果是第一种情况,先去检查初始种群是否过半数可行。如果初始种群几乎全部不可行,说明随机初始化给的z高度范围或者坐标范围不合适,优先调整初始化策略,让粒子起点在可行区域附近生成。如果是第二种情况,在代码里打印pbest更新次数,如果接近零,多半是pbest比较逻辑写错了,把大于小于号搞反了。
档案里全是解,也就是档案长期接近容量上限并且新旧解交替频繁,这种情况反而常见。它说明算法多样性有余,收敛性不足。优先降低变异概率、提高惯性权重的下降速度,让搜索后期多一些局部开发,前沿就能稳定下来。
6.4 目标函数数量级不一样导致整理混乱
航程目标动辄一两公里,高度变化代价可能是几十米,威胁代价可能是个位数,转弯角代价和坡度代价又是另一个量级。如果直接拿这些原始值做拥挤距离、做非支配排序,虽然支配关系不受影响,但拥挤距离会被量级大的目标主导,导致档案裁剪时总是保留大尺度目标上的边缘解,前沿分布很偏。
解决方法是归一化。我在计算拥挤距离之前,把档案里所有目标值按当前代的最小最大值缩放到[0,1]区间。这里要小心一个细节:最小最大值不要固定用全局上下界,而应该每代动态计算,否则迭代早期解范围很大,归一化后后期变化就体现不出来。此外,如果某些目标的理论上下界已知,用固定边界做归一化也行,但需要额外配置,通用性不如动态方法。
6.5 算法早熟收敛,前沿分布窄
早熟收敛在多目标粒子群里很常见,特征就是迭代到一百代左右,前沿基本不动了,所有解挤在很小一块区域里。原因有两个:一是种群多样性在迭代中快速流失,粒子们越飞越像;二是档案选择gbest时总选同一片区域,形成正反馈,把种群锁死。
解决思路是多管齐下。变异概率不能完全清零,至少保留0.03的底线。选择gbest时用锦标赛法,每次都从随机选出的档案成员里挑拥挤距离大的,而不是全局直接取拥挤距离最大的那个。最后,可以考虑对粒子速度做限幅,防止某些粒子被极端速度带着飞出搜索空间后又被截断回来,打乱局部搜索节奏。
7. 之后可以怎么扩展
如果这个项目要继续往下走,我认为有三个方向值得尝试。第一是把静态建筑障碍换成动态障碍,比如加入移动车辆、临时空域封闭区,这时候问题会变成动态多目标优化,需要在NMOPSO里引入时间维度和预测机制。第二是给路径加时间维度,也就是四维路径规划,让算法同时优化到达每个路径点的时刻,处理协同飞行和多机编队问题。第三是引入真实地图数据,把建筑轮廓从矩形升级为任意多边形,甚至把地形起伏也纳入建模,目标函数需要增加地形贴地飞行的代价项。
不管往哪个方向扩展,这个项目打下的基础都是可复用的。建模思路、NMOPSO的主体框架、外部档案和拥挤距离的实现,都可以平移过去。改动的只是目标函数的输入数据和约束形式,算法本身的逻辑不伤筋动骨。
我在实际跑这个项目的过程中,最深的体会是:多目标优化项目里,算法代码只占了工作量的一半不到,另一半全在建模和参数调试上。每改一个目标函数,就要重新验证一遍收敛性、前沿均匀性、路径合理性,不能偷懒。固定随机种子、记录每次实验的参数和指标、保持目标函数和约束之间的可配置性,这些看似繁琐的习惯,到最后会帮你节省大量返工时间。如果只让我给一条建议,那就是在建模型之前,先把你要优化的五个目标到底代表什么物理意义、它们之间怎么冲突,用一段话写清楚。写不清楚之前,先别急着写代码。