差速小车的Cartographer建图

目录

 

在之前的一些文章中,我们创建了DiffCart的仿真模型并能通过键盘控制它。 还为之提供了里程计IMU用于估计机器人的位姿。 现在我们来给DiffCart装上激光雷达,并使用Cartographer进行建图。

Cartographer是google的工程师开发的一个用于室内实时建图的SLAM解决方案。目前这种方案支持单线激光的2D建图, 也支持多线激光的3D建图。我们的初衷是使用多线激光进行3D建图,在写本文的demo的时候,虽然成功地对接上了Cartographer的3D建图方法,但是不清楚是算力不够还是建图参数没有调整, 3D定位建图过程非常缓慢,需要DiffCart走走停停才能看到建图效果。因此,我们还是额外提供了一个2D建图的demo,它就要流畅很多。

本文中,我们先进行3D建图,再在此基础上进行修改提供2D的建图方案。我们将记录下demo的编写调试过程,以及中间遇到的坑和相关思考。

1. 安装多线激光

安装多线激光,我一开始的想法是直接把之前创建的32线的Velodyne雷达模型直接include到DiffCart的模型文件中。 但是出于两方面的考虑,最后还是没有这么做。

  • 其一,我不清楚如何把这个雷达固定到小车上。我知道在SDF文件的<include>标签是可以添加<pose>子标签来指定放置位置的, 通过fixed类型的joint可以把两个link固连在一起。但是DiffCart和Velodyne的模型中都有多个link,我不知道该怎样指定具体的link固连起来。这方面的资料比较少,扒源码也比较麻烦。
  • 其二,demo的编写过程并没有过多的考虑模块化的问题。如果直接把模型文件include进来,那么以后我们将维护两个demo的插件。在系统的模块化设计比较合理,耦合度比较低的情况下, 这样处理还是比较方便的。但是我根本没考虑过这方面问题,而且还想着以后逐渐剥离ROS系统,纯粹使用Gazebo进行仿真。

所以,我们还是参考Velodyne仿真插件的套路, 在DiffCart的模型文件中新增了一个link来安装激光雷达。 如下图所示,我们在[−0.10.00.24]T的位置上安放了雷达的link,这个位置在xy平面上的投影正好与小车两轮的中点投影重合。 我们还使用一个fixed的joint将之与车体固连起来。如下面右图所示,小车上面那个圆柱就是新安装的雷达。

这仍然是一个32线的激光雷达,每线有90个采样点,更新频率是5Hz。一开始每线的采样点也是2187个,而且更新频率是10Hz。发现仿真跑不动,小车走起来有明显的卡滞, 而且Cartographer几乎没有输出。所以就调低了采样频率和采样点数量。然后,我们在仿真插件中按照Velodyne仿真插件的套路, 订阅激光传感器的数据消息,并在回调函数中解析消息,填充ROS的sensor_msgs::PointCloud2消息并发布。

2. 3D建图

现在,我们已经准备好了传感器和控制器,可以开始对接Cartographer进行建图了。 我们曾经按照官方教程安装过Cartographer, 但是在另外一个ROS工作空间下进行的,使用起来多少有些麻烦。可以将两个工作空间合并,但还是有点麻烦,所以我直接按照如下的指令安装了ROS官方维护的Cartographer。

        $ sudo apt install ros-melodic-cartographer*

在launch子目录下新建一个launch脚本diffcart_3d_cartographer.launch, 参考cartographer_ros的官方demo,如下面的代码片段所示, 我们在其中的第1到7行中运行cartographer_node节点,通过参数args指定配置文件所在目录和配置文件。 同时还将cartographer_node中所用的主题"imu"和"points2"重映射为我们在仿真插件中发布的关于IMU数据和点云数据主题。最后第7,8行中运行的节点cartographer_occupancy_grid_node, 将Cartographer生成的子图合并成为一个占用删格地图并通过ROS的主题发布出去。

        <node pkg="cartographer_ros" type="cartographer_node" name="cartographer_node" 
            args="-configuration_directory $(find gazebo_demos)/config -configuration_basename diffcart_3d.lua" output="screen">
            <remap from="imu" to="/imu_data"/>
            <remap from="points2" to="/point_cloud"/>
        </node>

        <node name="cartographer_occupancy_grid_node" pkg="cartographer_ros"
            type="cartographer_occupancy_grid_node" args="-resolution 0.05" />

为了方便调整Cartographer的运行参数,我们在gazebo_demos的根目录下创建了一个子目录config,并将cartographer_ros中的配置文件backpack_3d.lua文件拷贝过来, 命名为diffcart_3d.lua。 官方教程中,详细的说明了各个配置项的意义。 在下表中,我们列出一些比较重要的字段。

字段说明
map_frame"map"地图坐标系名称
tracking_frame"base_link"Cartographer将要跟踪的机器人坐标系名称
provide_odom_frametrueCartographer将使用Local SLAM的位姿估计作为里程计
odom_frame"odom"里程计坐标系名称。
use_odometrytrue在Local SLAM中使用里程计信息,Cartographer将订阅主题"odom"接收nav_msgs/Odometry类型的消息。
num_point_clouds1激光点云主题数量,由于我们只有一个激光雷达,所以Cartographer将订阅主题"points2"接收sensor_msgs/PointCloud2类型的消息。
MAP_BUILDER.use_trajectory_builder_3dtrue启用3D建图引擎。

这些配置项要求Cartographer维护从"map"到"odom"再到"base_link"的坐标变换。我们的插件只需要提供"/odom", "/imu_data"和"/point_cloud"三个主题的消息就可以驱动Cartographer进行定位和建图了。 所以,我们对DiffCart的里程计做了一些简单的修改,不再发布从"odom"到"base_link"的tf变换消息,而是nav_msgs/Odometry类型的消息。

此外,为了防止Cartographer出现一些莫名奇妙的错误,我们增加了"imu_link"和"laser_link"两个坐标系,并通过tf工具直接发布静态坐标关系,将之与机器人坐标系"base_link"固连在一起。 如下面的代码片段所示:

        <node pkg="tf" type="static_transform_publisher" name="laser_base_link_transform" args="0 0 0 0 0 0 base_link laser_link 100"/>
        <node pkg="tf" type="static_transform_publisher" name="imu_base_link_transform" args="0 0 0 0 0 0 base_link imu_link 100" />

我们还需要设置ROS运行参数"/use_sim_time"为true,来统一ROS与Gazebo之间的时间体系。调用脚本"bringup_gazebo.sh"运行Gazebo加载仿真环境。 世界文件diffcart_willowgarage.world还从Gazebo官方维护的模型仓库gazebo_models中引入了"willowgarage"模型,提供了一个室内场景。

        <param name="/use_sim_time" value="true" />
        <node name="gazebo" pkg="gazebo_demos" type="bringup_gazebo.sh"
            args="$(find gazebo_demos)/worlds/diffcart_willowgarage.world" output="screen"/>

完成必要的准备工作之后,我们就可以通过指令$ roslaunch gazebo_demos diffcart_3d_cartographer.launch运行launch脚本,开始Cartographer建图仿真了。 下面左右两幅图分别是Gazebo仿真环境和rviz中激光扫描和建图过程的截图。

由于系统运行十分缓慢,Cartographer响应很迟钝,需要走走停停才能看到建图效果,所以这里的截图只是走了一小段而已。估计需要比较细致的调整一下Cartographer的运行参数才能看到比较流畅的效果。

3. 2D建图

我还是希望能够看到一个比较流畅的效果的,可能3D的建图方法对算力的要求比较高,所以我们将DiffCart上的32线激光改成了单线激光,进行2D建图。主要有以下几个方面的改动:

  1. 新建了一个模型diffcart_with_single_laser,安装的是单线激光。
  2. 提供了一个世界文件将其中的DiffCart模型替换为单线激光版本的。
  3. 在config子目录下增加用于2D建图的配置文件
  4. 针对单线激光修改了接收激光扫描数据的回调函数OnLaserScanMsg, 具体修改内容参见源码,不再细述。
  5. 增加用于2D建图的launch脚本

修改完成之后,通过指令$ roslaunch gazebo_demos diffcart_2d_cartographer.launch运行2D建图的demo,并使用键盘控制DiffCart在仿真世界中运动一段时间后, 就可以看到下图的效果。整个过程还是比较流畅的,而且可以看到运动的轨迹和不断增加的约束。

4. 完

要运行Cartographer,我们需要根据传感器的类型和建图方法提供cartographer_ros的系统的*.lua配置文件。并根据该配置文件组织传感器数据消息的主题,以及相关的坐标系统。 我们的demo中Cartographer维护了地图、里程计和机器人本体之间的坐标关系。修改配置项provide_odom_frame为false,Cartographer将不再提供局部的位姿估计,需要用户自己根据实际情况提供。 由于SLAM问题本身就有定位和建图两个方面,所以建议将该配置项置为true。

您好!关于Cartographer建图漂移的问题,我能为您提供一些信息。Cartographer是一个开源的SLAM(Simultaneous Localization and Mapping)系统,它能够通过使用激光雷达和其他传感器数据来生成环境地图,并同时估计机器人在地图中的位置。所谓建图漂移是指机器人在建立地图的过程中,由于误差累积或其他因素导致地图与实际环境之间存在一定程度的偏差。 建图漂移是SLAM系统中一个常见的问题,它可能由多种因素引起,包括传感器误差、环境变化、运动模型不准确等。为了解决建图漂移问题,Cartographer采用了一系列的技术手段,如回环检测、优化等。回环检测指的是通过识别环境中已经访问过的区域,从而将机器人当前位置与先前访问过的位置进行关联,以减小建图漂移的影响。优化则是通过对机器人在地图上的运动轨迹进行优化,以修复漂移带来的偏差。 尽管Cartographer采用了多种方法来减小建图漂移,但完全消除建图漂移是一个相对困难的问题,特别是在长时间运行或复杂环境下。因此,在使用Cartographer进行建图时,需要仔细设置参数、合理选择传感器,并进行必要的环境校准和误差补偿,以最大程度地减小建图漂移的影响。此外,如果需要更精确的地图,还可以考虑采用其他SLAM系统或增加其他辅助定位方式。 希望这些信息能对您有所帮助!如果还有其他问题,请随时提问。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值