因为最近拿到一个Robosense16线的激光雷达,这是一个三维的激光雷达,所以就拿着这个雷达把一些开源的经典的SLAM算法都跑了一遍,中间也遇到了一些问题,所以就打算在博客上记录下来,供大家交流参考,接下来的一系类文章就是如何配置激光雷达与SLAM算法的连接。今天咱们先讲第一个SLAM算法——Hector。
关于Robosense与Hector算法建图的博文有一篇很详细,详情请参考:https://blog.csdn.net/geerniya/article/details/84866429
由于这篇博文的作者写的很详细,我主要写下自己建图的步骤和一些资料的链接,如有不懂的问题可以参考上面的博文链接。下面咱们开始Hector建图之旅。
一、安装雷达的驱动
环境:Ubuntu16.04+ROS kinetic
购置速腾聚创Robosense16的激光雷达,厂家会赠送参考手册,这个给一个下载链接:
链接:https://pan.baidu.com/s/1cNIraLOLdMb8P5kssK9lJQ
提取码:3ag2
按照手册一步一步操作即可,这里不详细记录其过程了。里面有一个设置静态IP的步骤,这里有一个比较详细的配置静态IP的博文,请参考:https://www.cnblogs.com/dengyungao/p/8523348.html
注:因为我平时用WIFI上网,所以这样配置是没有冲突的,如果你的电脑有多个网口,用宽带上网的话,这个方法貌似会有问题,你需要重新参考一下其他的方法,如果你用WiFi,你跳过这个问题就行。
至此,雷达的驱动已安装完成,你可以在RVIZ查看雷达的点云数据了,效果还是非常好的。看来贵的雷达还是有道理的。╮(╯▽╰)╭
二、Hector建图
1、使用pointcloud_to_laserscan将3d的激光雷达数据转换为2d的激光雷达数据
由于速腾Robosense16线雷达是一个3维的激光雷达,而Hector是一个2d的SLAM算法,所以需要将3D的雷达转换为2D的雷达,将3d激光雷达转换成2d雷达,有两种方式:一种是只使用3d雷达中的一条扫描线,另一种是将多条扫描线合成一条2d雷达扫描线。使用pointcloud_to_laserscan包可以很方便地实现第二种办法,第二种方法因为使用了多条扫描线,因此可以输出更高质量的2d雷达数据。
使用pointcloud_to_laserscan包将3d的激光雷达数据转换为2d的雷达数据可以参考这篇博文,讲解的很详细,详见:https://blog.csdn.net/geerniya/article/details/84880514
如果你对pointcloud_to_laserscan包中的参数比较感兴趣,你可以去ros wiki的官网中参考pointcloud_to_laserscan的详细介绍。
2、使用Hector-slam建图
在上一步的操作中,我们已经成功的将3d的激光雷达数据转化为2d的激光雷达数据,这也是hector-slam所能接受的输入数据。因为我在这里稍微有所改动,与博文https://blog.csdn.net/geerniya/article/details/84882203有所不同,所以我就详细的记录下面这个过程的步骤。
hector-slam采用的是卡尔曼滤波的思想,建图的过程不需要里程计,所以我们可以手持激光雷达构建2d的平面地图。如果你对hector-slam的原理感兴趣你可以参考其他相关的博文。(这个我没有仔细的研究过,所以没有相关的链接分享 ̄□ ̄||)
1)、由于ROS的软件源中已经集成hector-slam的包,所以我们可以用二进制形式安装,即使用命令:
sudo apt-get install ros-kinetic-hetor-slam
2)、建立hector-slam的启动文件
我们可以在 ~/catkin_ws/src/ros_rslidar/rslidar_pointcloud/launch中(这里是我激光雷达驱动文件的存放位置,你自己的根据实际情况来定)建立一个hector_slam_with_rslidar.launch,其具体的内容如下:
<launch>
<!-- start robosense -->
<include file="$ (find rslidar_pointcloud)/launch/rs_lidar_16.launch" />
<!-- start pointcloud to scan -->
<include file="$ (find pointcloud_to_laserscan)/launch/point_to_scan.launch" />
<!-- start hector_mapping node -->
<node pkg = "hector_mapping" type="hector_mapping" name="hector_mapping" output="screen">
<!-- Frame names -->
<param name="pub_map_odom_transform" value="true"/>
<param name="map_frame" value="map" />
<param name="base_frame" value="base_link" />
<param name="odom_frame" value="odom" />
<!-- Tf use -->
<param name="use_tf_scan_transformation" value="true"/>
<param name="use_tf_pose_start_estimate" value="false"/>
<!-- Map size / start point -->
<param name="map_resolution" value="0.05"/>
<param name="map_size" value="8192"/>
<param name="map_start_x" value="0.5"/>
<param name="map_start_y" value="0.5" />
<param name="laser_z_min_value" value = "-1.0" />
<param name="laser_z_max_value" value = "1.0" />
<param name="map_multi_res_levels" value="2" />
<param name="map_pub_period" value="2" />
<param name="laser_min_dist" value="0.4" />
<param name="laser_max_dist" value="30.0" />
<param name="output_timing" value="false" />
<param name="pub_map_scanmatch_transform" value="true" />
<!-- Map update parameters -->
<param name="update_factor_free" value="0.4"/>
<param name="update_factor_occupied" value="0.7" />
<param name="map_update_distance_thresh" value="0.2"/>
<param name="map_update_angle_thresh" value="0.06" />
<!-- Advertising config -->
<param name="advertise_map_service" value="true"/>
<param name="scan_subscriber_queue_size" value="5"/>
<param name="scan_topic" value="scan"/>
</node>
<!-- transform between base_link and odom/laser -->
<node pkg="tf" type="static_transform_publisher" name="baselink_to_laser" args="0 0 0 0 0 0 /base_link /laser 100" />
<node pkg="tf" type="static_transform_publisher" name="map_to_odom" args="0 0 0 0 0 0 /odom /base_link 100" />
<!-- start rviz -->
<node pkg="rviz" type="rviz" name="rviz" args="-d $(find hector_slam_launch)/rviz_cfg/mapping_demo.rviz"/>
</launch>
这个launch文件主要分为这几个部分:第一部分是启动Robosense激光雷达的启动文件;第二部分是启动pointcloud_to_laserscan节点,将激光雷达的三维数据转换为2d类型;第三部分是启动hector_mapping节点并配置相关参数;第四部分是发布静态tf变换,主要是base_link与laser、odom与base_link;第五部分是启动rviz界面。
其中比较重要的部分是hector_mapping节点参数配置和发布静态tf变换,如果这部分的关系没有理清是很容易出现错误的,现在我们就来讲讲这个部分,也是为以后的其他算法的构建做铺垫。在hector——mapping节点的frame配置中有这两个重要的参数<param name="base_frame" value="base_link" />
<param name="odom_frame" value="odom" />
由于hector算法是不需要odom(里程计),所以这里的odom_frame我们可以将其设置为base_link,即不使用odom这个frame,然后在静态tf变换中我们可以去掉 这个静态发布
<node pkg="tf" type="static_transform_publisher" name="map_to_odom" args="0 0 0 0 0 0 /odom /base_link 100" /> (*)
如果我们想保留odom,即 将odom_frame设为<param name="odom_frame" value="odom" />这时我们需要为其提供一个odom——base_link的变换,保留这个(*)这个静态变换,有兴趣的同学可以分别尝试一下。
下面贴上所讲的两种方法的tf树,以供参考:
这里还有一个问题需要注意的就是:<node pkg="tf" type="static_transform_publisher" name="baselink_to_laser" args="0 0 0 0 0 0 /base_link /laser 100" />在这个tf变换中,用到的是laser,这是激光雷达的frame_id ,因为我把robosense激光的雷达的frame_id改为/laser了,多以这里用的是/laser,如果你没改过的话应该是/rslidar,你也可以使用下面的命令查看
rostopic echo /scan
至此,整个建图过程我们已经讲解的很清楚了,我第一建图的时候出现了以下的错误:
你也应该知道是什么原因导致的错误了。