LIO-SAM多节点并行改造方案与ROS命名空间实践
1. 项目背景与需求分析
在机器人SLAM(即时定位与地图构建)领域,LIO-SAM作为基于激光雷达-惯性测量单元紧耦合的先进算法,因其高精度和鲁棒性被广泛应用于自动驾驶、移动机器人导航等场景。但在实际部署中,我们常遇到一个关键限制:原生代码架构默认只允许单个节点在ROS master上运行,这在多机器人协同或算法对比测试时会造成严重制约。
上周我在部署一个多AGV仓储系统时就遇到了这个问题——需要同时运行三个LIO-SAM节点分别处理不同区域的建图数据。直接启动多个节点会导致参数命名冲突和话题抢占,最终系统崩溃。经过两天源码级调试,我总结出一套完整的改造方案,现在分享给遇到同样困境的同仁们。
2. 核心问题拆解
2.1 原生代码的限制机制
通过分析LIO-SAM的utility.h和run.launch文件,发现其硬编码了以下关键元素:
- 所有节点的默认名称空间(namespace)均为
/根目录 - 话题名称如
/odometry/imu、/lio_sam/mapping/odometry等未做隔离 - 参数服务器中的参数键名如
lio_sam/useImuHeadingInitialization全局唯一
这种设计在单节点运行时完全合理,但当第二个节点启动时:
- 相同名称的节点会互相覆盖
- 话题订阅/发布产生冲突
- 参数服务器键值被重复写入
2.2 多节点运行的技术需求
要实现安全的多实例并行,必须确保每个节点拥有:
- 独立的ROS命名空间(namespace)
- 隔离的话题通信通道
- 专属的参数存储区域
- 不冲突的TF帧命名
3. 代码改造方案
3.1 命名空间动态化改造
修改launch/run.launch文件,增加namespace参数:
<launch> <arg name="robot_ns" default="robot1" /> <group ns="$(arg robot_ns)"> <node pkg="lio_sam" type="lio_sam_imuPreintegration" name="imuPreintegration" output="screen" /> <!-- 其他节点同理 --> </group> </launch>对应的C++代码中需要调整话题订阅:
// 原代码 ros::Subscriber subImu = nh.subscribe<sensor_msgs::Imu>("imu_correct", 200, &IMUPreintegration::imuHandler, this); // 修改为 ros::Subscriber subImu = nh.subscribe<sensor_msgs::Imu>("imu_correct", 200, &IMUPreintegration::imuHandler, this, ros::TransportHints().tcpNoDelay());3.2 参数隔离方案
在config/params.yaml中采用分层参数结构:
robot1: lio_sam: useImuHeadingInitialization: true imuTopic: "imu_correct" robot2: lio_sam: useImuHeadingInitialization: false imuTopic: "imu_raw"代码中通过ros::param::get("/robot1/lio_sam/useImuHeadingInitialization", useImuHeadingInitialization)方式读取。
3.3 TF帧命名冲突解决
修改include/utility.h中的帧定义:
#define MAP_FRAME (robot_ns + "/map") #define ODOM_FRAME (robot_ns + "/odom") #define BASE_FRAME (robot_ns + "/base_link")4. 完整实施步骤
4.1 基础改造流程
- 备份原项目代码
- 修改所有launch文件,添加namespace参数
- 更新utility.h中的帧命名逻辑
- 重构参数配置文件结构
- 调整所有话题订阅/发布的代码段
4.2 多节点启动示例
# 终端1 roslaunch lio_sam run.launch robot_ns:=agv1 # 终端2 roslaunch lio_sam run.launch robot_ns:=agv2此时可以通过rostopic list查看到隔离的话题:
/agv1/lio_sam/mapping/odometry /agv2/lio_sam/mapping/odometry5. 关键问题与解决方案
5.1 TF树冲突处理
当多个节点发布相同父子关系的TF时,需要在rviz中配置显示过滤器:
<rviz> <Display type="TF" enabled="true"> <frame names="agv1/map agv1/odom agv1/base_link"/> </Display> </rviz>5.2 资源占用优化
每个节点会独立加载点云地图,建议:
- 共享静态层地图(通过
/agv1/map话题转发) - 调整
voxel_filter参数降低计算负载 - 为每个节点分配固定CPU核心
6. 性能实测数据
在Intel NUC11上测试结果:
| 节点数 | CPU占用 | 内存占用 | 建图延迟 |
|---|---|---|---|
| 1 | 78% | 2.3GB | 120ms |
| 2 | 142% | 4.1GB | 135ms |
| 3 | 210% | 6.8GB | 155ms |
提示:当运行超过3个节点时,建议禁用各节点的可视化模块以节省资源
7. 扩展应用场景
这套改造方案不仅适用于LIO-SAM,还可应用于:
- 多机器人协同建图
- 算法不同参数配置的对比测试
- 传感器数据的分通道处理
- 教学演示中的多案例并行展示
我在实际项目中验证过,配合namespace和remap技术,甚至可以实现不同版本算法的AB测试。比如同时运行改进前后的LIO-SAM节点,实时对比建图效果差异。