视觉SLAM入门 -- 学习笔记 - Part 1

熟悉Linux

1. 如何在Ubuntu 中安装软件(命令⾏界⾯)?它们通常被安装在什么地⽅?

ubuntu下安装软件有四种方式:
①通过deb格式的离线软件包安装

sudo dpkg -i xxx.deb # 安装包,安装程序 -i: install
sudo dpkg -r package # 删除包 -r: remove

此法的默认安装目录为: /opt

②通过apt-get包管理器从软件源中在线安装(最常用的方式)

sudo apt-get install 软件名 # 安装
sudo apt-get remove 软件名 # 卸载
sudo apt-get update #更新源

软件的安装缓存位置: /var/cache/apt/archieve
安装后软件默认位置: /usr/share
可执行文件位置 : /usr/bin
配置文件位置: /etc
lib文件位置:/usr/lib

注:以下命令可以查看包的位置

dpkg -L 软件名

③直接解压gzip等压缩格式文件,会在bin目录下找到一个xxx.sh的可执行文件

此法的默认安装目录为:解压缩的目录

xxx.tar.gz文件解压方式:

tar -zxvf **.tar.gz

2. linux 的环境变量是什么?我如何定义新的环境变量?
(1)环境变量是操作系统中一个具有特定名字的对象,它包含了一个或者多个应用程序所将使用到的信息。例如Windows系统中的path环境变量,当要求系统运行一个程序而没有告诉它程序所在的完整路径时,系统除了在当前目录下面寻找此程序外,还可以到path中指定的路径去找。用户通过设置环境变量,来更好的运行进程。

(2)如果我们要将 /tmp/test 路径加入到 $PATH 变量(环境变量)中,有以下3种方法
① 控制台中设置 (只对当前shell有效)

export PATH=$PATH:/tmp/test

② 修改当前home目录下的 .bashrc 文件 (只对当前用户有效)

命令行输入:

vim ~/.bashrc #编辑配置文件

在最末尾加入:

export PATH=$PATH:/tmp/test # 加入环境变量

保存后返回命令行输入:

source ~/.bashrc #使配置文件生效。

③ 修改/etc/bashrc 文件 (针对所有用户有效)

sudo vim /etc/profile

在最末尾加入

export PATH=$PATH:/tmp/test

保存后返回命令行输入:

source /etc/profile

注:source命令通常用于重新执行刚修改的初始化文件,使之立即生效,而不必注销并重新登录。

3. linux 根⽬录下⾯的⽬录结构是什么样的?⾄少说出3 个⽬录的⽤途。
linux根目录结构:
视觉SLAM入门 -- 学习笔记 - Part 1_第1张图片
1)/bin 用户二进制文件
包含二进制可执行文件,系统所有用户可执行文件都在这个文件夹里,例如:ls,cp,ping等。

2)/sbin 系统二进制文件
包含二进制可执行文件,但只能由系统管理员运行,对系统进行维护。

3)/boot 引导加载程序文件
包含引导加载程序相关的文件。内核的initrd、vmlinux、grub文件位于/boot下。

4)/dev 设备文件
包含终端所有设备,USB或连接到系统的任何设备。例如:/dev/tty1、/dev/usbmon0

5)/etc 配置文件
包含所有程序配置文件,也包含了用于启动/停止单个程序的启动和关闭shell脚本。

6)/home HOME目录
所有用户用来存档他们的个人档案。

7)/lib 系统库
包含支持位于/bin和/sbin下的二进制文件的库文件,库文件名为 ld或lib.so.*

8)/media 可移动媒体设备
用于挂载可移动设备的临时目录
举例来说,挂载CD-ROM的/media/cdrom,挂载软盘驱动器的/media/floppy;

9)/mnt 挂载目录
临时安装目录,系统管理员可以挂载文件系统。

10)/opt 可选的附加应用程序
opt代表opitional;包含从个别厂商的附加应用程序。附加应用程序应该安装在/opt/或
者/opt/的子目录下。

11)/proc 进程信息
包含系统进程的相关信息
这是一个虚拟的文件系统,包含有关正在运行的进程的信息。例如:/proc/{pid}目录中包含的与特定pid相关的信息。

12)/srv 服务数据
srv代表服务。包含服务器特定服务相关的数据。例如,/srv/cvs包含cvs相关的数据。

13)/tmp 临时文件
包含系统和用户创建的临时文件。当系统重新启动时,这个目录下的文件都将被删除。

14)/usr 用户程序
包含二进制文件、库文件、文档和二级程序的源代码
/usr/bin 中包含用户程序的二进制文件。如果你在/bin 中找不到用户二进制文件,到/usr/bin目录看看。例如:at、awk、cc、less、scp。
/usr/sbin 中包含系统管理员的二进制文件。如果你在/sbin 中找不到系统二进制文件,
到/usr/sbin目录看看。例如:atd、cron、sshd、useradd、userdel。
/usr/lib中包含了/usr/bin和/usr/sbin用到的库。
/usr/local 中包含了从源安装的用户程序。例如,当你从源安装Apache,它会在/usr/local/apache2中。

15)/var 变量文件
可以找到内容可能增长的文件。这包括 - 系统日志文件(/var/log);包和数据库文件(/var/lib);电子邮件(/var/mail);打印队列(/var/spool);锁文件(/var/lock);多次重新启动需要的临时文件(/var/tmp);

4. 假设我要给a.sh 加上可执⾏权限,该输⼊什么命令?

chmod +x a.sh

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

chown xiang:xiang a.sh

格式:

chown 用户名:组名 文件名

如果是修改目录下所有子文件和子目录所有者

chown -R 用户名:组名 /目录

SLAM 综述文献阅读

1. SLAM 会在哪些场合中⽤到?⾄少列举三个⽅向。
手持设备定位:利用SLAM为手持设备定位
VR/AR :根据 SLAM 得到地图和当前视角对叠加虚拟物体做相应渲染,这样做可以使得叠加的虚拟物体看起来比较真实,没有违和感;
无人机领域,SLAM可以构建局部地图,辅助无人机进行自主避障、规划路径;
无人驾驶领域, SLAM 技术可以提供视觉里程计功能,然后跟其他的定位方式融合;
机器人定位导航领域:SLAM 可以用于生成环境的地图。机器人基于该地图执行路径规划、自主探索、导航等任务。

2. SLAM 中定位与建图是什么关系?为什么在定位的同时需要建图?
关系:
定位与建图= 内外兼修
定位侧重对自身的了解, 建图侧重对外在的了解

原因:
定位与建图相互关联, 准确的定位需要精确的地图;精确的地图来自准确的定位

3. SLAM 发展历史如何?我们可以将它划分成哪⼏个阶段?
SLAM是由Smith Self 和Cheeseman于1986年首次提出,距今为止已经发展了30多年,其主要发展历程可划分为以下3个时代:

①传统时代classical age(1986-2004):SLAM问题的提出,并将该问题转换为一个状态估计问题,利用扩展卡尔曼滤波、粒子滤波及最大似然估计等手段来求解。
②算法分析时代algorithmic-analysis age(2004-2015):研究SLAM的基本特性,包括观测性、收敛性和一致性。
③鲁棒性-预测性时代robust-perception(2015-):鲁棒性、高级别的场景理解,计算资源优化,任务驱动的环境感知。
视觉SLAM是在传统SLAM的基础上发展起来的,早期的视觉SLAM多采用扩展卡尔曼滤波等手段来优化相机位姿的估计和地图构建的准确性,后期随着计算能力的提升及算法的改进,BA优化、位姿优化等手段逐渐成为主流。随着人工智能技术的普及,基于深度学习的SLAM越来越受到研究者的关注。

4. 从什么时候开始SLAM 区分为前端和后端?为什么我们要把SLAM 区分为前端和后端?

SLAM系统结构出现前后端应该是在出现基于视觉的SLAM方法之后,推测应该在2010年之后。

SLAM系统的体系结构包括两个主要部分:前端(或者叫视觉里程计)与后端。
前端将传感器数据抽象成适用于估计的模型,估算相邻图像间相机的运动,以及局部地图的样子,也称为"视觉里程计"
后端接受不同时刻视觉里程计测量的相机位姿,以及回环检测的信息,对它们进行优化,得到全局一致的轨迹和地图。
前后端所实现的功能不同,目的不同。

5. 列举三篇在SLAM 领域的经典⽂献。

[1]Smith, R.C. and P. Cheeseman, On the Representation and Estimation of Spatial Uncertainty. International Journal of Robotics Research, 1986. 5
[2]Se, S., D. Lowe and J. Little, Mobile robot localization and mapping with uncertainty using scale­invariant visual landmarks. The international Journal of robotics Research, 2002. 21
[3]Mullane, J., et al., A Random­Finite­Set Approach to Bayesian SLAM. IEEE Transactions on Robotics, 2011

CMake 练习

1. include/hello.h 和src/hello.c 构成了libhello.so 库。hello.c 中提供⼀个函数sayHello(),调⽤此函数时往屏幕输出⼀⾏“Hello SLAM”。我们已经为你准备了hello.h 和hello.c 这两个⽂件,见“code/”⽬录下。
hello.h

#pragma once
void sayHello(); 

hello.c

#include "hello.h"
#include 

void sayHello() {std::cout<<"Hello SLAM"<<std::endl;}

2. ⽂件useHello.c 中含有⼀个main 函数,它可以编译成⼀个可执⾏⽂件,名为“sayhello”。

useHello.cpp:

#include "hello.h"

int main( int argc, char** argv ) {
  sayHello();
}

3. 默认⽤Release 模式编译这个⼯程。

4. 如果⽤户使⽤sudo make install,那么将hello.h 放⾄/usr/local/include/下,将libhello.so 放⾄/usr/local/lib/下。

请按照上述要求组织源代码⽂件,并书写CMakeLists.txt。
CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(hello)
if (NOT CMAKE_BUILD_TYPE)
    set(CMAKE_BUILD_TYPE "Release")
endif()

include_directories(${PROJECT_SOURCE_DIR}/include)
add_library(hello SHARED src/hello.cpp)

add_executable(useHello useHello.cpp)
target_link_libraries(useHello hello)

install(TARGETS hello LIBRARY DESTINATION /usr/local/lib)
install(FILES "./include/hello.h" DESTINATION /usr/local/include)

命令行:
视觉SLAM入门 -- 学习笔记 - Part 1_第2张图片

5. 为你的库提供 FindHello.cmake 文件,让其他用户可以通过 find_package 命令找到你的库,并实际测试你的程序确实可以这样做。

FindHello.cmake

FIND_PATH(HELLO_INCLUDE_DIR hello.h /usr/local/include)
FIND_LIBRARY(HELLO_LIBRARY NAMES hello PATH /usr/local/lib)

if(HELLO_INCLUDE_DIR AND HELLO_LIBRARY)
    set(HELLO_FOUND TRUE)
endif()

if(HELLO_FOUND)
    if(NOT HELLO_FIND_QUIETLY)
        message(STATUS "Found Hello: ${HELLO_LIBRARY}")
    endif()
else()
    if(HELLO_FIND_QUIETLY)
        message(FATAL_ERROR "Could not find hello library")
    endif()
endif()

CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(hello)
set(CMAKE_BUILD_TYPE "Realease")
message(STATUS "BUILD_TYPE = " ${CMAKE_BUILD_TYPE})

# include_directories(${PROJECT_SOURCE_DIR}/include)
# add_library(hello SHARED src/hello.cpp)

# add_executable(useHello useHello.cpp)
# target_link_libraries(useHello hello)

# install(TARGETS hello LIBRARY DESTINATION /usr/local/lib)
# install(FILES "./include/hello.h" DESTINATION /usr/local/include)

set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)

FIND_PACKAGE(HELLO REQUIRED)

if (HELLO_FOUND)
    message(STATUS "hello found")
endif()
message(STATUS "HELLO_INCLUDE_DIR = " ${HELLO_INCLUDE_DIR})
message(STATUS "HELLO_LIBRARY = " ${HELLO_LIBRARY})

include_directories(HELLO_INCLUDE_DIR)

add_executable(useHello useHello.cpp)
target_link_libraries(useHello ${HELLO_LIBRARY})


命令行
视觉SLAM入门 -- 学习笔记 - Part 1_第3张图片
CMake练习源码

理解ORB-SLAM2 框架

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

  1. 从github.com 下载ORB-SLAM2 的代码。地址在:

https://github.com/raulmur/ORB_SLAM2

提⽰:在安装git 之后,可以⽤git clone https://github.com/raulmur/ORB_SLAM2 命令下载
ORB-SLAM2。下载完成后,请给出终端截图。
视觉SLAM入门 -- 学习笔记 - Part 1_第4张图片

  1. 此时我们不着急直接运⾏ORB-SLAM2,让我们⾸先来看它的代码结构。ORB-SLAM2 是⼀个cmake ⼯程,所以可以从CMakeLists.txt 上⾯来了解它的组织⽅式。阅读ORB-SLAM2 代码⽬录下的CMakeLists.txt,回答问题:
    (a)ORB-SLAM2 将编译出什么结果?有⼏个库⽂件和可执⾏⽂件?
    答:编译结果:输出多个可执行文件程序和多个库文件。
    库文件:ORB_SLAM2(通过/src文件夹中的.cc文件生成动态库文件) (${PROJECT_NAME} 为 ORB_SLAM2)

对应原文件内容:

add_library(${PROJECT_NAME} SHARED
src/System.cc
src/Tracking.cc
src/LocalMapping.cc
src/LoopClosing.cc
src/ORBextractor.cc
src/ORBmatcher.cc
src/FrameDrawer.cc
src/Converter.cc
src/MapPoint.cc
src/KeyFrame.cc
src/Map.cc
src/MapDrawer.cc
src/Optimizer.cc
src/PnPsolver.cc
src/Frame.cc
src/KeyFrameDatabase.cc
src/Sim3Solver.cc
src/Initializer.cc
src/Viewer.cc
)

可执行文件:rgbd_tum、stereo_kitti、stereo_euroc、mono_tum、mono_kitti、mono_euroc

对应原文件内容:

add_executable(rgbd_tum Examples/RGB-D/rgbd_tum.cc)
target_link_libraries(rgbd_tum ${PROJECT_NAME})

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/Examples/Stereo)

add_executable(stereo_kitti Examples/Stereo/stereo_kitti.cc)
target_link_libraries(stereo_kitti ${PROJECT_NAME})

add_executable(stereo_euroc Examples/Stereo/stereo_euroc.cc)
target_link_libraries(stereo_euroc ${PROJECT_NAME})


set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/Examples/Monocular)

add_executable(mono_tum Examples/Monocular/mono_tum.cc)
target_link_libraries(mono_tum ${PROJECT_NAME})

add_executable(mono_kitti Examples/Monocular/mono_kitti.cc)
target_link_libraries(mono_kitti ${PROJECT_NAME})

add_executable(mono_euroc Examples/Monocular/mono_euroc.cc)
target_link_libraries(mono_euroc ${PROJECT_NAME})

(b)ORB-SLAM2 中的 include, src, Examples 三个⽂件夹中都含有什么内容?
答:include包含src中.cc程序代码的头文件
src包含相应程序所调函数的c++源文件
Examples包含针对不同类别相机的主程序
(c)ORB-SLAM2 中的可执⾏⽂件链接到了哪些库?它们的名字是什么?
答:链接到以下库:
(1)OPENCV_LIBS
(2)EIGEN3_LIBS
(3)Pangolin_LIBRARIES
(4)/ORB-SLAM2/Thirdparty/DBoW2/lib/libDBoW2.so
(5)/ORB-SLAM2/Thirdparty/g2o/lib/libg2o.so

对应原文件内容:

target_link_libraries(${PROJECT_NAME}
${OpenCV_LIBS}
${EIGEN3_LIBS}
${Pangolin_LIBRARIES}
${PROJECT_SOURCE_DIR}/Thirdparty/DBoW2/lib/libDBoW2.so
${PROJECT_SOURCE_DIR}/Thirdparty/g2o/lib/libg2o.so
)

使用摄像头或视频运行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/⽂件夹下。

下⾯是本题的提⽰:

  1. 为了实际运⾏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
了,请给出它编译完成的截图。

视觉SLAM入门 -- 学习笔记 - Part 1_第5张图片

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

在末尾加入:

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/Examples/MyVideo)

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

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

视觉SLAM入门 -- 学习笔记 - Part 1_第6张图片

2021-12-12更新

深蓝学院的课程开始越来越卷了,课程作业迎来了一次大更新,加量不加价,含泪血赚!

后面我将针对新的变动陆续更新各章的内容

熟悉Linux

1. 请描述apt-get 安装软件的整体步骤,说明Ubuntu 是如何管理软件依赖关系和软件版本的。

答:
①我们一般用的时候,都是 **sudo apt-get install 《package name》**就行了,要深究其过程的话:

  1. 扫描本地存放的软件包更新列表(由“apt-get
    update”命令刷新更新列表,也就是/var/lib/apt/lists/),找到最新版本的软件包;
  2. 进行软件包依赖关系检查,找到支持该软件正常运行的所有软件包;
  3. 从软件源所指 的镜像站点中,下载相关软件包;
  4. 解压软件包,并自动完成应用程序的安装和配置。

②​ Ubuntu上用与Debian一样的Deb软件管理工具,apt-get就是Ubuntu的Deb软件管理工具,即APT包管理工具。这个软件会从Ubuntu的软件源库里调用安装所需要安装的包,而且可以自动分析和解决依赖关系,并且将所依赖的软件都搞定。Ubuntu如果想安装指定版本的软件,可以在安装时在安装包名后边指定所要安装的版本即可。

2. 什么是软件源?如何更换系统自带的软件源?如何安装来自第三方软件源中的软件?

答:
①软件源(软件仓库)一般指debian系操作系统的应用程序安装包仓库,其中存放大量的软件包,apt会从软件源中下载软件,在/ect/apt/soure.list中可以为apt配置软件源。
②更新系统自带软件源:

# 这里尽量添加新的软件源,而不要删除掉原来自带的ubuntu软件源
 sudo gedit/etc/apt/sources.list 
# 添加源  
# 国内开源镜像站点汇总https://www.asfor.cn/server/mirror/index.html 
sudo apt-get update

③这个问题最上面的第一问就是了

3. 除了apt-get 以外,还有什么方式在系统中安装所需软件?除了Ubuntu 以外,其他发行版使用什么软件管理工具?请至少各列举两种。

答:
①还可以用Ubuntu自带的软件商店搜索、官网下载软件deb,gz.tar等类型的安装包、github下载的包大多要pip或make安装

②其它发行版本的软件管理工具:
在这里插入图片描述

4. 环境变量PATH 是什么?有什么用途?LD_LIBRARY_PATH 是什么?指令ldconfig 有什么用途?

答:
① ② 最上面第2问
③ LD_LIBRARY_PATH:程序已经成功编译并且链接成功后,使用LD_LIBRARY_PATH来搜索目录,该变量中只有动态库有意义。
④ ldconfig:一个动态链接库管理命令,主要是在默认搜寻目录(/lib和/usr/lib)以及动态库配置文件/etc/ld.so.conf内所列的目录下,搜索出可共享的动态链接库(lib.so),进而创建出动态装入程序(ld.so)所需的连接和缓存文件。缓存文件默认为/etc/ld.so.cache,此文件保存已排好序的动态链接库名字列表。

5. Linux 文件权限有哪几种?如何修改一个文件的权限?

答:
① 访问权限规定三种不同类型的用户:

  • 文件属主(Owner): 文件的所有者,称为属主。
  • 同组用户(Group):文件属组的同组用户。
  • 其它用户(Others):可以访问文件的其他用户。
    ② 字母形式修改权限;即“用户对象 操作符号 操作权限”
    chmod [options] mode files

6. Linux 用户和用户组是什么概念?用户组的权限是什么意思?有哪些常见的用户组?

答:
用户:分为普通用户、管理员用户(root用户)和系统用户。普通用户在系统上的任务是进行普通的工作,root用户对系统具有绝对的控制权,但操作不当会对系统造成损毁。所以在进行简单任务是进行使用普通用户。

用户组:用户组是用户的容器,通过组,我们可以更加方便的归类、管理用户。用户能从用户组继承权限,一般分为普通用户组,系统用户组,私有用户组。当创建一个新用户时,若没有指定他所属于的组,系统就建立一个与该用户同名的私有组。当然此时该私有组中只包含这个用户自己。标准组可以容纳多个用户,若使用标准组,在创建一个新的用户时就应该指定他所属于的组。

7. 常见的Linux 下C++ 编译器有哪几种?在你的机器上,默认用的是哪一种?它能够支持C++ 的哪个标准?

答:编辑器一般是gcc和g++,我这里默认是g++,支持C++11标准

gflags ,glog ,gtest 的使用

Google 提供了一系列非常好用的 C++ 工具,例如 gflags ,glog ,gtest 这三件套。这些程序在很多工程应用中都会用到。我们趁这个机会来熟悉它们。

  • glog 是日志打印工具;
  • gflag 是参数管理工具;
  • gtest是单元测试工具;

当我们在开发自己的应用时,可以灵活地使用这些三方库,加快算法的开发效率。

1. 请自行寻找这三个库的说明文档,并在系统中安装它们。请说明你是如何安装的。
【视觉SLAM】—Gtest/ Glog/ Gflags安装

CmakeLists.txt(适用 2、3、 4 题)

cmake_minimum_required(VERSION 3.17)
project(new_homework)

include(FetchContent)
FetchContent_Declare(
        googletest
        # Specify the commit you depend on and update it regularly.
        URL https://github.com/google/googletest/archive/609281088cfefc76f9d0ce82e1ff6c30cc3591e5.zip
)
## For Windows: Prevent overriding the parent project's compiler/linker settings
#set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(googletest)

set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_FLAGS_RELEASE "-std=c++11 -03 -fopenmp -pthread")


list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)

find_package(GFlags REQUIRED)
find_package(Glog REQUIRED)

include_directories(
        ${GFLAGS_INCLUDE_DIRS}
        ${GLOG_INCLUDE_DIRS}
        )

add_executable(glog glog.cpp)
target_link_libraries(glog ${GLOG_LIBRARIES})

add_executable(gflag gflag.cpp)
target_link_libraries(gflag ${GFLAGS_LIBRARIES})


add_executable(gtest_example gtest.cpp)
target_link_libraries(gtest_example gtest_main gmock_main pthread)

2. 将上一题中的打印改为使用 glog 的打印方式,以替代 std::cout 的输出方式。

#include 

int main(int argc, char **argv){
	//cout << "Hello World" << endl;	

    google::InitGoogleLogging(argv[0]);
    FLAGS_logtostderr = false; //设置日志消息是否转到标准输出而不是日志文件
    FLAGS_alsologtostderr = true; //设置日志消息除了日志文件之外是否去标准输出
    FLAGS_log_prefix = true;  //设置日志前缀是否应该添加到每行输出
    FLAGS_log_dir = "./log";    //预创建好
    LOG(INFO) << "Hello World" ;
}

3. 在 useHello.c 中增加一个 gflag 以指明打印的次数 print_times,默认为 1。当用户传递该参数时,即打印多少遍 Hello SLAM。

#include 
#include 

using namespace std;
// 使用gflags的宏定义
DEFINE_uint32(print_times, 1, "to print times");

int main(int argc, char** argv){
    //    调用解析函数(ParseCommandLineFlags)解析命令行
    //    https://zhuanlan.zhihu.com/p/95889124
    google::ParseCommandLineFlags(&argc, &argv, true);
	
    for (int i = 0; i < FLAGS_print_times; ++i) {
        cout << "Hello World" << endl;
    }
}

4. 书写一个 gtest 单元测试程序来测试你的工程能够正常运行。修改你的 CMakeLists.txt 来增加这个单元测试。

#include
using namespace std;
#include

///斐波那契数列
int fibo(int i) {
    if (i <= 0) {
        return 0;
    }
    if (i == 1 || i == 2) {
        return 1;
    }

    return fibo(i - 1) + fibo(i - 2);
}

TEST(TestGtestDemo, gtest_bool) {
    ASSERT_TRUE(3 == (1 + 1));  //这里会返回Failure
    ASSERT_FALSE(3 == 1);
}

TEST(TestGtestDemo, gtest_binary) {
    ASSERT_EQ(1, 1);  // 判断是否相等
    ASSERT_NE(1, 2);  // 判断是否不相等
    ASSERT_LT(1, 2);  // 判断是否小于
    ASSERT_LE(2, 2);  // 判断是否小于等于
    ASSERT_GT(2, 1);  // 判断是否大于
    ASSERT_GE(2, 2);  // 判断是否大于等于
}

TEST(TestGtestDemo, gtest_string) {
    ASSERT_STREQ("str1", "str1");  // 判断字符串是否相等
    ASSERT_STRNE("str1", "str2");  // 判断字符串是否不相等
    ASSERT_STRCASEEQ("STR1", "str1");  // 判断字符串是否相等,忽视大小写
    ASSERT_STRCASENE("Str1", "sTr2");  // 判断字符串是否不相等,忽视大小写
}

TEST(TestFibo, test_fibo_1) {
    int res = fibo(0);
    EXPECT_EQ(res, 0);
}

TEST(TestFibo, test_fibo_2) {
    int res = fibo(1);
    EXPECT_EQ(res, 1);
}

TEST(TestFibo, test_fibo_3) {
    int res = fibo(2);
    EXPECT_EQ(res, 1);
}

TEST(TestFibo, test_fibo_4) {
    int res = fibo(3);
    EXPECT_EQ(res, 2);
}

TEST(TestFibo, test_fibo_5) {
    int res = fibo(4);
    EXPECT_EQ(res, 3);
}
int main(int argc,char *argv[])
{
    testing::InitGoogleTest(&argc,argv);
    return RUN_ALL_TESTS();
}

输出:
视觉SLAM入门 -- 学习笔记 - Part 1_第7张图片

注意:如果使用clion的话,要自己加一个CMake Application
视觉SLAM入门 -- 学习笔记 - Part 1_第8张图片
完整项目

参考:

https://blog.csdn.net/qq_15698613/article/details/86551670
https://blog.csdn.net/ywk_hax/article/details/82505799
https://www.cnblogs.com/shuo1208/p/5927248.html
https://www.cnblogs.com/linuxAndMcu/p/11022532.html
https://blog.csdn.net/whut_chengjun/article/details/103069881

https://blog.csdn.net/li_my_linux/article/details/83094640
https://zhuanlan.zhihu.com/p/411036811

https://blog.csdn.net/hly453/article/details/86064424
https://blog.csdn.net/qq_21830903/article/details/95209007

深蓝学院-视觉SLAM十四讲-第一章作业
视觉slam学习笔记以及课后习题《第一讲初识slam》

glog简单使用
谷歌命令行解析工具gflags详解
GoogleTest 入门(2) CMake 项目中引入 GTest
https://github.com/google/googletest/tree/main/googletest
cmake应用:集成gtest进行单元测试

你可能感兴趣的:(SLAM,linux,ubuntu,自动驾驶)