在Android平台上使用Ceres求解器,官方教程不明確,且編譯過程遇到了很多問題。
環境
Ubuntu 18.04
源代碼
https://github.com/Great-Keith/ceres-android
准備工作
Eigen 3.3.7(最新):在編譯Ceres的時候需要使用。
NDK r20(最新):NDK r14b版本無法使用,建議使用高於14的版本。
Ceres 1.14.0(最新)已經附帶在倉庫中。
[NOTE] Ceres其他依賴項按照官方教程進行配置,建議先檢驗Linux系統下是否能夠安裝成功。
# 官方安裝指導 http://ceres-solver.org/installation.html
# CMake
sudo apt-get install cmake
# google-glog + gflags
sudo apt-get install libgoogle-glog-dev
# BLAS & LAPACK
sudo apt-get install libatlas-base-dev
# Eigen3
sudo apt-get install libeigen3-dev
# SuiteSparse and CXSparse (optional)
# - If you want to build Ceres as a *static* library (the default)
# you can use the SuiteSparse package in the main Ubuntu package
# repository:
sudo apt-get install libsuitesparse-dev
# - However, if you want to build Ceres as a *shared* library, you must
# add the following PPA:
sudo add-apt-repository ppa:bzindovic/suitesparse-bugfix-1319687
sudo apt-get update
sudo apt-get install libsuitesparse-dev
mkdir ceres-bin
cd ceres-bin
cmake ../ceres-solver-1.14.0
make -j3
make test
# Optionally install Ceres, it can also be exported using CMake which
# allows Ceres to be used without requiring installation, see the documentation
# for the EXPORT_BUILD_DIR option for more information.
make install
Android Studio 3.4.1:需要配置CMake, LLDB, ndk(在SDK Tools中點擊安裝)
官方Android指南
來源一:官方網站
原文
下載版本高於r9d的Android NDK版本,在jni目錄下使用ndk-build進行編譯,你會得到libceres.a。
解釋
具體使用方法:
cd ceres-solver-1.14.0/jni
EIGEN_PATH=/path/to/eigen/header ndk-build
隨后libceres.a便會出現在ceres-solver-1.14.0/obj/local/${ABI}目錄下。
${ABI}的值通過修改Application.mk中的APP_ABI := arm64-v8a一行,可.以換armeabi-7va, x86_64等等。
至於動態庫(*.so)的生成,根據網上的一些教程進行修改Android.mk和Application.mk,都無法正常編譯,官方GitHub里的issue中對於這些報錯,建議使用CMake進行編譯。
[NOTE] 如果從GitHub上clone的版本是不帶jni目錄的,只能使用CMake進行編譯。
來源二:代碼內的文檔
原文
編譯需要使用NDK r15或者更高版本。
需要使用CMake尋找NDK當中的toolchain來替換本身的自帶toolchain。假設你已經設置了變量$NDK_DIR,你可以使用如下命令編譯:
cmake \
-DCMAKE_TOOLCHAIN_FILE=\
$NDK_DIR/build/cmake/android.toolchain.cmake \
-DEIGEN_INCLUDE_DIR=/path/to/eigen/header \
-DANDROID_ABI=armeabi-v7a \
-DANDROID_STL=c++_shared \
-DANDROID_NATIVE_API_LEVEL=android-24 \
-DBUILD_SHARED_LIBS=ON \
-DMINIGLOG=ON \
<PATH_TO_CERES_SOURCE>
你可以為各種安卓STL或ABI進行編譯,但是最推薦使用c++_shared STL和armeabi-v7a(對於32位機)或arm64-v8a(對於64位機) ABI。許多API的版本都可以進行支持,但是推薦使用你安卓項目所支持的最高版本。
對於你的安卓項目和Ceres二進制文件,你需要使用相同的API版本和STL進行編譯。
編譯完成之后,你會得到一份libceres.so的庫,你可以在編譯的腳本中通過使用PREBUILT_SHARED_LIBRARY將它鏈接到你的安卓項目當中。
如果你正在編譯Ceres的例子,想要驗證你的庫能否使,你需要將他們和libceres.so放在安卓設備上一個可執行的公共目錄下(比如/data/local/tmp),並且確保NDK的STL也在同一個目錄下。
需要注意的是,所有的求解器或者其他被你包含在項目中的共享依賴項,都需要出現在你安卓的編譯配置和你的測試目錄當中。
解釋
最好采用CMake編譯這種方法,后面解釋如何修改這個命令。
編譯命令
參考資料:https://github.com/qiu-yongheng/cerestest
根據官方材料和參考資料得出如下命令:
rm -rf CMake*
/path/to/sdk/cmake/[version]/bin/cmake \
-DCMAKE_TOOLCHAIN_FILE=/path/to/sdk/ndk-bundle/build/cmake/android.toolchain.cmake \
-DEIGEN_INCLUDE_DIR=/path/to/eigen/header \
-DANDROID_ABI=[ABI]] \
-DANDROID_STL=[c++_shared | c++_static] \
-DANDROID_NATIVE_API_LEVEL=android-24 \
-DBUILD_SHARED_LIBS=ON \
-DMINIGLOG=ON \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_C_FLAGS="-s" \
-DCMAKE_C_FLAGS=-std=c99 -Os -fvisibility=hidden \
/path/to/ceres
make clean
make
make install
執行如上命令后,首先會遇到如下錯誤:undefined reference to '__android_log_write'
解決方法:打開[ceres]/internal/ceres/minglog/glog/logging.h,搜索__android_log_write,將帶有這個函數的幾行注釋掉。
重新編譯,最后會報錯誤:'libc++_shared.so' no found
解決方法:這個錯誤無關緊要,可以看到當前目錄下的lib目錄已經生成了我們想要的庫文件。從ndk-bundle中復制我們所需要的該文件到安卓項目中即可,該文件目錄可能是ndk-bundle/sources/cxx-stl/llvm-libc++/libs/[ABI]。無需繼續進行編譯。
[NOTE] /path/to/eigen/header這個地址,不能使用安裝eigen時候放置到的比如/usr/include地址,否則編譯的時候會出現沖突,應該直接使用下載解壓后的位置。
[NOTE] 每次cmake后,重新編譯需要提前先刪除當前目錄下的CMakeFiles, CMakeCache等中間文件,否則CMake的配置不會發生改變。
測試結果

