文章目录
Github代码地址:
https://github.com/liuzhenboo/2D-SLAM-By-Nonlinear-Optimization
1. SLAM问题概率模型
1.1 最大后验到最小二乘
SLAM问题其实就是一个状态估计的问题,就是要根据一系列观测来推测状态量;一般情况下,我们把SLAM问题建立在概率论的框架下。
说白了,SLAM就是要是解决这样一类后验概率问题:
p ( x ∣ z ) p(x|z) p(x∣z)
其中 x x x是系统当前状态量, z z z是与状态量相关的观测量;在求出这个条件概率之后,把观测值 Z Z Z带入,就可以获得 p ( x ∣ z = Z ) p(x|z=Z) p(x∣z=Z),这也就是我们需要的分布。
根据概率公式展开:
p ( x ∣ z = Z ) = p ( z = Z ∣ x ) p ( x ) p ( z = Z ) p(x|z=Z)=\frac{p(z=Z|x)p(x)}{p(z=Z)} p(x∣z=Z)=p(z=Z)p(z=Z∣x)p(x)
其中分母是常量,当作是归一化因子 η \eta η即可,所以也可写为:
p ( x ∣ z = Z ) = η p ( z = Z ∣ x ) p ( x ) p(x|z=Z)=\eta{p(z=Z|x)p(x)} p(x∣z=Z)=ηp(z=Z∣x)p(x)
p ( z ∣ x ) p(z|x) p(z∣x)表示在 x x x已知的情况下, z z z的概率分布;在求出 p ( z ∣ x ) p(z|x) p(z∣x)之后,把 z = Z z=Z z=Z带入,得到 p ( z = Z ∣ x ) p(z=Z|x) p(z=Z∣x),它也被称为似然项,它表示在 x x x取不同值的情况下, z = Z z=Z z=Z的概率。
p ( x ) p(x) p(x)也被称为先验,也就是在观测之前 x x x服从什么分布。这可以通过其他信息源得到,比如GPS,惯导等。如果事前不知道任何先验分布信息,那么可以将其设为1,表示不相信先验信息,只根据系统使用的量测来估计。
x M A P = a r g m a x x p ( z = Z ∣ x ) p ( x ) x_{MAP}= \mathop{argmax}\limits_{x}p(z=Z|x)p(x) xMAP=xargmaxp(z=Z∣x)p(x)
因为每次观测相互独立,所以上式可以写为:
x M A P = a r g m a x x ∏ i p ( z i = Z i ∣ x ) p ( x ) x_{MAP}= \mathop{argmax}\limits_{x}\prod_{i}p(z_i=Z_i|x)p(x) xMAP=xargmaxi∏p(zi=Zi∣x)p(x)
取负对数得到:
x M A P = a r g m i n x [ − ∑ i l o g p ( z i = Z i ∣ x ) − l o g p ( x ) ] x_{MAP}=\mathop{argmin}\limits_{x}\left[-\sum_ilogp(z_i=Z_i|x)-logp(x)\right] xMAP=xargmin[−i∑logp(zi=Zi∣x)−logp(x)]
如果假设观测 p ( z i ∣ x ) p(z_i|x) p(zi∣x)服从高斯分布 N ( h i ( x ) , ∑ i ) N(h_i(x),\sum_i) N(hi(x),∑i);先验 p ( x ) p(x) p(x)服从 N ( x p , ∑ x ) N(x_p,\sum_{x}) N(xp,∑x)那么有:
x M A P = a r g m i n x ∑ i ∣ ∣ z i − h i ( x ) ∣ ∣ ∑ i 2 + ∣ ∣ x − x p ∣ ∣ ∑ x 2 x_{MAP}=\mathop{argmin}\limits_{x}\sum_{i}||z_i-h_i(x)||^2_{\sum_i}+||x-x_p||^2_{\sum_x} xMAP=xargmini∑∣∣zi−hi(x)∣∣∑i2+∣∣x−xp∣∣∑x2
如果没有先验知识,那么可以写为:
x M A P = a r g m i n x ∑ i ∣ ∣ z i − h i ( x ) ∣ ∣ ∑ i 2 x_{MAP}=\mathop{argmin}\limits_{x}\sum_{i}||z_i-h_i(x)||^2_{\sum_i} xMAP=xargmini∑∣∣zi−hi(x)∣∣∑i2
显而易见,在SLAM的过程中,不断有新的残差项加入到系统,上述最小乘问题不断扩大。
1.2 非线性优化求解
设当前时刻状态向量为x,维度为n,我们将残差表示成向量的形式:
e ( x ) = [ e 1 ( x ) . . . e m ( x ) ] e(x) = \left[\begin{matrix} e_1(x) \\ ... \\ e_m(x) \end{matrix}\right] e(x)=⎣⎡e1(x)...em(x)⎦⎤
这里我们使用马氏范数,损失函数定义为:
E ( x ) = 1 2 ∣ ∣ e ( x ) ∣ ∣ Σ e 2 = 1 2 e ( x ) T Σ e − 1 e ( x ) E(x) =\frac{1}{2}||e(x)||^2_{\Sigma_e}= \frac{1}{2}{e(x)}^T\Sigma_e^{-1}e(x) E(x)=21∣∣e(x)∣∣Σe2=21e(x)TΣe−1e(x)
记 J i ( x ) = ∂ e i ( x ) ∂ x J_i(x)=\frac {\partial e_i(x)} {\partial x} Ji(x)=∂x∂ei(x),那么可以得到:
∂ e ( x ) ∂ x = J = [ J 1 ( x ) . . . J m ( x ) ] \frac {\partial e(x)}{\partial x}= J = \left[\begin{matrix} J_1(x) \\ ... \\ J_m(x) \end{matrix}\right] ∂x∂e(x)=J=⎣⎡J1(x)...Jm(x)⎦⎤
J i ( x ) = [ ∂ e i ( x ) ∂ x 1 . . . ∂ e i ( x ) ∂ x n ] J_i(x) =\left[\begin{matrix} \frac {\partial e_i(x)} {\partial x_1} ... \frac {\partial e_i(x)} {\partial x_n} \end{matrix}\right] Ji(x)=[∂x1∂ei(x)...∂xn∂ei(x)]
对残差函数泰勒展开,得到一阶近似:
e ( x + δ x ) ≈ e ( x ) + J δ x e(x+\delta x) \approx e(x)+J\delta x e(x+δx)≈e(x)+Jδx
那么带入损失函数可以近似得到:
E ( x + δ x ) = 1 2 e ( x + δ x ) T Σ e − 1 e ( x + δ x ) ≈ 1 2 e ( x ) T Σ e − 1 e ( x ) + δ x T J T Σ e − 1 e ( x ) + 1 2 δ x T J T Σ e − 1 J δ x E(x+\delta x) = \frac{1}{2}{e(x+\delta x)}^T\Sigma_e^{-1}e(x+\delta x) \\ \approx \frac{1}{2}{e(x)}^T\Sigma _e^{-1}e(x)+{\delta x}^T J^T \Sigma_e^{-1}e(x)+\frac{1}{2}{\delta x}^TJ^T\Sigma_e^{-1}J\delta x E(x+δx)=21e(x+δx)TΣe−1e(x+δx)≈21e(x)TΣe−1e(x)+δxTJTΣe−1e(x)+21δxTJTΣe−1Jδx
所以损失函数就转换为关于 δ x \delta x δx的二次函数,并且如果 J T Σ e − 1 J J^T\Sigma _e^{-1}J JTΣe−1J正定,那么损失函数有最小值。
对上式关于 δ x \delta x δx求一阶导数,并另其为零,得:
J T Σ e − 1 J δ x = − J T Σ e − 1 e ( x ) J^T\Sigma_e^{-1}J\delta x = -J^T\Sigma_e^{-1}e(x) JTΣe−1Jδx=−JTΣe−1e(x)
也常常写为
H δ x = b H\delta x = b Hδx=b
这样就可以得到增量 δ x \delta x δx,这样一直迭代,就可以不断优化当前解,直到误差小于阈值。这种方法被称为高斯牛顿法。
不过在实际中,求解上述方程需要 H H H矩阵可逆,而我在编程中,经常遇到 H H H不可逆的情况,所以实际代码中我使用了Levenberg-Marquardt法。其是对高斯牛顿法进行了改进,增加了阻尼因子一项,如下所示:
( H + μ I ) δ x = b (H+\mu I)\delta x = b (H+μI)δx=b
这