做自动驾驶感知和预测方向,Argoverse2这个数据集你大概率绕不过去。相比KITTI和nuScenes,它的传感器配置更接近量产车,地图信息也更丰富,尤其是运动预测任务,官方把场景切分、目标筛选都做好了,拿来就能训模型。这篇内容不是我对着官方文档的复读,而是我前前后后折腾Argoverse2的完整记录,从账号申请、AWS下载、目录结构,到点云、图像、运动轨迹的预处理,每一步都做了验证。该踩的坑我也替你踩了不少,直接照着走就行。适合刚接触这个数据集、想马上动手训练的同学。
1. 先把Argoverse2这个数据集拆明白
1.1 它到底包含哪些数据,能拿来做什么
Argoverse2是Argo AI开源的大规模自动驾驶数据集,采集城市是迈阿密、奥斯汀等几个美国城市。整套数据分成两大块,第一块是传感器原始数据,用于3D目标检测、3D追踪、点云分割这些感知任务;第二块是运动预测数据,用于轨迹预测、交互行为建模。
先说传感器数据。Argoverse2的采集车一共装了7个环视摄像头,分布在车头、车尾、两侧和后视镜附近,视野覆盖360度,摄像头以20帧每秒的频率录制。激光雷达配置比较特殊,是2个远距激光雷达加2个中距激光雷达的组合,远距雷达负责探测200米外的大范围场景,中距雷达保证车身周围20米近距离的点云完整度,所有雷达统一以10Hz频率输出点云。
这套传感器方案跟常见的单车单雷达配置完全不同,好处是近处没有盲区,远处又有足够的检测距离。实际用下来,Argoverse2的点云近处密度高,这对小目标检测、行人和锥桶识别非常友好。
再说运动预测数据。它提供的是带全局ID的目标轨迹,覆盖5秒历史观测和6秒未来预测,所有目标按10Hz采样,一条轨迹一共110个时间步。数据里除了车辆、行人、骑行者,还专门区分了摩托车、公交车、艺术车等细分类别,方便做不同类别的行为分析。
1.2 和Argoverse1、KITTI、nuScenes比,它强在哪
很多同学之前用的是Argoverse1,Argoverse2在多个维度上有明显升级。Argoverse1的运动预测数据没有传感器原始数据支撑,想做一些多模态融合实验,只能自己去外部找地图信息。Argoverse2把激光雷达点云、环视图像、高精地图都打包在了一套数据里,你既能做纯轨迹预测,也能做感知与预测联合训练。
对比KITTI,KITTI虽然经典,但传感器比较老了,点云稀疏且录制场景局限在德国卡尔斯鲁厄周边。Argoverse2的采集规模大得多,场景覆盖高速路、城市环岛、十字路口、停车场,而且提供的地图是矢量级高精地图,能直接算出车道中心线、边界、路沿等几何信息,KITTI在这块几乎没有。
对比nuScenes,nuScenes的优势是多模态和传感器数量多,但它的地图信息较弱,只有粗略的车道多边形。Argoverse2则提供了像素级且结构化程度更高的HD Map,官方API还能直接按时间戳查询当前车道的局部地图。如果研究重点是结构化场景理解下的预测决策,Argoverse2比nuScenes更契合。
2. 下载前准备:账号、协议、工具链一个都不能少
2.1 注册与协议签署:别在这上面浪费时间
Argoverse2下载不是点个链接就能拿,必须先注册账号并同意数据集协议。流程看起来多,实际也就十来分钟,但很多人第一步就卡住,原因是官方的注册页面入口藏得比较深。打开Argoverse的官网,找到Dataset页面,选择Argoverse2,点击下载入口后会跳转到用户中心,先填注册信息,再等邮件激活。
激活之后回到数据集页面,系统会让你勾选协议,这里要特别注意,协议里明确写了数据仅限非商业用途。如果你拿这个数据集做商业交付,后面会非常麻烦。整个申请流程一般几分钟内自动通过,但也有会遇到审批慢的情况,我第二次申请时等了半天,后来发现是注册邮箱的域名被系统拦截,换了个人邮箱立刻通过。
协议签署完成后,页面会显示当前账号的访问密钥,也就是AWS的Access Key和Secret Key。这个密钥是后续从S3拉数据的凭证,务必复制保存好。需要说明的是,Argoverse2的公开数据集存放在AWS S3的公开存储桶中,部分分支可以匿名访问,但用账号密钥下载速度更稳定,建议还是走官方认证流程。
2.2 本地环境与存储规划:先算好这笔账
在动手下载前,强烈建议先规划存储空间。Argoverse2整套数据体量不小,传感器子集完整下载大概需要几百GB,运动预测子集小一些,也有几十GB。如果你只做运动预测,不下载传感器数据,那对磁盘要求低很多;如果你要做多模态感知,建议直接预留至少1TB空间。
下载之前还要确认文件系统类型。我在一台ext4的服务器上跑没有任何问题,但在一台NTFS格式的移动硬盘上碰到了零散文件下载失败的情况,原因是NTFS对小文件IO不友好,而Argoverse2的目录里大量的是几百KB的标定JSON和地图文件。建议工作目录放在ext4或APFS格式的分区上。
工具链方面,最核心的是AWS CLI,我建议用带断点续传支持的版本。其次需要Python 3.8以上环境,安装argoverse官方依赖包,主要是argoverse、pyarrow、pandas、numpy、scipy、open3d这些。如果机器上有GPU,Anaconda环境统一管理最省心,避免在不同项目间切来切去时把依赖搞坏。
2.3 AWS CLI安装配置:一条命令搞定
AWS CLI的安装不复杂,在Ubuntu系统上直接使用pip安装:
pip install awscli安装完成后配置密钥,执行:
aws configure此时会依次要求输入Access Key ID、Secret Access Key、默认区域和输出格式。区域我建议填us-east-1,这是Argoverse2存储桶所在的区域,输出格式填json即可。
配置完成后可以先用下面的命令验证是否连通:
aws s3 ls s3://argo-ai-public/如果能看到存储桶列表,说明配置成功。注意这里不要用带空格的密钥,AWS CLI对密钥格式有严格校验。验证完成后,就可以开始正式下载了。
3. 实操:从AWS S3把数据拉到本地
3.1 下载指令与参数说明:不要用默认的递归命令直接拉
刚开始下载的同学最容易踩的坑,是直接执行一条超级大的递归下载命令,例如:
aws s3 cp --recursive s3://argo-ai-public/argoverse2/ ./这个命令本身没错,但Argoverse2数据量太大,一条命令跑到底,中途一旦网络抖动,前面的下载全部作废。我建议把下载拆成子目录执行,每条命令对应一个子集。
常用的几个子集路径大概是:
- 传感器原始数据:
s3://argo-ai-public/argoverse2/raw/ - 运动预测数据:
s3://argo-ai-public/argoverse2/forecasting/ - 高精地图数据:
s3://argo-ai-public/argoverse2/map_files/
所以对应的下载命令可以写成:
aws s3 cp --recursive s3://argo-ai-public/argoverse2/forecasting/ ./data/forecasting/ --no-sign-request如果你已经配置了密钥,不需要加--no-sign-request参数,它会自动使用本地密钥完成认证。加了这个参数的好处是兼容没有密钥的公开访问场景,但速度可能稍慢。
3.2 断点续传与并发下载:数据多更要稳着来
递归下载数据量大的时候,我强烈建议不要用单线程硬扛。AWS CLI自带的--recursive是单线程,速度有限,遇到某个文件失败还会中断整个任务。更靠谱的做法是先用aws s3 ls --recursive把文件列表导出来,然后交给支持并发下载的工具处理。
我实际操作中用的是aria2c,配合S3的公开URL,并发开16个线程,速度比AWS CLI单线程快好几倍。如果你更习惯用Python脚本,也可以用boto3自己写一个分片下载器,每个分片独立校验MD5,失败自动重试,这样一个几百GB的数据集下载也能稳定跑完。
下载完成之后,强烈建议做一次文件完整性校验。Argoverse2每个文件在S3端都有metadata里的ETag,也就是MD5值,可以用Python脚本遍历本地文件,逐个比对。我自己遇到过一个问题,某个下载工具超时后生成了0字节文件,校验时才发现的。这种情况如果直接用下游流程,到了读数据的时候才报错,排查起来非常痛苦。
3.3 下载常见状态与应对策略:网络问题不是玄学
下载过程中遇到最多的就是连接超时和限流。连接超时一般是防火墙或者网络丢包导致,先检查本地网络能否稳定访问S3域名的IP,如果不行,换一个网络环境或者换DNS。
遇到限流,表现为多个并发连接同时变慢,甚至收到SlowDown错误。这时不要死磕,把并发数降下来,或者等待几秒钟再继续。批处理脚本里我会设置一个指数退避逻辑,每次失败后等待时间为上一次的两倍,最多重试5次,实测成功率会高很多。
4. 数据落地后的目录结构:知道你的文件在哪儿
4.1 传感器数据目录:时间和传感器两套索引
完成原始数据下载后,目录结构大致如下:
argoverse2/ ├── raw/ │ ├── 0000b0f9-6d37-4d7d-b5d9-1f5a9b2b5e3f/ │ │ ├── cameras/ │ │ │ ├── ring_front_center/ │ │ │ │ ├── 4153438.jpg │ │ │ │ └── ... │ │ ├── lidar/ │ │ │ ├── middle_range_lidar_1/ │ │ │ │ ├── 412178.parquet │ │ │ │ └── ... │ │ ├── annotations/ │ │ │ ├── track0000.json │ │ │ └── ... │ │ └── city_SE3.json ├── forecasting/ │ ├── train/ │ │ ├── scenario_a/ │ │ │ ├── scenario.csv │ │ │ ├── track.csv │ │ │ ├── object.csv │ │ │ └── city_SE3.json │ └── val/ └── map_files/ ├── 739b6efa-9e2c-4932-8d5b-1eb918d4d34f/ └── ...每个log_id也就是一个场景文件夹,里面按传感器名称再分一层。图像文件是jpg格式,点云文件是parquet格式,这个是解压归档格式,不是直接可读的pcd或bin文件。点云字段通常包含x、y、z、intensity、laser_id等列,读取后用numpy处理即可。
4.2 运动预测数据目录:一个场景一个文件夹
运动预测数据的组织方式与传感器数据不同,是按scenario来组织的,一个场景文件夹就对应一次独立的预测任务。场景文件夹里的关键文件有四个:
scenario.csv:记录场景起止时间、场景ID、log_id等元信息track.csv:核心轨迹文件object.csv:目标静态属性city_SE3.json:城市坐标系到场景坐标系的变换矩阵
其中track.csv里的核心字段包括TIMESTAMP、TRACK_ID、OBJECT_TYPE、X和Y。TIMESTAMP是整体时间戳,不是相对时间,需要根据场景起始时间换算成相对时间。OBJECT_TYPE有AGENT、AV、OTHERS几种,其中AGENT就是需要预测的主目标,AV是自车,其他车辆行人都是OTHERS。
4.3 地图文件目录:矢量地图的切片组织
map_files目录按城市区域切片,每个文件是一个独立区域的HD Map。地图文件里包含了车道中心线、车道边界、道路标记、路沿、人行横道这些关键要素的矢量几何信息。读取地图文件时,需要把几何坐标从城市坐标系转换到场景坐标系,这个转换依赖每个场景自带的city_SE3.json。
5. 传感器数据预处理:图像和点云实战
5.1 相机标定文件和坐标变换:先搞懂四个坐标系
传感器数据预处理的第一步,是搞懂涉及的坐标系,否则后续所有坐标系变换都会出错。相机图像处理涉及图像像素坐标系、相机坐标系、自车坐标系以及城市坐标系。官方提供的标定文件里,包含了相机内参矩阵K、畸变系数、以及相机到自车的外参矩阵。
读取一张图像后用OpenCV去畸变:
import cv2 import json import numpy as np with open("calibration.json", "r") as f: calib = json.load(f) K = np.array(calib["K"]).reshape(3, 3) dist = np.array(calib["D"]).flatten() image = cv2.imread("4153438.jpg") undistorted = cv2.undistort(image, K, dist)这一步的目的是让图像像素位置和真实成像几何对齐,否则后续图像特征与点云做投影融合时,会错位好几个像素。
5.2 点云读取与体素化:parquet格式的小技巧
Argoverse2的点云虽然存在parquet文件里,但本质上就是一个带列名的二维矩阵。读取时用pyarrow或者pandas即可:
import pandas as pd cloud = pd.read_parquet("412178.parquet") points = cloud[["x", "y", "z"]].values intensity = cloud["intensity"].values拿到点云后,第一件事是过滤掉自车底部的噪点。Argoverse2的中距雷达在车底会打到地面,产生大量无效点,一般按z轴高度过滤即可。其次是做地面分割,最简单的办法是用RANSAC拟合一个平面,把地面点去掉。这个操作对下游目标检测尤其重要,能显著减少误检。
做完地面分割后,再做ROI裁剪,只保留以自车为中心、前后各60米、左右各30米范围内的点。这个范围覆盖了绝大多数交通场景,同时能大幅减少计算量。最后一步是按照网络输入要求做体素化,比如VoxelNet风格的pillar编码,或者直接用Open3D进行体素下采样。
5.3 图像与点云融合:时间戳对齐是核心
摄像头和激光雷达的采集频率不同,摄像头20Hz,激光雷达10Hz,所以图像和点云的时间戳不会完全对应。做融合时,需要在时间轴上做最近的邻居匹配,把一个时间戳的点云绑定到最近的图像帧上。
判断对齐是否正确的经验方法是,把点云投影到图像上,看边缘是否与图像中的实物轮廓吻合。投影公式是:
uv = K @ (R @ points + t)其中R和t是把自车坐标系的点云变换到相机坐标系的旋转和平移,这个矩阵在标定文件里都有。对齐好的数据,可以存储为一个字典或者缓存文件,避免每次训练前都重新对齐。
5.4 数据增强与格式转换:一个细节就能影响收敛
感知任务训练前的最后一步是数据增强。图像方面常见操作有随机翻转、随机裁剪、颜色抖动。点云增强则需要小心一些,不能盲目做全局旋转变换,否则坐标系和标注框会不匹配。推荐的做法是绕自车坐标系做小角度旋转扰动,同时平移量控制在0.5米以内。
数据格式转换方面,我建议把处理后的数据统一存成numpy数组或者LMDB格式,避免每次加载都现场读取parquet。这个转换在训练速度上的收益非常明显,尤其是小批量迭代时,能省掉大量IO时间。
6. 运动预测数据预处理:parquet实战
6.1 核心CSV文件字段解析:先把表结构吃透
运动预测数据的预处理与感知数据完全不同,核心是轨迹和时间序列处理。我以track.csv为例展开,它的各列含义如下:
TIMESTAMP:采样时间戳,单位是微秒TRACK_ID:目标唯一IDOBJECT_TYPE:目标类别X和Y:目标在城市坐标系下的位置CITY_NAME:城市标识
object.csv里给出每个TRACK_ID的静态属性,比如目标长度、宽度,这些数据对预测网络做目标尺寸编码时很关键。需要特别注意,不同目标的起始时间和结束时间不一样,一条轨迹可能在6秒预测窗口中才出现,也可能在历史5秒的某个时间点消失,预处理阶段必须处理这种不等长情况。
6.2 场景切分与坐标归一化:这是运动预测预处理的灵魂
官方训练数据中,每个场景包含一段5秒的历史轨迹和6秒的未来轨迹。训练模型时,需要把整段轨迹切分成输入部分和预测真值。
切分之前,先把城市坐标系下的全局坐标转换到以主目标AGENT为原点的局部坐标系。Argoverse2官方提供了city_SE3.json,我们可以读取旋转平移矩阵做变换。变换完成之后,再以目标当前时刻的朝向为参考,旋转到+x方向作为标准方向。
常用的坐标转换代码逻辑如下:
import json import numpy as np import pandas as pd with open("city_SE3.json", "r") as f: city_se3 = json.load(f) R = np.array(city_se3["R"]).reshape(3, 3) t = np.array(city_se3["t"]).reshape(3, 1) def transform_points(points): points_h = np.hstack([points, np.ones((points.shape[0], 1))]) return (R @ points.T + t).T[:, :2]之所以要做坐标归一化,是因为不同场景的绝对坐标差异很大,直接喂给模型,网络很难学到位置无关的几何模式。在实际训练中,AGENT的轨迹通常还要额外反转或者旋转增强,把训练数据量翻倍。
6.3 HD Map的提取与使用:矢量地图不等于栅格图
运动预测任务里,矢量地图是输入的核心特征。很多同学第一次拿到地图文件时,误以为需要将地图栅格化成图片,但实际上,Argoverse2的HD Map是矢量结构。
拿到地图后,可以通过官方API把地图里每一条车道中心线转换成点序列。这个点序列就是车道线的矢量表示,时间上连续、几何上精确。使用时需要把车道线点到目标车坐标系的相对位置作为输入特征,每个点包含相对X、相对Y、车道类型、是否可换道等信息。
相比栅格地图,矢量地图的优势是天然支持更长的感知范围。栅格地图在距离目标较远时,分辨率会因为固定网格尺寸而下降,而矢量地图的点序列无论多远都能保持几何精度,这对于处理长距离变道场景特别重要。
6.4 实操示例:把一条轨迹切成训练输入输出
直接共享一个我项目中使用的简洁版预处理脚本,它可以将parquet场景文件转换为模型需要的输入特征和预测真值:
import pandas as pd import numpy as np def load_scenario(scenario_dir): track = pd.read_csv(f"{scenario_dir}/track.csv") return track def preprocess(track, agent_id): agent_track = track[track["TRACK_ID"] == agent_id].sort_values("TIMESTAMP") history = agent_track.iloc[:50][["X", "Y"]].values.astype(np.float32) future = agent_track.iloc[50:110][["X", "Y"]].values.astype(np.float32) # 坐标归一化等其他变换省略 return history, future这里把前50帧作为历史信息,后60帧作为预测真值,时间步数正好对应官方数据集的5秒和6秒。这样做出来的样本,可以直接输入到基于LSTM、Transformer或者CNN的轨迹预测网络里。
7. 常见问题与排查技巧实录
7.1 下载速度慢或者断流:不要硬扛,用对工具
很多人直接用AWS CLI单线程递归下载,数据量一大就出问题。断点续传和并发下载不是可选项,面对几百GB的数据,必须用支持分片并发和断点续传的工具。
我常用的下载命令是这样:
aria2c -x 16 -s 16 -c -o forecasting.zip "https://argoverse2.s3.amazonaws.com/forecasting.zip"-x 16表示每个服务器最多开16个连接,-s 16表示分16段下载,-c支持断点续传。实测下来,国内网络环境下载速度稳定很多。中途即使断了,重新执行同一命令也能继续,不是从头再来。
7.2 parquet文件读取报错或者内存暴涨
parquet文件本身是列式存储,读取时pyarrow已经做了大量优化,但部分机器仍然会因为某些列类型异常或版本不兼容而报错。一个很典型的错误是pandas版本过旧,导致读取新的parquet schema时报错。
建议环境里固定安装较新版本的pyarrow和pandas:
pip install --upgrade pyarrow pandas如果遇到内存不足的问题,使用pd.read_parquet(path, columns=["x", "y", "z"])只读取需要的列,能显著降低内存占用。同样一个文件,全部读取可能占用1.2GB,只读取坐标三列可能只需要300MB。
7.3 时间戳对不齐
图像和点云的时间戳对不上是最常见的报错。Argoverse2里图像文件命名的时间戳单位是微秒,而点云文件命名的时间戳也是微秒,但两者的起始时刻不一定相同。如果没做对齐而直接使用,会出现图像内容和点云内容不在同一时刻的情况,训练出来的模型效果自然很差。
我的对齐逻辑是:
def find_nearest_timestamp(target, candidates): idx = np.argmin(np.abs(np.array(candidates) - target)) return idx先获取点云时间戳,再在图像时间戳列表里找最近的索引,同时限制最大时间差不超过50毫秒。超过这个阈值就放弃这一对数据。
7.4 坐标系偏移:检测框和点云不匹配
做3D检测时,经常发现框和点云位置对不上,要么整体偏移,要么某个方向上变形。排查的第一步是确认标定文件里的变换矩阵是否用对了。很多同学会混淆自车坐标系和城市坐标系,导致旋转矩阵乘反。
遇到这种问题时,Projection到一个已知场景里做可视化检查。选择一条直线路段,把激光雷达点云投影到图像上,观察路沿和车道线的边缘是否与图像中的路边重叠。如果整体向左偏,说明外参里的偏航角方向反了,把矩阵取逆再试一次。
7.5 常见问题速查表
| 问题现象 | 可能原因 | 解决建议 |
|---|---|---|
| 下载中断后文件不完整 | 未使用断点续传工具 | 改用aria2c或boto3分片下载 |
| parquet读取报错 | pyarrow版本过旧 | 升级pyarrow和pandas |
| 图像和点云时间对不上 | 未做最近邻时间对齐 | 限定最大时间差50ms |
| 检测框与点云偏差 | 坐标变换用错 | 可视化检查投影结果 |
| 内存占用过高 | 全量读取parquet | 按列读取,按需加载 |
| 场景坐标差异大 | 未做坐标归一化 | 参考官方city_SE3.json归一化 |
8. 预处理后的数据怎么验证:一张图看懂的检查方法
数据预处理做完,不能直接闷头训练模型,先做一次视觉检查,否则问题会在多个epoch之后才暴露,排查成本极高。我的习惯是写一段可视化脚本,把目标轨迹叠加到高清地图上,看一眼轨迹是否连续、车道是否对齐、坐标方向是否正确。
对于传感器数据,做一个点云到图像的投影检查,确认物体边缘对齐。如果投影不准,说明标定文件出了问题,优先级最高,必须优先修复。否则后续所有图像与点云融合的特征都会受影响。
数据验证通过后,再用少量样本跑一遍模型前向和反向,确认数据尺寸和网络输入层匹配。这一步能快速发现数据维度错误、NaN值等深层问题。
9. 我踩过的坑与最后的建议
最后再说点实际体会。预处理过程中,最容易出问题的不是某个算法多复杂,而是数据格式的细节。比如摄像头标定文件的畸变系数顺序,官方和OpenCV文档可能不完全一致;又比如parquet文件里某些点是空值,直接建模会导致NaN。整个过程中,建议每一步都打印shape和数值范围,做到心里有数。
如果你只是做运动预测,前期可以只下载forecasting和map_files两个子集,不必下载传感器原始数据,能省下大量时间和存储。等模型跑通之后,再考虑补充传感器数据做多模态实验。
数据处理脚本建议做到可重复,用明确的文件目录结构和配置文件管理路径。这样后续切换数据集子集或者重跑实验,都非常方便。Argoverse2是个质量很高的数据集,值得多花点时间把数据管线打好基础,后面的训练和分析都会顺很多。