第1章:轨迹数据读取与预处理

各位同学好,我是你们的老朋友。今天咱们聊聊轨迹数据读取与预处理。说实话,这步看着基础,但我在项目里见过太多人在这上面栽跟头。数据没洗干净,后面做定位融合、路径规划,全是白搭。

1.1 轨迹数据的“身份证”——CSV与JSON格式

城市道路轨迹数据,最常见的两种格式就是CSV和JSON。CSV像一张表格,每一行是一条轨迹点,每一列是属性。JSON则更灵活,适合嵌套结构。

CSV格式示例:

timestamp,latitude,longitude,altitude,speed,heading
1625097600,39.9042,116.4074,52.0,0.5,180.0
1625097601,39.9043,116.4075,52.1,0.6,181.0

JSON格式示例:

{
  "trajectory": [
    {"ts": 1625097600, "lat": 39.9042, "lon": 116.4074, "alt": 52.0, "spd": 0.5, "hdg": 180.0},
    {"ts": 1625097601, "lat": 39.9043, "lon": 116.4075, "alt": 52.1, "spd": 0.6, "hdg": 181.0}
  ]
}

我个人习惯用pandas读取CSV,用json模块处理JSON。代码很简单,但有个坑——时间戳格式。很多数据集的时间戳是字符串,比如"2021-07-01 12:00:00",你得先转成数值型,后面才好做时间对齐。

核心要点:读取数据时,务必检查时间戳字段的dtype。如果是object类型,先转datetime,再转时间戳。

1.2 数据清洗——去重与异常值处理

数据读进来了,下一步就是洗数据。我遇到过最离谱的情况:同一辆车在同一秒内出现了5个轨迹点,坐标还都不一样。这明显是传感器重复上报了。

去重策略:

  • 基于时间戳去重:同一辆车,同一秒,只保留第一个点
  • 基于坐标去重:连续两个点坐标完全一样,可能是静止或丢星,酌情处理
  • 基于轨迹ID去重:确保每个轨迹ID对应唯一一条轨迹

异常值处理:

  • 速度异常:城市道路限速60km/h,突然出现200km/h,肯定是异常
  • 坐标漂移:GPS信号差时,坐标会跳到几百米外
  • 高度突变:正常道路高度变化平缓,突然跳变几十米,多半是噪声

我的经验:异常值别直接删。先标记出来,看看是不是传感器故障。我曾经遇到一批数据,每天固定时间点出现速度异常,后来发现是那个时段有高架桥遮挡,GPS信号反射导致的。这种情况,删掉反而丢失了真实场景。

1.3 时间戳对齐——让所有数据“说同一种语言”

多传感器融合时,时间戳对齐是老大难。GPS是UTC时间,IMU是本地时钟,摄像头是帧时间。你不对齐,融合出来的轨迹就是“鸡同鸭讲”。

对齐方法:

  1. 线性插值法:假设两个时间点之间运动是匀速的,按比例插值
  2. 最近邻法:找到最接近目标时间戳的点,直接使用
  3. 样条插值法:用三次样条拟合轨迹,精度更高,但计算量大

我个人推荐线性插值。简单、稳定、够用。除非你做高精度地图匹配,否则没必要上样条。

def align_timestamps(traj, target_ts):
    """
    轨迹时间戳对齐(线性插值)
    traj: DataFrame,包含timestamp, lat, lon等列
    target_ts: 目标时间戳列表
    """
    import numpy as np
    from scipy.interpolate import interp1d
    
    # 提取原始时间戳和坐标
    ts = traj['timestamp'].values
    lat = traj['latitude'].values
    lon = traj['longitude'].values
    
    # 线性插值
    lat_interp = interp1d(ts, lat, kind='linear', bounds_error=False, fill_value='extrapolate')
    lon_interp = interp1d(ts, lon, kind='linear', bounds_error=False, fill_value='extrapolate')
    
    # 生成对齐后的轨迹
    aligned = pd.DataFrame({
        'timestamp': target_ts,
        'latitude': lat_interp(target_ts),
        'longitude': lon_interp(target_ts)
    })
    return aligned

注意:插值会引入误差。如果原始数据采样率太低(比如1Hz),插值出来的点可能不准确。我建议采样率至少10Hz以上再做插值。

1.4 知识体系总览

下面这张图,是我自己总结的轨迹数据预处理流程。你想想看,从原始数据到可用轨迹,中间要过多少关?

轨迹数据预处理流程 数据读取 CSV / JSON 格式检查 时间戳 / 坐标类型 数据去重 时间 / 坐标 / ID 异常值处理 速度 / 坐标 / 高度 时间戳对齐 线性 / 最近邻 / 样条 输出轨迹 清洗后的数据 预处理后的轨迹数据,才能用于后续的定位融合、路径规划等任务

1.5 实战小贴士

嗯,这里要注意。预处理不是一次性的活。你跑完定位算法,发现结果不对,很可能要回头检查预处理步骤。我有个习惯:每次预处理完,都可视化一下轨迹。画个图,看看有没有跳点、有没有空洞。肉眼一看,比任何统计指标都直观。

总结一下:

  • 读取数据时,先检查时间戳格式
  • 去重要谨慎,别把有效数据删了
  • 异常值先标记,再决定处理方式
  • 时间对齐用线性插值,简单够用
  • 预处理完,一定要可视化验证

好了,这一章就到这里。数据预处理是基本功,但也是决定成败的关键。下一章咱们聊聊轨迹滤波与平滑,到时候我会分享一个我在高速场景下踩过的坑,保证让你印象深刻。

可可精品资料库