
上篇讲了代价地图的原理分层结构、膨胀机制、滚动窗口都过了一遍。但光懂原理不够面试经常追问你项目里代价地图参数怎么设的膨胀权重调过吗传感器配置怎么写的参数调优这件事教科书上不怎么讲但实际项目中花的时间可能比写算法还多。同一套Nav2参数设得好导航丝滑设不好机器人到处撞墙。这篇把代价地图的核心配置拆开来讲每个参数的物理意义、调优方向、常见坑点都说清楚。一、obstacle_layer配置详解obstacle_layer负责把传感器数据转成障碍物标记。配置的核心是observation_sources——定义有哪些传感器数据源每个数据源怎么处理。obstacle_layer: plugin: nav2_costmap_2d::ObstacleLayer enabled: true combination_method: 1 observation_sources: lidar depth_cam lidar: topic: /scan data_type: LaserScan max_obstacle_height: 2.0 min_obstacle_height: 0.1 marking: true clearing: true obstacle_range: 3.0 raytrace_range: 3.5 depth_cam: topic: /camera/depth/points data_type: PointCloud2 max_obstacle_height: 1.5 min_obstacle_height: 0.05 marking: true clearing: true obstacle_range: 2.5 raytrace_range: 3.0几个关键参数marking——这个传感器数据是否用来标记障碍物。一般所有传感器都设成true。clearing——是否用来清除障碍物。传感器射线没打到的区域会被清除。如果某个传感器只设marking不设clearing它只能添加障碍不能移除障碍时间一长代价地图上全是鬼影。obstacle_range——最远标记距离。超过这个距离的障碍物不标记。设太小会漏检远处的障碍设太大噪声点也会被标记进来。raytrace_range——射线追踪距离。在这个范围内传感器射线穿过的格子会被清除标记为自由空间。通常比obstacle_range稍大一点。combination_method——多图层叠加方式。1表示取最大值0表示直接相加。一般用1就行。二、inflation_layer调优膨胀层是导航效果的关键。参数设不好机器人要么贴墙走要么绕大弯。inflation_layer: plugin: nav2_costmap_2d::InflationLayer enabled: true inflation_radius: 0.55 cost_scaling_factor: 10.0 inflate_unknown: falseinflation_radius——膨胀的最大距离。从障碍物表面向外扩展这么多米。这个值至少要大于机器人的circumscribed_radius外接圆半径通常设为半径的1.5-2倍。cost_scaling_factor——代价衰减速度。值越大衰减越快离障碍物稍远的地方代价值就降到很低了。值越小衰减越慢机器人会尽量远离障碍物。# 不同cost_scaling_factor的效果对比 import numpy as np distances np.linspace(0.25, 0.55, 50) # 内接圆到膨胀半径 for csf in [5.0, 10.0, 20.0]: costs 253 * np.exp(-csf * (distances - 0.25)) 1 # csf5: 衰减慢远距离仍有较高代价 # csf20: 衰减快只有紧贴障碍物才有高代价调参经验仓储AGV通道窄inflation_radius设小一点0.3-0.4cost_scaling_factor设大一点15-20让机器人敢走窄路。服务机器人环境开阔inflation_radius设大一点0.5-0.7cost_scaling_factor设小一点5-10让机器人离障碍物远一点走。三、static_layer和map配置static_layer加载SLAM生成的地图文件PGM/YAML格式。配置比较简单static_layer: plugin: nav2_costmap_2d::StaticLayer map_subscribe_transient_local: true enabled: true subscribe_to_updates: false关键是地图文件本身的参数要匹配# map.yaml image: map.pgm resolution: 0.05 origin: [-10.0, -10.0, 0.0] negate: 0 occupied_thresh: 0.65 free_thresh: 0.196resolution必须和代价地图的resolution一致。如果不一致地图和传感器数据对不上导航会出问题。occupied_thresh和free_thresh决定了什么灰度值算障碍物、什么算自由空间。默认值通常够用但如果你的地图质量不好太模糊或者对比度低可能需要调整。四、全局vs局部代价地图的参数差异Nav2有两套代价地图global_costmap和local_costmap。它们的参数策略不一样。global_costmap: global_frame: map robot_base_frame: base_link update_frequency: 1.0 publish_frequency: 1.0 width: 5 height: 5 rolling_window: true resolution: 0.05 local_costmap: global_frame: odom robot_base_frame: base_link update_frequency: 5.0 publish_frequency: 5.0 width: 3 height: 3 rolling_window: true resolution: 0.05global_costmap用map坐标系更新频率低1Hz覆盖范围大。它负责全局路径规划需要知道大范围的静态障碍分布。local_costmap用odom坐标系更新频率高5-10Hz覆盖范围小。它负责实时避障需要快速响应周围环境的动态变化。local_costmap用odom而不是map是因为odom坐标系下没有SLAM的修正跳变。代价地图跟着机器人平滑移动不会因为定位修正突然跳一下。五、面试高频追问Q代价地图的鬼影怎么解决A鬼影是动态障碍物移走后残留的标记。原因通常是clearing射线没覆盖到。检查obstacle_layer的clearing参数是否为trueraytrace_range是否足够大。也可以用ClearCostmap恢复行为强制清除。Qinflation_radius设小了会怎样A机器人会走离障碍物很近的路径甚至贴墙走。如果定位有误差或者控制有偏差容易撞上障碍物。Qcost_scaling_factor设大了会怎样A膨胀代价衰减很快离障碍物稍远的地方代价就接近0了。效果是机器人不太在意离障碍物的距离路径可能不够安全裕度。Q全局代价地图为什么用map坐标系A全局路径规划需要考虑整张地图的静态障碍必须在统一的地图坐标系下工作。如果用odom坐标系里程计漂移会导致地图和代价地图错位。Q多个传感器数据冲突怎么办Acombination_method1时取最大值。如果激光雷达说某个格子是障碍物深度相机说是自由的最终结果是障碍物。这是保守策略宁可多避障也不漏检。代价地图的参数调优没有标准答案得根据具体场景反复试。建议用rviz实时观察代价地图一边调参数一边看效果。下一篇我们进入全局规划器的选型对比。代价地图的配置和调优是导航项目里最花时间的环节之一。obstacle_layer的传感器配置、inflation_layer的衰减参数、全局和局部代价地图的差异化策略这些是面试中的高频考点。上一篇第267篇 代价地图原理下一篇我们来对比几种主流的全局规划器。如果这篇文章对你有帮助欢迎点赞支持一下你的鼓励是我持续更新的动力