激光SLAM总结——Fast LIO / Fast LIO2 / Faster LIO

news2024/11/24 4:20:28

激光SLAM总结——Fast LIO / Fast LIO2 / Faster LIO

在之前的工作中有接触过LOAM,最近在工作中又接触到Faster LIO相关的工作,于是想着对Fast LIO / Fast LIO2 / Faster LIO这一系列工作进行一个简单的总结,以加深自己对激光SLAM算法的理解,之前总结过的一些和激光SLAM算法相关的博客还有,感兴趣的同学可以一起学习讨论:
激光SLAM总结——VLOAM / LIMO算法解析
激光SLAM总结——LIO-Mapping / LIOM / LINS / LIO-SAM算法解析

1. Fast LIO

FAST LIO是2021年提出的一个激光和IMU紧耦合迭代卡尔曼滤波框架,论文的贡献主要是提供了一个新的卡尔曼增益计算公式,新公式不依赖于测量维度,仅依赖于状态维度,从而达到高效的计算

Fast LIO是基于LINS进行进一步优化,那么LINS有什么问题呢?LINS是紧耦合框架,点云构建的残差被直接写入了观测方程,点云残差构建如下: f i ( x b k + 1 b k ) = { ∣ ( p ^ i l k − p a l k ) × ( p ^ i l k − p b I k ) ∣ ∣ p a l k − p b l k ∣  if  p i l k + 1 ∈ F e ∣ ( p ^ i k − p a l ) T ( ( p a k − p b k ) × ( p a l − p c l ) ) ∣ ∣ ( p a l k − p b l k ) × ( p a l k − p c l c ) ∣  if  p i l k + 1 ∈ F p f_{i}\left(\mathbf{x}_{b_{k+1}}^{b_{k}}\right)=\left\{\begin{array}{cl} \frac{\left|\left(\hat{\mathbf{p}}_{i}^{l_{k}}-\mathbf{p}_{a}^{l_{k}}\right) \times\left(\hat{\mathbf{p}}_{i}^{l_{k}}-\mathbf{p}_{b}^{I_{k}}\right)\right|}{\left|\mathbf{p}_{a}^{l_{k}}-\mathbf{p}_{b}^{l_{k}}\right|} & \text { if } \mathbf{p}_{i}^{l_{k+1}} \in \mathbb{F}_{e} \\ \frac{\left|\left(\hat{\mathbf{p}}_{i}^{k}-\mathbf{p}_{a}^{l}\right)^{T}\left(\left(\mathbf{p}_{a}^{k}-\mathbf{p}_{b}^{k}\right) \times\left(\mathbf{p}_{a}^{l}-\mathbf{p}_{c}^{l}\right)\right)\right|}{\left|\left(\mathbf{p}_{a}^{l_{k}}-\mathbf{p}_{b}^{l_{k}}\right) \times\left(\mathbf{p}_{a}^{l_{k}}-\mathbf{p}_{c}^{l_{c}}\right)\right|} & \text { if } \mathbf{p}_{i}^{l_{k+1}} \in \mathbb{F}_{p} \end{array}\right. fi(xbk+1bk)= palkpblk (p^ilkpalk)×(p^ilkpbIk) (palkpblk)×(palkpclc) (p^ikpal)T((pakpbk)×(palpcl))  if pilk+1Fe if pilk+1Fp残差的维度和点的数量相关,假设残差的维度为 m m m,在计算卡尔曼增益过程中会计算残差相对状态变量的线性化矩阵 H k \mathbf{H}_{k} Hk,其维度为 m × n m \times n m×n,其中 n n n为状态变量维度,进而计算 H k P k H k T + V \mathbf{H}_{k}\mathbf{P}_{k}\mathbf{H}_{k}^T+\mathbf{V} HkPkHkT+V时维度将变为 m × m m \times m m×m,在计算卡尔曼增益的过程中是需要对该矩阵进行求逆,可以预见当用于计算残差的特征点数量特别大时,计算卡尔曼增益也会变得相对耗时,在Fast-LIO就是通过SMW恒等式解决了该问题,使得计算卡尔曼增益不再依赖于观测维度,下面我们进一步看看具体是怎么做的

1.1 总体框架

Fast LIO的总体框架如下图所示:
在这里插入图片描述
大致流程是将激光雷达输入到特征提取模块,可获得平面和边缘特征,将提取后的特征和IMU测量值进行状态估计,输出 10 H Z 10HZ 10HZ 50 H Z 50HZ 50HZ的状态估计结果,并根据状态估计结果将特征点注册到全局地图。

1.2 Iterated Kalman Filter

下面进行Fast LIO的公式推导:

假设IMU系为Body系,激光系到IMU系为刚体变换 I T L = ( I R L , I p L ) { }^I \mathbf{T}_L=\left({ }^I \mathbf{R}_L,{ }^I \mathbf{p}_L\right) ITL=(IRL,IpL)

IMU的连续运动学方程为: G p ˙ I = G v I , G v ˙ I = G R I ( a m − b a − n a ) + G g , G g ˙ = 0 G R ˙ I = G R I ∣ ω m − b ω − n ω ⌋ Λ , b ˙ ω = n b ω , b ˙ a = n b a \begin{aligned}{ }^G \dot{\mathbf{p}}_I & ={ }^G \mathbf{v}_I,{ }^G \dot{\mathbf{v}}_I={ }^G \mathbf{R}_I\left(\mathbf{a}_m-\mathbf{b}_{\mathrm{a}}-\mathbf{n}_{\mathrm{a}}\right)+{ }^G \mathbf{g},{ }^G \dot{\mathrm{g}}=\mathbf{0} \\ { }^G \dot{\mathbf{R}}_I & \left.={ }^G \mathbf{R}_I \mid \boldsymbol{\omega}_m-\mathbf{b}_{\boldsymbol{\omega}}-\mathbf{n}_\omega\right\rfloor \Lambda, \dot{\mathbf{b}}_{\boldsymbol{\omega}}=\mathbf{n}_{\mathbf{b} \boldsymbol{\omega}}, \dot{\mathbf{b}}_{\mathbf{a}}=\mathbf{n}_{\mathbf{b a}}\end{aligned} Gp˙IGR˙I=GvI,Gv˙I=GRI(ambana)+Gg,Gg˙=0=GRIωmbωnωΛ,b˙ω=nbω,b˙a=nba其中 G p I { }^G \mathbf{p}_I GpI G R I { }^G \mathbf{R}_I GRI是IMU的位置和姿态, a m \mathbf{a}_m am ω m \boldsymbol{\omega}_m ωm为IMU的测量, b a \mathbf{b}_{\mathbf{a}} ba b ω \mathbf{b}_\omega bω为随机游走高斯噪声

IMU的离散运动学方程为 x i + 1 = x i ⊞ ( Δ t f ( x i , u i , w i ) ) \mathbf{x}_{i+1}=\mathbf{x}_i \boxplus\left(\Delta t \mathbf{f}\left(\mathbf{x}_i, \mathbf{u}_i, \mathbf{w}_i\right)\right) xi+1=xi(Δtf(xi,ui,wi))其中: x ≐ [ G R I T G p I T G v I T b ω T b a T G g T ] T ∈ M \mathbf{x} \doteq\left[\begin{array}{llllll} { }^G \mathbf{R}_I^T & { }^G \mathbf{p}_I^T & { }^G \mathbf{v}_I^T & \mathbf{b}_{\boldsymbol{\omega}}^T & \mathbf{b}_{\mathbf{a}}^T & { }^G \mathbf{g}^T \end{array}\right]^T \in \mathcal{M} x[GRITGpITGvITbωTbaTGgT]TM u ≐ [ ω m T a m T ] T \mathbf{u} \doteq\left[\begin{array}{ll} \boldsymbol{\omega}_m^T & \mathbf{a}_m^T \end{array}\right]^T u[ωmTamT]T w ≐ [ n ω T n a T n b ω T n b a T ] T \mathbf{w} \doteq\left[\begin{array}{llll} \mathbf{n}_\omega^T & \mathbf{n}_{\mathrm{a}}^T & \mathbf{n}_{\mathrm{b} \boldsymbol{\omega}}^T & \mathbf{n}_{\mathrm{ba}}^T \end{array}\right]^T w[nωTnaTnbωTnbaT]T f ( x i , u i , w i ) = [ ω m i − b ω i − n ω i G v I i G R I i ( a m i − b a i − n a i ) + G g i n b ω i n b a i 0 3 × 1 ] \mathbf{f}\left(\mathbf{x}_i, \mathbf{u}_i, \mathbf{w}_i\right)=\left[\begin{array}{c} \boldsymbol{\omega}_{m_i}-\mathbf{b}_{\omega_i}-\mathbf{n}_{\omega_i} \\ { }^G \mathbf{v}_{I_i} \\ { }^G \mathbf{R}_{I_i}\left(\mathbf{a}_{m_i}-\mathbf{b}_{\mathbf{a}_i}-\mathbf{n}_{\mathbf{a}_i}\right)+{ }^G \mathbf{g}_i \\ \mathbf{n}_{\mathbf{b} \omega_i} \\ \mathbf{n}_{\mathbf{b a}_i} \\ \mathbf{0}_{3 \times 1} \end{array}\right] f(xi,ui,wi)= ωmibωinωiGvIiGRIi(amibainai)+Gginbωinbai03×1

下面迭代扩展卡尔曼滤波进行状态估计,定义误差状态如下: x ~ k − 1 ≐ x k − 1 ⊟ x ‾ k − 1 = [ δ θ T G p ~ I T G v ~ I T b ~ ω T b ~ a T G g ~ T ] T \widetilde{\mathbf{x}}_{k-1} \doteq \mathbf{x}_{k-1} \boxminus \overline{\mathbf{x}}_{k-1}=\left[\begin{array}{llllll} \delta \boldsymbol{\theta}^T & G \widetilde{\mathbf{p}}_I^T & G \widetilde{\mathbf{v}}_I^T & \tilde{\mathbf{b}}_{\boldsymbol{\omega}}^T & \tilde{\mathbf{b}}_{\mathbf{a}}^T & { }^G \widetilde{\mathbf{g}}^T \end{array}\right]^T x k1xk1xk1=[δθTGp ITGv ITb~ωTb~aTGg T]T其中, x k − 1 \mathbf{x}_{k-1} xk1为真实状态, ⊟ x ‾ k − 1 \boxminus \overline{\mathbf{x}}_{k-1} xk1为标称状态, x ~ k − 1 \widetilde{\mathbf{x}}_{k-1} x k1为误差状态

前向传播流程如下: x ^ i + 1 = x ^ i ⊞ ( Δ t f ( x ^ i , u i , 0 ) ) ; x ^ 0 = x ‾ k − 1 .  \widehat{\mathbf{x}}_{i+1}=\widehat{\mathbf{x}}_i \boxplus\left(\Delta t \mathbf{f}\left(\widehat{\mathbf{x}}_i, \mathbf{u}_i, \mathbf{0}\right)\right) ; \widehat{\mathbf{x}}_0=\overline{\mathbf{x}}_{k-1} \text {. } x i+1=x i(Δtf(x i,ui,0));x 0=xk1其中上述计算的是标称状态的传播,计算过程中不考虑的噪声,状态的协方差通过误差状态进行传播,并吸纳这部分噪声,如下,误差状态定位如下:: x ~ i + 1 = x i + 1 ⊟ x ^ i + 1 = ( x i ⊞ Δ t f ( x i , u i , w i ) ) ⊟ ( x ^ i ⊞ Δ t f ( x ^ i , u i , 0 ) ) ≃ ( 23 ) F x ~ x ~ i + F w w i . \begin{aligned} \widetilde{\mathbf{x}}_{i+1} & =\mathbf{x}_{i+1} \boxminus \widehat{\mathbf{x}}_{i+1} \\ & =\left(\mathbf{x}_i \boxplus \Delta t \mathbf{f}\left(\mathbf{x}_i, \mathbf{u}_i, \mathbf{w}_i\right)\right) \boxminus\left(\widehat{\mathbf{x}}_i \boxplus \Delta t \mathbf{f}\left(\widehat{\mathbf{x}}_i, \mathbf{u}_i, \mathbf{0}\right)\right) \\ & \stackrel{(23)}{\simeq} \mathbf{F}_{\tilde{\mathbf{x}}} \widetilde{\mathbf{x}}_i+\mathbf{F}_{\mathbf{w}} \mathbf{w}_i . \end{aligned} x i+1=xi+1x i+1=(xiΔtf(xi,ui,wi))(x iΔtf(x i,ui,0))(23)Fx~x i+Fwwi.其中: F x ‾ = [ Exp ⁡ ( − ω ^ i Δ t ) 0 0 − A ( ω ^ i Δ t ) T Δ t 0 0 0 I I Δ t 0 0 0 − G R ^ I i ⌊ a ^ i ] ∧ Δ t 0 I 0 − G R ^ I i Δ t I Δ t 0 0 0 I 0 0 0 0 0 0 I 0 0 0 0 0 0 I ] \mathbf{F}_{\overline{\mathbf{x}}}=\left[\begin{array}{cccccc} \operatorname{Exp}\left(-\widehat{\boldsymbol{\omega}}_i \Delta t\right) & \mathbf{0} & \mathbf{0} & -\mathbf{A}\left(\widehat{\boldsymbol{\omega}}_i \Delta t\right)^T \Delta t & \mathbf{0} & \mathbf{0} \\ \mathbf{0} & \mathbf{I} & \mathbf{I} \Delta t & \mathbf{0} & \mathbf{0} & \mathbf{0} \\ -{ }^G \widehat{\mathbf{R}}_{I_i}\left\lfloor\widehat{\mathbf{a}}_i\right]_{\wedge} \Delta t & \mathbf{0} & \mathbf{I} & \mathbf{0} & -{ }^G \widehat{\mathbf{R}}_{I_i} \Delta t & \mathbf{I} \Delta t \\ \mathbf{0} & \mathbf{0} & \mathbf{0} & \mathbf{I} & \mathbf{0} & \mathbf{0} \\ \mathbf{0} & \mathbf{0} & \mathbf{0} & \mathbf{0} & \mathbf{I} & \mathbf{0} \\ \mathbf{0} & \mathbf{0} & \mathbf{0} & \mathbf{0} & \mathbf{0} & \mathbf{I} \end{array}\right] Fx= Exp(ω iΔt)0GR Iia i]Δt0000I00000IΔtI000A(ω iΔt)TΔt00I0000GR IiΔt0I000IΔt00I F w = [ − A ( ω ^ i Δ t ) T Δ t 0 0 0 0 0 0 0 0 − G R ^ I i Δ t 0 0 0 0 I Δ t 0 0 0 0 I Δ t 0 0 0 0 ] \mathbf{F}_{\mathbf{w}}=\left[\begin{array}{cccc} -\mathbf{A}\left(\widehat{\boldsymbol{\omega}}_i \Delta t\right)^T \Delta t & \mathbf{0} & \mathbf{0} & \mathbf{0} \\ \mathbf{0} & \mathbf{0} & \mathbf{0} & \mathbf{0} \\ \mathbf{0} & -{ }^G \widehat{\mathbf{R}}_{I_i} \Delta t & \mathbf{0} & \mathbf{0} \\ \mathbf{0} & \mathbf{0} & \mathbf{I} \Delta t & \mathbf{0} \\ \mathbf{0} & \mathbf{0} & \mathbf{0} & \mathbf{I} \Delta t \\ \mathbf{0} & \mathbf{0} & \mathbf{0} & \mathbf{0} \end{array}\right] Fw= A(ω iΔt)TΔt0000000GR IiΔt000000IΔt000000IΔt0 那么协方差前向传播公式为: P ^ i + 1 = F x ‾ P ^ i F x ‾ T + F w Q F w T ; P ^ 0 = P ‾ k − 1 \widehat{\mathbf{P}}_{i+1}=\mathbf{F}_{\overline{\mathbf{x}}} \widehat{\mathbf{P}}_i \mathbf{F}_{\overline{\mathbf{x}}}^T+\mathbf{F}_{\mathbf{w}} \mathbf{Q} \mathbf{F}_{\mathbf{w}}^T ; \widehat{\mathbf{P}}_0=\overline{\mathbf{P}}_{k-1} P i+1=FxP iFxT+FwQFwT;P 0=Pk1在完成IMU前向传播后,一方面会根据前向传播的结果对激光点云去运动畸变,另一方面会使用激光点云计算残差构建观测方程。

Fast LIO中使用的是点到面的残差,残差 z j κ \mathbf{z}_j^\kappa zjκ计算如下: G p ^ f j κ = G T ^ I k κ I T L L k p f j ; j = 1 , ⋯   , m . { }^G \widehat{\mathbf{p}}_{f_j}^\kappa={ }^G \widehat{\mathbf{T}}_{I_k}^\kappa{ }^I \mathbf{T}_L{ }^{L_k} \mathbf{p}_{f_j} ; j=1, \cdots, m . Gp fjκ=GT IkκITLLkpfj;j=1,,m. z j κ = G j ( G p ^ f j κ − G q j ) \mathbf{z}_j^\kappa=\mathbf{G}_j\left({ }^G \widehat{\mathbf{p}}_{f_j}^\kappa-{ }^G \mathbf{q}_j\right) zjκ=Gj(Gp fjκGqj)其中 κ \kappa κ为迭代卡尔曼滤波中的迭代次数。为了将残差 z j κ \mathbf{z}_j^\kappa zjκ直接加入滤波过程,因此需要对残差进行线性化,线性化过程如下,如果将点云测量过程中的噪声移除的话,测量方程如下: 0 = h j ( x k L j n f j ) = G j ( G T I k I k T ˇ I j I T L ( L j p f j − L j n f j ) − G q j ) \mathbf{0}=\mathbf{h}_j\left(\mathbf{x}_k{ }^{L_j} \mathbf{n}_{f_j}\right)=\mathbf{G}_j\left({ }^G \mathbf{T}_{I_k}{ }^{I_k} \check{\mathbf{T}}_{I_j}{ }^I \mathbf{T}_L\left({ }^{L_j} \mathbf{p}_{f_j}-{ }^{L_j} \mathbf{n}_{f_j}\right)-{ }^G \mathbf{q}_j\right) 0=hj(xkLjnfj)=Gj(GTIkIkTˇIjITL(LjpfjLjnfj)Gqj)进行一阶近似后: 0 = h j ( x k , L j n f j ) ≃ h j ( x ^ k κ , 0 ) + H j κ x ~ k κ + v j = z j κ + H j κ x ~ k κ + v j \begin{aligned} \mathbf{0} & =\mathbf{h}_j\left(\mathbf{x}_k,{ }^{L_j} \mathbf{n}_{f_j}\right) \simeq \mathbf{h}_j\left(\widehat{\mathbf{x}}_k^\kappa, \mathbf{0}\right)+\mathbf{H}_j^\kappa \widetilde{\mathbf{x}}_k^\kappa+\mathbf{v}_j \\ & =\mathbf{z}_j^\kappa+\mathbf{H}_j^\kappa \widetilde{\mathbf{x}}_k^\kappa+\mathbf{v}_j \end{aligned} 0=hj(xk,Ljnfj)hj(x kκ,0)+Hjκx kκ+vj=zjκ+Hjκx kκ+vj其中 x k = x ^ k κ ⊞ x ~ k κ \mathbf{x}_k=\widehat{\mathbf{x}}_k^\kappa \boxplus \widetilde{\mathbf{x}}_k^\kappa xk=x kκx kκ H j κ \mathbf{H}_j^\kappa Hjκ h j ( x ^ k κ ⊞ x ~ k κ , L j n f j ) \mathbf{h}_j\left(\widehat{\mathbf{x}}_k^\kappa \boxplus \widetilde{\mathbf{x}}_k^\kappa,{ }^{L_j} \mathbf{n}_{f_j}\right) hj(x kκx kκ,Ljnfj)相对误差状态 x ~ k κ \widetilde{\mathbf{x}}_k^\kappa x kκ的雅可比,卡尔曼增益计算如下: K = P H T ( H P H T + R ) − 1 \mathbf{K}=\mathbf{P} \mathbf{H}^T\left(\mathbf{H} \mathbf{P} \mathbf{H}^T+\mathbf{R}\right)^{-1} K=PHT(HPHT+R)1其中 H = [ H 1 κ T , ⋯   , H m κ T ] T \mathbf{H}=\left[\mathbf{H}_1^{\kappa^T}, \cdots, \mathbf{H}_m^{\kappa^T}\right]^T H=[H1κT,,HmκT]T R = diag ⁡ ( R 1 , ⋯ R m ) \mathbf{R}=\operatorname{diag}\left(\mathbf{R}_1, \cdots \mathbf{R}_m\right) R=diag(R1,Rm) z k κ = [ z 1 κ T , ⋯   , z m κ T ] T \mathbf{z}_k^\kappa=\left[\mathbf{z}_1^{\kappa^T}, \cdots, \mathbf{z}_m^{\kappa^T}\right]^T zkκ=[z1κT,,zmκT]T,正如前面提到的 H P H T + R \mathbf{H} \mathbf{P} \mathbf{H}^T+\mathbf{R} HPHT+R的维度和观测维度相关,本文提出了一个新的卡尔曼增益计算公式: K = ( H T R − 1 H + P − 1 ) − 1 H T R − 1 \mathbf{K}=\left(\mathbf{H}^T \mathbf{R}^{-1} \mathbf{H}+\mathbf{P}^{-1}\right)^{-1} \mathbf{H}^T \mathbf{R}^{-1} K=(HTR1H+P1)1HTR1在这个公式中只需要进行两次求逆,但是求逆的维度都是状态变量的维度,状态变量的维度远小于测量维度,因此计算量也会小很多。公式的具体推导流程如下,根据SMW恒等式有: ( P − 1 + H T R − 1 H ) − 1 = P − P H T ( H P T + R ) − 1 H P \left(\mathbf{P}^{-1}+\mathbf{H}^T \mathbf{R}^{-1} \mathbf{H}\right)^{-1}=\mathbf{P}-\mathbf{P H}^T\left(\mathbf{H P}^T+\mathbf{R}\right)^{-1} \mathbf{H} \mathbf{P} (P1+HTR1H)1=PPHT(HPT+R)1HP因此我们有: K = ( H T R − 1 H + P − 1 ) − 1 H T R − 1 = P H T R − 1 − P H T ( H P H T + R ) − 1 H P H T R − 1 \begin{aligned} \mathbf{K} & =\left(\mathbf{H}^T \mathbf{R}^{-1} \mathbf{H}+\mathbf{P}^{-1}\right)^{-1} \mathbf{H}^T \mathbf{R}^{-1} \\ & =\mathbf{P H}^T \mathbf{R}^{-1}-\mathbf{P} \mathbf{H}^T\left(\mathbf{H} \mathbf{P} \mathbf{H}^T+\mathbf{R}\right)^{-1} \mathbf{H} \mathbf{P} \mathbf{H}^T \mathbf{R}^{-1} \end{aligned} K=(HTR1H+P1)1HTR1=PHTR1PHT(HPHT+R)1HPHTR1注意到 H P H T R − 1 = ( H P H T + R ) R − 1 − I . \mathbf{H} \mathbf{P} \mathbf{H}^T \mathbf{R}^{-1}=\left(\mathbf{H} \mathbf{P} \mathbf{H}^T+\mathbf{R}\right) \mathbf{R}^{-1}-\mathbf{I} . HPHTR1=(HPHT+R)R1I.因此我们可以获得: K = P H T R − 1 − P H T R − 1 + P H T ( H P T + R ) − 1 = P H T ( H P T + R ) − 1 . \begin{aligned} \mathbf{K} & =\mathbf{P} \mathbf{H}^T \mathbf{R}^{-1}-\mathbf{P} \mathbf{H}^T \mathbf{R}^{-1}+\mathbf{P} \mathbf{H}^T\left(\mathbf{H P}^T+\mathbf{R}\right)^{-1} \\ & =\mathbf{P H}^T\left(\mathbf{H P}^T+\mathbf{R}\right)^{-1} . \end{aligned} K=PHTR1PHTR1+PHT(HPT+R)1=PHT(HPT+R)1.计算完卡尔曼增益后,进一步我们就可以获得更新后的误差状态和协方差: x ^ k κ + 1 = x ^ k κ ⊞ ( − K z k κ − ( I − K H ) ( J κ ) − 1 ( x ^ k κ ⊟ x ^ k ) ) \widehat{\mathbf{x}}_k^{\kappa+1}=\widehat{\mathbf{x}}_k^\kappa \boxplus\left(-\mathbf{K z}_k^\kappa-(\mathbf{I}-\mathbf{K} \mathbf{H})\left(\mathbf{J}^\kappa\right)^{-1}\left(\hat{\mathbf{x}}_k^\kappa \boxminus \widehat{\mathbf{x}}_k\right)\right) x kκ+1=x kκ(Kzkκ(IKH)(Jκ)1(x^kκx k))当迭代收敛后标称状态更新为: x ‾ k = x ^ k κ + 1 , P ‾ k = ( I − K H ) P \overline{\mathbf{x}}_k=\widehat{\mathbf{x}}_k^{\kappa+1}, \overline{\mathbf{P}}_k=(\mathbf{I}-\mathbf{K H}) \mathbf{P} xk=x kκ+1,Pk=(IKH)P以上就完成了Fast LIO的推导过程。

1.3 实验结果

作者在论文中比较了Fast LIO和LINS的效果,在使用相同数据集的前提下而LINS平均每帧激光提取特征点147个需要34.5ms,Fast LIO平均每帧激光提取特征点784个,用7.3ms的平均处理速度并取得了更高的精度。

2. Fast LIO2

Fast LIO2发表于2021年,是在Fast LIO上进一步优化的一篇工作,其主要贡献是:(1)直接将原始点注册到地图而不提取特征,这样有助于提供整个系统的准确性;(2)通过增量k-d树结构ikd-Tree维护映射,该结构支持增量插入、删除和动态重新平衡,与现有的动态数据结构相比有更优越的整体性能

2.1 总体框架

Fast-LIO2的整体框架如下:
在这里插入图片描述
其中State Estimation部分和Fast-LIO是基本一致的,下面我们主要总结下区别较大的Mapping部分

2.2 ikd-Tree

2.2.1 Map Management

  1. 为了保证地图大小是可控的,只有在距离当前帧一定范围内的局部地图才会被保留,如下图所示:
    在这里插入图片描述
    在图(a)中,Body系位于 P 0 P_0 P0位置,初始化维护地图范围长度为 L L L,即蓝色方框内的区域;在图(b)中,当Body系移动到 P ′ P' P时,维护地图范围将从蓝色方框的区域移动到绿色方框的区域。其中 r = γ R r=\gamma R r=γR R R R为激光的FOV范围, γ \gamma γ为大于1的参与, d = ( γ − 1 ) R d=(\gamma-1) R d=(γ1)R

2.2.2 Tree Structure and Construction

  1. ikd-Tree是一个二分搜索树,和当前很多k-d树只在leaf nodes存储点的结构不同,ikd-Tree会在leaf nodes和internal nodes都对点进行存储;
  2. 在ikd-Tree中一个point只和一个node关联,point相关的属性存储在node上;
  3. ikd-Tree的数据结构如下图所示:
    在这里插入图片描述
    其中axis为用来进行空间划分的轴,treesize用于记录用当前节点为根节点的子节点的数量,invalidnum用于记录子节点被删除的节点的数量,如果点从地图中被删除,那么对应的节点的deleted标志位将被置为true,如果所有的子节点都已经被删除,那么treedeleted标注位将被置为true,range用于记录所有子节点对应的点覆盖的范围,具体来说记录的是一个包括所有子节点对应的点的矩形的最大最小值坐标。
  4. ikd-Tree的构建过程和普通kd-Tree的构建过程类似:循环依序取数据点的各维度来作为切分维度,取数据点在该维度的中值作为切分超平面,将中值左侧的数据点挂在其左子树,将中值右侧的数据点挂在其右子树。 递归处理其子树,直至所有数据点挂载完毕

2.2.3 Increment Updates

  1. Incremental Updates分为Point-wise操作和Box-wise操作,Point-wise指的是对一个点进行Insert、Delete或者Re-insert操作,Box-wise是对一个Box内的所有点进行Insert、Delete或者Re-insert操作

  2. Point Insertion with On-tree Downsampling,对于Point插入操作算法如下:
    在这里插入图片描述
    Point插入过程中会伴随着On-tree Downsample的操作,假定Downsample的分辨率为 l l l,根据分辨率 l l l可以将空间划分为若干个的立方体 C D \mathbf{C}_D CD,新插入点 p \mathbf{p} p会计算属于哪个 C D \mathbf{C}_D CD,算法计算离 C D \mathbf{C}_D CD中心 p center  \mathbf{p}_{\text {center }} pcenter 最近的点 P nearest \mathbf{P}_{\text {nearest}} Pnearest,然后将 C D \mathbf{C}_D CD里已经存在的点删除,然后将 P nearest \mathbf{P}_{\text {nearest}} Pnearest重新插入ikd-Tree。插入操作则是在ikd-Tree中递归地找到一个空节点,对于递归过程中涉及到的每一个非空节点会更新其节点属性。

  3. Box-wise Delete using Lazy Labels,在删除过程中,节点并不会立即被删除,而是delete标志位和treedeleted标志位做延后删除,判断节点是否要删除的流程如下:
    在这里插入图片描述
    假定要删除的范围是 C O \mathbf{C}_O CO,根据节点的range属性获得的范围是 C T \mathbf{C}_T CT,如果 C O \mathbf{C}_O CO C T \mathbf{C}_T CT不存在交集,则直接返回,如果 C O \mathbf{C}_O CO完全包含 C T \mathbf{C}_T CT,则将 C T \mathbf{C}_T CT包含的所有节点全部删除,如果 C O \mathbf{C}_O CO包含部分 C T \mathbf{C}_T CT递归到子节点做进一步判断。

2.2.4 Re-balancing

  1. Balancing Criterion,ikd-Tree的子树在满足如下两个条件时会激活平衡过程
    α \alpha α-balanced criterion: S (  T.leftchild  ) < α bal  ( S ( T ) − 1 ) S(\text { T.leftchild })<\alpha_{\text {bal }}(S(T)-1) S( T.leftchild )<αbal (S(T)1) S ( T . r i g h t c h i l d ) < α bal  ( S ( T ) − 1 ) S(T . r i g h t c h i l d)<\alpha_{\text {bal }}(S(T)-1) S(T.rightchild)<αbal (S(T)1) α \alpha α-deleted criterion: I ( T ) < α d e l S ( T ) I(T)<\alpha_{d e l} S(T) I(T)<αdelS(T)其中 α b a l ∈ ( 0.5 , 1 ) \alpha_{b a l} \in(0.5,1) αbal(0.5,1) α del  ∈ ( 0 , 1 ) \alpha_{\text {del }} \in(0,1) αdel (0,1) S ( T ) S(T) S(T)指的是 T T T为根节点子树的节点个数, I ( T ) I(T) I(T)指的是以 T T T为根节点子树的无效节点的个数。前者是为了维持整颗树的最大高度,后者则是及时将无效节点移除以保证其他增量操作的高效。
  2. Rebuild & Parallel Rebuild,子树的重建过程如下图所示:在这里插入图片描述
    第一步是子树进行展平,在展平的过程中将无效节点进行移除,第二步对展平后的节点进行重建。如果子树的规模过大,重建过程可能会导致延迟,为了避免这个问题,作者提出重建算法如下:
    在这里插入图片描述
    算法会先判断需要重建的规模,如果规模小于某个阈值是直接在主线程中进行重建,如果规模过大,则新建一个线程进行重建,在新线程的重建过程中,会对Insert操作和Delete操作进行上锁,这些操作在主线程中进行缓存,在新线程重建完成后,再将这些操作在新线程复现一遍,因此新线程中重建的子树除了更加平衡,其他信息和主线程中的子树是一致的。

2.2.5 K-Nearest Neighbor Search

  1. 在ikd-Tree的数据结构中记录了每个子树的覆盖的范围,因为在ikd-Tree进行K-Nearest Neighbor Search过程中会建立一个priority queue,其中记录在搜索过程中到目标点的距离。在K-Nearest Neighbor Search过程中,遍历到每一个节点,会优先计算以这个节点为根节点的子树覆盖的范围到目标点的距离,如果距离大于priority queue中的最大值,那么则停止对这个子树的搜索,通过这种方式提高搜索效率。

2.3 实验结果

2.3.1 时间复杂度

  1. C D = L x × L y × L z \mathbf{C}_D=L_x \times L_y \times L_z CD=Lx×Ly×Lz范围的Box-wise Delete和Search时间复杂度: O ( H ( n ) ) = { O ( log ⁡ n )  if  Δ min ⁡ ⩾ α ( 2 3 ) ( ∗ ) O ( n 1 − a − b − c )  if  Δ max ⁡ ⩽ 1 − α ( 1 3 ) ( ∗ ∗ ) O ( n α ( 1 3 ) − Δ min ⁡ − Δ med  )  if  ( ∗ )  and  ( ∗ ∗ )  fail and  Δ med ⁡ < α ( 1 3 ) − α ( 2 3 ) O ( n α ( 2 3 ) − Δ min ⁡ )  otherwise.  O(H(n))= \begin{cases}O(\log n) & \text { if } \Delta_{\min } \geqslant \alpha\left(\frac{2}{3}\right)(*) \\ O\left(n^{1-a-b-c}\right) & \text { if } \Delta_{\max } \leqslant 1-\alpha\left(\frac{1}{3}\right)(* *) \\ O\left(n^{\alpha\left(\frac{1}{3}\right)-\Delta_{\min }-\Delta_{\text {med }}}\right) & \text { if }(*) \text { and }(* *) \text { fail and } \\ & \Delta_{\operatorname{med}}<\alpha\left(\frac{1}{3}\right)-\alpha\left(\frac{2}{3}\right) \\ O\left(n^{\alpha\left(\frac{2}{3}\right)-\Delta_{\min }}\right) & \text { otherwise. }\end{cases} O(H(n))= O(logn)O(n1abc)O(nα(31)ΔminΔmed )O(nα(32)Δmin) if Δminα(32)() if Δmax1α(31)() if () and () fail and Δmed<α(31)α(32) otherwise. 其中 a = log ⁡ n S x L x a=\log _n \frac{S_x}{L_x} a=lognLxSx b = log ⁡ n S y L y b=\log _n \frac{S_y}{L_y} b=lognLySy c = log ⁡ n S z L z c=\log _n \frac{S_z}{L_z} c=lognLzSz Δ min ⁡ \Delta_{\min } Δmin Δ med  \Delta_{\text {med }} Δmed  Δ max ⁡ \Delta_{\max } Δmax a a a b b b c c c中最小、中间和最大值
  2. Point Insertion with On-tree Downsampling时间复杂度为 O ( log ⁡ n ) O(\log n) O(logn)
  3. 单线程re-building时间复杂度为 O ( n log ⁡ n ) O(n \log n) O(nlogn),双线程re-building时间复杂度为 O ( n ) O(n) O(n)
  4. K-Nearest Neighbor Search时间复杂度为 O ( log ⁡ n ) O(\log n) O(logn)

2.3.2 效率对比

  1. ikd-Tree效率对比如下:
    在这里插入图片描述
  2. Fast LIO2和其他SOTA方法效率对比如下:
    在这里插入图片描述
  3. Fast LIO和Fast LIO2的效率对比如下:
    在这里插入图片描述
    可以看出来,随着ikd-Tree的加入,Fast-LIO2的效率相对于Fast LIO会提高不少,以上就是对Fast LIO2的总结

3. Faster LIO

Faster LIO是高博团队发表于2022年的一篇论文,其主要贡献是是基于Fast LIO2将ikd-Tree的数据结构更新为iVox,进一步提高了算法效率,在知乎上有一篇高博对这个工作的介绍,感兴趣的同学可以参考Faster-LIO:快速激光IMU里程计,本篇只做一个简单总结

3.1 iVox

如下图是iVox的数据结构定义:
在这里插入图片描述
iVov的底层是一个空间哈希映射: p = [ p x , p y , p z ] T \mathbf{p}=\left[p_x, p_y, p_z\right]^T p=[px,py,pz]T v = 1 s [ p x , p y , p z ] T \mathbf{v}=\frac{1}{s}\left[p_x, p_y, p_z\right]^T v=s1[px,py,pz]T i d v = hash ⁡ ( v ) = ( v x n x )  xor  ( v y n y )  xor  ( v z n z )   m o d   N i d_v=\operatorname{hash}(v)=\left(v_x n_x\right) \text { xor }\left(v_y n_y\right) \text { xor }\left(v_z n_z\right) \bmod N idv=hash(v)=(vxnx) xor (vyny) xor (vznz)modN其中 p x , p y , p z p_x, p_y, p_z px,py,pz是空间点坐标, s s s是栅格大小, n x , n y , n z n_x, n_y, n_z nx,ny,nz是大质数,因为质数不与其他数字存在公约数,可以减少因取模操作而产生的周期性模式,从而避免哈希冲突, N N N是哈希表的大小。

在存储上,这些Voxel以Vector的数据结构进行存储或者使用PHC的数据结构进行存储,根据存储结构的不同分别称为Linear iVox或者iVox-PHC。

在查找K近邻时,先计算被查找的点落在哪个体素中,然后看预定义的范围内是否存在有效的iVox。如果有,就把这些iVox内部的点也考虑进来。我们在每个iVox内部查找至多K个最近邻,再进行合并即可。线性的iVox只须遍历内部点,然后进行部分排序,再进行汇总PHC的iVox则可以根据空间填充曲线上的索引值来查找最近邻。,使用这种方式进行最近邻搜索其效率更高,精度会有所下降,但是对于点云匹配来讲这种精度已经足够。

上述提到的PHC是一种建立高维数据与低维数据映射的方法,在查找最近邻时可以先把它看成这个iVox里的曲线上的ID,然后相关计算公式计算该ID周边的若干个近邻,如下图所示:在这里插入图片描述
在论文中有补充到,由于Faster LIO会限制填入每个栅格的点的数量,因此PHC带来的收益并不是特别明显

3.2 增量地图更新

在Fast LIO2中使用LUR缓存进行局部地图管理,在进行近邻搜索时,记录哪些体素是最近使用过的,那么不怎么使用的体素自然被移动到队尾。我们会设置一个局部地图的容量,超过最大容量时,就删除那些很久未使用的体素。删除操作是针对整个体素的,内部的点会被全部删除。这种局部地图缓存策略也会让局部地图跟随车辆运动,而实际操作的地方更少。如下图所示:
在这里插入图片描述

3.3 实验结果

如下是不同数据结构插入和最近邻搜索的耗时对比:
在这里插入图片描述
如下图是耗时和召回的关系曲线:
在这里插入图片描述
最后是Faster LIO整个系统耗时和精度对比:
在这里插入图片描述
在这里插入图片描述
可以看到,在相同的精度下Faster LIO确实取得了更快的速度,以上是对Faster LIO算法的简单总结

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1673106.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

网络网络层之(5)IPv6协议

网络网络层之(5)IPv6协议 Author: Once Day Date: 2024年5月12日 一位热衷于Linux学习和开发的菜鸟&#xff0c;试图谱写一场冒险之旅&#xff0c;也许终点只是一场白日梦… 漫漫长路&#xff0c;有人对你微笑过嘛… 全系列文档可参考专栏&#xff1a;通信网络技术_Once-Day…

未授权访问:Docker未授权访问漏洞

目录 1、漏洞原理 2、环境搭建 3、未授权访问 4、通过crontab反弹宿主机shell 防御手段 今天继续学习各种未授权访问的知识和相关的实操实验&#xff0c;一共有好多篇&#xff0c;内容主要是参考先知社区的一位大佬的关于未授权访问的好文章&#xff0c;还有其他大佬总结好…

【机器学习】机器学习与人工智能融合新篇章:自适应智能代理在多元化复杂环境中的创新应用与演进趋势

&#x1f512;文章目录&#xff1a; &#x1f4a5;1.引言 &#x1f68b;1.1 机器学习与人工智能的发展背景 &#x1f68c;1.2 自适应智能代理的概念与重要性 &#x1f690;1.3 研究目的与意义 ☔2.自适应智能代理的关键技术 &#x1f6e3;️2.1 环境感知与信息处理技术 …

whisper报错:hp, ht, pid, tid = _winapi.CreateProcess [WinError 2] 系统找不到指定的文件。

in _execute_child hp&#xff0c; ht&#xff0c; pid&#xff0c; tid _winapi.CreateProcess&#xff08;executable&#xff0c; args&#xff0c; FileNotFoundError&#xff1a; [WinError 2] 系统找不到指定的文件。 原因&#xff1a; 没装ffmpeg 或者 ffmpeg没添加到…

Nios实验使用串口输出“Hello Nios-II”字符到笔记本电脑

目录 实验过程 创建工程 修改程序 编译工程 运行项目 效果实现 总结 参考 实验过程 硬件设计见博主上篇博客 软件部分设计 下面使用 Nios II Software Build Tools for Eclipse 来完成当前项目的软件开发。 启动 Nios II SBT 按照下图所示点击 Nios II Software Build…

Backend - 数据分析 Pandas

目录 一、作用 二、基础环境 &#xff08;一&#xff09;执行虚拟环境的终端命令 &#xff08;二&#xff09;代码中导包 三、应用&#xff1a;一维数组 &#xff08;一&#xff09;Series对象 1. 含义 2. 常用属性和方法 &#xff08;1&#xff09;属性 &#xff08;…

springboot学习整理

视频&#xff1a;基础篇-01_springboot概述_哔哩哔哩_bilibili 介绍 spring boot 是spring提供的一个子项目&#xff0c;用于快速构建spring应用程序 spring构建&#xff1a; 1 导入依赖繁琐 &#xff1b; 2 项目配置繁琐 spring Framework: 核心 spring Boot :快速构建spring…

【LangChain学习之旅】—(21)聊天客服机器人的开发(上)

【LangChain学习之旅】—(21)聊天客服机器人的开发(上) “聊天机器人”说明项目的技术实现细节技术实现步骤简述第二步:增加记忆机制第三步:增加检索机制总结“聊天机器人”说明 聊天机器人(Chatbot)是 LLM 和 LangChain 的核心用例之一,很多人学习大语言模型,学习 …

Jmeter(三十九) - 从入门到精通进阶篇 - Jmeter配置文件的刨根问底 - 上篇(详解教程)

宏哥微信粉丝群&#xff1a;https://bbs.csdn.net/topics/618423372 有兴趣的可以扫码加入 1.简介 为什么宏哥要对Jmeter的配置文件进行一下讲解了&#xff0c;因为有的童鞋或者小伙伴在测试中遇到一些需要修改配置文件的问题不是很清楚也不是很懂&#xff0c;就算修改了也是…

今天开发了一款软件,我竟然只用敲了一个字母(文末揭晓)

软件课题&#xff1a;Python实现打印100内数学试题软件及开发过程 一、需求管理&#xff1a; 1.实现语言&#xff1a;Python 2.打印纸张&#xff1a;A4 3.铺满整张纸 4.打包成exe 先看效果&#xff1a; 1. 2.电脑打印预览 3.打印到A4纸效果&#xff08;晚上拍的&#x…

R语言手把手教你进行支持向量机分析

1995年VAPINK 等人在统计学习理论的基础上提出了一种模式识别的新方法—支持向量机 。它根据有限的样本信息在模型的复杂性和学习能力之间寻求一种最佳折衷。 以期获得最好的泛化能力.支持向量机的理论基础决定了它最终求得的是全局最优值而不是局部极小值,从而也保证了它对未知…

云粒智慧实时数仓的架构演进分享:OceanBase + Flink CDC

4月20日&#xff0c;在2024 OceanBase开发者大会上&#xff0c;云粒智慧的高级技术专家付大伟&#xff0c;分享了云粒智慧实时数仓的构建历程。他讲述了如何在传统数仓技术框架下的相关努力后&#xff0c;选择了OceanBase Flink CDC架构的实时数仓演进历程。 业务背景及挑战 …

企业数据治理过程有哪些挑战?该如何克服?

在数字化时代&#xff0c;数据已成为企业最宝贵的资产之一。随着大数据、云计算和人工智能等技术的兴起&#xff0c;企业积累的数据量呈指数级增长。这些数据中蕴含着巨大的商业价值&#xff0c;对于推动企业发展、优化决策制定、增强市场竞争力具有不可替代的作用。然而&#…

Python-VBA函数之旅-type函数

目录 一、type函数的常见应用场景 二、type函数使用注意事项 三、如何用好type函数&#xff1f; 1、type函数&#xff1a; 1-1、Python&#xff1a; 1-2、VBA&#xff1a; 2、推荐阅读&#xff1a; 个人主页&#xff1a; https://myelsa1024.blog.csdn.net/ 一、type函…

企业微信hook接口协议,ipad协议http,获取群成员列表简洁版

获取群成员列表简洁版 参数名必选类型说明uuid是String每个实例的唯一标识&#xff0c;根据uuid操作具体企业微信 请求示例 {"uuid":"3240fde0-45e2-48c0-90e8-cb098d0ebe43","roomid":10696052955016166 } 返回示例 {"data": {&q…

政安晨:【Keras机器学习示例演绎】(四十四)—— 使用序列到序列转换器实现英语到西班牙语的翻译

目录 简介 设置 下载数据 解析数据 文本数据矢量化 建立模型 训练我们的模型 解码测试句子 政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 收录专栏: TensorFlow与Keras机器学习实战 希望政安晨的博客能够对您有所裨益&#xff0c;如有不足之…

智慧管家物业管理系统(小组项目)

目录 前言 一、项目介绍 1、目的和背景 2、项目主要内容 3、技术介绍 二、功能模块 1、重要文件结构 2、功能实现&#xff08;部分个人负责模块功能&#xff09; 2.1 展示房源信息页面 2.2 房屋详情页面 2.3 房源信息管理 三、功能模块页面 1、前台模块 2、后台…

使用vue3+ts+vite从零开始搭建bolg(五):layout(持续更新中)

五、layout搭建 5.1静态搭建 在src下创建如图文件夹 这里用logo举例&#xff0c;在scripts里export <script lang"ts">export default {name: Logo,}</script> 然后在layout里引入 //引入左侧菜单顶部用户信息 import Logo from ./logo/index.vue 接…

M-有效算法

在赛场上&#xff0c;脑子就两个字“二分”&#xff0c;一点思路都没&#xff0c;完全不知道二分谁&#xff0c;怎么二分&#xff0c;从哪入手。隐隐约约也知道要变换公式&#xff0c;可惜没坚持这个想法。脑子里全是把k分离出来&#xff0c;赛后看了题解才知道&#xff0c;应该…

Electron + GitHub Actions | 自动化流程详解(下)

自动化部署 上篇介绍了 Electron Forge 打包应用教程。在实际开发中&#xff0c;自动化是提升效率和产出质量的关键。本篇我们将详细介绍如何将构建和发布 Electron 应用的过程自动化。 代码挂在 GitHub 仓库上&#xff0c;如果有帮助&#xff0c;记得给仓库点个赞&#xff1a…