【AUV任务分配】自组织映射SOM+Dubins曲线水下机器人多目标任务分配MATLAB仿真(含洋流、障碍物约束)
✅作者简介:热爱科研的Matlab仿真开发者,擅长数学建模、数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。
🍎 往期回顾关注个人主页:Matlab科研工作室
👇 关注我领取海量matlab电子书和数学建模资料
🍊个人信条:格物致知,完整Matlab代码获取及仿真咨询内容私信。
🔥 内容介绍
大家好,今天给大家带来一套面向水下 AUV(自主水下航行器)的多目标任务分配 MATLAB 仿真代码。这套方案采用SOM 自组织映射神经网络作为任务分配核心,区别于传统匈牙利算法、遗传算法等优化方法,属于自组织、分布式的任务指派思路;同时结合 Dubins 曲线实现带航向约束的轨迹生成,支持圆形障碍物避障、洋流扰动、单机器人负载上限约束,非常适合水下集群协同作业方向的课程设计、毕设和算法基线验证。
很多做 AUV 协同的同学容易踩一个坑:只做静态任务点的距离最优分配,忽略水下航行器本身的运动特性。AUV 不是可以瞬间转向的质点,它存在最小转弯半径,出发和到达都带有航向角约束,两点之间不能直接用欧氏距离评价代价。这份代码最大的亮点,就是把任务分配和运动轨迹代价(Dubins 路径长度)绑定在一起,同时引入障碍物、洋流、单机任务上限多重约束,更贴近真实水下作业场景。
一、项目整体概述
这套仿真系统解决的问题:给定多台 AUV 机器人、多个水下任务目标点,在存在障碍物、洋流干扰、AUV 最小转弯半径限制、单机任务数量上限的条件下,自动把目标任务分配给合适的 AUV,并且生成满足航向约束的 Dubins 航行轨迹。
核心实现模块:
SOM 自组织映射神经网络,作为任务分配主体,竞争获胜神经元机制完成目标指派;
Dubins 曲线轨迹生成,适配 AUV 非完整约束,起点、终点都携带航向角;
障碍物代价判断函数,分配时规避障碍物,不生成穿过障碍的路径;
洋流扰动模型,可开启洋流对 AUV 位置更新的偏移影响;
负载约束机制,限制单台 AUV 最多承接任务数量,避免任务过载;
任务监控模块,记录每台 AUV 承接任务数量、累计航行里程;
可视化绘图:初始位置分布图、任务分配连线图、轨迹实时绘制。
参数模式可选:
lineFlag=0:两点之间直线距离,适合理想质点模型对比;
lineFlag=1:Dubins 曲线,机器人和目标都带航向角,最贴合 AUV 场景;
lineFlag=2:仅机器人带航向角,目标点无航向约束;
洋流开关 currentFlag:0 关闭洋流,1 启用洋流偏移;
ObstacleFlag:障碍物显示开关,圆形障碍物模型。
✅ 已实现功能
多 AUV、多任务点初始化,支持自由增减机器人与目标数量;
SOM 竞争机制,每个任务点寻找代价最小的 AUV 作为获胜单元;
邻域权值更新,完成自组织映射迭代;
Dubins 路径计算,输出路径实际长度作为分配代价,而不是简单欧氏距离;
障碍物检测:如果 Dubins 路径穿过障碍物,会抬高代价,优先避开障碍;
负载上限约束,防止某一台 AUV 被分配过多任务;
洋流扰动叠加到 AUV 位置更新过程;
实时绘图,输出分配连线与航行轨迹。
⚠️ 方案本身存在的局限(适合写论文研究缺口)
SOM 用于任务分配属于启发式自组织方法,有它固有的短板:
SOM 是竞争学习机制,不能保证全局最优分配,更容易收敛到局部较优解;
邻域参数 r、学习率 B 需要人工调参,参数敏感,不同地图场景适配性差;
障碍物仅做代价惩罚,没有在线重规划,任务分配完成后路径固定;
没有动态目标、动态障碍物,当前所有任务点、障碍物都是静态;
没有考虑 AUV 能耗、通信距离、作业时间等更多水下约束;
未加入 AUV 之间的互避,只检测任务路径和环境障碍物冲突。
这些局限不是代码 bug,而是 SOM 任务分配方法本身的特性,也是后续改进创新的切入点。
二、代码整体结构与变量说明
这是单脚本一体化仿真,没有拆分成多个 m 文件,内部通过子函数调用实现模块化,包含:
主脚本:参数初始化、地图、机器人、目标、障碍物、洋流、SOM 参数;
distanceFunction:基础距离计算(基线版本);
obstacleFunction:带障碍物判断的代价函数,是整个分配逻辑的核心;
neighborFunction:SOM 邻域函数,计算获胜神经元的邻域范围;
updateCurrentFunction:SOM 权值更新函数,可叠加洋流扰动;
printerLineFunction:直线轨迹绘制,返回直线长度;
printerDubinsFunction:Dubins 曲线绘制,返回 Dubins 路径长度。
关键变量含义梳理:
Robot:AUV 二维坐标矩阵,每一列是一台机器人的 (x,y);
RobotV:AUV 速度与航向角,第二行是和 X 轴正方向的夹角;
Target:任务目标点坐标;
TargetV:目标点期望到达航向角;
Obstacle、ObstacleR:圆形障碍物中心坐标与半径;
RobortMonitor:监控矩阵,第一行记录每台 AUV 承接任务数,第二行记录累计航行距离;
taskMax:单台 AUV 最大任务上限,由总任务数除以机器人数量向上取整得到;
maxDis:单台 AUV 允许的最大航行里程阈值;
turnR:Dubins 曲线最小转弯半径,AUV 运动核心约束;
B、r:SOM 超参数,B 为学习率,r 为邻域半径;
vc、ai:洋流速度大小、洋流流向角;
Weight:SOM 神经元权重,这里直接映射 AUV 的位置;
WeightV:保存每台 AUV 当前航向角。
这个 SOM 的设计思路很巧妙:把每一台 AUV 直接当成 SOM 的一个神经元。每一个任务点输入网络,所有 AUV 互相竞争,代价最小的那台 AUV 成为获胜神经元,之后更新获胜神经元及其邻域的权值(也就是 AUV 虚拟位置),逐步完成任务点的映射分配。
三、运行流程拆解
第一步:环境与实体初始化
脚本开头先清空画布、设置仿真区域,然后依次定义:
任务目标点坐标、目标到达航向;
AUV 初始坐标、初始航向;
圆形障碍物位置与半径;
校验维度:目标数量和目标航向数量一致,机器人数量和机器人航向数量一致;
初始化监控数组 RobortMonitor,用来约束负载、统计里程;
设置 Dubins 转弯半径、洋流开关、轨迹模式开关 lineFlag。
然后绘制两张初始图:第一张是初始位置分布图,菱形标记 AUV,大圆点标记任务,叉号标记障碍物;第二张用于绘制任务分配连线与轨迹。
第二步:SOM 竞争分配主循环
循环遍历每一个任务目标点,依次执行下面这套逻辑:
调用 obstacleFunction,对当前任务点,计算所有 AUV 到该目标的代价; 代价不再是简单欧氏距离,而是 Dubins 路径长度,同时检测路径是否穿过障碍物;如果穿过障碍,代价会显著变大,该 AUV 不会优先被选中;
选出代价最小的 AUV,也就是获胜神经元 winnerR,对应的目标点 winnerT;
更新监控表:这台 AUV 承接任务数量 + 1;
判断该目标是否已经被分配,避免重复指派;
未分配的目标,进入 SOM 邻域更新:
neighborFunction:根据邻域半径 r,找到获胜神经元附近的神经元;
updateCurrentFunction:更新 AUV(神经元)的位置;如果开启洋流,位置更新时叠加洋流带来的偏移;
根据 lineFlag 选择轨迹生成方式:
直线模式:调用 printerLineFunction,画直线,返回直线长度;
Dubins 模式:调用 printerDubinsFunction,生成带起点航向、终点航向的 Dubins 曲线,绘制曲线并返回路径长度;
更新获胜 AUV 的航向角,任务完成后航向对齐目标的期望航向;
累加航行里程到 RobortMonitor,用于里程上限约束。
重点:为什么用 Dubins 代价而不是欧氏距离? AUV 属于非完整约束机器人,它不能侧向平移,运动受最小转弯半径限制。同样两个点,不同的起点航向、终点航向,Dubins 路径长度差异很大。如果只用欧氏距离分配,会出现 “距离很近,但 AUV 很难掉头到达、路径很长” 的不合理分配结果,这也是水下任务分配和地面机器人分配最大的区别。
第三步:障碍物与负载约束逻辑
obstacleFunction 是整套代码的约束核心:
输入:目标坐标、所有 AUV 位置、航向、障碍物信息、任务监控信息;
内部判断两条:①当前 AUV 任务数量是否已经达到 taskMax 上限;②候选 Dubins 路径是否与圆形障碍物相交;
只要触发负载超限,或者路径撞障碍,代价 Dist 就会被拉高,该 AUV 在本次竞争中落败;
只有负载充足、路径无碰撞的 AUV,才会以真实 Dubins 路径长度作为竞争代价。
这就实现了:任务分配阶段就同时考虑避障 + 负载均衡,而不是分配完成之后再去检查是否冲突。
第四步:洋流扰动机制
洋流是水下环境不可忽略的干扰。开启 currentFlag=1 之后,在 SOM 权值(AUV 位置)更新的时候,叠加洋流带来的位移偏移。 ai 是洋流流向角,vc 是洋流流速对应的偏移量。这个模型是简化的定常洋流模型,适合验证洋流对分配结果的影响:洋流会改变 AUV 等效到达代价,SOM 会倾向于把任务分配给顺着洋流方向航行的机器人,减少航行消耗。
四、核心算法原理:SOM 自组织映射用于任务分配
SOM 自组织映射是一种无监督竞争型神经网络,常规 SOM 用来做降维、聚类。而在这个 AUV 任务分配场景里,做了改造:
神经元集合 = AUV 集群;
输入样本 = 待分配的水下任务点;
竞争规则:输入一个任务点,所有神经元计算代价(Dubins 路径代价 + 障碍物惩罚 + 负载惩罚),代价最小的获胜;
学习规则:获胜神经元和它邻域内的神经元,向任务点方向更新自身位置;
自组织的结果:任务点会自发映射到最合适的 AUV 附近,形成任务指派。
对比其他经典任务分配算法:
匈牙利算法:求全局最优,适合小规模、静态、无复杂约束场景,维度大的时候计算量爆炸;
遗传算法、粒子群:群智能优化,迭代寻优,计算开销大;
SOM:分布式竞争,计算速度快,天然适合动态逐步分配,缺点是很难保证全局最优。
所以这套方案非常适合作为分布式集群任务分配的基线,用来和集中式最优算法做对比。
⛳️ 运行结果
📣 部分代码
function currentDistance = printerLineFunction(x1,x2,y1,y2,color,width)
line([x1,x2],[y1,y2],'Color',color,'LineWidth',width);
currentDistance=((x1-x2)^2+(y1-y2)^2)^0.5;
end