2019/08/08
第一讲是对本书内容的概述,第二讲是对SLAM的概述
全书的内容主要分为两个部分:
1. 第一部分为数学基础篇,我们会以浅显易懂的方式,铺垫与视觉 SLAM 相关的数学知识,包括:
这些就是我们所有的数学了,当然还有你以前学过的高等数学和线性代数。我保证它们看起来都不会很难——当然若你想进一步深入挖掘,我们会提供一些参考资料供你阅读,那些材料可能会比正文里讲的那些难一点。
2. 第二部分为 SLAM 技术篇。我们会使用第一部分所介绍的理论,讲述视觉 SLAM中各个模块的工作原理。
最后,如果你完全看不懂上面在说什么,恭喜你!这本书很适合你!加油!
本书所有源代码均托管到 github 上:https://github.com/gaoxiang12/slambook
SLAM中使用的相机,我们把相机分为单目(Monocular)、双目(Stereo)和深度相机(RGB-D)三个大类。此外, SLAM 中还有全景相机、 Event 相机等特殊或新兴的种类。虽然偶尔能看到它们在 SLAM 中的应用,不过到目前为止还没有成为主流。这三类相机的缺点:
我们把整个视觉 SLAM 流程分为以下几步:
这个框架本身,以及它所包含的算法已经基本定型,并且在许多视觉程序库和机器人程序库中已经提供。依靠这些算法,我们能够构建一个视觉 SLAM 系统,使之在正常的工作环境里实时进行定位与建图。因此,我们说, 如果把工作环境限定在静态、刚体,光照变化不明显、没有人为干扰的场景,那么,这个 SLAM 系统是相当成熟的了。
视觉里程计关心相邻图像之间的相机运动,最简单的情况当然是两张图像之间的运动关系。
VO 能够通过相邻帧间的图像估计相机运动,并恢复场景的空间结构。叫它为“里程计”是因为它和实际的里程计一样,只计算相邻时刻的运动,而和再往前的过去的信息没有关联。
假定我们已有了一个视觉里程计估计了两张图像间的相机运动。那么,只要把相邻时刻的运动“串”起来,就构成了机器人的运动轨迹,从而解决了定位问题。另一方面,我们根据每个时刻的相机位置,计算出各像素对应的空间点的位置,就得到了地图。
然而,仅通过视觉里程计来估计轨迹,将不可避免地出现累计漂移(Accumulating Drift)。这是由于视觉里程计(在最简单的情况下)只估计两个图像间运动造成的。每次估计都带有一定的误差,而由于里程计的工作方式,先前时刻的误差将会传递到下一时刻,导致经过一段时间之后,估计的轨迹将不再准确。
所谓的漂移(Drift),它将导致我们无法建立一致的地图。你会发现原本直的走廊变成了斜的,而原本 90 度的直角变成了歪的——这实在是一件很难令人忍受的事情!为了解决漂移问题,我们还需要两种技术: 后端优化和回环检测。回环检测负责把“机器人回到原始位置”的事情检测出来,而后端优化则根据该信息,校正整个轨迹的形状。
后端优化主要指处理 SLAM 过程中噪声的问题。
后端优化要考虑的问题,就是如何从这些带有噪声的数据中,估计整个系统的状态,以及这个状态估计的不确定性有多大——这称为最大后验概率估计(Maximum-a-Posteriori, MAP),这里的状态既包括机器人自身的轨迹,也包含地图。
在视觉 SLAM 中,前端和计算机视觉研究领域更为相关,比如图像的特征提取与匹配等,后端则主要是滤波与非线性优化算法。
回环检测,又称闭环检测(Loop Closure Detection),主要解决位置估计随时间漂移的问题。
为了实现回环检测,我们需要让机器人具有识别曾到达过的场景的能力。我们可以判断图像间的相似性,来完成回环检测。如果回环检测成功,可以显著地减小累积误差。所以视觉回环检测,实质上是一种计算图像数据相似性的算法。在检测到回环之后,我们会把“A 与 B 是同一个点”这样的信息告诉后端优化算法。然后,后端根据这些新的信息,把轨迹和地图调整到符合回环检测结果的样子。这样,如果我们有充分而且正确的回环检测,就可以消除累积误差,得到全局一致的轨迹和地图。
建图(Mapping)是指构建地图的过程。地图是对环境的描述,但这个描述并不是固定的,需要视 SLAM 的应用而定。
一组空间点的集合也可以称为地图,一个漂亮的 3D 模型亦是地图,一个标记着城市、村庄、铁路、河道的图片亦是地图。地图
的形式随 SLAM 的应用场合而定。大体上讲,它们可以分为度量地图与拓扑地图两种。
度量地图(Metric Map)
度量地图强调精确地表示地图中物体的位置关系,通常我们用稀疏(Sparse)与稠密(Dense)对它们进行分类。
对于定位来说,稀疏路标地图就足够了。而用于导航时,我们往往需要稠密的地图(否则撞上两个路标之间的墙怎么办?)。
稠密地图通常按照某种分辨率,由许多个小块组成。二维度量地图是许多个小格子(Grid),三维则是许多小方块(Voxel)。一般地,一个小块含有占据、空闲、未知三种状态,以表达该格内是否有物体。当我们查询某个空间位置时,地图能够给出该位置是否可以通过的信息。这样的地图可以用于各种导航算法,如 A*,D*‹等等,为机器人研究者们所重视。但是我们也看到,这种地图需要存储每一个格点的状态,耗费大量的存储空间,而且多数情况下地图的许多细节部分是无用的。另一方面,大规模度量地图有时会出现一致性问题。很小的一点转向误差,可能会导致两间屋子的墙出现重叠,使得地图失效。
拓扑地图(Topological Map)
相比于度量地图的精确性,拓扑地图则更强调地图元素之间的关系。
拓扑地图是一个图(Graph),由节点和边组成,只考虑节点间的连通性,例如 A, B 点是连通的,而不考虑如何从 A 点到达 B 点的过程。它放松了地图对精确位置的需要,去掉地图的细节问题,是一种更为紧凑的表达方式。然而,拓扑地图不擅长表达具有复杂结构的地图。如何对地图进行分割形成结点与边,又如何使用拓扑地图进行导航与路径规划,仍是有待研究的问题。
通过前面部分的介绍,对 SLAM 中各个模块的组成和主要功能有了直观上的理解。现在,要把它上升到理性层次——也就是用数学语言来描述 SLAM 过程。
假设机器人(携带着某种传感器)在未知环境里运动, 表示某个时刻,表示对应时刻机器人位置,它们构成了机器人的轨迹。
地图方面,设地图是由许多个路标(Landmark)组成的,而每个时刻,传感器会测量到一部分路标点,得到它们的观测数据。不妨设路标点一共有 N 个,用 表示它们。
在这样设定中,“机器人携带着传感器在环境中运动”,由如下两件事情描述:
运动方程公式——表示上一刻的位置与这一刻位置的关系:
其中:
是运动传感器读数(也叫输入),是噪声。这个公式被称为运动方程。
观测方程公式——机器人在 位置上看到某个路标点 ,产生了一个观测数据 ,用一个抽象的函数 h 来描述这个关系:
其中:
是观测噪声。
这两个方程描述了最基本的 SLAM 问题:知道运动测量的读数 u,以及传感器的读数 z 时,求解定位问题(估计 x)和建图问题(估计 y)。把 SLAM问题建模成了一个状态估计问题:如何通过带有噪声的测量数据,估计内部的、隐藏着的状态变量?
按照运动和观测方程是否为线性,噪声是否服从高斯分布进行分类,分为线性/非线性和高斯/非高斯系统。其中线性高斯系统(Linear Gaussian, LG 系统)是最简单的,它的无偏的最优估计可以由卡尔曼滤波器(Kalman Filter, KF)给出。而在复杂的非线性非高斯系统(Non-Linear Non-Gaussian, NLNG 系统)中,我们会使用以扩展卡尔曼滤波器(Extended Kalman Filter, EKF)和非线性优化两大类方法去求解它。
最早的实时视觉 SLAM 系统即是基于 EKF开发的。随后,为了克服 EKF 的缺点(例如线性化误差和噪声高斯分布假设),人们开始使用粒子滤波器(Particle Filter)等其他滤波器,乃至使用非线性优化的方法。时至今日,主流视觉 SLAM 使用以图优化(Graph Optimization)为代表的优化技术进行状态估计 。我们认为优化技术已经明显优于滤波器技术,只要计算资源允许,我们通常都偏向于使用优化方法(见第十、十一讲)。