最近很多朋友私信问我搞自动驾驶仿真或者数字孪生城市的时候到底拿什么才能生成一个真正能跑、能看、还能无限大的动态城市我都是同一个回答你先别急着堆资产、拉模型去看看这个叫“组合式无界4D城市生成模型”的工作。它把城市拆成静态场景和动态物体两件事分别生成再组合渲染最后形成一个可以用相机轨迹任意游走的4D世界。这个思路值得所有做世界模型、仿真验证、AIGC内容生产的人认真读一遍。我自己花了很长时间把这篇论文的流程走了一遍也踩了不少坑今天就用这篇博文把我理解的原理、实操细节、训练推理的关键点以及真实遇到的坑全部分享出来。无论你是研究生成模型还是做自动驾驶仿真、游戏大世界我建议你把这篇文章看完再去翻原论文会轻松很多。1. 从静态3D到动态4D这个模型到底在做什么1.1 无界4D城市是什么我们先掰扯清楚四个字无界、4D、城市、模型。城市大家都能理解就是有道路、建筑、行人、车辆、红绿灯这些东西。无界的意思不是指物理空间无限大而是指这个生成系统不限制在一个固定的包围盒里理论上可以沿着任意方向无限往外扩。这一点很重要因为传统NeRF或者3D高斯重建出来的城市就是一个有限体积的三维模型你走远了就没有了场景直接被裁掉。4D则是在3D空间基础上加了一个时间维。动态城市不是一张静态的全景图而是会动的车辆在移动、行人在走路、红绿灯在变化风吹过树叶也会动。所以4D城市就是一个连续的时空体任意时刻任意位置都有一个合理的内容呈现。那“模型”呢这里说的不是那种CPU/GPU跑推理的模型文件而是“世界模型”层面的含义它不能只是重建你给过的数据还得具备一定的泛化和想象能力给你一条没有走过的相机轨迹它能补出一条看起来合理、连续、动态的城市视频。举个例子你开车记录了一条路线有了多段视频和位姿传统方法能把这些视频里的内容“冻结”成一个静态三维场景。但当你换一条没有走过的路线去看时静态模型会露出很多空洞和拉伸。而这个组合式模型会先理解城市的基本布局再理解里面物体的运动规律然后针对新路线生成新的内容包括新的车辆和行人。这就是“世界模型”该干的事。1.2 为什么说它是世界模型而不是场景重建传统重建是在“恢复真实的物理世界”目标是让新视角看到的颜色和几何尽可能接近真实观测。而生成式世界模型的目标是“产生一个可信的世界”不仅要还原已知视角还必须在未知视角和未来时间点上给出合理内容。所以你翻这篇论文的方法设计时会发现它的思路不是“如何把多视图照片填充成一个空间”而是“如何让模型学会城市里的静态布局规律和动态运动规律”。它把城市看成两部分静态底图建筑物、道路、交通标志和动态物件车、人、可能的附加物分别用生成模型建模。这样至少在模式层面它具备了对新位置和新时间的预测能力。这是它区别于显式引擎的地方。有些仿真平台是靠人工建模和逻辑规则比如设定车辆路径来驱动那不是模型生成而是程序化生成。组合式4D城市模型是靠数据学习出来的潜在结构你给它一个位置和时刻它自己决定那里应该有一栋楼还是一辆车。所以你把它叫世界模型原因就在这里它在内部学到了城市运行的一种“条件概率分布”。2. 组合式生成为什么不直接生成一个整体2.1 直接生成一个巨大4D城市为什么不行你可能会想我把整座城市当成一个整体让扩散模型或者自回归模型去生成4D体素不就行了理论上可以实际完全跑不动。原因有三点。第一复杂度爆炸。一个城市哪怕只有几平方公里你用体素网格表示分辨率稍微高一点内存就瞬间打满。再加上时间维度每个体素还得有多帧状态这个张量大到没有任何单卡能装下甚至分布式训练也不划算。第二数据获取灾难。你要得到一个完整的、动态的城市3D标签需要同步采集深度、语义、光流还要逐帧标注车辆和行人轨迹。这种数据在真实道路上很难大规模采集仿真器里倒是能出数据但仿真器本身又缺真实性。第三控制不灵活。如果整个城市用一个整体模型描述客户想修改某个路口的交通流或者增加几个行人你都没办法局部修改。必须重新生成一次这在实际应用中是灾难。所以这篇论文选择了“组合式”Compositional——把城市拆成静态场景和动态物体两大块各自生成、各自优化最后合成到一起。这是工程上真正可行的路径。2.2 拆成静态场景和动态物体之后在组合式框架里至少有两大模块。第一个是静态场景生成器。它负责生成道路、建筑、地面、天空、交通设施这些不变的部分。这里的“不变”只是说在短时范围内基本不动但光照变化、红绿灯变化有时候也会影响视觉效果所以实际还会加一些条件变量。静态场景可以用一个紧凑的三维表示来建模例如把城市划分成局部块每个块用一个潜向量表示再通过神经渲染器生成该视角下的图像和深度。第二个是动态物体生成器。它专门负责生成人和车这类可移动目标。它要回答三个问题这个位置有没有物体什么类别它在什么时刻出现在哪个坐标、姿态和外观是什么这两个模块分开后各自的数据获取就简单多了静态场景只要有图像和几何就能学动态物体只要有2D检测框和轨迹就能学不用非得拿到一个一体化的动态三维世界标签。最后还有一个合成器负责把动态物体渲染结果和静态背景合成处理遮挡、光影和接触阴影。这个合成器就是组合的关键稍后我会展开讲。3. 核心组件与关键技术拆解3.1 静态场景生成器的内部结构我在复现时的理解是静态场景生成器不需要做成一个单一的全局模型而是做成“局部隐式场 全局布局码”的形式。城市是非常结构化的建筑遵循道路走向道路交叉口有特定几何规律。如果你用一个纯粹的隐式场去拟合整个城市就像逆向工程一个程序你希望某个网络能记住所有细节但这个网络根本没有足够容量。更好的方案是把城市划分成网格状的局部区块每个区块分配一个独立的潜码分别描述这个区内建筑密度、道路朝向、天空可见度等。渲染某个位置时先通过坐标查询找到所在区块和邻接区块的潜码再插值得到连续特征送进一个小的神经渲染头比如基于NeRF或3D高斯表示输出对应图像块。这样潜码就是城市的“可编辑属性”你改变某个区块的潜码就能改变那个区域的建筑风格。训练的时候不同区块共享同一个渲染网络权重只是潜码不同。这相当于让网络学会了“城市楼宇长什么样”的通则而潜码记的是局部差异。这也让模型具备了一定的跨界外推能力一个从没见过的城市区域只要给它一个合理的潜码也能被渲染成可信的楼房。3.2 动态物体生成器的三种粒度动态物体生成器比静态场景更复杂因为物体既要出现在正确的位置又要有合理的运动轨迹外观还得多样。论文我看下来实际是把它分解成了三层。第一层是“布局先验”即判断哪里会出现动态物体。比如道路上容易出现车辆人行道附近容易出现行人草地和建筑内部则基本没有。这个先验可以从语义地图上学也可以从轨迹数据里统计。第二层是“轨迹预测”给定一个起点和终点条件生成一条车辆或行人的运动路径。这个路径必须符合交通规则不能穿墙而过也不能逆着车道。第三层是“外观生成”为每一个物体实例生成一个三维外观表示可以是小型的NeRF或高斯模型然后在对应时间点上放在对应空间位置。这样的三层分解让动态生成变得可控你可以单独调整轨迹或者单独换一个外观模型而不需要重新生成整个场景。这非常符合工业场景的需求。比如做自动驾驶仿真时你希望今天测的是同一辆车外观、不同驾驶路径明天是不同外观、同一条路径。这种组合式离散控制是整体生成模型给不了的。3.3 组合渲染与遮挡处理组合渲染是整个模型最容易翻车的地方。动态物体在3D空间里是分散的但在2D屏幕上难免会遮挡静态背景也会互相遮挡。合成时不能简单地把动态物渲染结果叠加到静态背景上那样会出现半透明、边缘错位和双重曝光。我的经验是合成器最好具备以下几个输入静态背景的颜色图和深度图动态物体的颜色图、深度图和实例分割图。合成器输出最终图像的权重图或者alpha图利用深度关系判断谁在前面。同时动态物体的底部与地面接触的地方要有接触阴影不然物体会像“悬浮”在空中一样特别假。在实际代码实现中我的做法是先生成静态场景的完整视图然后逐帧渲染动态物体到同一相机参数下将动态物体的深度与静态深度做比较得到遮挡掩码再通过一个轻量级神经网络修正边界。这个方法实现起来不复杂比端到端一起训要稳定得多。3.4 相机轨迹控制与交互式探索当你有了静态场景、动态物体和合成器之后整个系统还需要一个“指挥者”让用户任意设置相机位姿和时间才能输出指定视角的视频。这个指挥者其实就是一个前向渲染流程给定时间t查询动态轨迹生成器得到每个物体的位置和姿态查询静态场景生成器得到背景然后相机参数从外部传入渲染出画面。这个过程必须支持“exposure”式的迭代查询因为城市的范围可能是无界的物体数量也可能很多。你不能一次性把全世界所有物体都生成出来而是只在相机视野范围内生成局部物体。也就是用一个滑动的局部窗口根据相机位置动态加载区块潜码和动态实例。这种局部生成全局潜码的方案正是“无界”的真正实现方式。我最初以为无界是用巨大的一次性网格看完后才明白那是“无限近视场的方式”用局部潜码在任意方向扩展当前视线内永远有内容。4. 实操过程数据准备、训练、推理全流程4.1 数据集的构成与预处理要复现这个模型第一关是数据。从论文信息来看它需要的是城市多视图视频数据包含准确的相机位姿和大致的时间同步。如果你没有条件采集自己的城市数据可以用公开的自动驾驶数据集作为起点里面有很多前视、环视视频和IMU/GNSS位姿非常适合。拿到数据后先做分帧和位姿解算。如果数据集自带位姿直接使用没有的话用现成的SLAM或运动恢复结构工具解算。注意相机位姿的精度直接影响静态场景生成质量尤其是大场景无界重建位姿稍微偏一点就会导致建筑边缘发糊。建议在解算后做一次全局光束法平差把累计漂移降下去。第二步是分离静态背景和动态物体。你可以跑一个现成的2D目标检测器比如常见的检测模型提取每一帧中的车辆和行人框。对这个检测结果做多目标追踪生成每个物体的时间轨迹。静态背景则通过“对同一区域多次观测取中值”的方式粗提取或者利用光流的运动边界来抠掉动态像素。第三步是划分训练区块。由于城市是无限的但我们计算量有限需要将场景切成重叠的局部窗口每个窗口作为一个训练样本。窗口的大小取决于场景复杂度一般以能包含一个路口或一段街区为宜。相邻窗口需要有重叠这样推理时插值才不会出现明显的“接缝裂缝”。4.2 静态模型的训练细节静态场景生成器的训练类似于NeRF但多了一个局部潜码表。每次输入一个窗口坐标和视角方向网络预测体密度和颜色。损失函数除了渲染颜色和真实颜色的差异外还要加上深度平滑损失和潜码的正则项否则潜码会过度拟合并丢失泛化能力。训练技巧上建议先用低分辨率比如256x256训练足够轮次让潜码稳定下来再上高分辨率微调。我踩过直接用1024分辨率的坑潜码震荡很厉害训练很久都不收敛。低分辨率阶段网络会更容易学到全局结构然后高分辨率阶段再去丰富纹理。这个“先结构、后纹理”的顺序对城市场景很管用。另外无界场景训练时相机位置要尽量均匀覆盖。如果某个区块的视角太少生成出来的建筑会像融化了一样因为网络根本没有足够约束。我后来在采样训练视角时会增加一个覆盖度检查每个区块若没有超过一定数量的相机样本就强行做镜像增强或者从邻居插值。4.3 动态模型的训练细节动态模型训练分两部分轨迹和外观。轨迹模型我实现时用的是一种扩散模型。把物体的轨迹表示为一系列空间点和速度向量在训练时给它噪声让模型学会从噪声中还原真实轨迹。条件变量包括起始点、终点、时间长度、物体类别。损失函数除了轨迹上的位置误差还要加一个碰撞惩罚如果轨迹与静态场景深度冲突或者两个物体轨迹重叠就要在损失里增加惩罚项。这个碰撞惩罚很关键不加的话生成的车会穿楼、行人会穿车。外观模型则是对每个物体类别训练一个条件生成器输入类别和物体大小输出一个物体的三维外观表示。这个外观模型可以做到非常轻量因为一辆车持有的是几百个高斯点或一个小型NeRF比一个大场景轻得多。每个物体实例只生成一次外观后续在所有时间帧中复用只是位置和姿态变化。训练时要注意类别不平衡。车辆样本远多于行人轨迹模型容易被车辆带偏。我的做法是对行人轨迹做上采样或者让损失函数按类别加权保证行人的起点终点预测也能保持稳定。4.4 合成器训练与整体微调合成器我建议单独训练不要一开始和两个生成器一起端到端训练。先生成静态渲染结果和动态渲染结果用它们作为合成器的输入目标图像是真实帧。合成器是一个小的卷积网络输出融合后的最终图像。单独训练合成器几分钟就能收敛然后再把它和前面的生成器一起做端到端微调。在端到端微调阶段损失要包含颜色、深度、光流三个方面。颜色损失保证视觉质量深度损失让动态物体和静态背景在几何上不要打架光流损失让动态物体的轨迹在相邻帧之间平滑。如果缺少光流损失车辆可能会在几帧之间跳变看起来像瞬移。训练时内存占用很大因为同时要跑静态生成和动态生成。我建议用混合精度训练并且把动态物体的数量限制在每批次最大32个。超过了就随机采样但每次采样要覆盖不同空间区域防止偏科。推理阶段就简单很多用户输入一条相机轨迹和时间范围系统逐步查询每个相机姿态下的潛码、动态物体的状态然后渲染合成。如果希望达到实时可以对静态场景预渲染成缓存动态物体单独实时渲染再合成。不过离线渲染的完全体验已经足够做内容生成了。5. 踩坑记录常见问题与排查技巧5.1 场景边缘闪烁这个问题在无界场景中特别明显相机转到两个局部区块交界处时建筑物出现断续的闪烁或“棱边跳变”。原因是两个区块的潜码不连续插值权重不够平滑。解决方法有三个增加区块重叠区域重叠的宽度至少要到视野范围的五分之一在潜码插值时使用平滑核而不是线性插值对每个区块的潜码做低通正则强制相邻区块的潜码差异不要过大。我在实际中三管齐下才解决。5.2 动态物体和静态背景发生穿模车辆或行人走到一半半个身体嵌在墙面里。这是因为轨迹模型没有充分感知静态场景几何。我说一个直接有效的办法在轨迹训练时把静态场景的低分辨率深度图作为条件输入给轨迹模型。这样模型看到前方是一堵墙就会避开。推理时也需要实时查询静态场景深度来约束轨迹相当于一个碰撞检测函数。市面上很多轨迹预测都没有这一步但在这个组合式框架里很容易加就看你愿不愿意多写这部分代码。5.3 长视频推理时轨迹漂移推理生成很长的视频时车辆轨迹会慢慢偏离道路中心甚至滑到路边。原因是扩散模型生成轨迹时是逐段生成的相邻段之间只有一端重叠重叠部分不一致导致微小偏移累积。我解决的办法是引入“回归锚点”每生成一小段轨迹就回退到最近的真实车道参考线上做一次投影约束。如果手头没有车道线数据就提取静态场景的灰度梯度或方向场作为弱参考把轨迹拉回主方向。5.4 训练显存不够显存不够是必然的除非你只用一小块街区。我试过的方案里梯度检查点可以显著减少静态场景渲染内存但会增加约百分之三十训练时间值得做。动态物体的外观模型要复用不要每帧重新生成我是把所有动态实例先推理出外观表示缓存到内存里训练时只取索引。这样显存从峰值80G降到了32G左右。5.5 光照一致性缺失合成时动态物体和静态背景的光照方向不一致看起来像塑料贴图贴上去。城市光照有强烈的方向性和阴影差一点就很假。我的思路是在合成器里额外输入一个光照特征让同一个网络同时预测物体的光照调整因子。训练时随机调整背景亮度让合成器学会把动态物体压暗或提亮以匹配背景。这一步对提升真实感帮助极大建议大家后面的版本都加上。6. 观察心得与可能的扩展方向真正做完这个流程后我对组合式生成的理解深了很多世界模型不一定要通过一个巨大的模型把所有事物“吞进去”再吐出来把复杂世界分解成静态和动态两大块分别建立生成模型再用一个轻量合成器衔接已经可以在现实数据上达到非常高的质量。这种思路尤其适合城市这种“静态底图稳定动态目标多变”的环境。后续有几个方向我自己很看好。第一个是加入语义控制你直接输入“左转路口改成环岛”“第三车道变公交车道”然后让静态生成器重画街区布局。第二个是将轨迹模型升级成交互式多辆车之间不再完全独立生成而是考虑车与车的交互这会让交通流看起来更真实。第三个是把这套组合式框架从城市搬到室内或野外静态底图成了房间和地形动态物体成了人和动物逻辑完全一样。如果你是做生成模型研究或者数字内容生产工具的我建议你重点研究一下它的模块解耦方式。不要急着把静态和动态做在一个网络里很多时候解耦才是能走向更大规模的关键。最后分享一个小技巧也是我在实际中最常用的一招把静态场景潜码的维度分成建筑几何、纹理风格、路面条件三部分这样你可以只微调纹理风格这一部分就能让同一个城市呈现白天、黄昏、雨天甚至科幻末日的不同外观而不用重新训练整个生成器。这个解耦思想本身就是组合式模型能走通的核心。希望这篇分享能帮到正在和城市场景、世界模型较劲的你。