3. ROS2基础:节点、话题、服务、参数等核心概念
在深入SLAM建图源码之前,必须先理解ROS2的四大核心通信原语:节点(Node)、话题(Topic)、服务(Service)和参数(Parameter)。SLAM建图系统本质上就是多个节点通过话题交换传感器数据与位姿信息,通过服务触发建图或保存地图,通过参数调整算法行为。本节将用SLAM场景贯穿讲解这些概念。
3.1 节点:功能模块的独立进程
节点是ROS2中最小的计算单元,一个机器人系统通常由几十个节点组成。每个节点负责一项特定任务,例如激光雷达驱动节点、里程计节点、SLAM建图节点、可视化节点等。节点之间相互独立,通过ROS2的通信机制协作,这种设计带来了故障隔离与模块复用的好处。
在SLAM建图中,典型节点包括:
/laser_driver:发布激光扫描数据/odometry_node:发布轮式里程计/slam_toolbox:执行建图与定位/rviz2:可视化地图与机器人位姿
创建节点时,需要给节点命名。在ROS2中,节点名是全局唯一的标识符,例如启动SLAM建图节点时,命令中会显式指定节点名:
ros2 run slam_toolbox slam_toolbox_node --ros-args -r __node:=slam_node
3.2 话题:异步数据流的通道
话题是ROS2中异步、单向、多对多的通信方式。发布者(Publisher)向话题写入消息,订阅者(Subscriber)从话题读取消息。话题适合传输持续更新的数据流,如激光扫描、图像、里程计等。
SLAM建图的核心数据流如下:
/scan (sensor_msgs/LaserScan)
└──> /slam_toolbox 节点订阅
/odom (nav_msgs/Odometry)
└──> /slam_toolbox 节点订阅
/tf (tf2_msgs/TFMessage)
└──> 所有需要坐标变换的节点订阅
/map (nav_msgs/OccupancyGrid)
└──> /rviz2 可视化节点订阅
话题通信的关键特性是解耦:发布者不知道也不关心谁在订阅,订阅者也不需要知道数据来源。这使得SLAM系统可以灵活替换传感器驱动,例如将2D激光换成3D激光,只要话题类型和消息格式一致,SLAM节点无需修改。
查看当前系统中的话题列表:
ros2 topic list
ros2 topic info /scan
ros2 topic hz /scan # 查看发布频率
3.3 服务:同步请求-应答通信
与话题的异步流不同,服务采用同步请求-应答模式。客户端(Client)发送请求并等待服务器(Server)处理完毕后返回响应。服务适合一次性、需要确认结果的操作,例如触发建图、保存地图、重置SLAM状态等。
在SLAM建图中,典型服务调用包括:
| 服务名称 | 服务类型 | 功能说明 |
|---|---|---|
/slam_toolbox/save_map |
slam_toolbox/save_map |
将当前建图结果保存为地图文件 |
/slam_toolbox/clear_queue |
std_srvs/Empty |
清除等待处理的激光数据队列 |
/slam_toolbox/deserialize_map |
slam_toolbox/deserialize_map |
加载已保存的地图数据 |
调用保存地图服务的命令行方式:
ros2 service call /slam_toolbox/save_map slam_toolbox/save_map "{destination: 'map_data'}"
服务通信的优点是可靠性:客户端能明确知道请求是否成功执行。缺点是阻塞性——如果服务器处理时间较长,客户端会一直等待。因此,服务不适合高频数据流,只适合低频控制指令。
3.4 参数:节点运行时的可配置项
参数是节点的本地配置项,以键值对形式存储。SLAM建图算法中有大量可调参数,例如地图分辨率、激光最大扫描距离、匹配阈值、位姿图优化频率等。通过参数调整,可以在不修改代码的情况下适配不同环境。
SLAM建图常用参数示例:
slam_toolbox:
ros__parameters:
map_resolution: 0.05 # 地图分辨率(米/像素)
max_laser_range: 12.0 # 激光最大有效距离
minimum_time_interval: 0.5 # 两次扫描匹配最小时间间隔
transform_publish_period: 0.05 # TF发布周期(秒)
use_scan_matching: true # 是否启用扫描匹配
loop_search_maximum_distance: 3.0 # 回环检测最大搜索距离
参数可以在启动时通过YAML文件加载,也可以在运行时动态修改:
# 启动时加载参数文件
ros2 run slam_toolbox slam_toolbox_node --ros-args --params-file slam_params.yaml
# 运行时查看参数
ros2 param get /slam_node map_resolution
# 运行时修改参数
ros2 param set /slam_node max_laser_range 15.0
3.5 核心概念关系图解
下图展示了SLAM建图场景中,节点、话题、服务、参数之间的协作关系。激光驱动节点通过话题持续发布扫描数据,SLAM节点订阅这些话题,同时读取参数配置算法行为,并通过服务接口响应外部控制指令,最终将地图通过话题发布给可视化节点。
3.6 综合案例:启动一个最小SLAM建图系统
将上述概念串联起来,启动一个完整的SLAM建图系统通常需要以下步骤:
- 启动传感器驱动节点(发布/scan话题)
- 启动里程计节点(发布/odom话题)
- 启动SLAM建图节点(订阅/scan和/odom,发布/map)
- 启动可视化节点(订阅/map和/tf)
# 终端1:启动激光雷达驱动
ros2 run laser_driver laser_node
# 终端2:启动SLAM建图
ros2 run slam_toolbox slam_toolbox_node --ros-args --params-file slam_params.yaml
# 终端3:启动可视化
ros2 run rviz2 rviz2
系统运行后,可以通过ros2 node list查看所有活跃节点,通过ros2 topic list查看所有话题,通过ros2 service list查看可用服务。这些命令是调试SLAM系统的基础工具。
3.7 误区与复盘
map_resolution如果设置过小(如0.01),会导致地图内存爆炸;设置过大(如0.5),则地图精度不足。修改参数前应查阅对应SLAM算法的文档说明。