高翔VO调试日志

高博十四讲VO调试日志

1. frame.h

1.1. 智能指针

智能指针是C++11标准模板库里面提供的模板类。普通指针指向的内存无法自动清除(人为用new delete),为了防止内存泄露,智能指针在生存期结束时可以自动析构释放内存。

shared_ptr<T> sp;
unique_ptr<T> up;
weak_ptr<T> make_shared<T>();
shared_ptr<int> ptr1(new int(100));//ptr1指向一个值为100的int型数据

我们可以认为每个shared_ptr都有一个关联的计数器,通常称其为引用计数,无论何时我们拷贝一个shared_ptr,计数器都会递增。当我们给shared_ptr赋予一个新值或是shared_ptr被销毁(例如一个局部的shared_ptr离开其作用域)时,计数器就会递减,一旦一个shared_ptr的计数器变为0,它就会自动释放自己所管理的对象。

shared_ptr允许多个指针指向同一个对象,unique_ptr则“独占”所指向的对象。标准库还定义了一种名为weak_ptr的伴随类,它是一种弱引用,指向shared_ptr所管理的对象,用来防止互相引用无法析构。这三种智能指针都定义在memory头文件中。

  • .lock()会检查weak_ptr指向的对象是否存在。如果存在,返回一个指向共享对象的shared_ptr,如果不存在,lock将返回一个空指针。frontend.cpp line 234

1.2. 线程锁

std::mutex

2. frontend.cpp frontend.h

2.1. Eigen字节对齐

EIGEN_MAKE_ALIGNED_OPERATOR_NEW

Eigen库为了使用SSE加速,在内存上分配了128位的指针,涉及字节对齐问题,出问题时在编译时不会报错,只在运行时报错。写下这一句能够让编译器自动将数据对齐。

SSE指令集是英特尔提供的基于SIMD(单指令多数据,也就是说同一时间内,对多个不同的数据执行同一条命令)的硬件加速指令,通过使用寄存器来进行并行加速。

2.2. 命名空间

namespace myslam{
    void Foo();
}

using declaration 访问特定的成员

using myslam::Foo();

using directive 访问整个namespace

using namespace myslam;
Foo();

一般来说,using declaration比using directive 安全。因为

  • using declaration明确的告诉我们可以用哪个成员。
  • using diclaration如果名字冲突了,编译器会报错;而using directive会覆盖了namespace的版本,而不做任何提示。

可以嵌套和设置别名。

2.3. Google glog

Google glog是一个基于程序级记录日志信息的c++库,编程使用方式与c++的stream操作类似,例:

   LOG(INFO) << "Found " << num_cookies << " cookies";

“LOG”宏为日志输出关键字,“INFO”为严重性程度。
官方文档见
http://google-glog.googlecode.com/svn/trunk/doc/glog.html

有好哥哥翻译了该文档
https://blog.csdn.net/junmuzi/article/details/79670351

2.4. auto类型

auto的原理就是根据后面的值,来自己推测前面的类型是什么。

auto的作用就是为了简化变量初始化,如果这个变量有一个很长很长的初始化类型,就可以用auto代替。

注意点:

1.用auto声明的变量必须初始化(auto是根据后面的值来推测这个变量的类型,如果后面没有值,自然会报错)

2.函数和模板参数不能被声明为auto(原因同上)

3.因为auto是一个占位符,并不是一个他自己的类型,因此不能用于类型转换或其他一些操作,如sizeof和typeid

4.定义在一个auto序列的变量必须始终推导成同一类型

2.5. 重新认识for循环

frontend.cpp line 233
基于范围的for循环,循环从头到尾的每一个元素

for (auto &kp : last_frame_->features_left_)

符号 & 表示 kp 是一个引用变量,将使用并改变 last_frame_->features_left 的原始数据。
若不带 & 则不会改变原始数据 , 循环时使用的是一个副本。

2.6. cv::calcOpticalFlowPyrLK()

frontend.cpp line 249

void cv::calcOpticalFlowPyrLK(	
InputArray 	prevImg,
InputArray 	nextImg,
InputArray 	prevPts,
InputOutputArray 	nextPts,
OutputArray 	status,
OutputArray 	err,
Size 	winSize = Size(21, 21),
int 	maxLevel = 3,
TermCriteria 	criteria = TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 30, 0.01),
int 	flags = 0,
double 	minEigThreshold = 1e-4 
)		

使用具有金字塔的迭代Lucas-Kanade方法计算稀疏特征集的光流。
参数:

prevImg :buildOpticalFlowPyramid构造的第一个8位输入图像或金字塔。
nextImg :与prevImg相同大小和相同类型的第二个输入图像或金字塔
prevPts :需要找到流的2D点的矢量(vector of 2D points for which the flow needs to be found;);点坐标必须是单精度浮点数。
nextPts :输出二维点的矢量(具有单精度浮点坐标),包含第二图像中输入特征的计算新位置;当传递OPTFLOW_USE_INITIAL_FLOW标志时,向量必须与输入中的大小相同。
status :输出状态向量(无符号字符);如果找到相应特征的流,则向量的每个元素设置为1,否则设置为0。
err :输出错误的矢量; 向量的每个元素都设置为相应特征的错误,错误度量的类型可以在flags参数中设置; 如果未找到流,则未定义错误(使用status参数查找此类情况)。
winSize :每个金字塔等级的搜索窗口的winSize大小。
maxLevel :基于0的最大金字塔等级数;如果设置为0,则不使用金字塔(单级),如果设置为1,则使用两个级别,依此类推;如果将金字塔传递给输入,那么算法将使用与金字塔一样多的级别,但不超过maxLevel。
criteria :参数,指定迭代搜索算法的终止条件(在指定的最大迭代次数criteria.maxCount之后或当搜索窗口移动小于criteria.epsilon时)。
flags :操作标志:
    OPTFLOW_USE_INITIAL_FLOW使用初始估计,存储在nextPts中;如果未设置标志,则将prevPts复制到nextPts并将其视为初始估计。
    OPTFLOW_LK_GET_MIN_EIGENVALS使用最小特征值作为误差测量(参见minEigThreshold描述);如果没有设置标志,则将原稿周围的色块和移动点之间的L1距离除以窗口中的像素数,用作误差测量。
minEigThreshold :算法计算光流方程的2x2正常矩阵的最小特征值,除以窗口中的像素数;如果此值小于minEigThreshold,则过滤掉相应的功能并且不处理其流程,因此它允许删除坏点并获得性能提升。

该函数实现了金字塔中Lucas-Kanade光流的稀疏迭代版本。

2.7. cv::KeyPoint

frontend.cpp line 260
Opencv中KeyPoint类中的默认构造函数如下:

CV_WRAP KeyPoint() : pt(0,0), size(0), angle(-1), response(0), octave(0), class_id(-1) {}

现分析各项属性

pt(x,y):关键点的点坐标;

size():该关键点邻域直径大小;

angle:角度,表示关键点的方向,值为[零,三百六十),负值表示不使用。

response:响应强度,网络上有如下解释:

1)”The response, by which the strongest keypoints have been selected.”

2)”Responseis indeed an indicator of “how good” (roughly speaking, in terms of corner-ness) a point is. The higher, the better. The strongest keypoints means the ones that are the best.“

octacv:从哪一层金字塔得到的此关键点。

class_id:当要对图片进行分类时,用class_id对每个关键点进行区分,默认为-1。

2.8. #pragma once

为了避免同一个头文件被包含(include)多次,C/C++中有两种宏实现方式:一种是#ifndef方式;另一种是#pragma once方式。
在能够支持这两种方式的编译器上,二者并没有太大的区别。

3. 跑代码报错

3.1. eigen

cmake时报错

tian@tian-legion:~/slambook2-master/ch13/build$ cmake ..
-- Configuring done
CMake Error in src/CMakeLists.txt:
Imported target "pangolin" includes non-existent path

    "/usr/include/eigen3"

in its INTERFACE_INCLUDE_DIRECTORIES.  Possible reasons include:

* The path was deleted, renamed, or moved to another location.

* An install or uninstall procedure did not complete successfully.

* The installation package was faulty and references files it does not
provide.



CMake Error in src/CMakeLists.txt:
Imported target "pangolin" includes non-existent path

    "/usr/include/eigen3"

in its INTERFACE_INCLUDE_DIRECTORIES.  Possible reasons include:

* The path was deleted, renamed, or moved to another location.

* An install or uninstall procedure did not complete successfully.

* The installation package was faulty and references files it does not
provide.



CMake Error in test/CMakeLists.txt:
Imported target "pangolin" includes non-existent path

    "/usr/include/eigen3"

in its INTERFACE_INCLUDE_DIRECTORIES.  Possible reasons include:

* The path was deleted, renamed, or moved to another location.

* An install or uninstall procedure did not complete successfully.

* The installation package was faulty and references files it does not
provide.



CMake Error in test/CMakeLists.txt:
Imported target "pangolin" includes non-existent path

    "/usr/include/eigen3"

in its INTERFACE_INCLUDE_DIRECTORIES.  Possible reasons include:

* The path was deleted, renamed, or moved to another location.

* An install or uninstall procedure did not complete successfully.

* The installation package was faulty and references files it does not
provide.



-- Generating done
CMake Generate step failed.  Build files cannot be regenerated correctly.

错误信息提示pangolin找不到eigen3,这是因为它默认搜索"/usr/include/eigen3"这个路径,但笔者在安装eigen3时手动编译,eigen被安装在"/usr/local/include/eigen3"这个目录下。

解决方法

sudo ln -s /usr/local/include/eigen3 /usr/include/eigen3

这样相当于创建了一个快捷方式,让其他程序在"/usr/include/eigen3"中也能找到eigen3.

3.2. fmt

报错

/usr/bin/ld: ../../lib/libmyslam.so: undefined reference to `fmt::v8::detail::assert_fail(char const*, int, char const*)'

解决,在

set(THIRD_PARTY_LIBS
        ${OpenCV_LIBS}

显式加上fmt

set(THIRD_PARTY_LIBS
        ${OpenCV_LIBS} fmt

3.3. 还是fmt

报错

/usr/bin/ld: /usr/local/lib/libfmt.a(format.cc.o): relocation R_X86_64_PC32 against symbol `stderr@@GLIBC_2.2.5' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: bad value
collect2: error: ld returned 1 exit status
make[2]: *** [src/CMakeFiles/myslam.dir/build.make:262: ../lib/libmyslam.so] Error 1
make[1]: *** [CMakeFiles/Makefile2:136: src/CMakeFiles/myslam.dir/all] Error 2
make: *** [Makefile:95: all] Error 2

查看报错信息,编译器提示我们重新把fmt这个库带着参数-fPIC编译一遍。具体操作是在fmt库的CMakeLists.txt里加上一句

add_compile_options(-fPIC)

再编译一遍这个库,问题解决。

4. 学习计划

计划在高博VO基础上加全局地图和轨迹的显示和回环检测。

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值