07 3D SLAM
7.1 多线激光雷达的工作原理
7.1.1 机械旋转式激光雷达
7.1.2 固态激光雷达
固态激光雷达的水平视野远小于机械旋转式激光雷达,通常在 120° 以内,垂直视野则和机械旋转式激光雷达相当。
7.2 多线激光雷达的扫描匹配
多线激光雷达的扫描匹配效果通常好于单线激光雷达,所以后端处理更简单。大多数多线激光雷达的SLAM系统都不使用子地图这样的概念,而是直接管理点云本身。点云配准主要以 Scan to Scan 和 Scan to Map 为主。
7.2.1 点到点 ICP
设需要配准的两个点云 S 1 = { p 1 , p 2 , . . . p m } S_1=\{\boldsymbol{p}_1, \boldsymbol{p}_2,...\boldsymbol{p}_m\} S1={p1,p2,...pm} 和 S 2 = { q 1 , q 2 , . . . q m } S_2=\{\boldsymbol{q}_1, \boldsymbol{q}_2,...\boldsymbol{q}_m\} S2={q1,q2,...qm}。若二者能够正确匹配,则对一组匹配点 p i ∈ S 1 , p j ∈ S 2 \boldsymbol{p}_i \in S_1,\boldsymbol{p}_j \in S_2 pi∈S1,pj∈S2,应该满足
p i = R q j + t \boldsymbol{p}_i = \boldsymbol{R}\boldsymbol{q}_j+\boldsymbol{t} pi=Rqj+t
ICP 算法的总体思路如下:
① 设初始位姿估计为 R 0 , t 0 \boldsymbol{R}_0,\boldsymbol{t}_0 R0,t0;
② 从初始位姿开始迭代,设第 k k k 次迭代时位姿估计为 R k , t k \boldsymbol{R}_k,\boldsymbol{t}_k Rk,tk;
③ 在位姿 R k , t k \boldsymbol{R}_k,\boldsymbol{t}_k Rk,tk 下,按最近邻方式寻找匹配点,记匹配后的点对为 ( p i , p j ) (\boldsymbol{p}_i ,\boldsymbol{p}_j) (pi,pj);
④ 计算本次迭代结果,求出最优 R k + 1 , t k + 1 \boldsymbol{R}_{k+1},\boldsymbol{t}_{k+1} Rk+1,tk+1;
R k + 1 , t k + 1 = arg min R , t ∥ p i − ( R q j + t ) ∥ 2 2 \boldsymbol{R}_{k+1},\boldsymbol{t}_{k+1}=\arg \min_{\boldsymbol{R},\boldsymbol{t}}\|\boldsymbol{p}_i -( \boldsymbol{R}\boldsymbol{q}_j+\boldsymbol{t})\|^2_2 Rk+1,tk+1=argR,tmin∥pi−(Rqj+t)∥22
⑤ 判断解是否收敛(误差值是否足够小),若不收敛,则返回第三步,否则结束。
7.2.2 点到线、点到面 ICP
和前面二维点到线 ICP 类似。在对某个 q i \boldsymbol{q}_i qi 进行变换后,并不是寻找一个最近邻,而是寻找一些最近邻,拟合成一条线或一个平面。
先考虑平面的情况,假设平面参数为 ( n , d ) ∈ R 4 (\boldsymbol{n}, d)\in \mathbb{R}^4 (n,d)∈R4,其中 n \boldsymbol{n} n 是单位法线向量, d d d 为截距。对于平面上某点 p \boldsymbol{p} p,满足
n ⊤ p + d = 0 \boldsymbol{n}^\top\boldsymbol{p}+d=0 n⊤p+d=0
而对于平面外的点,其与平面的垂直距离可表示为 n ⊤ p + d \boldsymbol{n}^\top\boldsymbol{p}+d n⊤p+d,于是建立误差函数
e i = n ⊤ ( R q i + t ) + d e_i=\boldsymbol{n}^\top(\boldsymbol{R}\boldsymbol{q}_i+\boldsymbol{t})+d ei=n⊤(Rqi+t)+d
( S 1 S_1 S1 中的点 q i \boldsymbol{q}_i qi 变换到 S 2 S_2 S2 中,寻找最近邻点并拟合平面,得到误差函数)
误差对 R , t \boldsymbol{R},\boldsymbol{t} R,t 的导数为
∂ e i ∂ R = − n ⊤ R q i ∧ , ∂ e ∂ t = n \frac{\partial e_i}{\partial R}=-n^\top R\boldsymbol{q}_i^\wedge,\quad\frac{\partial e}{\partial\boldsymbol{t}}=\boldsymbol{n} ∂R∂ei=−n⊤Rqi∧,∂t∂e=n
采用高斯-牛顿等方法不断优化迭代求出 R , t \boldsymbol{R},\boldsymbol{t} R,t 即可。
如果是直线,则可设直线方程(点向式)为
p = d τ + p 0 \boldsymbol{p}=\boldsymbol{d}\tau+\boldsymbol{p}_0 p=dτ+p0
其中, d \boldsymbol{d} d 是单位长度的方向矢量, p 0 \boldsymbol{p}_0 p0 是直线上一点, τ \tau τ 是参数。 对于不在直线上的某个点 q i \boldsymbol{q}_i qi,利用叉乘定义,将它到直线的垂直矢量作为误差函数,垂直矢量的长度即为垂直距离,
e i = d × ( R q i + t − p 0 ) \boldsymbol{e}_i=\boldsymbol{d}\times(\boldsymbol{R}\boldsymbol{q}_i+\boldsymbol{t}-\boldsymbol{p}_0) ei=d×(Rqi+t−p0)
误差对 R , t \boldsymbol{R},\boldsymbol{t} R,t 的导数为
∂ e i ∂ R = − d ∧ R q i ∧ , ∂ e i ∂ t = d ∧ \frac{\partial\boldsymbol{e}_i}{\partial\boldsymbol{R}}=-\boldsymbol{d}^\wedge\boldsymbol{R}\boldsymbol{q}_i^\wedge,\quad\frac{\partial\boldsymbol{e}_i}{\partial\boldsymbol{t}}=\boldsymbol{d}^\wedge ∂R∂ei=−d∧Rqi∧,∂t∂ei=d∧
高斯-牛顿法迭代求解。
7.2.3 NDT 方法
点到面 ICP 是对局部点进行平面拟合,点到线 ICP 是直线拟合。但是我们为什么要事先假定平面或直线呢?为什么要精确知道面和线参数呢?只需要得到这堆点云的局部统计信息(均值和方差),就可以进行匹配了。NDT的思路如下:
① 把目标点云( S 2 S_2 S2)按一定分辨率分成若干体素;
② 计算每个体素中的点云高斯分布。设第 k k k 个体素中的均值为 μ k \boldsymbol{\mu}_k μk,方差为 Σ k \boldsymbol{\Sigma}_k Σk;
③ 配准时,先计算每个点( S 1 S_1 S1)落在哪个体素( S 2 S_2 S2)中,然后建立该点与该体素的 μ k , Σ k \boldsymbol{\mu}_k,\boldsymbol{\Sigma}_k μk,Σk 构成的残差;
④ 用高斯-牛顿法或 L-M 法对估计位姿进行迭代,然后更新位姿。
关键在于第③步,记被配准点云中的某点 q i \boldsymbol{q}_i qi,经过 R 、 t \boldsymbol{R}、\boldsymbol{t} R、t 变换后,落在某个体素 i i i 中,记这个栅格中的残差为
e i = R q i + t − μ i \boldsymbol{e}_i=\boldsymbol{R}\boldsymbol{q}_i+\boldsymbol{t}-\boldsymbol{\mu}_i ei=Rqi+t−μi
最后的 R 、 t \boldsymbol{R}、\boldsymbol{t} R、t 由一个加权的最小二乘问题决定:
( R , t ) ∗ = arg min R , t ∑ i ( e i ⊤ Σ i − 1 e i ) . (\boldsymbol{R},\boldsymbol{t})^*=\arg\min_{\boldsymbol{R},\boldsymbol{t}}\sum_i(\boldsymbol{e}_i^\top\boldsymbol{\Sigma}_i^{-1}\boldsymbol{e}_i). (R,t)∗=argR,tmini∑(ei⊤Σi−1ei).
相当于最大化每个点落在所在栅格的概率分布,因此这是一个最大似然估计:
( R , t ) ∗ = arg max R , t ∏ i P ( R q i + t ) (\boldsymbol{R},\boldsymbol{t})^*=\arg\max_{R,\boldsymbol{t}}\prod_iP(R\boldsymbol{q}_i+\boldsymbol{t}) (R,t)∗=argR,tmaxi∏P(Rqi+t)
也就是说,既然目标栅格的点云符合某个统计形状,那么在正确的位姿估计下,落在其中的点也应当符合这个分布。
一个加权最小二乘问题的高斯牛顿解法如下:
∑ i ( J i ⊤ Σ i − 1 J i ) Δ x = − ∑ i J i ⊤ Σ i − 1 e i \sum_i(\boldsymbol{J}_i^\top\boldsymbol{\Sigma}_i^{-1}\boldsymbol{J}_i)\Delta x=-\sum_i\boldsymbol{J}_i^\top\boldsymbol{\Sigma}_i^{-1}\boldsymbol{e}_i i∑(Ji⊤Σi−1Ji)Δx=−i∑Ji⊤Σi−1ei
雅可比矩阵为
∂ e i ∂ R = − R q i ∧ , ∂ e i ∂ t = I \frac{\partial\boldsymbol{e}_i}{\partial\boldsymbol{R}}=-\boldsymbol{R}\boldsymbol{q}_i^\wedge,\quad\frac{\partial\boldsymbol{e}_i}{\partial\boldsymbol{t}}=\boldsymbol{I} ∂R∂ei=−Rqi∧,∂t∂ei=I
注: Σ \boldsymbol{\Sigma} Σ 是三维点的协方差矩阵,等于
Σ = [ σ ( x , x ) σ ( x , y ) σ ( x , z ) σ ( y , x ) σ ( y , y ) σ ( y , z ) σ ( z , x ) σ ( z , y ) σ ( z , z ) ] \boldsymbol{\Sigma}=\begin{bmatrix}\sigma(\boldsymbol{x},\boldsymbol{x})&\sigma(\boldsymbol{x},\boldsymbol{y})&\sigma\left(\boldsymbol{x},\boldsymbol{z}\right)\\\sigma(\boldsymbol{y},\boldsymbol{x})&\sigma(\boldsymbol{y},\boldsymbol{y})&\sigma\left(\boldsymbol{y},\boldsymbol{z}\right)\\\sigma\left(\boldsymbol{z},\boldsymbol{x}\right)&\sigma(\boldsymbol{z},\boldsymbol{y})&\sigma(\boldsymbol{z},\boldsymbol{z})\end{bmatrix} Σ= σ(x,x)σ(y,x)σ(z,x)σ(x,y)σ(y,y)σ(z,y)σ(x,z)σ(y,z)σ(z,z)
7.3 直接法激光雷达里程计
将多个点云配准、拼接在一起,形成局部地图,最终构建一个激光雷达里程计模块。最简单的配准方式是连续使用 Scan to Scan 方法,将下一帧数据与上一帧数据进行匹配。这种不需要提取特征点的激光雷达里程计被称为直接法激光雷达里程计。
7.3.1 使用 NDT 构建激光雷达里程计
7.3.2 增量式 NDT 里程计
不必把过去的点云拼接在一起形成局部地图,而是把配准好的点云更新到NDT 的每个体素内部,更新他们的高斯分布状态,再做下一步的配准。称这种思路为增量式的 NDT。这种情况下,不必重新构建 NDT 内部状态,也不必重新构建 Kd 树等数据结构,是一种相当快速的实现方式。(在第一帧基础上划分体素,然后不断更新、增加体素,故称为增量式)
两个关键:一是如何维护不断增加的体素,二是每个体素内的高斯参数应该如何改变。
- 高斯分布的增量更新
设某体素之前有 m m m 个历史点云,他们构成的高斯分布为 μ H , Σ H \boldsymbol{\mu}_{\rm{H}},\boldsymbol{\Sigma}_{\rm{H}} μH,ΣH,然后新增 n n n 个点,这 n n n 个点的均值和方差为 μ A , Σ A \boldsymbol{\mu}_{\rm{A}},\boldsymbol{\Sigma}_{\rm{A}} μA,ΣA。设合并后的估计为 μ , Σ \boldsymbol{\mu},\boldsymbol{\Sigma} μ,Σ。记历史点云中的点为 x 1 , . . . x m \boldsymbol{x}_1,...\boldsymbol{x}_m x1,...xm,新增点云为 y 1 , . . . y m \boldsymbol{y}_1,...\boldsymbol{y}_m y1,...ym。则有更新后的均值和协方差矩阵
μ
=
(
x
1
+
.
.
.
+
x
m
)
+
(
y
1
+
.
.
.
+
y
n
)
m
+
n
=
m
μ
H
+
n
μ
A
m
+
n
\boldsymbol{\mu}=\frac{(\boldsymbol{x}_1+...+\boldsymbol{x}_m)+(\boldsymbol{y}_1+...+\boldsymbol{y}_n)}{m+n}=\frac{m \boldsymbol{\mu}_{\rm{H}}+n\boldsymbol{\mu}_{\rm{A}}}{m+n}
μ=m+n(x1+...+xm)+(y1+...+yn)=m+nmμH+nμA
Σ
=
m
(
Σ
H
+
(
μ
H
−
μ
)
(
μ
H
−
μ
)
⊤
)
+
n
(
Σ
A
+
(
μ
A
−
μ
)
(
μ
A
−
μ
)
⊤
)
m
+
n
\boldsymbol{\Sigma}=\frac{m(\boldsymbol{\Sigma}_H+(\boldsymbol{\mu}_H-\boldsymbol{\mu})(\boldsymbol{\mu}_H-\boldsymbol{\mu})^\top)+n(\boldsymbol{\Sigma}_A+(\boldsymbol{\mu}_A-\boldsymbol{\mu})(\boldsymbol{\mu}_A-\boldsymbol{\mu})^\top)}{m+n}
Σ=m+nm(ΣH+(μH−μ)(μH−μ)⊤)+n(ΣA+(μA−μ)(μA−μ)⊤)
- 体素的增量维护
除了体素内部的高斯分布应该随点云更新以外,由于车辆往往从某个地点出发一直前行,体素本身也应该随着车辆运动而增加。然而,如果考虑长时间使用这个里程计算法,我们应该将体素数量限制在一定范围内。例如,我们希望体素总量保持在十万个左右,那些很多之前建立的体素应该定期删除。这需要我们维护一个近期使用的缓存机制)。我们会设置一个队列模型,把最近更新的体素放到最前面。当整个队列超出预期容量时,就删除最旧的那部分体素。
7.4 特征法激光雷达里程计
7.4.1 特征的提取
先提取特征点,再 对特征点做配准 的激光雷达里程计,称为特征法激光雷达里程计。
7.4.2 基于激光雷达线束的特征提取
从激光雷达中得到的点云,除了有 x , y , z x,y,z x,y,z 这样的位置,还有包括额外的信息:① 某个激光点来自哪一条扫描线,② 同一条线上的激光点的先后顺序关系。③ 有些驱动也会输出各点的极坐标角度、扫描时间等精确信息。
雷达是旋转扫描的,各点会先后形成一条扫描线。计算该扫描线在各点的 曲率,曲率小于某个值则认为是 平面点,否则认为是 角点。
7.4.4 特征法激光雷达里程计的实现
整个里程计的计算流程与之前的 NDT 类似,为角点和平面点分别构建两个局部地图,两者的 ICP 会放入同一个优化问题中。
需要注意的是,特征法里只是对原始点云进行简单特征提取,至于为什么要提取这些特征,为什么角点和平面点要应用不同的 ICP,仅仅是根据经验来设计的,
7.5 松耦合 LIO 系统
松耦合 LIO 系统中,IMU 和 轮速计为状态估计器提供惯性和速度方面的观测源,而雷达点云匹配结果(计算好的位姿)为系统提供位姿数据的观测源。
7.5.1 坐标系说明
由于引进了 IMU,先在有三个坐标系:世界坐标系(W)、IMU 坐标系(I)、雷达坐标系(L),记雷达到 IMU 的转换关系为 T I L \boldsymbol{T}_{\rm{IL}} TIL。由于 IMU 的运动模型都是在IMU坐标系下推导的,所以把点云都变换到 IMU 坐标系下,以 IMU 为中心来实现定位和建图效果。假设雷达扫描到某点 p L \boldsymbol{p}_{\rm{L}} pL,那么在 IMU 坐标系下,
p I = T I L p L \boldsymbol{p}_{\rm{I}}=\boldsymbol{T}_{\rm{IL}}\boldsymbol{p}_{\rm{L}} pI=TILpL