第一版Qwen-Drive-1.0的轨迹输出叠到路测视频上时,旁边的人问了一句:这路线是模型自己规划出来的,还是你照着真实轨迹描上去的?这个问题其实戳中了项目最核心的地方——视觉语言模型到底能不能在三维道路空间里自己“想”出一条可行驶的驾驶轨迹。
业界对视觉语言模型的常规用法停在“看图说话”层面:进去一张图像,出来一段文字描述,顶多再做点目标检测和OCR。Qwen-Drive-1.0想做的事是把这类模型从二维描述者变成三维空间里的驾驶决策者:输入多路相机的图像和一条自然语言导航指令,输出未来几秒的横纵向驾驶轨迹。这个项目适合正在做端到端自动驾驶、或者想用大模型做决策规划的同学参考,也适合对视觉语言模型多模态能力边界好奇的人。完整跑完一遍之后,我最深的体会是:让VLM理解道路没那么难,难的是让它的输出能和几何空间严格对齐、能真正用来开车。
1. 为什么选择让视觉语言模型管驾驶:从“看路”到“开车”的思维切换
这个出发点一开始很容易被误解。很多人以为Qwen-Drive-1.0是做“驾驶场景问答”,比如给模型看一张图,让它回答“前面是什么车”。实际上项目里几乎没有这类常规VQA任务。我要做的只有一件事:让模型直接输出一辆车未来几秒怎么走。这个动作看似简单,背后藏着一个选择:为什么不沿用传统感知-预测-规划三段式,也不直接用纯视觉端到端,偏偏要押注在视觉语言模型上。
1.1 传统端到端方案卡在了哪里
传统模块化方案的问题很典型。感知、预测、规划各自独立训练,感知误差会一级级往上传。感知少标了一个锥桶,预测层根本不知道它存在,规划层自然也不会避让;感知把车道线抖了一下,规划轨迹跟着抖,乘员就能感觉到顿挫。模块之间的接口就是信息瓶颈,大家都只在“自己那一步”优化,没人对最终驾驶行为负责。
纯视觉端到端方案解决了部分误差累积问题,因为梯度可以从最终方向盘转角一路传回像素,让模型自己去筛选和感知有关的特征。但我实测发现它有一个新问题:不可解释、不可干预。模型在训练集分布内跑得很顺,一旦遇到训练数据里少见的场景,比如前方有临时交通管制、前车突然停在一个诡异的位置,它不会“想一想”,只会硬着头皮输出一个可能不合理的轨迹。它缺少常识——而这恰好是语言模型目前相对擅长的部分。
1.2 视觉语言模型恰好补上了哪块拼图
视觉语言模型最强的能力,是它能把视觉特征和人类语言文本嵌到同一个语义空间里。传统视觉模型看一张图,输出的是“类别+框”;VLM看同一张图,可以理解“前方斑马线上有人正在过马路,我应该减速等待”。这种高层语义的理解,正好是传统感知头很难直接编码的东西。
但VLM也有天然短板:它通常在二维图像预训练,对“深度到底是多少”“这个车道离自车几个车身”没有精确的几何概念。Qwen-Drive-1.0的核心思路,就是把这个短板当成项目主线来解决:不指望VLM默认就会三维理解,而是在架构上强制它学习三维道路空间,把语言能力、视觉能力、几何推理能力掰到同一条驾驶轨迹上。模型不是简单地“看路”,而是要看懂“这一段三维道路结构在几何上长什么样”。
1.3 项目目标与技术边界
项目开始时,我先定了一条硬边界:不做底盘控制、不做高精地图依赖、不做传感器融合级别的定位。Qwen-Drive-1.0只负责输出“未来几秒的策略轨迹”。所谓策略轨迹,是指带有明确意图的横纵向路径点序列,而不是底盘可执行的方向盘转角指令。
这个边界设定很有必要。把底盘动力学的延迟、轮胎滑移、转向死区全部塞进VLM训练,模型参数量再大也会被噪声淹死。我希望模型解决的是“懂路”的问题:知道路怎么走、哪里能走、什么时候该让。至于怎么把轨迹平滑地变成方向盘动作,那是下游控制器的事。输入则取多路相机的图像序列和一条自然语言导航指令,输出未来5到8秒的轨迹点数组。整个项目用一个词概括:给视觉语言模型安上一副“三维道路的眼镜”。
2. 三维道路理解的构建:把2D像素翻译成可算的3D几何
视觉语言模型默认活在像素世界里,而驾驶决策活在物理世界里。要让模型输出能在真实路面上用的轨迹,必须先把图像特征从透视视角搬到一个没有尺度歧义的表示空间里。我选了BEV,鸟瞰视角空间。这条路很多自动驾驶感知方案都走过,但我不是拿BEV做目标检测,而是拿它当VLM的“几何工作台”。
2.1 输入视图与特征提取的取舍
传感器布局上,我用6路相机覆盖车身周围,前向另加一个中长焦镜头负责远距离路况。别急着把所有路的画面都拼成一整张大图塞给模型,那样算力爆炸而且空间混叠严重。我的做法是保留6路独立图像,每路各自过一遍共享权重的视觉编码器,提取多尺度特征图。视觉编码器直接用某个开源视觉语言模型底座的图像塔做初始化,省掉从零训练视觉部分的痛苦。
每个时间戳实际送入的是3帧:当前帧、0.5秒前帧、1.0秒前帧。之所以取前三帧而不是只送单帧,是因为单帧无法表达其他交通参与者的运动趋势。前车到底是停住了还是在匀速前进,只看一张图根本无法区分。三帧在时间上不能太密,间隔太密等效于静止,对运动感知帮助不大。这个采样策略在项目里像“小步快跑”一样,算力和信息量之间取了折中。
2.2 从透视图到BEV空间的特征投影
透视特征图里,同一个物体在不同距离下的尺度差异极大。正前方20米的车在图像里占很大的像素区域,侧前方60米的车可能只占一小块。VLM的注意力机制处理这种尺度差异很费力。把特征搬到BEV空间后,每个物体的尺寸基本一致,道路结构也直观暴露出来,比如车道是直的还是弯的、路口在哪、路缘石围在哪里。
投影过程用了LSS思路里的一招:对每个2D像素估算一组离散深度区间的概率分布,把像素特征“抬”成三维视锥体,再把视锥体特征投到自车为中心的栅格上做池化。栅格范围设定为前方60米、后方15米、左右各30米,分辨率0.5米,也就是240x90的格子。
直接输出像素级深度图的做法在项目里被否掉了,原因是深度回归噪声太大,容易把整条车道的几何形状搞得坑坑洼洼。最终实现里深度分布只作为软先验,真正负责空间推理的是BEV空间里的自注意力机制。
2.3 深度估计与自注意力机制的配合
周边格子之间的空间关系,需要靠Transformer的自注意力机制去建模。车道线为什么连续、路缘为什么是弧线、前车占据哪几个格子,这些关系在BEV空间里更自然。为了把“三维感”塞进注意力计算,每组BEV特征除了图像语义之外,还会拼接一个位置编码,包含格子的x坐标、y坐标和语义估计高度。
这个“语义高度”是从多视角相机特征中交叉投影出来的粗略值,不用特别精确,只要能区分路面、行人头部、卡车货箱的高度层次就行。这样注意力在计算“这个格子是否阻挡轨迹”时,会同时参考横向、纵向和高层信息,模型逐渐学会了把“高一点的语义特征在前方几个格子”理解成“一堵不能穿过的墙”。
2.4 三维道路表征输出:点、线、面三层结构
三维道路理解最终要落成可被损失函数监督的结构化输出。Qwen-Drive-1.0分三层输出,统一对齐到自车坐标系:
- 点层:关键路面元素的语义标签,包括锥桶、路缘石断点、人行横道角点等,数量不多但位置必须准确。
- 线层:车道中心线采样点,以及左右车道边界线,用来决定轨迹该“沿哪条线走”。
- 面层:可行驶区域掩码,每个BEV格子输出一个0到1的可通行概率,体现“这个区域能不能压上去”。
这三层不是独立分开的,而是同一个BEV特征骨干上引出三个预测头。点层给VLM提供“前方有异常小目标”的线索,线层给轨迹规划器提供参考线,面层给安全约束提供硬边界。轨迹生成时不是凭空画一条线,而是基于这条结构化几何骨架去推理。
3. 驾驶轨迹生成:不是“规划一条线”,而是“理解一段路”
如果只做一个几何轨迹回归器,传统CNN和MLP就够用了,没必要上视觉语言模型。真正让VLM发挥价值的地方,在于它能把自然语言指令、道路几何结构、实时交通态势统一到一个推理过程中。这里的驾驶轨迹生成,本质上是一次“带几何约束的条件概率推理”。
3.1 轨迹生成的基本范式:自回归token化还是连续回归
先试过把轨迹坐标离散成token,让模型像生成语言一样自回归一段序列。这条路的好处是与VLM天然匹配,不需要改太多结构;坏处是离散化精度损失很伤。轨迹点偏差20厘米在城市道路就是压线,更别说离散token之间还会产生“下一个点依赖上一个点”的错误累积。试运行两周后,我放弃了纯token化。
最终方案是混合式:先让模型输出一个粗粒度的“语义轨迹描述”,比如“直行40米,靠右侧车道,在红绿灯前停车”,再让轨迹回归头基于这段描述和BEV特征连续回归精确坐标点。语义轨迹描述承担“意图表达”,连续回归头承担“几何重建”,各干各擅长的事。这个设计后来证明是项目里收益最大的一次改动。
3.2 上下文指令如何注入:从自然语言到驾驶约束
导航指令不是简单拼在prompt末尾让模型“看着办”。太浅了。项目里做了一个可学习的adapter,把导航指令文本编码成一组embedding,再插入到BEV特征的键值序列里。这样就等于告诉模型:视觉空间里有一个格子集合,语言空间里有一个“右转”约束,两个空间需要在注意力层互相打招呼。
训练一段时间后,模型内部果然涌现出一种微妙的对齐:当指令是“前方路口右转”时,BEV空间里的注意力会提前增强右侧车道线对应的格子;当指令是“靠边停车”时,注意力更多落在右侧路缘和可停靠区域。我无法直接从参数里看到这种关联,但从特征图的可视化结果来看,这个机制是真实存在的。语言指令就这样变成了驾驶约束的一部分,而不是一句多余的注释。
3.3 横纵分离与动态障碍物处理
轨迹分解成横向和纵向两条独立分支:横向分支负责“走哪条线”的横向偏移,纵向分支负责“加速度和刹车的时序”。分离之后,模型不用在同一个输出空间里同时纠结方向和速度,学习难度大幅下降。复现的时候如果你的模型总在拐弯时顿挫,先检查是不是横纵没分开。
动态障碍物并没有让VLM自己在像素级跟踪。项目里专门加了一个轻量目标状态预测网络,对每个障碍物输出简单的恒速/恒加速度模型参数,再把“障碍物意图token”注入到Transformer解码器里。模型的轨迹生成头会看到“前方12米处有车,预计2秒内减速停车”这样浓缩过的token流,而不是一堆原始点云。
3.4 安全约束如何参与解码
VLM再聪明,也不能保证每次输出的轨迹都物理安全。解码阶段,我在采样候选轨迹集合上做约束筛选,而不是只取模型输出的一条确定性轨迹。候选轨迹来自两组:一是模型直接回归的结果,二是轨迹回归头根据语义描述采样出的N条变体。然后统一走一个成本函数打分:
- 超出可行驶区域掩码的,直接加巨额惩罚;
- 与障碍物包围盒干涉的,按距离倒数的形式加惩罚;
- 加加速度超过舒适阈值的,按非线性函数加惩罚;
- 与车道中心线偏离过大的,加轻量惩罚。
这条规则链相当于给语言模型的输出装了一个“行车伦理护栏”。模型负责出主意,规则负责把关。实测中碰撞率下降非常明显,不是模型变聪明了,而是它知道不合理的候选会被淘汰。
4. 训练数据与评估体系:没有高质量驾驶语料,一切都是空谈
做VLM驾驶规划,最花时间的不是模型结构,而是数据。开源的驾驶数据大多为感知任务设计,轨迹和自然语言指令的对齐程度远不够用。这一章聊聊数据怎么准备、评测怎么做,以及开环和闭环测试之间那道隐秘的鸿沟。
4.1 数据来源与标注策略
训练数据来自两块。一是公开驾驶数据集里的大规模场景,二是基于仿真环境自采的小规模长尾场景。公开数据覆盖良好天气和常见城市道路,自采仿真数据专门补长尾:雨天、逆光、窄路会车、施工改道、路口无标线等。
标注策略上不做逐像素语义分割,太贵了,主线是道路拓扑和中心线。具体工作流程是:先提取数据集里的高精地图元素,再叠加人工修正,最后把每一段真实人类驾驶轨迹转换成语义指令对。比如一辆车在前方路口右转,对应的指令是“右转进入匝道”,轨迹点取真实方向盘的横纵向结果。最终得到大约5万段训练片段,每段8秒,时间分辨率为0.2秒,也就是40个轨迹点。这个量级不算大,但配合数据增强和场景重采样勉强够用。
4.2 评测指标怎么选:L2误差、碰撞率、舒适性
开环评测阶段,指标很简单:预测轨迹和真实轨迹的平均位移误差ADE,以及终点位移误差FDE。但只看位移误差有陷阱,模型很容易学会输出一条“平均轨迹”,在直线跟车场景分数好看,一到复杂路口就原形毕露。所以项目里还额外监控碰撞率、车道保持率和舒适性指标。
| 指标 | 计算方式 | 关注点 |
|---|---|---|
| ADE(平均位移误差) | 每个预测点与真值点位距离的平均值 | 整体轨迹贴合度 |
| FDE(终点位移误差) | 最后一个预测点与真值终点的距离 | 预判停止位置的精度 |
| Collision Rate(碰撞率) | 轨迹是否与障碍物包围盒相交 | 安全底线 |
| Lane Keep Rate(车道保持率) | 轨迹点在可行驶区域内的比例 | 结构化道路上的合理性 |
| Jerk Max(最大加加速度) | 轨迹二阶差分峰值 | 乘坐舒适性 |
评测时按场景分层统计,分为直行、左转、右转、路口、环岛、施工区六类。只看整体均值会掩盖模型在左转场景上的重大缺陷,这是项目早期踩过的坑。
4.3 从开环测试到闭环测试的迁移
开环评测是“拿真实视频帧喂模型,看预测轨迹与真值轨迹相差多远”。模型没机会看到自己的预测轨造成的后果,误差不会累积。闭环仿真测试就完全不一样,模型输出的轨迹会被一个简化车辆模型去跟踪,然后车辆进入新位置生成新视角,模型需要再次规划。
第一次跑闭环时,分数掉得非常厉害。一个曾经开环ADE只有0.3米的模型,在闭环里30秒后就开始偏离车道。本质上是因为自车轨迹偏差改变了下一帧的输入分布,模型就进入了自己创造的一个全新视觉环境里。要解决这个问题,不能只追求开环数字好看,而是要在训练中加入一定比例的“闭环视角”数据,也可以说让模型学一点对自身误差的纠错意识。我后来在闭环评分里增加了“语义成功判据”:不纠缠厘米级精度,而是看它是否完成右转进入正确车道、是否在停止线前停下。用这个标准去衡量,模型的表现才更接近真车上路的能力。
5. 实际跑车踩坑记录:理想很丰满,现实有五个坑
训练收敛、开环指标达标之后,真正的问题才跳出来。下面这五个坑不是理论推导出来的,而是一版一版跑出来的。每一条几乎都能单独写篇文章,这里说重点。
5.1 幻觉坐标与几何崩塌
最典型的问题:模型对前方空旷区域会脑补出一条并不存在的人行横道或路肩边界,然后轨迹直接朝着路沿冲过去。我把它叫“几何幻觉”。原因是语言模型预训练阶段见过太多“像道路纹理”的图片,视觉token会误导几何分支去拟合一个不存在的结构。
解决办法有两步。一是训练时把BEV投影和几何深度作为辅助损失强制约束,不允许纯语言语义主导几何输出;二是在训练数据里清洗掉那些路面纹理特征过于明显的场景,并手工加入车道线残缺、路面有积水反光等对抗样本。效果比较明显,几何输出的虚警率降低了好几倍,但依然不能完全消除。所以在推理阶段,凡是轨迹点落在可行驶区域置信度低于阈值之外的,我是宁可让它停在原地也不想让它冲出去的。
5.2 轨迹平滑性与时间戳对齐问题
开环指标好看,不代表轨迹能真正落地。一开始输出的轨迹是逐点回归的,相邻轨迹点之间经常出现横向抖动和锯齿,就像手抖画出来的线。原因在于轨迹点预测头没有显式建模时间连续性。后来改成了用样条拟合输出,并给损失函数增加一阶、二阶差分惩罚项,强迫相邻点之间的位置和速度变化平滑。
另一个坑是延迟问题。VLM跑一遍推理大约需要200毫秒,如果模型基于当前时刻的图像规划轨迹,等推理完成时车辆已经往前开了将近一个车身。我一开始忽略了这个时间戳对齐问题,闭环仿真的时候感觉车“老慢半拍”。最终的方案是输入图像往前退3帧,让模型规划的是“200毫秒之后的当下”应该走的轨迹。这个补偿逻辑在真车上一定要做,而且要根据实际推理延迟动态调整。
5.3 小目标漏检引发的连锁事故
锥桶、路边石、小尺寸施工牌,这类目标在图像里像素占比很小,VLM的注意力经常扫不到它们,但驾驶决策又绝对不能撞它们。这不是一个单纯感知问题,因为漏检会导致轨迹完全无视这些目标存在,比感知延迟更危险。
处理思路是加一个小目标检测分支,与轨迹生成共享BEV骨干特征但不共享解码器。这个分支只要能通过“前方有异形障碍物”的粗粒度信号去影响注意力权重就行,不需要输出特别精确的边界框。相当于在模型内部装了一个哨兵,不追求识别得多细,但要求它在轨迹决策时给那些小格子足够的注意力权重。
5.4 数据偏置:过拟合“前车直行”
统计训练数据的时候发现,将近40%的场景都是城市快速路的直线跟车。模型在直线场景很稳,一到复杂路口就犹豫甚至乱来。你让它左转,它先直行一小段再缓慢左切;你让它过环岛,它干脆在入口处减速发呆。
数据偏置的问题只能靠重采样和合成场景硬掰。我把直线跟车场景的采样权重调低,把路口左转、右转、环岛、施工改道这些复杂场景的权重调高,又用仿真器批量生成了大量带随机车流的交叉路口数据。效果很直接:复杂场景的ADE下降明显,而直线场景的指标几乎不受影响。如果你的模型“直行很行,转弯很蠢”,优先检查训练分布是不是一样歪。
5.5 推理速度与算力消耗的权衡
Qwen-Drive-1.0在A100上推理一帧需要大约200毫秒,单看数字勉强可用,但要叠加上下游控制和图像采集延迟,留给规划的时间窗口就很紧张了。部署时做了两阶段推理:先用一个轻量视觉model快速提取车道线和障碍物结构,再让VLM直接在这个结构化输入上做规划。这个方案把大部分耗时从“理解原始图像”降到了“理解结构化场景”,但代价是会丢掉一些端到端语义信息。
我试过只保留结构化输入,结果遇到没见过的场景就有点呆。试过只保留原始像素输入,速度又上不去。最后的折中方案是结构化特征和原始像素特征双通道输入,在注意力层把它们融合起来,牺牲一点速度保精度。量化时视觉编码器用FP16,轨迹头和语言头用INT8,显存占用从接近12GB降到约8GB,推理延时稳定在160毫秒左右。
6. 下一步打算与个人体会
项目完整跑完一个版本,给了我不少超出预期的结论。原先最担心的“VLM根本搞不懂空间几何”并没有发生,只要架构上给它足够多的几何约束,它确实能学会三维道路推理。但这背后也藏着下一个更难的挑战,模型目前本质上是开环策略,它没有预测“未来场景演化”的能力。
6.1 从开环转向闭环世界模型
要让VLM真正理解三维道路并可靠驾驶,不能只做输入到轨迹的映射,还要让它在推理时预演“如果我在第2秒做出这个动作,世界会变成什么样子”。也就是说,需要给模型装一个驾驶世界的预测引擎:输入当前场景和候选动作,输出未来几秒的“预期观察”。有了这种预测能力,轨迹生成才能从“一步到底”变成“边决策边验证”。这是Qwen-Drive-1.0下一代版本的主攻方向。
6.2 用多任务头复用视觉Token的收益
我试过把检测、车道线分割、轨迹规划、指令理解全部接到同一个视觉骨干上形成多任务头。共享权重带来的好处是明显的,检测任务学到的特征能让轨迹规划更稳,轨迹规划反过来也能约束检测结果更贴近几何实际。但要注意loss权重,轨迹loss一旦权重过低,模型就会偏向“看得懂世界但对开车不感兴趣”。我最后把轨迹loss权重设到检测loss的三倍以上,模型才真正开始“以开车为中心”。
6.3 一点个人经验:先跑通最小可用闭环
如果让我重来一遍,一定不会一开始就想做一个完整的“驾驶大脑”。最开始的版本太贪心,什么都想学,结果什么都学不扎实。正确顺序应该是先定义一个最小可用闭环:一条直行道路、一个目标点、一个静态障碍物。让VLM能输出一条不撞上去的轨迹,实现这个再逐步加路口、加动态车流、加自然语言指令。
这套项目做的不是一个能立刻替掉传统规划器的产品,它更像是在回答一个基础问题:语言模型有没有可能成为几何空间里的驾驶决策器。目前我的答案是:能,但前提是你不让它裸碰几何,必须给它三维道路结构这个“扶手”,它才能真正站起来走路。