M2DGR数据集实战指南:从ORB-SLAM到FAST-LIO的完整配置流程 📅 发布时间:2026/9/17 9:57:25 👁 浏览次数: M2DGR数据集在主流SLAM框架中的实战配置指南从ORB-SLAM到FAST-LIO的完整流程这几年折腾SLAM的人越来越多如果你已经刷完《视觉SLAM十四讲》、跑过KITTI接下来一定会遇到一个尴尬单目、双目、LiDAR、IMU、真值样样齐全又免费开放的数据集其实没有想象中那么多。KITTI年代久远传感器配置老旧TUM的RGB-D场景偏室内而做地面机器人、移动底盘、巡检小车这类工作最接近实际工程形态的反而是M2DGR——上海交大发布的多传感器地面机器人数据集。我最早接触M2DGR是为了同时验证ORB-SLAM和FAST-LIO的定位精度结果发现这套数据集的坑比预想中多bag文件拆包复杂、传感器时间戳对不齐、不同SLAM框架的话题名和参数需求完全不一样。这篇文字就围绕M2DGR在ORB-SLAM与FAST-LIO中的配置过程展开把从下载、解析到调参、评估的完整流程写清楚适合正在做SLAM研究、准备SLAM面试或者打算在rk3588这类嵌入式平台上部署视觉/激光SLAM的工程师参考。1. M2DGR数据集多传感器SLAM的“面试官”1.1 数据集构成装了六只眼的地面机器人M2DGR全称是Multi-sensor Dataset for Ground Robot采集平台是一台轮式地面机器人传感器配置相当豪华6个全局快门相机前视双目四个朝向不同方向的侧视相机、1台32线激光雷达、高精度IMU、GNSS接收机部分序列还有红外相机。相比KITTI只有前向视觉和64线LiDARM2DGR更像是现代多传感器融合SLAM系统的完整模板专门用来测试视觉、激光、惯导之间怎么互相兜底。这套数据集的场景划分也是奔着工程痛点去的gate_01是院门周边parking_01是露天停车场street_01是街道还有室内大厅、隧道、森林小道等序列。我实测下来parking_01对这种开阔环境的视觉特征稀疏问题考验很大而tunnel_01和hall_01则是IMU退化场景这两种场景刚好对应ORB-SLAM容易跟丢、FAST-LIO容易漂移的典型工况。所以如果你想做多传感器融合方向的研究M2DGR比KITTI或者EuRoC的参考价值更接近真实部署环境。另外M2DGR提供了真值轨迹官方文件里有RTK和动捕系统对齐后的真值格式是TUM轨迹格式可直接用于evo评估。这一点非常关键因为很多数据集只给原始数据不给准真值你算法跑完连个对标尺都没有根本没法说清定位精度到底是好是坏。M2DGR这一点做得相当厚道。1.2 下载与解包先搞清楚bag里到底有什么下载M2DGR一般在官方GitHub仓库或百度云上进行每个序列是一个压缩包解压后里面是一个Rosbag文件有的还附带calibration文件夹和真值文件。我建议下载之前先看序列说明不要一上来就把几十个GB全下完。拿我当时做实验来说验证ORB-SLAM只需要含有双目图像和IMU数据的序列验证FAST-LIO需要LiDAR、IMU、GNSS三项全齐所以优先下载包含全部传感器的完整序列最省事。解压完成后第一件事不是急着跑算法而是看bag文件内部的完整话题结构。打开终端执行rosbag info xxx.bag你会看到类似这样的输出topics: /camera/left/image_raw /camera/right/image_raw /camera/left1/image_raw /camera/right1/image_raw /imu/data /lidar_points /navsat/fix ...注意不同序列的bag命名可能不一样有的用/lidar_points有的可能用/velodyne_points相机话题也常见带compressed后缀的压缩图像。先用rosbag info确认实际话题名再去做话题重映射这是所有后续配置的起点。我见过太多人拿着网上教程直接复制launch文件结果话题名对不上节点半天不输出折腾几小时发现只是名字写错了。另外关于图像压缩格式如果话题名里带compressed在ORB-SLAM里需要先解压图像。常见做法是写一个小节点订阅压缩话题、用cv_bridge解压后再以标准sensor_msgs/Image格式重新发布后面3.1节我会给出具体方案。2. 环境准备把ORB-SLAM和FAST-LIO的标准底座搭好2.1 系统与依赖库安装M2DGR的bag文件是ROS格式的所以整套流程必须在ROS环境里跑。我推荐用Ubuntu 18.04 ROS Melodic或者Ubuntu 20.04 ROS Noetic两个版本都实测过。M2DGR官方推荐ROS版本偏向Melodic但Noetic下把OpenCV版本适配好也一样跑。依赖库方面ORB-SLAM2/3需要Eigen3、Pangolin、OpenCV、g2o、SophusFAST-LIO需要PCL、Eigen、OpenCV。很多新手会让这些依赖互相打架尤其OpenCV版本问题Ubuntu 20.04自带的OpenCV 4.x和ORB-SLAM2内置的DBoW2有时会编译报错。我的经验是如果跑ORB-SLAM2建议用OpenCV 3.4.x系列如果跑ORB-SLAM3OpenCV 4.x问题不大。具体安装时可以用vcpkg或源码编译但更稳妥的方式是先装ros-desktop-full它会自带一套OpenCV再按SLAM框架要求补装Pangolin和g2o。还有一个常见坑是Pangolin版本。ORB-SLAM2对Pangolin的版本比较敏感后面新版本Pangolin改了头文件路径可能导致编译时找不到#include pangolin/pangolin.h。建议直接用ORB-SLAM2仓库推荐的0.5版本或者Ubuntu仓库里自带的旧版Pangolin。FAST-LIO这边仓库地址是hku-mars/FAST_LIO编译依赖主要是PCL和Eigen外加livox_ros_driver如果你用的是Livox雷达。跑M2DGR不需要Livox驱动因为它用的是Velodyne 32线雷达所以可以不开livox_ros_driver直接从源码编译FAST-LIO本体。2.2 时间同步跑数据集最容易忽略的第一道坎M2DGR的bag文件里有多个传感器的话题每个话题的时间戳是采集时记录下来的。但这里有个细节不同传感器的消息频率差别很大IMU一般是200HzLiDAR是10Hz相机是20Hz左右GNSS是1~5Hz。如果直接用rosbag play播放节点订阅时的消息到达顺序并不会完全按照时间戳对齐尤其当你把多个算法节点同时挂上去时系统调度延迟会进一步影响同步效果。我的建议是在播放bag时加上--clock参数让ROS使用bag中的时间作为系统时钟并且把use_sim_time置为true。具体操作rosbag play --clock --rate 1.0 xxx.bag然后在启动SLAM节点前在launch文件中加入param name/use_sim_time valuetrue/这个参数的意义是让所有节点读取/clock话题的时间而不是本机系统时间这样各节点之间的话题消息在时间轴上是一致的。对于FAST-LIO这种对IMU时间戳非常敏感的算法这一步不做后面调试时间偏移会让你崩溃。另外我在M2DGR上还遇到过一个现象bag里的图像话题和IMU话题时间戳偶发跳变个别消息的时间戳比前一条还早这在30分钟以上的长序列里尤其明显。折中方案是播放时用--rate保持原始速度不要加速播放并且尽量避免在播放同时开一堆可视化工具导致CPU争抢。3. 用ORB-SLAM吃下M2DGR的双目数据3.1 从bag中提取双目光流ORB-SLAM的入口需求很直接订阅两路同步图像一路左目一路右目。M2DGR的bag里通常有/camera/left/image_raw和/camera/right/image_raw这两个话题正好对应前视双目相机。如果话题名一致可以直接用ORB-SLAM2自带的ROS节点只需要修改launch文件里的订阅话题名。ORB-SLAM2的双目ROS节点launch类似这样launch param name/use_sim_time valuetrue/ node nameORB_SLAM2 pkgORB_SLAM2 typeStereo args/path/to/your/stereo_config.yaml outputscreen remap from/camera/left/image_raw to/camera/left/image_raw/ remap from/camera/right/image_raw to/camera/right/image_raw/ /node /launch但如果你下载的bag里图像话题带compressed后缀比如/camera/left/image_raw/compressed直接remap是行不通的因为sensor_msgs/CompressedImage和sensor_msgs/Image是不同类型。这时候需要写一个图像解压节点订阅压缩话题利用cv_bridge把压缩图像转成普通Image再发布到新话题。我给了个参考代码#!/usr/bin/env python3 import rospy import cv2 from sensor_msgs.msg import Image, CompressedImage from cv_bridge import CvBridge class ImageDecompressor: def __init__(self): self.bridge CvBridge() self.pub_left rospy.Publisher(/camera/left/image_raw, Image, queue_size10) self.pub_right rospy.Publisher(/camera/right/image_raw, Image, queue_size10) rospy.Subscriber(/camera/left/image_raw/compressed, CompressedImage, self.left_cb) rospy.Subscriber(/camera/right/image_raw/compressed, CompressedImage, self.right_cb) def left_cb(self, msg): cv_img self.bridge.compressed_imgmsg_to_cv2(msg, bgr8) self.pub_left.publish(self.bridge.cv2_to_imgmsg(cv_img, bgr8)) def right_cb(self, msg): cv_img self.bridge.compressed_imgmsg_to_cv2(msg, bgr8) self.pub_right.publish(self.bridge.cv2_to_imgmsg(cv_img, bgr8)) if __name__ __main__: rospy.init_node(image_decompressor) ImageDecompressor() rospy.spin()这个节点跑起来后ORB-SLAM的remap就可以保持不变了。3.2 相机参数与YAML配置ORB-SLAM的双目模式需要一份yaml文件里面包含Camera.fx、Camera.fy、Camera.cx、Camera.cy、Camera.bf这五个核心参数其中bf等于基线长度乘以fx。M2DGR官方在calibration文件夹里提供了相机内参和双目外参别自己瞎猜值直接读文件填进去。我记得有一段时间自己图省事想当然用了某个公开双目相机的内参去跑结果初始化可以过但地图点分布明显不对三角化出来的深度整体偏大。后来换成官方标定文件才正常。M2DGR的双目基线我记得是10cm级别对应bf大概是fx乘以0.1如果你的yaml里bf填错一位小数地图比例尺全是错的轨迹评估也会跟着崩。除了相机参数ORB-SLAM2的双目yaml里还有ORB提取数量、金字塔尺度因子、特征点匹配阈值等参数。针对M2DGR这种地面机器人场景我建议把ORB特征点数量从默认的1000提高到1500~2000因为地面场景纹理偏弱特征点太少容易跟踪不稳。但也不要无脑拉到3000以上特征提取耗时和匹配耗时都会翻倍30Hz的双目摄像头你很快会掉帧。这个权衡在parking_01这种空旷停车场场景尤其明显。3.3 跑起来只是开始评估才是关键ORB-SLAM跑M2DGR只是第一步跑完之后怎么知道它准不准才见功底。ORB-SLAM2在双目模式下会输出一个KeyFrameTrajectory.txt里面是每帧关键帧的位姿格式是TUM格式时间戳、平移xyz、四元数xyzw。M2DGR官方也提供了真值文件同样是TUM格式。两者直接放到evo里对比就行。我用的是evo这个工具安装之后执行evo_ape tum KeyFrameTrajectory.txt groundtruth.txt -a evo_rpe tum KeyFrameTrajectory.txt groundtruth.txt -a-a参数表示先做位姿对齐因为ORB-SLAM输出的坐标系和真值坐标系不一定一致。实测在street_01这种纹理丰富的场景ORB-SLAM的ATE能跑到0.1m级别但在parking_01这种开阔低纹理场景ATE可能直接飙到0.5m以上而且中途容易丢跟踪。这个结论本身就有意思同一个双目模型不同M2DGR场景的表现差异巨大正好可以用来做鲁棒性分析。画轨迹图也很重要用evo_traj tum --plot可以直观看到跟踪丢失点在哪里。我遇到过一种情况整体轨迹精度看起来还行但把轨迹画出来之后发现中途有一段完全偏离真实路线只是到后面又回来了。这种“中途跑飞再找回”的问题用APE数值根本看不出来必须可视化轨迹才现形。所以做SLAM评估眼睛和数字都要信不能只看一个指标。4. 用FAST-LIO吃下M2DGR的LiDARIMU数据4.1 话题重映射与雷达类型配置FAST-LIO是一个紧耦合的LiDAR-IMU融合算法核心思想是把LiDAR点云和IMU测量放到一个迭代卡尔曼滤波框架里估计状态。它对话题的需求很简单一个点云话题、一个IMU话题。M2DGR的bag里点云话题一般是/lidar_points或/velodyne_pointsIMU话题是/imu/data。FAST-LIO的配置全在config文件里比如fastlio_mid360.yaml或velodyne.yaml。打开后重点关注这几个字段common: lid_topic: /lidar_points imu_topic: /imu/data preprocess: lidar_type: 1 # 1: Velodyne, 2: Livox scan_line: 32 blind: 0.5M2DGR用的是32线机械雷达所以lidar_type填1scan_line填32。这里的blind是近距离盲区滤波默认0.5m即可太小会把雷达自身的噪声点也算进来太大会丢失近处的障碍物边缘影响前端匹配质量。话题名和你bag里不一致直接在yaml里改不用动代码。这一点FAST-LIO比ORB-SLAM省心一切参数外置改起来方便。4.2 配置参数现场记录外参、时间偏移、滤波我第一次用FAST-LIO跑M2DGR时定位直接飞了。原因有两个一是外参没配好二是时间偏移没有微调。先说外参。FAST-LIO的config文件里有extrinsic_T和extrinsic_R表示LiDAR在IMU坐标系下的平移和旋转。这个参数必须和M2DGR官方标定文件里的外参一致不能随便填单位矩阵。我当时图省事填了零平移结果点云投影到世界坐标系后整体扭曲得不像样。后来把官方标定结果填进去问题立刻解决。再说时间偏移。M2DGR的LiDAR和IMU时间戳虽然整体同步但可能存在固定的小偏差通常在几毫秒到几十毫秒之间。FAST-LIO的config里有time_offset这个参数意思是IMU时间戳相对点云时间戳的偏移补偿。我的方法是先跑一小段看输出的状态估计是否平滑如果速度或者姿态估计有明显的高频抖动就尝试将time_offset在小范围里搜索比如从0到0.05秒之间以0.005步进试跑。这个参数不像外参那样有明确标定值只能靠试加上观察。另外FAST-LIO对初始状态很敏感。启动时如果IMU的初始姿态估计不准后续整个轨迹都会漂。我建议播放bag之前让机器人静止至少2秒钟让IMU完成初始化和重力对齐。M2DGR的很多序列开头正好有一段车辆静止的时段这是天然的优势直接用就行。滤波相关参数我建议保守一点。FAST-LIO里filter_size_surf和filter_size_map控制体素滤波尺寸太小会让地图点云过大、计算量飙升太大会丢失细节、定位精度下降。对32线雷达我通常设filter_size_surf0.5、filter_size_map0.5在M2DGR的测试里定位精度和实时性都能接受。如果你用的是Livox MID-360可以适当调小到0.3因为Livox点云更密。4.3 关于Livox MID-360的额外补充近两年很多人问mid360使用fast-lio建图怎么配置M2DGR虽然不是Livox传感器采集的但配置逻辑完全可以平移到自有传感器上。如果你手里有一台Livox MID-360FAST-LIO仓库里有专门的fastlio_mid360.yaml模板里面已经预置好了MID-360的内外参与话题名。你需要改的只有两处lidar_type保持2Livox类型imu_topic改成自己IMU的话题名。还有一个容易忽略的点是Livox点云的话题名通常是/livox/lidar如果你的驱动版本较新可能带/livox/points之类的后缀只要yaml里对上就行。用Livox雷达跑FAST-LIO时注意初始化动作要领启动后先静止1~2秒然后让雷达做一些小幅度的平移和旋转让滤波器充分激励起来。如果初始化阶段车辆一直静止不动FAST-LIO可能一直处于等待状态不输出轨迹。5. 同一份数据两种范式的对比5.1 视觉与LiDAR在M2DGR上的表现差异同一个M2DGR序列既能跑ORB-SLAM又能跑FAST-LIO这本身就提供了极好的对比实验基础。我跑下来最直观的感受是在纹理丰富、光照正常的室内场景ORB-SLAM的精度并不比FAST-LIO差太多甚至在部分区间还能反超但在光线变化强烈或者纹理稀疏的室外场景ORB-SLAM的跟踪稳定性明显下降而FAST-LIO凭借LiDAR点云和IMU融合表现稳定得多。以M2DGR的parking_01为例这是一个开阔停车场序列路面纹理弱周围还有大面积天空和建筑物墙面反光。ORB-SLAM在快速转弯处出现过两次跟踪丢失恢复后轨迹有累计漂移。FAST-LIO在相同序列上全程没有丢跟踪但受到LiDAR点云运动畸变影响快速转弯时的局部轨迹略有一点点滞后感。这说明视觉SLAM的优势在于丰富的语义特征和低传感器成本劣势是退化场景鲁棒性差LiDAR-IMU融合的优势在于对光照、纹理不敏感劣势是对雷达本身的分辨率和扫描带宽有依赖。理解了这些你在实际项目里选型就不会盲目跟风。5.2 从实验到项目怎么选以及面试怎么聊现在很多SLAM岗位面试都会让候选人谈谈多传感器融合的理解M2DGR是一个非常好的谈资。你如果说“我跑过M2DGR用ORB-SLAM和FAST-LIO都验证过”面试官通常会接着问“两者在弱纹理场景下谁更稳”“传感器时间戳怎么做的同步”“外参怎么标定的”。这些细节在本文的配置流程里都有涉及能讲清楚就说明你是真的下过功夫而不只是跑了个hello world。实际工程中如果你的目标平台是rk3588这类嵌入式板子我建议优先考虑FAST-LIO这类LiDAR-IMU方案因为视觉SLAM的特征提取在边缘设备上往往跑不满帧率而LiDAR-IMU方案的点云匹配和状态估计在算力优化后通常更可控。当然如果成本敏感、只能上摄像头那ORB-SLAM系列依然是主流选择只是要做好动态物体和光照变化的兜底策略。6. 常见问题速查与避坑清单6.1 一张表解决90%的启动报错现象可能原因解决方案ORB-SLAM启动后无图像输出订阅话题名与bag不一致用rosbag info确认话题名remap或者写解压节点ORB-SLAM初始化失败相机内参或bf参数错误使用官方calibration文件逐一核对yaml参数ORB-SLAM轨迹尺度明显不对bf填错或者单目模式误用为双目确认双目模式检查bf是否等于fx×基线FAST-LIO启动后点云空白lidar_type或scan_line错误确认雷达类型Velodyne填1Livox填2线数32FAST-LIO启动后定位漂移外参错误或时间偏移过大填官方外参按0.005步进搜索time_offset播放bag时SLAM节点时间不同步没有设置use_sim_time播放加--clocklaunch里加use_sim_timetrueevo评估轨迹对齐失败真值和估计的坐标系或格式不一致统一为TUM格式使用-a自动对准编译ORB-SLAM2时OpenCV报错OpenCV版本不兼容使用OpenCV 3.4.x或切换到ORB-SLAM3这张表覆盖了我遇到过的绝大多数启动阶段问题如果你的故障不在表里先回头看rosbag info输出和ROS节点日志多半能在前10分钟定位问题。6.2 经验汇总这些坑我替你踩过了最后分享几条零散的实战心得。第一M2DGR的bag文件普遍很大动辄十几个GB播放时磁盘IO会直接影响话题消息的发布速率尤其是点云话题。建议把bag放在SSD上机械盘播放32线LiDAR点云时经常出现点云丢帧间接导致FAST-LIO位姿跳变。第二不要同时启动ORB-SLAM和FAST-LIO对比测试除非你的电脑是高端工作站。两个算法同时跑地图构建和可视化对CPU和内存压力都很大最终两个节点的实时性都会受影响实验结果也就不可信了。正确做法是各自单独跑同一个序列把轨迹保存下来最后再用evo统一对比。第三M2DGR真值文件的坐标系与ORB-SLAM输出坐标系一般不一致直接用evo对比数值没意义记得加对齐参数。如果真值文件里包含多段连续轨迹建议拆分成单段再评估不然段间的跳变会影响整体指标。第四在调试FAST-LIO时间偏移的时候我建议先把点云地图显示关掉只保留轨迹输出。因为实时渲染点云地图会占掉大量GPU资源而时间偏移导致的抖动在轨迹上就能看出来没必要把地图渲染也开着。这套配置流程我自己前后折腾了两个多星期跑了M2DGR里的五个序列把ORB-SLAM2、ORB-SLAM3、FAST-LIO都调通并做了对比评估。后续如果你想进一步扩展可以把M2DGR的GNSS数据接入用GPS因子做全局优化或者把视觉语义信息融合进来做动态物体过滤这些都是很好的研究方向。