4、数据输入格式:支持的数据类型与文件结构解析
做轨迹评估,第一步就是喂数据。但说实话,我见过太多人在这第一步就栽跟头了。数据格式不对,后面所有分析都是白搭。今天咱们就聊聊轨迹评估工具支持的那几种主流数据格式——TUM、KITTI、EuRoC,以及怎么避开那些常见的坑。
4.1 三种主流数据格式概览
目前业内用得最多的,就是这三种格式。我个人习惯把它们分成两类:带时间戳的和不带时间戳的。你想想看,时间戳这东西,直接决定了你能不能做时间对齐。
| 格式 | 来源 | 核心特点 | 时间戳 |
|---|---|---|---|
| TUM | 慕尼黑工业大学 | 每行包含时间戳+位姿 | 有(浮点数,单位秒) |
| KITTI | 卡尔斯鲁厄理工学院 | 纯位姿数据,无时间戳 | 无 |
| EuRoC | 苏黎世联邦理工学院 | 时间戳+位姿,但格式略有不同 | 有(整数,单位纳秒) |
核心要点: 评估工具能不能跑,90%取决于你的数据格式对不对。剩下10%是路径对不对。
4.2 TUM格式详解
TUM格式是我用得最多的,也是评估工具默认支持的格式。它的结构其实很简单,每行7个数字:
# 这是注释行,工具会自动忽略
timestamp tx ty tz qx qy qz qw
举个例子:
1403715273.542 1.234 2.345 3.456 0.123 0.234 0.345 0.912
1403715273.643 1.245 2.356 3.467 0.124 0.235 0.346 0.913
这里要注意几个细节:
- 时间戳:单位是秒,浮点数。我见过有人用整数秒,结果对齐全乱了
- 平移:tx, ty, tz,单位是米
- 旋转:四元数 qx, qy, qz, qw,必须是单位四元数
我的小技巧: 我习惯在文件开头加一行注释,写上数据来源和传感器类型。虽然工具不读,但自己回头看的时候特别有用。
4.3 KITTI格式详解
KITTI格式就有点不一样了。它没有时间戳,每行是一个3x4的变换矩阵:
r11 r12 r13 tx r21 r22 r23 ty r31 r32 r33 tz
说白了,就是把旋转矩阵和平移向量拼在一行里:
0.999 0.012 -0.015 1.234 -0.011 0.999 0.013 2.345 0.015 -0.013 0.999 3.456
嗯,这里要注意:
- 没有时间戳,所以评估时只能按顺序逐帧对比
- 矩阵必须合法,旋转部分必须是正交矩阵
- 12个数字,一个都不能少
警告: 我曾经遇到过一个数据集,旋转矩阵的行列式是-1,结果评估出来的误差大得离谱。后来才发现是坐标系定义反了。
4.4 EuRoC格式详解
EuRoC格式跟TUM有点像,但时间戳是整数纳秒:
timestamp_ns, tx, ty, tz, qx, qy, qz, qw
实际数据长这样:
1403715273542000000, 1.234, 2.345, 3.456, 0.123, 0.234, 0.345, 0.912
1403715273643000000, 1.245, 2.356, 3.467, 0.124, 0.235, 0.346, 0.913
为什么会有这种差异?因为EuRoC数据集是用工业相机采集的,时间精度要求更高。你想想看,视觉SLAM对时间同步的要求有多苛刻。
格式转换提醒: 如果你想把EuRoC转成TUM格式,记得把纳秒除以1e9。我写过一个脚本专门干这事,回头可以分享。
4.5 常见错误格式排查
做轨迹评估这几年,我踩过的坑真不少。下面这些是我遇到最多的:
- 分隔符问题:有人用逗号,有人用空格,有人用Tab。工具一般只认空格或Tab
- 四元数顺序:TUM格式是 qx qy qz qw,但有人写成 qw qx qy qz
- 时间戳单位:秒还是毫秒?纳秒还是微秒?这个搞错了,对齐全废
- 空行和注释:有些文件末尾有多余空行,工具会报错
- 数值精度:小数点后位数太少,导致位姿精度丢失
避坑指南: 我曾经花了一整天调试一个评估结果,最后发现是数据文件里混入了中文字符。嗯,从那以后我写了个格式校验脚本,跑数据前先过一遍。
4.6 格式校验小工具
我自己写了个简单的Python脚本,用来快速检查数据格式:
def check_tum_format(filepath):
with open(filepath, 'r') as f:
lines = f.readlines()
for i, line in enumerate(lines):
if line.startswith('#') or line.strip() == '':
continue
parts = line.strip().split()
if len(parts) != 8:
print(f"第{i+1}行:字段数不对,期望8个,实际{len(parts)}个")
return False
try:
[float(p) for p in parts]
except:
print(f"第{i+1}行:包含非数字字符")
return False
print("格式检查通过!")
return True
建议: 每次跑评估前,先用这个脚本过一遍数据。别问我为什么这么建议——问就是吃过亏。
4.7 知识体系总览
下面这张图,是我总结的数据格式核心逻辑:
说白了,这三种格式的核心就是「位姿数据+时间信息」。KITTI虽然没时间戳,但它的矩阵结构本身也是一种规范。你只要记住一点:工具怎么读,你就怎么给。
最后说一句: 数据格式这事,看起来简单,但真出问题的时候特别隐蔽。我建议你每次换数据集,都先拿小样本跑一遍,确认格式没问题再上全量数据。省得到时候跑了一晚上,第二天发现结果全是错的。