美文网首页
ORB-SLAM3 Android 移植保姆式图文流程(全网唯一

ORB-SLAM3 Android 移植保姆式图文流程(全网唯一

作者: Damon_He | 来源:发表于2022-07-01 18:07 被阅读0次

    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 <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

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

    ScreenClip [5].png

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


    相关文章

      网友评论

          本文标题:ORB-SLAM3 Android 移植保姆式图文流程(全网唯一

          本文链接:https://www.haomeiwen.com/subject/psncbrtx.html