实战(一)——从零构建适配Fast-LIVO的自定义数据集 1. 为什么需要自定义数据集刚开始接触Fast-LIVO时我和很多开发者一样习惯直接下载公开数据集来测试算法。但很快就发现一个问题公开数据集使用的传感器型号和我的设备完全不同。我的Livox Mid-40雷达视角只有38度而大多数数据集用的是水平视角更广的机械式雷达。这导致直接用公开数据训练的效果大打折扣。更麻烦的是相机参数。我手头是一台普通的USB工业相机焦距、畸变参数都和数据集里的高端设备相差甚远。有次尝试用公开数据标定的参数跑自己的设备点云和图像对齐误差竟然达到20cm完全没法用。这时候才明白想要获得最佳效果自定义数据集不是可选项而是必选项。自定义数据集的最大优势是传感器参数完全匹配。你的雷达型号、相机型号、安装位置都会如实反映在数据中。我后来用自采数据重跑Fast-LIVO定位精度直接提升了3倍。另一个好处是场景可控你可以专门采集目标场景的数据。比如我做仓储机器人开发时就重点采集了货架密集区域的数据这对提升实际场景的建图稳定性帮助巨大。2. 硬件准备与配置2.1 传感器选型建议我的设备组合是Livox Mid-40雷达加Basler ace acA1920-40gc相机这套配置性价比很高。Livox雷达的优势在于高点云密度在10米范围内每秒钟能产生约10万点比传统16线雷达还密集。相机选择要注意全局快门卷帘快门的果冻效应会导致运动模糊。Basler这款相机支持外部触发正好满足我们的需求。同步方案我推荐使用硬件触发。具体做法是用雷达的PPS信号触发相机这样时间同步精度能控制在微秒级。我试过软件同步结果时间偏差经常超过10毫秒对Fast-LIVO这种紧耦合算法来说简直是灾难。硬件接线很简单用BNC线连接雷达的PPS输出和相机的Trigger输入然后在相机驱动里设置触发模式。2.2 安装注意事项传感器安装有个关键原则刚性固定。我第一次安装时用了普通3D打印支架结果车辆振动导致雷达相机产生相对位移标定参数全废了。后来改用铝合金支架加防松螺丝问题才解决。另一个经验是视野重叠确保雷达和相机的视野有足够重合区域建议至少30%重叠。我的安装角度是雷达水平向前相机向下倾斜15度这样既能看清地面特征又能看到远处物体。3. 数据采集实战3.1 采集环境选择理想的采集环境需要丰富的特征和适度光照。我常去的地下停车场就是个好地方——墙面有清晰的管道纹理地面有规则的标线这些都能为SLAM提供稳定特征。避免纯白墙面或镜面反光区域这些地方算法会完全丢失特征。光照方面200-1000lux是最佳范围太暗会导致图像噪声大太亮又容易过曝。采集路径要遵循多样性原则。我一般走8字形路线包含前后移动、左右转弯、上下坡等动作。特别注意要采集一些闭环路径即最后回到起点附近这对评估算法精度很有帮助。一次完整采集建议10-15分钟这样既能获得足够数据又不会让文件过大。3.2 实时监控技巧采集时一定要实时监控数据质量。我写了个简单的ROS节点同时显示点云和图像重点检查点云是否完整有无大面积缺失图像是否过曝/欠曝时间戳是否同步点云和图像的时间差应小于1ms遇到问题立即停止采集。有次我发现点云有规律性缺失后来发现是USB3.0接口接触不良换成带锁紧的工业连接器就解决了。4. 数据预处理全流程4.1 时间同步校准即使使用硬件同步也建议做一次时间偏移校准。我的做法是晃动一个棋盘格同时被雷达和相机观测然后用以下命令计算时间差rosrun camera_calibration cameracalibrator.py --size 8x6 --square 0.024 image:/camera/image_raw通过观察点云中棋盘格和图像中棋盘格的位置偏差可以精确校准时间偏移。我实测发现即使硬件同步仍有约0.5ms的固有延迟校准后把这个值写入配置文件中。4.2 外参标定详解外参标定我推荐使用LiDAR-Camera标定板。这种特制标定板在雷达下会呈现明显角点方便提取特征。标定步骤将标定板放在不同距离和角度采集30组数据使用开源工具标定rosrun lidar_camera_calibration calibrate_lidar_camera.py --bag calibration.bag检查重投影误差我一般要求小于2个像素标定结果保存为4x4变换矩阵格式如下transform: rotation: rows: 3 cols: 3 data: [0, -1, 0, 0, 0, -1, 1, 0, 0] translation: rows: 3 cols: 1 data: [0.05, -0.1, 0.15]5. Fast-LIVO适配实战5.1 配置文件修改关键配置文件有两个avia_resize.yaml雷达参数lidar: topic: /livox/lidar max_range: 100.0 min_range: 0.1camera_pinhole_resize.yaml相机参数camera: topic: /camera/image_raw intrinsics: [1066.7, 0, 960, 0, 1066.7, 540, 0, 0, 1] distortion: [-0.05, 0.01, 0.001, 0.001]特别注意图像尺寸要和实际一致。我的相机分辨率是1920x1200但为了加速处理我在驱动里下采样到960x600所以配置文件也要对应修改。5.2 数据格式转换最后一步是将数据转为ROS bag格式。我写了个自动化脚本import rosbag from cv_bridge import CvBridge bridge CvBridge() with rosbag.Bag(output.bag, w) as bag: for img, points in zip(images, pointclouds): bag.write(/camera/image_raw, bridge.cv2_to_imgmsg(img), img.header.stamp) bag.write(/livox/lidar, points, points.header.stamp)录制时建议使用压缩存储rosbag record -O custom.bag --lz4 /camera/image_raw /livox/lidar6. 常见问题排查遇到过最棘手的问题是点云缺失。有次采集的数据在Fast-LIVO中只显示零星点云后来发现是雷达的FOV设置不对。Livox雷达默认只开启正前方60度区域需要在驱动中修改配置// livox_ros_driver/config/MID40_config.json { lidar_config: { scan_pattern: 0, // 0表示全FOV扫描 blind_spot: 0 } }另一个常见问题是图像时间戳跳跃。有次发现图像时间戳不连续导致算法崩溃。解决方法是在相机驱动中强制使用ROS时间self.image_pub.publish(self.bridge.cv2_to_imgmsg(cv_image, bgr8), rospy.Time.now())7. 效果评估与优化评估建图质量我主要看三个指标相对位姿误差RPE控制在0.5%以内绝对轨迹误差ATE闭环误差应小于1米点云对齐度用CloudCompare软件检查优化参数时重点调整optimization: max_iterations: 10 # 增加到15可提升精度但更耗时 huber_loss: 0.1 # 噪声大时调大到0.3最后提醒第一次跑自定义数据要有耐心。我的经验是至少要迭代3-5次采集才能得到理想数据。每次采集后记录下问题比如光照不足或特征太少下次针对性改进。记住好的数据集是算法成功的一半。