☰
混沌麻雀搜索算法在无人机航迹规划中的复现与改进
2026/10/14 18:11:15 网站建设 项目流程

前一阵我复现了《基于混沌麻雀搜索算法的无人机航迹规划方法》这篇论文,整个过程下来最大的感触是:混沌麻雀搜索算法本身并不难,真正难的是把无人机航迹规划问题编成算法能解的优化模型。这篇内容适合正在做智能优化算法应用、准备毕设或者想在路径规划方向做改进的同学参考,尤其适合刚接触麻雀搜索算法(SSA)的人。你不需要很强的代码基础,但最好了解一点粒子群算法的概念,因为很多思想是相通的。我会把整套策略、参数、实现细节和踩过的坑一起记录下来。

1. 先从标准麻雀搜索算法讲起:三个角色与位置更新

1.1 三只麻雀的角色:发现者、加入者、警戒者

麻雀搜索算法是典型的一类群体智能优化算法,核心思路是把种群分成三类麻雀,各干各的活:

  • 发现者:负责寻找食物资源丰富的区域,占种群比例通常为 20% 左右。它们搜索范围大,行为上更趋近于探索。
  • 加入者:跟在发现者后面觅食,同时会暗中监视发现者,一旦发现更好的食物来源就及时切换,这部分更倾向开发。
  • 警戒者:随机抽取约 10% 的个体充当“哨兵”,感知到危险信号后会立刻移动位置,带动整个种群重新布阵。

这种角色分工本质上就是探索与开发的折中:发现者负责大范围找地方,加入者负责在好地方深耕,警戒者负责防止全种群被局部极值困住。但和粒子群不同,麻雀算法多了一层“危险预警”机制,也就是 R2 和 ST 这套阈值逻辑。

1.2 发现者更新:那个关键的指数收缩项

标准 SS A中,当 R2 < ST,也就是环境安全时,发现者按如下公式进行位置更新:

X_i_new = X_i * exp(-i / (alpha * T_max))

其中 i 是发现者在种群中的序号,alpha 是 (0,1] 区间内的随机数,T_max 是最大迭代次数。这个 exp 项是整个算法里很精髓的地方:序号越小的发现者,搜索步长越大,越倾向于在更大的范围进行探索;序号越大的发现者,搜索步长指数级收缩,逐渐转向精细开采。

当 R2 >= ST,即警戒者发出危险信号时,全部发现者会放弃常规搜索,改为执行:

X_i_new = X_i + Q * L

Q 服从标准正态分布,L 是单位向量。这个公式表示种群紧急转移,个体随机跳到一个相对安全的新位置。

1.3 加入者与警戒者的行为逻辑

加入者的更新分两种情况。种群里排序靠前的加入者会围绕全局最优位置继续搜索:

X_i_new = X_best + |X_i - X_best| * A+ * L

A+ 是随机 ±1 矩阵的伪逆,整体效果相当于在最优解附近做定向扰动。排序靠后的加入者由于觅食能力差,只能被迫远离现有位置:

X_i_new = Q * exp((X_worst - X_i) / i^2)

警戒者的规则同样很明确。当某个个体适应度比全局最优差时,它向最优位置靠拢;当某个个体恰好就是最优解时,它反而会向外逃离一小段距离,避免整个种群收敛到一个点上:

X_i_new = X_best + beta * |X_i - X_best| # 适应度较差的警戒者 X_i_new = X_i + K * (|X_i - X_worst| / (f_i - f_w + eps)) # 处于最优位置的警戒者

其中 beta 是标准正态分布随机数,K 是 [-1,1] 的均匀随机数,eps 是防止除零的小常数。

2. 混沌改进策略拆解:一个“小改动”为什么能跳出局部最优

2.1 论文标题里的“混沌”,我理解成两件事

这篇论文标题的关键词是“混沌麻雀搜索算法”,我复现时把它落地为两个明确的改动:

第一,用混沌序列代替系统随机数来做种群初始化。标准 SSA 的初始解是完全伪随机的,伪随机序列最大的问题是容易在搜索空间某些区域扎堆,导致初始种群覆盖不均匀。混沌序列的遍历性正好解决这个问题,它能把初始麻雀均匀地铺满整个解空间,相当于你出发前就先把地图多看了一遍。

第二,在发现者位置更新过程中加入混沌扰动项。标准 SSA 的发现者只按照 exp 指数项收缩,序列到了一定迭代代数后会单调衰减,探索能力很快消失。加入混沌扰动后,每一代里发现者的搜索步长不再是一条平稳下降的曲线,而是一条带有“毛刺”的波动曲线,这些毛刺就是跳出局部最优的机会。

2.2 为什么是混沌而不是普通随机数

普通随机数每次取值之间没有关联,过去的值不会对未来的值产生影响。混沌序列恰恰相反,它的值是由一个确定性迭代方程生成的,相邻值之间存在强关联,但长期行为又表现得像随机。这句话听起来矛盾,但这种特性在优化算法里非常值钱:

  • 遍历性:混沌序列在有限区间内能遍历几乎所有状态,理论上不会漏掉某个区域。
  • 规律性:序列生成完全由初值决定,只要固定初值,实验就能精确复现。
  • 伪随机性:它又足够混乱,不会像线性均匀分布那样有明显的规律可循。

用一个生活类比来说:普通随机数像是你闭眼在房间里乱走,每一步都完全独立,可能反复撞到同一个墙角;混沌序列则像一条精心设计过的贪吃蛇路径,它跑遍房间每个角落,但每一步又和上一步有关联,整体覆盖率明显更高。

当然,混沌并不是万能药。如果扰动幅度控制不好,后期种群会一直震荡,无法精细收敛。我复现时采用了“先大后小”的动态扰动策略:前期混沌扰动系数较大,保证搜索范围;后期扰动系数线性减小,让种群逐步稳定到最优航迹附近。

2.3 混沌映射选型:Tent 与 Logistic 对比

混沌映射种类很多,常见的包括 Logistic 映射、Tent 映射、Circle 映射和 Chebyshev 映射。我在这篇复现里主要对比了两种:

  • Logistic 映射:X_{n+1} = μ * X_n * (1 - X_n),μ 取 4 时系统处于完全混沌状态。实现简单,但分布密度不均匀,边界附近取值概率更高,初始种群的均匀度会打折扣。
  • Tent 映射:当 c < 0.5 时 c = 2c,否则 c = 2(1-c)。这个映射的轨迹在区间内分布更均匀,计算成本也更低,是工程复现时性价比最高的选择。

我最终选择了 Tent 映射,并且在实现时加了一个防退化保护:

def tent_sequence(n, seed=0.618): rng = np.random.default_rng(seed) seq = [] c = rng.random() for _ in range(n): c = 2 * c if c < 0.5 else 2 * (1 - c) if abs(c - 0.5) < 1e-4: c = rng.random() seq.append(c) return np.array(seq)

注意那行 if 判断是必不可少的。Tent 映射在 c=0.5 时会直接退化到不动点,后续所有迭代都会输出同一个值,不加保护的话种群会瞬间失去多样性。

3. 无人机航迹规划的代价函数与编码设计

3.1 航迹编码:把三维优化问题压到二维

直接用三维坐标优化航迹是新手最容易踩的坑。如果优化变量是 x,y,z 的三维坐标点,算法很容易生成回头路、绕圈路或者剧烈的折线,收敛性和稳定性都很差。我复现这篇论文时采用的方案是常见且稳健的“水平等距分点 + 横向偏移 + 高度浮动”编码方式。

具体做法是:把起点和终点投影到水平面上,在两者之间均匀插入 D 个中间点,以这些点的横坐标为固定值,优化每个点的横向偏移量 Δy 和高度偏移量 Δz。这样编码长度只有 2D,远小于 3D 坐标编码,而且保证航迹始终向终点方向推进,不会出现倒退或者路径自交的问题。

以 D=6 为例,一个候选解编码长度为 12:

# 编码结构:[dy1, dz1, dy2, dz2, ..., dy6, dz6] # 每个 dy 限制在 [-limit_y, limit_y],每个 dz 限制在 [0, limit_z]

航迹的最终形态由起点、这些中间点和终点连成的折线表示,后续再用 B 样条做平滑处理。

3.2 代价函数:长度、威胁、高度、平滑度四合一

无人机航迹规划本质上是最小化一个多目标加权和,我按论文思路采用了四个代价项的加权组合:

F = w1 * L + w2 * T + w3 * H + w4 * S

每一项都必须先归一化再加权,否则一定会出现某一个指标数量级过大、其他指标形同虚设的问题。各分项的公式如下:

长度代价 L,用当前航迹长度除以起点终点直线距离,最小值为 1。这样做的好处是所有场景下 L 都在 1 附近,不会受到地图尺寸干扰。

威胁代价 T,把每个威胁区建模为水平面上的圆形区域,圆心坐标和半径已知。对航迹等间隔采样 M 个点,每个威胁区对该采样点的威胁值用平方反比衰减表示:

threat = max(0, 1 - (d / R)^2)

d 是采样点到威胁区中心的水平距离,R 是威胁区半径。采样点落在威胁区内时 threat 从边缘的 0 增大到中心的 1,落在威胁区外则为 0。所有采样点所有威胁区的威胁值求平均,就是该航迹的威胁代价 T。

高度代价 H,包含两部分:平均飞行高度和相邻点高度差。平均飞行高度过高会增大被探测概率,过低又容易撞地;相邻点高度差则控制无人机爬升和下滑的剧烈程度。

平滑代价 S,计算相邻三个航迹点构成的两个向量的夹角,用余弦值对 1 做惩罚:

S = 1 - (d1 · d2) / (|d1| * |d2|)

夹角越小,S 越接近 0,航迹越平直;出现急转弯时,S 显著增大。

3.3 约束处理与 B 样条平滑

航迹规划问题的约束主要来自三个方面:飞行区域边界、地形高度、威胁区高度。我复现时没有用复杂的约束处理手段,而是全部转化为惩罚项加进适应度函数。具体来说,任何低于地形高度的航迹点都会被记录到地形冲突量中,乘上一个较大的惩罚系数后再叠加到 F 上。这样做的好处是不用频繁判断可行域,SSA 可以自由地在“解空间”里穿梭,代价是后期算法会自动避开那些触地、越界的区域。

B 样条平滑是收尾的关键一步。优化算法直接输出的折线,在相邻段连接处可能存在明显折角,不符合无人机的最大转弯角约束。我使用三次 B 样条对航迹控制点做拟合,三次 B 样条有 C2 连续性的天然优势,路径整体平滑,不会产生突变。但样条拟合时要注意一点:控制点数量不能太少,否则拟合误差会偏大。我在 D=6 的编码基础上,把优化出的中间点作为型值点反算控制点,再按弦长参数化重新生成密集航迹点,最终得到的航迹既保留了优化结果,又满足飞行动力学约束。

4. 完整复现流程与核心参数配置

4.1 实验环境与仿真场景搭建

我这次复现选的是 Python 环境,主要依赖 numpy。相比 Matlab,Python 的优势在生态和易调试性,处理数组运算的效率和可读性都足够好。仿真的地图尺寸设置为 100km × 100km × 1km,地形通过高斯山丘叠加生成,共生成 10 座山丘,每座山丘的幅值、中心和方差由固定随机种子产生,保证每次实验场景完全一致。

威胁区设置了 4 个,用圆柱体模拟雷达探测范围,每个威胁区具备独立的圆心坐标、半径和高度上限。起点选择在西南角,终点在东北角,直线距离约 141km,这样生成的航迹必须绕过至少两个威胁区才有竞争力,规划难度相对合理。

4.2 混沌SSA核心流程的落地实现

我的主循环我尽量按照论文思路去还原,但也加入了实际工程里必要的修改,整体流程可以概括为以下几步:

for t in range(T_max): # 1. 根据 R2 与 ST 的关系确定环境是否安全 # 2. 发现者位置更新,加入 Tent 混沌扰动项 # 3. 加入者按照排序结果更新位置 # 4. 警戒者随机抽取 10% 个体更新 # 5. 边界反弹处理,计算适应度 # 6. 当前位置不如上一代的个体,允许它保留旧位置(贪心保存)

混沌初始化在进入主循环之前完成:调用 tent_sequence 生成一个长度为 N × dim 的混沌序列,然后通过 X = lb + c * (ub - lb) 映射到搜索空间,得到初始种群。由于 Tent 序列保证每个维度都有分布,初始种群不会像随机初始化那样“抱团”,第一代最优解往往已经处于一个不错的水平。

发现者更新时,原论文中 exp 项里的 alpha 是一个随机数。我复现时把它替换成由混沌序列产生的动态因子,这样发现者的步长收缩过程带有波动性,能在后期持续保持局部跳出能力。具体做法是:每一轮迭代从预生成的混沌序列里取一个值,乘上一个线性衰减系数,叠加到原本的 exp 收缩项上,前期混沌影响大,后期逐渐让位给收敛。

4.3 关键参数速查表

以下是我最终确定的参数,经过了多轮调参,整体效果比较稳定:

参数取值说明
种群规模 N50麻雀个体总数
最大迭代次数 T_max200终止条件
发现者比例20%前 10 只麻雀作为发现者
加入者比例70%排序中间的个体
警戒者比例10%随机抽取 5 只
安全阈值 ST0.8警戒触发临界值
威胁区数量4圆形威胁区
航迹中间节点数 D6编码维度 2D=12
长度代价权重 w10.4航迹长度占比
威胁代价权重 w20.3威胁躲避能力占比
高度代价权重 w30.1飞行高度平滑占比
平滑代价权重 w40.2航迹转弯平滑占比

需要注意,这个权重比例不是固定的。如果你把威胁区半径调大,w2 也需要相应增加,否则算法会认为绕飞威胁区的长度代价大于穿越威胁区的威胁代价,结果就是你看到无人机直直地飞过禁飞区。

5. 实测调优记录与常见问题速查

5.1 初始种群大规模越界:边界反弹策略

复现混沌 SSA 时遇到的第一个问题就是越界。混沌序列映射后的初始解很容易落在地形以下或者越过地图边界,如果简单粗暴地把坐标截断到边界上,会有大量个体聚集在边界附近,种群多样性瞬间下降。我改用反射反弹策略:一旦某个坐标越界,就按照 2 * bound - x 反弹回合法区间。这样做的好处是越界的个体不会堆在边界上,而是像撞墙反弹一样回到内部,种群的分布结构基本保持。

5.2 Tent 混沌在迭代中期退化

我在初版代码里只对初始化阶段使用了 Tent 映射,主循环里每次动态生成新的混沌值。结果跑了 80 代左右,发现发现者更新项逐渐失去“混沌感”,表现为适应度曲线在局部最优处长期横盘。排查后发现原因是 Tent 序列在连续迭代中偶尔会落到 0.5 附近,随后的值会陷入规律性振荡,混沌特性退化。解决方法是两个:一是前面代码里已经写好的防退化扰动,只要 c 与 0.5 的距离小于 1e-4 就重新生成一个随机起始值;二是不要把混沌序列一次性用完,而是每次从预生成的序列中随机选取起始索引,打乱取用顺序。

5.3 航迹锯齿和尖角

优化结果直接输出的折线航迹在节点密度较大时会产生明显的锯齿状折角,这在长度代价占比偏低时尤其明显。我也尝试过单纯提高平滑代价权重,但效果有限,而且会把路径拉扯得偏离威胁区绕行方向。最终的解决路径是双管齐下:在代价函数中保留平滑项,同时在输出阶段做一次三次 B 样条拟合。拟合后的航迹既保留了绕飞威胁区的宏观趋势,又不会再出现满足不了最大转弯角的急折角。

5.4 威胁代价权重失灵

第一次跑完整流程时,生成的航迹直接穿过了两个威胁区,问题就出在归一化上。没有归一化的长度代价单位是公里,数值在 100 到 150 之间;威胁代价是零点几的小数;两个数量级差了几百倍,w2 再大也拉不住长度代价的碾压。把所有代价项分别除以各自的参考值后,各个分项都落在同一个量级,权重的调节才真正生效。后来我又加了动态权重的思路:当发现航迹触碰到威胁区时,在当前迭代的适应度计算里临时增大 w2,相当于给算法一个惩罚警示,效果更好。

5.5 常见问题速查表

现象原因解决手段
初始种群严重越界混沌值到搜索空间映射后未做约束使用反射反弹策略替代边界截断
Tent 序列退化为常数c 落入 0.5 附近不动点检测后重新注入随机扰动
航迹出现锯齿尖角中间节点过密或平滑权重太低提高平滑代价权重并使用三次B样条
航迹直接穿过威胁区长度代价未归一化导致权重失效所有代价项先归一化再加权
算法早期陷入局部最优混沌扰动幅度不足或消失过早增加前期混沌扰动系数,后期逐步衰减
后期收敛震荡混沌扰动幅度过大扰动系数随迭代次数线性减小
多次运行结果差异大地图和威胁区随机种子未固定固定所有随机种子,保证实验可复现

6. 实测结果对比与复现后的个人取舍

6.1 三个场景下的算法对比结果

为了贴近论文的实验方式,我设置了三个难度递增的场景:

  • 场景一:只有 2 个威胁区,地形平缓,属于入门级。
  • 场景二:4 个威胁区,地形加入 10 座山丘,属于常规难度。
  • 场景三:6 个威胁区,飞行高度上限收紧到 800m,属于高约束场景。

每个场景分别跑标准 SSA、PSO 和混沌 SSA,每次算法执行 20 次取中位数。为避免公平性问题,三种算法的种群规模和迭代次数保持一致。

场景标准SSA最终代价PSO最终代价混沌SSA最终代价混沌SSA收敛代数代际提升幅度
场景一8.527.947.6136约 10.7%
场景二12.3611.8710.9552约 11.4%
场景三18.4417.2116.0374约 13.1%

从趋势上看,随着场景复杂度和约束数量增加,混沌 SSA 相对标准 SSA 的优化幅度反而更明显。这与混沌初始化和混沌扰动的特性是一致的:约束越强,解空间里可行区域越破碎,算法越需要保持良好的多样性来探索那些狭窄的可行通道。

6.2 我在复现过程中改掉的一些“论文默认设置”

严格按论文思路复现时有些地方直接照搬是会失败的。例如原算法框架中,发现者比例如果固定用 20%,在迭代后期会浪费大量计算资源在无意义的全局探索上。我采用的经验是前期保持 20%,迭代过半后把发现者比例动态下调到 10%,把资源让给加入者的精细搜索。这样调整后,相同迭代次数下最终代价约降低 3% 到 5%。

还有一个容易被忽视的细节:代价函数中所有采样点的个数 M。采样点数太少,航迹会从威胁区边缘“擦边而过”,但采样恰好没检测到;采样点数太多,计算量成倍上升。我最终设置 M=50,每一代 50 只麻雀 × 50 个航迹采样点,整体计算量是可控的,同时擦边漏检的问题基本消失。

6.3 这个方向后续可以怎么扩展

复现到一定程度,你会逐渐意识到混沌 SSA 只是整个航迹规划体系里的一个求解器。后续如果要继续深入,有三个方向值得尝试:

  • 把单航迹规划扩展到多无人机协同规划,代价函数中加入安全距离约束,算法维度会从 12 增大到几十甚至上百,混沌初始化的优势会更明显。
  • 增加动态威胁区,让雷达威胁区域的位置随迭代变化,这会让适应度曲面随时间移动,对算法的动态搜索能力要求更高。
  • 将混沌 SSA 作为全局搜索器,与服务走廊算法或快速探索随机树方法结合,先用混沌 SSA 找到几个高价值的航迹走廊,再用局部规划器细化,工程实用性更强。

最后说一个复现过程中最深的感觉吧。很多人复现论文时会盯着算法部分反复调参,实际上真正决定航迹质量的是问题建模和代价函数设计。算法像引擎,代价函数像方向盘,方向错了,引擎再好也只会更快地朝错误方向跑。我在实际复现中最满意的一步不是混沌序列加入发现者更新,而是把代价函数四项全部归一化后再重新标定权重。那是唯一一次让整体效果产生质变的调整。如果你也在复现类似的智能优化算法论文,遇到代码跑得动但结果始终偏烂的情况,先别怀疑算法,去检查你的优化问题是不是被合理编码了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询