前言
开始学习SLAM,使用的书籍是《视觉SLAM十四讲 从理论到实践》、版次2017年3月第1版、ubuntu版本18.04。由于版本较老,可能书上一些内容和现在的库有一些不同,在照着例子练习的时候会出现一些问题,所以将这些内容记录下来。
第三讲
1.Eigen库实践
Eigen库的安装与书上内容一致,通常是没有问题的,库会默认安装到"/usr/include/eigen3"中。
// 安装
sudo apt-get install libeigen3-dev
// 查看
sudo updatedb
locate eigen3
问题
在使用时,编译会报错: fatal error: Eigen/Core: 没有那个文件或目录
// 错误
fatal error: Eigen/Core: 没有那个文件或目录
#include <Eigen/Core>
^~~~~~~~~~~~
compilation terminated.
CMakeFiles/deepsort.dir/build.make:62: recipe for target 'CMakeFiles/deepsort.dir/deepsort/src/deepsort.cpp.o' failed
make[2]: *** [CMakeFiles/deepsort.dir/deepsort/src/deepsort.cpp.o] Error 1
CMakeFiles/Makefile2:105: recipe for target 'CMakeFiles/deepsort.dir/all' failed
make[1]: *** [CMakeFiles/deepsort.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2
错误的原因没有找到头文件。
解决办法
将头文件路径包含到CMakelist文件中
// 在CMakelist.txt添加
include_directories("/usr/include/eigen3")
2.pangolin安装
在3.7节的可视化演示中(slambook-master/ch3/visualizeGeometry),首先要安装pangolin。
问题
使用书本在1.2.2节给出的Github网站下载的pangolin-master资源包进行安装时遇到问题,编译报错。
报错原因猜测可能是因为使用的0.6版本,可能版本比较新,和其他文件不匹配。
解决办法
去下载0.5版本的包:https://github.com/stevenlovegrove/Pangolin,下载之后能正常安装,成功。
// pangolin安装命令
cd Pangolin //Pangolin 包的地址
mkdir build
cd build
cmake -DCPP11_NO_BOOST=1 ..
make
sudo make install
3.可视化演示
安装好pangolin后,编译visualizeGeometry.cpp出现问题。
问题
//报错
./visualizeGeometry: error while loading shared libraries: libpango_image.so: cannot open shared object file: No such file or directory
这是因为系统不知道libpango_image.so放在哪个目录下,需要刷新共享库。
解决办法
//刷新共享库
sudo ldconfig
接下来就可以正常运行程序了。
第四讲
1.Sophus实践
要求编译一个非模板类的Sophus库,在编译书中提供的 slambook-master/3rdparty/Sophus 第三方库时出现错误。
问题
在编译过程中,使用Cmake …的时候能够顺利通过,接着执行make命令的时候就会出现错误如下:
//make报错
slambook-master/3rdparty/Sophus/sophus/so2.cpp: In constructor ‘Sophus::SO2::SO2()’:
slambook-master/3rdparty/Sophus/sophus/so2.cpp:32:26: error: lvalue required as left operand of assignment
unit_complex_.real() = 1.;
^~
slambook-master/3rdparty/Sophus/sophus/so2.cpp:33:26: error: lvalue required as left operand of assignment
unit_complex_.imag() = 0.;
^~
CMakeFiles/Sophus.dir/build.make:65: recipe for target 'CMakeFiles/Sophus.dir/sophus/so2.cpp.o' failed
make[2]: *** [CMakeFiles/Sophus.dir/sophus/so2.cpp.o] Error 1
make[2]: 离开目录“/home/nova/slambook-master/3rdparty/Sophus/build”
CMakeFiles/Makefile2:144: recipe for target 'CMakeFiles/Sophus.dir/all' failed
make[1]: *** [CMakeFiles/Sophus.dir/all] Error 2
make[1]: 离开目录“/home/nova/slambook-master/3rdparty/Sophus/build”
Makefile:143: recipe for target 'all' failed
make: *** [all] Error 2
这个问题出现的原因不知道是什么。
解决办法
修改 slambook-master/3rdparty/Sophus/sophus/so2.cpp 文件的 SO2::SO2() 构造函数。
//修改前
SO2::SO2()
{
unit_complex_.real() = 1.;
unit_complex_.imag() = 0.;
}
//修改后
SO2::SO2()
{
//unit_complex_.real() = 1.;
//unit_complex_.imag() = 0.;
unit_complex_.real(1.);
unit_complex_.imag(0.);
}
修改完成后,可以成功编译Sophus库。
第五讲
1.安装opencv
在5.3.1中,安装OPENCV-3.1.0,按照书中的方法,成功下载安装包,安装依赖环境和编译opencv时出现问题。
问题1:依赖项安装
在按照书上的代码安装依赖项时,出现错误无法定位软件包 E: 无法定位软件包 libjasper-dev 。
解决办法
按照以下代码安装:
sudo add-apt-repository "deb http://security.ubuntu.com/ubuntu xenial-security main"
sudo apt update
sudo apt install libjasper1 libjasper-dev
问题2:编译opencv
opencv下载的是cmake工程,在cmake编译之后,使用make编译的时侯出现报错 /usr/include/c++/7/cstdlib:75:15: fatal error: stdlib.h: No such file or directory。
问题原因:这是由于gcc7已经把stdlib.h纳入了libstdc++以进行更好的优化,C Library的头文件stdlib.h使用 Include_next,而include_next对gcc系统头文件路径很敏感。
解决办法
在cmake编译时,使用以下代码:
cmake -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=/usr/local -D ENABLE_PRECOMPILED_HEADERS=OFF ..
2.实践:拼接点云
在实践点云拼接时,需要安装PCL库,在按照书上的方法安装时,出现问题。
问题:This only exists for history reasons. Please use the PCL version included in Ubuntu
问题出现的原因可能是我之前装过ros,导致安装失败,也可能是在18.04上面版本做了更新,不适用这种方法。
解决办法
看了很多帖子,安装PCL都是下载源码,然后编译安装,有些繁琐,在这里使用命令行安装:
sudo apt install libpcl-dev
sudo apt install pcl-tools
第六讲
1.安装Ceres
在按照书上的方法安装Ceres时,安装依赖项失败,3rdparty中的Ceres资源编译失败。
问题1:安装依赖
按照书上的代码安装依赖报错:E:无法定位软件包 libcxsparse3.1.2
问题的原因是ubuntu从18.04开始往后都是libcxsparse3。
解决办法
将libcxsparse3.1.2替换为libcxsparse3
sudo apt-get install liblapack-dev libsuitesparse-dev libcxsparse3 libgflags-dev libgoogle-glog-dev libgtest-dev
问题2:安装Ceres
3rdparty中的Ceres资源编译失败In instantiation of ‘struct Eigen::internal::promote_scalar_arg<ceres::Jet<double, 2>, Eigen::Matrix<ceres::Jet<double, 2>, 2, 2>, false>’:
通过搜索,这个问题出现的原因可能是和eigen3版本发生冲突。
解决办法
换个合适的版本重新编译,下载链接:Ceres,我选择的是与ubuntu18.04同年发布的1.14.0。
解压压缩包后,进入文件目录,编译安装:
//进入文件目录
cd ceres-solver-1.14.0/
mkdir build
cd build/
//编译
cmake ..
make
//安装
sudo make install
2.安装g2o
安装g2o时,按照书上的方法安装依赖项失败。
问题1:安装依赖
E: 软件包 libqglviewer-dev 没有可安装候选
出现的原因是版本更新,有些包不存在了。
解决办法
下载最新版本g2o有问题,在编译的时候报错,使用slambook2中提供的g2o,下载链接:g2o,根据README.md的内容,安装依赖。
## Requirements
- C++17 compiler (CI pipeline runs with gcc, clang and MSVC)
- cmake <http://www.cmake.org>
- Eigen3 <http://eigen.tuxfamily.org>
On Ubuntu / Debian these dependencies are resolved by installing the
following packages.
- cmake
- libeigen3-dev
### Optional requirements
- spdlog <https://github.com/gabime/spdlog>
- suitesparse <http://faculty.cse.tamu.edu/davis/suitesparse.html>
- Qt5 <http://qt-project.org>
- libQGLViewer <http://www.libqglviewer.com>
On Ubuntu / Debian these dependencies are resolved by installing the
following packages.
- libspdlog-dev
- libsuitesparse-dev
- qtdeclarative5-dev
- qt5-qmake
- libqglviewer-dev-qt5
使用以下命令安装依赖
sudo apt-get install libspdlog-dev libsuitesparse-dev qtdeclarative5-dev qt5-qmake libqglviewer-dev-qt5
在这里,安装libspdlog-dev会显示成功,但实际上使用是有问题的,缺少==/spdlog/cfg/env.h==文件,所以需要单独安装以下,使用源码安装,源码地址,安装命令如下所示:
#安装
cd spdlog #进入下载并解压后的目录
mkdir build
cd build
cmake ..
make -j
sudo make install
#卸载
cd build #进入安装文件夹的build目录
sudo xargs rm < install_manifest.txt
安装依赖后,编译安装下载的g2o。
//进入文件目录
cd g2o-master/
//编译
mkdir build
cd build/
cmake ..
make
sudo make install
第七讲
实践
在第七讲的实践中,使用的是第一版的代码,cmake的时候报警告,make编译pose_estimation_3d3d.cpp、pose_estimation_3d2d.cpp报错。
尝试使用第2版的代码进行编译,但第二版使用库是模板库,之前安装的是非模板库,所以还是修改第一版代码。
问题1:cmake警告
解决办法
cmake警告并不影响后续编译,所以不管。
问题2:slambook-master/ch7/pose_estimation_3d2d.cpp 报错
编译的是时候,出现报错 /home/nova/slambook-master/ch7/pose_estimation_3d2d.cpp:151:50: error: no matching function for call to ‘g2o::BlockSolver<g2o::BlockSolverTraits<6, 3> >::BlockSolver(g2o::BlockSolver<g2o::BlockSolverTraits<6, 3> >::LinearSolverType*&)’
Block* solver_ptr = new Block ( linearSolver ); // 矩阵块求解器
错误出现的原因是,g2o更新导致用法不一样了,传入参数的类型发生了变化。
解决办法
修改pose_estimation_3d2d.cpp中148行附近的内容:
//修改前
// 初始化g2o
typedef g2o::BlockSolver< g2o::BlockSolverTraits<6,3> > Block; // pose 维度为 6, landmark 维度为 3
Block::LinearSolverType* linearSolver = new g2o::LinearSolverCSparse<Block::PoseMatrixType>(); // 线性方程求解器
Block* solver_ptr = new Block ( linearSolver ); // 矩阵块求解器
g2o::OptimizationAlgorithmLevenberg* solver = new g2o::OptimizationAlgorithmLevenberg ( solver_ptr );
g2o::SparseOptimizer optimizer;
optimizer.setAlgorithm ( solver );
修改为:
//修改后
// 初始化g2o
typedef g2o::BlockSolver< g2o::BlockSolverTraits<6,3> > Block; // pose 维度为 6, landmark 维度为 3
//Block::LinearSolverType* linearSolver = new g2o::LinearSolverCSparse<Block::PoseMatrixType>(); // 线性方程求解器
//Block* solver_ptr = new Block ( linearSolver ); // 矩阵块求解器
//g2o::OptimizationAlgorithmLevenberg* solver = new g2o::OptimizationAlgorithmLevenberg ( solver_ptr );
std::unique_ptr<Block::LinearSolverType> linearSolver ( new g2o::LinearSolverCSparse<Block::PoseMatrixType>());
std::unique_ptr<Block> solver_ptr ( new Block ( std::move(linearSolver))); // 矩阵块求解器
g2o::OptimizationAlgorithmLevenberg* solver = new g2o::OptimizationAlgorithmLevenberg ( std::move(solver_ptr));
g2o::SparseOptimizer optimizer;
optimizer.setAlgorithm ( solver );
问题3:slambook-master/ch7/pose_estimation_3d3d.cpp 报错
编译的时候,出现报错 /home/nova/slambook-master/ch7/pose_estimation_3d3d.cpp: In function ‘void bundleAdjustment(const std::vector<cv::Point3_ >&, const std::vector<cv::Point3_ >&, cv::Mat&, cv::Mat&)’:
/home/nova/slambook-master/ch7/pose_estimation_3d3d.cpp:279:49: error: no matching function for call to ‘g2o::BlockSolver<g2o::BlockSolverTraits<6, 3> >::BlockSolver(g2o::BlockSolver<g2o::BlockSolverTraits<6, 3> >::LinearSolverType*&)’
Block* solver_ptr = new Block( linearSolver ); // 矩阵块求解器
错误出现的原因是:g2o更新导致用法不一样了,传入参数的类型发生了变化。
解决办法
修改pose_estimation_3d3d.cpp中279行附近的内容:
修改前:
修改后:
// 初始化g2o
typedef g2o::BlockSolver< g2o::BlockSolverTraits<6,3> > Block; // pose维度为 6, landmark 维度为 3
std::unique_ptr<Block::LinearSolverType> linearSolver ( new g2o::LinearSolverEigen<Block::PoseMatrixType>());
std::unique_ptr<Block> solver_ptr ( new Block ( std::move(linearSolver)));
g2o::OptimizationAlgorithmGaussNewton* solver = new g2o::OptimizationAlgorithmGaussNewton ( std::move(solver_ptr));
g2o::SparseOptimizer optimizer;
optimizer.setAlgorithm( solver );
第八讲
实践
在第七讲的实践中,使用的是第一版的代码,make编译报错。错误原因和第七讲的原因一样。
问题1:slambook-master/ch8/directMethod/direct_sparse.cpp 报错
编译的时候,出现报错 :
解决办法
将slambook-master/ch8/directMethod/direct_sparse.cpp 258-260行注释,并添加以下代码:
// 修改后
/*
DirectBlock::LinearSolverType* linearSolver = new g2o::LinearSolverDense< DirectBlock::PoseMatrixType > ();
DirectBlock* solver_ptr = new DirectBlock ( linearSolver );
// g2o::OptimizationAlgorithmGaussNewton* solver = new g2o::OptimizationAlgorithmGaussNewton( solver_ptr ); // G-N
g2o::OptimizationAlgorithmLevenberg* solver = new g2o::OptimizationAlgorithmLevenberg ( solver_ptr ); // L-M
*/
std::unique_ptr<DirectBlock::LinearSolverType> linearSolver ( new g2o::LinearSolverDense< DirectBlock::PoseMatrixType > ());
std::unique_ptr<DirectBlock> solver_ptr ( new DirectBlock ( std::move(linearSolver))); // 矩阵块求解器
g2o::OptimizationAlgorithmLevenberg* solver = new g2o::OptimizationAlgorithmLevenberg ( std::move(solver_ptr));
问题2:slambook-master/ch8/directMethod/direct_semidense.cpp 报错
编译的时候,出现报错 :
error: no matching function for call to ‘g2o::BlockSolver<g2o::BlockSolverTraits<6, 1> >::BlockSolver(g2o::BlockSolver<g2o::BlockSolverTraits<6, 1> >::LinearSolverType*&)’
解决办法
修改direct_semidense.cpp *solver 的初始化:
原代码:
DirectBlock::LinearSolverType* linearSolver = new g2o::LinearSolverDense< DirectBlock::PoseMatrixType > ();
DirectBlock* solver_ptr = new DirectBlock ( linearSolver );
// g2o::OptimizationAlgorithmGaussNewton* solver = new g2o::OptimizationAlgorithmGaussNewton( solver_ptr ); // G-N
g2o::OptimizationAlgorithmLevenberg* solver = new g2o::OptimizationAlgorithmLevenberg ( solver_ptr ); // L-M
修改后:
std::unique_ptr<DirectBlock::LinearSolverType> linearSolver ( new g2o::LinearSolverDense< DirectBlock::PoseMatrixType > ());
std::unique_ptr<DirectBlock> solver_ptr ( new DirectBlock ( std::move(linearSolver))); // 矩阵块求解器
g2o::OptimizationAlgorithmLevenberg* solver = new g2o::OptimizationAlgorithmLevenberg ( std::move(solver_ptr));
第九讲
实践:0.3
在0.1和0.2中,按照书上的教程都能顺利编译,但在0.3的程序中,出现错误。
问题1:编译的时候slambook-master/project/0.3/src/visual_odometry.cpp报错
编译的时候,出现报错no matching function for call :
错误出现的原因是,g2o更新导致用法不一样了,传入参数的类型发生了变化,和第七讲一样。
解决办法
将slambook-master/project/0.3/src/visual_odometry.cpp中193-195行修改为以下代码:
// 修改后
//Block::LinearSolverType* linearSolver = new g2o::LinearSolverDense<Block::PoseMatrixType>();
//Block* solver_ptr = new Block( linearSolver );
//g2o::OptimizationAlgorithmLevenberg* solver = new g2o::OptimizationAlgorithmLevenberg ( solver_ptr );
std::unique_ptr<Block::LinearSolverType> linearSolver ( new g2o::LinearSolverDense<Block::PoseMatrixType>());
std::unique_ptr<Block> solver_ptr ( new Block ( std::move(linearSolver)));
g2o::OptimizationAlgorithmLevenberg* solver = new g2o::OptimizationAlgorithmLevenberg ( std::move(solver_ptr));
问题2:double free or corruption (out) 已放弃 (核心已转储):
运行程序时报错:
double free or corruption (out)
已放弃 (核心已转储)
问题出现的具体原因不知道,可能是g2o版本的问题。
解决办法
修改CMakeists中的内容:
将第6行:
set( CMAKE_CXX_FLAGS "-std=c++11 -march=native -O3" )
改成:
set( CMAKE_CXX_FLAGS "-std=c++11 -O3" )
实践:0.4
问题和解决方法同0.3。