在Ubuntu 20.04上搞定ORB-SLAM3编译:一个C++14标准设置救了我的命

如果你正在Ubuntu 20.04上尝试编译ORB-SLAM3,却在 make 阶段被一连串 错误 1 卡住,这篇文章就是为你准备的。作为一个在计算机视觉领域深耕多年的开发者,我深知这种看似简单的编译错误可能让人抓狂——尤其是当网上大多数教程都只告诉你"按照步骤来"却没人解释为什么会出现这些错误时。

ORB-SLAM3作为目前最先进的视觉SLAM系统之一,其代码质量相当高,但它的编译过程却可能成为新手的第一道门槛。特别是在Ubuntu 20.04这个长期支持版本上,由于系统默认的编译器版本和C++标准设置,你很可能会遇到各种奇怪的编译错误。本文将深入剖析这些错误的根源,并提供经过实战验证的解决方案。

1. 理解编译错误的本质

当你看到终端中不断滚动的错误信息时,第一反应可能是"我哪里做错了?"。但实际上,这些错误大多源于一个简单但容易被忽视的问题:C++标准版本不匹配。

典型的错误输出看起来像这样:

make[2]: *** [CMakeFiles/ORB_SLAM3.dir/build.make:375:CMakeFiles/ORB_SLAM3.dir/src/MLPnPsolver.cpp.o] 错误 1
make[2]: *** [CMakeFiles/ORB_SLAM3.dir/build.make:76:CMakeFiles/ORB_SLAM3.dir/src/Tracking.cc.o] 错误 1
...
make: *** [Makefile:84:all] 错误 2

这些错误看似分散在不同的源文件中,但它们都有一个共同点:都是由于编译器无法正确处理代码中的C++14特性导致的。ORB-SLAM3大量使用了C++14标准引入的特性,而Ubuntu 20.04默认的g++编译器(g++ 9.3.0)虽然支持C++14,但CMake默认可能不会启用。

1.1 为什么C++标准如此重要?

C++标准决定了编译器如何处理你的代码。不同标准之间可能存在语法和功能上的差异:

C++标准 主要特性 兼容性
C++11 auto类型推导, lambda表达式 广泛支持
C++14 泛型lambda, 二进制字面量 需要显式启用
C++17 结构化绑定, if constexpr 较新编译器

ORB-SLAM3特别依赖C++14的几个关键特性:

  • 泛型lambda表达式(用于灵活的算法封装)
  • 变量模板(用于数学运算的通用实现)
  • 自动返回类型推导(简化模板代码)

2. 两种解决方案的深度对比

解决这个问题的核心在于告诉CMake使用C++14标准编译。有两种主要方法可以实现这一点,各有优缺点。

2.1 方法一:设置CMAKE_CXX_STANDARD

这是最直接的方法,只需在ORB-SLAM3的CMakeLists.txt中添加一行:

set(CMAKE_CXX_STANDARD 14)

优点

  • 明确指定整个项目的C++标准
  • 只影响当前项目,不会干扰系统其他部分
  • CMake会自动处理相关的编译器标志

缺点

  • 如果项目中有子模块需要不同标准,可能需要额外处理
  • 某些旧的CMake版本可能不完全支持这个指令

实际操作步骤:

  1. 使用文本编辑器打开ORB-SLAM3根目录下的CMakeLists.txt
  2. project(ORB_SLAM3) 声明之后添加上述set命令
  3. 保存文件并重新运行cmake和make

2.2 方法二:使用add_compile_options

另一种方法是通过编译选项直接指定标准:

add_compile_options(-std=c++14)

优点

  • 更底层,对所有编译器都有效
  • 可以与其他编译选项组合使用
  • 在某些复杂项目中可能更可靠

缺点

  • 会影响到所有编译单元,可能产生副作用
  • 需要手动确保与其他选项的兼容性

选择建议 : 对于大多数情况,方法一更为推荐。它更符合现代CMake的最佳实践,且能更好地处理项目依赖关系。只有在遇到特殊编译问题时,才考虑使用方法二。

3. 其他常见问题的解决方案

除了C++标准问题,编译ORB-SLAM3时还可能遇到其他几个典型问题。

3.1 OpenCV的pkg-config问题

错误信息通常为:

Package opencv was not found in the pkg-config search path

这是因为OpenCV 4.x默认不生成.pc文件。解决方法:

cd /usr/local/lib
sudo mkdir pkgconfig
cd pkgconfig
sudo touch opencv.pc
sudo nano opencv.pc

然后在opencv.pc文件中添加以下内容:

prefix=/usr/local
exec_prefix=${prefix}
includedir=${prefix}/include
libdir=${exec_prefix}/lib

Name: opencv
Description: The opencv library
Version:4.0.1
Cflags: -I${includedir}/opencv4
Libs: -L${libdir} -lopencv_shape -lopencv_stitching -lopencv_objdetect -lopencv_superres -lopencv_videostab -lopencv_calib3d -lopencv_features2d -lopencv_highgui -lopencv_videoio -lopencv_imgcodecs -lopencv_video -lopencv_photo -lopencv_ml -lopencv_imgproc -lopencv_flann -lopencv_core

3.2 Eigen版本兼容性问题

高版本的Eigen可能会导致编译警告,在资源有限的设备(如Jetson或树莓派)上甚至会导致编译过程卡死。建议:

  • 使用Eigen 3.3.x版本
  • 如果必须使用新版本,可以尝试禁用某些优化:
    add_definitions(-DEIGEN_DONT_VECTORIZE)
    add_definitions(-DEIGEN_DISABLE_UNALIGNED_ARRAY_ASSERT)
    

3.3 内存不足问题

在小型设备上编译时,可能会因内存不足而失败。可以尝试:

  • 增加swap空间
  • 使用 make -j2 而非 make -j$(nproc) 限制并行编译任务数
  • 关闭不必要的程序释放内存

4. 系统版本选择的考量

虽然原始文章建议使用Ubuntu 18.04,但Ubuntu 20.04 LTS仍然是完全可行的选择,只要你注意以下几点:

  1. 编译器版本

    • Ubuntu 20.04默认的g++ 9.3.0完全支持C++14
    • 如果需要C++17特性,可以考虑安装g++-10或更新版本
  2. 依赖管理

    sudo apt install build-essential cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev
    
  3. Python兼容性

    • Ubuntu 20.04默认的Python3版本为3.8
    • 某些脚本可能需要调整以适应新版本

提示:如果你确实遇到无法解决的问题,可以考虑使用Docker容器来创建一个与Ubuntu 18.04兼容的编译环境,而不必更换整个系统。

在实际项目中,我发现在Ubuntu 20.04上正确配置后,ORB-SLAM3的运行效率反而比在18.04上有所提升,特别是当利用新版本编译器的优化特性时。关键是要理解每个错误的根源,而不是盲目跟随教程。

更多推荐