目录

在之前的一些文章中,我们创建了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_frame true Cartographer将使用Local SLAM的位姿估计作为里程计
odom_frame "odom" 里程计坐标系名称。
use_odometry true 在Local SLAM中使用里程计信息,Cartographer将订阅主题"odom"接收nav_msgs/Odometry类型的消息。
num_point_clouds 1 激光点云主题数量,由于我们只有一个激光雷达,所以Cartographer将订阅主题"points2"接收sensor_msgs/PointCloud2类型的消息。
MAP_BUILDER.use_trajectory_builder_3d true 启用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建图相关推荐

  1. 【工程记录】基于松灵Scout mini底盘实现小车自主探索建图

    一.硬件配置 松灵scout mini底盘 速腾robense 16线激光雷达 瑞芬imu 因特尔nuc 二.工程技术栈 IMU驱动包(原创) 松灵底盘包(改写,里程计融合IMU角度信息) ROS N ...

  2. Cartographer建图和纯定位

    (一)cartographer在ros下安装参考: 要求: 64-bit, modern CPU (e.g. 3rd generation i7) 16 GB RAM Ubuntu 18.04 (Bi ...

  3. 机器人学习--Turtelbot3学习--如何使用cartographer建图

    问题描述: 按照创客智造官网的教程:https://www.ncnynl.com/category/turtlebot3-tutorial/ 安装好turtlebot3的配套软件后,默认是使用 gma ...

  4. odomimu融合用于Cartographer建图

    任务动机:使用odom&imu融合用于Cartographer建图,提高Cartographer建图时的匹配精度,同时降低运算消耗. 任务描述:使用odom&imu融合用于Cartog ...

  5. 用自己的机器人实现cartographer建图测试与地图保存应该这样做

    用自己的机器人实现cartographer建图测试与地图保存应该这样做 1.安装 2.测试 3.保存地图 亲测可行.(该教程使用github的代码地址,速度相对慢了一点,极速安装,请看这里: 极速安装 ...

  6. ros2 -foxy安装cartographer建图定位-- 源码安装 使用

    foxy 的cartographer_ros 和dashing 的兼容 cd  ~/xx__ws/src 安装源码 git clone https://ghproxy.com/https://gith ...

  7. 用自己的雷达进行Cartographer建图或仿真

    首先需要进行Cartographer安装以及雷达驱动安装等准备工作, 直至我们能够在雷达运行时找到发布LaserScan的Topic并获取数据, 以开始下一步的建图. 基本信息获取 启动雷达或gaze ...

  8. cartographer建图,重定位及发布消息结构为nav_msgs::Odometry的odom话题

    完整功能包(包含carto建图,重定位以及odom话题发布)上传至https://download.csdn.net/download/zhaohaowu/33647981 众所周知,cartogra ...

  9. HANDSFREE 2代小车 用xtion建图导航

    博主的实验室之前购买了HANDSFREE 2代的小车,因为手头没有激光雷达,所以使用了华硕的xtion pro摄像头来进行建图和导航 由于HANDSFREE 2代小车原生支持激光雷达,所以我们要用xt ...

最新文章

  1. CocosCreator上的游戏(调试)发布到微信小程序
  2. 如何用R和API免费获取Web数据?
  3. 【生活】 戴尔XPS 插上耳机之后,说话没声音,麦克风失效 window10 系统
  4. 可视化GDI操作题目
  5. boost::callable_traits移除const成员的测试程序
  6. 如果你想写自己的Benchmark框架
  7. python转嵌入式c_在C嵌入式python中刷新导入
  8. java break 在if 中使用_java中使用国密SM4算法详解
  9. 【学习笔记】JavaScript基础(一)
  10. jQuery对象与DOM对象的相互转换
  11. 前端学习(1698):前端系列javascript之原型链和instance
  12. http请求前后监听工具
  13. mysql有哪几种索引
  14. 20150409作业3 阅读《构建之法》1-5章
  15. C++ std::function怎么用
  16. 计算机分区格式转换,硬盘GPT分区与MBR分区如何转换
  17. 引用nbsp;TDA2030功放电路图
  18. BUUCTF[强网杯 2019]随便注 的三种解法
  19. WIN10安装VMware的管理员权限问题
  20. DropDownMenu下拉菜单

热门文章

  1. acrobat PDF删除部分_PDF原来可以这么玩
  2. IDEA破解补丁激活方式
  3. python中图片绘制和输出相关库的原理详解
  4. iOS 面试基础题目
  5. Android APP一段时间无操作显示屏保
  6. 脉冲响应不变法C语言程序,脉冲响应不变法-数字信号处理总结.ppt
  7. ubuntu安装和使用labellmg(含pyqt4的安装教程)
  8. 新年新故事 | Nice 兔 Meet U
  9. response.reset()
  10. 华为存储FusionStorage(备份②)