☰
Matlab粒子群算法机器人路径规划:从编码到避坑全解析
2026/10/20 22:03:26 网站建设 项目流程

简介:粒子群算法(PSO)求解机器人路径规划的MATLAB实现资源,面向机器人、自动化及智能优化领域的学习者与研究者,解决栅格地图环境下从起点到终点的避障最短路径寻优问题。包内以42个m源码文件为核心,配合20个asv备份、4个mat数据文件、3个fig界面图以及示意图等,共71个文件约126KB,完整覆盖粒子群初始化、适应度评估、个体最优与全局最优更新、速度位置迭代等核心流程,并带有多种测试与对比脚本,便于理解算法收敛过程和参数影响。已有1055人学习下载。资源可用于课程设计、算法对比或二次开发,能帮助读者掌握PSO与栅格地图建模的结合方式,快速搭建属于自己的机器人路径规划实验环境,是一份适合入门与进阶参考的MATLAB算法工程包。

1. 粒子群算法在机器人路径规划里到底解决什么问题

一条从A点到B点的路径,如果只要求最短,Dijkstra就能做;如果要求绕开障碍物,A*也能做。但一旦路径需要同时满足“长度短、转弯平缓、离障碍物有安全裕度、机器人运动学还走得过去”,这就不再是最短路问题,而是一个带约束的多目标优化问题。粒子群算法(PSO)正好适合这种场景:它不依赖地图的解析结构,只要你能写出评价路径好坏的函数,它就能在连续空间里搜出一组可行的路径点序列。

这篇笔记想聊的是,用Matlab把PSO落地到机器人路径规划的全流程:粒子群算法的流程怎么和路径规划问题一一映射、路径怎么编码成粒子、碰撞检测和适应度函数怎么写、参数怎么调,以及那些一看就懂、一跑就翻车的细节。适合刚接触路径规划的入门者,也适合想把手头栅格地图快速升级成优化求解方案的一线工程师。看完你可以从空白的Matlab脚本,从零跑出一张避开障碍物的平滑路径图,并且知道每一段代码为什么这么写、出了问题往哪里查。

2. 粒子群算法的流程:从速度位置更新到路径规划的数学映射

2.1 粒子群算法的核心流程五步:初始化、适应度、更新、边界、终止

粒子群算法模拟的是鸟群觅食过程。每个粒子代表问题空间里的一个候选解,粒子有位置和速度两个属性:位置是解本身,速度决定下一轮它朝哪个方向运动、走多远。每一轮迭代中,粒子同时受到三个力的作用:惯性项让它保持原来的运动趋势;个体最优项把它拉向自己历史上表现最好的位置;全局最优项把它拉向整个群体目前发现的最好位置。三者的加权和就是下一轮的速度。

标准粒子群算法的流程可以压缩成五步。第一步是初始化,在搜索空间里随机撒N个粒子,赋予随机初始速度和初始位置。第二步是计算适应度,把每个粒子的位置代入评价函数,得到一个可以排序的分数。第三步是更新个体最优pbest和全局最优gbest,逐粒子比较当前分数和历史最优分数。第四步是按速度公式更新每个粒子的速度和位置,然后做速度限幅和位置越界处理。第五步判断终止条件,到达最大迭代次数或分数收敛就结束,否则回到第二步。

把粒子群算法的流程平移到机器人路径规划时,有三个关键转变容易被忽略。第一个转变是粒子从“一个数值”变成“一条路径”;第二个转变是适应度从“函数值”变成“路径评价”,要同时考虑长度、碰撞和平滑;第三个转变是搜索空间从低维数值空间变成路径点坐标空间,维度一旦超过20,PSO的收敛行为会发生明显变化,参数就不能再照搬教科书默认值。

速度更新公式里的两个rand()是关键,它让群体保持随机性。没有这两个随机项,所有粒子会沿确定方向运动,很快收敛到同一个位置,失去搜索能力。但随机项也带来一个副作用:维度越高,随机扰动越大,粒子轨迹越不稳定,所以vMax限幅在路径规划里比在低维函数优化里更重要。还有一个容易被忽略的点:机器人路径规划里的gbest未必是真实可执行路径,它可能只是“罚分最低的不可行路径”。因此终止条件不能只看gbest分数不变,还要在结束后对gbest解码做几何合法性校验。

2.2 把路径规划问题写成粒子:路径编码与目标函数设计

机器人路径规划的标准输入是一张栅格地图,加上起点startPt和终点goalPt,输出是一串路径点。用PSO求解时,最常见的做法是固定起点终点,把中间的n个路径点作为优化变量。假设每个路径点有两个坐标分量x和y,那么一个粒子的维度就是2n。比如n取10,粒子维度就是20,这在PSO里已经属于中等维度,需要适当放大种群规模才能稳住收敛。

路径点数量n直接决定了搜索空间复杂度。n取5时维度低,跑起来很快,但路径点太少,相邻点连线容易横穿障碍物;n取50时维度100,搜索空间指数膨胀,粒子群极易陷入局部最优。我一般把n设在地图上障碍物间距的3到5倍,比如障碍物间距大约5个栅格,那n取15到25,先用10个点调通整体流程,再慢慢加密。

目标函数设计的优先级是固定的:碰撞惩罚大于长度代价,长度代价大于平滑代价。碰撞是硬约束,用大惩罚值;长度和平滑是软约束,用加权和。这样做的好处是,即使粒子当前还在障碍物内部,它也能看到“靠近出口方向罚分在下降”的梯度,从而被引导出碰撞区域。如果碰撞只用0/1开关处理,不可行解之间没有任何排序,粒子就只能在地图里瞎撞,前几十代几乎不产生有效信息。

2.3 为什么用PSO而不是A*或RRT:算法选型的三个判断条件

A*在栅格地图上的地位不用多说,但它的输出本质是栅格序列,路线是锯齿状的,后续平滑成本高,而且搜索空间随地图尺寸快速膨胀。RRT在高维构型空间里很擅长找可行解,但解的质量通常较差,需要反复做重连优化。PSO的优势在于:路径质量可以直接用连续的目标函数引导,解本身是连续坐标序列,天然适合接样条平滑,也容易加转弯半径、能耗这些工程约束。

我给自己定的判断标准有三条。第一,目标函数能写出来,不一定凸,但必须有区分度,路径好坏能排序。第二,路径不能只看长度,还要叠加平滑度、安全裕度等软指标,这类问题PSO调权值比A改启发函数直观得多。第三,规划频率不高,比如离线预规划或者10Hz以下的在线重规划。三条都满足,用PSO;如果只满足第一条,地图又是几百乘几百的小栅格图,老老实实用A更稳。

3. 用Matlab实现路径编码:路径点序列与控制点样条,粒子怎么表示一条路径

3.1 方案一:等间隔路径点序列编码与初始化

这是最直接、最容易上手的做法。起点和终点固定,中间n个点先按等间隔分布在起点终点连线上,再沿连线的垂直方向加一个随机偏移,作为粒子的初始位置。这样做比全图均匀随机初始化好得多,因为粒子一开始就分布在地图连通的整体方向上,不会大量撒进障碍物内部白送迭代次数。

% 生成一个粒子的初始位置:起点终点连线加垂直随机偏移 function initPos = initParticle(startPt, goalPt, n, offsetRange) % startPt: 起点坐标 [x, y] % goalPt: 终点坐标 [x, y] % n: 中间路径点个数 % offsetRange: 垂直方向随机偏移范围,单位与地图坐标一致 % 在起点终点之间等间隔插值,得到 n+2 个基准点 baseX = linspace(startPt(1), goalPt(1), n+2); baseY = linspace(startPt(2), goalPt(2), n+2); % 计算起点到终点的方向向量,并取垂直方向 dx = goalPt(1) - startPt(1); dy = goalPt(2) - startPt(2); len = sqrt(dx^2 + dy^2); nx = -dy / len; % 垂直单位向量的 x 分量 ny = dx / len; % 垂直单位向量的 y 分量 initPos = zeros(1, 2*n); for k = 1:n % 在垂直方向加一个随机偏移,正负都可能 offset = (rand - 0.5) * 2 * offsetRange; initPos(2*k-1) = baseX(k+1) + nx * offset; initPos(2*k) = baseY(k+1) + ny * offset; end end

这段代码的逻辑分三块:先用linspace在起点和终点之间确定n+2个等距点,去掉首尾后得到n个基准路径点;然后计算连线方向的垂直向量;最后对每个基准点沿垂直方向加随机偏移。关键在第7到第11行,垂直向量取(-dy, dx)方向,这样偏移可以在连线两侧随机铺开,而不是只往一个方向偏。

参数说明:offsetRange一般取地图尺寸的5%到10%。太小粒子全部挤在起点终点连线附近,遇到障碍物时很难产生绕行路径;太大则初始路径过度弯曲,大量粒子起点就在障碍物里。调用时要注意,n必须和粒子维度保持对应关系,粒子维度是2n,这个函数只负责生成其中一个个体的初始位置,外部循环要按粒子群规模反复调用它。

3.2 方案二:控制点加样条插值,维度更低路径更平滑

路径点序列编码的缺点是,n个点之间如果距离太大,连线可能斜穿障碍物。另一个常见做法是改成少量控制点加样条插值:粒子只编码几个控制点,控制点之间用三次样条生成密集路径,再做碰撞检测。这种编码方式维度低,解出来的路径天然平滑,更接近移动机器人实际能走的轨迹形状。

% 从控制点生成三次样条路径,用于碰撞检测和代价计算 function densePath = cubicSplinePath(controlPts, numDense) % controlPts: (m x 2) 控制点矩阵,第一行是起点,最后一行是终点 % numDense: 插值后整条路径的采样点数 nCtrl = size(controlPts, 1); t = 1:nCtrl; tt = linspace(1, nCtrl, numDense); % 对 x 坐标和 y 坐标分别做三次样条插值 xi = spline(t, controlPts(:,1), tt); yi = spline(t, controlPts(:,2), tt); densePath = [xi(:), yi(:)]; end

样条的好处是让路径在控制点附近连续且二次可导,转角变化平缓,代价是样条插值会产生过冲:控制点明明在障碍物外,插值曲线却可能拱进障碍物内部。所以碰撞检测必须基于密化后的路径,而不是只检测控制点。这点我在做某仓储调度Demo时踩过,最初只检测5个控制点,路径图形完全正常,放到机器人仿真里连续撞了几次货架,最后改成对样条后的200个点逐段检测才通过。

如果地图复杂,纯随机初始化会浪费大量迭代。常见做法是先用A或Dijkstra跑出一条参考路径,然后以参考路径为骨架,在路径点两侧做高斯采样生成粒子的初始位置。这个技巧不改变PSO本身,只改初始化分布,却能把前50代的无效搜索省掉大半。实现上,先把A的栅格路径抽稀成几何路径点,再对每个点加一个标准差为地图尺寸2%的高斯扰动。

3.3 两种编码方式对比与选型建议

方案一实现简单、可控性强,每个粒子点都是实际路径点,方便调试时单点定位问题;方案二维度低、路径平滑,适合室内窄道或对转向角有要求的场景。下面这个表是我实际选型时参考的对比关系。

对比项方案一:路径点序列方案二:控制点加样条
粒子维度2n2m,m通常只有n的一半
路径平滑度依赖路径点密度,可能折线样条保证C2连续
碰撞检测成本逐线段采样,密度可控需要先密化再检测,成本略高
调试直观性直接看路径点位置过冲问题需要额外检查
适合场景障碍物稀疏、地图较大窄道、有转向半径约束

选用建议一句话:地图网格超过500×500优先方案一,机器人有转向半径限制优先方案二。如果两者都想要,可以先方案一迭代出最终路径,再用样条平滑,平滑后重做碰撞检测。维度选择的经验表我也直接给出来,方便照抄:100×100地图用6到8个中间点,粒子数30,迭代150次;300×300地图用10到15个中间点,粒子数40到50,迭代250次;500×500地图用15到25个中间点,粒子数50到80,迭代300到500次。

4. 完整Matlab求解代码:主循环、碰撞检测与三个必调参数

4.1 全局版PSO求解器主循环与初始化

下面给出一段可以直接套用的框架代码。地图用栅格矩阵map表示,1为障碍物,0为空地。粒子群规模、最大迭代、维度、速度上限都收在结构体params里,方便批量化调参。

function [bestPath, bestCost, history] = psoPathPlanner(map, startPt, goalPt, params) % params 字段说明: % nSwarm 粒子群规模 % nIter 最大迭代次数 % dim 粒子维度,等于中间路径点数的两倍 % vMax 单次速度最大步长 % c1, c2 个体学习因子和群体学习因子 % wMax, wMin 惯性权重上下限 % offsetRange 初始化时垂直偏移范围 nSwarm = params.nSwarm; nIter = params.nIter; dim = params.dim; % 位置边界:覆盖整张地图的坐标范围 lb = [1, 1]; ub = [size(map, 2), size(map, 1)]; lbAll = repmat(lb, 1, dim/2); ubAll = repmat(ub, 1, dim/2); % 初始化位置与速度 positions = zeros(nSwarm, dim); velocities = zeros(nSwarm, dim); for i = 1:nSwarm positions(i,:) = initParticle(startPt, goalPt, dim/2, params.offsetRange); velocities(i,:) = -params.vMax + 2 * params.vMax * rand(1, dim); end % 初始化个体最优和全局最优 pbest = positions; pbestCost = inf(nSwarm, 1); for i = 1:nSwarm pbestCost(i) = pathFitness(positions(i,:), startPt, goalPt, map, params); end [gbestCost, gidx] = min(pbestCost); gbest = positions(gidx, :); history = zeros(nIter, 1); % 主循环 for iter = 1:nIter % 惯性权重线性递减 w = params.wMax - (params.wMax - params.wMin) * iter / nIter; for i = 1:nSwarm r1 = rand(1, dim); r2 = rand(1, dim); % 速度更新:惯性 + 个体认知 + 群体认知 velocities(i,:) = w * velocities(i,:) ... + params.c1 * r1 .* (pbest(i,:) - positions(i,:)) ... + params.c2 * r2 .* (gbest - positions(i,:)); % 速度限幅,防止一步跨过整个地图 velocities(i,:) = max(min(velocities(i,:), params.vMax), -params.vMax); % 位置更新与越界截断 positions(i,:) = positions(i,:) + velocities(i,:); positions(i,:) = max(min(positions(i,:), ubAll), lbAll); % 适应度评估并更新最优 f = pathFitness(positions(i,:), startPt, goalPt, map, params); if f < pbestCost(i) pbestCost(i) = f; pbest(i,:) = positions(i,:); if f < gbestCost gbestCost = f; gbest = positions(i,:); end end end history(iter) = gbestCost; end % 解码最终最优路径 bestPath = decodePath(gbest, startPt, goalPt); bestCost = gbestCost; end

主循环的核心速度更新公式里,注意r1和r2是逐元素随机数,不是两个标量。逐元素随机意味着每个维度独立扰动,这在高维搜索里能保持各路径点的独立性,避免整条路径被同一个随机数整体平移。vMax限幅放在位置更新之前,力度要狠,直接截断速度向量。

gbest的更新逻辑藏在if分支里:当前粒子先更新自己的pbest,再判断是否更新全局gbest。这个顺序不能反,否则一个不可行粒子会先污染全局最优,而且后续其他粒子都无法把它拉回来。history记录的是每一代的全局最优分数,画出来可以直接观察收敛趋势,判断是探索不足还是已经早熟。

解码函数很简单,把粒子向量拆回路径点序列:

function path = decodePath(pos, startPt, goalPt) n = numel(pos) / 2; path = zeros(n + 2, 2); path(1, :) = startPt; path(end, :) = goalPt; for k = 1:n path(k+1, :) = [pos(2*k-1), pos(2*k)]; end end

4.2 碰撞检测与路径适应度函数:惩罚与权重的具体写法

适应度函数是PSO真正意义上的评价标准,它决定搜索方向。碰撞检测则是适应度函数里最不能出错的底层工具,漏检一次,整条“最优路径”就是危险路径。

function cost = pathFitness(pos, startPt, goalPt, map, params) path = decodePath(pos, startPt, goalPt); % 1. 路径总长度代价 segLen = sqrt(sum(diff(path).^2, 2)); lengthCost = sum(segLen); % 2. 碰撞惩罚:分段检测,每撞一段加一次惩罚 collisionCost = 0; for k = 1:size(path, 1) - 1 if segmentCollides(path(k,:), path(k+1,:), map, params.stepSize) collisionCost = collisionCost + params.collisionPenalty; end end % 3. 平滑代价:计算路径相邻段的转角,越弯越大 smoothCost = 0; for k = 2:size(path, 1) - 1 v1 = path(k,:) - path(k-1,:); v2 = path(k+1,:) - path(k,:); cosAngle = sum(v1 .* v2) / (norm(v1) * norm(v2) + eps); smoothCost = smoothCost + (1 - cosAngle); end cost = params.wLen * lengthCost + collisionCost + params.wSmooth * smoothCost; end

长度代价用相邻路径点差分后逐段求欧氏距离再求和。碰撞惩罚逐段累加,每段只要和障碍物相交就加固定值,这样“撞一段”的路径和“撞五段”的路径分数有区分度,粒子能感知到碰撞数量的变化。如果只用单一巨大惩罚叠加到整条路径,所有不可行解的分数完全相同,搜索就退化成随机碰运气。

平滑代价用相邻两段向量的夹角余弦补数,路径完全直线时1-cosAngle等于0,急转弯时接近2。这个量纲天然和长度代价接近,不需要额外归一化。collisionPenalty的取值要和长度代价在同一决策平面上,我一般取地图对角线长度的10倍,再加wLen把长度项归一化到100以内。

function collides = segmentCollides(p1, p2, map, stepSize) d = norm(p2 - p1); numSamples = ceil(d / stepSize); collides = false; for s = 0:numSamples t = s / max(numSamples, 1); pt = p1 + t * (p2 - p1); % 连续坐标映射到栅格索引,并做边界截断 col = min(max(round(pt(1)), 1), size(map, 2)); row = min(max(round(pt(2)), 1), size(map, 1)); if map(row, col) == 1 collides = true; return; end end end

stepSize是关键细节,它决定线段上采样密度。推荐取栅格分辨率的0.5倍,比如栅格1米,采样步长取0.5米。取大会漏检细长障碍物,取小计算量成倍上涨。这里用round把连续坐标映射到栅格,配合min/max避免越界访问。

4.3 必调的三个参数:惯性权重、学习因子、速度上限

惯性权重w决定粒子继承上一代速度的程度。w大,粒子飞得远,全局探索强;w小,粒子在局部精细搜索。最常见的设置是wMax 0.9、wMin 0.4,配合线性递减,前中期探索、后期收敛。如果发现收敛进局部最优,把wMin提高到0.5,让后期保留一定逃逸能力。

学习因子c1、c2控制粒子靠向个体最优和全局最优的拉力。经典值是2.0和2.0,但实测高维路径规划里震荡明显。我习惯取c1=1.7、c2=1.7,偶尔会让c1略大于c2,让粒子先充分探索自己的历史区域,避免过早被全局最优吸过去。

vMax是安全阀,限制单次速度最大步长,防止粒子一步跳出地图或者跨过窄道障碍物。经验值是地图对角线长度的5%到10%。调参顺序建议:先固定w和c,只调vMax;路径能避开障碍但绕远,说明vMax太大,减小;路径陷入局部最优,说明vMax太小,增大并同步提高wMin。

参数推荐范围调整方向
wMax0.9收敛过快就接近1.0
wMin0.4早熟就提高到0.5
c11.7个体探索不足就增大
c21.7收敛太慢就增大
vMax地图对角线5%~10%路径绕远就减小,陷入局部就增大
collisionPenalty对角线长度的10倍碰撞多就增大

这些参数没有万能组合,但按“先保证不撞、再逼短、最后磨平”的顺序去调,比乱试快得多。每次调整只动一个参数,记录前后结果,这是PSO调参最基本也最容易被忽略的习惯。

5. 常见问题与避坑:五个一跑就翻车的粒子群路径规划细节

在整理坑之前,先解释一个现象:为什么PSO路径规划总是“看起来能跑,实际老翻车”。因为PSO是随机搜索,任何一次运行都是随机过程的一次采样。同一套参数跑十次,可能八次正常、两次撞墙,这种随机性会让新手很难判断自己到底改对没有。所以遇到翻车不要急着改参数,先复现三次,确认是参数问题还是随机性问题。

5.1 避坑记录1:适应度函数量纲不一致,路径疯狂绕远

现象:迭代几百次,最优路径明明不撞墙,却绕了地图一大圈,长度是直线距离的两三倍。

原因:长度代价数量级在几十,碰撞惩罚数量级在几千,两个项加在一起时,长度项被完全淹没。粒子只要不撞墙,分数基本由碰撞项决定,长度项完全不起作用,路径自然随便绕。

解决:把长度项归一化。用地图对角线长度做参考,cost = 100 * (lengthCost / diagLen) + collisionCost,把长度代价限制在100以内,碰撞惩罚取1000。两项在同一个决策层面上之后,粒子才会真正权衡“绕一点近路”和“撞一段墙”之间的代价。改完后还要把wSmooth调低,否则平滑项又会喧宾夺主。

5.2 避坑记录2:速度上限没限制,粒子直接飞出地图边界

现象:粒子初始位置还在起点附近,几百次迭代后,位置坐标跑到负数或者上万,代码在栅格索引处直接报错。

原因:速度更新公式里w * v保留了大速度,加上c2 * rand * (gbest - pos)后步长继续放大。如果vMax不设置,粒子几代就能飞出地图。

解决:主循环中加vMax限幅语句,velocities(i,:) = max(min(velocities(i,:), vMax), -vMax)。位置越界用截断到边界的方式处理,简单可靠。如果想保留多样性,可以在越界时把该维速度清零并随机重置位置,效果更好但要多写几行逻辑。

5.3 避坑记录3:初始化粒子全在障碍物内,前几十代找不到可行解

现象:迭代前五十代,全局最优分数纹丝不动,所有粒子都贴着障碍物分数很高。

原因:初始化粒子完全随机铺满地图,而障碍物密度高的时候,随机点落在障碍物内的概率很大。适应度函数里大量粒子都在碰撞状态,搜索梯度形同虚设。

解决:把初始化从全图均匀随机改成起点终点连线加小偏移,也就是第3章initParticle的做法。如果地图障碍物特别复杂,先跑一次A*得到参考路径,在参考路径周围做高斯采样初始化粒子。这两招都能把前50代的无效迭代省掉大半。

5.4 避坑记录4:惯性权重线性递减太快,后期收敛进局部最优

现象:前200代收敛很快,分数下降到一个值后不再变化,把粒子数从40加到120也无济于事。

原因:w从0.9线性降到0.4,前期探索充分,但后期w太小,群体速度快速趋同。一旦gbest被某个不可行但罚分不高的解带偏,所有粒子都被它吸引,再想跳出去就难了。

解决:改用非线性递减,w = 0.9 - 0.4 * (iter/nIter)^0.8,指数小于1让递减变慢。更有效的做法是每100代重构一部分粒子,在gbest附近加高斯噪声重新散布,保持群体活力。实测对机器人路径规划这类高维问题,重构策略比单纯调w有效得多。

5.5 避坑记录5:可视化路径平滑好看,机器人实际走不了

现象:Matlab画出的路径是平滑曲线,放到仿真里机器人却擦过墙角或者截穿障碍物。

原因:可视化画的是路径点连接线,碰撞检测时采样步长太粗,漏检了细长障碍物;或者样条插值后曲线拱起越过障碍物,但检测只针对原始路径点,没有检查插值后的密化路径。

解决:碰撞检测采样步长必须小于机器人半径。机器人半径0.2米,stepSize就取0.1米。样条插值后的密化路径也要重新走一遍segmentCollides。每次改完路径生成方式,都强制把“检测路径”和“实际执行路径”用同一份代码重新检测一遍,不要用肉眼代替检测。

6. 把PSO结果落地:样条平滑、二次碰撞复检与验证技巧

6.1 平滑后必须重新过一遍碰撞检测

PSO输出的路径点数量有限,直接交给机器人执行会走折线。常见做法是先用三次样条平滑,再对平滑后的路径逐段做碰撞复检。这两步缺一不可,平滑只是几何变换,不保证安全性。

% 对PSO解码后的路径做样条平滑,采样成200个点 pathDense = cubicSplinePath(bestPath, 200); % 二次碰撞复检:平滑后路径必须逐段重新检测 collisionFree = true; for k = 1:size(pathDense, 1) - 1 if segmentCollides(pathDense(k,:), pathDense(k+1,:), map, 0.5) collisionFree = false; break; end end if ~collisionFree % 平滑后穿障碍物,说明中间路径点太稀疏,需要增加粒子维度重新规划 disp('平滑路径存在碰撞,增加中间路径点后重新运行'); end

6.2 与参考算法的交叉验证和调参记录

验证PSO结果是否可信,我的习惯是在同一张栅格地图上跑A做对照,对比两个指标:路径长度和规划耗时。PSO路径长度小于等于A路径长度且不撞障碍物,说明目标函数和参数整定到位;PSO路径长度比A*长15%以上,说明权重分配有问题,大概率是长度代价权重太低。

每次调参只改一个变量,并记录成一张简单的参数表,包括粒子数、迭代次数、vMax、wMin、路径长度、碰撞次数。连续记录十次,比用眼睛盯收敛曲线可靠得多。参数不合适的现象也很有规律:路径绕远就加wLen,路径抖动就加wSmooth,撞障碍物就加大collisionPenalty,收敛不稳就降vMax。

我最早做某图像处理Demo里的路径规划时,贪图平滑曲线好看,跳过二次碰撞复检,结果仿真环境里机器人直接刮上货架。从那以后,我的流程里永远固定三件套:PSO求解、样条平滑、逐段复检,任何一步都不能省。这个习惯帮我避掉了后来很多次看似“随机”的翻车,也希望帮到你。

本文还有配套的精品资源,点击获取

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

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

立即咨询