跳转至

31. 激光雷达与二维建图

本章默认读者已经完成第 29 章的传感器话题检查和第 30 章的里程计、TF、时间检查。接下来只解决两个问题:底层驱动送上来的数据,能不能按二维 SLAM 需要的格式被正确解释;不同二维 SLAM 算法有什么区别,应该怎样选择和迁移。最后用一次短路线实测验证输入和算法结果。

本章讨论单线或已经转换为二维扫描的激光雷达,以及使用 ROS 2 话题进行数据交换的二维建图算法。多线雷达的三维建图、视觉建图和后续导航规划不属于本章主线。

31.1 从雷达话题到 SLAM 输入

第 29、30 章确认的是“设备和 ROS 2 链路在运行”。本章还要确认“上层算法收到的数据含义和格式正确”。驱动节点与 SLAM 节点通常通过 ROS 2 话题交换消息,常见输入契约如下:

输入 常见话题名称 消息类型或接口 用途
二维扫描 /scan、/lidar/scan sensor_msgs/msg/LaserScan 角度数组和距离数组;header.stamp、header.frame_id 必须有效
轮式里程计 /odom、/odometry/filtered nav_msgs/msg/Odometry 车体短时位姿和速度;frame_id、child_frame_id 要与 TF 一致
动态坐标变换 /tf tf2_msgs/msg/TFMessage 随时间变化的关系,例如 odom → base_link
静态坐标变换 /tf_static tf2_msgs/msg/TFMessage 固定安装关系,例如 base_link → laser

这些字段不是“有值就行”:ranges[i] 必须对应 angle_min + i × angle_increment 的测量方向,距离单位通常是米,无效值要符合消息约定;时间戳要能让算法把扫描和同一时刻的 TF 对上。不同算法对里程计、IMU 等辅助输入的要求不同,但二维 SLAM 至少要能获得有效的 LaserScan 和从雷达坐标系到机器人机体坐标系的 TF。只存在 /scan,没有 TF 或时间信息,不能直接视为满足建图条件。

先检查话题和数据格式是否匹配

先查看当前系统实际存在的节点和话题:

ros2 node list
ros2 topic list -t

再分别检查雷达和里程计:

ros2 topic info /scan --verbose
ros2 topic echo --once /scan
ros2 topic info /odom --verbose
ros2 topic echo --once /odom

第 29、30 章已经介绍了命令和检查方法,本章只强调与 SLAM 输入契约直接相关的结果:

  1. 话题名称和消息类型能否与目标算法的订阅参数对应;
  2. LaserScan 的角度、量程、距离单位、无效值、时间戳和 frame_id 是否符合消息语义;
  3. 里程计的 frame_id、child_frame_id、速度方向和频率是否与 odom → base_link 一致;
  4. /tf、/tf_static 是否能在扫描时间戳处提供完整变换,发布端 QoS 是否兼容;
  5. 算法需要的附加输入(连续里程计或 IMU)是否真的存在,而不是只在参数文件中填写了名称。

可以用下面的命令确认 TF 是否连通:

ros2 run tf2_ros tf2_echo base_link laser

其中 base_link 和 laser 只是常见示例,实际名称必须替换成消息和 TF 中使用的坐标名。若机器人使用 base_footprint 或其他雷达坐标名,应按实际系统替换。

31.2 输入不匹配时怎样调整

发现雷达有数据但 SLAM 不工作时,不要先盲目调整地图参数。先判断不匹配发生在哪一层:

现象 常见原因 优先处理方式
SLAM 订阅 /scan,驱动实际发布 /lidar/scan 只有话题名称不同 在 Launch 或参数中修改扫描话题,或使用重映射
消息类型不是 LaserScan 驱动发布点云或厂商自定义消息 使用厂家 ROS 2 驱动的二维扫描输出,或增加转换/适配节点,例如把点云转换为 LaserScan
frame_id 与 TF 中的名称不同 坐标命名或静态 TF 配置不一致 修正驱动参数、静态 TF 或 SLAM 的 frame 参数,不要随意改写真实安装方向
有扫描但提示找不到变换 缺少 base_link → laser 或 odom → base_link 补充正确的静态或动态 TF,并确认每条变换只有一个发布者
话题存在但 SLAM 收不到 QoS 不兼容、节点未真正订阅或命名空间不同 用 ros2 topic info --verbose 检查端点和 QoS,再修改订阅端配置或重映射
地图出现跳变或撕裂 时间戳停滞、时间基准不同、里程计方向错误或车轮打滑 先修复时间、TF 和里程计,再调整 SLAM 参数

话题重映射

如果只是发布的话题名称不同,所需的数据无需改动,可以保持驱动不变,在启动 SLAM 时重映射:

ros2 run <slam_package> <slam_executable> --ros-args \
  -r scan:=/lidar/scan

重映射只改变 ROS 2 图中的名称,不会改变消息内容。若消息类型、单位或坐标含义不一致,单纯重映射不能解决问题。

数据转换和适配

如果新雷达只发布 sensor_msgs/msg/PointCloud2,而二维 SLAM 只接受 sensor_msgs/msg/LaserScan,需要使用支持的转换节点或编写适配节点。适配节点至少要明确:投影平面、角度范围、量程、无效值、时间戳和输出 frame_id。如果里程计是厂商自定义消息,也要先转换成算法能够订阅的标准或约定接口。适配完成后,仍要重新执行第 29 章的节点、话题、频率、时间和坐标检查。

31.3 常见二维建图算法

二维 SLAM 的共同原理可以分成两步:前端根据相邻扫描(以及可选的里程计、IMU)估计机器人移动了多少,后端把这些位姿和扫描组织起来,逐步生成地图,并在回到旧区域时做闭环修正。不同算法的差别,主要在于怎样做扫描匹配、怎样表示和优化位姿、对里程计依赖多大,以及是否方便在 ROS 2 中维护。下面比较常见方案的工程差异,不把某一种算法宣传成所有场景的最佳答案。

算法 主要估计方法 对输入的典型要求 工程取舍
slam_toolbox 扫描匹配 + 位姿图优化;支持在线建图、继续建图和序列化地图 LaserScan、雷达 TF;通常配合连续里程计 ROS 2 集成直接,参数和保存流程清晰,适合作为首个验证方案
GMapping Rao-Blackwellized 粒子滤波;每个粒子代表一条可能的轨迹和地图 LaserScan、雷达 TF;较依赖里程计质量 经典资料多,但 ROS 2 可用性依发行版和移植包而定,不能直接照搬 ROS 1 命令
Cartographer 局部扫描匹配 + 子地图 + 全局位姿图优化,可扩展到三维 LaserScan,按配置使用里程计、IMU 等辅助输入 闭环和大场景能力较强,但配置项多、资源开销和调参成本较高
Hector SLAM 主要依靠高频激光扫描做实时匹配,弱化对轮式里程计的依赖 高频、时间稳定的 LaserScan 和正确雷达 TF 适合里程计质量有限但雷达频率高的场景;ROS 2 支持和维护状态需按发行版确认

可以这样理解四种方案的侧重点:slam_toolbox 重视 ROS 2 工程集成和位姿图维护;GMapping 用粒子表示轨迹不确定性,对里程计更敏感;Cartographer 把局部子地图和全局闭环结合起来,适合更复杂场景但配置更重;Hector SLAM 尽量依靠高频雷达本身,里程计要求相对低,但对扫描频率、时间稳定性和环境特征更敏感。

选择时先看三个条件:当前 ROS 2 发行版是否有可安装的驱动包、机器人能否提供算法所需的输入、团队是否能维护其参数和故障排查流程。首次建图优先选择输入要求明确、日志可读、保存和重新加载流程已验证的方案。

31.4 迁移或替换建图算法

从一种二维 SLAM 换成另一种时,通常不需要更换雷达硬件或雷达驱动。只要新算法仍接受相同的 LaserScan、TF 和里程计接口,就可以保留第 29、30 章已经验证的底层链路,主要替换 SLAM 节点及其配置。真正需要重新确认的是“新算法如何解释这些接口”,而不是重新制作一套传感器数据。迁移按以下顺序进行:

  1. 确认 ROS 2 支持:核对目标发行版、安装包、依赖和可执行节点,不要直接使用 ROS 1 的 Launch 或参数文件;
  2. 列出输入契约:记录扫描话题、消息类型、需要的 TF、里程计/IMU 输入、QoS 和最低频率,并写清每个字段的单位和坐标含义;
  3. 建立参数映射:将旧算法的 base_frame、odom_frame、map_frame、扫描话题和量程参数,逐项映射到新算法的参数名;不要只复制同名参数;
  4. 检查 TF 发布权:通常由底盘或里程计提供 odom → base_link,SLAM 负责估计 map → odom,传感器安装关系由静态 TF 提供,不能让两个节点同时发布同一段动态 TF;
  5. 确认输出接口:核对地图话题、地图元数据、保存服务或序列化文件格式。若下游导航仍订阅 /map,必要时使用重映射或增加适配;
  6. 先用短路线回放或低速实测:在相同场地比较扫描是否贴合墙面、闭环是否重合、地图比例和 CPU/内存占用;
  7. 重新验收并归档:保存新算法的 Launch、参数、ROS 2 发行版、驱动版本、地图文件和日志,不要沿用旧算法“看起来能用”的配置。

31.5 建图操作步骤

  1. 启动底盘、雷达驱动和必要的 TF,确认 /scan、/odom 和 TF 已通过输入检查。
  2. 只启动一套 SLAM,不要同时运行两个会订阅同一雷达并发布地图或 map → odom 的建图节点。
  3. 在 RViz 中显示扫描、TF 和地图,先原地缓慢转动,确认扫描随机器人姿态变化且没有明显错位。
  4. 低速沿场地边缘行驶,避免急转、长时间原地打滑和遮挡雷达视场。
  5. 回到已经经过的区域,观察墙线是否基本重合。若闭环处出现重影,先回到输入匹配和里程计检查。
  6. 建图完成后停止运动,再使用当前算法或导航框架提供的保存工具保存地图。
  7. 记录地图文件、分辨率、原点、算法名称、参数、Launch、驱动版本和建图日志。

31.6 故障排查

排查顺序保持为:输入话题 → 消息类型和 QoS → 时间戳 → TF → 里程计 → SLAM 参数 → 保存流程。前一层没有证据时,不要直接调整后一层。

现象 优先检查
SLAM 启动但没有地图 扫描话题名称、消息类型、QoS、节点订阅关系和启动参数
地图整体旋转或倾斜 雷达安装方向、frame_id 和静态 TF
地图重影或闭环错位 时间戳、odom → base_link、轮速方向、打滑和扫描频率
转弯处撕裂 机器人速度、角速度、扫描频率和里程计延迟
RViz 看不到地图 地图话题、固定坐标系、map → odom 发布者和 QoS
保存后文件为空或无法加载 保存时机、地图话题、输出路径、文件权限和算法的保存格式

章节导航

上一章:里程计、TF 与时间 · 返回本篇 · 下一章:地图保存、定位与坐标验证