3. 全局路径规划器:从NavFn到Theta*的实战选择
全局路径规划,说白了就是让机器人知道「大方向怎么走」。你给它一张地图、一个起点、一个终点,它得算出一条能走的路。Nav2里默认带了好几个规划器,但很多人装完就跑默认参数,结果机器人要么贴墙走、要么绕远路、要么直接卡死。今天我就把NavFn、A*、Theta*这几个东西掰开揉碎讲清楚。
3.1 NavFn规划器:老将出马,一个顶俩?
NavFn是Nav2里最老的全局规划器,也是默认配置之一。它的核心思路是「波前传播」——从目标点开始,像水波一样往外扩散,每个格子记录到目标的距离。然后机器人沿着梯度下降的方向走,就能到终点。
听起来挺简单对吧?但我在项目里见过不少人踩坑。有一次,一个朋友在仓库里跑AGV,地图稍微大一点(50m×30m),NavFn直接卡了十几秒才出路径。为什么?因为波前传播要遍历整个地图,地图越大,计算量呈平方级增长。
NavFn的配置参数不多,核心就这几个:
| 参数 | 默认值 | 说明 | 我的经验 |
|---|---|---|---|
allow_unknown |
true | 是否允许通过未知区域 | 室内建议false,室外可以true |
use_final_approach_orientation |
false | 终点是否调整朝向 | 建议true,否则机器人到终点会原地转圈 |
planner_window_x |
0.0 | 规划窗口X方向大小(0=全图) | 大地图建议设5-10米,减少计算量 |
planner_window_y |
0.0 | 规划窗口Y方向大小 | 同上 |
planner_window_x/y,机器人只能在窗口内规划路径。如果目标点在窗口外,规划会失败。我曾经因为这个排查了半天,最后发现是窗口设小了。
3.2 A*算法:核心参数调优,别只会改heuristic
A*是全局规划里的「万金油」。它用启发函数(heuristic)引导搜索方向,比NavFn聪明得多——不用遍历全图,只往目标方向搜。但很多人调A*只知道改heuristic_scale,其实还有几个关键参数。
先看A*的配置:
# A*规划器配置示例
planner_plugin: "nav2_navfn_planner/NavfnPlanner" # 注意:Nav2里A*也走Navfn插件
use_astar: true # 启用A*算法
allow_unknown: false
use_final_approach_orientation: true
# 核心调优参数
heuristic_scale: 1.0 # 启发函数权重,越大越贪心
tolerance: 0.25 # 终点容差(米)
max_iterations: 100000 # 最大迭代次数
这几个参数怎么调?我一个个说:
heuristic_scale:启发函数的权重。默认1.0是标准A*,保证最优解。如果你想要更快(可以接受次优),可以调到1.2-1.5。但别超过2.0,否则路径会变得很奇怪——我见过有人设3.0,结果机器人直接穿墙走了。tolerance:终点容差。如果你的终点在障碍物上(比如导航目标点刚好落在墙上),A*会找不到路径。设一个0.25-0.5米的容差,它会在附近找可到达的点。这个参数在动态环境中特别有用。max_iterations:最大迭代次数。地图越大、障碍物越多,迭代次数需求越大。默认10万次对于50m×50m的地图够用,但如果你的地图有100m×100m,建议调到50万次以上。
heuristic_scale降到0.8,路径就出来了。为什么?因为启发式权重太高会让搜索太「贪心」,忽略了狭窄通道的细节。
3.3 A* vs Theta*:到底差在哪?
很多人搞不清A*和Theta*的区别。我直接说人话:A*只能走「网格方向」(上下左右+对角线),所以路径全是锯齿状的折线。Theta*在A*的基础上加了「视线检查」(line-of-sight check),只要两点之间没有障碍物,它可以直接拉直线。
看个对比:
| 特性 | A* | Theta* |
|---|---|---|
| 路径形状 | 锯齿状折线 | 任意角度直线 |
| 计算速度 | 快 | 慢(多了视线检查) |
| 路径长度 | 次优(网格限制) | 更优(任意角度) |
| 适用场景 | 开阔环境、实时性要求高 | 狭窄通道、需要平滑路径 |
| Nav2支持 | 原生支持(Navfn插件) | 需安装第三方插件 |
你想想看,如果你的机器人要在仓库里走「S」形弯道,A*出来的路径全是90度折角,机器人每到一个折角就得停下来原地转弯,效率极低。Theta*可以直接切斜线过去,路径平滑很多。
3.4 规划器插件选择与配置:别装了就完事
Nav2的规划器是通过插件机制加载的。你可以在启动时指定用哪个,也可以在运行时动态切换。配置方式有两种:
方式一:通过参数文件配置
# planner_params.yaml
planner_server:
ros__parameters:
planner_plugins: ["GridBased"]
GridBased:
plugin: "nav2_navfn_planner/NavfnPlanner"
use_astar: true
tolerance: 0.25
allow_unknown: false
use_final_approach_orientation: true
方式二:通过launch文件配置
# planner_server.launch.py
from launch import LaunchDescription
from launch_ros.actions import Node
def generate_launch_description():
return LaunchDescription([
Node(
package='nav2_planner',
executable='planner_server',
name='planner_server',
output='screen',
parameters=[{
'planner_plugins': ['GridBased'],
'GridBased.plugin': 'nav2_navfn_planner/NavfnPlanner',
'GridBased.use_astar': True,
'GridBased.tolerance': 0.25,
}]
)
])
如果你要装Theta*插件,需要额外安装:
sudo apt install ros-humble-nav2-theta-star-planner
然后配置:
planner_server:
ros__parameters:
planner_plugins: ["ThetaStar"]
ThetaStar:
plugin: "nav2_theta_star_planner/ThetaStarPlanner"
heuristic_scale: 1.0
line_of_sight_step: 1.0 # 视线检查步长(米)
max_iterations: 100000
line_of_sight_step参数很关键。步长越小,视线检查越精确,但计算越慢。默认1.0米对于大多数场景够用。如果你的地图有大量细长障碍物(比如桌腿),建议调到0.5米。
3.5 实战选型建议
说了这么多,到底怎么选?我根据项目经验给个参考:
- 室内扫地机/服务机器人:NavFn就够了,地图小、路径简单,没必要上复杂的。
- 仓储AGV/工厂物流:用A*,地图中等、需要实时响应,A*的效率和最优性平衡最好。
- 狭窄通道/密集障碍物:用Theta*,虽然慢一点,但路径质量高,机器人不会卡死。
- 阿克曼转向车辆:必须Theta* + 后续路径平滑,否则转弯半径问题会让你崩溃。
嗯,最后说一句:不管你选哪个规划器,一定要在实际地图上跑一遍。仿真里看着完美的路径,到了真实环境可能全是坑。我吃过这个亏,所以现在每换一个规划器,第一件事就是拿真实数据测一遍。