ORB-SLAM3 Android 移植保姆式图文流程(全网唯一
ORB-SLAM3 Android 移植
1. 前期准备
ORB-SLAM3 开源链接:https://github.com/UZ-SLAMLab/ORB_SLAM3
依赖库如下:
- boost
- openssl
- OpenCV
- Eigen3
- DBoW2 and g2o
- Sophus
1.1 Android Studio新建 Native 工程
该步骤省略...
1.2 导入ORB-SLAM3源码
- cpp下新建文件夹 "orb-slam3" 用于存放 ORB-SLAM3 相关源码。
- 将 clone 下来的 ORB-SLAM3 源码中 include、 src 、Thirdparty 三个文件夹拷贝到新建的 orb-slam3 文件夹下。
- orb-slam3 文件夹下新建 CMakeLists.txt 。
1.3 编写 CMakeLists
# orb-slam3 下的 CMakeLists.txt
cmake_minimum_required(VERSION 3.18.1)
project(orbslam3)
include_directories(include include/CameraModels)
file(GLOB SRC_LIST "src/*.cc" "src/*.cpp" "src/CameraModels/*.cpp")
add_library(${PROJECT_NAME} SHARED ${SRC_LIST})
target_link_libraries( ${PROJECT_NAME} log)
此时编译肯定会报错,没关系尝试编译一下,看具体错误是哪些,挨个解决。
可以看到主要是 3 个依赖库(OpenCV、DBoW2、g2o)的头文件找不到。下面将缺少的依赖库逐个添加进来。
2. 第三方依赖库的编译与添加
2.1 OpenCV
前往 OpenCV 官网下载Android版本SDK
解压后更新 CMakeLists.txt 文件。
# orb-slam3 下的 CMakeLists.txt`
cmake_minimum_required(VERSION 3.18.1)
project(orbslam3)
include_directories(include include/CameraModels)
file(GLOB SRC_LIST "src/*.cc" "src/*.cpp" "src/CameraModels/*.cpp")
##-------------------------第三方库--------------------------------
# opencv (注意改成自己的路径)
set(OpenCV_DIR
D:/opencv/opencv-4.6.0-android-sdk/OpenCV-android-sdk/sdk/native/jni)
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
add_library(${PROJECT_NAME} SHARED ${SRC_LIST})
target_link_libraries( ${PROJECT_NAME} log)
2.2 DBoW2
DBoW2 库源码中已经包含,需要修改 CMakeLists 文件依赖进来。
# orb-slam3 下的 CMakeLists.txt
cmake_minimum_required(VERSION 3.18.1)
project(orbslam3)
include_directories(include include/CameraModels)
file(GLOB SRC_LIST "src/*.cc" "src/*.cpp" "src/CameraModels/*.cpp")
include_directories(.)
##-------------------------第三方库--------------------------------
include_directories(Thirdparty)
# opencv (注意改成自己的路径)
set(OpenCV_DIR
D:/opencv/opencv-4.6.0-android-sdk/OpenCV-android-sdk/sdk/native/jni)
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
# DBoW2
add_subdirectory(Thirdparty/DBoW2)
add_library(${PROJECT_NAME} SHARED ${SRC_LIST})
target_link_libraries( ${PROJECT_NAME} log)
修改 DBoW2 文件夹下的 CMakeLists.txt
# DBoW2 下的 CMakeLists.txt
cmake_minimum_required(VERSION 3.18.1)
project(DBoW2)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -O3")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -O3")
include_directories(DBoW2 DUtils)
file(GLOB SRC_LIST "DBoW2/*.cpp" "DUtils/*.cpp")
include_directories(${OpenCV_INCLUDE_DIRS})
add_library(DBoW2 SHARED ${SRC_LIST})
target_link_libraries(DBoW2 ${OpenCV_LIBS})
2.3 g2o
与 DBoW2 一样的操作。
# orb-slam3 下的 CMakeLists.txt
cmake_minimum_required(VERSION 3.18.1)
project(orbslam3)
include_directories(include include/CameraModels)
file(GLOB SRC_LIST "src/*.cc" "src/*.cpp" "src/CameraModels/*.cpp")
include_directories(.)
##-------------------------第三方库--------------------------------
include_directories(Thirdparty)
# opencv (注意改成自己的路径)
set(OpenCV_DIR
D:/opencv/opencv-4.6.0-android-sdk/OpenCV-android-sdk/sdk/native/jni)
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
# DBoW2
add_subdirectory(Thirdparty/DBoW2)
# g2o
add_subdirectory(Thirdparty/g2o)
add_library(${PROJECT_NAME} SHARED ${SRC_LIST})
target_link_libraries( ${PROJECT_NAME} log)
# g2o 下的 CMakeLists.txt
cmake_minimum_required(VERSION 3.18.1)
project(g2o)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -W")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -W")
configure_file(config.h.in ${g2o_SOURCE_DIR}/config.h)
include_directories(g2o/core g2o/solvers g2o/stuff g2o/types)
include_directories(../eigen-3.4.0)
file(GLOB SRC_LIST "g2o/types/*.cpp" "g2o/core/*.cpp" "g2o/stuff/*.cpp"
"g2o/stuff/*.c")
add_library(g2o SHARED ${SRC_LIST})
三个库添加好之后,再次尝试编译。依旧数十条报错,不要慌,继续看具体是什么错。
可以看到还有依赖的第三方库没有找到。继续整!
2.4 Eigen
官网下载
这里下载的是最新的版本 3.4.0,解压后拷贝到 ThirdParty 下。
同时,修改 CMakeLists 文件。
# orb-slam3 下的 CMakeLists.txt
cmake_minimum_required(VERSION 3.18.1)
project(orbslam3)
include_directories(include include/CameraModels)
file(GLOB SRC_LIST "src/*.cc" "src/*.cpp" "src/CameraModels/*.cpp")
include_directories(.)
##-------------------------第三方库--------------------------------
include_directories(Thirdparty)
# opencv (注意改成自己的路径)
set(OpenCV_DIR
D:/opencv/opencv-4.6.0-android-sdk/OpenCV-android-sdk/sdk/native/jni)
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
# DBoW2
add_subdirectory(Thirdparty/DBoW2)
# g2o
add_subdirectory(Thirdparty/g2o)
add_library(${PROJECT_NAME} SHARED ${SRC_LIST})
target_link_libraries( ${PROJECT_NAME} log)
# Eigen
include_directories(Thirdparty/eigen-3.4.0/)
include_directories(Thirdparty/eigen-3.4.0/Eigen)
include_directories(Thirdparty/eigen-3.4.0/Eigen/src)
2.5 Sophus
该库源码中已经有了。继续修改 CMakeLists 文件。
# orb-slam3 下的 CMakeLists.txt
cmake_minimum_required(VERSION 3.18.1)
project(orbslam3)
include_directories(include include/CameraModels)
file(GLOB SRC_LIST "src/*.cc" "src/*.cpp" "src/CameraModels/*.cpp")
include_directories(.)
##-------------------------第三方库--------------------------------
include_directories(Thirdparty)
# opencv (注意改成自己的路径)
set(OpenCV_DIR
D:/opencv/opencv-4.6.0-android-sdk/OpenCV-android-sdk/sdk/native/jni)
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
# DBoW2
add_subdirectory(Thirdparty/DBoW2)
# g2o
add_subdirectory(Thirdparty/g2o)
add_library(${PROJECT_NAME} SHARED ${SRC_LIST})
target_link_libraries( ${PROJECT_NAME} log)
# Eigen
include_directories(Thirdparty/eigen-3.4.0/)
include_directories(Thirdparty/eigen-3.4.0/Eigen)
include_directories(Thirdparty/eigen-3.4.0/Eigen/src)
# Sophus
include_directories(Thirdparty/Sophus)
2.6 'tr1/xxx' file not found问题
#include <tr1/xxx>
修改为 #include <xxx>
,并去掉 tr1 命名空间
//g2o/g2o/core/hyper_graph.h 41行 94行
//#include <tr1/unordered_map> 41行
#include <unordered_map>
...
// typedef std::tr1::unordered_map<int, Vertex*> VertexIDMap; 94行
typedef std::unordered_map<int, Vertex*> VertexIDMap;
// g2o/g2o/core/sparse_block_matrix_ccs.h
//#include <tr1/unordered_map> 40行
#include <unordered_map>
...
// typedef std::tr1::unordered_map<int, MatrixType*> SparseColumn; 227行
typedef std::tr1::unordered_map<int, MatrixType*> SparseColumn;
// g2o/g2o/core/estimate_propagator.h
//#include <tr1/unordered_map> 40行
#include <unordered_map>
...
// typedef std::tr1::unordered_map<OptimizableGraph::Vertex*, AdjacencyMapEntry, VertexIDHashFunction> AdjacencyMap; 139行
typedef std::unordered_map<OptimizableGraph::Vertex*, AdjacencyMapEntry,
VertexIDHashFunction> AdjacencyMap;
// g2o/g2o/core/robust_kernel.h
//#include <tr1/unordered_map> 33行
#include <unordered_map>
...
// ttypedef std::tr1::shared_ptr<RobustKernel> RobustKernelPtr; 78行
typedef std::shared_ptr<RobustKernel> RobustKernelPtr;
// g2o/g2o/core/marginal_covariance_cholesky.h
//#include <tr1/unordered_map> 39行
#include <unordered_map>
...
// typedef std::tr1::unordered_map<int, double> LookupMap; 54行
typedef std::unordered_map<int, double> LookupMap;
继续编译,Map.h
中找不到 pangolin/pangolin.h
。
ScreenClip [5].png
Pangolin
库是 Linux 上基于 OpenGL 用于 3D 绘图的。在Android平台用不上可以将其移除。
2.7 移除 Pangolin
修改 Map.h & Map.cc
// Map.h
//#include <pangolin/pangolin.h> 27行
...
// GLubyte* mThumbnail; 191行
unsigned char* mThumbnail;
// Map.cc
// mThumbnail = static_cast<GLubyte*>(NULL); 33行
mThumbnail = static_cast<unsigned char*>(NULL);
...
// mThumbnail = static_cast<GLubyte*>(NULL); 42行
mThumbnail = static_cast<unsigned char*>(NULL);
...
// mThumbnail = static_cast<GLubyte*>(NULL); 56行
mThumbnail = static_cast<unsigned char*>(NULL);
修改 Syetem.cc
// MapDrawer.h
//#include <pangolin/pangolin.h> 24行
...
// void DrawCurrentCamera(pangolin::OpenGlMatrix &Twc); 48行
...
// void GetCurrentOpenGLCameraMatrix(pangolin::OpenGlMatrix &M, pangolin::OpenGlMatrix &MOw); 51行
2.8 'stdint-gcc.h' file not found
stdint-gcc.h 改为 stdint.h
// orb-slam3/src/ORBmatcher.cc
// orb-slam3/Thirdparty/DBoW2/DBoW2/FORB.cpp
//#include<stdint-gcc.h>
#include<stdint.h>
2.9 se3mat.h 'eigen3/Eigen/Geometry' file not found
//#include<eigen3/Eigen/Geometry>
//#include<eigen3/Eigen/Core>
#include<Eigen/Geometry>
#include<Eigen/Core>
2.10 System.cc 'openssl/md5.h' file not found
openssl 需要交叉编译。
3. openssl 交叉编译
Linux环境
自行解决...
下载openssl源码
git clone git://git.openssl.org/openssl.git
编写 Shell 编译脚本:
#!/bin/bash
set -e
set -x
# 改成自己路径
SCRIPTPATH=/home/damon/openssl
export ANDROID_NDK_ROOT=/home/damon/android-ndk-r24
export OPENSSL_DIR=/home/damon/openssl/
toolchains_path=${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/linux-x86_64
# 这里用的最新的ndk-r24版本使用clang编译。低版本ndk自行修改成gcc编译
CC=clang
PATH=$toolchains_path/bin:$PATH
# 自行修改Android版本
ANDROID_API=21
# 64位so:arm64-v8a
outdir=armeabi-v7a
# 64位so:android-arm64
architecture=android-arm
cd ${OPENSSL_DIR}
make clean
./Configure ${architecture} -D__ANDROID_API__=$ANDROID_API
make
OUTPUT_INCLUDE=$SCRIPTPATH/output/include
OUTPUT_LIB=$SCRIPTPATH/output/lib/${outdir}
mkdir -p $OUTPUT_INCLUDE
mkdir -p $OUTPUT_LIB
cp -RL include/openssl $OUTPUT_INCLUDE
cp libcrypto.so $OUTPUT_LIB
cp libcrypto.a $OUTPUT_LIB
cp libssl.so $OUTPUT_LIB
cp libssl.a $OUTPUT_LIB
//授权执行编译
chmod 777 build.sh
./build.sh
arm64-v8a 的so库修改一下shell脚本多编译一次即可。
编译产物在 output 目录。
- 在本地工程 ThirdParty 文件夹下新建 openssl 文件夹。将编译产物 include 和 lib 文件夹拷贝到
ThirdParty/openssl
下。 - 修改 CMakeLists 文件。
cmake_minimum_required(VERSION 3.18.1)project(orb-slam3)
#-------------------------ORB-SLAM3---------------------------------
# orb-slam3 头文件
include_directories(include include/CameraModels)
# orb-slam3 源文件
file(GLOB SRC_LIST "src/*.cc" "src/*.cpp" "src/CameraModels/*.cpp")
include_directories(.)
#-------------------------第三方库---------------------------------
include_directories(Thirdparty)
# opencv
set(OpenCV_DIR
D:/opencv/opencv-4.6.0-android-sdk/OpenCV-android-sdk/sdk/native/jni)
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
# g2o
add_subdirectory(Thirdparty/g2o)
# DBoW2
add_subdirectory(Thirdparty/DBoW2)
# Sophus
include_directories(Thirdparty/Sophus)
# Eigen
include_directories(Thirdparty/eigen-3.4.0/)
include_directories(Thirdparty/eigen-3.4.0/Eigen)
include_directories(Thirdparty/eigen-3.4.0/Eigen/src)
# openssl
include_directories(Thirdparty/openssl/include)
add_library(crypto SHARED IMPORTED)
set_target_properties(crypto PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/Thirdparty/openssl/lib/${ANDROID_ABI}/libcrypto.so)
add_library(ssl SHARED IMPORTED)
set_target_properties(ssl PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/Thirdparty/openssl/lib/${ANDROID_ABI}/libssl.so)
4. boost交叉编译
参考链接:https://github.com/moritz-wundke/Boost-for-Android
这里使用的 boost 版本是1.72.0,其他版本的编译自行参考解决。
与 openssl 一样的套路,ThirdParty 目录下新建 boot 文件夹,将 linux 中编译产物头文件与lib拷贝进来。(ps: 头文件比较多需要较长时间)
同时修改 CMakeLists 文件。
cmake_minimum_required(VERSION 3.18.1)project(orb-slam3)
#-------------------------ORB-SLAM3---------------------------------
# orb-slam3 头文件
include_directories(include include/CameraModels)
# orb-slam3 源文件
file(GLOB SRC_LIST "src/*.cc" "src/*.cpp" "src/CameraModels/*.cpp")
include_directories(.)
#-------------------------第三方库---------------------------------
include_directories(Thirdparty)
# opencv
set(OpenCV_DIR
D:/opencv/opencv-4.6.0-android-sdk/OpenCV-android-sdk/sdk/native/jni)
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
# g2o
add_subdirectory(Thirdparty/g2o)
# DBoW2
add_subdirectory(Thirdparty/DBoW2)
# Sophus
include_directories(Thirdparty/Sophus)
# Eigen
include_directories(Thirdparty/eigen-3.4.0/)
include_directories(Thirdparty/eigen-3.4.0/Eigen)
include_directories(Thirdparty/eigen-3.4.0/Eigen/src)
# openssl
include_directories(Thirdparty/openssl/include)
add_library(crypto SHARED IMPORTED)
set_target_properties(crypto PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/Thirdparty/openssl/lib/${ANDROID_ABI}/libcrypto.so)
add_library(ssl SHARED IMPORTED)
set_target_properties(ssl PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/Thirdparty/openssl/lib/${ANDROID_ABI}/libssl.so)
# boost
include_directories(Thirdparty/boost-1_72_0/include)
add_library(boost_system STATIC IMPORTED)
set_target_properties(boost_system PROPERTIES IMPORTED_LOCATION
${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libboost_1_72_0/libboost_system.a)
add_library(boost_atomic STATIC IMPORTED)
set_target_properties(boost_atomic PROPERTIES IMPORTED_LOCATION
${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libboost_1_72_0/libboost_atomic.a)
add_library(boost_serialization STATIC IMPORTED)
set_target_properties(boost_serialization PROPERTIES IMPORTED_LOCATION
${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libboost_1_72_0/libboost_serialization.a)
target_link_libraries(${PROJECT_NAME} ${OpenCV_LIBS} DBoW2 g2o crypto ssl log)
5. 移除 Linux 绘图相关代码
- 删除 Viewer.h 和 Viewer.cc
- 删除 FrameDrawer.h 和 FrameDrawer.cc
- 删除 MapDrawer.h 和 MapDrawer.cc
- 其他源码中相关引用代码删除(主要修改 System 和 Tracking)
改动比较多前面数字表示行号,自行对照修改
// System.h
32 //#include "FrameDrawer.h"
33 //#include "MapDrawer.h"
39 //#include "Viewer.h"
74 //class Viewer;
75 //class FrameDrawer;
76 //class MapDrawer;
228 //Viewer* mpViewer;
230 //FrameDrawer* mpFrameDrawer;
231 //MapDrawer* mpMapDrawer;
// System.cc
43 /*mpViewer(static_cast<Viewer*>(NULL)),*/
185 //mpFrameDrawer = new FrameDrawer(mpAtlas);
186 //mpMapDrawer = new MapDrawer(mpAtlas, strSettingsFile, settings_);
191 /*mpFrameDrawer, mpMapDrawer,*/
229 /*if(bUseViewer)
//if(false) // TODO
{
mpViewer = new Viewer(this, mpFrameDrawer,mpMapDrawer,mpTracker,strSettingsFile,settings_);
mptViewer = new thread(&Viewer::Run, mpViewer);
mpTracker->SetViewer(mpViewer);
mpLoopCloser->mpViewer = mpViewer;
mpViewer->both = mpFrameDrawer->both;
}*/
// Tracking.h
26 //#include "Viewer.h"
27 //#include "FrameDrawer.h"
35 //#include "MapDrawer.h"
48 //class Viewer;
49 //class FrameDrawer;
80 //void SetViewer(Viewer* pViewer);
281 //Viewer* mpViewer;
282 //FrameDrawer* mpFrameDrawer;
283 //MapDrawer* mpMapDrawer;
// Tracking.cc
23 //#include "FrameDrawer.h"
44 /*FrameDrawer *pFrameDrawer, MapDrawer *pMapDrawer,*/
47 /*mpViewer(NULL),*/
48 /*mpFrameDrawer(pFrameDrawer), mpMapDrawer(pMapDrawer),*/
568 //mpFrameDrawer->both = true;
1090 //mpFrameDrawer->both = true;
1437 /*void Tracking::SetViewer(Viewer *pViewer
{
mpViewer=pViewer;
}*/
2201 /*mpFrameDrawer->Update(this);if(mCurrentFrame.isSet()) mpMapDrawer->SetCurrentCameraPose(mCurrentFrame.GetPose());*/
2219 /*if(mSensor == System::IMU_MONOCULAR || mSensor == System::IMU_STEREO || mSensor
== System::IMU_RGBD) mpMapDrawer->SetCurrentCameraPose(mCurrentFrame.GetPose());*/
2441 //mpMapDrawer->SetCurrentCameraPose(mCurrentFrame.GetPose());
2652 //mpMapDrawer->SetCurrentCameraPose(pKFcur->GetPose());
3783 /*if(mpViewer){ mpViewer->RequestStop(); while(!mpViewer->isStopped()) usleep(3000);}*/
3834 /*if(mpViewer) mpViewer->Release();*/
3843 /*if(mpViewer){ mpViewer->RequestStop(); while(!mpViewer->isStopped()) usleep(3000);}*/
3925 /*if(mpViewer) mpViewer->Release();*/
至此ORB-SLAM3移植Android平台编译OK,最后贴一张编译产物图