环境:Ubuntu18.04 + ROS melodic 

在驱动机器人动起来后,可以开始考虑让机器人在实际环境中自主导航了。自主导航需要SLAM技术,本文主要利用机器人的传感器数据构建高质量的地图,主要包含以下内容:

1、ROS中的地图

2、创建地图

3、利用rosbag记录数据

4、启动地图服务器以及查看地图

1、ROS中的地图

参考链接:http://wiki.ros.org/map_server#Map_format

map_server包中地图存储在一对文件中,一个YAML文件,一个image文件。YAML文件描述了地图元数据,并命名了图像文件, 图像文件对占用数据进行编码。

1.1  图像文件

图像文件以对应像素的颜色描述环境中每个单元格的占用状态。 在标准配置中,更白的像素是空闲的,被占用的空间具有更黑的像素,中间颜色的像素表示未知。 接受彩色图像,但颜色值会被平均为灰度值。通过SDL_Image读入图像数据,支持的格式会有所不同,具体取决于SDL_Image在特定平台上提供的内容。 一般而言,大多数流行的图像格式得到广泛支持。 一个值得注意的例外是OS X不支持PNG。

1.2 YAML文件

YAML格式用一个简单,完整的例子来解释:

image: testmap.png
resolution: 0.1
origin: [0.0, 0.0, 0.0]
occupied_thresh: 0.65
free_thresh: 0.196
negate: 0

必填字段:

image:包含占用数据的图像文件的路径; 可以是绝对的,也可以是相对于YAML文件的位置

resolution:地图的分辨率,米/像素

origin:地图中左下角像素的二维姿态,为(x,y,yaw),偏航为逆时针旋转(偏航= 0表示无旋转)。 系统的许多部分目前忽略了偏航。

occupied_thresh:大于此阈值的像素被视为完全占用。

free_thresh:小于此阈值的像素被认为是完全空闲的。

negate:是否应该反转 白/黑   空闲/占用(阈值的解释不受影响)

可选参数:

mode:可以有三个值之一:trinary,scale或raw。 Trinary是默认值。

参数解释:

如果像素的COLOR值x在[0,255]范围内,我们应该如何解释这个值?首先,我们将整数x转换为一个浮点数p,转换公式具体取决于yaml中negate标志的定义。

如果negate为0,则p =(255 - x)/ 255.0。这意味着黑色(0)现在具有最高值(1.0)而白色(255)具有最低值(0.0)。

如果negate为1,则p = x / 255.0。这是图像的非标准解释。

trinary
标准解释是三元解释,即解释所有值,使输出最终成为三个值之一。

如果p> occupied_thresh,则输出值100以指示单元格已被占用。

如果p <free_thresh,则输出值0以指示单元格是空闲的。

否则,输出-1 a.k.a. 255(作为无符号字符),以指示该单元格未知。

scale
这将调整上述解释,以允许更多的输出值。

如前所述,如果p> occupied_thresh,则输出值100,如果p <free_thresh,则输出值0。

否则,输出99 *(p - free_thresh)/(occupied_thresh - free_thresh)

这将允许您输出范围为[0,100]的完整渐变值。要输出-1,只需使用png的alpha通道,其中任何透明度都将被解释为未知。

raw
此模式将为每个像素输出x,因此输出值为[0,255]。

2、创建地图

2.1 启动 turtlebot3 gazebo仿真环境(roslaunch turtlebot3_gazebo  turtlebot3_stage_4.launch)

ros 地图显示在android ros地图构建_melodic

2.2 启动 turtlebot3_teleop_key 键盘驱动

(roslaunch turtlebot3_teleop turtlebot3_teleop_key.launch 或者前面自己编写的键盘驱动代码)

process[turtlebot3_teleop_keyboard-1]: started with pid [7499]

Control Your TurtleBot3!
---------------------------
Moving around:
        w
   a    s    d
        x

w/x : increase/decrease linear velocity (Burger : ~ 0.22, Waffle and Waffle Pi : ~ 0.26)
a/d : increase/decrease angular velocity (Burger : ~ 2.84, Waffle and Waffle Pi : ~ 1.82)

space key, s : force stop

CTRL-C to quit

2.3 启动 rviz 环境(roslaunch  turtlebot3_gazebo turtlebot3_gazebo_rviz.launch )

在本文的开发环境下,启动了 turtlebot3_gazebo turtlebot3_gazebo_rviz.launch 才能建图,主要是启动后会增加一个/robot_state_publisher节点发布 /tf_static 话题,当然也可以通过别的方式发布这个话题,这里是为了方便起见用了现成的launch文件,rosrun gmapping slam_gmapping 建图时需要这个话题消息。

同样如果用rosbag记录话题消息用来建图也得记录/tf_static,即 rosbag record -o data.bag /tf /scan /tf_static 。

ros 地图显示在android ros地图构建_ros_02

2.4 建图 (rosrun gmapping slam_gmapping )

结果如下,左上角为rviz里map话题的可视化结果,右上角为键盘驱动,右下角为gazebo仿真环境:

ros 地图显示在android ros地图构建_map_03

节点关系图为:

ros 地图显示在android ros地图构建_gmapping_04

3、利用rosbag记录数据

3.1 记录数据

启动上一步中相关环境后,执行以下命令记录scan 、tf 、tf_static话题上发布的所有消息:

rosbag record -o data.bag  /tf /scan /tf_static
wsc@wsc-pc:~$ rosbag record -h
Usage: rosbag record TOPIC1 [TOPIC2 TOPIC3 ...]

Record a bag file with the contents of specified topics.

Options:
  -h, --help            show this help message and exit
  -a, --all             record all topics
  -e, --regex           match topics using regular expressions
  -x EXCLUDE_REGEX, --exclude=EXCLUDE_REGEX
                        exclude topics matching the follow regular expression
                        (subtracts from -a or regex)
  -q, --quiet           suppress console output
  -o PREFIX, --output-prefix=PREFIX
                        prepend PREFIX to beginning of bag name (name will
                        always end with date stamp)
  -O NAME, --output-name=NAME
                        record to bag with name NAME.bag
  --split               split the bag when maximum size or duration is reached
  --max-splits=MAX_SPLITS
                        Keep a maximum of N bag files, when reaching the
                        maximum erase the oldest one to keep a constant number
                        of files.
  --size=SIZE           record a bag of maximum size SIZE MB. (Default:
                        infinite)
  --duration=DURATION   record a bag of maximum duration DURATION in seconds,
                        unless 'm', or 'h' is appended.
  -b SIZE, --buffsize=SIZE
                        use an internal buffer of SIZE MB (Default: 256, 0 =
                        infinite)
  --chunksize=SIZE      Advanced. Record to chunks of SIZE KB (Default: 768)
  -l NUM, --limit=NUM   only record NUM messages on each topic
  --node=NODE           record all topics subscribed to by a specific node
  -j, --bz2             use BZ2 compression
  --lz4                 use LZ4 compression
  --tcpnodelay          Use the TCP_NODELAY transport hint when subscribing to
                        topics.
  --udp                 Use the UDP transport hint when subscribing to topics

比如:

rosbag record -a 记录所有话题

rosbag record -o foo scan tf  文件名前加上foo前缀

rosbag record -O foo.bag scan tf  指定文件名

3.2 回放数据

使用  rosbag play 播放之前记录的包,--clock 标志表示需要rosbag发布时间信息

rosbag play --clock data_2018-08-10-18-27-20.bag

使用  rosbag info foo.bag 显示包文件信息。

3. 3 利用回放数据建图

rosparam set use_sim_time true

rosrun gmapping slam_gmapping

4、启动地图服务器以及查看地图

 执行 rosrun map_server  map_saver 保存地图,执行rosrun map_server map_server map.yaml,发布地图话题:

wsc@wsc-pc:~$ rostopic list
/map
/map_metadata
/rosout
/rosout_agg

可以在rviz中查看/map 话题 地图。

5、其他命令记录

在完成本文任务的过程中,遇到了一些问题,比如一开始gmapping 装不上,编译不来,解决方法见,后来又遇到 缺少 /tf_static 话题而不能建图的问题,解决问题的过程中用到了一些命令,一并记录下:

#查看 tf tree
rosrun tf view_frames
evince frames.pdf

# 设置调试等级
wsc@wsc-pc:~$ rosconsole 
rosconsole is a command-line tool for configuring the logger level of ROS nodes.

Commands:
	rosconsole get	display level for a logger
	rosconsole list	list loggers for a node
	rosconsole set	set level for a logger
	rosconsole echo	print logger messages


wsc@wsc-pc:~$ rosconsole list slam_gmapping
ros
ros.gmapping.message_filter
ros.roscpp
ros.roscpp.cached_parameters
ros.roscpp.roscpp_internal
ros.roscpp.roscpp_internal.connections
ros.roscpp.superdebug

rosconsole set slam_gmapping ros.gmapping.message_filter DEBUG




rosnode info /robot_state_publisher
--------------------------------------------------------------------------------
Node [/robot_state_publisher]
Publications: 
 * /rosout [rosgraph_msgs/Log]
 * /tf [tf2_msgs/TFMessage]
 * /tf_static [tf2_msgs/TFMessage]

Subscriptions: 
 * /clock [rosgraph_msgs/Clock]
 * /joint_states [sensor_msgs/JointState]

Services: 
 * /robot_state_publisher/get_loggers
 * /robot_state_publisher/set_logger_level