从KITTI到EVO:手把手完成LIO-SAM的部署、适配与精度评估

张开发
2026/4/20 17:21:00 15 分钟阅读

分享文章

从KITTI到EVO:手把手完成LIO-SAM的部署、适配与精度评估
1. KITTI数据集准备与格式转换第一次接触KITTI数据集时我被它庞大的数据量和复杂的目录结构搞得晕头转向。经过多次实践我总结出一套最高效的数据处理方法。KITTI数据集分为raw data和odometry两个主要部分对于LIO-SAM这类激光惯性里程计算法我们需要特别注意数据的选择和处理方式。1.1 数据集下载与选择KITTI官网需要注册才能下载数据这个过程确实有点麻烦。我推荐使用百度云盘的镜像资源搜索KITTI data_odometry_velodyne就能找到现成的打包文件。下载时要注意LIO-SAM需要同时获取两种数据*_sync.zip包含10Hz的IMU数据和去畸变的视觉数据激光数据以bin格式存储*_extract.zip包含100Hz的IMU原始数据但视觉数据未去畸变为什么需要两者因为LIO-SAM对IMU数据频率要求较高而_sync.zip中的激光数据格式更友好。我实测发现只使用_extract.zip转换时会遇到两个问题一是转换耗时极长txt格式的激光数据解析慢二是需要额外处理时间同步。1.2 数据转换实战转换工具我推荐两个方案官方kitti2bag和LIO-SAM作者修改版。先说说基础环境准备# 必须升级numpy sudo pip install -U numpy # 安装基础工具 sudo pip install kitti2bag pykitti tqdm对于只有_sync.zip的情况转换命令很简单kitti2bag -t 2011_09_30 -r 0016 raw_synced但结合_extract.zip时就需要特殊处理了。这里有个坑我踩过——时间戳对齐问题。LIO-SAM作者提供的脚本会自动处理这个问题关键代码如下# 时间戳线性拟合校正 imu_index np.asarray(range(len(imu_datetimes)), dtypenp.float64) z np.polyfit(imu_index, imu_datetimes, 1) imu_datetimes_new z[0] * imu_index z[1]转换完成后建议用rosbag info检查数据完整性。我遇到过bag文件中缺少IMU数据的情况这时候需要检查_extract.zip是否下载完整。转换后的bag文件通常很大序列00大约15GB记得预留足够磁盘空间。2. LIO-SAM源码适配KITTI直接跑原始LIO-SAM在KITTI上会报错主要因为两个关键差异点云ring信息和时间戳处理。经过多次调试我总结出最稳定的修改方案。2.1 点云ring信息计算KITTI的Velodyne HDL-64E激光雷达数据不包含ring字段而LIO-SAM依赖这个信息进行特征提取。我们需要根据垂直角度动态计算float verticalAngle atan2(thisPoint.z, sqrt(thisPoint.x*thisPoint.x thisPoint.y*thisPoint.y)) * 180 / M_PI; rowIdn (verticalAngle ang_bottom) / ang_res_y;这里ang_bottom和ang_res_y需要根据HDL-64E的参数设置ang_bottom 24.8°下方视角ang_res_y 0.4°垂直角分辨率实测中发现直接这样计算有时会导致rowIdn越界我增加了边界检查if (rowIdn 0 || rowIdn N_SCAN) continue;2.2 时间戳处理优化KITTI原始数据中没有每个点的时间戳需要根据扫描周期模拟float relTime (ori - cloudInfo.startOrientation) / cloudInfo.orientationDiff; laserCloudIn-points[i].time 0.1 * relTime; // 10Hz扫描周期这里有个细节需要注意当扫描跨过π角度时要做特殊处理否则会导致时间戳跳变。我的解决方案是if (!halfPassed) { if (ori cloudInfo.startOrientation - M_PI/2) { ori 2*M_PI; } else if (ori cloudInfo.startOrientation M_PI*3/2) { ori - 2*M_PI; } }2.3 轨迹输出格式转换为了用EVO评估需要将位姿输出为TUM格式。这里涉及坐标系转换Eigen::Matrixdouble, 4, 4 cali_paremeter; cali_paremeter 2.347736981471e-04, -9.999441545438e-01, -1.056347781105e-02, -2.796816941295e-03, 1.044940741659e-02, 1.056535364138e-02, -9.998895741176e-01, -7.510879138296e-02, 9.999453885620e-01, 1.243653783865e-04, 1.045130299567e-02, -2.721327964059e-01, 0, 0, 0, 1; Eigen::Matrixdouble, 4, 4 myloam_pose_f cali_paremeter * mylio_pose * cali_paremeter.inverse();这个变换矩阵是将结果转换到左相机坐标系与KITTI真值保持一致。输出时建议使用科学计数法保证精度pose2.setf(std::ios::scientific, std::ios::floatfield);3. EVO精度评估实战EVO是SLAM评估的神器但要用好它需要掌握一些技巧。我整理了最常用的四种评估模式及其解读方法。3.1 APE绝对轨迹误差分析APE反映整体轨迹精度我的常用命令evo_ape tum kitti_00_gt.txt lio_sam_00.txt -r trans_part --align \ --plot --plot_mode xz --save_results results/ape.zip关键参数说明-r trans_part只评估平移部分旋转误差单独评估--align先进行Umeyama对齐--plot_mode xz选择最能反映SLAM性能的xz平面输出结果中要重点关注max: 3.214192 mean: 1.082736 median: 0.945201 min: 0.012345 rmse: 1.214587我习惯用rmse作为主要指标当max值异常大时可能是某些帧出现了严重漂移。3.2 RPE相对位姿误差RPE反映局部一致性对激光SLAM更重要evo_rpe tum kitti_00_gt.txt lio_sam_00.txt -r trans_part -d 10 -u m \ --plot --save_results results/rpe.zip这里-d 10表示以10米为间隔计算相对位姿变化-u m指定单位为米。好的激光SLAM在10米间隔下的RPE通常应该小于1%。3.3 多算法对比技巧用evo_res可以方便地比较多个结果evo_res results/*.zip -p --save_table results/compare.csv表格输出包含所有关键指标我经常用这个功能比较不同参数配置的效果。加--save_table可以导出为CSV方便做进一步分析。3.4 轨迹可视化要点轨迹可视化时容易犯的错误是坐标系不统一evo_traj tum lio_sam_00.txt -r kitti_00_gt.txt -a -p \ --plot_mode xz --correct_scale--correct_scale确保三个轴比例一致避免图形变形。当轨迹很大时如KITTI 00序列建议用--n_to_align 100只对齐前100帧加快处理速度。4. 实战经验与调优建议经过多次实验我总结出几个提升LIO-SAM在KITTI上表现的技巧。4.1 参数调优关键点修改params.yaml中这几个参数效果最明显pointCloudMinRange: 5.0 # KITTI场景较大适当提高 pointCloudMaxRange: 100.0 mapResolution: 0.4 # 平衡精度和计算量IMU参数需要特别注意imuAccNoise: 1e-2 imuGyrNoise: 1e-3 imuAccBiasN: 1e-4 imuGyrBiasN: 1e-5KITTI的IMU噪声较大适当调高噪声参数反而能提升效果。4.2 常见问题解决遇到过最棘手的问题是点云抖动解决方案是检查ring计算是否正确调整scanRegistration中的featureExtraction参数增加imuHistorySize到1000另一个典型问题是轨迹漂移我通常从三个方面排查IMU-Camera外参是否准确点云去畸变是否充分回环检测是否生效4.3 性能优化技巧在低配设备上运行可以降低laserCloudStackNum到2关闭visualizeCloud使用ROS的compressed传输对于长时间序列如KITTI 00建议修改// 增加关键帧选择间隔 keyframeMeterGap 10.0; keyframeDegGap 30.0;记得在评估时要把这些调整考虑进去不同的参数设置会导致EVO结果有显著差异。我通常会在README中记录每次实验的具体参数方便结果复现和对比。

更多文章