ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

思岚RPLIDAR A1与Cartographer 2D建图部署实战

思岚RPLIDAR A1与Cartographer 2D建图部署实战 手头有一台吃灰好久的室内小车底盘翻出来一枚思岚RPLIDAR A1激光雷达第一反应就是别让它继续吃灰了。做机器人方向的朋友应该都清楚思岚雷达加上Google开源Cartographer是目前把2D建图跑起来最成熟的组合之一。这篇文章就是我完整的一次“从零部署”记录从硬件接线、驱动安装到Cartographer的编译配置再到实际建图调参和排坑每一步都写得比较细。内容适合几类人刚入坑SLAM、想用激光雷达快速出一张2D地图的新手手上有思岚雷达但一直没跑通Cartographer的爱好者以及准备把Cartographer接到自己小车上、需要一份可参考部署流程的开发者。我会把这次实战里的关键决策、参数选择和踩过的坑都放进来尽量让大家照着操作就能跑通少走弯路。1. 项目整体设计与部署思路1.1 为什么选思岚RPLIDAR Cartographer先说说选型的逻辑。思岚RPLIDAR系列在入门级2D激光雷达里几乎是“默认选项”A1型号几百块就能拿到8米测距范围覆盖室内小场景绰绰有余USB口直接出数据ROS驱动也是官方维护对新手极度友好。A2/A3型号精度更高、测距更远但部署流程基本一致所以这篇用A1做范例换A2也一样跑。Cartographer则是另一个维度的问题。早期很多人用Gmapping做2D建图但它对里程计依赖重回环检测基本靠运气地图稍微大点就容易错位。Cartographer不一样它引入了submap子图和回环优化机制激光匹配不依赖强里程计即使没有IMU和轮式编码器纯靠激光也能把图建起来这对没有现成底盘的玩家来说就是“救命稻草”。我这次没有用完整底盘的方案而是打算先把雷达接入系统让Cartographer以“手持雷达”模式跑通建图验证效果后再往小车上移植。纯激光模式虽然对运动速度敏感但能节省大量时间不用先去调里程计特别适合验证算法和熟悉整个部署链路。1.2 系统架构与数据流向整个系统的数据流其实很清晰思岚RPLIDAR A1通过USB串口接入主机rplidar_ros驱动节点读取原始测距数据发布ROS标准话题/scansensor_msgs/LaserScan。Cartographer节点订阅/scan内部先做点云畸变校正和子图匹配输出机器人位姿/tf和子图栅格数据。cartographer_occupancy_grid_node把子图拼成完整栅格地图发布到/map话题。保存时用map_server的map_saver订阅/map生成pgm和yaml文件。这套架构里最关键的逻辑是先解决数据源头雷达再解决坐标关系TF最后才是算法。之前很多朋友一上来就编译Cartographer结果雷达数据都还没看最后排查半天才发现问题在驱动层。正确的顺序应该是把雷达数据在rviz里看到清晰、稳定的扫阴影后再开始跑Cartographer。2. 硬件连接与雷达驱动部署2.1 硬件清单与连接细节我用的设备如下设备型号/参数备注激光雷达思岚RPLIDAR A18米测距10Hz扫描USB转串口线开发主机笔记本电脑Ubuntu 20.04预装ROS NoeticUSB转串口CP2102芯片雷达原厂线自带也可另购可选移动底盘/舵机云台本次验证阶段未接连接上没什么玄学USB线插上就能识别。这里要特别提醒一个坑RPLIDAR A1工作时电流不低如果电脑USB口供电不足会出现雷达转一会停一下、或者扫描数据有断层的现象。我试过扩展坞的USB口供电明显不稳后来直接插笔记本原生USB口才稳定。如果你在台式机前面板USB口遇到同样问题换到后置面板的口一般能解决。如果还不行就外接一个5V/2A的独立供电把雷达的红黑线接到电源上USB只做数据通信用。2.2 ROS工作空间与驱动安装在开始之前确认你已经装好ROS。我这边用的是NoeticUbuntu 20.04。先创建工作空间并下载思岚官方驱动mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone https://github.com/Slamtec/rplidar_ros.git cd ~/catkin_ws catkin_make source ~/catkin_ws/devel/setup.bash如果编译报错找不到serial或tf2相关包先补依赖sudo apt install ros-noetic-serial ros-noetic-tf2-geometry-msgs然后重新catkin_make。思岚官方仓库对ROS版本兼容做得不错我在Noetic下没有遇到大坑但老版本可能依赖旧接口我建议clone最新的master分支。2.3 启动雷达并验证扫描数据启动前先确认系统识别到了串口ls -l /dev/ttyUSB0如果显示当前用户没有读写权限执行sudo usermod -aG dialout $USER然后注销重新登录或者重新插拔设备。强烈建议不要用sudo chmod 777来绕过因为每次重启都要重新设置加用户组才是长期生效的方式。启动A1雷达roslaunch rplidar_ros rplidar_a1.launch正常启动后终端会看到雷达转速信息然后可以检查话题数据rostopic echo /scan能看到几百个点组成的LaserScan消息range数组里有具体的距离值。再把rviz拉起来添加一个LaserScan显示Fixed Frame选laser_frame或者base_link如果一切正常屏幕上就应该出现一个以雷达为中心的圆形扫描区域边缘是墙壁、桌腿的轮廓。这一步务必确认两个东西第一扫描轮廓外形要和实际房间一致第二雷达旋转方向是否和预期一致。如果轮廓严重畸变或者方向颠倒后面Cartographer出来的地图基本没法用先在这层排查清楚。3. Cartographer编译安装与工程配置3.1 依赖安装与编译顺序Cartographer的编译是很多人的噩梦难点不在它本身多复杂而在于依赖链比较多。我梳理一下最稳妥的安装顺序。首先是系统依赖直接装sudo apt-get update sudo apt-get install -y \ clang \ cmake \ ninja-build \ git \ libboost-all-dev \ libcairo2-dev \ libeigen3-dev \ libgflags-dev \ libgoogle-glog-dev \ liblua5.3-dev \ libsuitesparse-dev \ libceres-dev \ libprotobuf-dev \ protobuf-compiler \ python3-sphinx \ ros-noetic-usb-cam注意liblua5.3-dev和libceres-dev这两个包版本不对会导致后期编译失败。我先安装系统默认版本编译Cartographer时遇到abseil相关错误再去单独处理。Cartographer源码仓库里有个scripts目录里面有install_abseil.sh脚本推荐用它装特定版本的Abseilgit clone https://github.com/cartographer-project/cartographer.git cd cartographer bash scripts/install_abseil.sh这个脚本会把Abseil装到/usr/local注意它不会卸载系统自带的旧版Abseil如果系统里已经有冲突版本建议先把系统absl卸载掉再跑这个脚本否则会出现链接时找到两个版本的问题。我编译时就遇到过undefined reference后来清理干净重装就好了。3.2 编译cartographer与cartographer_ros编译Cartographer本体cd cartographer mkdir build cd build cmake .. -G Ninja ninja sudo ninja install这一步顺利的话Cartographer核心库就装好了。接下来编译ROS封装层。把cartographer_ros放到catkin工作空间的src目录下同时把cartographer本体也放到src目录这是为了让catkin_make自动找到依赖cd ~/catkin_ws/src git clone https://github.com/cartographer-project/cartographer_ros.git cd .. rosdep update rosdep install --from-paths src --ignore-src --rosdistro${ROS_DISTRO} -y catkin_makerosdep这步如果提示缺少依赖它会直接把需要的apt包列出来照着装就行。编译完成后建议先跑官方demo验证安装是否成功。官方demo包里有一个revo_pls的bag文件对于只是想确认Cartographer能否正常跑起来的人非常有价值。roslaunch cartographer_ros demo_revo_pls.launch如果网络下载bag不方便也可以跳过这一步直接进入自己的雷达配置。不过我还是建议把这个测试跑通因为它能帮你判断前面编译的环境是否可靠后面出了问题也知道不是Cartographer本身的锅。3.3 创建自己的雷达建图工程包我不喜欢直接改cartographer_ros里面的文件而是新建一个自己的包这样方便管理配置和launch文件。cd ~/catkin_ws/src catkin_create_pkg my_cartographer roscpp sensor_msgs nav_msgs tf2在my_cartographer包下创建config和launch两个目录。config存放lua配置文件launch存放启动文件。后面所有自定义配置都放这里。4. 2D建图实战与参数调优4.1 编写launch和lua配置先用一个launch文件把雷达和Cartographer串起来。核心内容如下launch !-- 启动思岚雷达 -- include file$(find rplidar_ros)/launch/rplidar_a1.launch / !-- 启动cartographer主节点 -- node namecartographer_node pkgcartographer_ros typecartographer_node args-configuration_directory $(find my_cartographer)/config -configuration_basename my_lidar_2d.lua outputscreen /node !-- 启动栅格地图发布节点 -- node namecartographer_occupancy_grid_node pkgcartographer_ros typecartographer_occupancy_grid_node args-resolution 0.05 / /launch这个launch里最重要的是occupancy_grid_node没有它Cartographer只发布内部的submap和位姿不会发布我们最终需要的/map栅格话题后面map_saver也就没有数据可以保存。再写一个lua配置文件这是整个建图效果的核心。我直接贴出我在手持雷达场景下验证可用的一份配置include map_builder.lua include trajectory_builder.lua options { map_builder MAP_BUILDER, trajectory_builder TRAJECTORY_BUILDER, map_frame map, tracking_frame base_link, published_frame base_link, odom_frame odom, provide_odom_frame true, publish_frame_projected_to_2d true, use_odometry false, use_nav_sat false, use_landmarks false, num_laser_scans 1, num_subdivisions_per_laser_scan 1, num_point_clouds 0, lookup_transform_timeout_sec 0.2, submap_publish_period_sec 0.3, pose_publish_period_sec 5e-3, trajectory_publish_period_sec 30e-3, } MAP_BUILDER.use_trajectory_builder_2d true TRAJECTORY_BUILDER_2D.use_imu_data false TRAJECTORY_BUILDER_2D.use_online_correlative_scan_matching true TRAJECTORY_BUILDER_2D.min_range 0.1 TRAJECTORY_BUILDER_2D.max_range 8.0 TRAJECTORY_BUILDER_2D.missing_data_ray_length 5.0 TRAJECTORY_BUILDER_2D.num_accumulated_range_data 10 SPARSE_POSE_GRAPH.optimize_every_n_nodes 90 SPARSE_POSE_GRAPH.global_sampling_ratio 0.003简单解释几个关键参数provide_odom_frame true 表示我没接外部里程计让Cartographer自己维护map到odom的坐标变换这样TF树才是完整的。use_odometry false 和 use_imu_data false 是因为纯手持雷达模式下没有这两个传感器。如果你后面接入底盘需要改成true并且提供对应的topic。min_range和max_range要根据雷达量程调整A1标称8米我建议max_range设7.5米左右太接近标称上限容易出现不稳定噪点。num_accumulated_range_data表示累积多少帧激光数据做一次匹配。这个值越大建图越平滑但运动快了容易产生拖影越小越灵敏但噪声更大。手持模式下我取10。4.2 启动建图与实时建议配置完成后一个终端启动雷达和Cartographersource ~/catkin_ws/devel/setup.bash roslaunch my_cartographer main.launch另一个终端打开rvizrvizFixed Frame选map添加Map、LaserScan、PoseArray和TF显示。如果一切正常屏幕上会实时看到雷达扫出的轮廓以及Cartographer估计出来的机器人轨迹红色轨迹线。手持雷达慢慢在室内走一圈地图会一点点被“画”出来。这里要重点说建图手法。激光雷达对运动很敏感特别是手持纯激光模式没有里程计辅助运动太急会让激光匹配直接发散。我摸索出来的正确姿势启动前先把雷达拿稳原地缓慢旋转一圈让Cartographer有足够的初始观测来建立第一块子图。移动时保持匀速、慢速避免突然加速、急转弯。走到拐角处稍微放慢让雷达充分扫描到新区域的特征。尽量走一个闭合回路比如绕客厅一圈回到起点这样回环检测能修正之前累积的漂移。如果地图出现局部错位、断裂不要急着改参数先检查运动是否太粗暴。很多新手建图失败是因为拿着雷达来回甩这就像闭着眼睛走路神仙算法也救不回来。4.3 保存地图建图完成后先停掉轨迹再保存状态最后用map_saver导出pgm。rosservice call /finish_trajectory 0 rosservice call /write_state {filename: /home/user/map.pbstream}这两步做完Cartographer会把最终优化后的地图状态写入pbstream文件。接下来用map_saver订阅/map话题保存栅格地图roscd my_cartographer rosrun map_server map_saver -f ~/maps/my_map这会在~/maps目录下生成my_map.pgm和my_map.yaml。yaml文件里包含了分辨率、原点坐标、占用阈值等信息这就是后续做导航定位要用的地图文件。5. 常见问题与排查技巧实录5.1 雷达数据层问题现象原因解决方案雷达不转或转一会停USB供电不足换原生USB口或独立5V供电/dev/ttyUSB0不存在没插好或驱动缺重新插拔安装CP2102驱动rviz看不到扫描数据串口权限不足把用户加入dialout组数据有大量NaN或Inf雷达被遮挡或转数异常检查遮挡重启雷达节点特别提一下串口权限问题。很多人启动雷达时看到权限报错网上随手搜到chmod 777就用了然后下次开机又报错非常低效。正确做法是加dialout组一劳永逸。如果加完重新登录还没生效可以考虑重启。5.2 Cartographer配置与TF问题TF坐标树不完整是我见过出现频率最高的运行时报错。启动后终端刷出一堆Unknown frame_id [laser_frame]或者“Could not find frame”的提示基本都是雷达的laser_frame到base_link这条变换链没建立。思岚官方驱动里会广播laser_frame到base_link的静态变换但如果你改了frame名或者数据源不是官方launch启动的就需要手动加一个static_transform_publishernode pkgtf2_ros typestatic_transform_publisher args0 0 0.1 0 0 0 base_link laser_frame /这里平移量是雷达在机器人坐标系里的安装位置根据实际情况改。手持雷达模式下我一般把雷达坐标系和base_link重合用一个全零的静态变换也行。5.3 建图漂移发散建图漂移是另一个高频问题表现是轨迹和地图重叠不上或者地图线条越来越模糊。排查顺序应该是先确认运动是否过快。纯激光模式下雷达扫到的特征少运动一快就容易匹配失败表现为轨迹乱跳。检查雷达是否长期面对空旷区域。比如走到一面白墙前面激光射出去没有返回有效点Cartographer没有特征可匹配漂移几乎必然发生。尝试调整参数提升匹配稳定性。参数层面我习惯先动这几个TRAJECTORY_BUILDER_2D.num_accumulated_range_data 15 TRAJECTORY_BUILDER_2D.use_online_correlative_scan_matching true SPARSE_POSE_GRAPH.optimize_every_n_nodes 50增大累积帧数相当于让每一帧“更厚”匹配更稳把优化节点数调低则让全局优化更频繁地图整体更一致但CPU开销会增大。如果你发现CPU占用已经吃满就别再降优化节点而是压缩scan频率或者降低submap_publish_period_sec。5.4 CPU占用过高Cartographer的实时回环检测非常吃CPU我笔记本跑起来有时候能到60%-80%占用。如果觉得卡可以做的操作在lua里把pose_publish_period_sec调大比如1e-3改成1e-2减少视觉节点的刷新开销。把submap_publish_period_sec从0.3调成0.5降低地图发布频率。如果雷达支持调速把扫描频率从10Hz降到5Hz匹配频率下降CPU立刻降下来。这道菜就是“以牺牲实时刷新换取流畅度”对静态建图场景影响不大。6. 踩坑心得与后续扩展建议6.1 这次部署最值得分享的三个教训第一雷达数据必须优先验证。我一开始图省事直接把雷达接到Cartographer结果地图乱七八糟折腾了一晚上发现是雷达USB供电不稳数据本身就断续。把雷达数据在rviz里摆正、确认稳定这是整个项目性价比最高的一步。第二配置参数一次只改一个。lua里参数太多如果同时改了好几个出了问题根本不知道是哪个引起的。我后来养成一个习惯每次只动一个参数建图一小段看效果再决定下一步。虽然慢但每个参数的作用都摸得很清楚。第三不要迷信别人的参数。网上能找到很多现成lua配置但那都是基于特定机器人和雷达的传感器安装位置、雷达量程、使用场景都不一样。配置可以抄但一定要结合自己的设备重新过滤一遍关键参数尤其是min_range、max_range和num_accumulated_range_data。6.2 后续扩展方向这套部署跑通之后下一步可以做很多事把雷达装到差速小车上接入轮式里程计use_odometry改为true建图质量和速度会明显提升。加一个IMU即便只有重力方向信息也能提升纯激光模式下的姿态估计稳定度。把保存下来的map.pbstream用于Cartographer的定位模式能实现已知地图下的重定位相当于给机器人加了“知道自己在哪里”的能力。如果你也用手持雷达跑通了这套流程我建议下一步务必试试接入里程计。同样是这套包只是加一个底盘编码器的/odom数据建图的手感会完全不一样机器人走起来也不用像手持那样小心翼翼。这算是我个人实战里感受最深的一段与其在一开始就追求高精度传感器不如先用最朴素的雷达把整套流程走通再像积木一样逐层加码。思岚雷达的稳定性和Cartographer的鲁棒性确实是被时间验证过的组合。
返回列表