racecar仿真竞赛经验总结(三)- 激光SLAM建图
racecar仿真竞赛经验总结(三)- 激光SLAM
前文链接:
racecar仿真竞赛经验总结(二)- racecar仿真模型介绍
由于使用激光SLAM建图需要搭建完整的tf树变换,博主提供的代码包已完整包含可以直接使用并建图,初学者建议使用racecar仿真竞赛经验总结(二)- racecar仿真模型介绍中提供的北邮老哥的racecar demo进行尝试
Gmapping构建地图
参数介绍
说明
此部分介绍ROS封装了的OpenSlam GMapping,gmapping功能包提供了基于激光的SLAM,在ROS系统中使用slam_gmapping节点表示。 通过该节点用户可以用机器人在移动过程中激光传感器获取的数据创建2D栅格地图。
订阅主题 - Subscribed Topics
- tf (tf/tfMessage),用于激光器坐标系,基座坐标系,里程计坐标系之间转换
- scan (sensor_msgs/LaserScan ) ,激光器扫描数据
发布主题 - Published Topics
- map_metadata (nav_msgs/MapMetaData),周期性发布地图metadata数据
- map (nav_msgs/OccupancyGrid),周期性发布地图数据
- ~entropy (std_msgs/Float64),发布机器人姿态分布熵的估计
服务 - Service
- dynamic_map (nav_msgs/GetMap),调用该服务可以获取地图数据
参数调节
重要参数说明
- particles (int, default: 30) gmapping算法中的粒子数,因为gmapping使用的是粒子滤波算法,粒子在不断地迭代更新,所以选取一个合适的粒子数可以让算法在保证比较准确的同时有较高的速度
- minimumScore (float, default: 0.0) 最小匹配得分,这个参数很重要,它决定了对激光的一个置信度,越高说明对激光匹配算法的要求越高,激光的匹配也越容易失败而转去使用里程计数据,而设的太低又会使地图中出现大量噪声,所以需要权衡调整
所有参数索引
这里提供一些中文翻译版本的参数说明,建议直接去上文ros wiki查
- ~inverted_laser (string, default:”false”), (已经已出在 版本 1.1.1; 用transform data 替换它) 激光器是right side up (scans are ordered CCW),还是 upside down (scans are ordered CW)?
- ~throttle_scans (int, default: 1),处理的扫描数据门限,默认每次处理1个扫描数据(可以设置更大跳过一些扫描数据)
- ~base_frame (string, default:”base_link”),机器人基座坐标系,在此例程中应为base_footprint
- ~map_frame (string, default:”map”),地图坐标系
- ~odom_frame (string, default:”odom”),里程计坐标系
- ~map_update_interval (float, default: 5.0),地图更新频率
- ~maxUrange (float, default: 80.0),探测最大可用范围,即光束能到达的范围
- ~sigma (float, default: 0.05),endpoint匹配标准差
- ~kernelSize (int, default: 1),用于查找对应的kernel size
- ~lstep (float, default: 0.05),平移优化步长
- ~astep (float, default: 0.05),旋转优化步长
- ~iterations (int, default: 5),扫描匹配迭代步数
- ~lsigma (float, default: 0.075),用于扫描匹配概率的激光标准差
- ~ogain (float, default: 3.0),似然估计为平滑重采样影响使用的gain
- ~lskip (int, default: 0),每次扫描跳过的光束数.
- ~minimumScore (float, default: 0.0),为获得好的扫描匹配输出结果,用于避免在大空间范围使用有限距离的激光扫描仪(如5m)出现的jumping pose estimates问题。 当 Scores高达600+,如果出现了该问题可以考虑设定值50。
- ~srr (float, default: 0.1),平移时里程误差作为平移函数(rho/rho)
- ~srt (float, default: 0.2),平移时的里程误差作为旋转函数 (rho/theta)
- ~str (float, default: 0.1),旋转时的里程误差作为平移函数 (theta/rho)
- ~stt (float, default: 0.2),旋转时的里程误差作为旋转函数 (theta/theta)
- ~linearUpdate (float, default: 1.0),机器人每旋转这么远处理一次扫描
- ~angularUpdate (float, default: 0.5),Process a scan each time the robot rotates this far
- ~temporalUpdate (float, default: -1.0),如果最新扫描处理比更新慢,则处理1次扫描。该值为负数时候关闭基于时间的更新
- ~resampleThreshold (float, default: 0.5),基于重采样门限的Neff
- ~particles (int, default: 30),滤波器中粒子数目
- ~xmin (float, default: -100.0),地图初始尺寸
- ~ymin (float, default: -100.0),地图初始尺寸
- ~xmax (float, default: 100.0),地图初始尺寸
- ~ymax (float, default: 100.0),地图初始尺寸
- ~delta (float, default: 0.05),地图分辨率
- ~llsamplerange (float, default: 0.01),于似然计算的平移采样距离
- ~llsamplestep (float, default: 0.01),用于似然计算的平移采样步长
- ~lasamplerange (float, default: 0.005),用于似然计算的角度采样距离
- ~lasamplestep (float, default: 0.005),用于似然计算的角度采样步长
- ~transform_publish_period (float, default: 0.05),变换发布时间间隔.
- ~occ_thresh (float, default: 0.25),栅格地图栅格值 (i.e., set to 100 in the resultingsensor_msgs/LaserScan)
- ~maxRange (float),传感器最大范围。如果在传感器距离范围内没有障碍物应该在地图上显示为自由空间。 maxUrange < 真实传感器最大距离范围 <= maxRange
参考配置
北邮老哥的gmapping配置在官方地图上效果不是很理想,具体怎么不理想呢…嗯
这里给出一份gmapping参考配置(如果安装了turtlebot可以直接用turtlebot的gmapping建图😁 比赛时我们就是走了这个捷径没怎么配置gmapping)
<?xml version="1.0"?>
<launch>
<arg name="scan_topic" default="scan" /> //laser的topic名称,与自己的激光的topic相对应
<arg name="base_frame" default="base_footprint"/>//机器人的坐标系
<arg name="odom_frame" default="odom"/>//世界坐标
<node pkg="gmapping" type="slam_gmapping" name="slam_gmapping" output="screen">//启动slam的节点
<param name="base_frame" value="$(arg base_frame)"/>
<param name="odom_frame" value="$(arg odom_frame)"/>
<param name="map_update_interval" value="0.01"/>//地图更新的一个间隔,两次scanmatch的间隔,地图更新也受scanmach的影响,如果scanmatch没有成功的话,是不会更新地图的
<param name="maxUrange" value="4.0"/>//set maxUrange < maximum range of the real sensor <= maxRange
<param name="maxRange" value="5.0"/>
<param name="sigma" value="0.05"/>
<param name="kernelSize" value="3"/>
<param name="lstep" value="0.05"/>optimize机器人移动的初始值(距离)
<param name="astep" value="0.05"/>//optimize机器人移动的初始值(角度)
<param name="iterations" value="5"/>//icp的迭代次数
<param name="lsigma" value="0.075"/>
<param name="ogain" value="3.0"/>
<param name="lskip" value="0"/>//为0,表示所有的激光都处理,尽可能为零,如果计算压力过大,可以改成1
<param name="minimumScore" value="30"/>//很重要,判断scanmatch是否成功的阈值,过高的话会使scanmatch失败,从而影响地图更新速率
<param name="srr" value="0.01"/>//以下四个参数是运动模型的噪声参数
<param name="srt" value="0.02"/>
<param name="str" value="0.01"/>
<param name="stt" value="0.02"/>
<param name="linearUpdate" value="0.05"/>//机器人移动linearUpdate距离,进行scanmatch
<param name="angularUpdate" value="0.0436"/>机器人选装angularUpdate角度,进行scanmatch
<param name="temporalUpdate" value="-1.0"/>
<param name="resampleThreshold" value="0.5"/>
<param name="particles" value="8"/>//很重要,粒子个数
<!--
<param name="xmin" value="-50.0"/>
<param name="ymin" value="-50.0"/>
<param name="xmax" value="50.0"/>
<param name="ymax" value="50.0"/>
make the starting size small for the benefit of the Android client's memory...
-->
<param name="xmin" value="-1.0"/>//map初始化的大小
<param name="ymin" value="-1.0"/>
<param name="xmax" value="1.0"/>
<param name="ymax" value="1.0"/>
<param name="delta" value="0.05"/>
<param name="llsamplerange" value="0.01"/>
<param name="llsamplestep" value="0.01"/>
<param name="lasamplerange" value="0.005"/>
<param name="lasamplestep" value="0.005"/>
<remap from="scan" to="$(arg scan_topic)"/>
</node>
参考资料
- http://openslam.org/gmapping.html
- http://blog.csdn.net/x_r_su/article/details/52723244
- http://blog.csdn.net/eaibot/article/details/51628371
- http://www.ncnynl.com/archives/201702/1364.html
方法推荐
使用reconfigure调参会方便很多,也比在yaml文件里直观
rosrun rqt_reconfigure rqt_reconfigure
操作步骤
打开键盘控制,启动gazebo并加载地图
roslaunch racecar_gazebo racecar.launch
修改gmapping参数配置
在racecar_gazebo/launch/gmapping.launch中修改对应参数项后启动gmapping(由于官方提供的源码包已经搭建好了激光雷达的tf树变换,这里直接启动就可以)
roslaunch racecar_gazebo slam_gmapping.launch
通过键盘操控小车完成建图
运行map_saver节点保存地图至racecar_gazebo/worlds/文件夹下
rosrun map_server map_saver -f ~/racecar_gazebo/worlds
Hector-mapping构建地图
参数介绍
hector_mapping是基于LIDAR的SLAM的节点,没有里程计量和低计算资源。为了简单起见,下面详细介绍的ROS API从用户角度提供了常用选项的信息,但不是所有可用于调试的选项。
订阅主题 - Subscribed Topics
- scan (sensor_msgs/LaserScan) ,SLAM系统使用的激光扫描
- syscommand (std_msgs/String) ,系统命令。 如果字符串等于“复位”,则地图和机器人姿势被重置为其初始状态
发布主题 - Published Topics
- map_metadata (nav_msgs/MapMetaData) ,从此话题获取地图元数据,将其锁定并定期更新
- map (nav_msgs/OccupancyGrid) ,从此话题获取地图数据,将其锁定并定期更新
- slam_out_pose (geometry_msgs/PoseStamped) ,估计的机器人姿势没有协方差
- poseupdate (geometry_msgs/PoseWithCovarianceStamped) ,估计的机器人姿态具有高斯估计的不确定性
服务 - Service
- dynamic_map (nav_msgs/GetMap) ,调用此服务以获取地图数据
参数调节
所有参数索引
这里提供一些中文翻译版本的参数说明,建议直接去上文ros wiki查
- ~base_frame (string, default: base_link) ,机器人基本坐标系的名称。这是用于定位和用于激光扫描数据的变换
- ~map_frame (string, default: map_link) ,map 坐标系的名称。
- ~odom_frame (string, default: odom) ,里程坐标系的名称。
- ~map_resolution (double, default: 0.025) ,地图分辨率[m]。 这是网格单元边缘的长度。
- ~map_size (int, default: 1024) ,地图的大小[每个轴的单元格数量]。 地图是正方形的并且具有(map_size * map_size)网格单元。
- ~map_start_x (double, default: 0.5) ,/map的原点[0.0,1.0]在x轴上相对于网格图的位置。 0.5在中间。
- ~map_start_y (double, default: 0.5) ,/map的原点[0.0,1.0]在y轴上相对于网格图的位置。 0.5在中间。
- ~map_update_distance_thresh (double, default: 0.4) ,执行地图更新的阈值[m]。平台必须以米为单位计算,在地图上一次更新起算到直行距离达到参数值之后再更新。
- ~map_update_angle_thresh (double, default: 0.9) ,执行地图更新的阈值[rad]。平台必须以米为单位计算,在地图上一次更新起算到转动达到参数值之后再更新。
- ~map_pub_period (double, default: 2.0) ,地图发布周期
- ~map_multi_res_levels (int, default: 3) ,地图多分辨率网格级数。
- ~update_factor_free (double, default: 0.4) ,用于更新范围[0.0,1.0]中的空闲单元格的地图更新修改器。 值0.5表示没有变化。
- ~update_factor_occupied (double, default: 0.9) ,用于在范围[0.0,1.0]中更新被占用单元的地图更新修改器。 值0.5表示没有变化。
- ~laser_min_dist (double, default: 0.4) ,系统使用的激光扫描端点的最小距离[m]。 距离此值更近的扫描端点将被忽略
- ~laser_max_dist (double, default: 30.0) ,系统使用的激光扫描端点的最大距离[m]。 超出此值的扫描端点将被忽略。
- ~laser_z_min_value (double, default: -1.0) ,相对于激光扫描器框架的最小高度[m],用于系统使用的激光扫描端点。 低于此值的扫描端点将被忽略。
- ~laser_z_max_value (double, default: 1.0) ,相对于激光扫描仪框架的最大高度[m],用于系统使用的激光扫描终点。 高于此值的扫描端点将被忽略。
- ~pub_map_odom_transform (bool, default: true) ,确定map-> odom转换是否应该由系统发布
- ~output_timing (bool, default: false) ,通过ROS_INFO处理每个激光扫描的输出时序信息。
- ~scan_subscriber_queue_size (int, default: 5) ,扫描订阅器的队列大小。 如果日志文件以比实时速度更快的速度回放到hector_mapping,则应将此值设置为高值(例如50)。
- ~pub_map_scanmatch_transform (bool, default: true) ,确定scanmatcher到map的转换是否发布到TF.坐标名通过tf_map_scanmatch_transform_frame_name参数确定。
- ~tf_map_scanmatch_transform_frame_name (string, default: scanmatcher_frame) ,发布scanmatcher到map转换的坐标名。
参考资料
- http://wiki.ros.org/hector_slam/Tutorials/SettingUpForYourRobot
- http://wiki.ros.org/hector_mapping
- http://www.youtube.com/playlist?list=PL0E462904E5D35E29
- http://www.sim.tu-darmstadt.de/publ/download/2011_SSRR_KohlbrecherMeyerStrykKlingauf_Flexible_SLAM_System.pdf
操作步骤
博主直接用turtlebot建好了地图,gmapping 的启动文件北邮老哥那个包里有写好的,如果需要使用hector需要自己编写launch文件了,编写好launch文件后启动方式和顺序与gmapping一样