2. 使用hector_slam构建无里程计地图

任务目标

在无里程计(Odometry)信息的场景下,仅依赖激光雷达(LiDAR)的扫描数据,使用 hector_slam 功能包实时构建二维栅格地图,并评估建图质量与漂移程度。本案例不涉及机器人底盘运动控制,聚焦于纯激光SLAM的最小可复现闭环。

环境与依赖

  • Ubuntu 20.04 + ROS Noetic(或 Ubuntu 18.04 + ROS Melodic)
  • 已安装 hector_slam:sudo apt install ros-${ROS_DISTRO}-hector-slam
  • 激光雷达驱动节点(本案例使用 gazebo 仿真环境提供激光数据,也可替换为真实雷达驱动)

核心实现

本案例的核心是配置 hector_slam 的启动文件,使其在无里程计输入时仅订阅激光话题 /scan 并发布地图。关键参数为 pub_map_odom_transform 与 map_frame 的设置,确保TF树中仅存在 map → laser 的变换。

<!-- hector_slam_no_odom.launch -->
<launch>
  <!-- 激光雷达驱动(仿真示例,实际使用时替换为真实驱动) -->
  <include file="$(find gazebo_ros)/launch/empty_world.launch">
    <arg name="paused" value="false"/>
  </include>
  <node name="spawn_robot" pkg="gazebo_ros" type="spawn_model"
        args="-urdf -model robot -param robot_description -x 0 -y 0 -z 0.1"/>

  <!-- 激光雷达节点(发布 /scan) -->
  <node name="laser_driver" pkg="hector_slam" type="laser_scan_publisher" output="screen"/>

  <!-- hector_slam 核心节点 -->
  <node pkg="hector_slam" type="hector_mapping" name="hector_mapping" output="screen">
    <param name="pub_map_odom_transform" value="false"/>
    <param name="map_frame" value="map"/>
    <param name="odom_frame" value="odom"/>
    <param name="base_frame" value="base_link"/gt;
    <param name="scan_topic" value="scan"/>
    <param name="map_resolution" value="0.05"/>
    <param name="map_size" value="2048"/>
    <param name="map_start_x" value="0.5"/>
    <param name="map_start_y" value="0.5"/>
    <param name="map_multi_res_levels" value="3"/>
    <param name="update_factor_free" value="0.4"/>
    <param name="update_factor_occupied" value="0.9"/>
    <param name="use_tf_scan_transformation" value="true"/>
    <param name="use_tf_pose_start_estimate" value="false"/>
    <param name="pub_map_scanmatch_transform" value="true"/>
    <param name="tf_map_scanmatch_transform_frame_name" value="scanmatcher_frame"/>
  </node>

  <!-- 地图保存服务 -->
  <node pkg="tf2_ros" type="static_transform_publisher" name="map_to_scanmatcher"
        args="0 0 0 0 0 0 map scanmatcher_frame"/>
</launch>

运行与验证

  1. 启动SLAM:roslaunch hector_slam hector_slam_no_odom.launch
  2. 控制机器人运动(仿真中通过键盘或脚本发布速度指令,使激光雷达扫描到不同区域):
    rostopic pub -r 10 /cmd_vel geometry_msgs/Twist '{linear: {x: 0.2}, angular: {z: 0.3}}'
  3. 观察地图:运行 rviz,添加 Map 显示,话题选择 /map。
  4. 保存地图:rosrun map_server map_saver -f ~/result_map

性能评估方法

  • 定性评估:在RViz中观察地图是否出现重影、错位或漂移。无里程计场景下,hector_slam依赖激光扫描匹配,在快速旋转或长直走廊中易产生累积漂移。
  • 定量评估:将保存的 result_map.pgm 与真实环境布局对比,测量已知障碍物(如墙角、柱子)的坐标误差。若环境中存在闭环路径,可观察地图首尾是否对齐。
  • 通过条件:地图轮廓清晰可辨,无大面积黑色错误占用;机器人绕行一圈后地图无明显错位(误差 < 0.5m);地图分辨率与设置的 map_resolution 一致。

常见问题

  • 地图不更新:检查 /scan 话题是否有数据,以及TF树中 map → base_link 变换是否由 hector_mapping 发布(使用 tf_echo map base_link 查看)。
  • 漂移过大:降低机器人运动速度,增大 map_multi_res_levels 至3或4,或减小 map_resolution 至0.025以提升匹配精度。
  • 启动崩溃:确认 hector_slam 版本与ROS发行版匹配,且激光话题类型为 sensor_msgs/LaserScan。