3 · 第一个导航地图:使用SLAM Toolbox构建静态地图
说实话,很多新手一上来就急着调路径规划,却忽略了最基础的东西——地图。没有一张靠谱的静态地图,导航就像蒙着眼走路。我个人习惯先把地图建好、存好,再谈其他。这一章我们就用 SLAM Toolbox 把第一张地图做出来,顺便聊聊地图格式和保存的那些坑。
3.1 为什么选SLAM Toolbox?
ROS2里建图工具有好几个,但SLAM Toolbox是我用得最顺手的。它不像gmapping那样只做2D激光SLAM,也不像cartographer那样配置复杂。说白了,它就是为Nav2量身定做的——开箱即用,还支持生命周期节点。我在项目里换过三四种建图方案,最后都回到了它身上。
3.2 启动建图:一条命令就够了
假设你已经有了激光雷达数据(或者仿真环境),启动SLAM Toolbox只需要一个launch文件。我个人习惯把参数单独放一个yaml,这样调起来方便。
# slam_toolbox_launch.py (片段)
from launch import LaunchDescription
from launch_ros.actions import Node
def generate_launch_description():
return LaunchDescription([
Node(
package='slam_toolbox',
executable='async_slam_toolbox_node',
name='slam_toolbox',
output='screen',
parameters=['./slam_params.yaml']
)
])
然后运行:
ros2 launch your_package slam_toolbox_launch.py
嗯,就这么简单。你会看到终端里不断输出图优化信息,同时RViz2里逐渐出现地图轮廓。我记得第一次跑通的时候,看着地图一点点展开,还是挺有成就感的。
3.3 地图格式:占用栅格地图
建图过程中,SLAM Toolbox内部维护的是一张 占用栅格地图 (OccupancyGrid)。每个格子有三种状态:占用(100)、空闲(0)、未知(-1)。你想想看,这其实就是一张灰度图——黑色是障碍,白色是自由空间,灰色是未探索区域。
| 栅格值 | 含义 | 可视化颜色 |
|---|---|---|
| 0 | 空闲 (free) | 白色 |
| 100 | 占用 (occupied) | 黑色 |
| -1 | 未知 (unknown) | 灰色 |
为什么用这种格式?因为导航时代价地图需要快速查询某个位置是否可通行。栅格结构简单,计算快。我在实际部署时发现,地图分辨率一般设 0.05米/像素,太粗了导航不精细,太细了文件大且容易受噪声影响。
3.4 保存地图:map_saver_cli 与 map_saver_server
地图建好了,不保存等于白干。SLAM Toolbox 提供了两种保存方式:
- 命令行工具 map_saver_cli —— 适合手动保存
- 服务端 map_saver_server —— 适合自动化流程
我最常用的是命令行,简单直接:
ros2 run nav2_map_server map_saver_cli -f my_map
这条命令会生成两个文件:my_map.yaml 和 my_map.pgm(或 .png)。YAML文件里记录了地图的元信息,比如分辨率、原点、占用阈值等。pgm就是那张灰度图。
3.5 YAML 参数详解
打开生成的 my_map.yaml,内容大概长这样:
image: my_map.pgm
resolution: 0.050000
origin: [-10.0, -10.0, 0.000000]
negate: 0
occupied_thresh: 0.65
free_thresh: 0.196
| 参数 | 说明 | 建议值 |
|---|---|---|
| image | 地图图片文件名(相对路径) | 与yaml同目录 |
| resolution | 每个像素代表的实际距离(米) | 0.05 |
| origin | 地图左下角在世界坐标系中的位姿 (x, y, yaw) | 根据建图范围定 |
| negate | 是否反转黑白(0不反转,1反转) | 0 |
| occupied_thresh | 像素灰度值高于此阈值视为占用 | 0.65 |
| free_thresh | 像素灰度值低于此阈值视为空闲 | 0.196 |
这里有个小细节:occupied_thresh 和 free_thresh 之间的区域会被当作未知区域。如果你发现地图里出现大量灰色噪点,可以适当调高 free_thresh 或降低 occupied_thresh。我一般保持默认,除非传感器噪声特别大。
3.6 避坑指南:地图原点与对齐
很多新手保存地图后,加载到Nav2里发现机器人位置对不上。原因往往是 origin 设置不合理。SLAM Toolbox 建图时默认把地图原点设在机器人起始位置附近,但如果你手动修改了 origin,一定要保证和实际建图范围匹配。
另外,如果你在仿真中建图,记得把地图保存到 ~/map 这样的独立目录,别跟代码混在一起。我习惯在项目里建一个 maps/ 文件夹,所有地图都放里面,方便管理。
3.7 验证地图:加载到Nav2
地图保存好了,怎么确认它没问题?最简单的方法是用 map_server 加载看看:
ros2 run nav2_map_server map_server --ros-args -p yaml_filename:=my_map.yaml
然后在另一个终端启动 RViz2,添加 Map 显示,选择话题 /map。如果地图显示正常,而且栅格黑白分明,那就说明成功了。我每次都会做这个验证,避免后期导航时才发现地图损坏。