Skip to content

SLAM - 同时定位与建图

SLAM(Simultaneous Localization and Mapping)是机器人自主导航的核心技术,它使机器人能够在未知环境中同时构建地图并确定自身位置。

什么是 SLAM?

┌─────────────────────────────────────────────────────────────┐
│                    SLAM 问题定义                             │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  输入:                                                     │
│    - 传感器数据(激光雷达、相机、IMU)                       │
│    - 里程计数据(轮式编码器、视觉里程计)                    │
│                                                             │
│  输出:                                                     │
│    - 环境地图(2D/3D)                                      │
│    - 机器人位姿(位置和方向)                                │
│                                                             │
│  挑战:                                                     │
│    - 传感器噪声                                             │
│    - 累积误差                                               │
│    - 动态环境                                               │
│    - 计算复杂度                                             │
│                                                             │
└─────────────────────────────────────────────────────────────┘

SLAM 算法分类

基于激光雷达的 SLAM

算法 特点 适用场景
gmapping 2D 激光 SLAM,基于粒子滤波 室内环境,小范围
cartographer Google 开发,2D/3D SLAM 室内外,大范围
hector_slam 无需里程计 无人机、手持设备
karto_slam 基于图优化 大规模环境

基于视觉的 SLAM

算法 特点 适用场景
ORB-SLAM 特征点法 室内外通用
LSD-SLAM 直接法 纹理丰富环境
DSO 直接稀疏里程计 高精度定位
RTAB-Map 视觉+激光融合 多传感器融合

在 ROS 中使用 SLAM

1. gmapping

gmapping 是最常用的 2D 激光 SLAM 算法。

安装

sudo apt install ros-noetic-gmapping

使用

# 启动 gmapping
roslaunch gmapping demo.launch

# 保存地图
rosrun map_server map_saver -f my_map

配置参数

<launch>
  <node name="gmapping" pkg="gmapping" type="slam_gmapping">
    <param name="base_frame" value="base_link"/>
    <param name="odom_frame" value="odom"/>
    <param name="map_frame" value="map"/>
    <param name="xmin" value="-25.0"/>
    <param name="xmax" value="25.0"/>
    <param name="ymin" value="-25.0"/>
    <param name="ymax" value="25.0"/>
    <param name="delta" value="0.05"/>
    <param name="maxUrange" value="12.0"/>
    <param name="maxRange" value="12.0"/>
  </node>
</launch>

2. cartographer

cartographer 是 Google 开发的 SLAM 系统,支持 2D 和 3D SLAM。

安装

sudo apt install ros-noetic-cartographer
sudo apt install ros-noetic-cartographer-ros

使用

# 2D SLAM
roslaunch cartographer_ros demo_backpack_2d.launch

# 3D SLAM
roslaunch cartographer_ros demo_backpack_3d.launch

# 保存地图
rosrun cartographer_ros cartographer_assets_writer - \
  -configuration_directory /path/to/config \
  -configuration_basename assets_writer.lua

配置文件

-- backpack_2d.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 = "odom",
  odom_frame = "odom",
  provide_odom_frame = false,
  publish_frame_projected_to_2d = true,
  use_odometry = true,
  use_nav_sat = false,
  use_landmarks = false,
  num_laser_scans = 1,
  num_multi_echo_laser_scans = 0,
  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.min_range = 0.3
TRAJECTORY_BUILDER_2D.max_range = 8.
TRAJECTORY_BUILDER_2D.missing_data_ray_length = 1.
TRAJECTORY_BUILDER_2D.use_imu_data = false
TRAJECTORY_BUILDER_2D.use_online_correlative_scan_matching = true
TRAJECTORY_BUILDER_2D.real_time_correlative_scan_matcher.linear_search_window = 0.1
TRAJECTORY_BUILDER_2D.real_time_correlative_scan_matcher.angular_search_window = math.rad(20.)

return options

3. RTAB-Map

RTAB-Map 是一个支持多传感器融合的 SLAM 系统。

安装

sudo apt install ros-noetic-rtabmap-ros

使用

# 使用激光雷达
roslaunch rtabmap_ros rtabmap.launch \
  laser_scan:=/scan \
  frame_id:=base_link

# 使用 RGB-D 相机
roslaunch rtabmap_ros rtabmap.launch \
  rgb_topic:=/camera/rgb/image_raw \
  depth_topic:=/camera/depth/image_raw \
  camera_info_topic:=/camera/rgb/camera_info

# 保存地图
rosrun map_server map_saver -f my_map

SLAM 实践步骤

步骤 1:准备传感器

# 检查激光雷达
rostopic echo /scan

# 检查里程计
rostopic echo /odom

# 检查 TF
rosrun tf view_frames

步骤 2:启动 SLAM

# 启动机器人
roslaunch my_robot bringup.launch

# 启动 SLAM
roslaunch gmapping slam.launch

# 启动 RViz 可视化
roslaunch my_robot rviz.launch

步骤 3:建图

# 使用键盘控制机器人移动
rosrun teleop_twist_keyboard teleop_twist_keyboard.py

# 在 RViz 中观察地图构建过程

步骤 4:保存地图

# 保存地图
rosrun map_server map_saver -f my_map

# 生成文件
# my_map.pgm  (地图图像)
# my_map.yaml (地图配置)

步骤 5:加载地图

# 加载地图
roslaunch map_server map_server.launch map_file:=/path/to/my_map.yaml

SLAM 调优技巧

1. 参数调优

# gmapping 参数
maxUrange: 激光雷达最大有效范围
particles: 粒子数量(越多越精确,但越慢)
delta: 地图分辨率
xmin/xmax/ymin/ymax: 地图范围

2. 传感器校准

# 检查 TF 树
rosrun tf view_frames

# 检查坐标变换
rosrun tf tf_echo /base_link /laser

3. 里程计校准

# 检查里程计精度
rostopic echo /odom

# 校准轮子间距和轮子半径

SLAM 评估

1. 视觉评估

在 RViz 中观察: - 地图是否一致 - 是否有重影 - 是否有闭环

2. 定量评估

使用 slam_eval 工具:

# 安装
sudo apt install ros-noetic-slam-eval

# 评估
rosrun slam_eval eval map1.yaml map2.yaml

常见问题

1. 地图漂移

原因:里程计误差累积

解决方案: - 增加闭环检测 - 使用更好的里程计(视觉里程计、IMU) - 减小粒子数量

2. 地图重影

原因:机器人移动过快或传感器噪声

解决方案: - 降低机器人移动速度 - 增加扫描匹配参数 - 使用更好的传感器

3. 计算资源不足

原因:粒子数量过多或地图范围过大

解决方案: - 减小粒子数量 - 减小地图范围 - 使用更高效的算法(cartographer)

实验

Lab 4: SLAM

  1. 启动 SLAM 系统
  2. 使用键盘控制机器人建图
  3. 保存地图
  4. 评估地图质量

下一步

参考资源