轨迹数据基础:从原始坐标到可用数据
大家好,我是你们的老朋友。今天我们来聊聊轨迹数据的基础处理。
说实话,很多刚入行的同学,一上来就急着调模型、跑网络。结果呢?数据预处理没做好,模型怎么调都不收敛。我当年就吃过这个亏,后来才明白——数据质量决定了模型的天花板。
轨迹数据的表示方法
轨迹数据说白了,就是物体在空间中的运动记录。最常见的表示方式有三种:
1. 坐标表示
这是最直观的方式。每个时间点记录一个位置。
- 二维坐标:(x, y) 或 (经度, 纬度)
- 三维坐标:(x, y, z) 或 (经度, 纬度, 高度)
举个例子,一个行人的轨迹可能是这样的:
t=0s: (2.3, 5.1)
t=0.1s: (2.5, 5.3)
t=0.2s: (2.8, 5.4)
...
嗯,这里要注意:坐标系的选取直接影响后续计算。我在项目中遇到过用经纬度直接算距离的,结果误差大得离谱。为什么?因为地球是球面,经纬度不是等距的。
2. 速度表示
速度是位置对时间的一阶导数。我们通常用两种方式:
- 瞬时速度:当前时刻的速度大小和方向
- 平均速度:一段时间内的位移除以时间
实际项目中,我更喜欢用速度向量 (vx, vy) 来表示。为什么呢?因为它保留了方向信息,对轨迹预测特别有用。
3. 加速度表示
加速度是速度对时间的一阶导数,也是位置的二阶导数。它反映了运动状态的变化。
你想想看,一个急刹车和匀速行驶,加速度完全不同。这对预测车辆行为非常关键。
我的经验:在轨迹预测中,我通常会把位置、速度、加速度都作为输入特征。三者的组合能提供更完整的运动信息。但要注意,加速度对噪声特别敏感,需要先做平滑处理。
坐标系转换
坐标系转换,说白了就是把数据从一个坐标系搬到另一个坐标系。常见的场景有:
1. 地理坐标系 vs 平面坐标系
GPS采集的数据通常是经纬度(WGS84坐标系),但模型训练时我们更习惯用平面坐标(比如UTM坐标系)。
转换公式大致是这样的:
# 伪代码示例
def wgs84_to_utm(lat, lon):
# 这里省略了复杂的投影计算
# 实际项目中可以用 pyproj 库
x = lon * 111320 * cos(lat)
y = lat * 110540
return x, y
避坑指南:我曾经直接用这个简化公式处理高纬度数据,结果误差达到了几十米。后来改用专业的投影库才解决。记住:简化公式只适合小范围区域。
2. 世界坐标系 vs 车辆坐标系
自动驾驶中经常需要把世界坐标转换到车辆坐标系。这样模型看到的数据就是「相对位置」,而不是「绝对位置」。
转换步骤:
- 平移:减去车辆当前位置
- 旋转:乘以车辆朝向的旋转矩阵
import numpy as np
def world_to_vehicle(world_pos, vehicle_pos, vehicle_yaw):
# 平移
relative_pos = world_pos - vehicle_pos
# 旋转
cos_yaw = np.cos(vehicle_yaw)
sin_yaw = np.sin(vehicle_yaw)
rotation = np.array([[cos_yaw, -sin_yaw],
[sin_yaw, cos_yaw]])
vehicle_pos = rotation @ relative_pos
return vehicle_pos
轨迹数据预处理
原始数据通常很「脏」,不能直接用。我总结了三个关键步骤:
1. 去噪
传感器数据难免有噪声。GPS信号飘移、雷达误检,都会产生异常点。
常用的去噪方法:
- 中值滤波:对窗口内的点取中值,能有效去除孤立噪声
- 卡尔曼滤波:利用运动模型预测,再结合观测值修正
- 阈值法:速度或加速度超过物理极限的点直接剔除
小技巧:我习惯先用阈值法粗筛,再用卡尔曼滤波精修。这样效率高,效果也好。阈值怎么定?看你的应用场景。行人一般速度不超过5m/s,车辆不超过30m/s。
2. 插值
传感器采样率不稳定,或者数据有缺失,就需要插值补全。
常见的插值方法:
| 方法 | 适用场景 | 优缺点 |
|---|---|---|
| 线性插值 | 匀速运动 | 简单快速,但不够平滑 |
| 三次样条插值 | 平滑运动 | 曲线光滑,但计算量大 |
| 多项式插值 | 已知运动规律 | 精度高,但容易过拟合 |
import numpy as np
from scipy import interpolate
# 原始数据(有缺失)
t = np.array([0, 1, 2, 4, 5]) # 缺少 t=3
x = np.array([0, 2, 4, 8, 10])
# 三次样条插值
f = interpolate.interp1d(t, x, kind='cubic')
t_new = np.array([0, 1, 2, 3, 4, 5])
x_new = f(t_new)
3. 重采样
不同传感器的采样率可能不同。比如摄像头30fps,雷达10fps。训练模型时,需要统一到相同的采样率。
重采样的步骤:
- 确定目标采样率(比如10Hz)
- 生成新的时间序列
- 用插值方法计算新时间点的位置
我的建议:重采样时要注意奈奎斯特采样定理。目标采样率至少是运动频率的两倍。比如行人步频约2Hz,那采样率至少4Hz。我一般取10Hz,留足余量。
实战中的注意事项
最后,分享几个我在项目中踩过的坑:
- 数据对齐:多传感器数据的时间戳要对齐。我习惯用插值法把不同传感器的数据统一到同一时间轴。
- 边界处理:轨迹的起点和终点数据往往不完整。我一般会截掉前后各5%的数据。
- 数据增强:如果数据量不够,可以对轨迹做小幅旋转、平移、加噪声。但注意不要改变运动规律。
好了,这一章的内容就到这里。轨迹数据预处理看似基础,但做得好不好,直接决定了模型的上限。下一章我们会聊到时序特征工程,到时候见。
课后练习:找一份公开的轨迹数据集(比如nuScenes),尝试对其中一条轨迹做去噪、插值、重采样。看看处理前后的轨迹有什么变化。