1. 项目概述为什么自动驾驶世界模型绕不开4D占用聊一个这两年自动驾驶圈被反复提的词世界模型。市面上关于世界模型的讨论很多有生成视频的有做驾驶预演的但落到量产最实际的一条线其实是先把空间被谁占了、未来会被谁占这件事表达清楚。围绕这套思路业界有个很形象的说法——在占用世界里驾驶。它的完整技术形态通常叫视觉中心的4D占用预测与规划也是世界模型范式里最接近落地的一支不用激光雷达只用摄像头看到的历史画面预测三维空间中各体素的未来占用状态再交给规划模块直接使用。我第一次接触到这个方向时第一反应是这不就是把占据栅格加了个时间轴吗。真正做过一轮实验之后才发现加时间轴带来的复杂度远不是多一层卷积那么简单数据怎么标、历史帧怎么融合、未来帧怎么监督、规划器怎么吃这个概率场每一环都有完全不同于传统感知的玩法。这篇文章我就按自己从读论文到跑实验再到思考量产落地的整个过程把这条技术链路拆开讲一遍希望能给同样在做BEV感知、预测决策、端到端规划方向的朋友一些参考。1.1 从障碍物框到占用体素的演进传统感知走的是目标检测路线把场景抽象成一个个框一个行人框、一辆车框、一个锥桶框。检测路线在L2级辅助驾驶里很成熟但到了更复杂的城市场景问题就露出来了——路面上不是只有能分类的目标还有散落的纸箱、掉落的水泥块、因施工被压弯的钢板甚至形状不规则的临时路障。这些东西很难被归进任何训练类别于是模型很可能输出不了框或者框得乱七八糟车却确实不能压过去。于是业界转向了占用网格思路把所有空间按一定分辨率切成小格子体素每一个格子只回答有没有东西。这很像在教室里给座位打标签要么有人要么没人不需要关心坐着的是谁。这个方案天然对未知物友好只要有物理实体会占空间它就在占用标签里被标记出来不需要知道它叫什么、属于哪一类。对驾驶安全来说不知道那是什么但知道那里不能走已经足够支撑避险动作。从BEV到3D占用再到4D占用是这条思路的递进。BEV鸟瞰图把三维世界压扁到地面上丢失高度信息立交桥、悬挂的电线、站在车头前方的行人下沿都难以用俯视图区分3D占用保留高度维度能表达桥上是空的、桥墩不能撞这样的立体关系再加上时间维度就构成了4D占用——不仅知道现在哪里有东西还能外推接下来几秒哪里会出现东西。为了更好理解三者的差异我习惯用下面这张表去对比维度BEV鸟瞰图3D占用4D占用预测空间表达俯视栅格丢失高度当前3D空间占用状态未来多帧3D空间占用状态悬挂/立体障碍物无法区分可以区分可以区分并预测变化趋势时间建模多为单帧单帧或短时序必须带时间外推对未知物体的容忍度弱依赖分类结果强只判占用强并支持预判典型用途车道级感知当前障碍避让安全规划、世界模型基础1.2 为什么是4D而不是3D很多人会问把当前帧的3D占用做准不就够了吗为什么非要预测未来答案是驾驶决策天然是面向未来的。规划模块需要知道的是我接下来3秒走的这条轨迹会不会撞到东西而不是现在这条轨迹上有没有东西。在十字路口对向车辆当前还在左侧车道但3秒后可能切到目标车道旁边一辆静止的车门可能随时打开走出一个人。3D占用只能告诉你它现在在那4D占用预测则告诉你它接下来可能在这。这种时间外推能力就是世界模型这个名字的真正含义——模型内部维护的不是单纯的障碍物列表而是一个接下来世界会怎么演变的隐式模拟器。这个加一维时间的改动工程影响远没有听上去那么小。输出的空间从单帧体素变成多帧体素序列计算量成倍增长监督信号从当前帧真值变成未来逐帧真值数据标注和采样的复杂度完全不一样更关键的是损失函数的设计逻辑也要跟着变因为未来越远越不确定不能要求模型像预测当前帧一样精确地预测第5帧。这些细节我会在后面章节展开。1.3 这篇内容适合谁如果你是做BEV感知、占据预测、预测决策、端到端规划方向的工程师或研究生这套思路基本属于必修课。如果你想了解纯视觉方案在量产工程里凭什么敢不带激光雷达这篇笔记也能帮你把视觉→三维→时序→规划这条链路串起来。我会尽量少堆公式名词多用场景和工程细节去解释让你看完之后至少知道该从哪些模块入手、有哪些坑要提前避开。2. 核心技术拆解从多目相机到未来占用预测整套系统如果拆开看大致是四块多相机图像编码、三维体素表征构建、时序状态融合、未来占用预测。下面逐个说。2.1 多相机输入与体素化表征纯视觉方案的第一步是把多个环视相机的画面搬到一个统一坐标系里。常见做法是先用一个共享权重的图像骨干网络把每一路相机提成多尺度特征图再利用相机内参、外参和深度信息把图像特征投影到车体周围的三维空间。这步在很多文章里被叫BEV构建但放到4D占用预测的场景里构建的不再是鸟瞰栅格而是含高度维的体素特征栅格。关键点是体素化具体怎么定义。常用车体坐标系会覆盖车前方约60到80米、左右约30到40米、高度约-2米到4米的范围这个高度范围要把地面以下的路面和上方的天桥底部分开又不需要覆盖整栋楼。体素分辨率一般取0.4到0.5米因为3D空间里的体素数量是长宽高相乘分辨率每缩小一半体素数量变成8倍计算量直接起飞。0.5米分辨率下80×40×6米的区域就能产生大约15万个体素已经足够占用分类使用如果想再识别精细的物体边界再单独做边缘优化而不是直接把全局分辨率拉高。投影方式上比较成熟的是两步走先用深度估计网络给每个像素预测一个深度分布把像素洒到三维空间中然后在体素网格内做加权求和得到每个体素上来自各相机的特征有些方案还会在投影时加一层注意力让模型自己决定哪些视角、哪些深度层级更可靠。这里很容易踩的一个坑是内外参标定一致性任何一路相机的外参偏差超过几个像素投影后的特征就会错位多目特征在体素里互相打架导致远处目标出现重影。所以在跑模型之前先把各路相机标定误差控制住比调任何网络参数都重要。2.2 时序融合让模型记住之前的世界有了当前帧的3D占用特征后下一步是让模型具备时间记忆。纯视觉方案没有激光雷达那样一帧一个干净点云单帧摄像头天然存在遮挡和深度模糊所以时间窗口非常关键。常用设计有两种。一种是显式时序拼接把过去5到10帧的BEV或体素特征沿时间维叠起来让Transformer或稀疏卷积直接融合。这样做简单直接但特征张量很大显存压力高。另一种是递归式维护一个隐状态向量每输入一帧通过门控循环单元或带时序注意力的模块把隐状态更新一次预测未来时也从隐状态解码。递归式在推理时比较省资源但训练时梯度要沿时间反向传播收敛难一些还容易出现状态漂移。实测下来大多数工程会采用折中方案过去几帧用可变形注意力做跨时间查询不需要把每一帧的所有体素都存起来只对当前帧的每个查询位置去历史帧对应位置附近采样特征。这样既保留了时间信息又控制住了显存。比起盲目堆帧数五到六帧历史输入通常已经能把速度、加速度这样的运动趋势学得比较稳定。再往上加帧收益会快速衰减反而带来时序对齐和训练内存的问题。2.3 未来占用预测从历史外推未来这是4D占用预测最核心的一步。拿到历史隐状态之后模型要输出未来1到5秒的占用序列。目前主流做法分两类。第一类是并行预测一次性把未来各帧的体素logits都算出来训练时用未来帧的占用真值做监督。实现简单、训练稳定但问题在于模型没有任何显式因果概念很难保证未来帧之间的时间连贯性。第二类是自回归预测先预测下一帧把预测结果作为输入再预测下下帧。自回归模型天然延续性好但存在误差累积第一帧错了后面越错越离谱。很多实际方案会把两者混着用比如在训练时用教师强制加速收敛在推理时再做自回归微调或者对未来每一帧输出一个是否可信的权重用权重去调节损失。这里要特别强调一点未来占用预测的目标不是把画面预测得多漂亮而是保证危险区域不漏报。一辆车未来会不会开过来、一个行人会不会横穿这类信息哪怕偏几个体素都有价值而那些已经静止的车位线、路边绿化带预测得准不准其实不影响驾驶安全。所以损失函数里应该对动态体素给予更高权重具体做法是拿未来帧真值和当前帧真值做差分找出状态发生变化的体素在损失里给这些体素额外加权。2.4 训练目标与损失函数设计占用预测本质上是个分类任务体素三分类空闲、占用、未知。最常用的是加权交叉熵因为空闲体素占比极高如果不加权模型会倾向于把所有格子都预测成空闲。通常按类别统计频率做倒置权重同时对占用这个类别再乘一个额外系数比如5到10倍。单靠分类损失还不够建议叠加一个Dice Loss或IoU Loss它直接优化占用区域的重叠度对边界更敏感能减轻类别不均衡带来的边界糊问题。第三类常用的是时序一致性损失让相邻时间步的占用输出在空间上不要闪跳如果模型预测某个体素下一帧被占用、再下一帧又突然完全空闲这种高频抖动对规划器来说非常不友好。可以在特征层面计算相邻帧输出的L2变化作为惩罚项。如果整个系统是端到端联合训练到规划器的还会在最后叠一个轨迹损失例如让规划轨迹与真值轨迹的L1误差最小再把碰撞约束以软惩罚形式加进去。3. 规划器如何使用4D占用预测结果预测本身不产生价值规划才是最终动作。这一章讲清楚占用结果如何被下游使用以及什么样的人设计规划器会真正喜欢这套输入。3.1 把未来占用变成规划器的输入4D占用预测输出的是多帧概率场规划器不可能直接把几十万个体素丢进优化器里算。工程上常见的做法是把未来各帧的占用概率压成一个可行驶成本地图像序列对每个体素结合它的占用概率、类别如果模型顺带输出动态/静态、以及距离自车的远近换算成规划成本。概率越高的体素如果轨迹从它上面经过惩罚系数就越大距离越近惩罚也会放大。这和人类开车的直觉一样看到前方远处有个东西飘在路上可以缓缓观察如果近在眼前必须立刻绕开或刹停。具体计算成本时每个候选轨迹点会被投影到对应时间帧的占用概率场上取路径点周围一个安全半径内的最大占用概率作为惩罚因子。这个安全半径要根据车宽和车速动态调整高速场景留更多余量低速穿梭时可以稍微收紧。轨迹生成常常先在Frenet坐标系下采样一系列备选轨迹包括不同的纵向加速度和横向偏移再用成本函数打分排序。整个过程很像是把前方有东西翻译成一个可以求导、可以搜索的数值场。3.2 路径成本计算与安全约束成本函数一般分好几项路线贴合度、速度偏好、加速度变化率、以及最重要的占用碰撞惩罚。碰撞惩罚要设计成软约束直接设成硬约束很容易导致无解轨迹。比较好的写法是指数惩罚旁路引导当占用概率超过某个阈值时成本指数上升这样规划器会尽量避免但万一找不到完全无碰撞轨迹还能给出一个减速避险方案而不是直接报无解。实际工程里还会额外给占用概率场加一个膨胀层。因为体素是离散的车辆本身有一定宽度轨迹点哪怕不在占用体素内也可能因为车宽擦到边。考虑未来预测本身有误差膨胀半径通常取车身宽度的一半再加0.3到0.5米的余地。这套逻辑很像给地图里的障碍物加缓冲带跑起来之后明显能降低刮蹭风险。膨胀半径也不能给太大否则在窄路会车时会频繁误刹体感很差得根据自车宽度和驾驶员风格去调。3.3 端到端联合优化与中间监督的取舍如果你的目标是研究范式的完全体可以把感知预测模块和规划模块放到一个网络里端到端训练图像进来损失直接反传到轨迹上中间占用预测头只作为辅助监督。端到端的好处是模型不会被感知中间结果束缚有可能学到一些绕过中间表征的捷径。但坏处也很明显——训练不稳定一个模块的误差会污染整个梯度出了问题很难定位。在工程上我更推荐先分开训练让占用预测头收敛到差不多的状态再加入规划损失联合微调几个轮次。本质上的是两阶段精调稳定性和最终效果都更可控。很多团队在中间监督和端到端之间反复横跳我的看法是中间监督不能省。纯视觉占用预测系统一旦少了中间监督规划器学歪了的时候很难定位是哪层出了问题。有显式的占用头在至少你可以在测试时把预测结果可视化人工很快判断是障碍物漏检还是路径成本设计不合理。这个排查效率在量产Debug阶段太重要了。4. 工程落地数据、显存、评估的实战指南接下来写点更偏执行的数据、显存、评估。这三个环节是很多人第一次跑通模型后深度崩溃的来源提前规划能少走不少弯路。4.1 数据预处理从点云标签到体素真值训练4D占用预测需要真值标签。如果常用开源驾驶数据集只提供3D框一个常见做法是把所有框的包围盒转成被占用的体素集合再配合路面区域外的高程模型生成地面空闲体素。但框对不规则物体无效所以如果数据集里有激光雷达点云最好直接用点云生成标签把每帧点云按位姿转换到车体坐标系落在哪个体素里那个体素标为占用。需要注意点云密度不均远处的体素可能因为点少没被标记但这并不代表它真的是空闲这类区域应该标为未知否则会让模型把没看清学成没东西。对于距离超过某阈值的体素建议直接归入未知类。这个未知类不是可选项而是纯视觉占用系统里决定安全上限的关键设计。预处理流程里有几个容易忽略的细节时间对齐多相机图像、激光雷达点云和定位位姿的时间戳差几毫秒在高速场景下可能整体平移几十厘米必须做严格时间同步。坐标补偿预测未来帧时如果车辆正在运动未来的占用状态其实包含两部分——被预测物体的运动以及自车自身前进导致的相对位移。训练时一定要把所有帧都转换到当前自车坐标系下否则模型会把自车运动也当成场景运动一起学推理时越跑越乱。标注过滤护栏、绿化带这类静态但边界模糊的物体真值本身存在噪声建议在损失中降低这类区域的权重。4.2 训练资源配置与显存优化4D占用模型是显存大户。一个中等规模的模型输入6路相机图像输出未来5帧的15万体素分类batch size开到8单卡24GB显存基本扛不住。实际训练时我常用三个手段。第一是图像编码器和体素解码器分开训练或者做梯度截断先让图像骨干收敛再冻结它训练占用头峰值显存可以压下去很多。第二是开启自动混合精度训练占用这类密集分类任务对浮点精度不敏感半精度在多数场景下能保持甚至提升速度。第三是用梯度检查点对编码器里每个模块只保留少量激活反向传播时再重算用一部分算力换显存这笔账在长序列训练时非常划算。如果连未来5帧都放不下就采用帧分组策略把未来帧的体素分两组一组进损失反传另一组只做前向不反传每轮迭代交替。这个技巧能让显存占用直接砍半收敛速度下降却非常有限。我实测下来未来3帧以内基本不需要这个技巧但一旦扩到5帧以上帧分组几乎是必须的。4.3 评估体系搭建别只看可视化视频。预测视频拍得再好看可能只是模型在复读上一帧。正式评估至少要看几类指标当前帧/未来帧占用IoU更细一点单独看静态体素和动态体素的IoU因为动态体素才是预测能力的体现。预测精度趋势未来1秒、2秒、3秒的IoU曲线正常应该是衰减的衰减过快说明模型几乎没有学到运动规律。碰撞率把规划轨迹叠加到未来占用真值上统计轨迹与未来占用发生重叠的比率。这是最能反映下游安全收益的指标。长尾场景命中率人为挑选施工区域、低速外卖车穿插、被遮挡行人突然出现等案例统计这些场景下的表现。还有一个容易被忽视的问题测试集里如果大量场景是直道跟车模型只要预测保持现状就能拿到很高的IoU会让人误以为效果很好。一定把直道、路口、变道场景分开评估尤其关注变道和路口那里才是4D占用预测真正起作用的地方。5. 踩坑记录4D占用预测的常见问题与排查这一章是我最想写的部分因为很多坑不会出现在论文里只会出现在实际工程中。我按问题的高发程度和危险程度排了个序。5.1 正负样本极度不均衡体素分类里超过九成是空闲体素占用体素可能不足3%。如果不加处理模型会稳定输出全空闲IoU看起来还不错因为空闲占绝大多数。解决思路不只在损失函数加权还可以对场景做区域采样训练时只对车辆周围一定半径内的体素计算损失同时强制保留一定比例的动态占用体素比如把未来几帧发生变化的体素按batch额外采样拼到损失里。这样做的根本目的是让模型把注意力放在真正会变化的边界区域。否则就算模型学得很好也会因为大量简单样本把梯度稀释掉导致动态物体边缘的预测始终模糊。对4D占用来说动态边界的敏感度比静态区域重要得多。5.2 未来帧预测越来越糊是常态所有预测模型都存在误差累积未来越远越模糊占用预测也一样。4D占用预测第1帧IoU可能到0.65第3帧掉到0.4第5帧只剩0.3这不一定是你模型坏了而是任务本身难。关键是看曲线斜率如果前两帧也掉得非常快说明模型没有学会基本运动规律。这时候可以尝试在训练时更强调短期帧的权重或者加入自车运动解耦把自车前进导致的所有物体相对移动这部分先单独建模让模型只负责学习目标物本身的运动。还有一个技巧是给未来帧真值加一点空间平滑因为体素分辨率有限未来帧的标注本身就存在量化噪声直接用硬标签监督远处的预测会让模型变得不稳定。我在实验里会先对未来真值做一次3D高斯膨胀再计算损失相当于告诉模型靠近占用的地方代价也很高实测对远端预测帧更友好。5.3 遮挡区域被当成了空地这是纯视觉占用预测最危险的一类错误。车辆前方有一辆大车大车后面藏着行人单帧图像根本看不到模型很容易把大车背后预测成空闲导致规划器大摇大摆选择从大车后方切入或者做出了前方空地可加速的判断。处理办法是充分利用前面说的未知类凡是历史帧里一直遮挡、当前帧没有观测到证据的区域输出应为未知。未知区域在成本函数里自定义成高代价探测区不主动规划进入等待后续帧观测到更多信息再决定。这比猜一个空闲出来安全得多。工程上可以把感知模型输出的占用概率、深度不确定性、历史遮挡mask综合起来算一个未知概率这个概率再放进规划成本函数权重甚至可以调得比占用还要高。5.4 模型在测试集涨点、上板就抖离线IoU涨了但车跑起来刹车频繁、方向不稳原因大概率有三类一是未来占用概率场的概率值标定不对规划器把0.4的概率当作必然碰撞导致过度刹车二是预测模块的时间滞后模型输出比实际世界慢了几百毫秒规划器算出来的轨迹都基于过期场景三是体素分辨率太大占用边界比车宽还粗糙路径贴着边界蹭过去。前两类可以通过校准输出概率、减小网络时延去解决。概率校准这件事比很多人以为的更重要占用概率本质上是分类置信度而规划器需要的是这里被我压过去出事的概率两者有差距需要用真值统计做一个映射比如把预测概率0.3但真实占用率只有0.1的区域单独挑出来调阈值。第三类建议在成本函数里加大膨胀层而不是盲目提高体素分辨率因为全局提高分辨率带来的显存压力远大于收益。6. 扩展心得两帧起步逐步走向端到端在这套范式的工程化过程中我最深的体会是它不是一个孤立的模型更像一条用统一表征把感知和决策串起来的系统工程。刚开始可以不用急着端到端先搭一个能预测未来占用概率场并离线可视化的基础版本把数据、训练、评估链路跑通再逐步把规划模块接进来。我个人的一个小建议是先做两帧预测而不是一步到位做五帧。把两帧预测做到稳定比如动态体素IoU能稳定在0.5以上再扩展到更长时序。这样做的好处是如果模型预测结果不理想你可以清晰判断到底是对短时运动建模不够还是长时外推本身不稳定排查问题会容易很多。如果你也在折腾这条路多关注动态体素的变化率和遮挡区域的未知类处理这两个细节它们是纯视觉占用预测能否真正上车的关键分水岭。