参考:
https://blog.youkuaiyun.com/seymour163/article/details/53947764
https://blog.youkuaiyun.com/u011092188/article/details/77833022
https://blog.youkuaiyun.com/weixin_44684139/article/details/104803225
https://blog.youkuaiyun.com/weixin_44684139/article/details/105007316
https://blog.youkuaiyun.com/weixin_30480651/article/details/95558823☆https://blog.youkuaiyun.com/seymour163/article/details/53947764
还是那句话,不用看参考,来看我。
Semi-direct Visual Odometry(SVO)下载编译
玩完orbslam,slam学习仿佛进入瓶颈,所以跑几个开源代码试一试。这次玩SVO。
1.准备工作
(1)创建工作空间
见这篇博文:https://blog.youkuaiyun.com/weixin_44684139/article/details/105258750
只需要看这一段:
创建完工作空间后,在工作空间common_space下/src中新建一个文件夹,名叫SVO。
注意,这个文件夹不仅仅防止SVO的源码,还有SVO的一系列支持库也安装在这里,会比较方便。
2.安装依赖库
接下来进入SVO文件夹。
安装一系列依赖库,依据这个链接:
https://blog.youkuaiyun.com/seymour163/article/details/53947764
值得注意的是,有一个库比较特殊,叫做vikit,这个是提供一些有用的数学工具。
总结一下依赖库有:
1 Sophus李群库
2 Fast 角点检测库
3 g2o - General Graph Optimization (可选)
4 vikit - Some useful tools that we need
5 ROS 依赖项
但是玩了很久slam的人,除了fast检测和vikit可能其他的都有。
注意事项:
安装sophus库的时候,要注意,现在sophus版本迭代的原因,导致新版模板类sophus并不适用于这个SVO的源码。因此记得回滚:git checkout a621ff,这样安装才是旧版本的非模板类sophus。流程为:
/home/mjy/dev/common_space/src/SVO在终端打开,命令为:
git clone https://github.com/strasdat/Sophus.git
cd Sophus
git checkout a621ff
mkdir build
cd build
cmake ..
make
sudo make install
但是
有的童鞋已经安装过新版sophus了,想新旧两版共存,这样该怎么办呢?需要在cmake … 的地方加上安装路径CMAKE_INSTALL_PREFIX= ,这个路径我一般会选择在/usr/local/底下
流程为:
git clone https://github.com/strasdat/Sophus.git
cd Sophus
git checkout a621ff
mkdir build
cd build
cmake -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=/usr/local/Sophus_not_template ..
make
sudo make install
3.下载编译SVO
先克隆下来
cd /home/mjy/dev/common_space/src/SVO
git clone https://github.com/uzh-rpg/rpg_svo.git
会出现一个文件夹rpg_svo
然后向bashrc中加入本ros空间(common_space)的环境变量
打开/.bashrc文件,加入这一行(如果之前加过,比如我在玩上一个orbslam的时候就加过,那就忽略这里)
source /home/mjy/dev/common_space/devel/setup.sh
然后在终端
$ source ~/.bashrc
最后回到common_space下(工作空间下),编译一下
catkin_make
就编译成功了。也有可能编译不成功。见补充
4.编译不成功的补充
由于之前新安装的sophus是单独自己定义的文件夹,因此源码并不能找到它。仔细观察报错内容,是vikit_common的报错。
那就让我们改一下sophus的寻找路径。
找到文件
/home/mjy/dev/common_space/src/SVO/rpg_vikit/vikit_common/CMakeLists.txt
第二十六行:
# FIND_PACKAGE(Sophus REQUIRED) 先注释掉这个,因为直接find是find不到的
set(Sophus_INCLUDE_DIRS "/usr/local/Sophus_not_template/include")
set(Sophus_LIBS "/usr/local/Sophus_not_template/lib/libSophus.so")
第65行左右,加一行:set(Sophus_LIBRARIES libSophus.so) 这个必须加,否则也会报错
# Create vikit library
set(Sophus_LIBRARIES libSophus.so)
ADD_LIBRARY(${PROJECT_NAME} SHARED ${SOURCEFILES})
TARGET_LINK_LIBRARIES(${PROJECT_NAME}
${OpenCV_LIBS}
${Sophus_LIBRARIES}
${catkin_LIBRARIES})
再找到文件
/home/mjy/dev/common_space/src/SVO/rpg_vikit/vikit_ros/CMakeLists.txt
改动同上面一样。
然后重新回到common_space下:
cd /home/mjy/dev/common_space
catkin_make
就成功了。
5.测试无g2o版本
下载数据集链接:http://rpg.ifi.uzh.ch/datasets/airground_rig_s3_2013-03-18_21-38-48.bag
然后在/home/mjy/dev/common_space/src/SVO/rpg_svo下新建一个Data文件夹存放数据集
然后开启四个终端:
- terminal for roscore
roscore
- terminal for roslaunch
roslaunch svo_ros test_rig3.launch
- terminal for rviz (robot visualizer)
rosrun rviz rviz -d /home/mjy/dev/common_space/src/SVO/rpg_svo/svo_ros/rviz_config.rviz
- terminal for rosbag
cd /home/mjy/dev/common_space/src/SVO/rpg_svo/Data
rosbag play airground_rig_s3_2013-03-18_21-38-48.bag
测试成功:
6.测试有g2o版本
即,把svo/CmakeLists.txt里的HAVE_G20设置为TRUE。
至于如何保证搜索到g2o,我的方法见:https://blog.youkuaiyun.com/weixin_44684139/article/details/104876193
也就是添加了g2o/cmake_modules的所在位置并SET( G2O_ROOT /usr/local/include/g2o )
但是可以先不添加,先只改true试一下,要是以后编译报错,显示g2o库找不到,再回来将svo/CmakeLists.txt中加入合适的set设置
重新编译:catkin_make
但是报错:
/home/mjy/dev/common_space/src/SVO/rpg_svo/svo/src/bundle_adjustment.cpp: In function ‘void svo::ba::setupG2o(g2o::SparseOptimizer*)’:
/home/mjy/dev/common_space/src/SVO/rpg_svo/svo/src/bundle_adjustment.cpp:356:76: error: no matching function for call to ‘g2o::BlockSolver<g2o::BlockSolverTraits<6, 3> >::BlockSolver(g2o::BlockSolver<g2o::BlockSolverTraits<6, 3> >::LinearSolverType*&)’
g2o::BlockSolver_6_3 * solver_ptr = new g2o::BlockSolver_6_3(linearSolver);
^
In file included from /usr/local/include/g2o/core/block_solver.h:199:0,
from /home/mjy/dev/common_space/src/SVO/rpg_svo/svo/src/bundle_adjustment.cpp:20:
/usr/local/include/g2o/core/block_solver.hpp:40:1: note: candidate: g2o::BlockSolver<Traits>::BlockSolver(std::unique_ptr<typename Traits::LinearSolverType>) [with Traits = g2o::BlockSolverTraits<6, 3>; typename Traits::LinearSolverType = g2o::LinearSolver<Eigen::Matrix<double, 6, 6> >]
BlockSolver<Traits>::BlockSolver(std::unique_ptr<LinearSolverType> linearSolver)
^
/usr/local/include/g2o/core/block_solver.hpp:40:1: note: no known conversion for argument 1 from ‘g2o::BlockSolver<g2o::BlockSolverTraits<6, 3> >::LinearSolverType* {aka g2o::LinearSolver<Eigen::Matrix<double, 6, 6> >*}’ to ‘std::unique_ptr<g2o::LinearSolver<Eigen::Matrix<double, 6, 6> >, std::default_delete<g2o::LinearSolver<Eigen::Matrix<double, 6, 6> > > >’
/home/mjy/dev/common_space/src/SVO/rpg_svo/svo/src/bundle_adjustment.cpp:357:100: error: no matching function for call to ‘g2o::OptimizationAlgorithmLevenberg::OptimizationAlgorithmLevenberg(g2o::BlockSolver_6_3*&)’
g2o::OptimizationAlgorithmLevenberg * solver = new g2o::OptimizationAlgorithmLevenberg(solver_ptr);
这个错误太常见了,就是g2o版本迭代导致的问题,使得优化器初始化的时候报错,因此我将源码改为适配新版g2o的形式:
打开文件
/home/mjy/dev/common_space/src/SVO/rpg_svo/svo/src/bundle_adjustment.cpp
将345行开始的setupG2o函数改为如下版本:
void setupG2o(g2o::SparseOptimizer * optimizer)
{
// TODO: What's happening with all this HEAP stuff? Memory Leak?
optimizer->setVerbose(false);
#if SCHUR_TRICK
// solver
// ---------------------------------------------源代码报错,可能是g2o的版本问题
// g2o::BlockSolver_6_3::LinearSolverType* linearSolver;
//linearSolver = new g2o::LinearSolverCholmod<g2o::BlockSolver_6_3::PoseMatrixType>();
// // linearSolver = new g2o::LinearSolverCSparse<g2o::BlockSolver_6_3::PoseMatrixType>();
//g2o::BlockSolver_6_3 * solver_ptr = new g2o::BlockSolver_6_3(linearSolver);
// g2o::OptimizationAlgorithmLevenberg * solver = new g2o::OptimizationAlgorithmLevenberg(solver_ptr);
typedef g2o::BlockSolver_6_3 BlockSolverType;
typedef g2o::LinearSolverCholmod<g2o::BlockSolver_6_3::PoseMatrixType> LinearSolverType; // 线性求解器类型
auto solver = new g2o::OptimizationAlgorithmLevenberg( // 这里用高斯牛顿会报错
g2o::make_unique<BlockSolverType>(g2o::make_unique<LinearSolverType>()));
// 更改代码说明:
// 我的代码 == 旧代码
// (g2o::make_unique<LinearSolverType>()) == linearSolver
// solver_ptr == g2o::make_unique<BlockSolverType>(g2o::make_unique<LinearSolverType>())
#else
// g2o::BlockSolverX::LinearSolverType * linearSolver;
// linearSolver = new g2o::LinearSolverCholmod<g2o::BlockSolverX::PoseMatrixType>();
// //linearSolver = new g2o::LinearSolverCSparse<g2o::BlockSolverX::PoseMatrixType>();
// g2o::BlockSolverX * solver_ptr = new g2o::BlockSolverX(linearSolver);
// g2o::OptimizationAlgorithmLevenberg* solver = new g2o::OptimizationAlgorithmLevenberg(solver_ptr);
typedef g2o::BlockSolverX BlockSolverType;
typedef g2o::LinearSolverDense<BlockSolverType::PoseMatrixType> LinearSolverType; // 线性求解器类型
auto solver = new g2o::OptimizationAlgorithmLevenberg( // 这里用高斯牛顿会报错
g2o::make_unique<BlockSolverType>(g2o::make_unique<LinearSolverType>()));
#endif
// ---------------------------------------------源代码报错,可能是g2o的版本问题
solver->setMaxTrialsAfterFailure(5);
optimizer->setAlgorithm(solver);
// setup camera
g2o::CameraParameters * cam_params = new g2o::CameraParameters(1.0, Vector2d(0.,0.), 0.);
cam_params->setId(0);
if (!optimizer->addParameter(cam_params)) {
assert(false);
}
}
修改部分集中在两条分割线中间 // ---------------------------------------------源代码报错,可能是g2o的版本问题
然后再次编译:
catkin_make
成功
但是
真正测试roslaunch的时候又报错!!!!!
报错内容为:
[svo-1] process has died [pid 28239, exit code -6, cmd /home/mjy/dev/common_space/devel/lib/svo_ros/vo __name:=svo __log:=/home/mjy/.ros/log/0a3287a2-7a83-11ea-b077-d43b0495d50d/svo-1.log].
内存泄漏?!
发现只要g2o打开就报这个错误。我一度以为,还是这个g2o的问题。因此我又对BA文件的setupG2O进行了一次修改,这是另外一种修改方式——unique_ptr问题
下面将我第一版改的代码注释掉了。
分界线很清晰
void setupG2o(g2o::SparseOptimizer * optimizer)
{
// TODO: What's happening with all this HEAP stuff? Memory Leak?
optimizer->setVerbose(false);
#if SCHUR_TRICK
// solver
// ---------------------------------------------源代码报错,可能是g2o的版本问题
// g2o::BlockSolver_6_3::LinearSolverType* linearSolver;
//linearSolver = new g2o::LinearSolverCholmod<g2o::BlockSolver_6_3::PoseMatrixType>();
// // linearSolver = new g2o::LinearSolverCSparse<g2o::BlockSolver_6_3::PoseMatrixType>();
//g2o::BlockSolver_6_3 * solver_ptr = new g2o::BlockSolver_6_3(linearSolver);
// g2o::OptimizationAlgorithmLevenberg * solver = new g2o::OptimizationAlgorithmLevenberg(solver_ptr);
// 原基础上改的,unique_ptr问题
g2o::BlockSolver_6_3::LinearSolverType* linearSolver;
linearSolver = new g2o::LinearSolverCholmod<g2o::BlockSolver_6_3::PoseMatrixType>();
// linearSolver = new g2o::LinearSolverCSparse<g2o::BlockSolver_6_3::PoseMatrixType>();
g2o::BlockSolver_6_3 * solver_ptr = new g2o::BlockSolver_6_3( std::unique_ptr<g2o::BlockSolver_6_3::LinearSolverType>(linearSolver) );
g2o::OptimizationAlgorithmLevenberg * solver = new g2o::OptimizationAlgorithmLevenberg(std::unique_ptr<g2o::BlockSolver_6_3>(solver_ptr));
// --------------------------------------------我的代码
// typedef g2o::BlockSolver_6_3 BlockSolverType;
// typedef g2o::LinearSolverCholmod<g2o::BlockSolver_6_3::PoseMatrixType> LinearSolverType; // 线性求解器类型
// auto solver = new g2o::OptimizationAlgorithmLevenberg( // 这里用高斯牛顿会报错
// g2o::make_unique<BlockSolverType>(g2o::make_unique<LinearSolverType>()));
// --------------------------------------------我的代码
// 更改代码说明:
// 我的代码 == 旧代码
// (g2o::make_unique<LinearSolverType>()) == linearSolver
// solver_ptr == g2o::make_unique<BlockSolverType>(g2o::make_unique<LinearSolverType>())
#else
// g2o::BlockSolverX::LinearSolverType * linearSolver;
// linearSolver = new g2o::LinearSolverCholmod<g2o::BlockSolverX::PoseMatrixType>();
// //linearSolver = new g2o::LinearSolverCSparse<g2o::BlockSolverX::PoseMatrixType>();
// g2o::BlockSolverX * solver_ptr = new g2o::BlockSolverX(linearSolver);
// g2o::OptimizationAlgorithmLevenberg* solver = new g2o::OptimizationAlgorithmLevenberg(solver_ptr);
// 原基础上改的,unique_ptr问题
g2o::BlockSolverX::LinearSolverType * linearSolver;
linearSolver = new g2o::LinearSolverCholmod<g2o::BlockSolverX::PoseMatrixType>();
//linearSolver = new g2o::LinearSolverCSparse<g2o::BlockSolverX::PoseMatrixType>();
g2o::BlockSolverX * solver_ptr = new g2o::BlockSolverX( std::unique_ptr<g2o::BlockSolverX::LinearSolverType>(linearSolver) );
g2o::OptimizationAlgorithmLevenberg* solver = new g2o::OptimizationAlgorithmLevenberg(std::unique_ptr<g2o::BlockSolverX>(solver_ptr));
// --------------------------------------------我的代码
// typedef g2o::BlockSolverX BlockSolverType;
// typedef g2o::LinearSolverDense<BlockSolverType::PoseMatrixType> LinearSolverType; // 线性求解器类型
// auto solver = new g2o::OptimizationAlgorithmLevenberg( // 这里用高斯牛顿会报错
// g2o::make_unique<BlockSolverType>(g2o::make_unique<LinearSolverType>()));
// --------------------------------------------我的代码
#endif
// ---------------------------------------------源代码报错,可能是g2o的版本问题
solver->setMaxTrialsAfterFailure(5);
optimizer->setAlgorithm(solver);
// setup camera
g2o::CameraParameters * cam_params = new g2o::CameraParameters(1.0, Vector2d(0.,0.), 0.);
cam_params->setId(0);
if (!optimizer->addParameter(cam_params)) {
assert(false);
}
}
但是毫无意外,依然报错。。。。。。
然后又变更了稀疏求解方式。。。。变更了迭代方式。。。。。
全都报错
最后放弃,还是不要打开g2o了。。。。。。
我去学C++了。。。。。。。。。