第3章 地图服务:地图格式解析、map_server配置、静态地图加载

地图,是机器人导航的「底图」。没有地图,定位和规划都无从谈起。这一章我带你彻底搞懂 Nav2 里的地图服务——从文件格式到服务器配置,再到怎么把一张静态地图稳稳地加载进系统。嗯,这里面的坑不少,我当年刚接触时也栽过跟头。

地图格式解析 PGM / YAML / PNG map_server 配置 参数 · 启动文件 静态地图加载 话题 · 生命周期 地图服务核心流程 YAML 描述文件 → map_server 解析 → 发布 /map 话题 代价地图订阅 → 全局/局部规划器使用

3.1 地图格式解析——PGM、YAML、PNG 到底怎么用?

ROS 里最经典的地图格式是 PGM + YAML 组合。PGM 存像素灰度值,YAML 写元数据。后来大家也常用 PNG,因为文件更小。我个人习惯用 PNG,但很多老项目还是 PGM。

一张地图的 YAML 文件长这样:

image: my_map.png
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 / free_thresh:灰度值判定阈值。大于 occupied 算障碍,小于 free 算自由空间。
  • negate:是否反转灰度。0 表示白墙黑障碍,1 则相反。
💡 我的经验: 如果你用 SLAM 工具生成地图,记得检查 origin 值。有一次我加载地图后机器人一直偏位,折腾半天发现是 origin 写错了符号。负号丢了,整个地图偏移了 10 米。

3.2 map_server 配置——启动文件怎么写才稳?

map_server 是 Nav2 里的一个生命周期节点。说白了,它负责把地图文件读进来,然后以 /map 话题发布出去。配置它其实就两步:写一个 YAML 描述文件,再写一个启动文件。

下面是一个典型的启动文件片段:

<node pkg="nav2_map_server" exec="map_server" name="map_server">
    <param name="yaml_filename" value="$(find-pkg-share my_robot)/maps/my_map.yaml"/>
    <param name="topic_name" value="map"/>
    <param name="frame_id" value="map"/>
</node>

几个关键参数:

  • yaml_filename:指向你的 YAML 文件。路径写错是最常见的启动失败原因。
  • topic_name:默认是 map。如果你有多个地图,可以改成别的名字。
  • frame_id:地图的坐标系,通常是 map。
⚠️ 注意: map_server 是生命周期节点,启动后需要先配置再激活。如果你用 ros2 launch,它会自动处理。但如果你手动运行节点,记得调用生命周期服务来激活它。我曾经在调试时忘了这一步,等了五分钟地图都没出来……

3.3 静态地图加载——从文件到话题的完整链路

地图加载的流程其实很直白:map_server 读取 YAML → 解析图片 → 生成 OccupancyGrid 消息 → 发布到 /map 话题。代价地图节点订阅这个话题,然后构建自己的障碍物层。

你可以用命令行验证地图是否加载成功:

ros2 topic echo /map --once

如果看到一大串 data 数组,说明地图已经进来了。如果没反应,检查 map_server 节点的状态:

ros2 lifecycle list /map_server

正常应该显示 active。如果是 unconfigured 或 inactive,手动激活一下:

ros2 lifecycle set /map_server configure
ros2 lifecycle set /map_server activate
🔧 避坑指南: 我曾经遇到一个诡异问题——地图加载了,但导航时机器人总往墙上撞。后来发现是地图的 occupied_thresh 设得太低,导致部分可通行区域被判定为障碍。建议你在调参时先用 rviz2 可视化一下地图,看看障碍物边界是否合理。

3.4 地图参数速查表

参数默认值说明
yaml_filename—地图 YAML 文件路径(必填)
topic_namemap发布的地图话题名
frame_idmap地图坐标系
resolution0.05地图分辨率(米/像素)
occupied_thresh0.65障碍物判定阈值
free_thresh0.196自由空间判定阈值

嗯,地图服务这部分内容不算多,但它是整个导航系统的地基。地基没打好,后面规划、避障全是空中楼阁。