2021.1.23 ——ORBSLAM2 代码学习之路(一)

第三十九天

   今天进行了第一次学习,感觉确实比自己一个人看能好很多,还能和其他人讨论,老师也会提醒一些地方。
感谢我优秀的同学的总结:
orb-slam2代码详解之mono kitti
orb-slam2代码详解之system

   我用自己的思路进行一下记录,注意,以下内容是对上述博客的。由于解读代码资料中已很详尽,除非一我认为些非常重要的地方,我的注释重点是代码的整体逻辑。

介绍一下,这是TZDOG
介绍一下,这是TZDOG

一、从mono_kitti.cc开始

    mono 指单目,kitti是数据集名称,因此这是一个使用单目kitti数据集的示例程序。
   必须要注意的一点是,这个文件是在EXAMPLE下,也就是说它是一个用ORBSLAM写的程序,而不是ORBSLAM的源码,虽然这个程序几乎都在跑它的源码。换句话说,ORBSLAM的究极目的,依然是个“工具库”。遗憾的是,这个库可不像<a+b_prb.h>那样通俗易懂,我们接下来就得花大功夫学习它,但在这之前,我们先搞定这个mono_kitti.cc。


    假设有一只TZDOG写完了毁天灭地ORBSLAM2,但是它的导师让它写个基于数据集的单目测试程序——要不然别人装上怎么知道好不好使。
    TZDOG想了想,既然ORBSLAM是ok的,那么它只需要:

  1. 将包括数据集的必要参数传给程序。
  2. 用ORBSLAM处理数据
  3. 将SLAM计算结果保存(不然算个啥)

说干就干!

将包括数据集的必要参数传给程序

    TZDOG的orbslam库需要字典库和一些冗杂的配置文件(除非你想自己设置),当然,最重要的需要有数据集。
    TZDOG 希望你这样使用样例文件:

./mono_kitti   path_to_vocabulary   path_to_settings     path_to_sequence
可执行文件     词典位置        配置文件路径       数据集所在路径

    幸运的是前两者基本是固定的,也就是说TZDOG早都准备好了,而数据集的路径你必须填写正确。

用ORBSLAM处理数据

   虽然有了数据,但这个数据还不够真实——实际的系统一次只会收到一张图片,而不是所有图片数据
   TZDOG没有办法,它不可能将所有图片都读到内存里,只好写了LoadImages函数,通过参数3将每个图片的路径保存下来,用来一帧一帧读。
   TZDOG实例初始化了SLAM对象,并将前两个参数传进去,它们是SLAM程序运行所需要的。ORB_SLAM2::SystemSLAM(argv[1],argv[2],ORB_SLAM2::System::MONOCULAR,true);
   TZDOG写了个循环,他按照数据集时间戳的时间精确地向这个实例化的SLAM对象传入每次读取的mat(就像下图一样),并记录了每次的处理时间。
在这里插入图片描述

将SLAM计算结果保存

   当处理完全部数据后,TZDOG的第一件事就是 SLAM.Shutdown();以免出什么问题
   TZDOG检查了一下每一帧处理用时的平均数和中位数,最后将计算的相机运行轨迹保存下来:SLAM.SaveKeyFrameTrajectoryTUM(“KeyFrameTrajectory.txt”);

GG

   现在TZDOG完成了测试任务,他写了个类似仿真的文件,将“虚假的数据”伪造成“真实的数据”,成功骗过了SLAM算法!

二、System.cc 之 构造函数

   时光倒转,TZDOG回到了他设计ORBSLAM核心类System的时候。System可是算法的核心,它的构造函数更是和心中的核心。追踪、建图、闭环检测三座大山都再次起步。

   TZDOG 决定让构造函数完成下列功能:

①用词袋初始化关键帧数据库( 用于 重定位 和 回环检测 )

②初始化一个Map类,该类用于存储指向所有 关键帧 和 地图点 的指针

③初始化画图工具,用于可视化。

④初始化 Tracking线程 ,主线程 ,使用this指针(只初始化不启动,启动在 main 函数里 TrackMonocular() 启动)

⑤初始化 Local Mapping线程 并启动(这里mSensor传入MONOCULAR)

⑥初始化 Loop Closing线程 并启动(这里mSensor传入的不是MONOCULAR)

⑦初始化 Viewer线程 并启动,也使用了this指针;给 Tracking线程设置Viewer

⑧三个线程每两个线程之间设置指针


   由于TZDOG爱讲狗语,所以我们需要稍微翻译一下:

   首先,TZDOG会检验传入字典路径和配置文件路径的合法性,然后:

  1. TZDOG用一个自己写的Database容器,接住了我们传入的字典,然后用字典建立了关键帧数据库,他会在重定位和回环检测时很有用!
    在这里插入图片描述

  2. TZDOG创建自己写的了Map容器,用来存储关键帧和地图点,当然,包括两个显示线程在内的其他地方都有用到它。 在这里插入图片描述

  3. TZDOG初始化了两个画图工具,它们就是在外面运行程序时实时显示运行结果的两个界面,初始化它们的时候用到了配置文件里的strsetting.(所以配置文件是有用的)

  4. 初始化第一座大山:Tracking,三座大山三座线程,幸运的是main函数自己的线程可不能浪费,它就是tracking线程(因此其中一个传入指针是this,后面还包括词典、Map容器等。)。

  5. 初始化第二座大山:LocalMapping + 启动LocalMapping线程,理所当然,传入的数据是Map容器指针和传感器类型,因为在这里插入图片描述在这里插入图片描述

  6. 初始化第三作大山:LoopClosing + 启动LoopClosing 线程 ,传入的数据与前面类似。

  7. TZDOG 初始化显示窗口对象,也就是画图线程,当然,如果你让它显示了的话。

  8. TZDOG 将三个线程之间的指针两两传递给对方,因为三个线程是一个整体,之间难免互通数据,更不要说共享信息 Map 和字典数据库了,提前告诉对方的位置有利于交流。

TZDOG通过上面八件事明白了三个道理:
1.下面这两部分三座大山都会使用
在这里插入图片描述
2.为了避免“三座大山”直接调用底层数据类,TZDOG机智地使用底层数据类初始化一个作为中间量的参数类,再通过线程,将参数类作为参数,传入给“大山”的Run()函数中去。
3.告别全局变量,从new和指针调用做起。

GG

TZDOG觉得今天写完构造就不错了,决定先歇歇,毕竟它是一只懒狗。

附录

数据集

   顾名思义,就是拿记录的真实数据去测试程序,很多数据集包含的信息非常多,有陀螺仪和其他传感器信息,但对于slam来说有图像信息就足够了。
kitti 数据集(这个是测试无人驾驶的数据集)
TUM数据集

string streams

    char*解放者、变量类型的克星、字符串处理yyds。
   stringstream类能够自动将传入的字符串,按照接收容器的类型进行转换,且不会存在缓冲区溢出问题,比sprintf更安全。stringstream

多线程

   多线程,就是一个程序跑几个同时进行的任务,一般是通过thread(Taskfun,Para)调用的,其中Para是Taskfun的参数,而后者内一般都有死循环,TZDOG的SLAM除了main跑traking外,其他"两座大山"通过线程调用实现。
   尽管TZDOG给各个线程之间传递了参数,但是线程之间的数据传输很复杂,因为我们必须避免任何一个资源被两个线程同时使用,当然,TZDOG会在底层处理好的。详情请见开头文章。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值