学习资料是深蓝学院的《从零开始手写VIO》课程,对课程做一些记录,方便自己以后查询,如有错误还请斧正。由于习惯性心算公式,所以为了加深理解,文章公式采用手写的形式。
VIO学习笔记(一)—— 概述
VIO学习笔记(二)—— IMU 传感器
已知:
状态量初始值:特征点的三维坐标
,相机的位姿
。
系统测量值:特征点
在不同图像上的图像坐标。
解决方式:
构建误差函数
,利用最小二乘
得到状态量的最优估计:
arg min q , p , f ∑ i = 1 m ∑ j = 1 n ∣ ∣ π ( q w c i , p w c i , f j ) − z f j c i ∣ ∣ Σ i j \argmin_{q,p,f} \sum_{i=1}^m\sum_{j=1}^n ||π (q _{wc _i} , p _{wc _i} , f _j ) − z_{ f _j}^{c_i} ||_{Σ _{ij}} q,p,fargmini=1∑mj=1∑n∣∣π(qwci,pwci,fj)−zfjci∣∣Σij
符号定义:
q q q: 旋转四元数
p p p: 平移向量
f f f: 特征点3D坐标
c i c_i ci: 第i个相机系
π ( ⋅ ) π(·) π(⋅): 投影函数
Z f j c i Z_{f_j}^{c_i} Zfjci: c i c_i ci对 f j f_j fj的观测
∑ i j \sum_{ij} ∑ij: ∑ \sum ∑范数
由于imu的数据采集频率大于相机的采集频率,所以在两个相机坐标系之间,存在多个imu坐标系即body坐标系,由于相机坐标系应根body坐标系相对应,所以对两图像间的imu数据进行预积分,使其变为一个。
为什么要预积分,slam系统中为了减小优化求解器的负担
,采用了关键帧
策略,IMU的速率显然要快于关键帧的插入,它们之间的关系可以用下图很好的表示。
紧耦合
的方式就是把imu和图像的信息共同来估计
状态量,所以如何协调
两者之间的关系了,预积分干了这么一件事,通过重新参数化,把关键帧之间的IMU测量值积分成相对运动的约束,避免了因为初始条件变化造成的重复积分
。
用IMU的slam、vio算法有很多,有滤波器的比如MSCKF,有基于图优化的比如VINS,OKVIS,ORB-SLAM等。就拿ORB-SLAM来说吧, 在bundle adjustment里,参与对象是keyframe,比如有2个keyframe: K F 1 , K F 2 KF_1,KF_2 KF1,KF2, 他们的位姿分别为: P 1 w , P 2 w P_{1w},P_{2w} P1w,P2w,那么他们的相对位姿 :
P 21 = P 1 w ⋅ P 2 w − 1 P_{21}=P_{1w}·P_{2w}^{-1} P21=P1w⋅P2w−1
我们可以认为 P 21 P_{21} P21为估计项,是由SLAM的位姿直接算出来的。如果要构成一个优化问题,我们还需要知道误差项和测量项。没错,是IMU可以计算在这两个KF间的测量项 P i m u P_{imu} Pimu,预计分干的事情就是计算这个测量项
。
r = P 21 ⋅ P i m u − 1 r=P_{21}·P_{imu}^{-1} r=P21⋅Pimu−1
在紧耦合的优化slam中,IMU就是提供了两个关键帧的相对测量
,从而构建误差函数对关键帧姿态的迭代优化。当然实际应用中不会是这么简单的形式,这里面要对各个变量分别求取误差,然后求雅克比矩阵。
找到一个 n 维的变量 x ∗ ∈ R n x^*∈R^n x∗∈Rn ,使得损失函数 F (x) 取局部最小值:
F ( x ) = 1 2 ∑ i = 1 m ( f i ( x ) ) 2 F(x)=\frac{1}{2}\sum_{i=1}^m(f_i(x))^2 F(x)=21i=1∑m(fi(x))2
其中 f i f_i fi是残差函数,比如测量值和预测值之间的差,且有 m ≥ n。局部最小值指对任意 ∥ x − x ∗ ∥ < δ ∥x − x^∗ ∥ < δ ∥x−x∗∥<δ 有 F ( x ∗ ) ≤ F ( x ) F (x^∗ ) ≤ F (x) F(x∗)≤F(x)
假设损失函数 F ( x ) F (x) F(x) 是可导并且平滑的,因此,二阶泰勒展开:
F ( x + ∆ x ) = F ( x ) + J ∆ x + 1 2 ∆ x ⊤ H ∆ x + O ( ∥ ∆ x ∥ 3 ) F (x + ∆x) = F (x) + J∆x + \frac12∆x ^⊤ H∆x + O (∥∆x∥ ^3) F(x+∆x)=F(x)+J∆x+21∆x⊤H∆x+O(∥∆x∥3)
其中 J 和 H 分别为损失函数 F 对变量 x 的一阶导和二阶导矩阵。
忽略泰勒展开的高阶项,损失函数变成了二次函数,可以轻易得到如下性质:
如果在点 x s x_s xs 处有导数为 0 ,则称这个点为稳定点
。
在点 x s x_s xs 处对应的 Hessian 为 H:
如果是正定
矩阵,即它的特征值都大于 0,则在 x s x_s xs 处有 F ( x ) F (x) F(x) 为局部最小值
;
如果是负定
矩阵,即它的特征值都小于 0,则在 x s x_s xs 处有 F ( x ) F (x) F(x) 为局部最大值
;
如果是不定
矩阵,即它的特征值大于 0 也有小于 0 的,则 x s x_s xs 处为鞍点
。
直接求解:线性最小二乘。
迭代下降法:适用于线性和非线性最小二乘。
找一个下降方向使损失函数随 x 的迭代逐渐减小,直到 x 收敛到 x ∗ x^∗ x∗ :
F ( x k + 1 ) < F ( x k ) F (x_{k+1} ) < F (x _k ) F(xk+1)<F(xk)
分两步:
第一,找下降方向
单位向量 d,
第二,确定下降步长
α.
假设 α 足够小,我们可以对损失函数 F (x) 进行一阶泰勒展开:
F ( x + α d ) ≈ F ( x ) + α J d F (x + αd) ≈ F (x) + αJd F(x+αd)≈F(x)+αJd
只需寻找下降方向,满足:
J d < 0 Jd < 0 Jd<0
通过 line search 方法找到下降的步长: α ∗ = a r g m i n α > 0 F ( x + α d ) α ^∗ = argmin _{α>0} {F (x + αd)} α∗=argminα>0F(x+αd)
从下降方向的条件可知: J d = ∥ J ∥ c o s θ Jd = ∥J∥ cos θ Jd=∥J∥cosθ, θ θ θ 表示下降方向和梯度方向的夹角。当 θ = π θ = π θ=π ,有
d = − J T ∥ J ∥ d =\frac{-J^T}{∥J∥} d=∥J∥−JT
即梯度的负方向
为最速下降方向。缺点:最优值附近震荡,收敛慢。
在局部最优点 x ∗ x ^∗ x∗ 附近,如果 x + ∆ x x + ∆x x+∆x 是最优解,则损失函数对 ∆x的导数等于 0,对损失函数的二阶泰勒展式
取一阶导有:
∂ ∂ ∆ x ( F ( x ) + J ∆ x + 1 2 ∆ x ⊤ H ∆ x ) = J ⊤ + H ∆ x = 0 \frac{∂}{∂∆x}(F (x) + J∆x + \frac12∆x ^⊤ H∆x )= J ^⊤ + H∆x = 0 ∂∆x∂(F(x)+J∆x+21∆x⊤H∆x)=J⊤+H∆x=0
得到: ∆ x = − H − 1 J ⊤ ∆x = −H^{ −1} J ^⊤ ∆x=−H−1J⊤ 。缺点:二阶导矩阵计算复杂。
将损失函数的二阶泰勒展开记作
F ( x + ∆ x ) ≈ L ( ∆ x ) ≡ F ( x ) + J ∆ x + ∆ x ⊤ H ∆ x F (x + ∆x) ≈ L(∆x) ≡ F (x) + J∆x + ∆x ^⊤ H∆x F(x+∆x)≈L(∆x)≡F(x)+J∆x+∆x⊤H∆x
求以下函数的最小化:
∆ x ≡ a r g min ∆ x ( L ( ∆ x ) + 1 2 μ ∆ x ⊤ ∆ x ) ∆x ≡ arg\min_{∆x} (L(∆x) + \frac12μ∆x^ ⊤ ∆x) ∆x≡arg∆xmin(L(∆x)+21μ∆x⊤∆x)
其中, μ ≥ 0 μ ≥ 0 μ≥0为阻尼因子
, 1 2 μ ∆ x ⊤ ∆ x = 1 2 μ ∥ ∆ x ∥ 2 \frac12 μ∆x ^⊤ ∆x = \frac12 μ∥∆x∥^ 2 21μ∆x⊤∆x=21μ∥∆x∥2是惩罚项
(不让步长过大)。
对新的损失函数求一阶导,并令其等于 0 有:
L ′ ( ∆ x ) + μ ∆ x = 0 ⇒ ( H + μ I ) ∆ x = − J ⊤ L ^′ (∆x) + μ∆x = 0\\ ⇒ (H + μI) ∆x = −J ^⊤ L′(∆x)+μ∆x=0⇒(H+μI)∆x=−J⊤
为了公式约简,可将残差组合成向量的形式。
f ⃗ ( x ) = [ f 1 ( x ) f 2 ( x ) … f 1 ( x ) ] \vec{f } (x)= \begin{bmatrix} f_1(x) \\ f_2(x) \\ … \\f_1(x) \\ \end{bmatrix} f(x)=⎣⎢⎢⎡f1(x)f2(x)…f1(x)⎦⎥⎥⎤
则有: f ⊤ ( x ) f ( x ) = ∑ i = 1 m ( f i ( x ) ) 2 f ^⊤ (x)f (x) = \sum_{i=1}^m (f _i (x))^2 f⊤(x)f(x)=∑i=1m(fi(x))2
同理,如果记 J ⃗ i ( x ) = ∂ f i ( x ) ∂ x \vec{J}_ i (x) = \frac{∂f_i(x)}{∂x} Ji(x)=∂x∂fi(x) 则有:
∂ f ⃗ ( x ) ∂ x = J ⃗ = [ J ⃗ 1 ( x ) J ⃗ 2 ( x ) … J ⃗ i ( x ) ] \frac{∂\vec{f}(x)}{∂x}= \vec{J} =\begin{bmatrix} \vec{J}_ 1 (x) \\ \vec{J}_ 2(x) \\ … \\\vec{J}_ i (x) \\ \end{bmatrix} ∂x∂f(x)=J=⎣⎢⎢⎡J1(x)J2(x)…Ji(x)⎦⎥⎥⎤
残差函数 f ⃗ ( x ) \vec{f} (x) f(x) 为非线性函数,对其一阶泰勒近似有:
f ( x + ∆ x ) ≈ l ( ∆ x ) ≡ f ( x ) + J ∆ x f (x + ∆x) ≈ l(∆x) ≡ f (x) + J∆x f(x+∆x)≈l(∆x)≡f(x)+J∆x
请特别注意,这里的 J 是残差函数 f 的雅克比矩阵。代入损失函数:
F ( x + ∆ x ) ≈ L ( ∆ x ) ≡ 1 2 l ( ∆ x ) ⊤ l ( ∆ x ) = 1 2 f ⊤ f + ∆ x ⊤ J ⊤ f + 1 2 ∆ x ⊤ J ⊤ J ∆ x = F ( x ) + ∆ x ⊤ J ⊤ f + 1 2 ∆ x ⊤ J ⊤ J ∆ x F (x + ∆x) ≈ L(∆x) ≡ \frac12l(∆x) ^⊤ l(∆x)\\ \quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad= \frac12f ^⊤ f + ∆x ^⊤ J ^⊤ f + \frac12∆x ^⊤ J ^⊤ J∆x\\ \quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad= F (x)+ ∆x ^⊤ J ^⊤ f + \frac12∆x ^⊤ J ^⊤ J∆x F(x+∆x)≈L(∆x)≡21l(∆x)⊤l(∆x)=21f⊤f+∆x⊤J⊤f+21∆x⊤J⊤J∆x=F(x)+∆x⊤J⊤f+21∆x⊤J⊤J∆x
这样损失函数就近似成了一个二次函数,并且如果雅克比是满秩的,则 J ⊤ J J ^⊤ J J⊤J 正定,损失函数有最小值。
另外, 易得: F ′ ( x ) = ( J ⊤ f ) ⊤ F ^′ (x) = (J ^⊤ f ) ^⊤ F′(x)=(J⊤f)⊤ ,以及 F ′ ′ ( x ) ≈ J ⊤ J F ^{′′} (x) ≈ J ^⊤ J F′′(x)≈J⊤J.
令损失函数就近似式的一阶导等于 0,得到:
J ⊤ J ∆ x g n = − J ⊤ f J ^⊤ J ∆x_{ gn }= −J^ ⊤ f J⊤J∆xgn=−J⊤f
上式就是通常论文里看到的 H ∆ x g n = b H∆x _{gn} = b H∆xgn=b,称其为 normal equation
.
Levenberg (1944) 和 Marquardt (1963) 先后对高斯牛顿法进行了改进,求解过程中引入了阻尼因子
:
( J ⊤ J + μ I ) ∆ x l m = − J ⊤ f w i t h μ ≥ 0 (J^ ⊤ J + μI )∆x_{lm} = −J ^⊤ f \quad \quad \quad with \quad μ ≥ 0 (J⊤J+μI)∆xlm=−J⊤fwithμ≥0
μ > 0 μ > 0 μ>0 保证 ( J ⊤ J + μ I ) (J ^⊤ J + μI) (J⊤J+μI) 正定,迭代朝着下降方向进行。
μ μ μ 非常大,则 ∆ x l m = − 1 μ J ⊤ f = − 1 μ F ′ ( x ) ⊤ ∆x _{lm} = −\frac 1μ J ^⊤ f = − \frac1μ F^ ′ (x) ^⊤ ∆xlm=−μ1J⊤f=−μ1F′(x)⊤ , 接近最速下降法.
μ μ μ 比较小,则 ∆ x l m ≈ ∆ x g n ∆x _{lm} ≈ ∆x _{gn} ∆xlm≈∆xgn , 接近高斯牛顿法。
阻尼因子 μ μ μ 大小是相对于 J ⊤ J J ^⊤ J J⊤J 的元素而言的。半正定的信息矩阵 J ⊤ J J^⊤ J J⊤J特征值 { λ j {λ_j } λj} 和对应的特征向量为 { v j {v _j } vj}。对 J ⊤ J J ^⊤ J J⊤J 做特征值分解
分解后有: J ⊤ J = V Λ V ⊤ J ^⊤ J = VΛV ^⊤ J⊤J=VΛV⊤ 可得(不知道咋算出来的,先记住接着向下走吧,有时间再补特征分解的知识!!!):
∆ x l m = − ∑ j = 1 n v j T F ′ T λ j + μ v j ∆x_{ lm} = −\sum_{j=1}^n\frac{v_j^TF^{'T}}{λ_j+μ}v_j ∆xlm=−j=1∑nλj+μvjTF′Tvj
所以,一个简单的 μ 0 μ _0 μ0 初始值的策略就是:
μ 0 = τ ⋅ max ( J ⊤ J ) i i μ_ 0 = τ · \max{} (J ^⊤ J)_{ ii} μ0=τ⋅max(J⊤J)ii
通常,按需设定 τ ∼ [ 1 0 − 8 , 1 ] τ ∼ [10 ^{−8} , 1] τ∼[10−8,1]。
定性分析
,直观感受阻尼因子的更新:首先比例因子分母始终大于 0,如果:
ρ < 0 ρ < 0 ρ<0, 则 F ( x ) ↑ F (x) ↑ F(x)↑ ,应该 μ ↑ → ∆ x ↓ μ ↑→ ∆x ↓ μ↑→∆x↓, 增大阻尼减小步长。
如果 ρ > 0 ρ > 0 ρ>0 且比较大,减小 μ μ μ, 让 LM 接近 Gauss-Newton 使得系统更快收敛。
反之,如果是比较小的正数,则增大阻尼 μ μ μ,缩小迭代步长。
1963 年 Marquardt 提出了一个如下的阻尼策略:
i f ρ < 0.25 μ : = μ ∗ 2 e l s e i f ρ > 0.75 μ : = μ / 3 if \quad \quad\quadρ < 0.25\\ \quad\quad\quad\quadμ := μ ∗ 2\\ elseif \quadρ > 0.75\\ \quad\quad\quad\quadμ := μ/3 ifρ<0.25μ:=μ∗2elseifρ>0.75μ:=μ/3
Marquardt 好不好呢?如下图所示 :
会看到 μ μ μ存在一定的跳动,这就导致步长存在一定的晃动,不稳定。
i f ρ > 0 μ : = μ ∗ m a x ( 1 3 , 1 − ( 2 ρ − 1 ) 3 ) ; ν : = 2 e l s e μ : = μ ∗ ν ; ν : = 2 ∗ ν \quad \quad if \quadρ > 0\\ \quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quadμ := μ ∗ max(\frac13,1 − (2ρ − 1)^ 3 );ν := 2 \\ else\\ \quad\quad\quad\quad\quad\quad\quad\quad\quad\quadμ := μ ∗ ν;ν := 2 ∗ ν ifρ>0μ:=μ∗max(31,1−(2ρ−1)3);ν:=2elseμ:=μ∗ν;ν:=2∗ν
引言:最小二乘中遇到 outlier 怎么处理?核函数如何在代码中实现?有多种方法,这里主要介绍 g2o 和 ceres 中使用的 Triggs Correction .
鲁棒核函数直接作用残差 f k ( x ) f _k (x) fk(x) 上,最小二乘函数变成了如下形式:
min x 1 2 ∑ k ρ ( ∥ f k ( x ) ∥ 2 ) \min_x\frac12\sum_kρ (∥f _k (x)∥ ^2) xmin21k∑ρ(∥fk(x)∥2)
将误差的平方项记作 s k = ∥ f k ( x ) ∥ 2 s _k = ∥f _k (x)∥^ 2 sk=∥fk(x)∥2 , 则鲁棒核误差函数进行二阶泰勒展开有:
1 2 ρ ( s ) = 1 2 ( c o n s t + ρ ′ ∆ s + ρ ′ ′ ∆ 2 s ) \frac12ρ (s) = \frac12(const + ρ ^′ ∆s + ρ^ ′′ ∆^ 2 s) 21ρ(s)=21(const+ρ′∆s+ρ′′∆2s)
上述函数中 ∆ s k ∆s _k ∆sk 的计算稍微复杂一点:
∆ s k ∆s _k ∆sk 代入 1 2 ρ ( s ) \frac12ρ (s) 21ρ(s)有:
代三角号的计算步骤很蒙,没有算出来,找了一下论文,发现论文也是这样写的:
估计是哪个地方的知识点不到位把,再研究研究!!!
柯西鲁棒核函数的定义为:
ρ ( s ) = c 2 l o g ( 1 + s c 2 ) ρ(s) = c^ 2 log(1 +\frac{s}{c^2}) ρ(s)=c2log(1+c2s)
其中 c c c 为控制参数。对 s s s 的一阶导和二阶导为:
ρ ′ ( s ) = 1 1 + s c 2 , ρ ′ ′ ( s ) = − 1 c 2 ( ρ ′ ( s ) ) 2 ρ ^′ (s) =\frac{1}{1+\frac{s}{c^2}},\quad\quad\quad\quadρ ^{′ ′} (s) =-\frac{1}{c^2}(ρ ^′ (s) )^2 ρ′(s)=1+c2s1,ρ′′(s)=−c21(ρ′(s))2
95% efficiency rule (Huber, 1981):itprovides an asymptotic efficiency 95% that of linear regression for the normal distribution.
• 如果残差 f i f _i fi 是正态分布,Huber
c = 1.345 c = 1.345 c=1.345,
C a u c h y c = 2.3849 Cauchy c = 2.3849 Cauchyc=2.3849
• 如果残差非正态分布,需估计残差方差,然后对残差归一化。median absolute residual 方法
σ = 1.482 ⋅ m e d ( m e d ( r ) − r i ) σ = 1.482 · med(med(r) − r _i ) σ=1.482⋅med(med(r)−ri).
定义:
一个特征点在归一化相机坐标系
下的估计值与观测值的差。
r c = [ x z − u y z − v ] r _c= \begin{bmatrix} \frac xz-u \\ \frac yz-v \\ \end{bmatrix} rc=[zx−uzy−v]
其中,待估计的状态量为特征点的三维空间坐标 ( x , y , z ) ⊤ (x, y, z) ^⊤ (x,y,z)⊤ ,观测值 ( u , v ) ⊤ (u, v) ^⊤ (u,v)⊤ 为特征在相机归一化平面的坐标。
特征点在归一化相机坐标系
与在相机坐标系
下的坐标关系为:
[ x y z ] = 1 λ [ u v 1 ] \begin{bmatrix} x \\y \\z\end{bmatrix}=\frac1λ\begin{bmatrix} u \\v \\1\end{bmatrix} ⎣⎡xyz⎦⎤=λ1⎣⎡uv1⎦⎤
其中 λ = 1 / z λ = 1/z λ=1/z 称为逆深度
(更接近于高斯分布)。
特征点逆深度在第 i 帧中初始化得到,在第 j 帧又被观测到,预测其在第 j 中的坐标为:
[ x c j y c j z c j 1 ] = T b c − 1 T w b j − 1 T w b i T b c [ 1 λ u c i 1 λ v c i 1 λ 1 ] \begin{bmatrix} x _{c_ j} \\y _{c_ j} \\z _{c_ j} \\1\end{bmatrix}=T^{−1}_{bc}T _{wb_j}^{-1}T_{wb_i} T_{bc} \begin{bmatrix} \frac1λu_{c_i} \\\frac1λv_{c_i} \\\frac1λ\\1\end{bmatrix} ⎣⎢⎢⎡xcjycjzcj1⎦⎥⎥⎤=Tbc−1Twbj−1TwbiTbc⎣⎢⎢⎡λ1uciλ1vciλ11⎦⎥⎥⎤
将i帧中观测到的数据变换到相机坐标系,将相机坐标系变换到body坐标系,将第i个body坐标系变换到世界坐标系,将世界坐标系变换到第j个body坐标系,将body坐标系变换到相机坐标系,得到第j帧的预测值。这期间相对于纯视觉多了相机坐标系变换到body坐标系,然后再由body坐标系变换回相机坐标系的过程
。
视觉重投影误差为:
r c = [ x c i z c i − u c i y c i z c i − u c i ] r _c= \begin{bmatrix} \frac {x_{c_i}}{ z_{c_i}}-u_{c_i} \\ \frac {y_{c_i}}{ z_{c_i}}-u_{c_i} \\ \end{bmatrix} rc=[zcixci−ucizciyci−uci]
IMU 的真实值为 ω ω ω, a a a, 测量值为 ω ~ \tilde{ω} ω~, a ~ ã a~,则有:
ω ~ b = ω b + b g + n g a ~ = q b w ( a w + g w ) + b a + n a ω̃ ^b = ω^b + b^ g + n ^g\\ ã = q _{bw} (a ^w+g^w ) + b^a + n^a ω~b=ωb+bg+nga~=qbw(aw+gw)+ba+na
上标 g g g 表示 gyro, a a a 表示 acc, w w w 表示在世界坐标系 world, b b b 表示imu 机体坐标系 body。
PVQ 对时间的导数可写成:
p ˙ w b t = v t w v ˙ t w = a t w q ˙ w b t = q w b t ⊗ [ 0 1 2 w b t ] ṗ _{wb _t} = v _t^ w\\ v̇ _t^ w = a_ t^ w\\ q̇ _{wb _t} = q _{wb _t}⊗\begin{bmatrix} 0\\ \frac12w^{b_t}\\ \end{bmatrix} p˙wbt=vtwv˙tw=atwq˙wbt=qwbt⊗[021wbt]
从第 i 时刻的 PVQ 对 IMU 的测量值进行积分得到第 j 时刻的 PVQ:
p w b j = p w b i + v i w ∆ t + ∬ t ∈ [ i , j ] ( q w b t a b t − g w ) δ t 2 v j w = v i w + ∫ t ∈ [ i , j ] ( q w b t a b t − g w ) δ t q w b j = ∫ t ∈ [ i , j ] q w b t ⊗ [ 0 1 2 w b t ] p_{wb_j} = p_{wb_i}+ v _i^ w ∆t +\iint_{t∈[i,j]}(q_{ wb _t} a ^{b t} − g ^w )δt^ 2\\ v _j ^w= v _i ^w+\int_{t∈[i,j]}(q_ {wb _t} a^{b_t} − g ^w )δt\\ q _{wb _j}=\int_{t∈[i,j]}q _{wb _t}⊗\begin{bmatrix} 0\\ \frac12w^{b_t}\\ \end{bmatrix} pwbj=pwbi+viw∆t+∬t∈[i,j](qwbtabt−gw)δt2vjw=viw+∫t∈[i,j](qwbtabt−gw)δtqwbj=∫t∈[i,j]qwbt⊗[021wbt]
每次 q wb t 优化更新后,都需要重新进行积分,运算量较大。所以引出下文预积分解决方案。
一个很简单的公式转换,就可以将积分模型转为预积分模型:
q w b t = q w b i ⊗ q b i b t q_{ wb _t} = q _{wb _i} ⊗ q _{b _i b _t} qwbt=qwbi⊗qbibt
那么,PVQ 积分公式中的积分项则变成相对于第 i 时刻的姿态,而不是相对于世界坐标系的姿态
:
p w b j = p w b i + v i w ∆ t − 1 2 g w ∆ t 2 + q w b i ∬ t ∈ [ i , j ] ( q b i b t a b t ) δ t 2 v j w = v i w − g w ∆ t + q w b i ∫ t ∈ [ i , j ] ( q b i b t a b t ) δ t q w b j = q w b i ∫ t ∈ [ i , j ] q b i b t ⊗ [ 0 1 2 w b t ] p_{wb_j} = p_{wb_i}+ v _i^ w ∆t -\frac12g^w∆t ^2+q_{wb_i}\iint_{t∈[i,j]}(q _{b _i b _t} a ^{b t} )δt^ 2\\ v _j ^w= v _i ^w-g^w∆t+q_{wb_i}\int_{t∈[i,j]}(q _{b _i b _t} a ^{b t} )δt\\ q _{wb _j}=q_{wb_i}\int_{t∈[i,j]}q _{b _i b _t} ⊗\begin{bmatrix} 0\\ \frac12w^{b_t}\\ \end{bmatrix} pwbj=pwbi+viw∆t−21gw∆t2+qwbi∬t∈[i,j](qbibtabt)δt2vjw=viw−gw∆t+qwbi∫t∈[i,j](qbibtabt)δtqwbj=qwbi∫t∈[i,j]qbibt⊗[021wbt]
预积分量仅仅跟 IMU 测量值有关
,它将一段时间内的 IMU 数据直接积分起来就得到了预积分量
:
α b i b j = ∬ t ∈ [ i , j ] ( q b i b t a b t ) δ t 2 β b i b j = ∫ t ∈ [ i , j ] ( q b i b t a b t ) δ t q b i b j = ∫ t ∈ [ i , j ] q b i b t ⊗ [ 0 1 2 w b t ] α _{b _i b _j} =\iint_{t∈[i,j]}(q _{b _i b _t} a ^{b t} )δt^ 2\\ β _{b _i b _j} = \int_{t∈[i,j]}(q _{b _i b _t} a ^{b t} )δt\\ q _{b _i b _j}=\int_{t∈[i,j]}q _{b _i b _t} ⊗\begin{bmatrix} 0\\ \frac12w^{b_t}\\ \end{bmatrix} αbibj=∬t∈[i,j](qbibtabt)δt2βbibj=∫t∈[i,j](qbibtabt)δtqbibj=∫t∈[i,j]qbibt⊗[021wbt]
重新整理下 PVQ 的积分公式,有:
[ p w b j v j w q w b j b j a b j g ] = [ p w b i + v i w ∆ t − 1 2 g w ∆ t 2 + q w b i α b i b j v i w − g w ∆ t + q w b i β b i b j q w b i q b i b j b i a b i g ] \begin{bmatrix} p_{wb_j} \\ v _j ^w \\ q _{wb _j} \\ b_j^a \\ b_j^g \end{bmatrix} = \begin{bmatrix} p_{wb_i}+ v _i^ w ∆t -\frac12g^w∆t ^2+q_{wb_i}α _{b _i b _j} \\ v _i ^w-g^w∆t+q_{wb_i}β _{b _i b _j} \\ q_{wb_i}q _{b _i b _j} \\ b_i^a \\ b_i^g \end{bmatrix} ⎣⎢⎢⎢⎢⎡pwbjvjwqwbjbjabjg⎦⎥⎥⎥⎥⎤=⎣⎢⎢⎢⎢⎡pwbi+viw∆t−21gw∆t2+qwbiαbibjviw−gw∆t+qwbiβbibjqwbiqbibjbiabig⎦⎥⎥⎥⎥⎤
定义:
一段时间内 IMU 构建的预积分量作为测量值,对两时刻之间的状态量进行约束,
[ r p r v r q r b a r b g ] 15 × 1 = [ q b i w ( p w b j − p w b i − v i w ∆ t + 1 2 g w ∆ t 2 ) − α b i b j q b i w ( v j w − v i w + g w ∆ t ) − β b i b j 2 [ q b j b i ⊗ ( q b i w ⊗ q w b j ) ] x y z b j a − b i a b j g − b i g ] \begin{bmatrix} r _p \\ r _v \\ r _q \\ r_{ba} \\ r_{bg} \end{bmatrix} _{15×1} = \begin{bmatrix} q_{b_iw}(p_{wb_j} -p_{wb_i}- v _i^ w ∆t + \frac12g^w∆t ^2)-α _{b _i b _j} \\ q_{b_iw}(v _j ^w - v _i ^w + g^w∆t) - β _{b _i b _j} \\ 2[q_{b _jb _i} ⊗ (q_{ b _i w} ⊗ q_{ wb _j} )] _{xyz} \\ b_j^a - b_i^a \\ b_j^g - b_i^g \end{bmatrix} ⎣⎢⎢⎢⎢⎡rprvrqrbarbg⎦⎥⎥⎥⎥⎤15×1=⎣⎢⎢⎢⎢⎡qbiw(pwbj−pwbi−viw∆t+21gw∆t2)−αbibjqbiw(vjw−viw+gw∆t)−βbibj2[qbjbi⊗(qbiw⊗qwbj)]xyzbja−biabjg−big⎦⎥⎥⎥⎥⎤
上面误差中位移,速度,偏置都是直接相减得到。第二项是关于四元数的旋转误差,其中 [·] xyz 表示只取四元数的虚部
(x, y, z) 组成的三维向量。
这里使用 mid-point 方法,即两个相邻时刻 k 到 k+1 的位姿是用两个时刻的测量值 a, ω 的平均值来计算:
一个 IMU 数据作为测量值的噪声方差我们能够标定。现在,一段时间内多个 IMU 数据积分形成的预积分量的方差
呢?
已知一个变量 y = A x , x ∈ N ( 0 , Σ x ) y = Ax, x ∈ N (0, Σ _x ) y=Ax,x∈N(0,Σx), 则有 Σ y = A Σ x A ⊤ Σ _y = AΣ _x A ^⊤ Σy=AΣxA⊤
Σ y = E ( ( A x ) ( A x ) ⊤ ) = E ( A x x ⊤ A ⊤ ) = A Σ x A ⊤ Σ _y = E((Ax)(Ax)^ ⊤ )\\ = E(Axx ^⊤ A ^⊤ )\\ = AΣ x A ^⊤ Σy=E((Ax)(Ax)⊤)=E(Axx⊤A⊤)=AΣxA⊤
所以,要推导预积分量的协方差,我们需要知道imu 噪声和预积分量之间的线性递推关系
。
假设已知了相邻时刻误差的线性传递方程:
η i k = F k − 1 η i k − 1 + G k − 1 n k − 1 η_{ ik} = F _{k−1} η _{ik−1} + G _{k−1} n _{k−1} ηik=Fk−1ηik−1+Gk−1nk−1
比如:状态量误差为 η i k = [ δ θ i k , δ v i k , δ p i k ] η_ {ik} = [δθ_{ ik} , δv _{ik} , δp _{ik} ] ηik=[δθik,δvik,δpik],测量噪声为 n k = [ n k g , n k a ] n _k = [n _k^ g , n _k^ a ] nk=[nkg,nka]。
误差的传递由两部分
组成:当前时刻的误差
传递给下一时刻,当前时刻测量噪声
传递给下一时刻。
综艺节目中常有传递信息的节目,前一个人根据上一个人的信息 + 自己的理解(测量)传递给下一个人,导致这个信息越传越错。
协方差矩阵可以通过递推计算得到:
Σ i k = F k − 1 Σ i k − 1 F k − 1 ⊤ + G k − 1 Σ n G k − 1 T Σ _{ik} = F _{k−1} Σ _{ik−1} F^ ⊤_{k−1} + G _{k−1} Σ _n G_{ k−1}^T Σik=Fk−1Σik−1Fk−1⊤+Gk−1ΣnGk−1T
其中, Σ n Σ _n Σn 是测量噪声的协方差矩阵,方差从 i 时刻开始进行递推, Σ i i = 0 Σ _{ii} = 0 Σii=0。
通常对于状态量之间的递推关系是非线性的方程如 x k = f ( x k − 1 , u k − 1 ) x _k = f (x _{k−1} , u _{k−1}) xk=f(xk−1,uk−1),其中状态量为 x x x, u u u 为系统的输入量。
我们可以用两种方法来推导状态误差传递的线性递推关系:
一种是基于一阶泰勒展开
的误差递推方程。
一种是基于误差随时间变化的递推方程
。
令状态量为 x = x ^ + δ x x = x̂ + δx x=x^+δx,其中,真值为 x ^ x̂ x^,误差为 δ x δx δx。另外,输入量 u u u 的噪声为 n n n。
非线性系统 x k = f ( x k − 1 , u k − 1 ) x _k = f (x _{k−1} , u _{k−1} ) xk=f(xk−1,uk−1) 的状态误差的线性递推关系如下:
δ x k = F δ x k − 1 + G n k − 1 δx_ k = Fδx _{k−1} + Gn_{ k−1} δxk=Fδxk−1+Gnk−1
其中,F 是状态量 x k x _k xk 对状态量 x k − 1 x _{k−1} xk−1 的雅克比矩阵,G 是状态量 x k x_ k xk对输入量 u k − 1 u _{k−1} uk−1 的雅克比矩阵。
证明:对非线性状态方程进行一阶泰勒展开有:
x k = f ( x k − 1 , u k − 1 ) x ^ k + δ x k = f ( x ^ k − 1 + δ x k − 1 , u ^ k − 1 + n k − 1 ) x ^ k + δ x k = f ( x ^ k − 1 , u ^ k − 1 ) + F δ x k − 1 + G n k − 1 x _k = f (x _{k−1} , u _{k−1} )\\ x̂ _k + δx_ k = f (x̂_{ k−1} + δx_{ k−1} , û_{ k−1} + n _{k−1} )\\ x̂ _k + δx _k = f (x̂ _{k−1}, û _{k−1} ) + Fδx_{ k−1} + Gn _{k−1} xk=f(xk−1,uk−1)x^k+δxk=f(x^k−1+δxk−1,u^k−1+nk−1)x^k+δxk=f(x^k−1,u^k−1)+Fδxk−1+Gnk−1
如果我们能够推导状态误差随时间变化的导数关系,比如:
δ x ′ = A δ x + B n δx^{'} =Aδx + Bn δx′=Aδx+Bn
则误差状态的传递方程为:
δ x k = δ x k − 1 + δ x k − 1 ′ ∆ t → δ x k = ( I + A ∆ t ) δ x k − 1 + B ∆ t n k − 1 δx _k = δx_{ k−1} + δx_{k−1} ^{'} ∆t\\ → δx _k = (I + A∆t)δx _{k−1}+ B∆tn_{k−1} δxk=δxk−1+δxk−1′∆t→δxk=(I+A∆t)δxk−1+B∆tnk−1
这两种推导方式的可以看出有:
F = I + A ∆ t , G = B ∆ t F = I + A∆t, G = B∆t F=I+A∆t,G=B∆t
这是因为 VIO 系统中已经知道了状态的导数和状态之间的转移矩阵。如:我们已经知道速度和状态量之间的关系:
v ˙ = R a b + g v̇ = Ra^ b + g v˙=Rab+g
那我们就可以推导速度的误差和状态误差之间的关系,再每一项上都加上各自的误差
就有:
v ˙ + δ v ˙ = R ( I + [ δ θ ] × ) ( a b + δ a b ) + ( g + δ g ) δ v ˙ = R δ a b + R [ δ θ ] × ( a b + δ a b ) + δ g δ v ˙ = R δ a b − R [ a b ] × δ θ + δ g v̇ + δv̇= R (I + [δθ] _× )( a ^b + δa ^b) + (g + δg)\\ δv̇= Rδa^ b + R[δθ]_ × (a ^b + δa^ b) + δg\\ δv̇= Rδa^ b - R[a^b]_ × δθ + δg v˙+δv˙=R(I+[δθ]×)(ab+δab)+(g+δg)δv˙=Rδab+R[δθ]×(ab+δab)+δgδv˙=Rδab−R[ab]×δθ+δg
由此就能依次类推,轻易写出整个 A 和 B 其他方程了。
首先回顾预积分的误差递推公式,将测量噪声也考虑进模型:
确定误差传递的状态量,噪声量,然后开始构建传递方程。
用前面一阶泰勒展开的推导方式 δ x k = F δ x k − 1 + G n k − 1 δx_ k = Fδx _{k−1} + Gn_{ k−1} δxk=Fδxk−1+Gnk−1,我们希望能推导出如下的形式:
F, G 为两个时刻间的协方差传递矩阵。
这里我们直接给出 F, G 的最终形式,后面会对部分项进行详细推导:
其中的系数为:
下面对F的第三行进行推导,其他行列的推导类似:
视觉残差为:
对于第 i 帧中的特征点,它投影到第 j 帧相机坐标系下的值为:
拆成三维坐标形式为:
再推导各类 Jacobian 之前,为了简化公式,先定义如下变量:
Jacobian 为视觉误差对两个时刻的状态量,外参,以及逆深度求导:
根据链式法则,Jacobian 的计算可以分两步走:
第一步误差对 f c j f _{c _j} fcj 求导:
第二步 f c j 对各状态量求导:
在求解非线性方程时,需要知道误差 e B 对两个关键帧 i, j 的状态量p, q, v, b a , b g 的 Jacobian。
对 i, j 时刻的状态量 p, q, v 求导还是比较直观的,直接对误差公式进行计算就行。但是对 i 时刻的 b ai , b gi 求导就显得十分复杂,下面我们详细讨论。
因为 i 时刻的 bias 相关的预积分计算是通过迭代一步一步累计递推的,可以算但是太复杂。所以对于预积分量直接在 i 时刻的 bias 附近用一阶泰勒展开来近似,而不用真的去迭代计算。
其中
表示预积分量对 i 时刻的 bias 求导。
这些雅克比根据前面讨论的协方差传递公式,能一步步递推得到:
下面我们来讨论 IMU 误差相对于两帧的 PVQ 的 Jacobian:
由于 r p 和 r v 的误差形式很相近,对各状态量求导的 Jacobian 形式也很相似,所以这里只对 r v 的推导进行详细介绍。
对rp的推导过程:
5. 对 i 时刻姿态求导
上式可化简为:
其中 [·] L 和 [·] R 为四元数转为左/右旋转矩阵的算子。
6. 角度误差对 j 时刻姿态求导
7. 角度误差对 i 时刻陀螺仪偏置 b gi
这公式……我傻了!!!
相关资料: