在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系统下是否能够安装成功。
# 官方安装指导 # 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 installAndroid 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=http://www.likecs.com/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=http://www.likecs.com/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=http://www.likecs.com/path/to/sdk/ndk-bundle/build/cmake/android.toolchain.cmake \ -DEIGEN_INCLUDE_DIR=http://www.likecs.com/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的配置不会发生改变。
测试结果