SLAM十四讲
预备知识
SLAM,Simultaneous Localization and Mapping,同时定位与地图构建。
- 搭载特定传感器的主体,在没有环境先验信息的情况下,于运动过程中建立环境模型,同时估计自己的运动
- 若传感器主要为相机,则称为视觉SLAM
初识 SLAM
视觉SLAM
单目相机
在单目相机中,无法通过单张图片计算场景中物体与相机之间的距离;
必须移动相机,才能估计运动,同时估计场景中物体的远近和大小——结构。
由于物体与相机之间的距离不同,当相机移动时,物体在图像上的运动形成视差,通过视差,能够定量地判断物体离得远,还是离得近
- 单目SLAM估计的轨迹和地图将与真实的轨迹和地图相差一个因子,即所谓的尺度。
- 由于单目SLAM无法仅凭图像确定真实尺度,所以又称为尺度不确定性。
- 平移之后才能计算深度
- 无法确定真实尺度
双目相机
使用双目相机和深度相机目的是,通过某种手段测量物体与相机之间的距离,克服单目相机的缺点。
双目相机已知两个相机之间的距离——基线,通过基线来估计每个像素的空间位置。
但双目相机视差的计算非常消耗计算资源,计算量是双目的主要问题之一。
RGB-D相机
通过红外结构光或Time-of-Flight(ToF)原理,主动向物体发射光并接收返回的光,测出物体与相机之间的距离。
但噪声大、视野小、易受日光干扰等,主要用于室内
经典视觉SLAM框架
还有传感器信息读取->回环检测->后端(非线性)优化
- 传感器信息读取——主要为相机图像信息的读取和预处理。
- 前端视觉里程计(Visual Odometry)——估算相邻图像间相机运动,以及局部地图的样子,VO又称为前端(Front End)
- 后端(非线性)优化(Optimization)——接收不同时刻视觉里程计测量的相机位姿,以及回环检测的信息,对它们进行优化,得到全局一致的轨迹和地图,接在VO之后,又称为后端(Back End)
- 回环检测(Loop Closure Detection)——判断机器人是否到达过先前的位置,若检测到回环,会把信息提供给后端进行处理
- 建图(Mapping)——根据估计的轨迹,建立与任务要求对应的地图
视觉里程计
为了定量地估计相机运动,必须了解相机与空间点的几何关系
视觉里程计能够通过相邻帧间的图像估计相机运动,并恢复场景的空间结构
- 只计算相邻时刻的运动,而和过去的信息没有关联
通过视觉里程计来估计轨迹,将出现累积漂移(Accumulating Drift)
因为视觉里程计在最简单的情况下只估计两个图像间的运动造成的
- 回环检测将"机器人回到原始点"情况检测出来
- 后端优化则根据该信息,校正整个轨迹的形状
后端优化
笼统的说,后端优化主要处理噪声问题。
后端优化要考虑的问题——如何从带有噪声的数据中估计整个系统的状态,以及这个状态估计的不确定性有多大
即最大后验概率估计(Maximum-a-Posteriori,MAP)——状态包括自身轨迹、地图。
前端给后端提供待优化的数据,以及这些数据的初始值。
后端负责优化过程,面对的只有数据
- 前端和计算机视觉更为相关,如图像特征提取与匹配等
- 后端主要是滤波与非线性优化算法
回环检测
主要解决位置估计随时间漂移的问题
实质上是一种计算图像数据相似性的算法
建图
地图大致可分为度量地图与拓扑地图。
度量地图
度量地图强调精确地表示地图中物体的位置关系,通常用稀疏与稠密分类。
- 稀疏地图是由路标组成的地图,而不是路标的部分可以忽略
- 稠密地图着重于建模所有看到的东西。
定位时用稀疏路标地图就足够了;而用于导航,则需要稠密地图。
拓扑地图
拓扑地图强调地图元素之间的关系,拓扑地图是一个图,由节点和边组成,只考虑节点间的连通性。
SLAM问题的数学表述
运动方程和观测方程
运动方程
x k = f ( x k − 1 , u k , w k ) x_k=f(x_{k-1},u_k,w_k) xk=f(xk−1,uk,wk)
- x k x_k xk——各时刻的位置
- u k u_k uk——运动传感器的读数或者输入
- w k w_k wk——过程中加入的噪声
观测方程
z k , j = h ( y j , x k , v k , j ) z_{k,j}=h(y_j,x_k,v_{k,j}) zk,j=h(yj,xk,vk,j)
- z k , j z_{k,j} zk,j——在 x k x_k xk时刻对 y j y_j yj路标点的观测数据
- v k , j v_{k,j} vk,j——观测里的噪声
知道运动测量的读数 u u u,以及传感器读数 z z z时,如何求解定位问题(估计 x x x),和建图问题(估计 y y y)
将SLAM问题建模为一个状态估计问题:通过带有噪声的测量数据,估计内部的、隐藏着的状态变量
按照运动和观测方程是否为线性,噪声是否服从高斯分布进行分类,分为线性/非线性和高斯/非高斯系统。
- 线性高斯系统(Linear Gaussian,LG)最简单,其无偏最优估计可以由卡尔曼滤波器(Kalman Filter,KF)给出
- 非线性非高斯系统(Non-Linear Non-Gaussian,NLNG),使用以扩展卡尔曼滤波器(Extended Kalman Filter,EKF)和非线性优化两大方法去求解。
在三维空间的运动由3个轴构成,机器人运动由3个轴上的平移,绕3个轴的旋转来描述,共6个自由度。
实践-Ubuntu系统
g++编译
g++ helloSLAM.cpp
——用编译器g++把.cpp
文件编译成可执行文件
./a.out
——运行编译出的可执行文件
使用cmake
用cmake命令生成一个makefile文件,再用make命令根据这个makefile文件的内容编译整个工程。
先执行cmake再执行make,执行cmake过程中处理了工程文件之间的关系,而执行make过程实际调用了g++来编译程序
cmake .
——在当前目录下进行cmake
cmake ..
——对上一层文件夹,即代码所在的文件夹进行编译
三维空间刚体运动
描述刚体在三维空间中的运动
旋转矩阵
点、向量和坐标系
刚体——位置+姿态
向量内积:
a
⋅
b
=
∑
i
=
1
3
a
i
b
i
=
∣
a
∣
∣
b
∣
cos
<
a
,
b
>
a·b=\sum_{i=1}^3{a_ib_i}=|a||b|\cos<a,b>
a⋅b=i=1∑3aibi=∣a∣∣b∣cos<a,b>
向量外积,即叉乘:
a
×
b
=
a
∧
b
=
∣
a
∣
∣
b
∣
sin
<
a
,
b
>
a×b=a{\wedge}b=|a||b|\sin<a,b>
a×b=a∧b=∣a∣∣b∣sin<a,b>
外积可用反对称矩阵表示
坐标系间的欧式变换
两个坐标系之间的运动由一个旋转和一个平移组成——刚体运动
欧式变换由旋转和平移组成。
旋转矩阵也称为方向余弦阵,实际上是各基向量夹角的余弦值
- 旋转矩阵是行列式为1的正交矩阵
- 反之,行列式为1的正交矩阵也为旋转矩阵
- 旋转矩阵的集合记为
SO(n)
——特殊正交群(Special Orthogonal Group)
旋转矩阵为正交矩阵,其转置描述了一个相反的旋转
a
=
R
a
′
a=Ra'
a=Ra′
a
′
=
R
−
1
a
=
R
T
a
a'=R^{-1}a=R^Ta
a′=R−1a=RTa
再考虑欧式变换中的平移,
a
′
=
R
a
+
t
a'=Ra+t
a′=Ra+t
记 R 12 R_{12} R12为把坐标系2的向量变换到坐标系1
从右读到左
对于平移 t 12 t_{12} t12——坐标系1原点指向坐标系2原点的向量,从1到2的向量
t 21 ≠ − t 12 t_{21}\neq-t_{12} t21=−t12——两个系之间存在旋转关系
故当问题为“我的坐标时”——应该是 t w c t_{wc} twc而非 t c w t_{cw} tcw