资讯动态

Ubuntu 20.04下Ceres Solver源码编译与SLAM集成完整指南

发布时间:2026/10/3 7:44:10 来源:尧图企业网站定制
1. 安装前先弄清楚Ceres依赖什么、为什么源码编译最稳Ceres Solver在SLAM、三维重建、相机标定这些方向几乎是绕不开的依赖库ORB-SLAM3、VINS-Fusion、LIO-SAM这些项目里都能看到它的身影。它本质上是一个专门求解非线性最小二乘问题的C库对于搞过优化求解的同学来说Ceres就像是一个老朋友帮你把复杂的数值优化过程封装得明明白白。我在Ubuntu20.04上部署这些项目时踩过不少坑这篇文章就把整个安装过程从头到尾捋一遍包括每个依赖包的作用、版本怎么选、编译的时候有哪些坑希望能让读者少走弯路。1.1 Ceres到底解决什么问题先花半分钟说清楚Ceres是干什么的。在视觉SLAM里我们要根据图像特征点的观测来估计相机位姿和地图点位置这个问题最终会转化成一个最小化重投影误差的优化问题。手写高斯牛顿法或者LM算法不是不行但工程上要考虑稀疏性、鲁棒核函数、数值求导这些问题工作量很大。Ceres把这些都封装好了你只需要定义代价函数、残差块和损失核函数剩下的交给求解器。它支持自动求导、数值求导和解析求导内置了LM和Dogleg等求解策略还能用OpenMP和TBB做多线程加速。这也是为什么ORB-SLAM系列、VINS系类都选择它作为后端优化的核心库。1.2 版本选型1.14还是2.x这是安装前必须定下来的事。Ceres目前主流有两个大版本分支1.14.0和2.x系列。1.14.0是2019年前后的稳定版很多SLAM项目比如ORB-SLAM2、ORB-SLAM3早期commit都是基于这个版本测试的API比较老网上资料也最多。2.x系列从2022年开始逐步成为主线API上有一些破坏性变更比如一些头文件路径调整、函数命名规范化。新项目建议直接用2.1.0或2.2.0老项目建议跟着原仓库锁定的版本走。我自己遇到过ORB-SLAM3在编译时用Ceres 2.x报一堆类型不匹配的错误切回1.14.0就顺利通过了。所以安装前先去项目CMakeLists.txt里看一眼[find_package(Ceres)]那句后面写的版本号按需安装别盲目追求新版。2. 环境确认与基础依赖安装Ceres本身不是一个零依赖的库它需要Eigen做矩阵运算、glog做日志、gflags做参数解析可选的还有SuiteSparse、TBB等加速库。这里的顺序很关键依赖没装好就编译Ceres后面会冒出各种奇奇怪怪的undefined reference错误。2.1 先确认系统与工具链我用的环境是Ubuntu20.04内核版本5.15左右gcc/g版本9.4.0CMake版本3.16.3。这几个基础工具版本直接决定了后面能否顺利编译。如果你的系统比较干净建议先执行一遍系统更新把软件源索引刷新一下。sudo apt update sudo apt upgrade -y然后确认编译工具链是否齐全gcc --version g --version cmake --version make --version如果没有安装执行这条命令统一装好sudo apt install -y build-essential cmake git其中build-essential会装好gcc、g、make这是编译C/C项目的基本盘。cmake版本3.16以上足够编译Ceres但如果系统自带的cmake过旧建议用pip装一个新版pip3 install cmake --upgrade注意pip装的cmake可能在/usr/local/bin确保它优先于/usr/bin下的旧版本可以用which cmake确认一下。2.2 安装Eigen、glog、gflags、SuiteSparse这部分是Ceres安装的关键依赖任何一个缺失或版本不兼容都会导致编译失败。我建议直接分两组安装第一组是必须依赖第二组是推荐依赖。必须依赖包括sudo apt install -y libeigen3-dev sudo apt install -y libgoogle-glog-dev sudo apt install -y libgflags-dev推荐依赖用于支持稀疏矩阵加速求解sudo apt install -y libsuitesparse-dev sudo apt install -y libatlas-base-devEigen是一个头文件库不需要编译安装libeigen3-dev会默认装到/usr/include/eigen3。但注意Ceres搜索Eigen时默认找的是/usr/include/eigen3路径如果你是从源码安装Eigen到/usr/local/include/eigen3后续CMake配置时要手动指定-DEIGEN_INCLUDE_DIR这个坑我在后文详细说。glog是Google的日志库Ceres用它输出优化过程中的调试信息。gflags是命令行参数解析库Ceres的可选工具会用到它建议一起装。SuiteSparse是一套稀疏矩阵求解工具集合包含UMFPACK、CHOLMOD、SPQR等求解器。Ceres在做大规模BA优化时使用SuiteSparse能大幅提升求解速度建议务必安装。libatlas-base-dev是BLAS和LAPACK的实现同样用于加速线性代数运算。2.3 额外提一下TBB和OpenMPCeres支持通过TBBThreading Building Blocks做多线程加速。在Ubuntu20.04上可以用一条命令安装sudo apt install -y libtbb-dev但这个依赖比较看心情如果你发现TBB版本和Ceres不兼容可以在CMake配置时通过-DTBBOFF关掉。默认情况下Ceres也会尝试用OpenMPgcc自带支持这一般不会出问题。我个人的建议是第一次安装时先把TBB装上如果编译Ceres时出现tbb相关的错误再回退不迟。多线程加速在BA优化场景下确实能感受到明显性能提升。3. 核心依赖编译注意点与版本冲突直接用apt装依赖看起来很简单但实际部署中我遇到最多的就是Eigen版本和glog版本导致的编译问题。这一节把常见版本坑单独拿出来说因为这些问题在SLAM项目联调阶段几乎必现。3.1 Eigen的版本选择与路径坑Ubuntu20.04的软件源里libeigen3-dev默认是3.3.7这个版本对Ceres 1.14和2.x都兼容所以如果你只是希望能编译通过用apt装的就够了。但有个细节如果你同时电脑上有其他版本Eigen比如ROS自带了一套Eigen、或者Anaconda环境里也带了一套Eigen编译时CMake可能会找到不同的版本导致编译出来的程序在运行时崩溃。这种问题非常隐蔽报错形式通常是报错信息eigen_assert失败或者断言错误。我的排查经验是编译前先看Ceres的CMake输出确认它找到的是哪个路径下的Eigengrep -i eigen CMakeCache.txt正常的输出应该指向/usr/include/eigen3。如果指向了别的位置建议把非标准路径的Eigen暂时移走或者在CMake配置时显式指定cmake -DEIGEN_INCLUDE_DIR/usr/include/eigen3 ..另外有些项目会要求Eigen 3.4以上版本这时候apt装的3.3.7就不够了。要从源码装Eigen的话记得安装完后做符号链接sudo ln -s /usr/local/include/eigen3/Eigen /usr/local/include/Eigen sudo ln -s /usr/local/include/eigen3/unsupported /usr/local/include/unsupported否则很多依赖Eigen的库会找不到头文件。3.2 glog版本升级引起的链接地狱如果你从源码编译安装新版glog比如手动编译了glog 0.6.0那么Ceres在链接glog时可能会出现undefined reference to google::这类错误。原因是新版glog把命名空间从google改成了glog。Ubuntu20.04仓库自带的libgoogle-glog-dev版本是0.4.0默认命名空间是google和Ceres 1.14兼容得很好。如果你自作主张升级了glog再回头编译老版本Ceres就会在链接阶段炸掉。解决办法有三条按推荐顺序排列用apt自带的glog不要手动升级如果非要升级glog就用Ceres 2.x版本它已经适配了新的命名空间手动修改老版本Ceres的源码把glog相关的命名空间全部替换成glog::工作量很大不推荐。这条经验来自VINS-Fusion部署我在一段时间内被这个问题折磨了很久换回apt自带版本后马上就好了。3.3 SuiteSparse加速与BLAS的关系SuiteSparse和BLAS/LAPACK是一套组合拳。Ceres在CMake配置阶段会检测LAPACK和BLAS库是否存在如果检测不到就自动关闭SuiteSparse相关支持。这时即使装了libsuitesparse-dev也无法启用CHOLMOD等加速求解器。检查是否启用成功看CMake输出里这几行-- Found LAPACK library: /usr/lib/x86_64-linux-gnu/liblapack.so -- Found BLAS library: /usr/lib/x86_64-linux-gnu/libblas.so -- SuiteSparse found (with LAPACK enabled)如果显示-- Suitesparse not found大概率是LAPACK没有被正确识别。在Ubuntu20.04上需要额外安装liblapack-devsudo apt install -y liblapack-dev libblas-dev安装后清理Ceres的build目录重新编译就能识别到了。这一步之所以重要是因为SLAM后端优化中Ceres默认用的密集求解器在几千个路标点的规模下性能下降明显而使用稀疏求解器CHOLMOD能快上好几倍。4. Ceres源码编译安装全流程依赖准备好之后编译Ceres本身反而是最不容易出错的部分。官方GitHub仓库地址是github.com/ceres-solver/ceres-solver我们可以用git clone的方式来获取源码也可以直接下载release的tar包。4.1 下载源码并切换到指定版本我一般推荐直接clone最新仓库然后根据项目需要切换到对应taggit clone https://github.com/ceres-solver/ceres-solver.git cd ceres-solver git tag -l比如你要装1.14.0版本就执行git checkout 1.14.0要装2.1.0版本就执行git checkout 2.1.0这里想提醒一下如果是第一次下载clone到的默认分支通常是最新的2.2.0。如果你不确定项目要求什么版本先问自己一个问题这个项目是近几年更新的吗如果项目更新频繁直接使用master分支一般没问题如果是经典老项目优先选择1.14.0。4.2 编译选项与完整构建命令确认版本后开始正式编译。我的习惯是在源码根目录下新建一个build目录所有构建产物都放在里面这样要清理时直接删掉build目录就行不会污染源码。cd ceres-solver mkdir build cd build cmake .. make -j$(nproc) sudo make install这里的-j$(nproc)表示用CPU所有核心并行编译大幅缩短编译时间。在8核16线程的机器上全量编译Ceres大概需要一到两分钟速度很快。如果希望优化编译过程可以在cmake阶段指定Release模式cmake -DCMAKE_BUILD_TYPERelease ..Release模式会开启-O3优化Ceres在算法求解时数值性能更好。Debug模式主要用于调试一般不需要。还有一个参数是-DMINIGLOGON这个选项告诉Ceres使用自带的迷你glog替代系统的glog。如果不想装glog、或者glog版本冲突严重可以用这个选项避开问题。但我个人不推荐因为迷你glog功能不全调试信息输出也不完整。编译完成后Ceres的库文件会被安装到/usr/local/lib下头文件在/usr/local/include/ceres。确认是否安装成功ls /usr/local/lib/libceres* ls /usr/local/include/ceres正常会看到libceres.a或者libceres.so以及一堆头文件。到这里Ceres库本身就算安装完成了。4.3 通过官方示例验证安装这一步很多人会跳过但我建议无论如何都跑一下官方自带的示例程序它能在正式进入项目之前快速暴露环境问题。Ceres源码的examples目录下有一个helloworld示例它求解一个最简的非线性最小二乘问题。在build目录下执行make -j$(nproc) helloworld ./bin/helloworld正常输出是一串初始值到最优值的迭代过程最后x和y分别收敛到0.5和0.1左右。如果这个示例能跑通说明Ceres的核心功能函数、自动求导、线性求解器都工作正常。我还建议编译一下bundle_adjuster这个示例它是Ceres对SLAM问题最直接的应用示例能验证SuiteSparse是否真正链接成功make -j$(nproc) bundle_adjuster ./bin/bundle_adjuster ../data/problem-16-22106-pre.txt这里会看到一个包含16个相机和22106个观测点的BA问题被顺利优化同时在输出中能看到Ceres Solver Report一栏里面记录着迭代次数、终止条件、耗时等信息。如果你的编译配置里SuiteSparse没有生效这个程序依然能跑但每次迭代的时间会明显变长这是一个可感知的性能差异。5. 在CMake项目中正确引用Ceres装好Ceres后下一步就是在自己的项目里使用它。这一节讲CMake的配置方法这部分虽然不难但每次都有朋友踩坑重点讲两个细节。5.1 引用Ceres的标准CMake写法Ceres官方提供了FindCeres.cmake安装后会被放到/usr/local/lib/cmake/Ceres目录下。在项目CMakeLists.txt里这样写find_package(Ceres REQUIRED) target_link_libraries(your_target ${CERES_LIBRARIES}) target_include_directories(your_target PRIVATE ${CERES_INCLUDE_DIRS})这里的CERES_LIBRARIES会自动解析Ceres及其所有依赖库的链接路径CERES_INCLUDE_DIRS则指向Ceres和Eigen的头文件路径。如果你是老项目可能会遇到find_package(Ceres)找不到的情况。大概率是因为Ceres安装目录不在CMake默认搜索范围内可以手动指定路径cmake -DCeres_DIR/usr/local/lib/cmake/Ceres ..5.2 和Eigen一起引用的常见坑Ceres的头文件会间接引用Eigen所以如果你在target里同时使用Eigen和Ceres必须先包含Eigen的头文件路径再包含Ceres的头文件路径。这个顺序在CMake里一般不体现因为include_directories是累加关系不关心顺序但在源码中include的顺序会影响编译。更常见的坑是Eigen版本不一致导致的模板编译错误。比如你的项目里自己引用了/usr/include/eigen3的Eigen 3.3.7而Ceres在安装时用了源码编译的Eigen 3.4两套Eigen头文件混用编译时就会出现internal::eigen_assert之类非常晦涩的报错。解决办法是统一Eigen来源。要么全部用apt安装的Eigen要么全部用源码安装的Eigen。在CMakeCache里检查EIGEN_INCLUDE_DIR变量的值确认家里只有一个Eigen版本。6. 实战中的高频问题与排查记录这部分是踩坑合集。我在多台电脑、多个Ubuntu20.04环境、多个SLAM项目里折腾Ceres的安装和集成每次遇到的问题都不太一样总结出下面这张速查表希望能帮读者快速定位问题。问题现象可能原因解决办法编译时找不到ceres/ceres.hCeres未安装或路径不在搜索范围检查/usr/local/include/ceres是否存在CMake中指定Ceres_DIR编译时出现undefined reference to google::...glog版本过新命名空间变更卸载手动编译的glog改用apt的libgoogle-glog-dev编译时出现Eigen相关模板错误多个Eigen版本冲突统一Eigen来源建议用apt的libeigen3-dev编译时提示找不到SuiteSparse缺少LAPACK/BLAS依赖安装liblapack-dev、libblas-dev删除build目录重新配置CMake找不到CeresConfig.cmakeCeres安装路径非标准手动指定Ceres_DIR或设置CMAKE_PREFIX_PATH编译成功后运行时崩溃Eigen对齐问题或版本混用检查所有依赖库是否使用同一Eigen安装路径编译速度极慢未开启OpenMP/TBB加速安装libtbb-dev或者在CMake中开启-DOPENMPON6.1 CMake找不到Ceres这个问题是初学者最常遇到的。明明Ceres装了但项目里find_package(Ceres REQUIRED)就是报错。多数情况下是Ceres编译后安装路径不在CMake的默认查找路径里。推荐用CMAKE_PREFIX_PATH来指定cmake -DCMAKE_PREFIX_PATH/usr/local/lib/cmake/Ceres ..或者在项目CMakeLists.txt的find_package之前手动设置set(Ceres_DIR /usr/local/lib/cmake/Ceres) find_package(Ceres REQUIRED)另外检查一下如果是从源码安装时用了-DCMAKE_INSTALL_PREFIX指定了其他前缀那CMake配置时也必须带上同样的参数。6.2 与ROS环境共存时的问题很多SLAM项目会在ROS环境下编译这时候Ceres安装位置可能不止一个。比如ROS的包管理器可能自动装了一份Ceres到/opt/ros/noetic/lib而你自己又源码装了一份在/usr/local/lib。两个版本同时存在时CMake会优先找到哪个完全取决于CMAKE_PREFIX_PATH和环境变量CMAKE_INCLUDE_PATH的搜索顺序。我在ORB-SLAM3编译时遇到过这个问题最后通过在CMakeLists里显式指定Ceres路径来解决set(Ceres_DIR /usr/local/lib/cmake/Ceres)如果你希望ROS环境自带的Ceres生效就把它对应路径放在最前面。6.3 多版本Ceres编译冲突的处理如果电脑上已经有旧版本Ceres现在要装新版直接编译安装新版本一般不会覆盖旧版本的头文件但动态库会。旧的libceres.so会被新的替换这导致一个编译好的老程序依赖新版本Ceres运行反而可能崩溃。处理方法有两种一是直接把旧版本完全卸载包括头文件和库文件二是用-DCMAKE_INSTALL_PREFIX把不同版本安装到不同前缀下然后在不同项目中指定不同路径。第二种方法更干净但需要额外注意rpath的设置。一般而言对于技术学习或日常工具开发我推荐直接卸载旧版本、安装新版本即可版本隔离只在需要同时维护多个老项目时才值得考虑。7. 在SLAM项目部署中的实际经验这篇博文之所以专门写Ubuntu20.04下的Ceres安装很大程度上是因为它和SLAM项目部署高度相关。如果你点进来是为了装ORB-SLAM3、VINS-Fusion或者LIO-SAM那这一节的经验也许比前面的教程更有用。7.1 ORB-SLAM3对Ceres版本的选择ORB-SLAM3在自己的CMakeLists里写的find_package(Ceres REQUIRED)并没有指定版本但实际测试下来它和Ceres 1.14.0的兼容性明显优于2.x。原因是ORB-SLAM3内部使用了部分Ceres旧API在Ceres 2.0之后有了改动导致编译报错。如果你非要使用Ceres 2.x来编译ORB-SLAM3一种可行的改法是修改ORB-SLAM3源码中涉及Ceres的部分把旧API替换成新API。但这样做非常痛苦需要逐个检查残差块的构建方式。相比之下直接安装Ceres 1.14.0时间成本低得多。7.2 VINS-Fusion的依赖顺序VINS-Fusion是一个视觉惯性导航系统它依赖Ceres做后端优化。我在Ubuntu20.04上部署时遇到过一个问题同时安装Ceres和Eigen之后VINS-Fusion编译时提示Ceres版本太旧。查了一下VINS-Fusion对Ceres 1.14支持良好但如果系统里存在多个版本CeresCMake可能找到的是旧版本。解决方法和前面一样使用Ceres_DIR显式指定Ceres安装路径。同时确认Eigen版本不低于3.3。VINS-Fusion官方文档里没有特别指明这两点但实际操作中这两步必不可少。7.3 视觉惯性导航系统里Ceres加速的实际体感我做过一个小的对比实验在同一个VINS-Fusion数据集上分别使用Ceres默认配置不启用SuiteSparse和启用SuiteSparse的配置后端优化单帧处理的耗时差距在20%到40%之间。数据集规模越大、约束越多差距越明显。因此如果你的项目包含视觉SLAM或大规模BA优化强烈建议在安装Ceres时确保SuiteSparse被正确识别。判断方法很简单编译Ceres时看CMake输出是否包含以下内容-- Found SuiteSparse: ... (with LAPACK enabled)如果只有SuiteSparse found而没有with LAPACK字样说明LAPACK可能没有链接上需要补装liblapack-dev然后重新编译Ceres。这一步值得花时间。8. 卸载与重装Ceres的正确方式最后聊一下卸载和重装。Ceres安装教程很多但卸载教程很少。将来如果升级Ceres或者装坏了要重来知道怎么彻底卸载能避免很多烦恼。8.1 从系统中移除Ceres如果你是通过make install安装在默认路径下的可以用以下方式卸载cd ceres-solver/build sudo make uninstall注意make uninstall只在CMake生成了uninstall目标时才有效。CMake默认不生成这个目标需要提前用cmake -DUNINSTALL_TARGETON配置。如果你当初没有开启就只能手动删除文件sudo rm -rf /usr/local/lib/libceres* sudo rm -rf /usr/local/include/ceres sudo rm -f /usr/local/lib/cmake/Ceres/CeresConfig.cmake sudo rm -f /usr/local/lib/cmake/Ceres/CeresTargets.cmake sudo rm -f /usr/local/lib/pkgconfig/ceres.pc如果当初指定了CMAKE_INSTALL_PREFIX则把上面路径换成对应前缀下的路径。8.2 重新安装时的注意事项重新安装前记得清理旧的build目录否则CMake可能会有缓存残留cd ceres-solver rm -rf build如果之前使用过-D参数指定依赖库路径重新配置时务必带上同样的参数或者直接清空build目录让它重新检测。我自己在Ubuntu20.04上多次重装Ceres之后养成了一个小习惯把所有自定义安装记录在一个笔记里包括使用了哪些cmake参数、依赖装到了哪个路径下。这样下次换机器或者重装系统照着笔记执行一遍就能还原环境不会丢三落四。在多个版本的切换实践中我后来比较喜欢用Docker来隔离开发环境在容器里编译SLAM项目就不需要反复折腾宿主机上的库版本了。当然这是后话如果只是单机开发上面这套手动安装流程已经足够可靠。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑