
简介面向SLAM、自动驾驶与微型无人机方向研究者的数据集总结文档系统梳理了TUM RGB-D、KITTI、EuRoC三大公开数据集的采集设备、数据格式、真值标注与评估指标。压缩包内为单个docx文件共1个文件约1.93MB便于随时查阅。目前已有9609人浏览学习适合作为入门数据集认知与选型参考。文档内容较为详尽TUM部分涵盖彩色图与深度图的PNG存储、比例缩放规则、groundtruth轨迹txt格式以及ATE与RPE评价指标和点云生成方法KITTI部分介绍了采集平台所搭载的惯性导航系统、激光扫描仪、灰度与彩色相机等传感器配置以及raw data等数据组织方式EuRoC部分则说明微型无人机多传感器数据特点。这些梳理能帮助读者在SLAM、自动驾驶、无人机等实验与论文复现中快速理解数据来源与评测方法。1. 三个数据集不只是“录数据”而是一套精心布设的评测装置大多数开发者第一次接触 TUM、KITTI、EuRoC 时第一反应都是“找一段 rosbag 跑一下 SLAM”。但真正把这些数据集用明白的人会告诉你数据集的复杂度不在于传感器多贵、场景多真实而在于它的“评测设计”——TUM 的深度图为什么要缩放 5000 倍KITTI 为什么要拿激光雷达的正前方时刻当快门基准EuRoC 为什么非要把 IMU 中心定义为机体坐标系原点这些细节决定了你从数据集里读出的轨迹精度数字到底可不可信。把三个数据集放在一起看本质上是三种典型的 SLAM 传感器配置RGB-D 单目加深度、多传感器自动驾驶平台、双目加 IMU 的无人机。它们共享同一个难题——如何把一次 SLAM 运行的轨迹误差变成一个可复现、可比较的量化指标。搞懂这套评测装置比多跑几个序列更有价值。2. TUM RGB-D深度图缩放、四元数轨迹与 ATE/RPE 的数学本质2.1 深度图为什么是 16 位、为什么偏偏缩放 5000 倍TUM 的深度图以 PNG 格式存储为 640x480 的 16 位单色图像彩色图则是 8 位 RGB。这里最反直觉的是深度图的编码方式像素值 5000 对应 1 米也就是深度值等于像素值除以 5000.0而像素值 0 被规定为缺失值。为什么不用浮点深度、也不用 8 位整数16 位 PNG 在解码上比浮点深度的二进制格式省事得多PNG 无损压缩对 16 位数据的压缩率也稳定而且缩放 5000 倍后1 毫米的深度变化对应 5 个像素值量化精度对视觉 SLAM 足够用。常见的实现思路是把depth_px / 5000.0当成实际米制深度但要注意一个坑0 像素值必须被过滤否则点云里会出现一堆位于相机光心处、距离为 0 的杂点。import numpy as np import imageio.v2 as imageio depth imageio.imread(depth.png).astype(np.float32) depth_m depth / 5000.0 mask depth 0 # 0 是缺失值不能用 points_z depth_m[mask]深度误差在视觉 SLAM 里不是均匀分布的同样的像素深度误差在远距离处会被放大因为三角化误差与距离平方近似成正比。TUM 的室内场景密度大、物体近能把这个误差控制在小范围内。理解 5000 倍缩放本质上就理解了 Kinect 这类消费级深度传感器的量化噪声边界。2.2 groundtruth 轨迹格式为什么是 tx ty tz qx qy qz qwTUM 的真值存放在 txt 里每行格式为timestamp tx ty tz qx qy qz qwtimestamp 是 Unix 纪元以来的浮点秒数位置是彩色相机光学中心相对于运动捕捉系统世界原点的坐标姿态用单位四元数表示。这里值得追问的是为什么不用欧拉角或者干脆用旋转矩阵四元数只有 4 个分量、没有万向锁问题、插值方便更重要的是 SVD 对齐时四元数转旋转矩阵是线性操作。欧拉角的俯仰角接近 ±90° 时数据集的真值会突然出现跳变这种跳变不是传感器误差是表示方式的奇异性。用四元数存储姿态的连续性在数学上是被保证的。另一个容易忽略的细节四元数给出的方向是彩色相机光学中心的朝向而不是深度相机或 IMU 的朝向。这意味着你在评估自己的 SLAM 系统时输出的估计姿态必须是“彩色相机坐标系下的姿态”否则对齐后误差会带上一个固定旋转偏移。# rgbd_dataset_freiburg1_xyz 某行真值结构 1341845746.621552 -0.055673 0.010236 -0.007318 0.999504 -0.001873 0.011427 -0.028243 # 时间戳 tx ty tz qx qy qz qw该行含义是在 1341845746.62 秒时刻彩色相机光心位于运动捕捉系原点附近的 (-0.056, 0.010, -0.007) 米处朝向由最后一个四元数给出。注意位置和姿态都是相对于世界坐标系的而不是相对于上一帧。2.3 ATE 的 SVD 对齐到底在“消除”什么绝对轨迹误差ATE的思路很直接把估计轨迹和真值轨迹按时间戳关联后先做一个刚体变换对齐再计算逐点差异。但为什么要对齐因为你的 SLAM 系统估计出来的轨迹通常不在真值坐标系里——单目 SLAM 初始化任意RGB-D SLAM 的世界系也可能和运动捕捉系差一个旋转平移。TUM 官方评估脚本用的正是 Kabsch 算法对两组对应点求质心用 SVD 分解协方差矩阵得到旋转矩阵再算出平移。import numpy as np def kabsch_align(P, Q): # P: 估计轨迹位置 (N,3), Q: 真值轨迹位置 (N,3) centroid_P P.mean(axis0) centroid_Q Q.mean(axis0) H (P - centroid_P).T (Q - centroid_Q) U, _, Vt np.linalg.svd(H) R Vt.T U.T if np.linalg.det(R) 0: # 保证右手坐标系否则会出现镜像旋转 Vt[-1, :] * -1 R Vt.T U.T t centroid_Q - R centroid_P aligned (R P.T).T t return aligned, np.linalg.norm(aligned - Q, axis1).mean()SVD 求出来的 R 一定是一个正交矩阵但正交矩阵包括镜像反射行列式为 -1所以代码里必须检查行列式。这个细节是很多自写评估脚本翻车的重灾区——如果不处理对齐后的轨迹会被“镜像”过去误差大得离谱但你看不出哪不对。2.4 RPE 固定窗口与漂移测量的关系相对姿势误差RPE不关心全局坐标系它计算的是“一段时间间隔内相对运动的误差”。官方脚本默认计算所有时间戳对之间的误差但这个数量是轨迹长度的平方级所以必须用-max_pairs下采样或者用-fixed_delta固定窗口。RPE 测量的是视觉里程计的漂移率比如每秒漂移多少米。注意 TUM 对 RPE 的定位是“测量视觉测距系统的漂移”对 ATE 的定位是“测量可视 SLAM 系统的性能”。如果你的算法是带闭环的 SLAMATE 更合适如果只是纯里程计RPE 更能反映真实漂移。窗口太小RPE 只反映短时噪声窗口太大漂移被平均掉。一般做法是先跑一个-delta_unit s -delta 1再跑一个-delta 5对比观察漂移是否随时间线性增长。3. KITTI激光雷达快门同步、syncedrectified 与自动驾驶数据的时间基准3.1 为什么要等激光雷达朝向正前方才释放快门KITTI 的采集平台上有两个灰度相机、两个彩色相机和一个 64 线激光扫描仪所有传感器以 10Hz 采集。硬件设计里有个容易被忽略的细节相机快门在激光雷达朝向正前方时释放。原因在于激光雷达是旋转扫描的一帧 360° 点云不是瞬时采集的而是花 100ms 扫完一圈。如果相机快门和雷达扫描相位不对齐图像时刻对应的车体姿态和雷达帧首尾时刻对应的姿态会差几十毫秒这在车辆高速行驶时会导致目标在图像和点云里错位几个像素到几十像素。把快门对齐到雷达朝向正前方的时刻等于给所有数据定了一个统一的“时间锚点”。# 同步逻辑以10Hz雷达为节拍器 # 雷达打到正前方 - 触发相机曝光 - 记录GPS/IMU姿态 - 组成一帧这套硬件同步的替代方案是软件时间戳插值但插值依赖传感器时钟的稳定性和驱动延迟精度远不如快门硬件触发。KITTI 选择硬件同步换来的好处是所有传感器在同一个时间语义下采样评估时不需要再做复杂的时间对齐。3.2 raw data 与 syncedrectified两个词各自解决了什么raw data 里包含两类数据原始的没有同步、没有矫正和处理过的同步且矫正。原始数据保留了畸变和未对齐的时间戳用于标定和传感器建模syncedrectified 数据是经过消除畸变和双目矫正的、且和其他传感器序列对齐过的图像。双止矫正的本质是把左右相机图像投影到同一个虚拟平面上使极线水平对齐。这样做的直接收益是视差计算变成一维搜索深度估计和特征匹配的计算量大幅下降。对 SLAM 评估而言用 syncedrectified 数据可以省掉畸变矫正这一步直接喂给特征提取器。3.3 image_00 为什么是同步参考系KITTI 的 raw data 每个序列都包含 image_00 到 image_03 四路相机外加 velodyne 点云和 GPS/IMU 数据。官方文档明确指出所有传感器数据序列以 image_00 作为同步参考系。也就是说其他传感器的时间戳需要向 image_00 对齐。这个设计动机很实际图像帧率的抖动最小、曝光时间固定、并且彩色和灰度图像成对出现以它为参考系可以保证“看到的就是同时刻的”。工程上的代价是你下载的每个数据包里GPS/IMU 时间戳并非整数 10Hz而是按图像帧打点。评估自己的融合算法时要用插值把 IMU 采样对齐到 image_00 的时间轴上不能直接拿原始时间戳硬比。3.4 object 是单帧tracking 是连续序列数据集结构如何约束算法边界KITTI 的 object 数据集按“2D 检测、3D 检测、鸟瞰图检测”三个任务组织数据本身是单帧训练集带标注、测试集不带。tracking 数据集则是一段连续序列标注以 tracklets 形式给出。object 和 tracking 的差异不是文件组织方式不同而是任务本质不同检测算法不要求帧间关联所以单帧采样即可跟踪算法必须验证时间一致性所以需要连续帧。做多目标跟踪时如果只拿 object 数据训练、用 tracking 数据测试大概率翻车——因为 object 数据里没有帧间遮挡和轨迹碎片这些跟踪特有的难题。数据集结构的边界就是任务定义的边界这个边界在选数据时就要想清楚。4. EuRoCBody Frame 为什么以 IMU 为中心、T_BS 坐标变换约定的工程逻辑4.1 为什么机体坐标系的原点放在 IMU 中心EuRoC 的无人机飞行器上四个传感器双目相机两个 cam0/cam1、惯性测量单元 imu0、激光测距仪 leica0各有各的坐标系但飞行器的 Body Frame 被定义在 IMU 的中心。这个选择背后的逻辑是视觉惯性导航的状态估计里IMU 是积分核心角速度和加速度都定义在 IMU 坐标系下把 Body Frame 定在 IMU 中心就把“积分坐标系”和“状态变量坐标系”合成了同一个避免在每一个 IMU 采样时刻都做一次从 Body 到 IMU 的外参旋转。对惯导系统而言外参标定的误差会二次方地累积进位置所以能省一次变换就省一次。配套地每个传感器文件夹里都有一个 sensor.yaml描述该传感器坐标系到 Body Frame 的变换关系以及内参。这意味着 EuRoC 的数据不是“裸传感器流”而是已经带上了完整的外参定义——用官方给的变换做初始化比从零标定双目-IMU 外参的结果稳定得多。4.2 R_WC 和 T_BS旋转坐标系变换约定的读法EuRoC 的文档里定义了一个容易读反的约定R_WC 表示“将 C 坐标系下表示的向量变换成 W 坐标系下表示”所以 R_WC 实际上是从 Camera 到 World 的旋转矩阵而不是反过来。同理T_BS 表示将所有 Sensor 坐标系下的向量变为 Body Frame 下的向量。import numpy as np # 设 T_BS 是 sensor.yaml 给出的 Sensor-Body 变换 T_BS np.loadtxt(cam0/sensor.yaml的变换部分) # 设 T_WB 是 Vicon 给出的 Body-World 位姿groundtruth 提供 T_WB load_vicon_pose(data.csv, row100) # 链式变换Sensor - Body - World T_WS T_WB T_BS # 验证旋转部分的行列式必须为 1否则坐标系约定读反了 assert np.linalg.det(T_WS[:3, :3]) 0这里最常见的错误是把矩阵乘法的顺序写反。T_WB 表示先取 Body 系下的点变换到 WorldT_BS 表示先取 Sensor 系下的点变换到 Body所以从 Sensor 到 World 必须执行T_WS T_WB T_BS外面的变换矩阵在左边。如果写成T_BS T_WB语义就变成了“先到 World 再到 Sensor”结果轨迹会绕着一个奇怪的轴旋转。4.3 Vicon 动作捕捉系统如何提供毫米级真值EuRoC 的 groundtruth 由 Vicon 动作捕捉系统提供在无人机上贴一组反射标志多台高速红外相机从不同角度观测这些标志重建出刚体在单一坐标系下的 6D 位姿帧率 100Hz、精度毫米级。这套系统的本质是外部基准它的精度比无人机上任何传感器都高一个量级所以能当“真值”用。但注意 groundtruth 给出的是 Vicon 坐标系下的位姿不是你 SLAM 系统自己定义的世界系。所以在评估时你的估计轨迹仍然要做一次类似 TUM ATE 的刚体对齐才能和 Vicon 真值对比。EuRoC 数据里还包含 leica0激光测距仪提供的辅助测量用于校核 Vicon 系统自身的误差。4.4 三个数据集的互补关系室内、室外与空中把三个数据集串起来看它们覆盖了三类典型场景TUM 是室内手持 Kinect运动速度慢、深度信息丰富适合 RGB-D SLAMKITTI 是室外车载运动速度快、场景深度大适合双目视觉和激光雷达融合的自动驾驶EuRoC 是室内无人机快速旋转加剧烈平移恰好是视觉惯性导航最吃紧的运动模式。这种互补决定了按数据集选算法的策略如果你的系统在 TUM 上精度好但在 KITTI 上会飞点多半是深度噪声建模和远距离三角化出了问题如果在 EuRoC 上发散多半是 IMU 与视觉的外参或时间戳对齐有偏差。一个数据集说明不了问题三个数据集的失败模式放在一起才能定位瓶颈。5. 评测避坑时间戳单位、坐标系链式乘法与深度缺失值的五处翻车现场5.1 Unix 浮点秒、KITTI 基准、EuRoC 整数时间戳被混用现象跑通流程后 ATE 误差在几十米量级改哪个参数都没用。原因三个数据集的时间戳语义不同。TUM 的 timestamp 是 Unix 纪元以来的浮点秒KITTI 的时间戳是相对于采集启动时刻的毫秒/微秒整数EuRoC 的 groundtruth 是 18 位整数时间戳单位是纳秒。直接拿两套时间戳做最近邻关联结果自然是错位到相隔几分钟的帧上。解决统一换算成 double 秒。TUM 直接用浮点秒KITTI 用start_time delta / 1e6EuRoC 用ts_ns / 1e9。关联时再设置一个最大时间差阈值如 0.02 秒超过阈值的配对直接丢掉。从那以后我拿到新数据集的第一件事都是写一个时间戳单位探测函数先打印三行样本看量级再进评估流程。5.2 SVD 对齐被少数离群帧拉偏现象ATE 的均值看着不大但轨迹里某一小段明显有鼓包标准差超大。原因Kabsch 算法是最小二乘意义下的对齐少数漂移严重的帧比如快速旋转时特征丢失导致的跳变会把整个刚体变换“拽”向它们导致正常区间也被偏置。解决先做一次粗对齐计算逐点误差后去掉超过 3 倍中位数的离群帧用剩余帧重新做精细对齐。评估脚本里看到的均值/中位数/标准差三个数字要对照着看——均值和中位数差太远就是有离群帧存在。5.3 深度像素 0 值被当成“距离 0 米”生成点云现象点云在相机光心附近出现一团密集的黑色杂点肉眼上像是传感器坏掉了。原因深度图里 0 是缺失值没有深度测量不是距离 0 米。直接把像素值除以 5000.0 再生成 PLY就把缺失点全部堆到了相机原点。解决生成点云前先构建 mask像素值大于 0只保留有效深度像素同时把彩色图像对应像素同步过滤保证点云的颜色和位置一一对应。凡是基于深度图跑点云处理的算法第一步都该是“过滤 0 值”而不是先转成米制浮点。5.4 EuRoC 的 T_BS 乘反了轨迹像被绕了一个轴翻转现象视觉惯性里程计跑出来的轨迹和真值在形状上一致但整体绕某个轴转了 180 度ATE 算下来大得离谱。原因T_BS 的语义是 Sensor 系到 Body 系链式变换必须写T_WB T_BS。把顺序写成T_BS T_WB后几何上变成先到世界再回传感器轨迹被一个错误旋转矩阵扭曲。解决用官方提供的位姿真值做一次单位检查——变换矩阵旋转部分行列式为 1、且用一组已知坐标点做正向变换验证输出方向。建议在工程里开一个“坐标系沙盒”脚本所有外参读取后先在静态数据上验证一遍再做在线融合。5.5 KITTI 的 synced 与 rectified 分开下载后文件名对不上现象下载了同步数据又下载了矫正数据结果图像文件名和点云时间戳对不上程序直接崩。原因KITTI 的 raw data 里 synced 数据和 rectified 数据的文件组织、时间戳基准可能不同。它把“同步”和“矫正”拆成两个下载包两者之间并没有保证文件名一一对应尤其是不同版本解压后目录结构有差异。解决统一用时间戳做关联不要依赖文件名前缀。先读所有数据源的 timestamp 字段按 10Hz 周期取公共时间节点再在这个节点上做传感器数据拼接。以 image_00 时间戳为基准其他传感器全部插值到该时间轴上。6. 设计取舍三套真值系统的共同哲学与“尺子”困境三个数据集都用了同一个策略外部运动捕捉系统提供真值而不是用传感器自身的测量当基准。这背后的取舍是——真值系统的精度必须比被测系统高一个量级否则你量出来的“误差”里混着基准自身的噪声。Vicon 能做到毫米级所以它能刻 IMU 和相机运动捕捉系统做不到室外场景所以 KITTI 只能退而求其次用高精度 GPS/IMU 组合导航做基准。真值精度和场景真实度之间本身就是一对矛盾。ATE 与 RPE 的分工也藏着同一个设计取舍绝对精度和相对一致性是两种不同的系统能力。ATE 对齐后比较全局轨迹适合闭环 SLAMRPE 只关心局部窗口的相对运动适合漂移分析。没有一个指标能同时回答“系统最终有多准”和“系统会不会随时间飘”所以数据集才要同时提供两个评测维度、两份脚本、两种参数调法。这种设计不是冗余而是把“SLAM 系统性能”这个模糊概念拆成了两个可独立优化的目标。从那以后我每到一个新学到的数据集都会先问三个问题真值坐标系的原点定在哪时间戳的单位是什么传感器外参的变换方向按什么约定书写。这三个问题答对了评估脚本才有意义答错了后面所有精度数字都是虚假的安慰。希望帮到你也祝你在 SLAM 这条路上少走我走过的弯路。本文还有配套的精品资源点击获取