3. 代价地图参数与路径规划故障
Nav2 的路径规划并不是直接在静态地图上画线,而是在两张“代价地图”上做搜索:global_costmap 服务于全局规划器(如 NavFn、Smac Planner),决定从起点到目标点的宏观可通行走廊;local_costmap 服务于局部规划器与控制器(如 DWB、MPPI),决定机器人眼前几米内如何避障、贴边与通过窄口。两张地图共用一套代价地图插件体系,但分辨率、尺寸、更新频率和插件组合往往不同。参数配错时,典型表现不是“程序崩溃”,而是路径贴着墙走、规划失败报 “Failed to create plan”、机器人原地打转或频繁触发恢复行为。理解参数到路径可行性的因果链,是排障的核心。
分辨率:栅格粒度决定“能不能看见缝”
resolution 是每个栅格代表的实际边长(米/格)。全局地图常用 0.05 m,局部地图常用 0.05 m 或更细的 0.03 m。分辨率的影响体现在两个方向:过粗时,宽度小于 2~3 个栅格的通道会被膨胀层“吃掉”,规划器认为不可通行;过细时,栅格数量按面积平方增长,全局地图 40 m×40 m 在 0.05 m 下是 800×800=64 万格,降到 0.02 m 则变成 2000×2000=400 万格,规划搜索与代价更新开销显著上升,且传感器噪声更容易形成孤立致命格。
一个可操作的判断方法是:机器人外接圆直径 D、安全余量 m,则通道最小可通行宽度约为 D+2m;若该宽度除以 resolution 小于 3,就应怀疑分辨率或膨胀参数过激。例如差速机器人宽 0.6 m、要求两侧各留 0.1 m,则需 0.8 m 通道;0.05 m 分辨率下约 16 格,尚可;若误设为 0.2 m,则只有 4 格,膨胀后极易闭合。
膨胀层:inflation_radius 与 cost_scaling_factor 的耦合
膨胀层(inflation_layer)把障碍物的致命代价向外扩散,形成“软代价梯度”,让规划器倾向于走中间而不是贴墙。inflation_radius 决定软代价扩散的最大距离,cost_scaling_factor 决定代价随距离衰减的快慢:值越大衰减越快,梯度越陡,路径越容易贴近膨胀边界;值越小梯度越平缓,路径越居中但可能绕远。
常见故障是 inflation_radius 小于机器人内切圆半径,导致规划出的路径几何上穿过机器人无法通过的区域,表现为全局路径“看起来能走”,局部控制器却反复报碰撞或无法跟踪。经验起点是 inflation_radius ≥ 机器人外接圆半径 + 0.05~0.1 m。另一个隐蔽问题是全局与局部膨胀参数不一致:全局地图膨胀过大导致窄门被判死,局部地图膨胀过小又让机器人贴墙,二者叠加会出现“全局规划失败但局部明明能过”的矛盾现象。
障碍层与体素层:观测如何变成代价
obstacle_layer 基于激光/点云的 2D 投影标记障碍,关键参数包括 observation_sources、max_obstacle_height、raytrace_max_range/raytrace_min_range 与 marking/clearing。若 max_obstacle_height 设得过低,桌面、货架横梁等高于阈值的障碍不会被标记,路径会从下方“穿过”;设得过高,又把悬挂物、天花板结构误判为地面障碍,造成虚假封锁。
voxel_layer 用于三维点云,通过 z_resolution、z_voxels 构建体素柱,再按 origin_z、z_hit、z_max 等参数决定哪些体素投影为 2D 致命格。典型故障是 z_voxels × z_resolution 覆盖的高度范围不足:机器人前方斜坡或低矮台阶落在范围之外,局部地图看不到,直到碰撞才触发。另一个高频问题是清除(clearing)失效——raytrace_max_range 小于传感器实际量程,动态障碍离开后残留的致命格长期不消失,局部规划器持续绕行甚至卡死。
典型故障模式与排查路径
故障一:全局规划持续失败。日志出现 “Failed to create plan” 或 “Start/goal in collision”。先确认起点/终点是否落在致命格上(机器人自身足迹被静态层误标也会导致),再检查 inflation_radius 是否把唯一通道封死。可在 RViz 中订阅 /global_costmap/costmap,把颜色方案切到 costmap,观察窄口处是否整片变为 100 号致命色。
故障二:路径贴墙、控制器反复报碰撞。多为膨胀半径小于机器人外接圆,或 cost_scaling_factor 过大导致软代价梯度太陡。把 inflation_radius 提到外接圆半径以上,并适当降低 cost_scaling_factor(例如从 5.0 调到 3.0),路径会明显向通道中心靠拢。
故障三:动态障碍离开后仍绕行。检查 raytrace_max_range 是否覆盖传感器量程、clearing 是否开启、局部地图 update_frequency 是否过低。若残影只在局部地图出现,通常是清除射线未覆盖到该距离。
故障四:低矮台阶或悬空横梁处理异常。前者是 max_obstacle_height 或体素高度范围不足,后者是阈值过高把高处结构误判为地面障碍。需要结合机器人实际高度与场景几何重新标定 z_max、origin_z 与 max_obstacle_height。
一份可对照的参数核查表
| 参数 | 所在层 | 示例值 | 失配时的典型现象 |
|---|---|---|---|
| resolution | 两层 | 0.05 m | 过粗:窄道闭合;过细:CPU 升高、孤立致命格增多 |
| inflation_radius | 两层 | 0.45 m | 小于外接圆:路径穿模、控制器报碰撞 |
| cost_scaling_factor | 两层 | 3.0 | 过大:贴墙;过小:过度绕远 |
| max_obstacle_height | 障碍层 | 2.0 m | 过低:高处障碍漏标;过高:悬挂物误封 |
| raytrace_max_range | 障碍层 | 3.5 m | 小于量程:动态障碍残影不消失 |
| z_resolution × z_voxels | 体素层 | 0.05 × 16 | 覆盖高度不足:斜坡、台阶漏检 |
归根结底,代价地图参数不是孤立的数值,而是一条从“传感器观测”到“栅格代价”再到“搜索可行性”的链条。分辨率决定空间粒度,膨胀层决定安全边界与路径偏好,障碍层与体素层决定观测如何被信任和清除。排障时沿着这条链从全局到局部逐段核对,比盲目试参更可靠。