3. 全局路径规划参数:A*算法参数解析、Dijkstra参数对比、全局代价地图参数设置
各位同学,咱们今天聊点硬核的——全局路径规划。说白了,就是让机器人在出发前,先在地图上画出一条从A到B的“大路”。我这些年调过的机器人,十有八九的问题都出在这一步。你想想看,全局路径都没规划好,后面的局部避障再牛,那也是白搭。
这一节,我带你手撕三个核心模块:A*算法、Dijkstra算法,还有全局代价地图。嗯,咱们一个一个来。
3.1 A*算法参数解析
A*算法,说白了就是“带方向的Dijkstra”。它比Dijkstra聪明的地方在于,它知道自己要去哪,所以不会像个无头苍蝇一样到处乱撞。
我个人习惯把A*的核心参数分成三组:启发式函数、搜索策略、路径平滑。
3.1.1 启发式函数(Heuristic Function)
这是A*的灵魂。启发式函数决定了“估算距离”的准确度。我见过很多新手直接拿欧几里得距离当启发式,结果路径拐来拐去,像喝醉了一样。
| 启发式类型 | 公式 | 适用场景 | 我踩过的坑 |
|---|---|---|---|
| 曼哈顿距离 | |dx| + |dy| | 四方向移动(如室内走廊) | 在斜向移动时路径会“锯齿状” |
| 欧几里得距离 | sqrt(dx² + dy²) | 八方向或自由移动 | 计算量大,且容易低估代价 |
| 切比雪夫距离 | max(|dx|, |dy|) | 八方向移动(如AGV) | 路径偏“直”,但可能撞角 |
| 对角线距离 | dx + dy + (√2 - 2) * min(dx, dy) | 八方向移动(推荐) | 我最常用,平衡了速度和精度 |
3.1.2 搜索策略参数
A*的搜索过程,说白了就是维护一个“待探索列表”。这里有几个关键参数,我一个个说。
- open_set大小限制:默认是无限大。但在大场景下,我建议设个上限(比如50000个节点)。否则内存爆了,你哭都来不及。
- 搜索步长(resolution):默认是地图分辨率。我个人习惯设成0.5米,太大路径会“跳”,太小计算量爆炸。
- 路径剪枝(path pruning):这个参数很多人忽略。开启后,算法会去掉路径上不必要的拐点。嗯,我建议默认开启。
3.1.3 路径平滑
A*出来的路径,往往是“折线”。直接让机器人走,它会一顿一顿的,像在跳机械舞。所以我们需要平滑。
ROS里常用的平滑方法有两种:
- 梯度下降平滑:迭代优化路径点,让它们更平滑。我一般迭代50次,再多就过拟合了。
- B样条曲线:用控制点生成平滑曲线。效果好,但计算量大。适合离线规划。
# 我常用的A*参数配置(yaml格式)
A_star:
heuristic_type: "diagonal" # 对角线距离
heuristic_weight: 1.1 # 稍微贪心一点
search_resolution: 0.5 # 米
open_set_limit: 50000 # 防止内存爆炸
smooth_iterations: 50 # 平滑迭代次数
path_pruning: true # 剪枝
3.2 Dijkstra参数对比
Dijkstra算法,说白了就是A*的“老大哥”。它没有启发式,所以会遍历所有可能的路径,直到找到最短的那条。优点是保证最优,缺点是慢。
我什么时候用Dijkstra?嗯,场景不大(比如10x10米以内),或者对路径最优性要求极高的时候。比如,机器人要穿过一个狭窄的通道,A*可能因为启发式“骗”自己走了弯路,但Dijkstra不会。
| 对比项 | A* | Dijkstra |
|---|---|---|
| 搜索效率 | 高(有方向) | 低(无方向) |
| 路径最优性 | 近似最优(取决于启发式) | 绝对最优 |
| 内存占用 | 低 | 高(需要存储所有节点) |
| 适用场景 | 大场景、实时规划 | 小场景、离线规划 |
| ROS默认实现 | navfn / global_planner | navfn(可切换) |
在ROS里,切换其实很简单。global_planner的use_dijkstra参数设为true,它就变成Dijkstra了。我建议你做个实验:同一个场景,分别跑A*和Dijkstra,看看路径差异。你会发现,Dijkstra的路径往往更“圆润”,因为它考虑了所有可能性。
3.3 全局代价地图参数设置
全局代价地图,说白了就是一张“打分表”。每个格子都有一个代价,机器人规划路径时,会尽量走代价低的格子。
代价地图的参数,我分成三类:膨胀层、静态层、障碍物层。
3.3.1 膨胀层(Inflation Layer)
这是最重要的层。它把障碍物“膨胀”一圈,让机器人离障碍物远一点。膨胀半径设多大?嗯,我一般设成机器人半径的1.5倍。太小了容易刮蹭,太大了路径绕远路。
# 膨胀层参数示例
inflation_layer:
inflation_radius: 0.55 # 米,机器人半径0.35m,乘1.5
cost_scaling_factor: 10.0 # 代价衰减速度,越大衰减越快
cost_scaling_factor这个参数,我吃过亏。有一次设成5.0,结果代价衰减太慢,机器人为了避开一个很小的障碍物,绕了半个地图。后来改成10.0,路径就正常了。你想想看,这个值越大,代价从障碍物边缘到膨胀半径边缘的“过渡”就越陡峭,机器人会更倾向于贴着障碍物走。
3.3.2 静态层(Static Layer)
静态层就是地图本身。参数不多,但有一个坑:map_topic。我见过有人把话题名写错,结果机器人一直用空地图规划路径,直接撞墙。
- map_topic:地图话题名,默认是"/map"。
- subscribe_to_updates:是否订阅地图更新。如果你用动态地图(比如SLAM实时建图),建议设为true。
- track_unknown_space:是否把未知区域当作障碍物。我建议设为false,否则机器人会“害怕”没去过的地方。
3.3.3 障碍物层(Obstacle Layer)
障碍物层负责处理传感器数据(激光雷达、深度相机等)。参数比较多,我挑几个关键的讲。
| 参数 | 说明 | 我的建议值 |
|---|---|---|
| observation_sources | 传感器列表,如"scan" | 按实际传感器名称写 |
| obstacle_range | 障碍物最大检测距离 | 2.5米(室内) |
| raytrace_range | 射线追踪范围(清除障碍物) | 3.0米(比obstacle_range大一点) |
| max_obstacle_height | 障碍物最大高度 | 2.0米(高于机器人高度) |
| min_obstacle_height | 障碍物最小高度 | 0.0米(地面杂物也算) |
obstacle_range设成5.0米,结果机器人把远处的墙也当成障碍物,导致全局路径绕了一大圈。后来改成2.5米,路径就合理了。记住,全局代价地图不需要看到太远,够用就行。
3.4 知识体系总览
说了这么多,我画了一张图帮你理清思路。全局路径规划的核心,就是“算法+地图”的组合。算法决定怎么找路,地图决定哪里能走。
嗯,这张图把咱们今天讲的内容串起来了。左边是算法,右边是地图。你调参的时候,要同时考虑这两边。比如,你把膨胀半径设大了,A*的搜索空间就变小了,路径可能更安全,但也可能绕远路。这就是个trade-off。
好了,这一节的内容就到这。记住,全局路径规划不是一蹴而就的,需要反复试错。你调参的时候,多看看Rviz里的路径变化,慢慢就有感觉了。