《视觉SLAM十四讲》slambook2配置和编译记录

最近有时间重拾《SLAM14讲》这本经典SLAM入门书。作者高老师提供了书中的整套习题和示例代码[https://github.com/gaoxiang12/slambook2]。
因为时间久远(当前2025年6月),书本推荐的系统是ubuntu14,我的系统是ubuntu22.04,可能不支持老版本的第三方库了,所以我基本采用新版的第三方库,配置和编译的时候遇到了一些问题。
现在从一个全新的系统开始配置:

1. 安装依赖库


主要是slambook2/3rdparty/ 提供的第三方库,还有这些库的依赖库。
全部从源码编译安装:

# 安装示例
git clone https://github.com/RainerKuemmerle/g2o.git
cd g2o && mkdir build && cd build
cmake .. 
make -j$(nproc)
sudo make install

Tips:

  1. 编译安装以前最好先切换到某个稳定版本,因为有的库安装时需要明确其依赖库的版本(例如Ceres 的配置文件 CeresConfig.cmake 在生成过程中需要知道你使用的 Abseil 库的版本号,后面会提到)。
    具体方法如下:
git tag   // 查看tag
git checkout tags/20240116 -b version-20240116  //-b <新建分支名字>
  1. Sophus库使用新版本会在编译到25%时死机,所以用的slambook2推荐sophus-13fb328。
  2. opencv安装,采用官方文档,直接安装最新版的opencv和opencv-contrib。
  3. 使用apt安装pcl/libepoxy 库。

2. 代码适配

1. g2o::make_unique 全部替换成std::make_unique
2. 由于 OpenCV 4.x 版本中,常量名发生了变化,创建替换脚本update_opencv_constants.sh将部分旧的常量名替换为新的常量名:

#!/bin/bash

# 定义要搜索和替换的目录
SEARCH_DIR="/home/koap/workspace/slambook2"

# 替换旧的常量名
find $SEARCH_DIR -type f -name "*.cpp" | xargs sed -i 's/CV_LOAD_IMAGE_COLOR/IMREAD_COLOR/g'
find $SEARCH_DIR -type f -name "*.cpp" | xargs sed -i 's/CV_LOAD_IMAGE_GRAYSCALE/IMREAD_GRAYSCALE/g'
find $SEARCH_DIR -type f -name "*.cpp" | xargs sed -i 's/CV_LOAD_IMAGE_UNCHANGED/IMREAD_UNCHANGED/g'

echo "Constants have been updated to OpenCV 4.x style."

# 替换所有 .cpp 文件中的旧常量
find $SEARCH_DIR -type f -name "*.cpp" | xargs sed -i 's/CV_FM_8POINT/cv::FM_8POINT/g'
find $SEARCH_DIR -type f -name "*.cpp" | xargs sed -i 's/CV_FM_RANSAC/cv::FM_RANSAC/g'
find $SEARCH_DIR -type f -name "*.cpp" | xargs sed -i 's/CV_FM_LMEDS/cv::FM_LMEDS/g'
find $SEARCH_DIR -type f -name "*.cpp" | xargs sed -i 's/CV_BGR2GRAY/cv::COLOR_GRAY2BGR/g'
find $SEARCH_DIR -type f -name "*.cpp" | xargs sed -i 's/CV_GRAY2BGR/cv::COLOR_BGR2GRAY/g'
find $SEARCH_DIR -type f -name "*.cpp" | xargs sed -i 's/CV_BGR2RGB/cv::COLOR_BGR2RGB/g'
find $SEARCH_DIR -type f -name "*.cpp" | xargs sed -i 's/CV_FILLED/cv::FILLED/g'

echo "✅ OpenCV FM constants updated to OpenCV 4.x style."

3. 编译/安装/运行中的报错

1.

CMake Error at cmake_install.cmake:46 (message):
Cannot generate CeresConfig.cmake due to missing Abseil version. Using
resulting package configuration will likely result in integration errors.
Set absl_VERSION manually to disable this error message.

  • 原因分析:ceres-solver安装时报错,Ceres 的配置文件 CeresConfig.cmake 在生成过程中需要知道使用的 Abseil 库的版本号。
  • 解决办法:在确认好absl的版本后,在ceres的cmake时添加:
cmake .. -Dabsl_VERSION=20230802

2.

error: invalid use of incomplete type ‘PyFrameObject’

  • 原因分析:这个错误发生在使用 pybind11 的代码中,尤其是在与 Python 3.13(Miniconda)结合时。这是一个典型的 Python 3.12+ 中引入的“受限头文件”机制 导致的问题。
  • 解决方法:将环境中的python降级到3.11解决。

3.

error: ‘enable_if_t’ is not a member of ‘std’

高频次问题!

  • 原因分析:这个错误表明代码中使用了 std::enable_if_t,但编译器(C++11)无法识别它。std::enable_if_t 是 C++14 引入的模板别名(alias template),用于 SFINAE(替换失败并非错误)机制。
  • 解决方法:在CMakeLists.txt中指定使用高版本的C++编译器:(推荐17+)
set(CMAKE_CXX_FLAGS "-std=c++17")

4.

/usr/bin/ld: /usr/local/lib/libabsl_log_internal_log_sink_set.a(log_sink_set.cc.o):
relocation R_X86_64_TPOFF32 against '_ZZN4absl12lts_2024011612log_internal...`'
can not be used when making a shared object; recompile with -fPIC

  • 原因分析:编译opencv时,依赖于 Abseil 库。系统中安装的 Abseil 是以静态库形式存在,但这些静态库没有使用 -fPIC 编译,因此不能被用来构建共享库(.so 文件),比如 OpenCV 的模块 opencv_sfm.so。
  • 解决方法:重新构建 Abseil 动态库,并启用 -fPIC. 在cmake时添加:
cmake .. -DBUILD_SHARED_LIBS=ON \
         -DCMAKE_POSITION_INDEPENDENT_CODE=ON \
         -DCMAKE_BUILD_TYPE=Release

5.

error while loading shared libraries: libpango_windowing.so.0: cannot open shared object file: No such file or directory

  • 原因分析:已经安装了pangolin,在/usr/local/lib/下能找到libpango_windowing.so.0,在但是报libpango_windowing.so.0找不到。
  • 解决方法:更新动态链接器缓存。
sudo ldconfig

6.

CMake 3.24 or higher is required. You are running version 3.22.1

  • 原因分析:某些库需要高版本的CMake,但是apt里面版本比较旧。
  • 解决方法:使用snap安装cmake,将路径添加到PATH第一位使其成为默认的cmake。
sudo snap install cmake --classic
export PATH=/snap/bin:$PATH

7.

/home/koap/miniconda3/include/spdlog/fmt/fmt.h:27:14: fatal error: spdlog/fmt/bundled/core.h: No such file or directory
27 | # include <spdlog/fmt/bundled/core.h>
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.

  • 原因分析:我最初没有重新装spdlog,而是将miniconda中已有的libspdlog.so软链接了在/usr/lib中,该spdlog不是完整的,没有自带的fmt。
  • 解决方法
    1) 从源码编译安装spdlog。
    或者
    2) 使用外部的fmt,在CMakeLists.txt中添加声明:
add_definitions(-DSPDLOG_FMT_EXTERNAL)

8.

/home/koap/miniconda3/lib/libstdc++.so.6: version `GLIBCXX_3.4.30' not found (required by /usr/local/lib/libopencv_core.so.411)

  • 原因分析:程序在运行时尝试加载 /usr/local/lib/libopencv_core.so.411,这个库 需要更新版本的 libstdc++(GCC 的 C++ 标准库),但当前环境中优先使用了 Miniconda 自带的老版本 libstdc++(缺少 GLIBCXX_3.4.30)。
  • 解决方法:强制使用系统自带的 libstdc++:
# 可以加到~/.bashrc
export LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH

9.

terminate called after throwing an instance of 'cv::Exception'
what(): OpenCV(4.11.0) ... error: (-15:Bad number of channels)
Invalid number of channels in input image:
'VScn::contains(scn)' where 'scn' is 1

  • 原因分析:调用cv::imread(, 0)去读取图像(是单通道图), 又调用cv::cvtColor时报错,因为但该函数期望的是一个 三通道或四通道图像(彩色图)。
  • 解决方法:报错处的cv::imread(, 0)改成cv::imread()。

10.

CMake Error at CMakeLists.txt:11 (find_package):
Found package configuration file:

/usr/local/lib/cmake/Ceres/CeresConfig.cmake

but it set Ceres_FOUND to FALSE so package "Ceres" is considered to be NOT FOUND.

Reason given by package:
Found Eigen dependency, but the version of Eigen found () does not exactly match the version of Eigen Ceres was compiled with (3.4.0).

  • 原因分析:安装的 Ceres Solver 是使用 Eigen 3.4.0 编译的,与当前系统中找到的 Eigen 版本不一致。但其实系统的eigen版本就是3.4.0 。应该是ceres识别不到apt安装的eigen的版本号?(所以从源码安装最好自己指定版本,减少这类的报错)
  • 解决方法:从源码重新安装eigen和ceres,指定版本号。
wget https://gitlab.com/libeigen/eigen/-/archive/3.4.0/eigen-3.4.0.tar.gz
tar -xzf eigen-3.4.0.tar.gz
cd eigen-3.4.0
mkdir build && cd build
cmake ..
sudo make install
git clone https://github.com/ceres-solver/ceres-solver.git
cd ceres-solver
git checkout <tag-or-commit-id>  # 推荐使用稳定版本如 2.1.0
mkdir build && cd build
cmake .. \
  -DEIGEN_INCLUDE_DIR=/usr/local/include/eigen3 \  # 直接指定EIGEN路径
  -DBUILD_EXAMPLES=OFF \
  -DBUILD_TESTING=OFF
make -j$(nproc)
sudo make install

11.

undefined reference to 'g2o::csparse::CSparse::CSparse()'
undefined reference to 'g2o::csparse::CSparse::freeSymbolic()'

  • 原因分析:缺少 g2o_solver_csparse 这个库。g2o::csparse::CSparse ,g2o::csparse::CSparse::freeSymbolic()和 g2o::LinearSolverCSparse 的实现就在 libg2o_solver_csparse.so 或 .a 里。
  • 解决方法:在ch9的CMakeLists.txt添加g2o_solver_csparse:
# ...existing code...
SET(G2O_LIBS g2o_csparse_extension g2o_stuff g2o_core g2o_solver_csparse cxsparse g2o_solver_cholmod)
# ...existing code...

12. ch10, 运行./pose_graph_g2o_lie sphere.g2o 时

Sophus ensure failed in function 'void Sophus::SO3Base::normalize() [with Derived = Sophus::SO3]', file '/usr/local/include/sophus/so3.hpp', line 273.
Quaternion ( 0.706662 4.32706e-17 0.707551 -4.3325e-17) should not be close to zero!
Aborted (core dumped)

  • 原因分析:这个错误是 Sophus 库中的一个运行时断言(assert)触发,说明程序中某个 SO3 或 SE3 的四元数构造或旋转操作导致了一个接近零向量的非法单位四元数。
    read函数漏写了return true;,导致C++返回未定义值,导致后续出错:四元数归一化失败导致的崩溃。
  • 解决方法:确保 read 函数有 return true; 确认四元数顺序与 g2o 文件一致。

13. ch11, 安装DBow3

  • 原因分析:由于版本太老,编译报错。
  • 解决方法
    CMakeLists.txt:
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

检查并补全 BowVector.h 的头部:

#pragma once

#include <map>
#include <iterator>
#include <ostream>
#include <string>
#include <cstdint>
#include <cstddef>

14. ch12, PCL相关

/home/koap/workspace/slambook2/ch12/dense_RGBD/surfel_mapping.cpp: In function ‘SurfelCloudPtr reconstructSurface(const PointCloudPtr&, float, int)’:
/home/koap/workspace/slambook2/ch12/dense_RGBD/surfel_mapping.cpp:31:9: error: ‘class pcl::MovingLeastSquares<pcl::PointXYZRGB, pcl::PointXYZRGBNormal>’ has no member named ‘setPolynomialFit’; did you mean ‘setPolynomialOrder’?
31 | mls.setPolynomialFit(polynomial_order > 1);
| ^~~~~~~~~~~~~~~~
| setPolynomialOrder

  • 原因分析:PCL 1.12 及以后版本中,setPolynomialFit 方法已被移除或重命名。现在只需设置 setPolynomialOrder。

  • 解决方法:直接删除或注释掉 mls.setPolynomialFit(...) 这一行,只保留 mls.setPolynomialOrder(polynomial_order); 即可。

15. ch12, 运行./dense_mapping test_data/ 时报错

read total 202 files.
*** loop 1 ***
Segmentation fault (core dumped)

  • 原因分析:update函数为定义为bool类型,但是没有返回值。
  • 解决方法:可以改为void,或者添加返回值 return true;

运行以后,生成了一个全黑的图,解决方法:https://github.com/gaoxiang12/slambook2/issues/323

16. ch12, 运行./pointcloud_mapping 时报错

(base) koap@koap:~/workspace/slambook2/ch12/dense_RGBD$ ./pointcloud_mapping
正在将图像转换为点云...
转换图像中: 1
Segmentation fault (core dumped)

  • 原因分析
    在CMakeLists.txt中,我把set(CMAKE_CXX_FLAGS "-std=c++17 -02")写成了set(CMAKE_CXX_FLAGS "-std=c++17 -march=native -O3")。
    -march=native 导致了某些库(如 OpenCV、PCL、Eigen)或你自己代码中对内存访问/向量化操作的行为变化,从而导致崩溃。
  • 解决方法:去掉 -march=native 后,程序能正常运行,因为编译器会生成更通用的代码,兼容性更好。 谨慎使用!
posted @ 2025-06-27 14:03  唐康  阅读(225)  评论(0)    收藏  举报