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 源码中 includesrcThirdparty 三个文件夹拷贝到新建的 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 修改为 #include ,并去掉 tr1 命名空间

//g2o/g2o/core/hyper_graph.h 41行 94行

//#include  41行
#include 
...
//      typedef std::tr1::unordered_map     VertexIDMap;      94行
typedef std::unordered_map     VertexIDMap;
// g2o/g2o/core/sparse_block_matrix_ccs.h  

//#include  40行
#include 
...
//      typedef std::tr1::unordered_map SparseColumn; 227行
typedef std::tr1::unordered_map SparseColumn;
// g2o/g2o/core/estimate_propagator.h  

//#include  40行
#include 
...
//      typedef std::tr1::unordered_map AdjacencyMap; 139行
typedef std::unordered_map AdjacencyMap;
// g2o/g2o/core/robust_kernel.h  

//#include  33行
#include 
...
//      ttypedef std::tr1::shared_ptr RobustKernelPtr; 78行
typedef std::shared_ptr RobustKernelPtr;
// g2o/g2o/core/marginal_covariance_cholesky.h  

//#include  39行
#include 
...
//      typedef std::tr1::unordered_map     LookupMap; 54行
typedef std::unordered_map     LookupMap;

继续编译,Map.h 中找不到 pangolin/pangolin.h

Pangolin 库是 Linux 上基于 OpenGL 用于 3D 绘图的。在Android平台用不上可以将其移除。

ScreenClip [5].png

2.7 移除 Pangolin

修改 Map.h & Map.cc

// Map.h 
//#include  27行
...

//    GLubyte* mThumbnail; 191行   
unsigned char* mThumbnail;
// Map.cc 
//    mThumbnail = static_cast(NULL); 33行    
mThumbnail = static_cast(NULL);
...
//    mThumbnail = static_cast(NULL); 42行    
mThumbnail = static_cast(NULL);
...
//    mThumbnail = static_cast(NULL); 56行    
mThumbnail = static_cast(NULL);

修改 Syetem.cc

// MapDrawer.h 
//#include  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
#include

2.9 se3mat.h 'eigen3/Eigen/Geometry' file not found

//#include
//#include
#include
#include

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 文件夹。将编译产物 includelib 文件夹拷贝到 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(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,最后贴一张编译产物图


你可能感兴趣的:(ORB-SLAM3 Android 移植保姆式图文流程(全网唯一))