深蓝学院从零开始手写VIO(四)——后端优化实践

深蓝学院从零开始手写VIO(四)——后端优化实践

  • 非线性最小二乘问题求解的优化方法
    • 使用舒尔补加速求解
    • 信息矩阵不满秩的处理方法
    • Solver的代码框架
  • 滑动窗口算法

声明:本专栏文章为深蓝学院《从零开始手写VIO》课程个人学习笔记,更多学习资源请咨询深蓝学院相关课程。

本节课为主要以VINS-Mono为例,讲解VIO后端优化中的一些实践trick。

非线性最小二乘问题求解的优化方法

根据前几讲的内容可知,最小二乘问题的求解往往可以归结为求解如下所示的正则方程(normal equation)过程:
J T Σ − 1 J Δ x = − J T Σ − 1 r Λ Δ x = − b \begin{aligned} \bm{J}^T\bm{\Sigma}^{-1}\bm{J}\Delta\bm{x}&=-\bm{J}^T\bm{\Sigma}^{-1}\bm{r}\\ \bm{\Lambda}\Delta\bm{x}&=-\bm{b} \end{aligned} JTΣ1JΔxΛΔx=JTΣ1r=b

显然在信息矩阵 Λ \bm{\Lambda} Λ满秩的情况下,上式的解为 Δ x = − Λ − 1 b \Delta\bm{x}=- \bm{\Lambda}^{-1}\bm{b} Δx=Λ1b。但在实际应用中,除了相机位姿外,滑动窗口还存在大量的路标点,这会使得 Λ \bm{\Lambda} Λ维数很大,而求解高维矩阵的逆会带来极大地计算负担,并不是我们所期望的。

使用舒尔补加速求解

我们知道信息矩阵 Λ \bm{\Lambda} Λ是一个稀疏矩阵,特别是对于主对角线上的分块矩阵, Λ a a \bm{\Lambda}_{aa} Λaa Λ b b \bm{\Lambda}_{bb} Λbb来说,二者是一个对角矩阵,而求解对角矩阵的逆是一件非常容易的事情。如下式所示,我们将优化变量 Δ x \Delta\bm{x} Δx分为位姿和路标点两部分:
[ Λ p p Λ p l Λ l p Λ l l ] [ Δ x p Δ x l ] = − [ Δ b p Δ b l ] \begin{bmatrix} \bm{\Lambda}_{pp} & \bm{\Lambda}_{pl}\\ \bm{\Lambda}_{lp} & \bm{\Lambda}_{ll}\\ \end{bmatrix}\left[\begin{array}{c}\Delta\bm{x}_p \\ \Delta\bm{x}_l\end{array}\right]=-\left[\begin{array}{c}\Delta\bm{b}_p \\ \Delta\bm{b}_l\end{array}\right] [ΛppΛlpΛplΛll][ΔxpΔxl]=[ΔbpΔbl]

随后对等式两边同时乘以矩阵 [ I − Λ p l Λ l l − 1 0 I ] \begin{bmatrix} \bm{I} & -\bm{\Lambda}_{pl}\bm{\Lambda}_{ll}^{-1}\\ \bm{0} & \bm{I} \end{bmatrix} [I0ΛplΛll1I]将其化简为下三角形式有:
[ Λ p p Λ p l Λ l p Λ l l ] [ Δ x p Δ x l ] = − [ Δ b p Δ b l ] [ I − Λ p l Λ l l − 1 0 I ] [ Λ p p Λ p l Λ l p Λ l l ] [ Δ x p Δ x l ] = − [ I − Λ p l Λ l l − 1 0 I ] [ Δ b p Δ b l ] [ Λ p p − Λ p l Λ l l − 1 Λ l p 0 Λ l p Λ l l ] [ Δ x p Δ x l ] = − [ Δ b p − Λ p l Λ l l − 1 Δ b l Δ b l ] \begin{aligned} \begin{bmatrix} \bm{\Lambda}_{pp} & \bm{\Lambda}_{pl}\\ \bm{\Lambda}_{lp} & \bm{\Lambda}_{ll}\\ \end{bmatrix}\left[\begin{array}{c}\Delta\bm{x}_p \\ \Delta\bm{x}_l\end{array}\right]&=-\left[\begin{array}{c}\Delta\bm{b}_p \\ \Delta\bm{b}_l\end{array}\right]\\ \begin{bmatrix} \bm{I} & -\bm{\Lambda}_{pl}\bm{\Lambda}_{ll}^{-1}\\ \bm{0} & \bm{I} \end{bmatrix}\begin{bmatrix} \bm{\Lambda}_{pp} & \bm{\Lambda}_{pl}\\ \bm{\Lambda}_{lp} & \bm{\Lambda}_{ll}\\ \end{bmatrix}\left[\begin{array}{c}\Delta\bm{x}_p \\ \Delta\bm{x}_l\end{array}\right]&=-\begin{bmatrix} \bm{I} & -\bm{\Lambda}_{pl}\bm{\Lambda}_{ll}^{-1}\\ \bm{0} & \bm{I} \end{bmatrix}\left[\begin{array}{c}\Delta\bm{b}_p \\ \Delta\bm{b}_l\end{array}\right]\\ \begin{bmatrix} \bm{\Lambda}_{pp} - \bm{\Lambda}_{pl}\bm{\Lambda}_{ll}^{-1}\bm{\Lambda}_{lp} & \bm{0}\\ \bm{\Lambda}_{lp} & \bm{\Lambda}_{ll}\\ \end{bmatrix}\left[\begin{array}{c}\Delta\bm{x}_p \\ \Delta\bm{x}_l\end{array}\right]&=-\left[\begin{array}{c}\Delta\bm{b}_p-\bm{\Lambda}_{pl}\bm{\Lambda}_{ll}^{-1}\Delta\bm{b}_l \\ \Delta\bm{b}_l\end{array}\right]\\ \end{aligned} [ΛppΛlpΛplΛll][ΔxpΔxl][I0ΛplΛll1I][ΛppΛlpΛplΛll][ΔxpΔxl][ΛppΛplΛll1ΛlpΛlp0Λll][ΔxpΔxl]=[ΔbpΔbl]=[I0ΛplΛll1I][ΔbpΔbl]=[ΔbpΛplΛll1ΔblΔbl]

可见 ( Λ p p − Λ p l Λ l l − 1 Λ l p ) Δ x p p = − ( Δ b p − Λ p l Λ l l − 1 Δ b l ) \left(\bm{\Lambda}_{pp} - \bm{\Lambda}_{pl}\bm{\Lambda}_{ll}^{-1}\bm{\Lambda}_{lp} \right)\Delta\bm{x}_{pp}=-(\Delta\bm{b}_p-\bm{\Lambda}_{pl}\bm{\Lambda}_{ll}^{-1}\Delta\bm{b}_l) (ΛppΛplΛll1Λlp)Δxpp=(ΔbpΛplΛll1Δbl),有了 Δ x p p \Delta\bm{x}_{pp} Δxpp之后可进一步通过求解 Λ l p δ x p p + Λ l l Δ x l l = Δ b l \bm{\Lambda}_{lp}\delta\bm{x}_{pp}+\bm{\Lambda}_{ll}\Delta\bm{x}_{ll}=\Delta\bm{b}_l Λlpδxpp+ΛllΔxll=Δbl得到 Δ x l l \Delta\bm{x}_{ll} Δxll。显然,在利用舒尔补对正则方程消元之后,我们只需要求解一个维数更小的线性方程组即可获得对应的解向量。

信息矩阵不满秩的处理方法

信息矩阵 Λ \bm{\Lambda} Λ可以是一个非常理想的情况,实际上,在大多数应用中,信息矩阵 Λ \bm{\Lambda} Λ并不满秩(例如前面提到过的单目vSLAM具有7个自由度,单目VIO具有4个自由度)。针对这一问题,可以有如下几种处理方法:

  • 使用LM求解:由于LM求解过程中会对信息矩阵 Λ \bm{\Lambda} Λ添加阻尼项 λ I \lambda\bm{I} λI,添加之后的信息矩阵必定是满秩的(零行的对角线位置都加上了 λ \lambda λ)。该方法虽然能够保证正则方程有解,但解可能会向零空间便宜(这里具体原因涉及现行代数求解的一些知识,暂时还不太理解)。
  • 添加先验约束:信息矩阵 Λ \bm{\Lambda} Λ不满秩的根本原因在于整个系统求解的初值不确定,因此如果将状态量的初值固定住,就可以有效约束系统的不确定性。常用的方法包括:1)对信息矩阵中的 Λ 11 \bm{\Lambda}_{11} Λ11添加单位矩阵 I \bm{I} I;2)强行将 Λ 11 \bm{\Lambda}_{11} Λ11认为设定为极大值(例如 1 0 15 10^{15} 1015);3) 将Jacobian矩阵中对应的项 J 11 \bm{J}_{11} J11设为零。(上述三种方法的本质都是使得初值对应的 Δ x 0 = 0 \Delta\bm{x}_0=\bm{0} Δx0=0,从而固定初值。
  • 固定位姿:将起始相机位姿设为基准位姿,使用下一个帧间位姿(或特征点)固定尺度。

Solver的代码框架

采用类似g2o的图优化方式,使用定点存储优化变量,使用边存储误差函数。

滑动窗口算法

Λ = Λ p + J a T Σ a − 1 J a b = b p + J a T Σ a − 1 r \begin{aligned} \bm{\Lambda}&=\bm{\Lambda}_p+\bm{J}_a^T\bm{\Sigma}^{-1}_a\bm{J}_a\\ \bm{b}&=\bm{b}_p+\bm{J}^T_a\bm{\Sigma}^{-1}_a\bm{r} \end{aligned} Λb=Λp+JaTΣa1Ja=bp+JaTΣa1r

回顾上一讲中如上式所示的滑窗边缘化过程。由于在边缘化之后,包含边缘化变量的残差函数 r ( x m , x r ) \bm{r}(\bm{x}_m,\bm{x}_r) r(xm,xr)已经被丢弃,其对应的Jacobian矩阵 J p \bm{J}_p Jp将保持不变,相应的先验信息矩阵( Λ p = J T Σ − 1 J \bm{\Lambda}_p=\bm{J}^T\bm{\Sigma}^{-1}\bm{J} Λp=JTΣ1J)也将保持不变。同时,为了避免解的零空间漂移,我们需要限定 J a T Σ a − 1 J a \bm{J}_a^T\bm{\Sigma}^{-1}_a\bm{J}_a JaTΣa1Ja保持和 Λ p \bm{\Lambda}_p Λp处于同样的线性化点。

但对于先验残差来说,虽然 J p \bm{J}_p Jp仍然保持不变,但保留下的各变量残差 r ( x r , x r ) \bm{r}(\bm{x}_r,\bm{x}_r) r(xr,xr)将随着迭代过程的变化继续变化,此时若先验残差 b p \bm{b}_p bp仍然表示在原线性化点时的估计残差,同样会使得解空间出现漂移。但由于残差 b p \bm{b}_p bp表示的是当前的估计值,我们不能固定其不变(否则待求解变量一直在原地踏步,就失去意义了),因此我们需要使得先验残差跟随当前的估计值进行变化。常用的方法为对其进行一阶泰勒近似:
b p ′ = b p + ∂ b p ∂ x r Δ x r = b p − Λ p Δ x r \bm{b}_p'=\bm{b}_p+\frac{\partial\bm{b}_p}{\partial\bm{x}_r}\Delta\bm{x}_r=\bm{b}_p-\bm{\Lambda}_p\Delta\bm{x}_r bp=bp+xrbpΔxr=bpΛpΔxr

你可能感兴趣的:(从零开始手写VIO)