3、地图基础:地图类型、生成与加载
做导航,地图就是机器人的「眼睛」。没有地图,机器人就是个瞎子。
我刚开始接触 Nav2 时,对地图的理解也很浅。觉得不就是一张图片嘛,机器人能看懂就行。后来踩了不少坑才明白——地图的类型、格式、加载方式,每一个细节都直接影响导航效果。
今天咱们就把地图这块彻底聊透。
3.1 地图类型:Occupancy Grid 与 Costmap
ROS2 导航里,地图主要分两种:Occupancy Grid(占用栅格地图)和 Costmap(代价地图)。很多人容易搞混,其实它们分工完全不同。
3.1.1 Occupancy Grid——原始地图
Occupancy Grid 是 SLAM 建图后保存下来的原始地图。它用栅格(grid)表示环境,每个格子存一个值:
- 0:空闲(可通行)
- 100:占用(障碍物)
- -1:未知(没探测到)
说白了,它就是一张黑白灰的图片。白色是路,黑色是墙,灰色是未知区域。
3.1.2 Costmap——导航用的「热力图」
Costmap 是在 Occupancy Grid 基础上生成的。它给每个格子加了一个「代价」值,范围 0~255。
- 0:完全安全
- 1~50:有轻微风险
- 50~100:接近障碍物
- 100~253:很危险
- 254:致命障碍(机器人中心不能进入)
- 255:未知区域
为什么要搞这么复杂?你想想看,机器人是有体积的。如果只靠原始地图,它可能贴着墙走,结果把自己卡住。Costmap 通过「膨胀」操作,把障碍物周围一圈也标记为危险区域,这样机器人就会自动保持安全距离。
3.2 地图生成:SLAM 与已知地图
地图怎么来的?两种方式:自己建(SLAM),或者用现成的(已知地图)。
3.2.1 SLAM 建图——从零开始
SLAM(Simultaneous Localization and Mapping)就是让机器人在未知环境中一边走路一边画地图。ROS2 里常用的 SLAM 工具有:
- slam_toolbox:最推荐,功能全,支持重定位和地图保存
- Cartographer:Google 出品,精度高,但配置复杂
- Hector SLAM:不需要里程计,适合无人机或履带车
我个人习惯用 slam_toolbox。启动命令很简单:
ros2 launch slam_toolbox online_async_launch.py
建图完成后,用这个命令保存地图:
ros2 run nav2_map_server map_saver_cli -f my_map
它会生成两个文件:my_map.pgm(图片)和 my_map.yaml(配置文件)。
3.2.2 已知地图——拿来就用
如果你已经有地图(比如 CAD 图纸、之前建好的地图),可以直接加载。Nav2 支持两种格式:
- PGM/PNG 图片 + YAML 配置:最常见
- YAML 直接定义:适合程序生成的地图
加载已知地图的命令:
ros2 run nav2_map_server map_server --ros-args -p yaml_filename:=my_map.yaml
嗯,这里要注意:YAML 文件里的 resolution(分辨率)和 origin(原点)必须和实际环境一致。否则机器人会「迷路」。
3.3 地图格式与加载
地图文件到底长什么样?咱们拆开看看。
3.3.1 YAML 配置文件
一个标准的 my_map.yaml 内容如下:
image: my_map.pgm
resolution: 0.05
origin: [-10.0, -10.0, 0.0]
occupied_thresh: 0.65
free_thresh: 0.196
negate: 0
| 参数 | 含义 | 我的建议 |
|---|---|---|
| image | 地图图片文件名 | 路径要写对,建议用路径 |
| resolution | 每个像素代表的实际距离(米) | 0.05 米(5cm)比较常用 |
| origin | 地图左下角在真实世界中的坐标 (x, y, yaw) | 建图时自动生成,别手动改 |
| occupied_thresh | 像素值超过此阈值视为障碍物 | 0.65 是默认值,够用 |
| free_thresh | 像素值低于此阈值视为空闲 | 0.196,别乱调 |
| negate | 是否反转黑白 | 一般设为 0 |
occupied_thresh 和 free_thresh。图片压缩可能导致像素值变化,地图就废了。
3.3.2 地图加载流程
Nav2 加载地图的完整流程,我画了张图帮你理解:
流程其实很简单:
- map_server 读取 .pgm 和 .yaml 文件
- 发布
/map话题(Occupancy Grid 格式) - Costmap 层订阅
/map,生成全局和局部代价地图 - 导航时,全局规划器用全局 Costmap,局部规划器用局部 Costmap
3.3.3 动态地图更新
实际场景中,环境会变化。比如仓库里堆了新货架,或者会议室桌椅被移动了。这时候怎么办?
Nav2 支持两种更新方式:
- 静态地图 + 传感器实时更新:激光雷达扫描到新障碍物,Costmap 自动更新。这是默认方式。
- 动态地图重载:调用
map_server的服务,重新加载地图文件。
我建议用第一种。毕竟机器人自己「看」到的障碍物,比地图文件更实时。
3.4 本章小结
地图是导航的基石。Occupancy Grid 是原始数据,Costmap 是加了「安全距离」的增强版。建图用 slam_toolbox,加载用 map_server。记住:地图的分辨率、原点、阈值,任何一个参数错了,导航都会出问题。
我见过太多人卡在地图加载这一步。其实只要把 YAML 文件里的参数理解透,问题就解决了一大半。