《视觉SLAM十四讲》学习日志(二)——初识SLAM
小萝卜机器人的例子:
就像这种机器人,它的下面有一组轮子,脑袋上有相机(眼睛),为了让它能够探索一个房间,它需要知道:
1.我在哪——定位
2.周围环境怎么样——建图
定位和建图可以理解成感知的 "内外之分",一方面要明白自身的状态(位置),另一方面要了解周围的环境(地图)。要完成这些工作,我们可以通过在房间铺设导引线,在墙上贴识别二维码,在室外可以给机器人安装定位设备,这些我们都称之为传感器,传感器分为两类:
1.携带于机器人本体上,例如相机,激光传感器等
2.安装于环境中的,例如导引线,识别二维码等。
然而大量利用这些外部传感器很明显是不现实的,抛开成本,光是在环境中铺设这些传感器就很不现实,有些地方不能铺设导轨,有些地方没有信号,相对地, 安装于机器人身上的传感器测到的都是一些间接的物理量,并不能得到直接的位置信息,我们只能通过一些间接的手段,推算出位置。虽然听起来很麻烦,但是它有一个很明显的好处就是对环境条件没有要求,适用于测量未知环境。
SLAM中非常强调未知环境,因此,谈论视觉SLAM时,主要指如何用相机解决定位和构图问题。SLAM中使用的相机是以一定速率拍摄周围的环境,形成一个连续的视频流。普通相机能以每秒钟30张的速度采集图像,按照工作方式不同,可以分为单目相机,双目相机和深度相机。
单目相机:顾名思义,只有一个摄像头,我们通常的照片就是单目摄像机拍摄的图像,以二维的形式反映了三维的世界。显然,这个过程丢掉了深度(距离),比如:
你很难分辨出手掌上的人是真人还是模型。
如果想恢复三维结构,我们必须改变相机的视角,因此必须移动相机,才能估计它的运动,同时估计场景中物体的远近和大小,不妨称之为结构,一方面,我们知道相机往右移动,图像里的东西会向左移动,另一方面,近处的物体移动快,远处的物体运动缓慢。于是,当相机移动时,这些物体在图像上的运动形成了视差。通过视差我们可以判断哪些物体离得远,哪些离得近。
现在我们知道了物体远近,但是它们仍然是相对的值,如果把相机的运动和场景大小同时放大两倍,单目相机看到的图像是一样的。因此,单目SLAM估计的轨迹和地图将与真实的轨迹和地图相差一个因子,也就是尺度。由于单目SLAM无法仅凭图像确定这个真实尺度,所以又称尺度不确定性。
平移之后才可以计算深度,以及无法确定真实尺度,这给单目SLAM的应用带来了很大麻烦。根本原因是通过单张图像无法确定深度。
双目相机:
由两个单目相机组成,这两个单目相机之间的距离(成为基线)是已知的。通过这个基线来估计每个像素的空间位置——和人眼类似。基线的距离越大,能测量到的就越远。双目相机的距离估计是比较左右眼的图像获得的,并不依赖其他传感设备。因此室内外都可以应用。它的缺点是配置与标定均比较复杂,其深度量程和精度受双目的基线与分辨率所限,而且视差的计算非常消耗计算资源,需要使用 GPU 和 FPGA 设备加速后,才能实时输出整张图像的距离信息,因此计算量是双目的主要问题之一。
深度相机:
又称 RGB-D 相机,最大的特点是可以通过红外结构光或 Time-of-Flight(TOF) 原理,像激光传感器那样,通过主动向物体发射光并接收返回的光,测出物体与相机之间的距离。
经典视觉SLAM框架:
整个视觉SLAM流程包括以下步骤。
1.传感器信息读取。在视觉SLAM中主要为相机图像信息的读取和预处理。如果是在机器人中,还可能有码盘、惯性传感器等信息的读取和同步。
2.视觉里程计(Visual Odometry,VO)。视觉里程计的任务是估算相邻图像间相机的运动,以及局部地图的样子。VO又称为前端。
3.后端优化(Optimization)。后端接受不同时刻视觉里程计测量的相机位姿,以及回环检测的信息,对它们进行优化,得到全局一致的轨迹和地图,由于接在VO之后,又称后端。
4.回环检测(Loop Closing)。判断机器人是否到达过先前的位置。如果检测到回环,它会把信息提供给后端进行处理。
5.建图(Mapping)。根据估计的轨迹,建立与任务要求对应的地图。
关于SLAM问题的数学表述,在后续的博文中会提到。
小试牛刀:
1.安装Linux系统,这个不用多说。
2.编写helloSLAm.cpp。首先建一个文件夹。
$mkdir slambook
$cd slambook
$mkdir ch2
然后在ch2下写helloSLAM.cpp。
$cd ch2
$vim helloSLAM.cpp
将如下代码写入。
#include <iostream> using namespace std; int main(int argc,char** argv)
{
cout<<"Hello SLAM"<<endl;
return ;
}
先使用g++编译。
$g++ helloSLAM.cpp
确保你的机器里有g++。如果没有,请使用以下命令安装。
$sudo apt-get install g++
编译成功后,输入:
$./a.out
即可运行。
我们可以发现,g++默认把源文件编译成 a.out 。
3.使用cmake
在刚才的目录下新建一个 CMakeLists.txt 文件,输入:
#声明要求的 cmake 最低版本
cmake_minimum_required( VERSION 2.8 ) #声明一个cmake工程
project( HelloSLAM ) #添加一个可执行程序
#语法:add_executable(程序名 源代码文件)
add_executable( helloSLAM helloSLAM.cpp )
在当前目录下(slambook/ch2),调用 cmake 对该工程分析:
用 make 对工程进行编译:
$make
然后运行:
$./helloSLAM
cmake 和 g++都可以对C++文件进行编译,那么它们之间的区别是什么?
通常一个小型C++项目可能含有十几个类,各类之间还存在着复杂的依赖关系。其中一部分要编译成可执行文件,另一部分要编译成库文件。如果仅靠g++命令,需要输入大量的编译指令,整个编译过程会非常繁琐。因此对于C++项目,使用一些工程管理工具会更加高效。也就是cmake。
4.使用库
创建如下文件(slambook/ch2/libHelloSLAM.cpp):
#include <iostream> using namespace std; void printHello()
{
cout<<"Hello SLAM"<<endl;
}
这个库提供了一个printHello()函数,调用此函数将打印出一条信息,但是没有main()函数,意味着这个库中没有可执行文件,我们在CMakeLists.txt里加上如下内容:
add_library( hello libHelloSLAM.cpp)
这条命令告诉cmake,我们想把这个文件编译成一个叫做“hello”的库,然后和上面一样,编译整个工程:
$cd build
$cmake ..
$make
这时,在build文件夹中就会生成一个libhello.a文件,这就是得到的库,
Linux中,库分为静态库和共享库,静态库以.a作为后缀名,共享库以.so结尾,所有库都是一些函数打包后的集合,差别在于静态库每次被调用都会生成一个副本,而共享库只有一个副本,更省空间。如果想生成共享库,那么只需要:
add_library( hello_shared SHARED libHelloSLAM.cpp)
此时得到的就是libhello_shared.so了。
为了让别人使用这个库,我们需要提供一个头文件,说明这些库里面都有些什么,因此,对于库的使用者,只要拿到了头文件和库文件,就可以调用这个库了,下面编写libhello的头文件。
slambook/ch2/libHelloSLAM.h
#ifndef LIBHELLOSLAM_H_
#define LIBHELLOSLAM_H_
void printHello();
#endif
根据这个文件和我们刚才编译得到的库文件,就可以使用printHello()函数了,下面写一个可执行程序来调用这个简单的函数:
slambook/ch2/useHello.cpp
#include "libHelloSLAM.h" int main(int argc,char** argv)
{
printHello();
return ;
}
然后,在CMakeLists.txt中添加一个可执行程序的生成命令,链接到刚才使用的库上:
add_executable( useHello useHello.cpp )
target_link_libraries( useHello hello_shared)
5.使用IDE
关于kdevelop的安装教程请看:
http://blog.csdn.net/p942005405/article/details/75715288
《视觉SLAM十四讲》学习日志(二)——初识SLAM的更多相关文章
- 《SLAM十四讲》个人学习知识点梳理
0.引言 从六月末到八月初大概一个月时间一直在啃SLAM十四讲[1]这本书,这本书把SLAM中涉及的基本知识点都涵盖了,所以在这里做一个复习,对这本书自己学到的东西做一个梳理. 书本地址:http:/ ...
- 高博-《视觉SLAM十四讲》
0 讲座 (1)SLAM定义 对比雷达传感器和视觉传感器的优缺点(主要介绍视觉SLAM) 单目:不知道尺度信息 双目:知道尺度信息,但测量范围根据预定的基线相关 RGBD:知道深度信息,但是深度信息对 ...
- 《视觉SLAM十四讲》第2讲
目录 一 视觉SLAM中的传感器 二 经典视觉SLAM框架 三 SLAM问题的数学表述 注:原创不易,转载请务必注明原作者和出处,感谢支持! 本讲主要内容: (1) 视觉SLAM中的传感器 (2) 经 ...
- 《视觉SLAM十四讲》第1讲
目录 一 视觉SLAM 注:原创不易,转载请务必注明原作者和出处,感谢支持! 一 视觉SLAM 什么是视觉SLAM? SLAM是Simultaneous Localization and Mappin ...
- 视觉slam十四讲第七章课后习题6
版权声明:本文为博主原创文章,转载请注明出处: http://www.cnblogs.com/newneul/p/8545450.html 6.在PnP优化中,将第一个相机的观测也考虑进来,程序应如何 ...
- 视觉slam十四讲第七章课后习题7
版权声明:本文为博主原创文章,转载请注明出处:http://www.cnblogs.com/newneul/p/8544369.html 7.题目要求:在ICP程序中,将空间点也作为优化变量考虑进来 ...
- 浅读《视觉SLAM十四讲:从理论到实践》--操作1--初识SLAM
下载<视觉SLAM十四讲:从理论到实践>源码:https://github.com/gaoxiang12/slambook 第二讲:初识SLAM 2.4.2 Hello SLAM(书本P2 ...
- 视觉SLAM十四讲:从理论到实践 两版 PDF和源码
视觉SLAM十四讲:从理论到实践 第一版电子版PDF 链接:https://pan.baidu.com/s/1SuuSpavo_fj7xqTYtgHBfw提取码:lr4t 源码github链接:htt ...
- SLAM十四讲中Sophus库安装
Sophus截止目前有很多版本,其中大体分为两类,一种是用模板实现的方法,一种是用非模板类实现的,SLAM十四讲中使用的是非模板类库,clone Sophus: git clone http://gi ...
随机推荐
- 时间格式_java
@Test public void testDate(){ Date date=new Date(); System.out.println(date); /*日期格式*/ DateFormat df ...
- Spring基础篇——DI/IOC和AOP原理初识
DI(Dependency Injection),依赖注入,和我们常听说的另一个概念 IOC(控制反转)其实归根结底实现的功能是相同的,只是同样的功能站在不同的角度来阐述罢了.这里博主就不去过多的辨析 ...
- internal关键字
internal修饰符可以用于类型或成员,使用该修饰符声明的类型或成员只能在同一程集内访问,接口的成员不能使用internal修饰符. 就是使用internal的类只能在同一个项目中使用,不能在别的项 ...
- .NetCore如何使用ImageSharp进行图片的生成
ImageSharp是对NetCore平台扩展的一个图像处理方案,以往网上的案例多以生成文字及画出简单图形.验证码等方式进行探讨和实践. 今天我分享一下所在公司项目的实际应用案例,导出微信二维码图片, ...
- ARM微控制器与嵌入式系统
个牛人在ARM实现嵌入式系统的过程 第一章 概览 1.1课程概览 认识ARM嵌入式系统(什么是ARM?什么是嵌入式系统?) 备战智能车 在科技活动中玩起来 积累计算机.电路基础知识 1.2如何学好嵌 ...
- 2、Java基础:概念
1.面向对象和面向过程的区别 面向过程 优点:性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源;比如单片机.嵌入式开发.Linux/Unix等一般采用面向过程开发,性能是最重要的因素 ...
- vscode 使用ESLint 自动检查,保存时自动格式化
1:全局安装eslint `npm install -g eslint`2: 打开vscode 点击 “文件”----->“首选项”---->“设置”,在右侧“用户设置/settings. ...
- KVM之配置桥接网卡
配置桥接网卡 添加桥接网卡br0,注释掉已有的eth0配置 [root@ubuntu01 ~]# vi /etc/network/interfaces # This file describes th ...
- win10开机后将存在多个系统选择,改为直接进入系统无需选择
win10系统安装后,可能出现每次开机都要选择操作系统,比较麻烦,所以就来设置下如何直接进入系统,无须选择 1.我的电脑右键“属性”—“高级系统设置”—“系统属性” 2.设置“启动和故障恢复”如下 选 ...
- Mysql实现数据库主从复制架构
MySQL复制 (1)扩展方式: Scale Up ,Scale Out (2)MySQL的扩展 读写分离 复制:每个节点都有相同的数据集 向外扩展 二进制日志 单向 (3)复制的功用: 数据分布 负 ...