ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

M2DGR多模态SLAM数据集:地面机器人激光视觉惯性评测与退化检测

M2DGR多模态SLAM数据集:地面机器人激光视觉惯性评测与退化检测 有个做室内巡检机器人的朋友上个月找我说他那套激光惯性里程计在 KITTI 上跑出来的轨迹误差只有十几厘米换到自家写字楼的走廊里二十米之后就开始飘回到起点能差出两米。我每次被问这类问题第一句话都是反问他有没有拿 M2DGR 测过。M2DGR 是上海交大团队开源的一套面向地面机器人的多模态 SLAM 数据集全称 Multi-Modal and Multi-Ground-Robot Dataset里面同时装了三维激光雷达、鱼眼相机、RGB-D 相机、红外相机、IMU 和 RTK 接收机场景从室外马路一路铺到电梯轿厢里。它填的是一个很具体的坑KITTI、nuScenes 这些明星数据集是给自动驾驶准备的平台是车、工况是高速、视角是车顶俯视而绝大多数服务机器人、巡检机器人、AGV 压根不在那个工况里跑。你要做激光 SLAM、视觉惯性里程计或者多模态融合需要一套能真实暴露几何退化和视觉退化的评测数据这份东西值得花几天时间认真啃一遍。1. M2DGR 补的是哪块空白从车载数据集到地面机器人的工况落差1.1 KITTI 和 nuScenes 为什么喂不饱地面机器人先说清楚一件事KITTI 和 nuScenes 都是极好的数据集问题不在于它们质量差而在于它们描述的运动和场景跟地面机器人不是一回事。KITTI 的采集车跑在城区和高速上速度动辄几十公里每小时传感器架在车顶一米七以上视野开阔几乎不存在前方三米是墙这种情况。它的真值来自高精度组合导航室外开阔天空下卫星信号稳定轨迹精度能到厘米级。这套设定对自动驾驶算法是合理的但你把同一套算法搬到一台身高四十厘米、跑在一点二米宽走廊里的轮式机器人上会立刻遇到三个新问题视角被墙和门框挤满激光雷达打在近处的点占比极高运动以频繁的原地转向和低速蠕行为主IMU 的零偏和尺度误差被放大场景里存在大量几何自相似结构走廊两侧平行墙面让沿走廊方向的约束几乎消失。nuScenes 在传感器丰富度上比 KITTI 好很多六相机加多雷达城市场景也更复杂。但它的运动模型依然是车辆运动学平面近似成立z 轴方向基本没有变化。而地面机器人会上坡、会进电梯、会被抬起来搬走、会在草地和减速带上抖到怀疑人生。M2DGR 的价值就在这里。它把平台换成了一台真实的小型轮式地面机器人保留多模态传感器的丰富度同时把场景往难受的方向推——走廊、电梯、门口、草地、坡道这些在车载数据集里几乎不会出现或者只出现几帧的场景在这里是主力。1.2 三十多条序列、八类场景难的地方到底在哪官方口径是三十多条序列、覆盖八类典型场景每条序列长度大致在一到五分钟之间。这个规模听起来不算大但你要理解它的设计逻辑它不是靠数据量取胜而是靠场景的针对性。我把几类场景按难度排个序说说各自卡在哪。室外道路和广场类序列相对友好天空开阔RTK 真值有效激光雷达和视觉都有足够特征主要考验的是标定精度和时间同步。这类序列适合用来验证你的系统基线是否正常如果连这类都跑不出合理轨迹那问题一定出在标定或者话题配置上不用往下查。长走廊类序列是真正开始难受的地方。两侧墙面平行且纹理重复激光雷达扫描到的点几乎全落在一个平面上沿走廊方向的平移约束退化视觉上重复的瓷砖和门框让特征匹配频繁误配。这类序列里你会观察到一种很典型的现象俯仰角和横滚角估计得挺准走廊方向的位置越走越飘。草地和起伏路面类序列的问题在于振动和打滑。轮式机器人在草地上打滑会让轮式里程计彻底失效同时高频振动会污染 IMU 数据视觉相机的图像也会出现轻微的果冻效应。这类序列是检验 IMU 噪声建模和鲁棒滤波的好材料。电梯类序列是我个人认为最有价值的一类。金属轿厢内壁卫星信号完全不可用激光雷达打出去的点全在四面墙上视觉上除了门缝几乎没有可跟踪特征而且电梯升降会带来剧烈的 z 轴运动。绝大多数数据集根本没有这种场景但它对写字楼、医院、酒店场景的配送机器人来说就是每天都要经历的日常。1.3 六类传感器不是堆料而是在覆盖两类不同的失效模式很多人看到 M2DGR 的传感器清单第一反应是这么多传感器跑融合一定很强。实际上这套配置的设计意图恰恰相反——它是把激光雷达会退化和相机会退化这两种失效模式塞进同一个数据集里逼你去做互补而不是让你用冗余去掩盖问题。激光雷达解决的是几何问题给出三维结构和尺度信息在光照变化的场景里稳定可靠但遇到长走廊、大平面、玻璃幕墙就会退化。鱼眼相机给的是超大视场角这台机器人身材矮、传感器安装位置低转弯时普通视角相机的视野很容易被自身结构或近处障碍物挡住鱼眼的大视场能缓解这个遮挡问题。RGB-D 相机给的是近距离稠密深度室内纹理弱、光照差的时候靠稀疏特征点的视觉里程计很容易掉稠密深度能提供额外的几何约束。红外相机处理的是可见光失效的场景比如强逆光或者低照度环境热特征在那里可能比灰度特征更可靠。IMU 提供高频运动先验几百赫兹的输出在两次激光扫描之间补齐运动同时也给重力方向一个绝对的参考。RTK 接收机提供厘米级绝对真值这是评测的基础。这个组合背后其实是一个很务实的分工不同传感器覆盖不同的失效区间谁在什么时候失效、另一个能不能顶上就是这套数据集想让你研究的问题。2. 在跑第一条轨迹之前数据获取、目录结构和标定信息的正确读法2.1 获取渠道和下载策略上的现实取舍M2DGR 的下载不是点一下就完事官方走的是申请制——填一份表单说明用途然后拿到下载链接。这个流程本身不复杂但要有心理准备商用或者论文用途填写清楚会顺利很多。下载环节有两个实际建议。第一是不要一上来就把全部序列拉下来原始 rosbag 的数据量在几十到上百 GB 这个量级分卷压缩、校验、解压再占一遍空间硬盘会很难受。我的做法是先只拿三条序列一条室外道路、一条长走廊、一条电梯。这三条覆盖了简单—中等—困难三个档位足够把环境搭好、把工具链跑通。第二是解压后立刻做一次完整性检查。rosbag 分卷文件如果传输过程中断过解压看起来成功但播放到某个时间点会报错这种问题在后期调算法的时候会浪费你大量时间。播放前用rosbag info先过一遍确认消息数量和时长都合理。# 先看 bag 的基本信息消息数、时长、话题列表 rosbag info m2dgr_corridor_01.bag # 播放时锁定时钟配合 use_sim_time 使用 rosbag play --clock -r 0.5 m2dgr_corridor_01.bag2.2 目录组织与序列命名的一般规律每条序列基本是一份独立的 rosbag配套的还有标定文件和真值文件。序列命名大致遵循场景名加序号的形式同一场景下的多条序列用编号区分方便你按场景做批量评测。标定文件通常包含三类内容各相机的内参和畸变参数、相机与激光雷达之间的外参、激光雷达与 IMU 之间的外参。真值文件一般是以 TUM 格式给出的位姿序列每行是时间戳加位置加四元数可以直接喂给 evo 做误差统计。官方还配了一个工具包主要用途是处理图像数据的格式转换和标定辅助。这个工具包非常重要原因在第 3 节会详细说。提示把标定文件和工具包单独复制到一个干净的工作目录里不要跟 bag 混在一起。后面你会发现改外参、换畸变模型、对比不同参数是家常便饭标定文件乱放会让版本管理彻底失控。2.3 外参方向搞反是最高频的低级错误外参矩阵的方向搞反是这类多传感器数据集上排名第一的低级错误而且它的症状很迷惑算法能跑轨迹看起来也像那么回事只是误差莫名其妙地大或者在某些路段突然崩掉。判断方向的原则是记住从哪到哪的写法。T_lidar_cam和T_cam_lidar互为逆语义完全不同。如果你不确定官方给的是哪个方向用一个五分钟就能做完的验证方法挑一帧有清晰竖直墙面和水平地面的点云用你手里的外参把点云投影到图像上然后打开图像对应帧叠在一起看。如果点云轮廓和图像里的墙面边缘、桌角、门框对齐得很好方向就是对的如果整体错位甚至镜像翻转基本就是把方向搞反了。除了方向和数值还有三个容易被忽略的细节。旋转矩阵要用正交性检查一下R * R^T是不是接近单位阵误差超过千分之一说明数值精度有问题。四元数的顺序要确认是 xyzw 还是 wxyz不同库的默认约定不一样。欧拉角的旋转顺序也要确认是 ZYX 还是 XYZ这两种在俯仰角接近九十度时结果差异巨大。时间偏移同样重要。相机和 IMU 之间存在触发延迟如果这个偏移没标定或者标错了视觉惯性里程计的尺度估计会一直偏。校准的土办法是让机器人做几次快速原地旋转和急停然后把 IMU 的角速度曲线和相机帧间光流的大小做时间对齐找出让两者峰值重合的偏移量。3. 让数据真正跑起来图像解码、时间同步和话题重映射3.1 ROS 版本选择和依赖处理的取舍M2DGR 原始数据是标准的 ROS bag 格式用 ROS1 的 Noetic 是最省事的路径工具链成熟几乎所有开源 SLAM 方案都有现成的 ROS1 版本。如果你已经在 ROS2 生态里可以用 rosbag 转换工具把 bag 转成 ROS2 格式再播放但要注意转换过程中自定义消息类型需要先编译对应的消息包这一步经常卡人。我个人在两种场景下的选择不一样。做算法对比实验的时候用 ROS1因为生态里的成熟方案多改起来的成本低。做工程验证、考虑往实车部署的时候用 ROS2因为长期来看更干净只是要接受前期配置的额外开销。依赖方面最容易被忽略的其实是image_transport相关的插件。M2DGR 的图像话题是压缩存放的解码需要对应的传输插件缺了它你会看到话题存在但订阅不到数据。3.2 H.264 图像解码是绕不过去的一课这是整份数据集上最容易被低估的一个环节。为了控制数据体积官方把图像以视频压缩的方式存放直接用常规的图像订阅工具去看要么什么都看不到要么报解码错误。这不是数据坏了而是需要专用的解码流程。处理办法有两条路。第一条是用官方工具包把压缩话题解码成标准图像话题适合快速查看和调试。第二条是把整条序列的图像批量解成图片文件或者新 bag适合需要反复读图的视觉算法。我一般推荐第一条路原因是存储成本。原始 bag 里图像占比不大但解成 PNG 之后体积会膨胀十倍以上一条五分钟的序列就能吃掉几十 GB。只有在做视觉 SLAM 调参、需要反复看图像质量的时候才值得把某一条序列解出来。3.3 话题名称、频率与同步方式的实操细节表里的频率是量级参考具体以rosbag info的实际输出为准。话题名也可能因序列而异动手之前先看一遍再说。传感器典型话题类型频率量级使用时的注意点三维激光雷达PointCloud210 Hz点数量大注意 ring 字段和扫描线数配置鱼眼相机压缩图像20-30 Hz需解码畸变模型多为等距模型RGB-D 相机图像加深度15-30 Hz彩色与深度可能不同步深度有效距离有限红外相机压缩图像20-30 Hz像素深度和灰度动态范围与可见光不同IMUImu100-200 Hz高频注意角速度和加速度的单位与噪声RTK 接收机定位消息1-10 Hz只有室外有效需检查固定解状态时间同步这块很多人第一反应是用message_filters的近似时间同步器然后随便填个队列大小就上。这里有两个坑。第一个坑是队列大小和最大时间间隔的关系。队列太大会匹配到时间上差很远的消息引入伪同步队列太小在丢帧的时候同步直接失败导致算法收不到数据。我的经验值是队列长度取传感器频率差的三到五倍最大时间间隔取最慢传感器周期的百分之五十到八十然后根据实际丢帧率微调。第二个坑是时钟源。播放 bag 的时候一定要加--clock参数同时把节点的use_sim_time设为 true。如果忘了这一步节点用的是系统墙上时钟而消息时间戳是录制时间两者可能差好几个月同步器会彻底罢工而且报错信息通常很隐晦让人一头雾水。话题重映射看起来是最没技术含量的活但它导致的失败案例一点都不少。不同 SLAM 方案对话题名和消息类型的要求不一样有的要求 IMU 话题带协方差字段有的要求点云必须带 ring 字段有的要求图像必须是标准图像话题而不是压缩话题。每次换一个算法框架第一件事就是把这几个要求逐条核对一遍能省下大把排查时间。4. 各流派 SLAM 方案在 M2DGR 上的适配与调参要点4.1 激光雷达惯性方案性能差异主要来自退化处理激光雷达惯性里程计是最容易被 M2DGR 打脸的类别因为它在开阔场景里表现太好了好到让人忘记它有多依赖结构特征。紧耦合的方案对 IMU 的依赖度更高好处是能平滑掉激光扫描之间的运动畸变在快速旋转时表现更稳。松耦合的方案实现简单但在剧烈运动下容易因为点云畸变校正不到位而失准。实测下来的相对关系是室外开阔序列上各方案差距不大走廊和电梯序列上差距会被放大好几倍。外参配置是最容易出错的地方。激光雷达到 IMU 的旋转外参通常不是单位阵因为两者安装朝向不同很多人以为装在同一块板子上就默认是单位旋转结果跑出来的轨迹在转弯时总是往一个方向偏。扫描线数和水平分辨率这两个参数必须跟传感器实际规格匹配配错了的表现是点云被错误地按环索引切分地面和墙面混在一起里程计输出一堆莫名其妙的跳跃。32 线机械雷达的水平点数跟 16 线、64 线都不一样一定要按实际值填。还有一个特别实用的技巧调参不要一上来就调滤波器参数。先拿室外序列把外参和扫描参数确认死确认轨迹合理之后再拿走廊和电梯序列去暴露退化问题。如果直接拿最难的序列调参你会分不清是参数问题还是场景问题。4.2 视觉与视觉惯性方案畸变模型是分水岭视觉类的方案在 M2DGR 上最大的门槛不是特征点数量而是畸变模型。鱼眼相机厂商的畸变特性跟针孔加径向切向模型差得很远必须用等距模型一类的专门模型来建模。很多开源方案默认配的是针孔模型你直接把鱼眼内参填进去它能把畸变系数硬算出一组数来程序也不会报错但特征点的归一化坐标是错的三角化出来的深度全乱套。这是我在这个问题上踩过最久的一个坑——程序不崩只是精度差你很难第一时间怀疑到畸变模型上。RGB-D 相机看起来最省事因为深度直接给了。但它有三个现实问题。彩色和深度图像之间在时间上可能不是严格同步的快速运动时两者的错位会带来明显的深度误差。深度相机的有效量程有限超过一定距离深度值无效或者噪声极大室内走廊这种场景里超过三米基本就不能用了。红外散斑在有阳光直射或者大面积无纹理表面的场景下会失效表现出来就是深度图上出现大片空洞。针对这三点我的一般做法是对 RGB-D 只使用有效量程内的深度超过阈值直接置为无效宁缺毋滥在快速运动段降低深度权重靠 IMU 或者视觉特征顶过去对有阳光直射的室外序列干脆放弃深度通道只用彩色图像做纯视觉或者视觉惯性。4.3 多模态融合真正能吃到红利的位置跑过一轮之后你会发现多模态融合的好处不在平均意义上的精度提升而在于失效切换时不崩。在开阔场景里加了红外或者深度的融合方案跟纯激光方案差距很小投入产出比看起来很低。但在电梯、长走廊、强逆光这几类场景里融合方案的价值就体现出来了。这里给一个我自己常用的分工思路。场景类型主力传感器备份传感器融合策略重点室外开阔激光雷达加 RTK视觉精度优先紧耦合长走廊IMU 加视觉激光雷达抑制几何退化方向的漂移电梯轿厢IMU视觉、深度重力对齐与零速检测草地起伏激光雷达IMU抑制振动带来的高频噪声低照度红外、深度激光雷达特征可用性判断这套分工背后的判断依据是哪个传感器在当下这个场景里没有退化。真正难的部分不是融合本身而是退化检测——你得先知道谁失效了才谈得上加权或者切换。M2DGR 提供了现成的失效场景正好拿来标定你的退化检测阈值。5. 评测环节真值怎么用才不算自己骗自己5.1 RTK 真值的有效区间和需要剔除的时段拿到真值文件不代表可以直接算误差必须先做一遍数据清洗。RTK 有几种典型的不良状态。固定解丢失时会退化为浮点解甚至单点解精度从厘米级掉到米级。城市环境里高楼和树冠会造成多路径效应定位出现突跳。进入室内和电梯之后完全没有信号真值要么中断要么输出乱值。清洗的方法是检查定位状态字段和卫星数只保留固定解且卫星数足够的时段。再结合速度做一次合理性检查如果相邻两帧之间算出来的速度超过物理可能的上限这一段就要剔除。我一般的做法是把速度阈值设在机器人最大速度的一点五倍左右宁可多剔一点也不要让脏数据污染统计结果。注意室内和电梯序列没有可用的绝对真值这一点必须提前接受。在这些序列上你要做的是相对评测——闭环误差、分段一致性、重力方向估计而不是绝对轨迹误差。5.2 绝对误差和相对误差的正确计算方式绝对轨迹误差衡量的是整条轨迹的全局一致性相对位姿误差衡量的是局部漂移速度两者回答了不同的问题做实验报告的时候最好都给。用 evo 计算的时候有一个选项必须想清楚。带尺度对齐的评估会把你的尺度误差掩盖掉因为对齐过程会顺手把轨迹缩放到跟真值一样大。而视觉惯性里程计的尺度估计恰恰是核心指标之一如果用了带尺度对齐你测出来的精度会虚高。我的建议是视觉惯性方案报不带尺度对齐的结果纯激光方案因为尺度本来准确用哪种都行但要在报告里写清楚用了哪种。# 绝对轨迹误差SE(3) 对齐不做尺度修正 evo_ape tum ground_truth.txt estimated.txt -a -p --plot_modexyz # 相对位姿误差评估局部漂移 evo_rpe tum ground_truth.txt estimated.txt -a -p --delta 1 --delta_unit m # 一次性对比多条轨迹适合做方案对比实验 evo_traj tum run_a.txt run_b.txt --refground_truth.txt -p --plot_modexy还有一个容易被忽略的问题时间戳对齐。估算轨迹和真值轨迹的时间戳往往不是严格对应的evo 会做插值但如果两条轨迹的时间戳偏差过大插值出来的对应关系就是错的误差统计会完全没有意义。跑完 evo 之后一定要看一眼对齐后的轨迹图如果两条曲线在时间上明显错位先解决时间戳问题再说。5.3 退化序列该怎么量化光报 ATE 没意义在电梯和长走廊序列上只报一个全局绝对误差是没有信息量的。电梯序列只有几十秒整体尺度小ATE 看起来往往不大但这条轨迹的重力对齐可能已经崩了。我推荐三个更有区分度的指标。第一个是分段误差把轨迹按时间或者距离切成若干段逐段算误差看误差是均匀增长还是某一段突然跳变后者说明系统在某个特定时刻失效了。第二个是最大瞬时漂移用滑动窗口算局部误差的峰值它能暴露那些被平均值掩盖的短时失效。第三个是闭环前后差如果序列本身有回环比较回环前后的轨迹差能直接反映累积漂移。对于电梯序列额外加一个重力方向误差把估计轨迹在静止段的姿态跟实际重力方向做对比。这个指标对 IMU 零偏和重力对齐的建模质量非常敏感比位置误差更有诊断价值。6. 文档里没写、但一定会遇到的几个坑6.1 时间戳跳变与丢帧的处理策略rosbag 录制过程中如果磁盘写入跟不上会出现丢帧表现出来是某个话题在一小段时间内没有消息。这对松耦合方案影响不大但对紧耦合的视觉惯性方案是致命的因为滤波器需要连续的时间序列来传播状态。处理办法是在播放前先统计一下各话题的时间间隔分布找出异常大的间隔位置。如果丢帧不严重可以调整同步器的最大时间间隔让它容忍过去如果丢帧集中在一段时间最干净的做法是把这段整体裁掉用rosbag filter按时间范围重新生成一个子 bag。# 按时间范围裁剪 bag去掉问题时段 rosbag filter input.bag output.bag t.to_sec() 100 and t.to_sec() 2006.2 畸变模型、像素格式和内参深度这些细节除了前面说的鱼眼畸变模型还有几个细节值一提。红外图像的位深和灰度动态范围跟可见光不一样有些算法默认按 8 位灰度处理拿到 16 位红外图会直接截断特征全丢。处理前先确认像素编码格式。RGB-D 的彩色内参和深度内参通常是两套各自有自己的畸变参数做深度与彩色配准的时候要用各自的内参用错了会出现边缘重影。标定文件里的内参可能是以不同分辨率给出的比如标定时用的是全分辨率而你实际使用的时候做了降采样这时内参必须按比例缩放主点坐标也要跟着变。这属于特别容易忘的一步而且忘了之后表现是误差普遍偏大但没有明显异常非常难查。6.3 存储和算力的规划建议原始数据加解压后的图像很容易让一块一 TB 的硬盘告急。我的做法是建立三级存储策略原始 bag 保留在慢速大容量盘上只把当前实验需要的几条序列放到 SSD解压出来的图像只在调试期间保留调完立刻删中间结果和轨迹文件单独一个目录按实验编号归档。算力方面如果是想在边缘计算平台上跑视觉 SLAM需要注意一个现实很多视觉惯性方案的单线程里程计在 ARM 架构上跑不到实时尤其是在高分辨率鱼眼图像上。常见的优化方向是把特征提取放到 GPU 或者专用的视觉加速单元上把里程计主体留在 CPU 上同时把图像分辨率降到实际需要的水平。参数化的时候不要照搬论文里的配置要在目标平台上实测每一帧的处理耗时找到能跑满传感器频率的配置组合。7. 拿 M2DGR 做点不一样的事几个值得深入的方向7.1 复现多模态融合论文时的现实预期数据集有了很多人第一件事是找几篇多模态融合的论文复现。这里要有个心理预期论文里的结果大多在自己的私有数据集上采集方式、标定精度、时间同步质量都跟公开数据集有差异。你在 M2DGR 上复现不出论文里的数字未必是方法有问题。比较靠谱的做法是先建立一套自己信得过的基线。用同一条序列、同一套外参、同一个评测脚本把三到四个开源方案跑出结果形成一张参照表。之后无论换什么新方法都是往这张表里加一列这样你才有判断力去区分方法本身有效和调参调对了。7.2 退化检测一个被低估但很值钱的方向多模态融合里真正难的不是融合公式而是判断现在该信谁。M2DGR 恰好提供了各种退化场景非常适合用来做退化检测的研究。一个可行的切入点是基于激光点云的结构分析。把点云按方位角分块对每块做协方差分析看特征值分布。如果某个方向的特征值分布高度扁平说明这个方向缺乏几何约束属于退化方向。把退化方向打印出来跟实际场景对照你很快就能标定出一套阈值。同样的思路可以用在视觉侧统计特征点数量、匹配内点率、光流一致性形成视觉置信度。把这两路置信度做融合得到一个当前该信谁的权重再喂给后面的融合模块。这套思路不复杂但在实际工程里非常有用而且用 M2DGR 标定出来的阈值能直接迁移到实车上。7.3 从数据集到实车真正的鸿沟在哪最后说一点务实的。在 M2DGR 上跑出好看的轨迹跟实车上稳定运行中间隔着的不是算法而是三件事传感器型号不同导致的内外参不同、时间同步机制不同导致的数据质量不同、机械结构和振动特性不同导致的噪声特性不同。我的建议是把这个数据集当成算法验证台而不是性能证明书。在上面验证的是你的算法在退化场景下的行为是否合理、你的退化检测是否可靠、你的参数是否有一致的物理意义。至于实车部署那是另一个战场标定、同步、散热、算力预算每一项都能单独写一篇长文。我个人在这套数据上花了大概两个月最大的收获不是某个算法跑出了多少精度的数字而是第一次清楚地看到了自己那套系统在什么情况下会坏。这个认知比任何单条轨迹的误差曲线都值钱。
返回列表