karto_g2o - yuhannah/skills_map GitHub Wiki

ROS 下编译 G2O ( karto 后端使用 g2o )

(一)eigen多版本切换

主要流程:

1.已有的eigen版本保留

2.官网下载其他版本的源码(eigen只有头文件,不需要编译)

3.不同版本文件夹命名eigen3.2.92 eigen3.4.0

4.使用时替换默认文件夹中的头文件

ubuntu系统安装的eigen3是3.2.92.

g2o需要3.3以上

(二)cmake多版本切换

主要流程:

1.已有的cmake版本保留

2.官网下载编译好的需要的cmake版本

3.解压后放在/opt下

4.建立软连接

5.第4步后还不行,继续添加环境变量

ubuntu系统安装的cmake是3.5.1

g2o需要3.14以上

(三)下载独立编译g2o

主要流程:

1.下载源码到Thirdparty/

2.删除git仓库

3.编译(需要指定eigen头文件路径)

cd g2o
mkdir build
cd build
cmake .. -DEIGEN3_INCLUDE_DIR=/usr/include/eigen3
make

(四)用catkin_make编译g2o

主要流程:

1.下载源码到catkin_ws/src/

2.在g2o/目录下添加package.xml

<package format="2">
  <name>g2o</name>
  <description>ROS wrapper for the g2o library (needed for slam_karto)</description>
  <version>0.4.4</version>
  <license>BSD</license>
  <maintainer email="[email protected]">xx</maintainer>
  <maintainer email="[email protected]">xx</maintainer>

  <buildtool_depend>catkin</buildtool_depend>

  <depend>roscpp</depend>
  <depend>eigen</depend>
  <depend>suitesparse</depend>

</package>

3.在g2o的CMakeLists.txt中添加catkin

project(g2o)

# add here
find_package(catkin REQUIRED COMPONENTS roscpp)

# ...

include(CMakePackageConfigHelpers)
WRITE_BASIC_PACKAGE_VERSION_FILE(
    "${G2O_VERSION_CONFIG}" VERSION ${G2O_VERSION} COMPATIBILITY SameMajorVersion
)

# add here
include_directories(${catkin_INCLUDE_DIRS})
catkin_package()

4.删除catkin_ws/src/下原有的CMakeLists.txt

5.生成新的CMakeLists.txt

cd ~/catkin_ws/src
rm -rf CMakeLists.txt
catkin_init_workspace

6.删除catkin_ws/build catkin_ws/devel 下原有的编译结果

7.编译,仅编译g2o包,切指定eigen3目录

cd ~/catkin_ws
catkin_make -DCATKIN_WHITELIST_PACKAGES="g2o" -DEIGEN3_INCLUDE_DIR=/usr/include/eigen3

(五)用catkin_make编译g2o+karto(没有依赖关系)

主要流程:

1.在g2o的cmake_modules/修改FindEigen3.cmake文件,添加指定头文件路径

set(EIGEN3_INCLUDE_DIR "/usr/include/eigen3")

2.保留第四条的所有修改

3.编译,包含g2o的graph_slam

catkin_make -DCATKIN_WHITELIST_PACKAGES="open_karto;slam_karto;sparse_bundle_adjustment;g2o"

这里有个问题,如果将第1条的指定路径,放在cmake命令中执行,那g2o能找到eigen3,但是其他库找不到eigen3,原因不明。

4.清空编译内容,重新编译,删除第1条的设置指定路径,在cmake命令中执行,所有库都能正常找到eigen3了

catkin_make -DCATKIN_WHITELIST_PACKAGES="open_karto;slam_karto;sparse_bundle_adjustment;g2o" -DEIGEN3_INCLUDE_DIR=/usr/include/eigen3

(六)用cmake编译g2o+karto(没有依赖关系)

主要流程:

1.将第四条的修改搬到Thirdparty/中,修改对应的g2o的CMakeLists.txt,和添加package.xml

2.编译,在cmake命令中指定eigen3目录路径

cd graph_slam mkdir build_pc
cd build_pc
cmake .. \
  -DCMAKE_INSTALL_PREFIX=../install \
  -DCATKIN_DEVEL_PREFIX=../devel_pc \
  -DEIGEN3_INCLUDE_DIR=/usr/include/eigen3
make -j2

(七)用catkin_make编译带g2o的karto(有依赖关系,从第五条继续)

主要流程:

1.修改slam_karto的CMakeLists.txt,添加g2o

find_package(catkin REQUIRED
  COMPONENTS
    message_filters
    nav_msgs
    open_karto
    rosconsole
    roscpp
    sensor_msgs
    sparse_bundle_adjustment
    tf
    visualization_msgs
    g2o # add here
)

2.修改slam_karto的package.xml,添加g2o

<package>
  <build_depend>g2o</build_depend>
  <run_depend>g2o</run_depend>
</package>

3.清空编译内容,重新编译

catkin_make \
-DCATKIN_WHITELIST_PACKAGES="open_karto;slam_karto;sparse_bundle_adjustment;g2o" \ 
-DEIGEN3_INCLUDE_DIR=/usr/include/eigen3

(八)用cmake编译带g2o的karto(有依赖关系,从第六条继续)

主要流程:

1.将第七条的修改搬到Thirdparty/中,修改对应的slam_karto的CMakeLists.txtpackage.xml

2.清空编译内容,重新编译

cd graph_slam
mkdir build_pc
cd build_pc
cmake .. \
-DCMAKE_INSTALL_PREFIX=../install \
-DCATKIN_DEVEL_PREFIX=../devel_pc \
-DEIGEN3_INCLUDE_DIR=/usr/include/eigen3
make

3.添加g2o_solver.h/.cpp (来源网络slam_toolbox)

4.在slam_karto中使用g2o_solver,并修改CMakeLists.txt (来源网络,暂时这么写,后续调整代码)

add_executable(slam_karto src/slam_karto.cpp src/spa_solver.cpp src/g2o_solver.cpp)
target_link_libraries(slam_karto ${catkin_LIBRARIES})

修改c++11到c++14,用于编译g2o(这一条可选,出现问题再改,后来重新编译没有产生问题,于是舍弃了修改)

set(CMAKE_CXX_STANDARD 14)

5.清空编译内容,重新编译,出现问题

/home/yu/sources/graph_slam/Thirdparty/slam_karto/src/g2o_solver.h : fatal error: g2o/core/sparse_optimizer.h: 没有那个文件或目录

CMakeLists.txt中添加g2o源码路径,从catkin中传递进去,给slam_karto使用

打印看 ${PROJECT_SOURCE_DIR}=/home/yu/sources/graph_slam/Thirdparty/g2o

include_directories(${catkin_INCLUDE_DIRS} ${EIGEN3_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR})
catkin_package(
  INCLUDE_DIRS
    ${PROJECT_SOURCE_DIR}
  LIBRARIES
)

6.清空编译内容,重新编译,上述问题解决,新的问题出现

/home/yu/sources/graph_slam/Thirdparty/g2o/g2o/core/g2o_core_api.h:13:24: fatal error: g2o/config.h: 没有那个文件或目录

CMakeLists.txt中添加g2o编译目录路径,从catkin中传递进去,给slam_karto使用。

catkin_package(
  INCLUDE_DIRS
    ${PROJECT_SOURCE_DIR} # find g2o *.h
    ${PROJECT_BINARY_DIR} # no install, find g2o/config.h
  LIBRARIES
)

g2o/config.h只有在 install 后才会在头文件目录下。当前没有 install ,只有 cmake ,g2o/config.h文件在 build_pc/g2o/g2o/config.h, 手动添加目录。

添加后catkin会产生warning,说文件目录放的位置不合理,暂时没有解决方案:

CMake Warning at /opt/ros/kinetic/share/catkin/cmake/catkin_package.cmake:418 (message):
  catkin_package() include dir '/home/yu/sources/graph_slam/build_pc/g2o'
  should be placed in the devel space instead of the build space
Call Stack (most recent call first):
  /opt/ros/kinetic/share/catkin/cmake/catkin_package.cmake:102 (_catkin_package)
  g2o/CMakeLists.txt:553 (catkin_package)

7.清空编译内容,重新编译,上述问题解决,新的问题出现

/home/yu/sources/graph_slam/Thirdparty/g2o/g2o/core/base_fixed_sized_edge.h:38:40: fatal error: ceres/internal/fixed_array.h: 没有那个文件或目录

产生问题的地方如下所示:

g2o/CMakeLists.txt中,设置变量 G2O_USE_VENDORED_CERES=ON,表示用g2o自带的ceres。

set(G2O_USE_VENDORED_CERES ON CACHE BOOL "Use vendored Ceres from g2o/EXTERNAL/ceres")

g2o/EXTERNAL/CMakeLists.txt中,由于变量 G2O_USE_VENDORED_CERES=true,添加 ceres 目录下的文件进行编译。

if(G2O_USE_VENDORED_CERES)
  add_subdirectory(ceres)
endif()

g2o/core/CMakeLists.txt中,由于变量 G2O_USE_VENDORED_CERES=true,用命令 target_compile_definitions() 定义了一个宏 G2O_USE_VENDORED_CERES 给代码使用。

if(G2O_USE_VENDORED_CERES)
  target_compile_definitions(core PUBLIC "G2O_USE_VENDORED_CERES")
  target_link_libraries(core PUBLIC g2o_ceres_ad)
else()
  find_package(Ceres REQUIRED)
  target_link_libraries(core PUBLIC ceres)
endif()

代码中,比如 g2o/g2o/core/base_fixed_sized_edge.h 的头文件选择用g2o自带的,而不是本地安装的。

#ifdef G2O_USE_VENDORED_CERES
#include "g2o/EXTERNAL/ceres/fixed_array.h"
#else
#include <ceres/internal/fixed_array.h>
#endif

最后这里产生的问题,编译发现没有定义变量 G2O_USE_VENDORED_CERES,于是找本地路径,而本地没有安装 ceres,于是找不到头文件。

CMakeLists.txt看,是定义了 G2O_USE_VENDORED_CERES 的,应该找g2o自带的头文件,为什么没定义成功??

测试了其他文件,target_compile_definitions() 的用法是正确的,能定义变量。

当前的临时方案,是屏蔽代码中的if...else...,默认使用g2o自带的ceres。

8.清空编译内容,重新编译,上述问题临时解决,新的问题出现

g2o未定义的引用

就是说 g2o 的库没有链接到 slam_karto. 解决方案,将 g2o 编译生成的库文件通过 catkin_package() 传递给 slam_karto.

catkin_package(
  INCLUDE_DIRS
    ${PROJECT_SOURCE_DIR} # find g2o *.h
    ${PROJECT_BINARY_DIR} # find g2o/config.h
  LIBRARIES
    core
    csparse_extension freeglut_minimal
    solver_cholmod solver_csparse solver_dense solver_eigen solver_pcg solver_slam2d_linear solver_structure_only
    g2o_ceres_ad g2o_cli_library g2o_hierarchical_library g2o_incremental_library g2o_interactive_library g2o_simulator_library
    types_data types_icp types_sba types_sclam2d types_slam2d_addons types_slam3d types_slam3d_addons
    calibration_odom_laser_library interface_library opengl_helper parser_library stuff tutorial_slam2d_library
)

这里又遇到问题,按照devel_pc中生成的g2o的库:libg2o_cli.so libg2o_core.so libg2o_csparse_extension.so 等,然后在 LIBRARIES 中添加 g2o_cli g2o_core g2o_csparse_extension 等等,报错找不到这些库。

查找CMakeLists.txt,发现 add_library() 定义的库名字叫:g2o_cli_library core csparse_extension 等。在 LIBRARIES 中添加这样的名字,编译通过。

编译通过。

9.整理代码。把第8条g2o库链接好了以后,第7条的问题自动消失了。舍弃第7条的处理。

10.整理代码,添加launch参数,指定不同的后端优化算法。

11.仿真bag测试通过,两种优化算法均正常使用,有优化效果。

⚠️ **GitHub.com Fallback** ⚠️