SLAM代码(设计模式)

对于“面向对象”撸代码的程序猿同志们,有本必备的书的叫做《设计模式-可复用面向对象软件的基础》。那么而在slam的实现中有没有这一种或者几种可以总结归纳的设计模式呢?

我们在看一些slam的书的时候,有些要么就是介绍很多状态估计的理论,要么就是介绍很多多视几何的各种视觉理论。那么我们在看了这些理论之后,仍然无法下手,那么一个典型的好的slam的代码的基本结构是什么样的呢?一个slam代码的基本结构是怎样的?有哪些基本要素?

这里一个自然的想法就是从图像中获取想要的定位的信息。在机器人移动的过程中相机捕捉到一个图像序列。在这个图像序列中机器人看到周围的景物是在按照一定的规律移动和变化的,那么景物移动的规律和机器人自身移动的规律有什么关系呢?这个关系可以根据空间变换来确定。

那么如何根据图像序列的内容提取景物的移动规律呢?可以跟踪图像上景物的一些点,图像很多点的统计规律可以表征景物的移动规律。这就是提取特征点进行跟踪或者直接使用灰度点跟踪的意义所在,根据我们使用的点的方式不容,可以看到两种不容的slam前端分方法——直接法和特征法。

那么如何实现这样的跟踪器呢?slam算法在读到一张图像之后,首先把当前图像的点和前一帧图像的点对应起来,那么需要多少个点对应呢?怎么实现点对应呢?基于特征的方法是提取图像中的特征点用于匹配不同图像中相同的点,这是一种思路,常用的有sift orb等。另外一个思路是由于机器人的运动相对于图像的帧率较慢的时候,图像的内容变化较小,因此在局部搜索可以找到上一帧图像的点的位置,这就是直接法的思路。

我们这里引入一个Frame结构,为了实现上述的跟踪器,第一步是读取图像,通过图像的数据估计当前帧对应的位姿状态。场景中相同的点在不同的视角中构成一个基础矩阵的关系,一个图像帧的图像平面和另一帧的图像的平面之间构成单应矩阵的关系。使用最小二乘法通过图像点可以计算得到单应矩阵和基础矩阵,,使用矩阵奇异值分解(SVD)可将单应矩阵或者基础矩阵分解恢复出位姿变化。这些内容的实现可以放到Frame结构,也可以像ORB那样专门放到一个Initializer里边。Frame需要和Map完成互动。除了需要计算当前帧的位姿,还要完成特征点的三维重建。有的方法使用了一个深度滤波器,如SVO,LSD中考虑了极线与深度的夹角,这样会得到一个半稠密的地图。因为稠密的地图点想要试试完成一般是需要使用GPU来完成的。图像的上的特征点和空间中的三维点如何对应呢?常用的方法是PnP。PnP是已知三维点计算相机位姿,三维重建是已知相机位姿计算三维点。

PnP的计算中需要知道相机的内参数,这里引入第二个结构相机模型Camera,他保存并管理相机的参数,进行一些图像空间到世界空间的转换,完成图像点(关键特征点)的去畸变。

如何解决累计误差问题,常用的方法是使用路标点和当前图像点进行匹配估计相机的运动,这时候需要存储这些路标点的描述子。另外一方面在LSD-SLAM, SVO等方法中,是怎样存储路标点的呢?这里引入一个结构叫做Mappoint

如何评价一个路标点的好坏程度?如何如何保存病管理这些路标点呢?路标点的添加删除等管理工作可以放入另外一个结构Map中进行。地图中以何种形式保存这些路标呢,一种方法是路标放在图像帧里作为关键帧KeyFrame进行保存和提取。关键帧串起来成为一个地图。这样做的好处就是我们使用了关键帧继承了帧的性质,便于以后特征点匹配。在前边累计相机运动的时候参考帧是前一帧图像,这里的参考帧是关键帧的图像。关键帧是相机运动过程中保留了重要信息的最小集合中的元素。理论上关键帧是没有重叠的。后端优化的对象主要是关键帧。

那么我们换一个角度来看问题,从时间轴上,我们关心的的有两个状态,一个当前的时刻,另外一个以前的时刻。对于当前的时刻我们要保持实时性。对于以前的时刻我们要通过他来提高精度。这就是为什么要分开来做前端和后端的问题。 事实上,优化并非仅仅存在与后端,优化存在与前端的运动估计中(基础矩阵计算,于运动估计的计算),后端中关键帧的优化(BA)。这些优化中形成矩阵结构H是稀疏的(对应图网络),可以显式的利用图优化表示。H的稀疏性为图优化方法的SLAM提供了实时性的保证。这里可以引入一个结构Optimizater,用来完成上述内容中提到的各种优化工作。我们这里总结一下可以优化的步骤是那些呢?

  • 三维点(点的深度)的优化(三角测量)
  • 后端的关键帧中的位姿和路标点的BA(关键帧的边缘化)
  • 初始化过程的单应矩阵和基础矩阵的优化
  • PnP计算相机位姿

注意

有些VO的算法中由于后端很小,所以吧后端的内容一起移到了前端,然后每一帧都做一次BA,这样要求H矩阵(BA中的被优化结构)一定要保持稀疏性。

维护一个地图的另外一个好处就是即使当前跟踪的某一帧丢失,之后跟踪上的帧任然就可以恢复出运动。这样的前提是一个不断跟新的地图,而且这个地图是正确的。这样的地图可以是局部的也可以全局的。全局地图的规模较大(更像SLAM,可以完成闭环),计算量比较大,因此适用于一些要求精确定位的地方,对于一些计算能力弱的场合适用于局部地图(更像一个VO,不能做闭环)。在局部地图中,考虑需要丢掉一些之前的帧,这个过程叫做marginalization(边缘化)。

跟踪器的状态有几种,1. 初始化,顺利跟踪,丢失。因此我们还需要一个初始化的过程,这个过程中有哪些内容?对第一/二帧图像的匹配,单应和基础矩阵的计算。这个其实在Frame结构中涉及过。那么可以构建一个Initializer,完成相应的工作。

到这里,slam只是完成了一部分,可以称之为前端吧。我们在之后的内容接续介绍关于后端的设计方法和一些模块的关系总结。

    原文作者:wendox
    原文地址: https://blog.csdn.net/wendox/article/details/53454768
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞