目前机器人使用中需要进行 SLAM 建图,因为移动机器人想要实现自主行走,核心在于实现自主定位导航,在自主定位导航技术中会涉及到定位、建图、路径规划等问题,而地图构建的好坏将直接影响机器人的行走路径。机器人想要到达某个目的地,需要和人类绘制地图一样,描述环境、认识环境的过程主要就是依靠地图。

 

而目前建图方式有激光雷达、视觉建图、还有深度学习等。今天介绍的 cartographer 就属于激光 slam。主流的激光 SLAM 算法有 hector、gmapping、karto、cartographer 等。

 

下面简单的介绍几种 SLAM 算法:

1.hector 是一种结合了鲁棒性较好的扫描匹方法 2D_SLAM 方法和使用惯性传感系统的导航技术。传感器的要求较高,高更新频率小测量噪声的激光扫描仪,不需要里程计。使空中无人机与地面小车在不平坦区域运行存在运用的可能性。作者利用现代激光雷达的高更新率和低距离测量噪声,通过扫描匹配实时地对机器人运动进行估计。所以当只有低更新率的激光传感器时,即便测距估计很精确,对该系统都会出现一定的问题。

 

hector 基于优化的算法(解最小二乘问题),优缺点:不需要里程计,但对于雷达帧率要求很高 40Hz,估计 6 自由度位姿,可以适应空中或者地面不平坦的情况。初值的选择对结果影响很大,所以要求雷达帧率较高。 

 

2.gmapping 是一种基于粒子滤波的激光 SLAM 算法,它已经集成在 ROS 中,是移动机器人中使用最多的 SLAM 算法。基于粒子滤波的算法用许多加权粒子表示路径的后验概率,每个粒子都给出一个重要性因子。但是,它们通常需要大量的粒子才能获得比较好的的结果,从而增加该算法的的计算复杂性。此外,与 PF 重采样过程相关的粒子退化耗尽问题也降低了算法的准确性。

 

缺点:严重依赖里程计,无法适应无人机及地面不平坦的区域,无回环(激光 SLAM 很难做回环检测),大的场景,粒子较多的情况下,特别消耗资源。

 

3.karto 是基于图优化的 SLAM 算法,用高度优化和非迭代 cholesky 矩阵进行稀疏系统解耦作为解。图优化方法利用图的均值表示地图,每个节点表示机器人轨迹的一个位置点和传感器测量数据集,箭头的指向的连接表示连续机器人位置点的运动,每个新节点加入,地图就会依据空间中的节点箭头的约束进行计算更新。路标 landmark 越多,内存需求越大,然而图优化方式相比其他方法在大环境下制图优势更大。

 

 karto 采取的是 spa(karto_slam)或 g2o(nav2d),karto 的前端与后端采取的是单线程进行。

 

4.LagoSLAM 是线性近似图优化,不需要初始假设。基本的图优化 slam 的方法就是利用最小化非线性非凸代价函数 . 每次迭代, 解决局部凸近似的初始问题来更新图配置,过程迭代一定次数直到局部最小代价函数达到 . (假设起始点经过多次迭代使得局部代价函数最小). 。假设图中每个节点的相对位置和方向都是独立的,作者求解了一个等价于非凸代价函数的方程组。为此,提出了一套基于图论的程序,通过线性定位和线性位置估计,得到非线性系统的一阶近似。

 

 5. cartographer 是 google 开发的实时室内 SLAM 项目,cartographer 采用基于 google 自家开发的 ceres 非线性优化的方法,cartographer 的亮点在于代码规范与工程化,非常适合于商业应用和再开发。并且 cartographer 基于 submap 子图构建全局地图的思想,能有效的避免建图过程中环境中移动物体的干扰。并且 cartographer 支持多传感器数据(odometry、IMU、LaserScan 等)建图,支持 2D_SLAM 和 3D_SLAM 建图。

 

能天然的输出协方差矩阵,后端优化的输入项。成本较低的雷达也能跑出不错的效果。cartographer 是 google 推出的一套基于图优化的 SLAM 算法。

 

cartographer 算法并没有给人惊艳的感觉,但该算法的主要目标是实现低计算资源消耗,达到实时 SLAM 的目的,所以很适合嵌入式端的使用。

 

这篇文章是介绍 cartographer 在 linuxPC 环境(Ubuntu16)下进行源码下载进行 demo 测试的教程,本文的前提条件是你的电脑里已经安装了 ROS 以下版本的任意一个:Noetic、Kinetic、Melodic。

 

算法分析

该算法主要分为两个部分,第一个部分称为 Local SLAM, 该部分通过一帧帧的 Laser Scan 建立并维护一系列的 Submap,而所谓的 submap 就是一系列的 Grid Map。当再有新的 Laser Scan 中会通过 Ceres Scan Matching 的方法将其插入到子图中的最佳位置。但是 submap 会产生误差累积的问题,因此,算法的第二个部分,称为 Global SLAM 的部分,就是通过 Loop Closure 来进行闭环检测,来消除累积误差:当一个 submap 构建完成,也就是不会再有新的 laser scan 插入到该 submap 时,算法会将该 submap 加入到闭环检测中。闭环检测的本质也是一个优化问题,该优化问题被表达成了一个 pixel-accurate match 的形式,解决优化问题的方法是 Branch-and-Bound Approach.

 

 

安装介绍

cartographer 的安装主要包括三个部分:cartographer、cartographer-ros、ceres-solver。其中 cartographer 是计算的部分,cartographer-ros 是算法在 ROS 中通讯交互数据的部分,ceres-solver 谷歌开发的一款用于非线性优化的库,在谷歌的开源激光雷达 slam 项目 cartographer 中被大量使用。

 

安装的方法有两种,一种是官网的集成式下载配置,一种是把 cartographer 需要的依赖部分分别安装配置。

 

两种方式区别就在于,第一种虽然方便,但是由于网络问题(你懂的)所以 Google 的相关文件下载会失败,所以就出现了,把依赖单独下载编译,最后下载 cartographer 进行编译。

 

官网方式:

1. 安装 wstool 下载工具、rosdep 和 ninja 编译工具(ninja 是一个新型的编译小工具,用来替换复杂的 make,从而实现快速编译)

 

sudo apt-get update
sudo apt-get install -y python-wstool python-rosdep ninja-build

 

2. 建立一个 wstool 下载+ROS 基本编译的二合一环境

mkdir catkin_wscd catkin_wswstool init srcwstool merge -t src https://raw.githubusercontent.com/googlecartographer/cartographer_ros/master/cartographer_ros.rosinstall

 

这是 wstool 命令生成 .rosinstall 的文件里面的内容,可以看到设置了 cartographer、cartographer-ros 下载链接。

 

 

wstool update -t src

 

静静等待下载,速度就取决你对于 Google 的认知。

 

3. 安装 proto3.

Protocol Buffers(简称 Protobuf) ,是 Google 出品的序列化框架,与开发语言无关,和平台无关,具有良好的可扩展性。Protobuf 和所有的序列化框架一样,都可以用于数据存储、通讯协议。

 

src/cartographer/scripts/install_proto3.sh

 

此外其实除了 Protobuf 我们还可以配置其他依赖,这些脚本都在这个目录,如果编译过程中遇到依赖问题就可以去利用脚本去下载。

 

 

4.rosdep init 在安装 ROS 时候就安装过了,不过这个经常会出现问题,我之前写过一篇 ROS 安装的文件,大家有兴趣可以去看看

对于这个问题,有两种解决思路:访问 DNS 解析环节解决或者直接切换软件源。

 

DNS 解析环节解决:

 

 

切换 linux 软件源:

 

 

sudo rosdep initrosdep updaterosdep install --from-paths src --ignore-src --rosdistro=${ROS_DISTRO} -y

 

5. 最后一步编译

catkin_make_isolated --install --use-ninjasource install_isolated/setup.bash

 

但是好多时候因为下载问题,就会出现这样那样的问题,所以就出现了下面的方法,把包单独下载,然后再进行编译安装。

 

注!:在我编译 cartographer 过程中,和文章所写这种一气呵成的感觉恰恰相反,我编译了好多次才编译成功的,而且中间出现各种编译问题,基本都是版本问题。所以请大家注意下载各个分包的版本,切记,切记,切记~

 

你看我 probuf 版本下载记录就知道了。

 

 

分包编译方式:

cartographer 分成 6 个部分,分别是 eigen3.2.9,ceres1.13.0,protobuf 大于 3.0.0,cartographer,cartogpher_ros,abseil。分开进行编译:

 

1.eigen

Eigen 是高级 C ++ 模板标头库,用于线性代数,矩阵和矢量运算,几何变换,数值求解器和相关算法。自 3.1.1 版以来,Eigen 是根据 Mozilla Public License 2.0 许可的开源软件。早期版本是根据 GNU 较宽松通用公共许可证授权的。

 

注意警告:cartographer 对 eigen,ceres,protobuf 有严格的版本限制,版本必须严格!!!

 

#选择版本 3.2.9git clone  https://gitlab.com/libeigen/eigen.gitmkdir buildcd buildcmake ..sudo make install

 

安装完成

 

2.ceres

Ceres solver 是谷歌开发的一款用于非线性优化的库,在谷歌的开源激光雷达 slam 项目 cartographer 中被大量使用。

 

注意:ceres 版本必须是 1.13.0,其它版本与 eigen3.2.9 不匹配

 

#选择版本 1.13.0git clone https://github.com/ceres-solver/ceres-solver.gitmkdir buildcd buildcmake ..make -j8sudo make install

 

编译过程中如果出现这个编译问题:

Failed to find glog

 

-- Failed to find installed glog CMake configuration, searching for glog build directories exported with CMake.

 

-- Failed to find an installed/exported CMake configuration for glog, will perform search for installed glog components.

 

-- Failed to find glog - Could not find glog include directory, set GLOG_INCLUDE_DIR to directory containing glog/logging.h

 

这个原因是缺失 glog 库(glog 是一个 C++ 日志库,它提供 C++ 流式风格的 API。在安装 glog 之前需要先安装 gflags,这样 glog 就可以使用 gflags 去解析命令行参数),我们可以用 apt-get install 安装,也可以下载源码进行编译安装 .

 

apt-get install 安装:

sudo apt-get install libgoogle-glog-dev

 

下载源码进行编译安装:

git clone https://github.com/google/glog.gitcd glogmkdir buildcmake ..makesudo make install

 

再重新进行 cere 编译安装,又通过一关

 

 

3. protobuf

Protocol Buffers(简称 Protobuf) ,是 Google 出品的序列化框架,与开发语言无关,和平台无关,具有良好的可扩展性。Protobuf 和所有的序列化框架一样,都可以用于数据存储、通讯协议。

 

注意:protobuf 安装方式特殊,脚本安装

 

选择版本 3.0.0git clone https://github.com/protocolbuffers/protobuf.git./autogen.sh

 

这次也会遇到 error 问题,

 

第一个 error48: autoreconf: not found

 

是在不同版本的 tslib 下执行 autogen.sh 产生。它们产生的原因一样,是因为没有安装 automake 工具,  用下面的命令安装好就可以了。

 

sudo apt-get install autoconf automake libtool

 

第二个 error 可能是下载问题,这边会提示你下载失败,你可以选择注释掉,或者使用我提供的第二种编译方法:

 

#如遇见 Error,prot:443,注释 autogen.sh 脚本 34 行./configuremake -j8sudo make installsudo ldconfig#测试一下 protobufprotoc --version#不出意外将会显示 libprotoc 3.0.0

第二种编译方法:

 

上文说到,我们在 cartographer/scripts 目录下可以找到 cartographer 依赖文件的下载的脚本,这些的脚本里面还有编译的选项,这时候我们就可以看下 install_proto3.sh 这个文件,里面可以看到如下内容:

 

mkdir buildcd buildcmake -G Ninja \  -DCMAKE_POSITION_INDEPENDENT_CODE=ON \  -DCMAKE_BUILD_TYPE=Release \  -Dprotobuf_BUILD_TESTS=OFF \  ../cmakeninjasudo ninja install

 

我们直接复制直接编译即可。

 

4.abseil

abseil 是 google 开源的 C++通用库,其目标是作为标准库的补充。abseil 不但提供了标准库没有但很常用的功能,也对标准库的一些功能进行了增强设计,使用 abseil 库能使程序性能和开发效率都取得不错的提升。

 

cartographer 对 abseil 没有版本要求,但是一定要有。

 

git clone https://github.com/abseil/abseil-cpp.gitmkdir buildcd buildcmake .. -DCMAKE_CXX_STANDARD=11make -j8sudo make install

 

不过在后续编译 abseil,大家可能会遇到这个问题

 

CMake Error at CMakeLists.txt:49 (find_package):

 

By not providing "FindAbseil.cmake" in CMAKE_MODULE_PATH this project has

 

asked CMake to find a package configuration file provided by "Abseil", but

 

CMake did not find one.

 

Could not find a package configuration file provided by "Abseil" with any

 

of the following names:

 

AbseilConfig.cmake

 

abseil-config.cmake

 

Add the installation prefix of "Abseil" to CMAKE_PREFIX_PATH or set

 

"Abseil_DIR" to a directory containing one of the above files.If "Abseil"

 

provides a separate development package or SDK, be sure it has been

installed.

 

 

不过没事,是因为 CMakeLists.txt 在进行搜寻 absil 中,定义的名称和你编译 abseil 名称不同,CMakeLists.txt 是大写的,而实际你编译安装后的包名称为小写。

 

 

修改如上所示:Abseil 修改为 absl 

 

5.carographer

注意:carographer 和 cartographer _ros 版本必须对应

 

mkdir cartographercd cartographer & mkdir srccd src
git clone https://github.com/cartographer-project/cartographer.gitgit clone https://github.com/cartographer-project/cartographer_ros.git
catkin_make_isolated   /*也可以用*/  catkin_make_isolated --install --use-ninja

 

编译成功:

 

 

建图开发

现在安装了 Cartographer 和 Cartographer 的 ROS 集成,官方也提供了一些数据集,Deutsches Museum(德意志博物馆),这样我就可以很方便测试 Cartographer 生成地图和其他的功能了。

 

下载示例包(例如德意志博物馆的 2D 和 3D 背包系列)到一个已知的位置

 

示例位于~/Downloads,并使用 roslaunch 来调出演示:

 

# Download the 2D backpack example bag.wget -P ~/Downloads https://storage.googleapis.com/cartographer-public-data/bags/backpack_2d/cartographer_paper_deutsches_museum.bag
# Launch the 2D backpack demo.roslaunch cartographer_ros demo_backpack_2d.launch bag_filename:=${HOME}/Downloads/cartographer_paper_deutsches_museum.bag# Download the 3D backpack example bag.wget -P ~/Downloads https://storage.googleapis.com/cartographer-public-data/bags/backpack_3d/with_intensities/b3-2016-04-05-14-14-00.bag# Launch the 3D backpack demo.roslaunch cartographer_ros demo_backpack_3d.launch bag_filename:=${HOME}/Downloads/b3-2016-04-05-14-14-00.bag

 

又会是下载的问题,这些文件又大,下载速度又慢还经常失败,我也是废了九牛二虎之力下载下来的。

 

 

为了方便大家测试,大家可以公众号后台私我,或者添加我微信号,我把我下载好的文件发给大家。

 

截图有限,之前操作都忘记截图了,导致现在就只有一个了,大家凑合看了哈。

 

 

生成 .pdstream 地图(等待直到 cartographer_offline_node 完成),

 

roslaunch cartographer_ros offline_backpack_2d.launch bag_filenames:=${HOME}/Downloads/cartographer_paper_deutsches_museum.bag

 

然后运行纯定位:

roslaunch cartographer_ros demo_backpack_2d_localization.launch  load_state_filename:=${HOME}/Download/cartographer_paper_deutsches_museum.bag.pbstream   bag_filename:=${HOME}/Downloads/cartographer_paper_deutsches_museum.bag

 

此外还有 turtlebot 的数据,其实都是一样的,大家也可以看一下创客智造的 cartographer_turtlebot 教程。

 

这就是我分享的 cartographer 的简单测试使用,未来我会介绍更加详细的 cartographer 使用以及源码解析。此外如果大家有什么更好的思路,也欢迎分享交流哈。