添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
暴走的柿子  ·  HTTP中的Range: ...·  1 年前    · 
伤情的柿子  ·  memorystream.write ...·  1 年前    · 

cartographer安装报错及解决方法

疫情原因在家自学,闲来无事想看看cartographer代码,没想到就一脚踏入安装编译的大坑中,卡在这里两天,总算最后顺利解决,记录一下我这几天的历程吧。


在安装过程中,我基本上把所有的坑都踩了一遍,例如protoc版本不对应、ceres-solver链接被墙。甚至还有些网上搜不到问题。。。不过可能是因为我比较菜,有些问题是操作不当引起的,仅供参考,我会例举出安装出错的地方。


下面我不会在说安装的过程,因为好多帖子说的已经很详细了,我列出两个我觉得很好的安装过程,一个是官网的,一个是我借鉴过的。按照这两个链接的方法,基本能行。接下来我要说的是,如果你按照这些链接里的步骤去做了,但还是有问题,你可以参考一下我的做法。

1、官网:


2、博主白色小靴:


一、protoc版本问题(1)


1、报错


我的电脑是Ubuntu16.04 + ROS kinetic,因为安装ROS时就已经默认安装了protoc2.6.1,如果你已经按照网上其他帖子安装更新的protoc,会造成冲突。可能的报错有:

(1)Unrecognized syntax identifier “proto3”. This parser only recognizes “proto2”.

(2)‘google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(google::protobuf::Descriptor const*, google::protobuf::Message const*, int const*, int, int, int, int, int, int)’未定义的引用


2、我的尝试


上面那些报错,只要是和protoc有关的,基本上都是因为protoc版本冲突。我在遇到这些问题后,按照网上的帖子,不用cartographer自带脚本安装protoc,而是采用源码编译protoc新版本,源码编译参考我上面列出的非官网安装方法帖子,但是仍旧出现那些问题。


我也试过使用 sudo apt-get remove libprotobuf-dev ,然后删除 which protoc 显示路径下的protoc,但是仍然不行。需要注意的是,如果使用了 sudo apt-get remove libprotobuf-dev 卸载protoc,会导致自动删掉好多ROS自带的库,完事后还需要重新装一遍ROS,使用这个命令即可恢复ROS:sudo apt-get install ros-kinetic-desktop-full


3、解决办法


你可以按照下面的步骤看看是不是符合你的情况。首先使用下面的命令查看安装位置和版本,注意我已经使用源码编译了protobuf:

// 查看protoc版本
protoc --version	
libprotoc 3.11.4
// 查看安装位置
which protoc		
/usr/local/bin/protoc

ROS自带的protoc安装在:/usr/bin 路径下,可以看到新版本的protoc会默认安装到 /usr/local/bin 路径,这样可以避免冲突。cartographer安装时,默认搜索的路径是 /usr/bin ,有的帖子说建立/usr/local/bin/protoc 到 /usr/bin/protoc 的链接 或者干脆把 /usr/local/bin/protoc 复制到 /usr/bin 文件夹,但是还是解决不了。


因为我发现真正冲突的是libprotobuf.so ,而不是protoc。 你可看一下系统默认和新安装的libprotobuf.so的位置:

(1)系统默认位置:/usr/lib/x86_64-linux-gnu

(2)新安装版本位置: /usr/local/lib

这个默认安装位置如何查看,你可以在cartographer的CMakeLists.txt文件中,加入下面的命令来输出默认libprotobuf的位置,注意这两条语句要放在find_package(Protobuf 3.0.0 REQUIRED)后面:

MESSAGE(STATUS "ceres111 include dir " ${CERES_INCLUDE_DIRS})
find_package(Boost REQUIRED COMPONENTS iostreams)
find_package(Ceres REQUIRED COMPONENTS SuiteSparse)
find_package(Eigen3 REQUIRED)
find_package(LuaGoogle REQUIRED)
find_package(Protobuf 3.0.0 REQUIRED)
//这两个是测试原始protobuf安装位置的
MESSAGE(STATUS "protobuf include dir " ${PROTOBUF_INCLUDE_DIR})
MESSAGE(STATUS "protobuf library dir " ${PROTOBUF_LIBRARY})

下面是我的输出:

-- protobuf include dir /usr/include
-- protobuf library dir /usr/lib/x86_64-linux-gnu/libprotobuf.so


因此,我源码编译的protobuf确实安装成功了,但是cartographer没有用到,或者没有找到安装的位置,所以, 我的解决办法是,在cartographer的CMakeLists.txt中,加入下面的命令,强制指定libprotobuf的位置,注意也要放在find_package(Protobuf 3.0.0 REQUIRED)后面:

MESSAGE(STATUS "ceres111 include dir " ${CERES_INCLUDE_DIRS})
find_package(Boost REQUIRED COMPONENTS iostreams)
find_package(Ceres REQUIRED COMPONENTS SuiteSparse)
find_package(Eigen3 REQUIRED)
find_package(LuaGoogle REQUIRED)
find_package(Protobuf 3.0.0 REQUIRED)
//这两个是测试原始protobuf安装位置的
MESSAGE(STATUS "protobuf include dir " ${PROTOBUF_INCLUDE_DIR})
MESSAGE(STATUS "protobuf library dir " ${PROTOBUF_LIBRARY})
//下面这两个是指定protobuf位置
SET(PROTOBUF_INCLUDE_DIR /usr/local/include/)
SET(PROTOBUF_LIBRARY /usr/local/lib/libprotobuf.so)

使用这一步改进,我的cartographer编译成功了。


二、protoc版本问题(2)

1、报错


虽然使用上面的方法解决了那种版本报错,但还是有问题,现在的报错为:

#error This file was generated by a newer version of protoc

#error incompatible with your Protocol Buffer headers. Please update


2、原因


查看下面的文件,路径为:/usr/local/include/google/protobuf。这个是采用源码编译protobuf后,头文件的路径,查看该文件夹下的port_def.inc 文件,在这个文件里查找:#define PROTOBUF_VERSION ,因为我安装的protoc版本是3.11.4,所以我的port_def.inc 文件里是 #define PROTOBUF_VERSION 3011004 ,即把变量PROTOBUF_VERSION设置为了3011004。


再查看这个文件,路径:/build_isolated/cartographer/install/cartographer/mapping/proto,找到 trajectory.pb.h,可以看到,里面有一个判断如下

#include <google/protobuf/port_def.inc>
//#if PROTOBUF_VERSION < 3011000
//#error This file was generated by a newer version of protoc which is
//#error incompatible with your Protocol Buffer headers. Please update
//#error your headers.
//#endif
//#if 3011004 < PROTOBUF_MIN_PROTOC_VERSION
//#error This file was generated by an older version of protoc which is
//#error incompatible with your Protocol Buffer headers. Please
//#error regenerate this file with a newer version of protoc.
//#endif


因此,如果你重复安装过很多遍protoc(没错,是我!),我发现/usr/local/include/google/protobuf 下的port_def.inc 可能没有随着更新,意思是,可能你已经安装了protoc3.11.4,但是 port_def.inc 还是旧版本的,所以,虽然你更新了protoc,但还是会有#error This file was generated by a newer version of protoc 报错。


3、解决办法


采用源码编译新版本protobuf,在编译之前,把/usr/local/include/google/protobuf 删掉,即把 protobuf 文件夹里的所有内容都删掉,然后再源码编译 。我遇到的问题就是,我既尝试了源码编译,发现还是有问题,然后又使用cartographer自带的脚本安装,使用脚本安装后 port_def.inc 没有更新,所以还是报错。



三、ceres函数未定义的引用

1、报错


使用上面两个方法改进,我的cartographer已经编译成功,但是cartographer_ros编译报错,报错内容如下,反正就是关于ceres的好多函数未定义的引用。


/home/sx/catkin_frt/install_isolated/lib/libcartographer.a(ceres_scan_matcher_2d.cc.o):在函数‘cartographer::mapping::scan_matching::CeresScanMatcher2D::Match(Eigen::Matrix<double, 2, 1, 0, 2, 1> const&, cartographer::transform::Rigid2<double> const&, std::vector<Eigen::Matrix<float, 3, 1, 0, 3, 1>, std::allocator<Eigen::Matrix<float, 3, 1, 0, 3, 1> > > const&, cartographer::mapping::Grid2D const&, cartographer::transform::Rigid2<double>*, ceres::Solver::Summary*) const’中:

ceres_scan_matcher_2d.cc:(.text+0x283):对‘ceres::Problem::AddResidualBlock(ceres::CostFunction*, ceres::LossFunction*, double* const*, int)’未定义的引用


2、原因


这种未定义的引用一般,要么是CMakeLists.txt 的 target_link_libraries 没写对,要么就是库的版本不对。显然我感觉cartographer_ros 的CMakeLists.txt 没写错。。所以怀疑是ceres-solver版本不对。


因为我发现在编译cartographer 和 cartographer_ros 时,都会依赖ceres-solver,整个cartographer编译的顺序是,先编译cartographer,然后生成一个库libcartographer.a,路径是 /install_isolated/lib,然后编译cartographer_ros 时会依赖这个libcartographer.a。在我编译cartographer时,CMakeLists.txt 中有find_package(Ceres REQUIRED COMPONENTS SuiteSparse),编译的输出信息是:

-- Found installed version of Eigen: /usr/lib/cmake/eigen3
-- Found required Ceres dependency: Eigen version 3.2.92 in /usr/include/eigen3
-- Found required Ceres dependency: glog