Project Overview: UE5 Rendering Fidelity vs E2E Autonomous Driving, Part 1
传统自动驾驶是模块化流水线(modular pipeline):感知(检测/分割)→ 预测(他车轨迹)→ 规划(路径搜索)→ 控制(PID/MPC 跟踪),每个模块独立开发、独立训练,模块之间靠人工定义的中间表示(如目标框、车道线、占据栅格)传递信息。
端到端(End-to-End,E2E)把这整条链换成一个神经网络,直接从传感器输入映射到驾驶动作:
其中 是 时刻的观测(相机画面、定位与姿态), 是输出的控制量或未来轨迹, 是全部可学习参数。中间不存在任何人工定义的接口——感知和规划之间没有信息瓶颈。
流水线里感知模块的优化目标是检测精度(mAP 之类),这个指标和最终”开得好不好”只有间接关系;感知漏掉一个远处行人,规划模块拿到的世界里根本不存在这个人,误差无法回传修正感知。
端到端则可以把最终驾驶目标的损失 通过反向传播(backpropagation)穿透整个网络:
感知特征为了”开好”而学,而不是为了”检测准”而学。这是”梯度可穿透、联合训练”这句话的实际含义。
学术与量产的主流路线是**模仿学习(Imitation Learning)**中的行为克隆(Behavior Cloning):用专家(人类司机或仿真特权智能体)的驾驶数据 做监督学习:
已知的核心弱点是协变量偏移(covariate shift):训练数据里的画面都是”开得好”时看到的,一旦模型犯错把车开到异常位置,画面就落在训练分布之外,错误会级联放大。缓解手段是数据聚合(DAgger 类)或让专家数据覆盖恢复动作。本项目中两个主角模型都属于这条路线的视觉-语言模型(VLM)变体。
模型在分布 的画面(UE4 渲染)上训练,在分布 的画面(UE5 渲染)上测试。输入层面的**协变量偏移(covariate shift)**指:
是像素输入, 是驾驶动作。即:画面的特征分布漂移了,但”画面该怎么开”这个映射关系没变。监督学习的一切泛化保证都建立在”训练分布 = 测试分布”上,一旦 ,模型表现只能实测,无法先验推断。
仿真到现实(Sim-to-Real)是同一结构的问题:训练用仿真画面,部署到真实世界, 与 的差距是”假”与”真”的差距。常见缓解手段是域随机化(domain randomization)——故意把仿真的光影、材质、天气打乱,让训练分布足够宽,把真实世界”包进去”。
本项目研究的是它的姊妹版:仿真到仿真(Sim-to-Sim), 与 只差渲染引擎一代。优势在于变量完全可控——同一张地图、同一条路线、同一辆车,唯一变化的是渲染管线,这是在 Sim-to-Real 里永远做不到的隔离。
两种结论在文献里都能找到支持,意味着答案取决于模型、任务和差距大小的具体组合——这是必须实测而非推理的问题。域差距本身还可以量化,见本项目的 KID 测量(跨引擎 0.0743,同引擎重跑 0.0001)。
CARLA(Car Learning to Act)把仿真拆成两个进程:
默认端口约定(0.9.x 系):2000 是 RPC 端口,2001 是传感器数据流端口,2002 是 Traffic Manager(TM,交通流量管理器)端口——本项目因 Windows 端口占用问题全部迁移,见”硬件与双仿真器拓扑”一篇。
关键性质是:Python API 在两代引擎间保持同源。CARLA 0.9.15 的服务端是 UE 4.26,CARLA 0.10 的服务端是 UE 5.5,但客户端面对的 carla.World、carla.Vehicle、传感器接口几乎是同一套。于是可以在客户端写一份评测逻辑,只换连接的服务端,就构成”只换渲染引擎”的对照实验——评分器、路线解析、罚分注入两侧共用同一份代码,天然排除了评测实现差异这个混杂变量。
闭环评测必须开同步模式(synchronous mode):客户端调一次 world.tick(),服务端才推进一个固定步长 (本项目对应仿真帧率),渲染与物理等客户端确认。异步模式下服务端自由跑,慢模型(VLM 逐帧推理 0.7–1s/帧)会漏帧,控制时序错乱。同步模式是”模型慢但评测公平”的前提,代价是墙钟时间被模型推理速度拖长。
# 客户端最小骨架(两侧版本通用)
client = carla.Client(host_ip, rpc_port) # host_ip 为宿主 IP,不能写死 localhost
world = client.get_world()
settings = world.get_settings()
settings.synchronous_mode = True # 客户端掌控时钟
settings.fixed_delta_seconds = 0.05 # 每 tick 20 FPS 仿真时间
world.apply_settings(settings)
0.10 至今仍是技术预览:仅 Town10 重制版一张城镇地图、天气锁死白天、ScenarioRunner/Leaderboard 官方评测链不兼容。这意味着 UE5 侧的闭环基建(路线执行器 + 评分)必须自建——本项目的 UE5 侧评测链即参照 Bench2Drive 思路自行实现,PyPI 包名也不同(carla vs carla-ue5-api,二者不能装在同一环境)。
全局光照(Global Illumination,GI)指光线在表面间多次弹射后的间接照明——墙面被阳光照亮后再把暖色反弹到路面,阴影边缘因环境光而柔和。
对本研究的影响:软阴影的方向和长度、路面高光、玻璃反光全部改变,直接重写了画面的低层统计分布——这正是卷积/视觉编码器最敏感的特征层。
纳尼特(Nanite)把网格按簇(cluster)流式加载,运行时按屏幕占比选择细节层级,微多边形直接光栅化。效果是建筑立面、植被的几何细节量级提升,且不再有手工 LOD(细节层级)切换的突变。UE5 侧 Town10 的墙面涂鸦、树冠密度远高于 UE4 侧同名地图,很大程度来自这项升级(外加地图整体重制)。
车辆动力学与碰撞从 PhysX 换成 Chaos。这意味着即使画面完全一样,车的物理行为也不同——悬架、轮胎摩擦、碰撞响应都换了实现。对照实验里无法把物理单独隔离,这是”复合差异”的核心成分之一。
渲染升级不是免费的。本项目在同一台 RTX 5090 上实测(Epic 画质、720p、Town10 系地图、同步模式):
| 服务端 | 同步 FPS | 相对实时 | server 显存增量 |
|---|---|---|---|
| CARLA 0.9.15(UE4) | 97.6 | 4.9× | +8.1 GB |
| CARLA 0.10(UE5) | 42.3 | 2.1× | ~9 GB |
UE5 比 UE4 慢约 2.3 倍。这组数字同时是实验设计约束:同步模式下仿真时钟被 GPU 帧率封顶,VLM 逐帧推理再叠加,直接决定了采数和评测的墙钟预算。
UE4→UE5 不是”只换渲染”:渲染(Lumen/Nanite)、物理(PhysX→Chaos)、地图资产(Town10 重制)三者绑定更换。因此任何 UE4/UE5 的分数差异都不能干净地归因给”渲染保真度”单一变量——后续所有结论都带这个限定词。
同一模型、同一路线集、同一评分实现,在三个条件下各跑一遍:
| 档 | 条件 | 回答的问题 |
|---|---|---|
| 1 | UE4 基线(baseline) | 模型在原生训练域的水平,作参照原点 |
| 2 | UE5 zero-shot | 权重一行不改直接换引擎,域差距的裸效应 |
| 3 | UE5 微调(fine-tune) | 若掉分,自采数据能回收多少 |
三档构成完整的故事链:基线定原点,zero-shot 测域差距的方向与幅度,微调测可修复性。若第 2 档就不掉分,第 3 档退化为”锦上添花”验证——实际结果正是如此(AutoMoT 满分后已无回收空间,SimLingo 微调三版失败另成一课)。
“只保留渲染和物理差异”在工程上意味着一长串显式对齐:
剩下无法对齐的才构成处理变量:渲染管线(Lumen/Nanite)、物理引擎(PhysX/Chaos)、地图资产(Town10 重制)。
每个模型在每档下得到 条路线的分数(路线从 20 条砍到 10 条,路线级样本 60→30,MDE 约恶化 倍)。因为同一批路线在三档下重复测量,这是配对设计(paired design):比较的是逐路线的分数差 ,而非两批独立样本的均值差。配对消除了路线难度这个混杂变量,代价是样本量小——任何结论的显著性都受限于 ,必须显式报告 MDE(最小可检测效应),不能只看均值涨跌。
┌─ Windows 11 宿主 ────────────────────────┐
│ CARLA 0.9.15 server (UE4) ─┐ │
│ CARLA 0.10 server (UE5) ├─ RTX 5090 │
│ (渲染/物理,吃 GPU 显存) ─┘ │
└──────────┬───────────────────────────────┘
│ TCP(动态发现的宿主 IP)
┌──────────┴───────────────────────────────┐
│ WSL2 Ubuntu 22.04(所有 Python) │
│ conda: mysim-ue5 / mysim-simlingo / │
│ mysim-automot │
└───────────────────────────────────────────┘
为什么这样拆:CARLA 渲染依赖的图形栈在 WSL2 里不可靠(Vulkan 支持残缺),而训练栈(flash-attn/triton)在原生 Windows 上受限。混合形态让两边都走最稳的路:server 在 Windows 原生跑,Python 全在 WSL2。carla 与 carla-ue5-api 两个客户端包二进制不兼容,所以必须分属不同 conda 环境,永不混装。
Windows 的 NAT/容器网络栈(winNAT)会成段保留 TCP 端口,落在保留段内的端口任何进程都无法 bind。本项目三次被吞端口:最初约定的 2000–2002 被保留段 1921–2020 整个吞掉,CARLA server bind 抛出 WSAEACCES,异常未被捕获直接崩溃(错误码 0xe06d7363)。
诊断与规避:
# 查看当前被 winNAT 保留的端口段(大重启后必须复查,段会漂移)
netsh int ipv4 show excludedportrange tcp
实测该保留段动态漂移——重启后旧段消失、新段出现(如 1921–2020 变为 2756–3355、1937–2036),把刚迁好的端口又吞掉一次,最终端口迁到 2137–2222 的间隙才稳定。注意 crash XML 里的 AdapterName 字段会把 bind 失败误导成显卡问题,启动失败先查 netsh 再查 adapter。
WSL2 使用 NAT 网络,WSL 内的 localhost 指向 WSL 虚拟机自己,不是 Windows 宿主。连接宿主的 CARLA server 必须动态取默认网关:
# WSL2 内取 Windows 宿主 IP(禁止硬编码,重启后可能变)
ip route show | awk '/default/{print $3}'
渲染留在 Windows、控制放 Linux 的拓扑,使这一个坑贯穿了所有评测/采数脚本——任何硬编码 localhost 的连接都是定时炸弹。
SimLingo(CVPR 2025 Highlight,CARLA Challenge 2024 冠军)是把**视觉-语言模型(Vision-Language Model,VLM)**直接当司机用的代表:骨架为 InternVL2-1B(十亿参数量级的视觉-语言模型),只接一个前视相机,没有 LiDAR、没有环视、没有高精地图——画面是它的全部感知来源。
工作方式是逐帧看图生成:每来一帧画面,VLM 把图像 token 与导航指令(target point 等)拼进上下文,自回归地生成驾驶决策对应的输出,再解码为轨迹点与控制量。语言-动作对齐(language-action alignment)是它的核心设计——驾驶动作被表示为模型词表里的 token,复用了大模型的序列建模能力。
VLM 自回归生成使闭环推理只有 0.04–0.065 倍实时(每帧约 0.7–1 秒)。这直接压缩了实验规模:评测路线从 20 条砍到 10 条,墙钟预算成为硬约束。慢还带来一个工程要求——必须用同步模式仿真,否则模型推理期间世界已跑远,控制时序全乱。
官方成绩口径:论文 Table 2,Bench2Drive DS 85.07±0.95(3 seeds)——注意 README/榜单转述的 85.9 与论文口径略有出入,本项目引用一律以论文为准。
AutoMoT(ICML 2026)以 Qwen3-VL 为底座,采用**异步专家混合(asynchronous Mixture-of-Transformers,MoT)**结构,总参数约 5.6B,拆成两个专家:
“异步”指两个专家按不同频率运行:动作专家高频出控制保证实时性,理解专家低频更新高层表征——缓解了大模型逐帧推理慢与驾驶控制需要高频率之间的矛盾(对照 SimLingo 只能逐帧满速生成)。
AutoMoT 代表强模型的能力上限视角:官方 Bench2Drive 成绩 DS 87.34 / SR 70.00(README 口径;HF 模型卡为 89.42/74.09)。本项目只给它做两档——UE4 基线 + UE5 zero-shot,不做微调:官方训练配置需要单卡 80GB 显存,RTX 5090 的 32GB 跑不动。
AutoMoT 的动作分支吃 LiDAR BEV 特征,不是纯视觉。渲染引擎更换只影响相机这一路输入,点云分支几乎不受像素风格影响——渲染变量被几何传感器稀释。因此”AutoMoT 在 UE5 上表现如何”不能干净地回答”渲染保真度对模型的影响”,任何从它身上得出的渲染结论都必须打折听,严格结论只适用于其视觉通路。
AutoMoT 的发布权重(2026-05-17)与当代代码跨代际改名:ckpt 里 BEV 投影层叫 transfuser_proj.*,代码里叫 bev_encoder_proj.*(shape 完全一致)。流式加载器按名匹配,该层匹配不上就静默随机初始化,64 个 BEV token 全是垃圾——症状是车满油门顶死障碍物(18 路线平均 DS 27.5 vs 官方 87.34),而加载器只打印 missing/unexpected 不报错。修复是加前缀重映射表;教训是ckpt 装载后必须把 missing/unexpected 当硬错误查。
驾驶分数(Driving Score,DS)是 CARLA Leaderboard/Bench2Drive 系的标准指标:路线完成度乘以一串惩罚项的连乘积。
标准惩罚系数(leaderboard 口径):撞行人 (罚一半)、撞车辆 (罚四成)、闯红灯 (罚三成)、违章(如违停标志)(罚两成)。例:开完全程(RC=100)但撞了一次车闯了一次红灯,DS 。
乘法结构的设计意图:违章越多惩罚越狠且不可”抵销”——每类违章独立打折,两次撞车就是 ,接近归零。路线超时(timeout)直接判失败。
DS 只有在两侧实现完全一致时才能横向比。本项目 UE4/UE5 两侧的罚分注入(infraction 检测与系数施加)使用同一套实现,杜绝了”UE5 侧检测器更松所以分高”这类假效应。另有一个容易被忽略的口径问题:同模型重跑本身有噪声(SimLingo 侧高达 12.91 分,来自个别路线”卡死↔完成”的二元翻转),所以任何 DS 差异都必须和重跑噪声、MDE 放在一起读——单看均值涨跌没有意义。
KID(Kernel Inception Distance,核初始距离)衡量两组图像在特征空间里的分布距离。流程:
核函数取三次多项式核 , 是特征维度。三项分别是分布内相似度、跨分布相似度、分布内相似度——若两分布相同,跨项等于内项,MMD² 趋近 0。
更常见的 FID(Fréchet Inception Distance)假设特征服从高斯分布,只比较均值与协方差,且是有偏估计——样本少时系统性偏大。KID 用 MMD 的无偏估计,无高斯假设,小样本下数值稳定,适合做”同引擎重跑”这种应严格为零的对照组。
| 对照 | KID | 含义 |
|---|---|---|
| UE4 vs UE5(跨引擎) | 0.0743,95% 置信区间 [0.0712, 0.0775] | 域差距存在且置信区间很窄 |
| UE5 重跑 vs UE5 重跑(域内对照) | 0.0001 | 尺子本身的底噪,接近零 |
两组相差约 700 倍——渲染域差距不是肉眼错觉,是可测量的分布事实。按场景分组更有信息量:直行 0.094 < 左转 0.122 < 右转 0.196。转弯时视野里建筑立面与路口结构占比更大,恰是新旧渲染差异最富集的区域——场景结构决定域差距大小。
KID 在本研究里的三个用途:证明域差距存在(存在性判据)、按场景分组定位差距来源、以及尝试与分数变化做相关分析(后者未获显著结果,因为根本没有掉分可归因)。