Win10 VS2017 LearnVIORB 配置指南

本文详细记录了在Windows 10环境下,如何基于VS2017和CMake配置并编译DBoW2和g2o库,以及解决过程中遇到的OpenCV、BLAS/LAPACK、cholmod等依赖问题,供学习者参考。
摘要由CSDN通过智能技术生成

前言

  我们对于LearnVIORB的配置,并非从头开始,一个库一个库地配置,如此则区区一篇博文是不够的。因此,我们选择在ORBSLAM2的基础上,配置LearnVIORB

  我们在Releasex64/MD配置下,沿用ORBSLAM2Eigen3OpenCV3.1Pangolinboost四个库,而重新配置DBoW2g2o两个库。这是因为LearnVIORB的作者似乎对上述两个库做了二次的修改,此可以从其github获悉。

  这里需要注意的是,由于我全程采用/MD进行配置,而原先的Pangolin的运行库则默认是/MT模式的,故而需要另外配置/MD模式下的Pangolin,此可以参考我的另一篇博文。

  LearnVIORB的源码则采用LearnViORB_NOROS,其下载地址如下:地址

  相关配置环境再次总结如下:

  • Win10
  • VS2017
  • CMake3.18.4
  • Release x64 /MD
  • LearnViORB_NOROS

DBoW2 配置

构建生成解决方案

  在 Configure 的时候选择x64模式

在这里插入图片描述
  接下来提示没有找到OpenCV,需要在OpenCV_DIR的属性项目中设置含有OpenCVConfig.cmakeopencv-config.cmake文件的目录。由于我的电脑上的OpenCV都是阉割版本,所以就先暂时忽略掉这个错误。

在这里插入图片描述
  清空build文件夹,打开库的根目录下的CMakeLists.txt文件,删除其中的find_package(OpenCV REQUIRED),然后保存,重新 Configure 一下。

  Configure 没有任何问题,直接 Generate 生成解决方案。

编译基于VS2017

  在VS2017中采用Releasex64模式,同时修改DBoW2项目的属性如下:

  • 项目属性/配置属性/常规/目标文件扩展名 = .lib
  • 项目属性/配置属性/常规/配置类型 = 静态库(.lib)
  • C/C++/代码生成/运行库 = 多线程DLL(/MD)

  同时在配置属性/VC++目录的包含目录和库目录中将之前忽略掉的 OpenCV 的源文件、库文件所在目录写上去。然后直接右键项目生成即可。

  编译时发现FORB.cpp文件中有一行报错,如下修改即可:

// #include <stdint-gcc.h>	   before
#include <stdint.h> 				// after

  最后编译完成,库文件路径如下:

在这里插入图片描述
  最后新建文件夹DBoW2,然后将源文件和生成的库文件分别整理在其下新建的的includelib文件夹即可。

g2o 配置

依赖库 BLAS(LAPACK) 库的配置

  Configure 的时候还是x64的配置,然后就报错找不到BLAS库。

在这里插入图片描述
  BLAS库和LAPACK库是两个线性代数运算库,后者是基于前者实现的。有赖于此,我们只需要配置好LAPACK这个库理应也就OKay。LearnVIORB的作者在github上给出了上述两个库的官方地址:BLASLAPACK

  我们打开官方地址按图索骥,发现LAPACK的官方早已提供 Win10 下的编译好的版本,其相关内容在该网址中如下所示:

Download the Visual Studio Solution LAPACKE examples and unzip.The Solution contains all the includes, libraries and dlls you need.

  直接点击引用中的超链接下载即可,其中就有我们需要的库文件和源文件。将上述两个文件所在的includelib文件夹解压备用。

  Okay,有基于上,我们依旧清空build文件夹,将CMakeLists.txt文件中的如下部分删掉,暂时忽略掉上述报错。

FIND_PACKAGE(BLAS REQUIRED)
FIND_PACKAGE(LAPACK REQUIRED)

构建生成解决方案

  再次基于x64构建,这次是因为缺少Eigen的路径而报错,直接写上即可,最终Eigen的路径如下所示:

在这里插入图片描述
  至此构建完成,直接 Generate 即可。

编译基于VS2017

  打开构建的解决方案,各种属性的配置参照上述DBoW2库的配置,唯一不同的是,在配置前者时,额外添加的是OpenCV库的包含目录和库目录;这次我们就直接添加之前忽略的LAPACK库的包含目录和库目录即可。

  编译时报错如下:

1>e:\gitrepository\learnviorb_noros\thirdparty\g2o\g2o\core\matrix_operations.h(49): fatal error C1001: 编译器中发生内部错误。
1>(编译器文件“msc1.cpp”,第 1518 行)
1> 要解决此问题,请尝试简化或更改上面所列位置附近的程序。

  我们切换到matrix_operations.h文件发生错误的位置,删除出错部分附近的,第47行以及第65行的template<>,相关代码如下:

	...
    template<>	// 删除该行
    inline void axpy(const Eigen::MatrixXd& A, const Eigen::Map<const Eigen::VectorXd>& x, int xoff, Eigen::Map<Eigen::VectorXd>& y, int yoff)
    {
      y.segment(yoff, A.rows()) += A * x.segment(xoff, A.cols());
    }
    ...
    template<>  // 删除该行
    inline void atxpy(const Eigen::MatrixXd& A, const Eigen::Map<const Eigen::VectorXd>& x, int xoff, Eigen::Map<Eigen::VectorXd>& y, int yoff)
    {
      y.segment(yoff, A.cols()) += A.transpose() * x.segment(xoff, A.rows());
    }
	...

  再次编译,报错如下:

在这里插入图片描述
  max函数的问题可以通过添加#include <algorithm>解决,而vasprintf函数的问题则通过添加WINDOWS宏即可解决,这一点可以通过查看vasprintf函数的上下文获悉。

  此后则一路绿灯,编译完成,生成的库文件如下所示:

在这里插入图片描述

依赖库 cholmod 的配置

  在将配置完成的g2o库整合到LearnVIORB的过程中,我们发现在linear_solver_cholmod.h文件中引用了cholmod.h文件,而后者是无存的,因此报错。相关代码如下:

#ifndef G2O_LINEAR_SOLVER_CHOLMOD
#define G2O_LINEAR_SOLVER_CHOLMOD

#include "../core/linear_solver.h"
#include "../core/marginal_covariance_cholesky.h"
#include "../core/batch_stats.h"
#include "../stuff/timeutil.h"
#include "../stuff/sparse_helper.h"

#include <cholmod.h>				// error occur!

  纯粹cholmod库的配置在 Windows 系统下似乎不易,但我获悉suitesparse库中包含有cholmod库,正如我们之前配置的PALACK库中也包含有BLAS库一样。有基于此,我们就只需要配置出suitesparse库即可。该库在 Windows 系统下有源码版本可供配置,其github地址如下:地址

  不知为何,github上的下载总是报错,我们因而去码云上下载,地址如下:地址

  解压后直接 Configure->Generate 即可,一路绿灯,成功构建生成解决方案。

  编译也是一路绿灯,注意采用Releasex64/MD模式即可。成功编译生成所有的库文件后,我们新建suiteparse文件夹,其下包含includelib文件夹,前者添加所有的源文件,即库的根目录下的SuiteSparse目录,后者则添加所有的库文件,命令行切换到相关目录下使用dir /b *.lib >list.txt可以快速获取,生成的list.txt文件的内容如下:

libamd.lib
libcamd.lib
libccolamd.lib
libcholmod.lib
libcolamd.lib
metis.lib
suitesparseconfig.lib

  然后我在我的LearnVIORB项目中新建suitesparse属性表,添加对应的suitesparse库的包含目录和库目录以及附加依赖项即可。

其他库的配置

  其他的库我直接沿用ORBSLAM2的库,这里就不再赘述。

编译错误Debug

MapPoint.cc

  在编译运行项目时,该文件下述代码将会报错,大致是静态声明数组的大小表达式必须是常量云云。

	float Distances[N][N];		// error occur!

  直接修改为动态的声明即可,记得在该函数的末尾要添加释放指针的代码,如下所示:

	// float Distances[N][N];
	float ** Distances = new float*[N];
	for (int i = 0; i < N; i++)
		Distances[i] = new float[N];
	...
	delete[] Distances;

usleep 函数的修改

  该函数是 Linux 下的库函数,Windows 下无法使用。此外,该函数延时的单位是微秒,而 Windows 下对应的Sleep函数延时单位则是秒,因此需要修改为以下形式:

	// usleep(3000)
	std::this_thread::sleep_for(std::chrono::microseconds(3000));

  注意要加上#include <windows.h>头文件的引用。

TemplatedVocabulary.h

  在该文件的第1484行,报错表达式的计算结果不是常数。我将buf数组改为动态声明

  // char buf[size_node]; 
  char* buf = new char[size_node];
  int nid = 1;
  while (!f.eof()) {
	...
  }
  delete buf;

sparse_block_matrix.hpp

  该文件报错为:sparse_block_matrix.hpp(277): fatal error C1001: 编译器中发生内部错误。

  注释第277行代码,替换如下:

	// internal::axpy(*a, srcVec, srcOffset, destVec, destOffset);
	internal::template axpy<SparseMatrixBlock>(*a, srcVec, srcOffset, destVec, destOffset);

 &esmp;之后原先的第279行又报错如此,继续注释替换如下:

	if (destOffset < srcOffset)
		// internal::atxpy(*a, srcVec, destOffset, destVec, srcOffset);
		internal::template atxpy<SparseMatrixBlock>(*a, srcVec, srcOffset, destVec, destOffset);

sparse_block_matrix_ccs.h

  其错误和sparse_block_matrix.hpp文件报错相同,在第125行,注释修改如下:

	// internal::atxpy(*a, srcVec, srcOffset, destVec, destOffset);
	internal::template atxpy<SparseMatrixBlock>(*a, srcVec, srcOffset, destVec, destOffset);

sparse_block_matrix_diagonal.h

  第97行,应对同上,不再赘述。

	// internal::axpy(A, srcVec, srcOffset, destVec, destOffset);
	internal::template atxpy<SparseMatrixBlock>(A, srcVec, srcOffset, destVec, destOffset);

链接错误Debug

  经过上述代码的修改,编译时终于不再报错,接下来是链接时的错误。

/MD 的问题

  由于上述DBoW2库和g2o库都是在/MD模式下配置的,因此在LearnVIORB项目链接时,和我原先的Pangolin.lib的运行库模式不匹配。这一点可以参考我的另一篇博文,另外配置/MD模式的Pangolin库即可。由于我先前配置过,因此我在这里就直接迁移了。

无法解析的外部符号

  链接时的报错还有:

1>libcholmod.lib(cholmod_super_numeric.o.obj) : error LNK2001: 无法解析的外部符号 dtrsm_
1>libcholmod.lib(cholmod_super_solve.o.obj) : error LNK2001: 无法解析的外部符号 dtrsm_
1>libcholmod.lib(cholmod_super_numeric.o.obj) : error LNK2001: 无法解析的外部符号 ztrsm_
1>libcholmod.lib(cholmod_super_solve.o.obj) : error LNK2001: 无法解析的外部符号 ztrsm_
1>libcholmod.lib(cholmod_super_numeric.o.obj) : error LNK2001: 无法解析的外部符号 dgemm_
1>libcholmod.lib(cholmod_super_solve.o.obj) : error LNK2001: 无法解析的外部符号 dgemm_
1>libcholmod.lib(cholmod_super_numeric.o.obj) : error LNK2001: 无法解析的外部符号 zgemm_
1>libcholmod.lib(cholmod_super_solve.o.obj) : error LNK2001: 无法解析的外部符号 zgemm_
1>libcholmod.lib(cholmod_super_numeric.o.obj) : error LNK2001: 无法解析的外部符号 dsyrk_
1>libcholmod.lib(cholmod_super_numeric.o.obj) : error LNK2001: 无法解析的外部符号 zherk_
1>libcholmod.lib(cholmod_super_numeric.o.obj) : error LNK2001: 无法解析的外部符号 dpotrf_
1>libcholmod.lib(cholmod_super_numeric.o.obj) : error LNK2001: 无法解析的外部符号 zpotrf_
1>libcholmod.lib(cholmod_super_solve.o.obj) : error LNK2001: 无法解析的外部符号 dgemv_
1>libcholmod.lib(cholmod_super_solve.o.obj) : error LNK2001: 无法解析的外部符号 zgemv_
1>libcholmod.lib(cholmod_super_solve.o.obj) : error LNK2001: 无法解析的外部符号 dtrsv_
1>libcholmod.lib(cholmod_super_solve.o.obj) : error LNK2001: 无法解析的外部符号 ztrsv_

  该错误和我之前一篇博文中,因为没有添加opengl32.lib而报的错误在原理上非常相似。这些缺少实现的函数,都是BLASLAPACK库的函数。

  由于LAPACKg2o的依赖库,我们之前已经配置过,按理说可以直接沿用。但是,我如此尝试后,发现上述函数依旧缺失而无法解析。因此,我们转到之前在码云上下载的suitesparse库的根目录下,在其下的suitesparse-metis-for-windows-master\lapack_windows\x64找到其自带的BLASLAPACK的库文件,然后将其复制到先前创建的suitesparse\lib目录中,并在LearnVIORB项目中的suitesparse属性表添加对应的附加依赖项即可。

  注意上述文件夹下的所有.dll文件都是程序运行所必须的,需要额外复制到LearnVIORB程序的运行目录下。

缺少各种 dll 文件

  直接按照要求添加即可,不说废话。

运行的一些注意事项

  首先,我们选择LearnVIORB_NOROS\Examples\ROS\ORB_VIO\src\ros_vio.cc作为程序的入口。该源文件额外用到了boost库,我选择沿用ORBSLAM2之前配的boost库。

  我采用的运行参数如下,仅供参考:

D:/ORB-SLAM2/Run/Vocabulary/ORBvoc.bin D:/ORB-SLAM2/config/euroc.yaml D:/ORB-SLAM2/Run/data/mav0/imu0/data.csv D:/ORB-SLAM2/Run/data/mav0/cam0/data.csv D:/ORB-SLAM2/Run/data/mav0/cam0/data

 &esmp;其提供的ros_vio.cc默认是基于EuRoC数据集的单目模式,只用到了cam0的图像数据和imu0的惯性数据。此外,由于该数据集一共有两万九千多行的 IMU 数据,读取起来特别慢,而且还没有什么回显,不看代码只看命令行界面的话还以为程序陷入什么死循环。因此,如果只是做测试的话,可以修改一下代码,不用把 IMU 数据全部读取完,只读上几千行就够跑很多帧了。

  此外,该文件还存在一个 BUG,就是读取iListData而构成的fullPath变量的末尾缺少一个g,这样会导致图像文件无法读取。我这里说起来很抽象,其实代码看过去一望便知。修改的话很简单,如下所示:

	// string temp = iListData[j].imgName.substr(0,iListData[j].imgName.size()-1);
	string temp = iListData[j].imgName;

  噢对了,运行时用的参数文件并非ORBSLAM2原版自带的参数文件,而是作者修改后添加了相关 IMU 配置的参数文件。其路径可参考如下:LearnVIORB_NOROS\config\euroc.yaml。其实就在库的根目录下的config目录里。

运行效果

  由于我采用的是EuRoCVicon Room 1 01数据集,开头的很多帧运动不足,一直没有成功初始化。如此的情况,稍等片刻即可。

  至于速度,普通帧倒是挺流畅的,只是每次插入关键帧的时候都会卡一下。

  运行效果如下图所示:

在这里插入图片描述

后记

  这篇指南是我一边配一边写的,草草写就,仅做记录。如今也无心校勘修改,因此仅供参考。如有所助,幸甚至焉。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值