尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

LIO-SAM算法与Livox Mid360激光雷达:从Gazebo仿真到实机部署全流程指南

LIO-SAM算法与Livox Mid360激光雷达:从Gazebo仿真到实机部署全流程指南 在机器人SLAM领域从算法仿真到实机部署的“最后一公里”往往充满挑战。最近我们团队基于Livox Mid360固态激光雷达成功将经典的LIO-SAM算法部署到实车并在华南理工大学五山校区3号楼前完成了实机建图与定位测试。与此同时为了验证算法逻辑和进行安全、高效的开发迭代一套完整的Gazebo仿真环境也必不可少。本文将系统性地拆解LIO-SAM Mid360的全流程部署方案涵盖实机环境搭建、驱动配置、算法适配、实机运行以及Gazebo仿真环境构建与测试。无论你是正在研究激光SLAM的学生还是希望将先进算法落地的工程师这份从仿真到实机的完整笔记都将为你提供清晰的路径和可复现的代码。1. 背景与核心概念为什么选择LIO-SAM与Mid360在开始实操之前有必要厘清几个核心概念理解我们技术选型背后的原因。LIO-SAM (Lidar Inertial Odometry via Smoothing and Mapping)是Tixiao Shan于2020年开源的一个紧耦合激光惯性里程计框架。它并非一个纯粹的“建图”算法而是一个高频率、高精度的里程计。其核心优势在于紧耦合优化 将激光雷达点云特征面特征、角特征与IMU预积分结果在一个因子图框架下进行联合优化充分利用IMU的高频特性弥补激光雷达低帧率的不足从而得到平滑、高频率的位姿估计。回环检测与全局优化 集成基于Scan-Context的回环检测模块能够有效消除累积误差实现大规模场景下的全局一致性地图。工程友好 代码结构清晰基于ROS框架易于二次开发和与其他模块如导航集成。Livox Mid360是一款非重复扫描模式的固态激光雷达。与传统机械旋转雷达相比它的优势在于高可靠性与长寿命 无旋转部件更耐冲击和振动。独特的扫描图案 非重复扫描模式使得随着时间推移点云覆盖率会越来越高对于特征提取尤其是平面特征非常有利。内置IMU Mid360本身集成了6轴IMU这为LIO-SAM这类紧耦合激光惯性里程计提供了“开箱即用”的硬件基础无需额外标定雷达与IMU的外参需注意内置IMU的质量和同步问题。Gazebo仿真在机器人开发中扮演着“安全沙盒”的角色。在实机调试前在仿真环境中验证算法逻辑 确保算法流程正确话题通信正常。测试极端场景 可以轻松模拟传感器失效、剧烈运动等难以在实机复现的场景。加速开发迭代 无需硬件准备和户外测试效率极大提升。成本与安全 避免实机测试可能带来的设备损坏和安全风险。因此LIO-SAM Mid360的组合在理论上是性能与工程实践的优秀结合。而从Gazebo仿真到实机部署的路径则是一套稳健的机器人系统开发方法论。2. 环境准备与版本说明我们的工作将在Ubuntu系统和ROS框架下进行。以下是经过验证的环境配置强烈建议你保持一致以避免不必要的兼容性问题。2.1 硬件与操作系统实机平台 搭载NVIDIA显卡的移动机器人/车辆。我们的测试平台为Intel NUC NVIDIA Jetson Xavier NX。仿真平台 任何支持Ubuntu的PC或虚拟机均可。操作系统Ubuntu 20.04。这是ROS Noetic的官方支持系统拥有最完善的生态。虽然Ubuntu 22.04/24.04也可行但部分依赖如PCL、GTSAM的编译可能会遇到更多问题。ROS版本ROS Noetic。这是最后一代支持Ubuntu 20.04的ROS1版本LIO-SAM原生基于ROS1开发。2.2 核心依赖安装在Ubuntu 20.04上首先安装ROS Noetic桌面完整版然后安装必要的系统依赖和第三方库。# 1. 配置ROS Noetic源并安装 sudo sh -c echo deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main /etc/apt/sources.list.d/ros-latest.list sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654 sudo apt update sudo apt install ros-noetic-desktop-full # 2. 初始化rosdep sudo rosdep init rosdep update # 3. 安装系统依赖和工具 sudo apt install -y git cmake libeigen3-dev libboost-all-dev libsuitesparse-dev sudo apt install -y ros-noetic-navigation ros-noetic-robot-localization ros-noetic-robot-state-publisher sudo apt install -y libpcl-dev ros-noetic-pcl-ros ros-noetic-pcl-conversions ros-noetic-tf2-sensor-msgs # 4. 安装GTSAM (因子图优化库 LIO-SAM的核心) cd ~ git clone https://github.com/borglab/gtsam.git cd gtsam git checkout 4.1.1 # 使用与LIO-SAM兼容的版本 mkdir build cd build cmake -DGTSAM_BUILD_WITH_MARCH_NATIVEOFF .. # 关闭本地指令集优化以提高兼容性 sudo make install -j$(nproc)2.3 Livox SDK与ROS驱动安装这是让Mid360在ROS中“说话”的关键。# 1. 安装Livox SDK cd ~ git clone https://github.com/Livox-SDK/Livox-SDK.git cd Livox-SDK mkdir build cd build cmake .. make sudo make install # 2. 安装Livox ROS Driver cd ~ git clone https://github.com/Livox-SDK/livox_ros_driver.git ws_livox/src cd ws_livox catkin_make -j$(nproc) source devel/setup.bash编译成功后livox_ros_driver包会提供启动Mid360的launch文件。3. LIO-SAM算法部署与Mid360适配LIO-SAM原版代码主要适配Velodyne和Ouster雷达需要对点云预处理部分进行修改以适配Mid360的坐标体系和点云格式。3.1 下载与编译LIO-SAMcd ~ mkdir -p lio_ws/src cd lio_ws/src git clone https://github.com/TixiaoShan/LIO-SAM.git cd .. catkin_make -j$(nproc)3.2 关键适配修改点云预处理Mid360发布的点云话题为/livox/lidar消息类型为livox_ros_driver/CustomMsg且雷达坐标系通常为livox_frame。我们需要将其转换为LIO-SAM所需的sensor_msgs/PointCloud2类型并映射到正确的坐标系如laser_link。方法一使用livox_to_pointcloud2节点推荐我们可以编写一个简单的转换节点。在lio_ws/src下创建一个新包cd ~/lio_ws/src catkin_create_pkg mid360_adapter roscpp sensor_msgs pcl_ros livox_ros_driver在mid360_adapter/src下创建livox_converter.cpp#include ros/ros.h #include livox_ros_driver/CustomMsg.h #include sensor_msgs/PointCloud2.h #include pcl/point_cloud.h #include pcl/point_types.h #include pcl_conversions/pcl_conversions.h typedef pcl::PointXYZINormal PointType; pcl::PointCloudPointType cloud; ros::Publisher pubCloud; void livoxCallback(const livox_ros_driver::CustomMsg::ConstPtr msg) { cloud.clear(); cloud.header.stamp pcl_conversions::toPCL(msg-header).stamp; for (const auto point : msg-points) { if (std::isfinite(point.x) std::isfinite(point.y) std::isfinite(point.z)) { PointType p; p.x point.x; p.y point.y; p.z point.z; p.intensity point.reflectivity; // 注意Mid360的CustomMsg中没有直接的time字段如果需要时间偏移需额外处理 cloud.push_back(p); } } sensor_msgs::PointCloud2 output; pcl::toROSMsg(cloud, output); output.header.frame_id laser_link; // 发布到LIO-SAM期望的坐标系 output.header.stamp msg-header.stamp; pubCloud.publish(output); } int main(int argc, char** argv) { ros::init(argc, argv, livox_converter); ros::NodeHandle nh; ros::Subscriber sub nh.subscribelivox_ros_driver::CustomMsg(/livox/lidar, 100, livoxCallback); pubCloud nh.advertisesensor_msgs::PointCloud2(/points_raw, 100); // 发布到LIO-SAM订阅的话题 ros::spin(); return 0; }在CMakeLists.txt中添加add_executable(livox_converter src/livox_converter.cpp) target_link_libraries(livox_converter ${catkin_LIBRARIES} ${PCL_LIBRARIES}) add_dependencies(livox_converter ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})重新编译工作空间cd ~/lio_ws catkin_make。方法二修改LIO-SAM的imageProjection.cpp进阶直接修改LIO-SAM源码中的imageProjection.cpp的cloudHandler函数使其能直接订阅并解析livox_ros_driver/CustomMsg。这种方法更彻底但侵入性强。核心是添加一个针对CustomMsg的回调函数将点数据提取并填充到LIO-SAM内部的cloudQueue中。由于代码较长这里给出关键思路复制原有的laserCloudHandler函数修改参数类型并在utility.h中声明新的回调函数。3.3 配置LIO-SAM参数修改~/lio_ws/src/LIO-SAM/config/params.yaml以适应Mid360和你的机器人。# 常见需要修改的参数 pointCloudTopic: “/points_raw” # 改为我们转换后的话题 imuTopic: “/imu/data” # Mid360 IMU话题通常是 /livox/imu lidarFrame: “laser_link” # 激光雷达坐标系 baselinkFrame: “base_link” odometryFrame: “odom” mapFrame: “map” # 传感器设置 sensor: livox # 雷达类型设为livox N_SCAN: 1 # Livox Mid360可视为单线虽然是非重复面扫描 Horizon_SCAN: 4000 # 根据点云密度调整 timeField: offset_time # 对于CustomMsg可能需要设置为 ‘offset_time’ 或 ‘none’ # 外参关键 # 如果Mid360的IMU与雷达中心不重合或机器人有外置IMU需要填写准确的变换矩阵。 # 这里假设雷达和IMU坐标系重合对于Mid360内置IMU这是一个近似。 extrinsicTrans: [0.0, 0.0, 0.0] extrinsicRot: [1, 0, 0, 0, 1, 0, 0, 0, 1] # 单位矩阵 extrinsicRPY: [0.0, 0.0, 0.0] # 地图和优化参数可根据场景调整 mapResolution: 0.4特别注意extrinsicRot是旋转矩阵的行优先展开。如果雷达和IMU之间存在安装角度必须通过标定获取准确的外参否则会严重影响精度。4. 实机部署与华南理工大学现场测试4.1 实机系统启动流程在实机机器人上我们需要按顺序启动各个节点形成一个完整的SLAM系统。启动Mid360驱动 连接Mid360雷达到机器人主机并启动驱动节点。source ~/ws_livox/devel/setup.bash roslaunch livox_ros_driver livox_lidar.launch启动后使用rostopic list应能看到/livox/lidar和/livox/imu话题。启动点云转换节点 将CustomMsg转换为PointCloud2。source ~/lio_ws/devel/setup.bash rosrun mid360_adapter livox_converter此时/points_raw话题应有数据。启动LIO-SAM 这是核心算法节点。source ~/lio_ws/devel/setup.bash roslaunch lio_sam run.launch启动后LIO-SAM会开始接收点云和IMU数据并输出高频的odometry话题和map话题。启动可视化RVIZ 用于实时查看建图效果和机器人轨迹。roslaunch lio_sam rviz.launch在RVIZ中添加PointCloud2显示话题选择/map或/cloud_registered添加Path显示话题选择/odometry_path。4.2 华南理工大学五山校区3号楼前测试要点我们在华工3号楼前的广场及周边道路进行了测试。该场景包含开阔广场 特征相对较少考验IMU和里程计的稳定性。林荫道与建筑 提供丰富的结构化特征墙面、柱子、树木。行人与非机动车 动态物体对点云匹配是干扰。测试过程与观察初始化 在开阔地缓慢旋转机器人一周帮助算法初始化并构建初始地图。匀速行驶 控制机器人沿道路匀速行驶在RVIZ中观察地图的拼接质量和轨迹的平滑度。回环测试 控制机器人绕行一个闭合环路如绕楼一周观察回环检测是否触发以及触发后地图是否被正确修正明显的“拉直”效果。动态物体处理 观察行人穿过时地图中是否会留下“鬼影”。LIO-SAM基于特征匹配对动态物体有一定鲁棒性但快速移动的物体仍可能产生短暂干扰。实机运行效果 在场景特征丰富的情况下LIO-SAMMid360能够稳定输出高频率、低漂移的里程计构建的栅格地图或点云地图清晰建筑轮廓分明。回环检测有效能够在大范围运行后校正累积误差。5. Gazebo仿真环境搭建与测试仿真环境允许我们在没有硬件的情况下验证整个算法流水线。我们将创建一个带激光雷达和IMU传感器的机器人模型并在Gazebo中运行。5.1 创建仿真机器人URDF模型在lio_ws/src下创建一个新的功能包用于仿真cd ~/lio_ws/src catkin_create_pkg lio_sam_gazebo rospy urdf xacro gazebo_ros mkdir -p lio_sam_gazebo/urdf lio_sam_gazebo/launch lio_sam_gazebo/worlds在urdf文件夹下创建mobile_robot.xacro文件定义一个简单的差分驱动机器人并搭载一个仿Mid360的激光雷达和IMU传感器。?xml version1.0? robot namemobile_robot xmlns:xacrohttp://www.ros.org/wiki/xacro !-- 基础底盘 -- link namebase_footprint/ link namebase_link visual geometry box size0.6 0.4 0.2/ /geometry /visual collision geometry box size0.6 0.4 0.2/ /geometry /collision inertial mass value10/ inertia ixx0.4 ixy0 ixz0 iyy0.2 iyz0 izz0.4/ /inertial /link joint namebase_footprint_joint typefixed parent linkbase_footprint/ child linkbase_link/ /joint !-- 激光雷达模拟Mid360 -- link namelaser_link visual geometry cylinder length0.05 radius0.05/ /geometry /visual inertial mass value0.1/ inertia ixx0.0001 ixy0 ixz0 iyy0.0001 iyz0 izz0.0001/ /inertial /link joint namelaser_joint typefixed parent linkbase_link/ child linklaser_link/ origin xyz0.2 0 0.15 rpy0 0 0/ /joint !-- Gazebo插件模拟激光雷达 -- gazebo referencelaser_link sensor typeray namelidar_sensor pose0 0 0 0 0 0/pose visualizefalse/visualize update_rate10/update_rate !-- 仿真频率 -- ray scan horizontal samples4000/samples !-- 模拟Mid360点云密度 -- resolution1/resolution min_angle-3.14159/min_angle max_angle3.14159/max_angle /horizontal vertical samples1/samples !-- 模拟固态雷达的非重复扫描这里简化为单线 -- resolution1/resolution min_angle0/min_angle max_angle0/max_angle /vertical /scan range min0.1/min max50.0/max resolution0.01/resolution /range noise typegaussian/type mean0.0/mean stddev0.01/stddev /noise /ray plugin namegazebo_ros_lidar_controller filenamelibgazebo_ros_ray_sensor.so ros namespace//namespace remapping~/out:scan/remapping !-- 发布到/scan话题 -- /ros output_typesensor_msgs/LaserScan/output_type frame_namelaser_link/frame_name /plugin /sensor /gazebo !-- Gazebo插件模拟IMU -- gazebo referencebase_link sensor typeimu nameimu_sensor always_ontrue/always_on update_rate200/update_rate visualizetrue/visualize topic/imu/data/topic plugin filenamelibgazebo_ros_imu_sensor.so nameimu_plugin topicName/imu/data/topicName bodyNamebase_link/bodyName updateRateHZ200.0/updateRateHZ gaussianNoise0.000001/gaussianNoise xyzOffset0 0 0/xyzOffset rpyOffset0 0 0/rpyOffset frameNamebase_link/frameName initialOrientationAsReferencefalse/initialOrientationAsReference /plugin /sensor /gazebo !-- 差分驱动控制器 -- gazebo plugin namedifferential_drive_controller filenamelibgazebo_ros_diff_drive.so commandTopiccmd_vel/commandTopic odometryTopicodom/odometryTopic odometryFrameodom/odometryFrame robotBaseFramebase_footprint/robotBaseFrame publishOdomTFtrue/publishOdomTF publishWheelTFfalse/publishWheelTF publishTftrue/publishTf wheelSeparation0.4/wheelSeparation wheelDiameter0.1/wheelDiameter torque10/torque updateRate30.0/updateRate /plugin /gazebo /robot5.2 创建Gazebo世界与启动文件在worlds文件夹下创建一个简单的世界文件test.world可以添加一些墙壁和障碍物。在launch文件夹下创建simulation.launchlaunch !-- 启动Gazebo世界 -- include file$(find gazebo_ros)/launch/empty_world.launch arg nameworld_name value$(find lio_sam_gazebo)/worlds/test.world/ arg namepaused valuefalse/ arg nameuse_sim_time valuetrue/ arg namegui valuetrue/ arg nameheadless valuefalse/ arg namedebug valuefalse/ /include !-- 将机器人模型加载到参数服务器 -- param namerobot_description command$(find xacro)/xacro $(find lio_sam_gazebo)/urdf/mobile_robot.xacro / !-- 在Gazebo中生成机器人 -- node namespawn_urdf pkggazebo_ros typespawn_model args-param robot_description -urdf -model mobile_robot -x 0 -y 0 -z 0.1 / !-- 发布机器人关节状态 -- node namerobot_state_publisher pkgrobot_state_publisher typerobot_state_publisher outputscreen param namepublish_frequency typedouble value50.0 / /node !-- 启动LIO-SAM需要先对仿真点云进行转换 -- !-- 仿真激光雷达发布的是LaserScan需要转换为PointCloud2 -- node pkglaser_scan_matcher typepoint_cloud_converter namepoint_cloud_converter remap fromscan to/scan/ remap fromcloud to/points_raw/ /node !-- 启动LIO-SAM -- include file$(find lio_sam)/launch/run.launch !-- 需要根据仿真传感器话题调整params.yaml中的话题名 -- !-- 例如将pointCloudTopic改为/points_raw, imuTopic改为/imu/data -- /include !-- 启动RVIZ -- node pkgrviz typerviz namerviz args-d $(find lio_sam)/config/mapping.rviz / /launch注意 仿真中的激光雷达是sensor_msgs/LaserScan类型而LIO-SAM需要sensor_msgs/PointCloud2。我们需要一个转换节点如laser_scan_matcher包中的point_cloud_converter或者使用laser_geometry库编写一个简单的转换节点。5.3 仿真环境测试启动仿真cd ~/lio_ws source devel/setup.bash roslaunch lio_sam_gazebo simulation.launch控制机器人运动 打开一个新终端使用键盘控制机器人移动观察建图过程。rosrun teleop_twist_keyboard teleop_twist_keyboard.py观察与调试 在RVIZ中你应该能看到仿真激光雷达的点云被转换为PointCloud2后输入LIO-SAM并实时输出地图和轨迹。由于仿真环境传感器数据纯净且无噪声建图效果通常会非常理想。这验证了算法流水线的正确性。6. 常见问题与排查思路在实机部署和仿真过程中你可能会遇到以下典型问题问题现象可能原因排查思路与解决方案启动LIO-SAM后无点云显示1. 话题名称不匹配。2. 点云转换节点未运行或出错。3. 雷达驱动未启动。1. 使用rostopic list和rostopic echo /points_raw检查话题和数据。2. 检查转换节点的日志rosnode info /livox_converter。3. 确认/livox/lidar话题存在且有点云数据。地图严重漂移或发散1. 雷达-IMU外参不准确。2. IMU数据质量差或话题频率低。3.params.yaml中运动模型参数不合适。1.重新标定外参这是影响精度的最关键因素。2. 使用rostopic hz /imu/data检查IMU频率应高于100Hz。3. 调整params.yaml中的imuAccNoise,imuGyrNoise等噪声参数。回环检测不触发1. Scan-Context描述子参数不合适。2. 场景特征太少回环检测失败。3. 位姿估计误差太大候选帧搜索失败。1. 调整params.yaml中loopClosure相关参数如distanceThres,scanDistance。2. 尝试在更具辨识度的场景下测试。3. 确保前端里程计精度可先在小范围内测试回环。Gazebo仿真中LIO-SAM不更新地图1. 仿真点云未正确转换为PointCloud2。2. 仿真时间/clock话题未启用或不同步。1. 检查point_cloud_converter节点是否正常运行输出话题是否为/points_raw。2. 在simulation.launch中确保use_sim_time为true并在LIO-SAM的launch文件中也设置param nameuse_sim_time valuetrue/。编译GTSAM或LIO-SAM时出错1. 依赖库版本冲突。2. 编译器版本问题。3. 内存不足。1. 严格按照本文的版本Ubuntu 20.04, GTSAM 4.1.1。2. 尝试使用catkin_make -j1单线程编译定位错误。3. 检查系统内存编译GTSAM可能需要较大内存。Mid360点云在RVIZ中显示异常如全红点云强度值范围异常。Livox雷达的反射率 (reflectivity) 范围可能与RVIZ默认的强度色彩映射不匹配。在RVIZ的PointCloud2显示属性中将Color Transformer改为AxisColor或FlatColor或者调整Autocompute Intensity Bounds。7. 最佳实践与工程建议将研究型算法稳定地部署于实机机器人需要遵循一定的工程规范。外参标定是生命线 对于LIO-SAM这类紧耦合算法雷达与IMU之间的变换矩阵 (extrinsicTrans和extrinsicRot) 必须精确。建议使用开源工具如lidar_imu_calib或Kalibr进行严格标定。标定场地应避免振动和磁干扰。时间同步与传感器诊断 确保雷达点云和IMU数据的时间戳是同步的。Mid360驱动通常能提供硬件时间同步。使用rosbag record录制数据包然后用rqt_bag检查不同话题的时间戳对齐情况。定期检查IMU数据的零偏和噪声。参数调优循序渐进 不要一次性修改大量参数。建议的调优顺序基础运行 确保外参正确算法能跑起来。前端里程计 调整featureExtraction和mapOptmization中的cornerThreshold,surfThreshold等特征提取参数使特征点数量适中、分布合理。后端优化与回环 调整loopClosure参数在保证实时性的前提下提高回环检测的召回率和准确率。性能与鲁棒性 调整voxelFilter体素滤波参数以平衡地图精度和计算负载。仿真与实机结合迭代 将仿真环境作为算法逻辑的“单元测试”环境。任何大的代码修改或参数调整先在仿真中验证基本功能再上实机测试性能。可以录制实机的ROS Bag数据在仿真环境中进行“数据回放”测试这能极大提高调试效率。系统集成与日志 将LIO-SAM作为机器人导航系统的一个节点。其输出的odometry话题可以提供给robot_localization包进行多传感器融合。务必为关键节点如LIO-SAM、驱动、转换节点配置roslaunch中的output”screen”或rosout日志并建立日志归档机制便于问题回溯。安全与容错 实机运行时务必有紧急停止机制。LIO-SAM可能因剧烈运动、特征丢失等原因发生短暂失效导致位姿跳变。应在下游节点如控制器中增加对里程计质量的判断和容错逻辑例如检查协方差或使用健康状态话题。从Gazebo中的虚拟传感器到华南理工大学校园里的真实Mid360雷达这条部署路径打通了机器人算法从仿真验证到实地应用的闭环。通过解决驱动适配、坐标转换、外参标定、参数调优等一系列实际问题我们不仅让LIO-SAM算法跑了起来更深刻理解了激光惯性里程计系统各模块间的耦合关系。希望这份详尽的记录能帮助你少走弯路更快地将优秀的SLAM算法部署到你自己的机器人平台上。下一步你可以尝试集成视觉传感器进行VIL-SAM或者将LIO-SAM的输出与导航栈如MoveBase结合实现真正的自主导航。
返回列表