https://download.csdn.net/download/qq_45685327/87721374
上一节我们已经实现通过gmapping的构建地图并在rviz中显示了地图,不过,上一节中地图数据是保存在内存中的,当节点关闭时,数据也会被一并释放,我们需要将栅格地图序列化到的磁盘以持久化存储,后期还要通过反序列化读取磁盘的地图数据再执行后续操作。在ROS中,地图数据的序列化与反序列化可以通过 map_server 功能包实现。
1.map_server简介
map_server功能包中提供了两个节点: map_saver 和 map_server,前者用于将栅格地图保存到磁盘,后者读取磁盘的栅格地图并以服务的方式提供出去。
map_server安装前面也有介绍,命令如下:
sudo apt install ros-<ROS版本>-map-server
2.map_server使用之地图保存节点(map_saver)
2.1map_saver节点说明
订阅的topic:
map(nav_msgs/OccupancyGrid)
- 订阅此话题用于生成地图文件。
2.2地图保存launch文件
地图保存的语法比较简单,编写一个launch文件,内容如下:
nav02_map_save.launch
<launch>
<arg name="filename" value="$(find mycar_nav)/map/nav" />
<node name="map_save" pkg="map_server" type="map_saver" args="-f $(arg filename)" />
</launch>
其中 mymap 是指地图的保存路径以及保存的文件名称。
SLAM建图完毕后,执行该launch文件即可。
source ./devel/setup.bash
roslaunch nav_demo nav02_map_save.launch
2.3保存结果解释2.3
xxx.pgm 本质是一张图片,直接使用图片查看程序即可打开。
xxx.yaml 保存的是地图的元数据信息,用于描述图片,内容格式如下:
#声明地图图片资源的路径
image: /home/xiaoming/demo2/src/nav_demo/map/nav.pgm
# 地图刻度尺单位是 米每像素
resolution: 0.050000
# 地图位姿(相对于rviz中的原点的位姿)
origin: [-50.000000, -50.000000, 0.000000]
# 占用阈值
negate: 0
# 空闲阈值
occupied_thresh: 0.65
# 取反
free_thresh: 0.196
解释:
-
image:被描述的图片资源路径,可以是绝对路径也可以是相对路径。
-
resolution: 图片分片率(单位: m/像素)。
-
origin: 地图中左下像素的二维姿势,为(x,y,偏航),偏航为逆时针旋转(偏航= 0表示无旋转)。
-
occupied_thresh: 占用概率大于此阈值的像素被视为完全占用。
-
free_thresh: 占用率小于此阈值的像素被视为完全空闲。
-
negate: 是否应该颠倒白色/黑色自由/占用的语义。
map_server 中障碍物计算规则:
- 地图中的每一个像素取值在 [0,255] 之间,白色为 255,黑色为 0,该值设为 x;
- map_server 会将像素值作为判断是否是障碍物的依据,首先计算比例: p = (255 - x) / 255.0,白色为0,黑色为1(negate为true,则p = x / 255.0);
- 根据步骤2计算的比例判断是否是障碍物,如果 p > occupied_thresh 那么视为障碍物,如果 p < free_thresh 那么视为无物。
备注:
- 图片也可以根据需求编辑。
3.map_server使用之地图服务(map_server)
3.1map_server节点说明
发布的话题
map_metadata(nav_msgs / MapMetaData)
- 发布地图元数据。
map(nav_msgs / OccupancyGrid)
- 地图数据。
服务
static_map(nav_msgs / GetMap)
- 通过此服务获取地图。
参数
〜frame_id(字符串,默认值:“map”)
- 地图坐标系。
3.2地图读取
通过 map_server 的 map_server 节点可以读取栅格地图数据,编写 launch 文件如下:
nav03_map_server.launch
<launch>
<!-- 设置地图的配置文件 -->
<arg name="map" default="nav.yaml" />
<!-- 运行地图服务器,并且加载设置的地图-->
<node name="map_server" pkg="map_server" type="map_server" args="$(find mycar_nav)/map/$(arg map)"/>
</launch>
其中参数是地图描述文件的资源路径,执行该launch文件,该节点会发布话题:map(nav_msgs/OccupancyGrid)
3.3地图显示
首先运行刚刚编写的launch文件,发布地图文件的话题
roslaunch nav_demo nav03_map_server.launch
在 rviz 中使用 map 组件可以显示栅格地图:
经过尝试,发现没有/map话题,找到的方案是关闭一下roscore,再启动,然后在启动launch文件
roscore
roslaunch nav_demo nav03_map_server.launch
rostopic list
rviz
打开rviz,添加map组件
订阅/map话题
另请参考:
- map_server - ROS Wiki