第2章:Costmap2D基础:全局代价地图与局部代价地图

大家好,我是你们的导航调参讲师。今天咱们聊聊代价地图——这玩意儿可以说是Nav2的「眼睛」和「皮肤」。没有它,机器人就是个睁眼瞎,到处乱撞。

我记得刚入行那会儿,总觉得代价地图就是个简单的黑白栅格图。直到有一次,机器人在走廊里莫名其妙地绕远路,我才意识到——嗯,这里面的门道深着呢。

2.1 什么是代价地图?

说白了,代价地图就是一张二维网格图。每个格子(我们叫它cell)都存着一个数值,代表这个位置「好不好走」。

  • 0:自由空间,随便走
  • 100:障碍物,别碰
  • 0~100之间:越靠近障碍物,数值越高

你想想看,如果只有0和100两种值,那机器人就像在走迷宫——要么能走,要么不能走。但现实世界哪有这么简单?

核心概念:代价地图的价值就在于「渐变」。它告诉机器人:离墙远一点,但别太远,不然过不了门。

2.2 全局 vs 局部:两套地图各司其职

Nav2里有两套代价地图,很多人一开始搞混。我简单解释一下:

对比项 全局代价地图 局部代价地图
范围 整个已知地图 机器人周围一小块
更新频率 低(几秒一次) 高(几十毫秒一次)
用途 规划长距离路径 实时避障、局部路径调整
分辨率 可低一些(省内存) 通常较高(精细避障)

我个人的习惯是:全局地图分辨率设0.05米,局部设0.025米。这样全局规划快,局部避障精细。

小技巧:如果你发现机器人规划路径时卡顿,先检查全局代价地图的分辨率——别设得太高,0.05米对大多数场景足够了。

2.3 膨胀层与障碍物层

代价地图由多个「层」叠加而成。最常用的两层是:

障碍物层(Obstacle Layer)

这层负责把传感器数据(激光雷达、深度相机等)转成障碍物标记。说白了,就是「看到啥就标啥」。

我曾经遇到过一个坑:激光雷达安装角度偏了5度,结果障碍物层一直把地面当成墙。机器人原地转圈,死活不走。后来一查,是传感器帧和基座标系没对齐。

膨胀层(Inflation Layer)

这层才是避障的精髓。它把障碍物周围的格子也标上代价,让机器人「不敢靠近」。

膨胀层有两个关键参数:

  • inflation_radius:膨胀半径。机器人中心到障碍物的最小距离。
  • cost_scaling_factor:代价衰减速度。值越大,代价下降越快。

注意:inflation_radius设太大,机器人过不了窄门;设太小,容易蹭墙。我一般从机器人宽度的一半开始调,比如机器人宽0.5米,就先设0.25米。

2.4 代价地图的更新机制

代价地图不是静态的——它一直在变。更新机制分三步:

  1. 传感器数据输入:激光雷达扫描一圈,得到障碍物点云
  2. 标记与清除:新扫描到的障碍物标记上,之前扫到但这次没扫到的清除掉
  3. 膨胀计算:对标记的障碍物做膨胀,生成渐变代价

这里有个关键点:清除机制。如果机器人看到障碍物移走了(比如行人走开),代价地图必须及时清除旧标记。否则机器人会一直绕着「幽灵障碍物」走。

避坑指南:我曾经把 obstacle_range 设得太小(0.5米),结果机器人只看到眼前半米内的障碍物,远处的墙完全无视。路径规划出来直接穿墙——嗯,那场面挺尴尬的。

2.5 知识体系总览

下面这张图帮你理清本章的核心逻辑:

代价地图知识体系 代价地图 全局代价地图 局部代价地图 障碍物层 + 膨胀层 + 静态层 障碍物层 + 膨胀层 传感器输入 → 标记/清除 → 膨胀计算 → 代价更新 关键参数:inflation_radius | cost_scaling_factor | obstacle_range 分辨率 | 更新频率 | 传感器帧对齐

2.6 实战建议

最后,给你几个我踩过坑后总结的建议:

  • 先调障碍物层,再调膨胀层:如果障碍物都检测不准,膨胀层再完美也没用
  • 用rviz2可视化调试:打开代价地图显示,一眼就能看出问题——比如障碍物偏移、膨胀太大
  • 注意坐标系:传感器帧、基座标系、地图帧必须对齐。我见过太多人栽在这上面

一句话总结:代价地图就是机器人的「安全距离感」。调好了,它走位风骚;调不好,它要么撞墙,要么绕远路。