3、轨迹数据格式详解:TUM格式、KITTI格式、EuRoC格式、ROS bag中的/tf与/odom话题
做SLAM轨迹评估,第一关就是搞懂数据格式。
我见过太多同学,算法写得飞起,结果栽在格式转换上。明明轨迹是对的,评估工具就是不认。说白了,就是没搞清楚这些格式到底在表达什么。
今天咱们就把四种最常见的轨迹格式掰开揉碎讲清楚。你想想看,搞懂了这些,后面做评估才能得心应手。
3.1 TUM格式:最直观的轨迹表示
TUM格式来自慕尼黑工业大学。我个人习惯把它叫做「时间戳+位姿」格式。为什么?因为它太直白了。
# 每一行:timestamp tx ty tz qx qy qz qw
# 示例:
1.234567890 1.0 2.0 3.0 0.0 0.0 0.0 1.0
2.345678901 1.1 2.1 3.1 0.01 0.01 0.0 0.9999
格式很简单:时间戳 + 平移 + 四元数。时间戳单位是秒,平移单位是米。
关键点:四元数的顺序是 qx qy qz qw,不是 qw qx qy qz。这个顺序搞反了,轨迹直接飞掉。
我在项目中遇到过一件事。有个同学用evo评估,结果轨迹误差大得离谱。查了半天,原来是四元数顺序写反了。嗯,这种坑踩一次就记住了。
3.2 KITTI格式:自动驾驶的标配
KITTI格式是自动驾驶领域的标杆。它不存时间戳,只存位姿。为什么?因为KITTI的数据采集频率是固定的10Hz,时间信息可以从帧号推算。
# 每一行:3x4变换矩阵,按行展开
# 示例:
1.0 0.0 0.0 1.0 0.0 1.0 0.0 2.0 0.0 0.0 1.0 3.0
这个矩阵是 R|t 的形式。前三列是旋转矩阵,最后一列是平移向量。
小技巧:KITTI格式没有时间戳。如果你需要时间信息,得自己维护一个时间戳列表。我一般会单独存一个timestamp.txt文件。
我曾经在评估KITTI数据集时,发现轨迹和真值对不上。后来才意识到,KITTI的坐标系是「右-下-前」,而我的算法用的是「右-前-上」。坐标系不统一,评估结果就是废的。
3.3 EuRoC格式:视觉惯导的宠儿
EuRoC格式和TUM格式很像,但多了一个东西:协方差矩阵。
# 每一行:timestamp, p_x, p_y, p_z, q_x, q_y, q_z, q_w, cov_matrix(6x6)
# 示例:
1.234567890 1.0 2.0 3.0 0.0 0.0 0.0 1.0 0.01 0.0 0.0 0.0 0.0 0.0 ...
协方差矩阵是6x6的,对应位置和姿态的不确定性。这个信息在做融合或者滤波时特别有用。
注意:EuRoC的协方差矩阵是上三角存储的。解析时别搞成下三角,否则结果完全不对。
我个人习惯在评估EuRoC轨迹时,会先检查协方差矩阵的对角线元素。如果数值特别大,说明这个位姿估计不太靠谱,我会考虑把它剔除掉。
3.4 ROS bag中的/tf与/odom话题
ROS bag是实际工程中最常见的格式。但也是最容易出问题的。
/tf话题:坐标变换树
/tf话题发布的是坐标变换关系。每个变换包含:
- frame_id:父坐标系
- child_frame_id:子坐标系
- transform:平移+旋转
- timestamp:时间戳
举个例子,如果你看到:
frame_id: "odom"
child_frame_id: "base_link"
transform: [1.0, 2.0, 3.0, 0.0, 0.0, 0.0, 1.0]
这表示base_link在odom坐标系下的位姿。
核心要点:/tf发布的是相对变换,不是绝对位姿。要得到完整轨迹,你需要从tf树中提取出连续的变换序列。
/odom话题:里程计数据
/odom话题包含的信息更丰富:
- pose:位姿(位置+姿态)
- twist:速度(线速度+角速度)
- covariance:协方差矩阵
我建议优先使用/odom话题做评估。为什么?因为它自带协方差信息,而且数据更完整。我在项目中遇到过,/tf话题有时候会丢帧,但/odom话题一般不会。
3.5 格式对比与选择建议
| 格式 | 时间戳 | 位姿表示 | 协方差 | 适用场景 |
|---|---|---|---|---|
| TUM | 有 | 四元数+平移 | 无 | 通用评估 |
| KITTI | 无 | 3x4矩阵 | 无 | 自动驾驶 |
| EuRoC | 有 | 四元数+平移 | 有 | 视觉惯导 |
| ROS bag | 有 | 多种形式 | 可选 | 实际工程 |
选哪种格式?我的建议是:
- 做学术评估,用TUM格式。工具支持最好。
- 做自动驾驶,用KITTI格式。行业标准。
- 做视觉惯导,用EuRoC格式。协方差信息很有用。
- 做实际工程,从ROS bag里提取。最贴近真实场景。
3.6 格式转换实战
实际工作中,你经常需要在不同格式之间转换。我分享一个常用的转换思路:
# TUM转KITTI示例(Python伪代码)
def tum_to_kitti(tum_file, kitti_file):
with open(tum_file, 'r') as f:
lines = f.readlines()
with open(kitti_file, 'w') as f:
for line in lines:
# 解析TUM格式
parts = line.strip().split()
t = float(parts[0])
tx, ty, tz = float(parts[1]), float(parts[2]), float(parts[3])
qx, qy, qz, qw = float(parts[4]), float(parts[5]), float(parts[6]), float(parts[7])
# 四元数转旋转矩阵
R = quaternion_to_matrix(qx, qy, qz, qw)
# 构建3x4矩阵
T = np.eye(4)
T[:3, :3] = R
T[:3, 3] = [tx, ty, tz]
# 按行展开写入
f.write(' '.join(map(str, T[:3, :].flatten())) + '\n')
避坑指南:我曾经在转换时忘记处理时间戳对齐。TUM格式的时间戳是浮点数,KITTI没有时间戳。如果你需要时间信息,记得单独保存。
3.7 本章知识体系
下面这张图展示了四种轨迹格式的核心关系:
搞懂了这些格式,你就能在评估工具和实际数据之间自由切换。嗯,这就是做轨迹评估的第一步。
总结一下:格式只是载体,核心是位姿数据本身。不管用什么格式,确保时间戳对齐、坐标系统一、四元数顺序正确,评估结果才可信。
可可精品资料库