全局路径规划器调参:A*与Dijkstra算法原理、规划器参数详解、路径平滑度优化
说到全局路径规划,很多新手容易把它和局部规划搞混。我简单解释一下:全局规划是「看地图找路」,局部规划是「看传感器躲障碍」。今天咱们就聚焦前者,把A*和Dijkstra这两个老牌算法聊透。
一、A*与Dijkstra:两个核心算法的本质区别
先问个问题:你从北京去上海,是走直线快,还是绕道南京快?
Dijkstra的做法是:把所有可能的路都走一遍,最后告诉你最短的那条。A*则聪明一些——它知道上海在东边,所以优先往东走,西边的路基本不碰。
算法核心差异
- Dijkstra:只考虑「已走距离」(g值),保证找到最短路径,但搜索范围大
- A*:考虑「已走距离 + 预估距离」(g + h),用启发函数引导搜索方向
我在项目中遇到过一个问题:用Dijkstra规划10km×10km的地图,跑了3秒才出结果。换成A*后,同样的地图0.3秒就搞定了。你想想看,对于实时性要求高的机器人,这个差距意味着什么。
关键公式
A*的代价函数:f(n) = g(n) + h(n)
其中h(n)是启发式估计,常见的有欧几里得距离、曼哈顿距离
二、规划器参数详解:ROS中的navfn与global_planner
ROS里常用的全局规划器有两个:navfn和global_planner。我个人习惯用global_planner,因为它更灵活,参数也更丰富。
| 参数名 | 默认值 | 说明 | 我的建议 |
|---|---|---|---|
| use_dijkstra | false | true用Dijkstra,false用A* | 地图小于500×500用A*,更大用Dijkstra |
| use_quadratic | true | 二次近似,影响路径平滑度 | 建议开启,路径更自然 |
| lethal_cost | 253 | 障碍物代价值 | 别改太小,否则路径会贴墙 |
| neutral_cost | 50 | 自由空间代价值 | 调大可以让路径更居中 |
| cost_factor | 0.55 | 代价缩放因子 | 我一般设0.6~0.8,路径更安全 |
嗯,这里要注意:use_quadratic这个参数很多人忽略。它控制的是代价的衰减方式。开启后,路径会倾向于走「中间」,而不是贴着障碍物边缘。我在做仓储机器人时,就因为没开这个参数,机器人老是蹭着货架走,看着都揪心。
三、路径平滑度优化:让机器人走得更像人
A*规划出来的路径有个毛病——全是直角转弯。你想想看,机器人走到墙角突然来个90度急转,不仅看着别扭,轮子磨损也大。
优化方法一:路径剪枝
去掉路径中不必要的中间点。比如三个点A→B→C,如果A到C的连线不碰障碍,就把B去掉。
def prune_path(path):
pruned = [path[0]]
for i in range(1, len(path) - 1):
if not in_line_of_sight(pruned[-1], path[i+1]):
pruned.append(path[i])
pruned.append(path[-1])
return pruned
优化方法二:贝塞尔曲线插值
在转弯处插入控制点,生成平滑曲线。我常用的做法是每三个路径点生成一段二次贝塞尔曲线。
实战技巧
我曾经在AGV项目里遇到一个问题:路径平滑后,机器人反而撞到了障碍物。排查发现是平滑后的曲线穿过了障碍物边缘。解决方案是:平滑后做一次碰撞检测,如果碰撞就回退到原始路径。
优化方法三:代价地图膨胀
在规划前,把障碍物膨胀一圈。这样规划出来的路径天然就离障碍物远,平滑后也不容易碰撞。
避坑指南
我曾经把膨胀半径设得太大,结果机器人过不了门。后来学乖了:膨胀半径 = 机器人半径 + 安全余量(0.1~0.2m)。别贪心,安全余量太大反而走不了窄路。
四、知识体系总览
下面这张图是我自己整理的全局路径规划调参思路,你可以照着这个流程来排查问题。
说白了,全局路径规划调参就三步:选算法、调参数、做平滑。每一步都有坑,但踩过一次就记住了。我刚开始做的时候,光调cost_factor就花了两天,后来发现是地图分辨率设错了——你说冤不冤?
最后分享一个经验:调参时别一次改太多。每次只改一个参数,记录下效果。这样出了问题也知道回退到哪。我见过有人一口气改了五个参数,结果路径乱成一锅粥,最后只能重装系统——别学他。
可可精品资料库