1. CMake编译
第13讲使用cmake 编译,熟悉cmake的朋友可以跳过本章节,本节主要介绍编译规则。
➢ 父工程(最顶层CMakeLists.txt)
cmake_minimum_required(VERSION 2.8)
project(myslam)
set(CMAKE_BUILD_TYPE Release)
set(CMAKE_CXX_FLAGS "-std=c++11 -Wall")
set(CMAKE_CXX_FLAGS_RELEASE "-std=c++11 -O3 -fopenmp -pthread")
list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake_modules)
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
############### dependencies ######################
# Eigen
include_directories("/usr/include/eigen3")
# OpenCV
find_package(OpenCV 3.2 REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
# pangolin
find_package(Pangolin REQUIRED)
include_directories(${Pangolin_INCLUDE_DIRS})
# Sophus
find_package(Sophus REQUIRED)
include_directories(${Sophus_INCLUDE_DIRS})
# G2O
find_package(G2O REQUIRED)
include_directories(${G2O_INCLUDE_DIRS})
# glog
find_package(Glog REQUIRED)
include_directories(${GLOG_INCLUDE_DIRS})
# gtest
find_package(GTest REQUIRED)
include_directories(${GTEST_INCLUDE_DIRS})
# gflags
find_package(GFlags REQUIRED)
include_directories(${GFLAGS_INCLUDE_DIRS})
# csparse
find_package(CSparse REQUIRED)
include_directories(${CSPARSE_INCLUDE_DIR})
set(THIRD_PARTY_LIBS
${OpenCV_LIBS}
${Sophus_LIBRARIES}
${Pangolin_LIBRARIES} GL GLU GLEW glut
g2o_core g2o_stuff g2o_types_sba g2o_solver_csparse g2o_csparse_extension
${GTEST_BOTH_LIBRARIES}
${GLOG_LIBRARIES}
${GFLAGS_LIBRARIES}
pthread
${CSPARSE_LIBRARY}
)
enable_testing()
############### source and test ######################
include_directories(${PROJECT_SOURCE_DIR}/include)
add_subdirectory(src)
add_subdirectory(test)
add_subdirectory(app)
解释如下:
cmake_minimum_required(VERSION 2.8): 设置最低需要的 CMake 版本为 2.8。一些新的cmake语法不支持老的版本。
project(myslam): 定义项目名称为 myslam。
set(CMAKE_BUILD_TYPE Release): 设置默认的构建类型为 Release。
set(CMAKE_CXX_FLAGS "-std=c++11 -Wall"): 设置编译器标志,使用 C++11 标准并启用所有警告。
set(CMAKE_CXX_FLAGS_RELEASE "-std=c++11 -O3 -fopenmp -pthread"): 设置在 Release 模式下的编译器标志,包括优化选项O3(代码极致优化)、OpenMP 和 pthread(多线程支持)。
list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake_modules): 将自定义的 CMake 模块路径添加到 CMAKE_MODULE_PATH。CMAKE_MODULE_PATH是一个cmake 使用find_package()查找的环境变量,添加后额外增加搜索路径。
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin): 设置可执行文件的输出目录为项目根目录下的 bin 目录。
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib): 设置库文件的输出目录为项目根目录下的 lib 目录。
include_directories("/usr/include/eigen3"): 包含 Eigen 库的头文件。Eigen只有头文件没有库文件,默认linux 下gcc的头文件搜索路径为/usr/include 和/usr/local/include ,并不会递归搜索。
find_package(OpenCV 3.2 REQUIRED): 查找 OpenCV 库,要求版本至少为 3.2(大于该版本)。如果找到,将设置相关变量。REQUIRED表示找不到就退出。
include_directories(${OpenCV_INCLUDE_DIRS}): 包含 OpenCV 库的头文件。这是find_package 找到的.cmake模块中定义的变量,指定了头文件的搜索路径。通常使用apt或者源码安装时,其安装目录都在OpenCVConfig.cmake或者FindOpenCV.cmake模块中定义。
set()将所有第三方库添加到 THIRD_PARTY_LIBS 变量中,这些库将在后续的编译和链接过程中使用。
add_subdirectory(src): 添加 src 子目录,CMake 将在该目录中查找 CMakeLists.txt 文件。然后被导入作为子工程被编译,子工程通常可以使用父工程的变量。
➢ src工程
add_library(myslam SHARED
frame.cpp
mappoint.cpp
map.cpp
camera.cpp
config.cpp
feature.cpp
frontend.cpp
backend.cpp
viewer.cpp
visual_odometry.cpp
dataset.cpp)
target_link_libraries(myslam
${THIRD_PARTY_LIBS})
add_library 生成一个库,myslam是库的名字,SHARED表是生成动态库(.so),其他是依赖项。库和可执行程序都是目标target,需要依赖第三方库
target_link_libraries 讲生成的库链接。
cmake本身也是使用编译器生成c++程序。生成c++程序,步骤为预处理、编译、汇编、链接。cmake 是简化了一大堆g++ 指令。编译如果报错出现头文件未包含,未定义的行为,怀疑库的版本不正确,链接错误说明平台错误或者找不到对应的库。
2. 踩坑
本人使用ubuntu18.04 编译,结果如下:
正确生成了该工程,需要注意更改以下配置:
对于该工程依赖库,大部分都可以使用apt工具或者snap下载,如果编译报错,说明版本不对,卸载后下载源码编译。
sudo apt update
# Eigen
sudo apt install libeigen3-dev
# OpenCV
sudo apt install libopencv-dev
# Pangolin
sudo apt install libpangolin-dev
# Sophus
sudo apt install libsophus-dev
# G2O
sudo apt install libg2o-dev
# Glog
sudo apt install libgoogle-glog-dev
# GTest
sudo apt install libgtest-dev
# GFlags
sudo apt install libgflags-dev
# CSparse
sudo apt install libsuitesparse-dev
根据系统镜像源会下载对应的版本,但是往往不是最新的版本,也可能不兼容。因此需要下载源码安装:
Pangolin为例:
git clone https://github.com/stevenlovegrove/Pangolin.git Pangolin
cd Pangolin
mkdir build && cd build
cmake ..
make -j8
sudo make install
本人实际测试,需要做以下修改:
gtest可以删除,同时注释enable_testing(),不开启make test。
额外安装gtest,需要拷贝库到系统目录
sudo apt-get install libgtest-dev
cd /usr/src/gtest
sudo cmake CMakeLists.txt
sudo make
sudo cp *.a /usr/lib
pangolin 版本0.5 g2o版本g2o-20201223 ceres 1.14,其他库可以直接使用apt工具下载安装。
采用外部构建cmake工程
mkdir build
cd build
cmake ..
make -j8
cmake .. 通过,说明cmake查找到了相关库,语法正确。并且根据当前的平台和编译器生成了Makefile文件。
make -j8采用8个线程同时编译构建,出现链接时错误,这是因为缺少对fmt链接,且设置为动态链接时,系统提供的fmt库编译时没有加-fPIC选项,这是一种解决运行时采用相对位置的方式。解决办法有两种,重新编译fmt库覆盖掉系统的库,或者将链接改成静态链接。
例如将src工程cmakelists.txt 改成:
add_library(myslam STATIC
frame.cpp
mappoint.cpp
map.cpp
camera.cpp
config.cpp
feature.cpp
frontend.cpp
backend.cpp
viewer.cpp
visual_odometry.cpp
dataset.cpp)
target_link_libraries(myslam
${THIRD_PARTY_LIBS} fmt)
将SHARED 改成 STATIC,同时添加fmt。其他工程类似。
3. 运行
下载kitti数据集
链接:https://pan.baidu.com/s/1li-O4g-XPZFgWgJHl0c4Tw?pwd=oq4f
提取码:oq4f
将下载好的数据集提取到/slambook2/ch13/Data下,修改/slambook2/ch13/config下载default.yaml中的路径为数据集所在路径,对应的default.yaml为:
%YAML:1.0 # data # the tum dataset directory, change it to yours! # dataset_dir: /media/xiang/Data/Dataset/Kitti/dataset/sequences/00 dataset_dir: /home/hucheng/slam_ws/slambook2/ch13/Data/00 # camera intrinsics camera.fx: 517.3 camera.fy: 516.5 camera.cx: 325.1 camera.cy: 249.7 num_features: 150 num_features_init: 50 num_features_tracking: 50
bash运行./bin/run_kitti_stereo
4. 后续工作
➢ 搭建windows开发slam14讲工程
➢ 详细讲解cmake语法和跨平台开发
➢ 快速讲解C++新特性
➢ 搭建docker和vnc 容器
➢ 增加euroc、tum、rosbag数据集接口
➢ 增加闭环检测模块
➢ 优化特征提取与追踪模块
➢ Ceres实现非线性优化
➢ 融合IMU实现松耦合
➢ 融合IMU实现紧耦合
➢ 源码doxygen注释
➢ 源码详细讲解
➢ SLAM公式与原理详细推导
后续工作会在腾讯文档更新,链接地址:
【腾讯文档】Slam14讲深入浅出
https://docs.qq.com/doc/DWkVabkt4eG9Lc3lL