Cartographer编译问题整理

Cartographer


​ 毕设工作设计到与cartographer进行定量实验比较。本人在Enigmatisms/cartographer_tester中整理了cartographer以及ros驱动代码,添加了自动化轨迹读取等功能,两周前在Ubuntu 18.04上已经完成了测试,但在Ubuntu 20.04上一直编译不通过,调了一下午才调出来。本文记录了cartographer在不同版本的Ubuntu上(尤其是20.04)的一些典型编译问题以及解决方案。笔者现已经通过文中所说的解决方案完成了cartographer的编译。


Lua Not Found

​ 从Github上下载Lua,本地编译安装并且sudo make install 是可以使得这个错误消失。但是,我在Ubuntu 18.04用此方法安装Lua 5.3之后,编译导致ABSL库问题(与Lua有关的)。遂sudo make uninstall卸载,使用

1
sudo apt install lua5.2

​ 通过apt安装。但是这样安装的lua5.2,编译时仍然说找不到(即使重启,仍然也找不到)。不过,其实我跳过了官网的rosdep步骤,先走完rosdep步骤再编译就能找到lua 5.2了。关于如何解决rosdep update速度慢的问题,见 [这篇博客,亲测有效]. 这篇博客虽然针对20.04,对于18.04,只需要修改python3为python2.7即可。


Undefined Reference to ABSL

absl库可能产生问题:

1
2
3
4
5
6
7
8
9
10
11
[241/387] Linking CXX executable cartographer_pbstream
FAILED: cartographer_pbstream
: && /usr/bin/c++ -O3 -DNDEBUG -rdynamic CMakeFiles/cartographer_pbstream.dir/cartographer/io/pbstream_main.cc.o -o cartographer_pbstream libcartographer.a /usr/local/lib/libceres.a -lglog -lspqr -ltbb -lcholmod -lccolamd -lcamd -lcolamd -lamd -llapack -lf77blas -latlas -lsuitesparseconfig -lrt -lcxsparse -llapack -lf77blas -latlas -lsuitesparseconfig -lrt -lcxsparse -llua5.2 -lm /usr/lib/x86_64-linux-gnu/libboost_iostreams.so.1.71.0 -lglog /usr/lib/x86_64-linux-gnu/libgflags.so.2.2.2 -lcairo /usr/local/lib/libprotobuf.a /usr/local/lib/libabsl_leak_check.a /usr/local/lib/libabsl_cord.a /usr/local/lib/libabsl_cordz_info.a /usr/local/lib/libabsl_cord_internal.a /usr/local/lib/libabsl_cordz_functions.a /usr/local/lib/libabsl_cordz_handle.a /usr/local/lib/libabsl_hash.a /usr/local/lib/libabsl_city.a /usr/local/lib/libabsl_bad_variant_access.a /usr/local/lib/libabsl_low_level_hash.a /usr/local/lib/libabsl_raw_hash_set.a /usr/local/lib/libabsl_bad_optional_access.a /usr/local/lib/libabsl_hashtablez_sampler.a /usr/local/lib/libabsl_exponential_biased.a /usr/local/lib/libabsl_str_format_internal.a /usr/local/lib/libabsl_synchronization.a /usr/local/lib/libabsl_stacktrace.a /usr/local/lib/libabsl_graphcycles_internal.a /usr/local/lib/libabsl_symbolize.a /usr/local/lib/libabsl_malloc_internal.a /usr/local/lib/libabsl_debugging_internal.a /usr/local/lib/libabsl_demangle_internal.a /usr/local/lib/libabsl_time.a /usr/local/lib/libabsl_strings.a /usr/local/lib/libabsl_strings_internal.a /usr/local/lib/libabsl_base.a -lpthread /usr/local/lib/libabsl_spinlock_wait.a -lrt /usr/local/lib/libabsl_throw_delegate.a /usr/local/lib/libabsl_raw_logging_internal.a /usr/local/lib/libabsl_log_severity.a /usr/local/lib/libabsl_int128.a /usr/local/lib/libabsl_civil_time.a /usr/local/lib/libabsl_time_zone.a -lpthread && :
/usr/bin/ld: libcartographer.a(histogram.cc.o): in function `cartographer::common::Histogram::ToString[abi:cxx11](int) const':
histogram.cc:(.text+0x43c): undefined reference to `absl::strings_internal::CatPieces[abi:cxx11](std::initializer_list<std::basic_string_view<char, std::char_traits<char> > >)'
/usr/bin/ld: histogram.cc:(.text+0x95a): undefined reference to `absl::strings_internal::AppendPieces(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, std::initializer_list<std::basic_string_view<char, std::char_traits<char> > >)'
collect2: error: ld returned 1 exit status
[256/387] Building CXX object CMakeFiles/cartographer.mapping.internal.3d.scan_matching.fast_correlative...er_3d_test.dir/cartographer/mapping/internal/3d/scan_matching/fast_correlative_scan_matcher_3d_test.cc.o
ninja: build stopped: subcommand failed.
<== Failed to process package 'cartographer':
Command '['ninja', '-j16', '-l16']' returned non-zero exit status 1.

​ 此问题可能由两部分原因导致:

  • Ubuntu 20.04上,cartographer,cartographer_ros等模块以及abseil-cpp模块均需要使用c++17标准编译(来源于这个Github issue:8.0 fails: undefined reference to absl::lts_2020_09_23::Status::Status #2196),原始的install_abseil.sh是这样的:

    1
    2
    3
    4
    5
    cmake -G Ninja \
    -DCMAKE_BUILD_TYPE=Release \
    -DCMAKE_POSITION_INDEPENDENT_CODE=ON \
    -DCMAKE_INSTALL_PREFIX=/usr/local/stow/absl \
    ..

    如果修改为:

    1
    2
    3
    4
    5
    6
    7
    8
    cmake -G Ninja \
    -std=c++17 \
    -DABSL_CXX_STANDARD=17 \
    -DCMAKE_BUILD_TYPE=Release \
    -DCMAKE_POSITION_INDEPENDENT_CODE=ON \
    -DCMAKE_INSTALL_PREFIX=/usr/local/stow/absl \
    -DABSL_PROPAGATE_CXX_STD=ON \
    ..

    ​ 增加-std=c++17-DABSL_CXX_STANDARD=17-DABSL_PROPAGATE_CXX_STD=ON ,前两个选项为了使得编译使用c++17标准,最后一个选项防止编译warning。而其他cartographer相关模块,只需要在每个模块下的CMakeLists.txt中的project(xxx)后添加

    1
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17")

  • Google查找问题时,在abseil-cpp库的issue里找到了这么一个issue: undefined reference errors (absl::strings_internal::CatPieces and absl::ByChar::Find)。其中有个人提到:

Confirmed on my end: if I add back what was removed from AbseilConfigureCopts.make in commit c695489 then it works.

​ 于是我修改install_abseil.sh

1
git checkout c6954897f7ece5011f0126db9117361dc1a6ff36	# 修改到这个commit

​ 编译abseil-cpp,完成后删除cartographer之前的build_isolated以及devel_isolated并重新编译cartographer。则不再出现absl库问题。


PythonInterp 版本问题

​ Ubuntu 20.04首次摒弃 python 2.7,包括ROS(rospy)在内全面转向python3,但是可能还是存在一些余孽?继续编译后我遇到了如下问题:

1
2
3
4
5
6
7
8
9
10
CMake Error at /usr/share/cmake-3.16/Modules/FindPackageHandleStandardArgs.cmake:146 (message):
Could NOT find PythonInterp: Found unsuitable version "2.7.18", but
required is at least "3" (found /usr/bin/python)
Call Stack (most recent call first):
/usr/share/cmake-3.16/Modules/FindPackageHandleStandardArgs.cmake:391 (_FPHSA_FAILURE_MESSAGE)
/usr/share/cmake-3.16/Modules/FindPythonInterp.cmake:169 (FIND_PACKAGE_HANDLE_STANDARD_ARGS)
/opt/ros/noetic/share/catkin/cmake/python.cmake:4 (find_package)
/opt/ros/noetic/share/catkin/cmake/all.cmake:164 (include)
/opt/ros/noetic/share/catkin/cmake/catkinConfig.cmake:20 (include)
CMakeLists.txt:55 (find_package)

​ emmm,我查了一下trace stack中的所有cmake文件,没有什么发现,只是cmake无法找到python3,并且在which python时显示的是2.7.18的 python2。看来是默认python有问题,只需要使用:

1
2
sudo update-alternatives --install /usr/bin/python python /usr/bin/python2.7 1
sudo update-alternatives --install /usr/bin/python python /usr/bin/python3.8 2

​ 就可以解决问题,自此所有问题都得到了解决,cartographer顺利安装。


其他记录

  • 成功无bug适配了cartographer的cere-solver版本是2.0.0,在Ubuntu 18.04以及20.04上通用。
  • cartographer的 CMakeLists.txt很复杂,但是读一读还是能学到一些有趣的东西,比如:cmake_parse_arguments