从零开始手写Cartographer(1): 开端
阅读原文时间:2023年07月08日阅读:1

写在前面的话

我做SLAM已经三年了。读书时初学SLAM,一开始无从下手,直到读了高博士的博客,茅塞顿开,渐入佳境。后来又买了他的《视觉SLAM十四讲》,常伴手边,直至毕业。几个月前找工作的时候,他是我的面试官,与之交谈,如沐春风。那时候我就萌生出一个念头,希望追随博士的脚步,把这些年的经验和心得分享给后来人,所谓“人人为我、我为人人”,应该就是如此吧。 -- 2022.04.16

激光SLAM与Cartographer

我的水平远不及博士,只好挑自己擅长的东西说起。Cartographer是谷歌2015年发布的激光SLAM开源项目,功能完善,逻辑清晰,在学术和工程上都很具代表性。我做相关的工作已经两年了,论文和代码都读过一遍,也尝试做了一些优化和扩展,所以就拿它来做分享。

Cartographer本身是一个浩大的工程,并不利于初学者学习。本文希望根据它的设计思路,从零开始构建一个简易的2D激光SLAM工程。参考资料:

这里放出一张官方的动图:

SLAM之我见

这里先说说什么是SLAM:SLAM译作同时定位与地图构建,被认为是实现真正全自主移动机器人的关键。我记得这是我硕士论文的第一句,听着确实有掉书袋的嫌疑,也确实费耳朵。从我工作经验来讲,SLAM问题姑且可以等同于:如何通过整合局部观测来建立全局地图。

激光SLAM的观测是点云,每帧点云都是对环境的局部观测;而激光SLAM的目的就是用各时刻的点云拼成全局地图。这个过程如同拼图一样:

当然,以上是我对于“基于图优化的SLAM方法”做的理解,自然有偏颇之处。这里建议初学者不必拘泥于具体概念,相信有一定项目基础后会有更深的体会。

让我们开始吧!

开发环境:Linux,推荐Ubuntu。

其实如果我们的代码是纯C++且不依赖于第三方库,那么无论何种平台(Windows/Linux/MacOS)都可以编译运行。但实际上我们经常会用到仅支持Linux的第三方库,所以我们不得不用Linux。

实际上,Linux也是非常基本的开发环境,而ubuntu是最知名的Linux发行版,有了问题也容易找到资料。如果手头没有Linux环境,可以用WSL或云服务器,这里不再详述。

对于一个崭新的ubuntu环境来说,我们通常需要安装一些基本的工具来编译:

# gcc等基本编译套件
sudo apt install build-essential
# cmake
sudo apt install cmake

然后我们创建工程目录,姑且称之为slam。然后创建src目录存放代码,build目录存放编译产物:

sudo mkdir slam slam/src slam/build

我们在src目录中写一个最简单的C++程序,保存为hello.cc:

#include <iostream>

int main() {
  std::cout << "hello, slam!" << std::endl;
  return 0;
}

这里我们用了Google Style作为工程规范。

我们使用cmake来编译我们的工程。需要在slam下写一个CMakeLists.txt:

# 指定最低版本
cmake_minimum_required(VERSION 2.8)
# 指定项目名
project(slam)
# 用src/hello.cc产生一个名为hello的可执行项目
add_executable(hello src/hello.cc)

此时路径树应该是这样的:

slam\
 |---src\
 |    |--- hello.cc
 |
 |---build\
 |
 |---CMakeLists.txt

我们进入build目录,执行编译:

cd build
cmake ..
make

此时会在build下产生hello可执行文件,可以执行它:

./hello

此时如果输出"hello, slam!"字样,说明成功了。

到此为止,我们有了一个好的开始。下节我们讲述一些激光SLAM的基础概念,并做工程实现。


以上工程可以参考我的github(https://github.com/ysklab/cartographer-from-scratch)仓库,需要手动checkout到指定commit。本节的commit信息为:

start with "hello slam"

这里假设读者具备基本的git操作知识,包括clone、log、checkout等。