ORB-SLAM3 Android 移植
1. 前期準(zhǔn)備
ORB-SLAM3 開源鏈接:https://github.com/UZ-SLAMLab/ORB_SLAM3
依賴庫如下:
- boost
- openssl
- OpenCV
- Eigen3
- DBoW2 and g2o
- Sophus
1.1 Android Studio新建 Native 工程
該步驟省略...
1.2 導(dǎo)入ORB-SLAM3源碼
- cpp下新建文件夾 "orb-slam3" 用于存放 ORB-SLAM3 相關(guān)源碼。
- 將 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)
此時編譯肯定會報錯,沒關(guān)系嘗試編譯一下,看具體錯誤是哪些,挨個解決。

可以看到主要是 3 個依賴庫(OpenCV、DBoW2、g2o)的頭文件找不到。下面將缺少的依賴庫逐個添加進(jìn)來。
2. 第三方依賴庫的編譯與添加
2.1 OpenCV
前往 OpenCV 官網(wǎng)下載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 庫源碼中已經(jīng)包含,需要修改 CMakeLists 文件依賴進(jìn)來。
# 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})
三個庫添加好之后,再次嘗試編譯。依舊數(shù)十條報錯,不要慌,繼續(xù)看具體是什么錯。

可以看到還有依賴的第三方庫沒有找到。繼續(xù)整!
2.4 Eigen
官網(wǎng)下載
這里下載的是最新的版本 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
該庫源碼中已經(jīng)有了。繼續(xù)修改 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;
繼續(xù)編譯,Map.h 中找不到 pangolin/pangolin.h。
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環(huán)境
自行解決...
下載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
//授權(quán)執(zhí)行編譯
chmod 777 build.sh
./build.sh
arm64-v8a 的so庫修改一下shell腳本多編譯一次即可。
編譯產(chǎn)物在 output 目錄。
- 在本地工程 ThirdParty 文件夾下新建 openssl 文件夾。將編譯產(chǎn)物 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 中編譯產(chǎn)物頭文件與lib拷貝進(jìn)來。(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 繪圖相關(guān)代碼
- 刪除 Viewer.h 和 Viewer.cc
- 刪除 FrameDrawer.h 和 FrameDrawer.cc
- 刪除 MapDrawer.h 和 MapDrawer.cc
- 其他源碼中相關(guān)引用代碼刪除(主要修改 System 和 Tracking)
改動比較多前面數(shù)字表示行號,自行對照修改
// 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,最后貼一張編譯產(chǎn)物圖
