Python写基于非线性优化的2D-SLAM系统(已开源)


Github代码地址:
https://github.com/liuzhenboo/2D-SLAM-By-Nonlinear-Optimization

1. SLAM问题概率模型

1.1 最大后验到最小二乘

SLAM问题其实就是一个状态估计的问题,就是要根据一系列观测来推测状态量;一般情况下,我们把SLAM问题建立在概率论的框架下。

说白了,SLAM就是要是解决这样一类后验概率问题:

p ( x ∣ z ) p(x|z) p(xz)

其中 x x x是系统当前状态量, z z z是与状态量相关的观测量;在求出这个条件概率之后,把观测值 Z Z Z带入,就可以获得 p ( x ∣ z = Z ) p(x|z=Z) p(xz=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(xz=Z)=p(z=Z)p(z=Zx)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(xz=Z)=ηp(z=Zx)p(x)

p ( z ∣ x ) p(z|x) p(zx)表示在 x x x已知的情况下, z z z的概率分布;在求出 p ( z ∣ x ) p(z|x) p(zx)之后,把 z = Z z=Z z=Z带入,得到 p ( z = Z ∣ x ) p(z=Z|x) p(z=Zx),它也被称为似然项,它表示在 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=Zx)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=xargmaxip(zi=Zix)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[ilogp(zi=Zix)logp(x)]
如果假设观测 p ( z i ∣ x ) p(z_i|x) p(zix)服从高斯分布 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(xpx)那么有:

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=xargminizihi(x)i2+xxpx2

如果没有先验知识,那么可以写为:

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=xargminizihi(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)=21e(x)Σe2=21e(x)TΣe1e(x)

J i ( x ) = ∂ e i ( x ) ∂ x J_i(x)=\frac {\partial e_i(x)} {\partial x} Ji(x)=xei(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] xe(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)=[x1ei(x)...xnei(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Σe1e(x+δx)21e(x)TΣe1e(x)+δxTJTΣe1e(x)+21δxTJTΣe1Jδx

所以损失函数就转换为关于 δ x \delta x δx的二次函数,并且如果 J T Σ e − 1 J J^T\Sigma _e^{-1}J JTΣe1J正定,那么损失函数有最小值。

对上式关于 δ 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Σe1Jδx=JTΣe1e(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

  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台发的技术细节和最佳实践,逐步培养起自己的项目发和问题解决能力。此外,在求职或创业过程中,具备跨平台发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值