ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

Cartographer源码安装与官网数据集实测:从依赖编译到跑通2D SLAM

Cartographer源码安装与官网数据集实测:从依赖编译到跑通2D SLAM Cartographer 这套系统我断断续续折腾过好多次从最开始在 Ubuntu 16.04 上被依赖坑到怀疑人生到后来在 Noetic 上一条命令跑通中间攒了不少经验。如果你正卡在“安装”这一步或者刚装完不知道拿什么验证效果这篇就按我的实际操作路径来写照着做基本能顺下来。先说它是什么Cartographer 是 Google 开源的一套基于图优化的 SLAM 库支持 2D 激光雷达和 3D 传感器组合建图定位精度高而且能输出闭环约束做机器人导航地图几乎是首选方案之一。官网提供了一批标准的开源数据集bag 文件包含不同场景的激光、IMU、里程计数据正好用来验证安装结果和调参手感。这篇适合刚接触 Cartographer、想在本地把它跑起来看效果的人也适合已经在用但想系统理解配置参数的同学。1. 安装前的整体思路为什么 Cartographer 难装以及两条可行路线Cartographer 难装是出了名的但难的不是它本身的代码而是依赖关系太复杂。它依赖 ceres-solver、protobuf、abseil、glog、gflags、gtest 这些底层库而且对版本有要求。地图构建的核心优化部分由 ceres-solver 承担它负责把激光帧间约束和非线性误差一起做图优化数据序列化又依赖 protobufabseil 提供了一些基础数据结构字符串处理、哈希表之类的。只要你系统中这些库的版本和 Cartographer 要求的不一致编译期就可能报出一堆看不懂的错。所以我的建议是不要一上来就想“跑通官网数据集”先把依赖环境当成一个独立任务来处理。整理好自己的 ROS 环境和系统版本再决定走哪条路。1.1 环境选型系统、ROS、编译器的搭配推荐组合是 Ubuntu 20.04 ROS Noetic这是目前网上教程最多、坑最少、最稳的组合。ROS 版本直接决定你后面用 apt 装的依赖是什么版本Noetic 的 Python 是 3.8工具链成熟cartographer_ros 在 Noetic 下编译基本不会因为 Python 版本翻车。当然 Ubuntu 18.04 Melodic 也可以但一些依赖包需要手动编译的步骤会多一些不是新手最优选。如果你实在想用 Ubuntu 22.04 ROS Humble也不是不行但要知道 Humble 用的是新版 protobuf、abseil和 Cartographer 默认依赖有冲突概率需要做不少兼容处理。从零开始的话新手不要和版本硬刚直接装 20.04 Noetic 是最划算的。另外确认编译器版本。Ubuntu 20.04 自带的 gcc 9 完全没问题如果你系统里同时装了多个 gcc 版本注意让 CMake 选到正确的那个否则可能出现 ABI 不兼容导致编译失败的情况。1.2 两条路线怎么选源码编译 vs Docker 镜像路线一源码编译。这也是官方文档为主推的方式适合想理解构建过程、后面需要改代码、加自定义传感器的人。缺点是依赖多中途报错要自己解决。路线二用 Docker 镜像。如果你只想把 Cartographer 跑起来、看官网数据集效果、验证算法流程Docker 是最省事的方案。官方仓库里维护了一份 Dockerfile把依赖和源码都打包好了你只需要装好 NVIDIA Container Toolkit如果要用显卡和 Docker拉镜像就能直接跑 bag。但 Docker 方案有个问题数据只能通过挂载目录进容器RViz 等 GUI 工具要用 x11 转发或者 vnc操作起来不直观。而且真正做机器人项目时你的驱动、串口、雷达节点通常跑在宿主机上容器网络和共享内存配置又成了一套新麻烦。我后面要把自己写的里程计节点、IMU 驱动都接进来所以选择源码编译。如果你明确只想验证效果Docker 是合理的快速路径但跟着这篇一步步编译一次后面调参会顺手很多我对关键节点都会标注说明。2. 源码编译安装 Cartographer从依赖到可用的完整过程我按“装基础库 → 编 ceres → 编 protobuf → 编 abseil → 编 cartographer/cartographer_ros → 验证环境”这个顺序来。顺序很重要因为 CMake 查找依赖是被动的依赖没装好后面编到一半再回头补非常浪费时间。2.1 创建 ROS 工作空间并安装基础系统库先把 ROS Noetic 装好然后创建工作空间mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone https://github.com/cartographer-project/cartographer.git git clone https://github.com/cartographer-project/cartographer_ros.git然后通过 apt 安装基础依赖。官方文档给的命令比较全你不需要全部手动装下面这个列表是我实测可用的sudo apt-get update sudo apt-get install -y \ cmake g git google-mock libboost-all-dev \ libcairo2-dev libeigen3-dev libgflags-dev \ libgoogle-glog-dev liblua5.3-dev libprotobuf-dev \ libsuitesparse-dev libwebp-dev ninja-build \ protobuf-compiler python3-sphinx python3-pip \ ros-noetic-rosbag ros-noetic-tf2-eigen \ ros-noetic-pcl-ros ros-noetic-rviz注意 liblua5.3-dev 是 Cartographer 的 Lua 配置解释器依赖必装。如果你系统原本装了其他 Lua 版本最好先卸载冲突项否则编译 cartographer 源码时可能会报 “Could not find Lua” 或者 “lua.h not found” 之类的错误我踩过一次。装完这些以后顺手装 vcstoolsudo pip3 install -U vcstool官方建议用 wstool 下载额外依赖但实际整个依赖树里cartographer 和 cartographer_ros 两个仓库就够了其他都是系统级依赖或由 CMake 自行拉取。2.2 编译 ceres-solver地图优化引擎ceres-solver 是 Cartographer 做图优化和 scan-to-map 匹配的核心库。版本建议用 1.13我之前在 2.0 版本上遇到过和 Cartographer 的 API 不兼容问题。源码编译cd ~ git clone https://github.com/ceres-solver/ceres-solver.git cd ceres-solver git checkout 1.13.0 mkdir build cd build cmake .. make -j8 sudo make install这里有几个注意点ceres-solver 编译依赖 Eigen所以前面必须先装好 libeigen3-dev。编译时间取决于机器四核以上大概几分钟。如果你机器有多个核可以用make -j$(nproc)但内存小于 8G 的话建议限制并行度比如-j4否则编译到一半可能因为内存不足崩掉。还有一点如果系统里已经通过 apt 安装了 libceres-dev会出现两套 ceres 冲突编译 Cartographer 时找不到它要的头文件。建议在编译前先卸载系统自带的 ceressudo apt-get remove libceres-dev2.3 编译 protobuf版本匹配是关键Cartographer 官方声明依赖 protobuf 3.4.1。我一开始偷懒装了系统自带的新版 protobuf结果运行时报 “protobuf version mismatch” 错误。这个错在 Cartographer 里极其常见因为 protobuf 的版本号写死在编译产物里只要运行时链接的库和编译时版本不一致就会崩。所以老老实实指定版本编译cd ~ git clone https://github.com/protocolbuffers/protobuf.git cd protobuf git checkout v3.4.1 mkdir build cd build cmake ../cmake -DCMAKE_POSITION_INDEPENDENT_CODEON \ -Dprotobuf_BUILD_TESTSOFF \ -DCMAKE_INSTALL_PREFIX/usr/local make -j8 sudo make install-DCMAKE_POSITION_INDEPENDENT_CODEON这个选项一定要加否则编出来的静态库不能链接进 cartographer 的动态库后面会报 relocation 错误。装完可能需要更新一下动态链接库缓存sudo ldconfig2.4 编译 abseil一个容易忽略的硬依赖Cartographer 从很早的版本就引入了 abseil用于内部数据结构和内存管理。它不会自动通过 CMake 拉取你必须先编译安装。最简单的方式是cd ~ git clone https://github.com/abseil/abseil-cpp.git cd abseil-cpp mkdir build cd build cmake .. -DCMAKE_POSITION_INDEPENDENT_CODEON \ -DCMAKE_INSTALL_PREFIX/usr/local make -j8 sudo make install sudo ldconfig如果你跳过这一步编译 cartographer_ros 时会看到类似Could not find abseil或者找不到 absl 命名空间的错误。这个问题在 Ubuntu 20.04 上最容易出现因为 apt 源里没有完整的 abseil 开发包。2.5 编译 cartographer 与 cartographer_ros依赖都就位后回到工作空间编译。先编 cartographer 本体cd ~/catkin_ws/src/cartographer mkdir build cd build cmake .. make -j8 sudo make install这一步如果前面依赖没问题会很顺利。然后编 cartographer_ros。注意 cartographer_ros 不是一个普通 catkin 包它依赖 cartographer 的安装路径所以要确保上一步 install 完成后再执行cd ~/catkin_ws catkin_make source devel/setup.bash如果你要用 catkin build 也没问题但需要提前安装 catkin_tools。catkin_make虽然老胜在稳定。编完以后验证一下环境是否能被正确找到roscd cartographer_ros能正常roscd就说明编译安装阶段基本完成了。3. 拿到官网数据集下载、确认和 bag 文件基础安装好了下一步就是用官网数据集跑通整个链路。这里说的“官网数据集”是指 Cartographer 官方维护的公开 bag 包比如 backpack_2D、backpack_3D、Revo LDS 等等。它们收录了真实传感器采集的激光数据、IMU 数据、里程计数据还配套了 launch 文件和 rviz 配置是最标准的验证输入。3.1 下载哪些数据集对 2D SLAM 来说最经典的入门数据集是 Revo LDS它数据量适中场景不大建图效果干净适合第一次跑mkdir -p ~/carto_data cd ~/carto_data wget -c https://storage.googleapis.com/cartographer-public-data/bags/revo_lds/rev_lds.bag如果你主要做机器人导航更需要贴近实际场景的 2D 数据那就下 backpack 2D 数据集wget -c https://storage.googleapis.com/cartographer-public-data/bags/backpack_2d/cartographer_paper_deutsches_museum.bag跑完 2D 再想试试 3D可以下 backpack 3Dwget -c https://storage.googleapis.com/cartographer-public-data/bags/backpack_3d/with_intensities/backpack_3d.bag它们是公开数据直接 wget 就行。下载前注意bag 文件体积不小Revo LDS 大概几百 MB3D backpack 有 1.5G 左右先确认磁盘空间。如果网络不稳定-c参数可以断点续传这是我反复下载后的经验。3.2 bag 文件结构与话题检查bag 文件本质是 ROS 话题数据的打包容器里面按时间顺序记录了每一个话题消息。运行前最好先看一眼话题名和类型否则 launch 里订阅错了话题跑出来的地图会是空的。用以下命令查看rosbag info ~/carto_data/cartographer_paper_deutsches_museum.bag你会发现典型输出包括/scan激光雷达话题sensor_msgs/LaserScan/imuIMU 数据sensor_msgs/Imu/odom轮式里程计nav_msgs/Odometry/points2或类似话题3D 激光点云Cartographer 默认的 launch 文件中已经配置好了常见话题名但如果你手里是自定义 bag一定要用rosbag info确认话题名是否匹配这是很多人第一次跑不出来地图的最主要原因。4. 把官网数据集跑起来launch 文件解析和回放实操数据备好了环境也编译好了接下来就是关键的回放操作。你需要开三个终端一个启动 roscorelaunch 会自动带起来也可能不带一个启动 cartographer_ros 的 launch 文件一个用来回放 bag。4.1 跑 Revo LDS 数据集先跑 Revo LDS 这个最小的# 终端1启动 ROS Master如果 launch 里没写则需要 roscore # 终端2启动 cartographer_ros roslaunch cartographer_ros demo_revo_lds.launch bag_filename:~/carto_data/rev_lds.bag # 终端3按 bag 录制时的原始速率发布数据 rosbag play --clock ~/carto_data/rev_lds.bag注意这里bag_filename是 demo_revo_lds.launch 定义好的参数不要自己拼错路径。--clock选项非常关键它让 bag 把录制时的 ROS 时间作为时钟源发布Cartographer 对时间戳一致性极其敏感。不加--clock系统会使用当前机器时间而 bag 里是录制时间两者对不上算法直接飘。启动 rviz 的话demo_revo_lds.launch 默认已经调起并加载了官方 rviz 配置。你会在界面上看到激光点云数据scan 话题、靠近激光传感器原点位置有 submap 实时更新随着 bag 播放地图逐渐渲染出来同时显示轨迹。我第一次跑完地图的细节恢复得很干净走一圈闭合回环后原来严重偏差的走廊尽头会自动拉正。那种直观感受确实打动我——即使我对源码还一知半解也能立刻理解“图优化闭环约束”在干什么。4.2 跑 backpack 2D 数据集Revo LDS 只是单雷达建图backpack 2D 数据集多了 IMU 和里程计参与融合更能看出 Cartographer 的多传感器协同能力roslaunch cartographer_ros demo_backpack_2d.launch bag_filename:~/carto_data/cartographer_paper_deutsches_museum.bag rosbag play --clock ~/carto_data/cartographer_paper_deutsches_museum.bagbag 开始回放后RViz 中能看到带颜色的 submap 方格不断向周围扩展轨迹线跟着刷新。和 Revo 数据集最大的区别是这里 IMU 提供了重力和局部姿态参考即使在快速转弯、激光退化明显的场景中整体轨迹也能保持稳定不会像纯激光那样出现撕裂感。如果这一步跑出来地图能看清楚建筑结构和展柜轮廓说明安装没问题cartographer 核心功能已经生效。如果 rviz 里地图一片空白或者轨迹乱飘优先检查时间同步、话题名、IMU 数据是否为有效值这三个方向。4.3 launch 文件到底做了什么demo_backpack_2d.launch不算复杂核心就四件事启动cartographer_node这是核心 SLAM 节点负责接收/scan、/imu、/odom话题计算位姿并更新地图。启动cartographer_occupancy_grid_node把 submap 转换成 ROS 标准的nav_msgs/OccupancyGrid方便导航栈直接使用。配置三个 Lua 参数文件map_builder.lua、trajectory_builder_2d.lua、backpack_2d.lua。启动 rviz 并加载官方配置让你默认看到地图、轨迹、机器人模型坐标系。理解了这些你就不会把“直接 roslaunch”当成黑盒。比如以后你自己改了雷达话题名不用改源码直接在 launch 里的remap标签处映射过来就行想关掉 IMU在 trajectory_builder_2d.lua 里把use_imu_data改成 false。配置优先于改代码这是 Cartographer 设计得比较舒服的地方。5. 常见问题与调参速查我从坑里爬出来后的记录这部分内容全是实话。整个安装和跑通官方数据集的过程中我栽过好几个跟头有些问题现在翻网上的 issue 和博客答案还散得到处都是。我把高频问题整理成一个速查表附带我个人排查顺序。5.1 高频报错的解决记录现象根因处理方式编译 cartographer 时报ceres相关错误系统自带 ceres 版本不兼容或没装 Eigen卸载 apt 版 libceres-dev源码编译 1.13.0确认 libeigen3-dev 已装编译 cartographer_ros 时提示找不到 abseilabseil 没有编译安装回 2.4 节流程编译后执行sudo ldconfig运行时 protobuf 报版本 mismatch 或直接段错误protobuf 版本不是 3.4.1按 2.3 节源码重编并确认/usr/local/lib里的动态库优先级高于/usr/libroslaunch 提示找不到demo_revo_lds.launchcartographer_ros 没 source 到当前环境source ~/catkin_ws/devel/setup.bash确认roscd cartographer_ros能进入rosbag play后 RViz 里一直没有地图时间不同步或话题不匹配加--clock参数用rosbag info对比话题名跑 backpack_2d 时轨迹频繁跳变IMU 数据未启用或 label 异常检查 IMU 话题是否发布必要时在 lua 里把use_imu_data设为 false 测试纯雷达效果编译时单个目标文件因内存不足被 kill并行编译串数太多用-j2或-j4重新编译释放内存后再继续不要小看sudo ldconfig这一步特别是你源码安装了 protobuf 和 abseil 之后。系统默认搜索/usr/lib和/lib而源码安装默认进/usr/local/lib如果不刷新缓存程序运行时可能仍然链接到旧版本库出现“编译时用的是新头文件、运行时用的是旧库”这种极难排查的问题。5.2 关键配置参数如何影响建图效果跑通只是第一步想针对自己的雷达和数据调优你得知道 lua 文件里每个参数大概在干嘛。打开~/catkin_ws/src/cartographer_ros/configuration_files/trajectory_builder_2d.lua我个人认为最核心的是这几个min_range/max_range雷达有效距离范围和你的传感器量程要对应。一般 2D 雷达设置 0.3 到 30 米即可。设大了会把远处的噪声点带进来设小了会丢有效特征。use_online_correlative_scan_matching是否开启实时相关性扫描匹配。它先把局部地图与当前扫描做暴力匹配得到粗位姿再交给 ceres 做精细优化。开着能明显提升机器人快速旋转时的鲁棒性代价是 CPU 消耗变大。桌面级 CPU 建议开着。ceres_scan_matcher.translation_weight/rotation_weightceres 优化时平移和旋转的权重。如果机器人底盘打滑轨迹容易漂可以适当降低 rotation_weight让优化更信任激光匹配结果。反过来如果激光在走廊这种退化场景里容易沿走廊方向漂可以稍微提高 translation_weight 或配合后端回环。submaps.num_range_data一个 submap 包含多少帧激光数据后再继续构建下一个 submap。这个数值太小submap 数量变多计算量增大太大单个 submap 内部误差累积变大回环修正时处理起来更吃力。当面场景比较空旷时可以适当调大。motion_filter.max_time_seconds/max_distance_meters/max_angle_radians控制每隔多久、走多远、转多大角度才插入一帧。机器人长时间原地不动时这个过滤器能避免插入大量冗余关键帧降低计算量。原地旋转调试机器人时如果发现地图总在抖可以稍微把这几个阈值调大一点。我不建议你一次性把所有参数都改了。跑官方数据集时用默认参数本身就能出很好的结果。想调参就在自己的小车上逐个参数做横向对比固定其他参数只改一个看地图和轨迹的变化每次只改一处便于定位是哪个参数引起的。5.3 实操心得跑通之后怎么验证结果是否可靠很多人跑完官方数据集看到 RViz 里出现地图就以为完事了其实不够。我更推荐做几件额外的验证第一观察回环闭合的瞬间。回环闭合是 Cartographer 最漂亮也最关键的机制——当机器人经过之前到过的地方后端检测到与早期 submap 的相似匹配会一次性修正整条轨迹和地图。你可以在 RViz 里把视角拉远盯着地图边缘当 robot 回到起点附近时地图会发生一次整体“拉伸校正”这正是闭环生效的迹象。第二保存地图看占用栅格是否干净。建图结束后用map_server或cartographer_ros自带的命令把当前地图导出为 pgm 和 yaml。在图片里看墙的厚度是否均匀、通道是否连续、有没有大量重影。官方数据集在默认参数下墙体线条会非常锐利。如果你自己的数据跑出来墙体发虚、重影多基本可以判断传感器外参标定或者时间同步还有问题。第三用rostopic echo /tf和rostopic hz /scan检查数据频率。Cartographer 对输入话题频率有一定最低要求低于 5Hz 的激光数据很难建出好图。先确认数据源本身没问题再怀疑算法参数。第四备份配置文件。每换一个数据集我都会复制一份 lua 配置存成单独文件标注数据来源和改动内容。调试机器人时频繁切换场景、换雷达这是救命的习惯。最后分享一点我自己的体会如果你只是第一次跑通官方数据集我建议你先跑 Revo LDS 的 bag看的是后端回环和数据关联如何让轨迹收敛。跑完后心里对“SLAM 是怎么漂、怎么拉回来”会有很直观的感受。然后再跑 backpack 2D体会加入 IMU 和里程计后的稳定感。两次跑通的间隔里不需要写任何代码只需要看懂 lua 配置和 RViz 里的地图、轨迹、submap 三层关系就行。关于安装如果编译到一半报错不要慌先看报错里最后一个库的名字基本就是缺失依赖或者版本冲突。跑过一遍源码编译后你对整个系统的依赖结构就有数了。后面再做更大项目再回到 Cartographer 看源码、加约束、接自己的传感器驱动起点会完全不一样。
返回列表