參考:
https://blog.csdn.net/seymour163/article/details/53947764
https://blog.csdn.net/u011092188/article/details/77833022
https://blog.csdn.net/weixin_44684139/article/details/104803225
https://blog.csdn.net/weixin_44684139/article/details/105007316
https://blog.csdn.net/weixin_30480651/article/details/95558823☆https://blog.csdn.net/seymour163/article/details/53947764
還是那句話,不用看參考,來看我。
Semi-direct Visual Odometry(SVO)下載編譯
玩完orbslam,slam學習彷彿進入瓶頸,所以跑幾個開源代碼試一試。這次玩SVO。
1.準備工作
(1)創建工作空間
見這篇博文:https://blog.csdn.net/weixin_44684139/article/details/105258750
只需要看這一段:
創建完工作空間後,在工作空間common_space下/src中新建一個文件夾,名叫SVO。
注意,這個文件夾不僅僅防止SVO的源碼,還有SVO的一系列支持庫也安裝在這裏,會比較方便。
2.安裝依賴庫
接下來進入SVO文件夾。
安裝一系列依賴庫,依據這個鏈接:
https://blog.csdn.net/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.csdn.net/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++了。。。。。。。。。