视觉SLAM理论与实践学习笔记(一)
二 熟悉linux
1. 如何在 Ubuntu 中安装软件(命令行界⾯)?它们通常被安装在什么地⽅?
2. linux 的环境变量是什么?我如何定义新的环境变量?
3. linux 根目录下⾯的目录结构是什么样的?至少说出 3 个目录的用途。
4. 假设我要给 a.sh 加上可执行权限,该输入什么命令?
5. 假设我要将 a.sh ⽂件的所有者改成 xiang:xiang,该输入什么命令?
三 SLAM综述文献阅读
1. SLAM 会在哪些场合中用到?至少列举三个⽅向。
2. SLAM 中定位与建图是什么关系?为什么在定位的同时需要建图?
3. SLAM 发展历史如何?我们可以将它划分成哪几个阶段?
4. 列举三篇在 SLAM 领域的经典文献。
四 Cmake练习
五 理解ORB-SLAM2框架
1. 从 github.com 下载 ORB-SLAM2 的代码。
2. 代码结构
(a) ORB-SLAM2 将编译出什么结果?有⼏个库⽂件和可执⾏⽂件?
(b) ORB-SLAM2 中的 include, src, Examples 三个⽂件夹中都含有什么内容?
(c) ORB-SLAM2 中的可执⾏⽂件链接到了哪些库?它们的名字是什么?
六 使用摄像头或视频运行ORB-SLAM2
1. 编译 ORBSLAM2
2. 如何将 myslam.cpp或 myvideo.cpp 加⼊到 ORB-SLAM2 ⼯程中?请给出你的 CMakeLists.txt 修改⽅案
(1)将myslam.cpp和myvidoe.cpp都放到Examples/Monocular文件夹下,并修改myslam.cpp和myvideo.cpp中加载文件的路径。
(2)因为修改了加载文件的路径,所以将myvideo.yaml、myvideo.mp4、ORBvoc.txt都放到Examples/Monocular文件夹下。
(3)修改ORB_SLAM2/CMakeLists.txt,加入以下内容
3. 运行myvideo和myslam
(1)myvideo
(2)myslam
二 熟悉linux
计算机领域的绝⼤多数科研⼈员都在 Linux 下⼯作,不掌握 Linux 会使你在研究道路上⼨步难⾏。Linux 系统的基本知识亦是学习本课程的先决条件。如果你还未接触过 Linux,请阅读本次习题中提供的材料(见 books/⽬录下)。我建议阅读《鸟哥的 Linux 私房菜》第 1、 2 章了解 Linux 历史,第 5-8 章了解基础操作。如果你在⽤ Ubuntu,也可以参考 Ubuntu 维基上⾃带的指南: http://wiki.ubuntu.org.cn/Ubuntu.
不要把 Linux 想得太困难。现代的 Linux 系统多数具有⽅便的图形界⾯,⼗分容易上⼿。最好的学习⽅式可能是马上安装⼀个 Linux 然后熟悉它的操作界⾯,多数时候和 Windows/mac 差别不⼤。我们在本书中使⽤ Ubuntu 16.04,读者也可以按个⼈⼜味选择任意适合你的发⾏版,不过最好使⽤ Ubuntu 系列,这样我和你的操作⽅式会⽐较相似。等你熟悉 Linux 后,请回答以下问题(如果你已经很熟悉,就跳过上⾯的阅读内容,直接回答即可):

1. 如何在 Ubuntu 中安装软件(命令行界⾯)?它们通常被安装在什么地⽅?
命令中常用的安装软件方式有两种:
(1)apt-get 方式
$ sudo apt-get install software_name
(2)dpkg方式
$ sudo dpkg -i package_name.deb
软件的默认安装位置为 /usr/bin

2. linux 的环境变量是什么?我如何定义新的环境变量?
在 Linux 系统中,环境变量是用来定义系统运行环境的一些参数,比如每个用户不同的家目录(HOME)、邮件存放位置(MAIL)等。
(1)临时设置:
$ export PATH=my_path
(2)用户设置:
$ sudo gedit ~/.bashrc
添加export PATH=my_path
$ source ~/.bashrc
(3)系统全局设置:
$ sudo gedit /etc/profile
添加:
$ export PATH=my_path
$ source /etc/profile

3. linux 根目录下⾯的目录结构是什么样的?至少说出 3 个目录的用途。
/home 系统默认的用户家目录。在新增一个一般使用者账号时,默认的用户家目录都会规范到这里来。
/bin 包含二进制可执行文件,系统所有用户可执行文件都在这个文件夹里,例如:ls,cp,ping等。
/sbin 包含二进制可执行文件,但只能由系统管理员运行,对系统进行维护。
/dev 包含终端所有设备,USB或连接到系统的任何设备。例如:/dev/tty1、/dev/usbmon0
/usr 包含二进制文件、库文件、文档和二级程序的源代码。
/etc 存放系统的所有配置文件。
/mnt 临时安装目录,系统管理员可以挂载文件系统。
/lib 包含支持位于/bin和/sbin下的二进制文件的库文件
/proc 包含系统进程的相关信息。
/root root用户的主目录
/boot 包含引导加载程序相关的文件。内核的initrd、vmlinux、grub文件位于/boot下。
/var 软件运行所产生的文件或者数据库文件
/tmp 包含系统和用户创建的临时文件。当系统重新启动时,这个目录下的文件都将被删除。
/opt 包含从个别厂商的附加应用程序。附加应用程序应该安装在/opt/或者/opt/的子目录下。
/media 用于挂载可移动设备的临时目录。
/srv 包含服务器特定服务相关的数据。例如,/srv/cvs包含cvs相关的数据。
/run 最常用的就是存放进程的ID。
/srv 网络服务启动以后所取用的数据目录。
/sys 同/proc非常类似,记录与内核相关的信息。

4. 假设我要给 a.sh 加上可执行权限,该输入什么命令?
$ chmod a+x a.sh

5. 假设我要将 a.sh ⽂件的所有者改成 xiang:xiang,该输入什么命令?
$ chown xiang:xiang a.sh

三 SLAM综述文献阅读
当你对某个研究领域不了解时,最好是从综述⽂献开始了解这个领域的整体⾯貌。 SLAM 作为⼀个近30 年的研究领域,⾄今也存在着⼤量的综述、总结类的⽂章。请阅读本次作业 paper/⽬录下的⽂章 [1–3](其中 [3] 是中⽂⽂献),了解这个领域的⼤致情况。如果你的时间有限,可以仅阅读每篇⽂章的第⼀章(也就是引⾔⼀章),然后回答下列问题:

1. SLAM 会在哪些场合中用到?至少列举三个⽅向。
增强现实,自动驾驶,高风险或恶劣环境的救援任务,行星、陆地、空中和海洋的探索。

2. SLAM 中定位与建图是什么关系?为什么在定位的同时需要建图?
定位与建图是相互依赖的,为了精确地移动,机器人必须有一个精确的环境地图;然而,要建立一个精确的地图,必须要知道移动机器人的感知位置,因此,在定位的同时需要建图。所以,同时定位与建图可以比喻为先有鸡还有先有蛋?

3. SLAM 发展历史如何?我们可以将它划分成哪几个阶段?
(1)The classical age (1986-2004):经典时代,SLAM的主要概率公式的引入,包括扩展卡尔曼滤波器、RBPF和最大似然估计的方法;此外,它指出了与效率与鲁棒性的数据关联有关的基本挑战。
(2)the algorithmic-analysis age (2004-2015):算法分析时代,研究了SLAM的基本特性,包括可观测性、收敛性和一致性。在这一时期,稀疏性对高效SLAM求解的关键作用也得到了理解,主要的开源SLAM库也得到了开发。
(3)the robust-perception age(2015-至今):鲁棒感知时代,其中主要的性能指标包括鲁棒性能、高层次的理解、资源认知、任务推断。

4. 列举三篇在 SLAM 领域的经典文献。
(1)MSCKF:
AI Mourikis,SI Roumeliotis, A Multi-State Constraint Kalman Filter for Vision-aided Inertial Navigation. [J]. IEEE International Conference on Robotics & Automation.2007
(2)ORB-SLAM2:
Mur-Artal R , Tardos J D . ORB-SLAM2: An Open-Source SLAM System for Monocular,Stereo, and RGB-D Cameras[J]. IEEE Transactions on Robotics, 2017:1-8.
(3)VINS-Mono:
Qin Tong, Li Peiliang, Shen Shaojie. VINS-Mono: A Robust and Versatile MonocularVisual-Inertial State Estimator[J]. IEEE Transactions on Robotics:1-17.

四 Cmake练习
cmake 是⼀种常⽤、⽅便的,⽤于组织 Linux 下 C++ 程序的⼯具。有许多库,例如 OpenCV、 g2o、Ceres 等,都⽤ cmake 组织它们的⼯程。所以,不管是使⽤别⼈的库,还是编写⾃⼰的库,都需要掌握⼀些 cmake 的基本知识。也许你之前没有听过这个⼯具,但不要紧,我们准备了阅读材料“books/CmakePractice.pdf”(cmake 实践,由⼀位北⼤同学撰写)。请阅读此⽂的第 1 ⾄ 6 章,并完成以下⼯作:书写⼀个由 cmake 组织的 C++ ⼯程,要求如下:

include/hello.h 和 src/hello.c 构成了 libhello.so 库。 hello.c 中提供⼀个函数 sayHello(),调⽤此函数时往屏幕输出⼀⾏“Hello SLAM”。我们已经为你准备了 hello.h 和 hello.c 这两个⽂件,见“code/”⽬录下。
⽂件 useHello.c 中含有⼀个 main 函数,它可以编译成⼀个可执⾏⽂件,名为“sayhello”。
默认⽤ Release 模式编译这个⼯程。
如果⽤户使⽤ sudo make install,那么将 hello.h 放⾄/usr/local/include/下,将 libhello.so 放
⾄/usr/local/lib/下。
请按照上述要求组织源代码⽂件,并书写 CMakeLists.txt。
解答:
为了便于理解流程,我创建了两个CMake工程,test1用来生成libhello.so库,test2通过链接test1创建的库来输出“Hello SLAM”。
(1)test1
test1的目录结构如下图所示:
在这里插入图片描述

test1/CMakeLists.txt:

SET(CMAKE_BUILD_TYPE "Release")
PROJECT(HELLOLIB)
ADD_SUBDIRECTORY(lib)

test1/lib/CMakeLists.txt:

SET(CMAKE_BUILD_TYPE "Release")
SET(LIBHELLO_SRC hello.cpp)
ADD_LIBRARY( hello SHARED ${LIBHELLO_SRC} )
INSTALL(TARGETS hello LIBRARY DESTINATION lib)
INSTALL(FILES hello.h DESTINATION include/hello)

之后创建build文件夹进行编译,这里有一个细节,为了将库安装到自己电脑的/usr/local下,所以cmake的指令是$ cmake -DCMAKE_INSTALL_PREFIX=/usr/local ..,之后正常编译安装就可以了。

在这里插入图片描述

(2)test2
test2的目录结构如下图所示:
在这里插入图片描述

test2/CmakeLists.txt

SET(CMAKE_BUILD_TYPE "Release")
PROJECT(USEHELLO)
ADD_SUBDIRECTORY(src)

test2/src/CmakeLists.txt:

SET(CMAKE_BUILD_TYPE "Release")
ADD_EXECUTABLE(sayhello useHello.cpp)
INCLUDE_DIRECTORIES(/usr/local/include/hello)
TARGET_LINK_LIBRARIES(sayhello hello)

之后创建build文件夹进行编译,运行可执行文件输出“Hello SLAM”:
在这里插入图片描述

五 理解ORB-SLAM2框架
ORB-SLAM2[4] 是⼀个⾮常经典的视觉 SLAM 开源⽅案,它可以作为你学习 SLAM 的范本。但是现在我们还没有讲解很多关于视觉 SLAM 的知识,所以仅从代码⼯程⾓度上来了解 ORB-SLAM2。请按照提⽰完成以下⼯作。

从 github.com 下载 ORB-SLAM2 的代码。
地址在: https://github.com/raulmur/ORB_SLAM2.提⽰:在安装 git 之后,可以⽤ git clone https://github.com/raulmur/ORB_SLAM2 命令下载ORB-SLAM2。下载完成后,请给出终端截图。
在这里插入图片描述

2. 代码结构
此时我们不着急直接运⾏ ORB-SLAM2,让我们⾸先来看它的代码结构。 ORB-SLAM2 是⼀个cmake ⼯程,所以可以从 CMakeLists.txt 上⾯来了解它的组织⽅式。阅读 ORB-SLAM2 代码⽬录
下的 CMakeLists.txt,回答问题:

(a) ORB-SLAM2 将编译出什么结果?有⼏个库⽂件和可执⾏⽂件?
编译结果:生成多个可执行文件程序和多个库文件。
库文件:通过/src文件夹中的.cc文件生成动态库文件ORB_SLAM2
可执行文件:rgbd_tum、stereo_kitti、stereo_euroc、mono_tum、mono_kitti、mono_euroc

(b) ORB-SLAM2 中的 include, src, Examples 三个⽂件夹中都含有什么内容?
include文件夹:包含了src中程序的函数头文件
src文件夹:包含了生成库的c++源文件
Examples文件夹:各数据集测试文件和相机参数文件

© ORB-SLAM2 中的可执⾏⽂件链接到了哪些库?它们的名字是什么?
(1) ORB_SLAM2/lib/ libORB_SLAM2.so
(2) OPENCV_LIBS
(3) EIGEN3_LIBS
(4) Pangolin_LIBRARIES
(5) ORB_SLAM2/Thirdparty/DBoW2/lib/libDBoW2.so
(6) ORB_SLAM2/Thirdparty/g2o/lib/libg2o.so

你会发现 ORB-SLAM2 从代码组织⽅式来看并不复杂。实际上⼤部分中⼩型库都不会很复杂,⽽更⼤的库可能在 CMakeLists.txt 中有各种各样的兼容性检查,确保它们在各个平台上都能顺利运⾏。现在你已经了解了 ORB-SLAM2 的代码结构了。抛开代码内容来说,⾄少你已经知道如何编译,使⽤这个库了。 ORB-SLAM2 可以在数据集上运⾏,也可以在实际的摄像头上运⾏。下⾯的作业将指导你⽤⾃⼰的笔记本摄像头来运⾏ ORB-SLAM2。

六 使用摄像头或视频运行ORB-SLAM2
请注意本题为附加题。
了解⼀样东西最快的⽅式是⾃⼰上⼿使⽤它,不要担⼼弄坏你的笔记本,⼤部分时候它都是你可靠的伙伴。这个作业中,我将指导你⽤⾃⼰的笔记本摄像头读取到的图像,来运⾏ ORB-SLAM2,看看它能不能实际⼯作。你也可以外接⼀个 usb 摄像头,这会让你的⼿更加灵活⼀些(不⽤费⼒端着笔记本到处跑)。或者,如果你的电脑碰巧没有摄像头/摄像头故障了/你正在⽤虚拟机,那我们也可以在事先录制好的⼀段视频中运⾏ ORB-SLAM2(见 code/myvideo.mp4,这是我在特蕾西亚草坪散步的时候⽤⼿机拍摄的⼩视频)。由于我们还没有讲过任何关于 OpenCV 或者图像⽅⾯的问题,所以本节我给你写好了⼀个 myslam.cpp⽂件(如果你使⽤录制视频,请⽤ myvideo.cpp)。这个⽂件会打开你⾃带的摄像头(或视频),读取图像,并交给 ORB-SLAM2 处理。由于你现在已经了解 cmake 原理了,所以我要请你⾃⼰来思考如何将这个⽂件与 ORB-SLAM2 结合起来。相信我,这件事并不难。 myslam.cpp 和 myvideo.cpp ⽂件见本次作业的code/⽂件夹下。
下⾯是本题的提⽰:

编译 ORBSLAM2
为了实际运⾏ ORB-SLAM2,你需要安装它的依赖项,并通过它本⾝的编译。它的依赖项见它⾃⼰的 github 主页,请按照主页上的提⽰安装好 ORB-SLAM2 的依赖项。具体来说,对于 pangolin(⼀个 GUI 库),你需要下载并安装它,它同样是个 cmake ⼯程,所以我不必谈怎么编译安装的细节了。对于 opencv 和 eigen3,你可以简单的⽤⼀⾏命令来解决:
sudo apt-get install libopencv-dev libeigen3-dev libqt4-dev qt4-qmake libqglviewer-dev libsuitesparse-dev libcxsparse3.1.2 libcholmod-dev其中⼀部分是 g2o 的依赖项,现阶段不⽤太在意它的具体内容。⾄此,你应该可以顺利编译 ORBSLAM2 了,请给出它编译完成的截图。
由于之前编译过了,没有保存截图,所以再次编译,就会出现以下结果

在这里插入图片描述

2. 如何将 myslam.cpp或 myvideo.cpp 加⼊到 ORB-SLAM2 ⼯程中?请给出你的 CMakeLists.txt 修改⽅案
注意到, ORB-SLAM2 提供了若⼲数据集中的运⾏⽰例,这可以作为我们运⾏⾃⼰摄像头程序的参考,因为它们很相似。对于数据集上的⽰例, ORB-SLAM2 会⾸先读取数据集中的图像,再放到SLAM 中处理。那么对于我们⾃⼰的摄像头,同样可以这样处理。所以最⽅便的⽅案是直接将我们的程序作为⼀个新的可执⾏程序,加⼊到 ORB-SLAM2 ⼯程中。那么请问,如何将 myslam.cpp或 myvideo.cpp 加⼊到 ORB-SLAM2 ⼯程中?请给出你的 CMakeLists.txt 修改⽅案。

在这里插入图片描述
myslam.cpp:
在这里插入图片描述

2)因为修改了加载文件的路径,所以将myvideo.yaml、myvideo.mp4、ORBvoc.txt都放到Examples/Monocular文件夹下。

在这里插入图片描述

3)修改ORB_SLAM2/CMakeLists.txt,加入以下内容

add_executable(myvideo Examples/Monocular/myvideo.cpp)
target_link_libraries(myvideo ${PROJECT_NAME})

add_executable(myslam Examples/Monocular/myslam.cpp)
target_link_libraries(myslam ${PROJECT_NAME})

3. 运行myvideo和myslam
现在你的程序应该可以编译出结果了。但是我们现在还没有谈相机标定,所以你还没办法标定你的摄像头。但没有关系,我们也可以⽤⼀个不那么好的标定参数,先来试⼀试效果(所幸 ORB-SLAM2对标定参数不太敏感)。我为你提供了⼀个 myslam.yaml(myvideo.yaml),这个⽂件是我们假想的标定参数。现在,⽤这个⽂件让 ORB-SLAM2 运⾏起来,看看 ORB-SLAM2 的实际效果吧。请给出运⾏截图,并谈谈你在运⾏过程中的体会。

(1)myvideo
在这里插入图片描述

(2)myslam

在这里插入图片描述

注意,本题只需你能运⾏ ORB-SLAM2 即可,并不是说“成功地运⾏ SLAM”。要顺利运⾏ SLAM 还需要⼀些经验和技巧,希望你能在动⼿过程中有所体会。作为建议,请尽量在光照充⾜、纹理丰富的场合下运⾏程序。如果默认参数不合适,你也可以尝试换⼀换参数。