amcl_demo之地图服务器——map_server
在amcl_demo的launch文件中,通过如下的形式开启了map_server。 首先根据系统环境变量"TURTLEBOT_GAZEBO_MAP_FILE"指定地图文件。然后开启ROS节点map_server提供地图服务。
<arg name="map_file" default="$(env TURTLEBOT_GAZEBO_MAP_FILE)"/>
<node name="map_server" pkg="map_server" type="map_server" args="$(arg map_file)" />
我们也可以通过如下指令完成相同的操作。首先需要保证roscore存在,如果不存在,我们可以通过下面的第一行语句将之打开。该语句最后的'&'是类Unix系统的一个特性,可以通过后台的形式运行roscore。
然后,通过rosrun工具加载map_server节点。该指令通过`echo $TURTLEBOT_GAZEBO_MAP_FILE`
获取环境变量,即map_server的地图文件。
$ roscore &
$ rosrun map_server map_server `echo $TURTLEBOT_GAZEBO_MAP_FILE`
地图服务器通过服务的形式提供地图数据,它是amcl_demo的导航系统运行的基本数据之一。 本文先介绍地图文件的格式,再介绍map_server的功能和使用方法,源码分析不是本文所要讨论的内容。
1. 地图文件格式
通过如下指令我们可以找到demo所用的地图文件,它是turtlebot_gazebo包的目录maps下的一个yaml文件。yaml是一种描述语言,类似于xml,html,只是格式相对简单很多。
$ echo $TURTLEBOT_GAZEBO_MAP_FILE
/home/xxx/catkin_ws/src/turtlebot_simulator/turtlebot_gazebo/maps/playground.yaml
我们查看一下存放地图文件的目录,里面一共有两个文件。这两个文件一起描述了地图数据,其中playground.yaml描述了地图的基本信息(metadata),playground.pgm则是一个图片,如下面右图所示, 它描述了地图中实际的占用信息。
$ roscd turtlebot_gazebo/maps/
$ ls
playground.pgm playground.yaml
下面是文件playground.yaml的内容。
free_thresh: 0.196
image: playground.pgm
negate: 0
occupied_thresh: 0.65
origin: [-6.8999999999999915, -5.8999999999999915, 0.0]
resolution: 0.05
其中字段image指示了实际的地图图片,这里是playground.pgm。我们也完全可以使用"*.png, *.jpg"的图片当作地图。一般都是用灰度图的,彩色图片也可以的,map_server会将之转换为灰度图后再进行处理。 图片中像素越接近于白色,对应的删格是空闲的可能性就越大。相应的,像素越深越可能被占用。在ymal文件中字段free_thresh和occupied_thresh是两个阈值,用于判定对应删格是否空闲。 两个阈值之间的范围被认为是未知的环境,不确定是否被占用了。
字段negate标志着是否反转图像灰度对应占用概率的逻辑。而origin以\((x, y, yaw)\)的形式描述了图像中左下角的像素在地图中的位置和方向角,\(yaw = 0\)表示地图没有转动。 resolution描述了地图的分辨率,单位为米每像素(meters / pixel)。
2. map_server
我们以文初的终端指令的形式运行map_server,可以使用工具rosnode来查看运行节点的信息。通过$ rosnode list
我们可以获取当前ROS系统中运行的节点。
其中'/map_server_"后面跟着一串数字的节点正是我们的研究对象,'/rosout'则是伴随着roscore一起运行的节点。
$ rosnode list
/map_server_1560416807248702808
/rosout
我们通过指令$ rosnode info
获取了地图服务器节点的运行信息。从输出结果来看,该节点没有订阅任何主题,发布了'/map','/map_metadata'和'/rosout'三个主题。
其中'/rosout'与系统的日志相关,主要用于打印调试信息。'/map'和'/map_metadata'是两个latched topic。这种latched topic发布了最后一条消息后,ros会将之保存下来,每当右新的订阅者出现时,
就会自动的发送最后信息到该订阅器。我们可以通过订阅'/map'或者'/map_metadata'来获取地图信息。
$ rosnode info /map_server_1560416807248702808
--------------------------------------------------------------------------------
Node [/map_server_1560416807248702808]
Publications:
* /map [nav_msgs/OccupancyGrid]
* /map_metadata [nav_msgs/MapMetaData]
* /rosout [rosgraph_msgs/Log]
Subscriptions: None
下面是指令$ rosnode info
输出信息的一部分。我们除了订阅'/map'来获取地图信息之外,还可以通过服务'/static_map'获取地图信息。
个人认为,地图服务器还应该提供一个set_map的服务用于更新地图信息。
Services:
* /map_server_1560416807248702808/get_loggers
* /map_server_1560416807248702808/set_logger_level
* /static_map
3. 完
map_server在acml_demo中扮演了地图数据提供者的角色。它发布了'/map'和'/map_metadata'两个latched主题,我们可以通过订阅这两个主题来获取地图信息。 此外,还可以通过服务'/static_map'获取地图信息。