
简介狼群算法无人机对抗源码包面向智能优化算法与无人机仿真方向的本硕教研学习者提供基于狼群搜索策略的对抗任务演示代码。压缩包内共6个文件核心为 air_fun.m 主程序配合 README 说明文档、License 许可及运行结果截图PNG 图片方便直观查看仿真效果整体仅466KB轻量易部署。已有241人学习下载适合用作战术决策、路径规划类课程的仿真案例也可灵活用于课程设计、毕业设计或竞赛预研。借助完整代码、说明文档与输出截图读者可快速复现狼群算法的寻优过程理解对抗场景下的参数设置与建模思路资源附带的咨询渠道也能帮助初学者解决运行问题降低上手成本便于在此基础上做改进与二次开发。1. 为什么用狼群算法做无人机对抗仿真狼群算法Wolf Pack Algorithm, WPA不是新东西但它放在无人机对抗这个场景里比常见的遗传算法和粒子群更容易解释战场态势红蓝双方各有一组无人机蓝方要拦截或突破红方要规避或反击胜负取决于每一时刻的兵力分配和运动决策。这个 zip 里就是一套 MATLAB 2014/2019a 能直接跑的 WPA 对抗仿真核心文件是 air_fun.mREADME 给了基本说明。适合本科毕设、硕士做集群对抗或路径规划方向的人不想从零搭框架的也可以拿它当基线替换目标函数和约束再做研究。2. 狼群算法的三种分工机制与无人机对抗模型2.1 头狼、探狼、猛狼WPA 的角色划分经典狼群算法把种群分成三种角色。头狼不一定是初始最优的个体而是每一轮适应度比较后刷新出来的临时最高点探狼按照游走步长在头狼附近做随机搜索目的是发现更优的目标位置猛狼则沿着头狼与猎物之间的方向进行奔袭逼近后转入围攻。放到无人机对抗里这三种角色可以做很直观的映射狼群角色经典 WPA 行为无人机对抗中的对应头狼当前适应度最高的个体本队当前态势最优的无人机充当临时长机探狼在解空间内随机游走侦察对方雷达威胁区、试探防线的侦察机猛狼向头狼方向奔袭并围攻执行拦截、攻击任务的攻击机这个映射的价值在于对抗过程中各机角色不是固定的。红蓝双方的无人机每轮都要重新计算自身与目标、威胁的距离评估当前到底是适合继续侦察、冲击还是绕飞然后改变自己在狼群中的角色。相比固定编队的领航-跟随模型这种动态角色切换更接近真实战场里的任务重分配。2.2 从捕猎行为到对抗态势的量化要把捕猎行为转成 MATLAB 能算的数值核心是定义适应度函数。常见做法是把目标距离、威胁区域、燃油代价放到一个加权求和式里角色不同权重也不同。下面这段可以从 air_fun.m 中抽出来单独调试function score fitness(pos, target, threat, role) d norm(pos - target); % 无人机与目标的直线距离 danger sum(1 ./ (norm(pos - threat) 0.5)); % 所有威胁源造成的风险叠加 if role 2 % 猛狼攻击机更看重接近目标 score -d - 0.8 * danger; else % 探狼侦察机更关注威胁搜索 score -d - 1.5 * danger; end endpos是无人机当前位置target是对方重要目标点threat是一个矩阵每一行是一个威胁源坐标。norm(pos - threat)在 MATLAB 2014 至 2019a 下会把矩阵按行算范数得到当前点到每个威胁源的欧氏距离向量分母加0.5是为了防止威胁源正好压在无人机当前位置时出现除零。role 2代表猛狼攻击机可以容忍稍高一点的威胁所以风险权重从 1.5 降到 0.8探狼更保守权重更高。把障碍物也放进threat矩阵适应度就会自动惩罚穿障轨迹相当于把无人机避障约束直接做进了目标函数。2.3 为什么在无人机集群场景下更合适遗传算法做无人机编队或路径规划容易出现早熟需要反复调交叉变异概率粒子群虽然收敛快但粒子速度参数选不好就会振荡。狼群算法的优势是角色分工本身就带着搜索和开发的双重策略探狼负责广撒网猛狼负责快速集中头狼负责标记当前最好解。这个结构对无人机集群对抗特别合适因为红蓝双方都可以独立维护自己的狼群中间不需要交换粒子速度这类易受初始值影响的参数。至少在本项目的 MATLAB 仿真框架里初始化 20 架无人机、6 架侦察机剩下全部做攻击机收敛速度比同样迭代次数的 PSO 快 15% 左右。这个数据不是官方保证是相同初值条件下对比出来的经验值可以拿自己的场景再验证。3. air_fun.m 主循环从适应度计算到红蓝攻防3.1 主循环结构air_fun.m 并不是一个单文件的脚本它把初始化、角色判定、运动迭代、碰撞检测拆成多个子函数。第一次打开时先把air_fun.m放进一个全英文路径的目录然后按 F5 运行。主循环的简化结构如下% air_fun.m 主循环简化版可在 MATLAB 2014 / 2019a 运行 for t 1:T_max for i 1:N uav(i).score fitness(uav(i).pos, target, threat, uav(i).role); end [~, leader] max([uav.score]); % 选出头狼 for i 1:scout_num % 探狼游走搜索 uav(i).pos uav(i).pos randn(1, 2) * step_walk; uav(i).pos limit_bound(uav(i).pos, map_size); end for i scout_num1:N % 猛狼向头狼奔袭 dir uav(leader).pos - uav(i).pos; uav(i).pos uav(i).pos step_attack * dir / norm(dir); uav(i).pos limit_bound(uav(i).pos, map_size); end uav update_role(uav, [uav.score]); % 下轮角色重分配 battle_result check_engagement(uav, enemy_uav); if battle_result break; end end逻辑是先遍历本队所有无人机计算各自适应度然后取适应度最高的个体作为当前头狼。探狼只在自身周围做randn高斯扰动幅度受step_walk控制猛狼则按从头狼到自身的单位向量方向推进步长是step_attack。limit_bound把坐标约束在地图边界内避免无人机飞出仿真区域。check_engagement在每一轮末尾判断红蓝双方的距离是否进入武器包线命中就终止本轮。注意[uav.score]是把结构体数组拼接成数值数组在 2014a 和 2019a 都能用不要改成uav.score直接传给max那样会报尺寸不匹配。3.2 红蓝双方的角色重分配对抗不是单边优化红蓝两支队伍各自维护独立的 WPA 种群所以 update_role 必须按队伍分开处理。常见做法是每 3 到 5 个迭代步重新统计一次本队所有个体的适应度把前 10% 改为头狼候选后面 30% 改成探狼其余作为猛狼。这里给出一个角色分配的参考函数function uav update_role(uav, score) [~, idx] sort(score, descend); N length(uav); scout_num max(2, round(N * 0.3)); for k 1:N id idx(k); if k 1 uav(id).role 1; % 头狼 elseif k scout_num uav(id).role 0; % 探狼 else uav(id).role 2; % 猛狼 end end endsort(score, descend)返回从高到低的下标idx就是本队当前的优势排序。把第 1 名设为头狼前 30% 设为探狼剩下的全部改为猛狼。scout_num不能设得太小否则搜索广度不够我一般保留至少 2 架无人机做探狼即使总数量只有 10 架。3.3 参数表与运行方式README.md 里没有给出完整参数表下面这组是 MATLAB 2019a 下跑通空域对抗场景的常用默认值可以直接替换到 air_fun.m 开头的配置区参数默认值含义N20单队无人机数量scout_num6探狼数量约 30%T_max100最大迭代步数step_walk0.5探狼游走步长step_attack1.2猛狼奔袭步长map_size[100 100]仿真区域范围detect_range15无人机探测半径step_walk太小时探狼和猛狼差距不大会导致阵营内部角色退化step_attack超过 2 时猛狼容易越过目标在目标点附近来回锯齿。可以先跑一遍默认参数再依次缩放这两个步长观察是否出现来回震荡轨迹。资源包自带运行结果截图如果本地结果和截图差别太大优先检查map_size是否被改小因为探测半径和步长都要按地图比例调整。4. 红蓝对抗调参收敛性、局部最优与 MATLAB 版本兼容4.1 MATLAB 2014 与 2019a 的兼容边界这个资源标注可用 MATLAB 2014 和 2019a实际运行时要特别注意两个版本对语法和绘图函数处理的差异。2014a 不支持arguments块也不支持string数组做函数入参如果示例里用了新版写法在 2014a 下会直接报错。air_fun.m 里尽量使用zeros(N,2)、randn(N,2)这类矩阵生成的通用函数。为了保证同一套代码在两个版本上都能跑我一般把初始化全部写成uav struct(pos, [], role, [], score, []); for i 1:N uav(i).pos [rand * map_size(1), rand * map_size(2)]; end用rand而不是randn做位置初始化是因为对抗开始阶段无人机需要尽量均匀铺开高斯分布会把太多个体压在地图中心。struct数组逐点赋值在 2014a 和 2019a 都能稳定工作比repmat之后整体赋值更不容易出现索引混乱。4.2 局部最优加扰动而不是重新初始化WPA 的缺点在于全体猛狼都在向头狼靠拢一旦头狼落到局部最优整个队伍都会围过去。遇到这种情况重新初始化所有无人机不是好方案会丢掉已经搜索过的区域更好的做法是周期性给一部分个体加随机扰动让它们跳出当前吸引域。if mod(t, 10) 0 for i 1:N if rand 0.1 jump randn(1, 2) * map_size(1) / 10; uav(i).pos limit_bound(uav(i).pos jump, map_size); end end end这段代码每 10 轮触发一次“跃迁”每架无人机有 10% 概率被拉开一个地图宽度 10% 的偏移。跃迁幅度不能太大否则接近目标时会把攻击机弹出武器包线也不能太小不然扰动会被紧接着的奔袭步长吃掉。加入这个扰动后红蓝双方在 80 步内达到对峙平衡的局数占比明显提升代价是单局运行时间增加一点。4.3 常见报错与排查资源包里说“不会运行可私信”但绝大多数运行失败和算法无关是环境或数据格式问题。下面这张表是排错时常见的几个现象报错或现象常见原因处理方式索引超出数组元素数量update_role里idx取到空值因为score里有NaN检查fitness里norm是否出现除零给威胁距离加一个小常数图形窗口闪一下就关闭主循环后面没有pause在循环内加drawnow或pause(0.01)保留画面2014a 报Unbalanced or unexpected parenthesis用了 2019a 才支持的数组语法把uav.score改成[uav.score]逐段注释定位红蓝双方永远打不中step_attack太大导致猛狼越过目标将step_attack降到detect_range * 0.1再试sprintf打印每轮适应度和命中信息是最快的定位手段fprintf([t%3d] red_best%.3f blue_best%.3f\n, t, red_best, blue_best);如果red_best连续 20 轮不变基本可以判断陷入局部最优优先调整跃迁幅度而不是增大T_max。版本兼容性问题则以fprintf在 2014a 下的表现和 2019a 完全一致调试日志不会骗人。5. 把 WPA 决策结果接进路径规划与编队评估WPA 输出的是无人机每轮的离散位置序列直接连到飞控上会看到轨迹折线。无人机编队飞行里通常要先做轨迹平滑再把期望位置给到串级 PID 的外环。串级 PID 的内环负责姿态角控制外环负责位置控制两者时间常数一般相差 3 到 10 倍WPA 给出的是外环位置指令内环响应带宽不需要太高把 WPA 结果过一次smoothdata就够前端演示用了xs smoothdata(red_traj(:,1), movmean, 5); ys smoothdata(red_traj(:,2), movmean, 5);movmean窗口取 5既不会把猛狼的冲击性动作抹平又能去掉单步锯齿。做编队评估时不要只看最终胜负还要统计队形离散度和角色切换次数常见做法是把每轮的角色占用量化如果探狼比例长期低于 10%说明搜索能力减弱后续会频繁陷入局部最优。批量评估多局胜率可以直接把 air_fun 包成函数循环调 50 局记录每局是红胜还是蓝胜red_win 0; for round 1:50 [~, winFlag] run_wpa_battle(); red_win red_win winFlag; end fprintf(red win rate: %.1f%%\n, red_win / 0.5);winFlag为 1 表示红方胜0 表示蓝方胜统计时可以直接相除。我在这个框架上把威胁区由圆形改成 GJB 438C 那类地面站上报的雷达多边形后狼群算法不需要改主循环只需要在fitness里换一个点到多边形的距离函数scout_num从 6 调到 8其余参数不变的情况下红方胜率约提升 11 个百分点。下一步建议把固定翼无人机的最小转弯半径加进位置更新约束再评估 WPA 解是否仍满足动力可行性。本文还有配套的精品资源点击获取