视觉语言模型如何生成三维驾驶轨迹:Qwen-Drive-1.0实践解析 第一版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能输出一条不撞上去的轨迹实现这个再逐步加路口、加动态车流、加自然语言指令。这套项目做的不是一个能立刻替掉传统规划器的产品它更像是在回答一个基础问题语言模型有没有可能成为几何空间里的驾驶决策器。目前我的答案是能但前提是你不让它裸碰几何必须给它三维道路结构这个“扶手”它才能真正站起来走路。