场景三部曲:ODD、OpenSCENARIO 2.0 与采样经济学

自动驾驶测试有一个让人绝望的起点:世界是无限的。天气 × 光照 × 道路 × 交通参与者 × ……任何有限的测试预算扔进这个组合空间,都听不见响。行业的应对不是硬扛,而是递进的三个动作:先用 ODD 把无限世界砍出边界,再用 OpenSCENARIO 2.0 给场景一门声明式的描述语言,最后用采样经济学决定有限的预算花在哪几个点上。这篇把三者串成一条线:边界 → 描述 → 选样。

一、ODD:给无限世界砍出边界

ODD(Operational Design Domain,运行设计域)= 系统被设计为能够正常运行的条件集合:道路类型、速度范围、天气、光照、地理区域、交通参与者类型……每个维度一条边界。概念出自 SAE J3016,是 L3 及以上自动驾驶的立身之本:系统只承诺在 ODD 内正常工作,出了 ODD 就要降级或请求接管(MRM,最小风险操作)。

一个具体例子:某高速 NOA 的 ODD = 结构化高速 + 0~130km/h + 小雨及以下 + 有光照(白天或有路灯的夜晚)。

没有 ODD,测试范围是无限的

ADAS 验证的根本难题是“里程灾难”:要在统计学上证明系统比人类司机更安全,需要几十亿公里的测试里程——真实世界场景的组合是无穷的,任何固定预算撒进去都约等于零。

ODD 是把无限问题砍成有界问题的第一刀:只承诺 ODD 内的安全,只验证 ODD 内的行为。测试范围从“整个世界”变成“一个有限维度的参数空间”——这才是可规划、可度量、可签字的东西。

ODD 与测试范围的四个映射关系

  1. ODD 内 = 正面清单。 ODD 的每个维度变成场景空间的坐标轴,场景三层级(功能场景 → 逻辑场景 → 具体场景)在这个有界空间里采样覆盖。覆盖率的含义因此改变:不是“世界覆盖了多少”,而是“ODD 覆盖了多少”——这是可计算的(格子填满率)。
  2. ODD 边界 = 测试权重最高的区域。 边界是最危险的地方:系统必须在边界上识别出“我快出 ODD 了”。所以边界要做双侧测试——内侧边缘(如 129km/h)必须正常工作;外侧边缘(如 131km/h)必须正确识别并降级、提醒接管。均匀采样是浪费,边界加密才是正道——和单元测试“边界值分析”是同一个直觉,只是维度更多。
  3. ODD 外 = 不是“不测”,是“测另一件事”。 ODD 外的行为不被要求“功能正确”,但被要求“安全地失效”。所以越界场景仍在测试范围内,测的是越界检测:系统知不知道自己在 ODD 外?知不知道得有多快?这是 SOTIF(ISO 21448,预期功能安全)的核心关切——ISO 26262 管“系统故障”,SOTIF 管“没故障但性能不足”(比如逆光下识别率掉到不可用),而 SOTIF 论证的地基就是 ODD + 场景覆盖。
  4. ODD 变更 = 测试范围的重估触发器。 产品迭代就是扩 ODD(先高速后城区、先晴天后小雨)。每次扩 ODD 都触发同一条链:新维度/新边界 → 场景空间扩容 → 用例缺口分析 → 测试范围变更,这条链要走 ALM 的影响分析流程——ODD 在需求层声明,用例层标注,中间靠追溯链连着。

落地:ODD 怎么进用例管理

工程上的最小实现,是在用例 manifest 里加一个 odd 字段,每条用例标注它覆盖的 ODD 坐标:

- id: TC-AEB-0042
  req: [REQ-AEBS-003]
  odd: {road: highway, speed: 50kph, weather: clear, light: day}

“ODD 覆盖率”由此成为一张可生成的报表:把所有已测用例的参数填进 ODD 格子,空格就是测试缺口——场景覆盖度量的最小实现。注意这张报表的真正用途不是“把格子填满”(参数一多,格子总数就是天文数字),而是把空格按风险排序——有限的预算先填哪几格,正是本文第三个话题的事。

二、OpenSCENARIO 2.0:给场景一门声明式语言

边界有了,场景怎么写?OSC2 = ASAM OpenSCENARIO 2.0,场景描述标准的 2.0 版,2022 年正式发布。出身值得一提:以色列公司 Foretellix(团队来自半导体验证行业)把自己的场景语言 M-SDL(Measurable Scenario Description Language)开源并捐给 ASAM 作为 2.0 的基础;标准发布后,Foretellix 停掉 M-SDL,全面并入 OSC2。

先澄清一个常见误会:1.x 和 2.0 不是升级替代关系,两者并行开发(计划未来合并)。1.x 是 XML、命令式、面向“具体场景”;2.0 是另起炉灶的声明式语言。

和 1.x 的本质区别

  OpenSCENARIO 1.x OpenSCENARIO 2.0
形式 XML 文本 DSL(python-like 语法)
范式 命令式:描述“怎么执行” 声明式:描述“应该发生什么”
覆盖层级 具体场景(参数值固定) 抽象 / 逻辑 / 具体三级通吃
参数空间 基本不支持 原生:范围 + 约束 + 覆盖目标
生态 装机量大(esmini、CARLA) 早期,Foretify 是首个原生平台

三级通吃那行值得展开:场景三层级(功能场景 → 逻辑场景 → 具体场景)在 OSC2 里被语言化了——一份文件可以从功能场景一路细化到具体场景,而 1.x 只接得住“具体场景”那一层。

三个关键字

OSC2 的关键设计就三个关键字,看官方概念文档里的 snowstorm 例子:

scenario env.snowstorm:
    storm_data: storm_data with:
        keep(it.storm == snow)               # 硬约束:必须是雪
        keep(soft it.wind_velocity >= 30kph) # 软约束:尽量满足
        cover(it.wind_velocity, unit: kph)   # 覆盖目标:这个维度要铺满

具体场景不再手写,而是约束求解器根据 cover 目标自动生成。

杀器特性:双重解释

同一份场景描述,既能驱动仿真(让场景发生),也能当监控器(判定场景是否真的发生了)。对测试的意义很直接:激励和判定用同一份声明,“写两遍、两边对不上”的错漏直接消失。

在 ASAM OpenX 家族里的位置

OSC2 对测试平台的意义和 XiL 的环境抽象同构:场景描述与仿真器解耦——今天接 CARLA,明天接 Prescan,场景文件不改。

三、采样经济学:全组合为什么不是答案

边界有了(ODD),语言有了(OSC2),还剩最后一问:逻辑场景展开成具体场景,点怎么选? 最容易想到的答案是全组合——每个参数的所有取值两两配对、全跑一遍。一句话评价:

全组合是“覆盖完美但预算无限”的理论解——而工程的真问题是“预算有限时按风险密度分配预算”,全组合恰好按“空间体积”分配预算,方向就错了。

先算爆炸的数学

以前车切入场景为例,一个逻辑场景的典型参数:本车速度、目标车速度、切入距离、切入时长、车道宽、曲率、天气、光照、路面附着、目标类型……8~15 个参数很正常。

每个维度只取 10 个值:10¹⁰ = 一百亿个具体场景。SIL 再快(每秒 100 个场景加速跑)也要 3 年多;放到 HIL/实车(一个场景几分钟起),物理上不可能。这就是维度灾难。

膨胀曲线可以亲手算出来:两个参数(本车速度 6 档 × 切入距离 9 档)= 54 个场景,SIL 分分钟跑完;再叠 3 个参数、各取 10 个值 = 54,000 个,约 9 分钟;再叠 2 个 = 540 万个,要跑 15 个小时;凑齐 10 个参数各 10 个值,就是上面那一百亿、3 年。拐点就在眼前,不在理论里。

更致命的是:跑完也没用

假设真有一百亿的机时,全组合依然是错的投资:

  1. 大部分组合无效:物理上不可能(130km/h + 大曲率 + 冰面附着同时出现)、语义矛盾(切入距离 50m 但切入时长 0.5s)、落在 ODD 之外(定义域外的点不该测功能正确性)。全组合不知道这些,照跑;
  2. 危险场景是稀疏的:参数空间里“会触发问题”的区域占比极小——往往贴着边界组合。全组合按空间体积均匀撒预算,99.99% 烧在“注定通过”的场景上,单位成本的信息收益趋近于零;
  3. 覆盖是假象:跑完一百亿个点能拿到一个“空间覆盖”的数字,但监管和审核要的是“风险论证”——全组合给了一个数字,没给一份论证。

行业的替代策略(按思路分四类)

  1. 理性化简:全组合的“聪明子集”。 边界值分析 + 等价类:每个参数不取 10 个值,取“边界 ± 一个代表值”;pairwise 组合测试:不要求全组合,只要求任意 2 个参数的取值组合都出现一次——NIST 的研究(Kuhn 等)表明,绝大多数故障由 1~2 个参数的交互触发,于是覆盖规模从指数掉到对数级,拿到的交互覆盖却没差多少。
  2. 风险加权采样:不按体积按密度。 按真实世界分布采(自然驾驶数据 NDD):常见场景多采;按风险加权:罕见但致命的(鬼探头、前车急刹)反而加密。法规测试矩阵就是现成的例子——Euro NCAP 的 CCRs 速度点(按风险选定若干速度档),本质是权威机构替你做了风险加权选择,直接借用等于白嫖了它的采样策略。
  3. 引导式搜索:让仿真结果反过来指挥采样。 falsification:把“找危险场景”当优化问题(遗传算法、贝叶斯优化),目标函数是“离出事还有多远”,专往快失败的方向钻;覆盖引导(fuzzing 思路):监控被测系统的内部状态覆盖,引导参数往没走过的状态空间钻。
  4. 真实数据回灌。 从自然驾驶数据、事故库、影子模式里挖“真实发生过的组合”——概率上不占优,相关性上无敌。

全组合什么时候合法

全组合不是永远错:参数少(2~3 个)、取值离散且少、执行便宜(SIL)时,它就是正确策略——比如配置开关矩阵、模式组合。判断标准一句话:算得出总数、跑得完总数、每个组合都有意义——三条缺一条,就该换策略。

四、三部曲合奏:边界 → 描述 → 选样

三者各管一段,合起来是一条流水线:

真实世界(场景组合无穷)
      │  ODD:只承诺域内安全,边界双侧加密
      ▼
有界参数空间(格子化的 ODD 坐标)
      │  OSC2:keep 圈出合法空间,cover 声明铺满目标
      ▼
逻辑场景(参数范围 + 约束,抽象/逻辑/具体三级通吃)
      │  采样:求解器按 cover 目标与风险密度选点,全组合从不出现
      ▼
跑得完、能签字的具体场景集

几处相互咬合的接口值得单独点名:


回看整条链:ODD 回答“在哪测”——把无限世界砍成有限格子;OSC2 回答“怎么写”——用 keep/cover 声明“应该发生什么”,而不是“怎么执行”;采样回答“怎么选”——预算有限,按风险密度而不是空间体积分钱。 三刀的顺序不能反:没有边界,描述没有定义域;没有描述,采样没有操作对象;没有采样,前两者只是纸面上的好主意。边界、描述、选样——场景测试方法论的主线,就这三步。


附:名词解释(按出场顺序)

名词 通俗解释
ODD(运行设计域) Operational Design Domain:系统承诺能正常工作的条件集合(道路、速度、天气、光照……),每个维度一条边界
SAE J3016 自动驾驶分级标准(L0~L5),ODD 概念的出处
MRM(最小风险操作) Minimal Risk Maneuver:系统出 ODD 或失效时的兜底动作——降级、靠边停车、提醒接管
NOA 领航辅助驾驶:按导航路线自动完成变道、上下匝道等功能的高阶辅助驾驶
里程灾难 要统计证明自动驾驶比人安全需要几十亿公里测试里程、现实中跑不完的两难
场景三层级 功能场景(自然语言)→ 逻辑场景(参数范围)→ 具体场景(参数定值)的场景分层方法
边界值分析 / 等价类 经典测试设计法:参数只取边界附近和几个代表值,不铺满整个取值域
SOTIF / ISO 21448 预期功能安全标准:管“系统没故障但性能不足”导致的风险
ISO 26262 汽车功能安全标准:管“系统故障”导致的风险
ALM 应用生命周期管理工具链:需求—用例—结果的追溯归它管
manifest(用例清单) 与代码分离的用例元数据文件,用例的标签、ODD 坐标都写在里面
ASAM 汽车自动化与测量系统标准化协会,OpenX 仿真标准家族归它维护
OpenSCENARIO 2.0 / OSC2 ASAM 的场景描述标准 2.0 版:声明式 DSL,2022 年发布;1.x(XML)与其并行存在
M-SDL Foretellix 的可度量场景描述语言,开源后捐给 ASAM,成为 OSC2 的基础
Foretellix 以色列场景验证公司,团队出身半导体验证行业
DSL(领域特定语言) 为单一领域定制的小型语言,相对通用编程语言而言
命令式 / 声明式 命令式描述“怎么一步步执行”,声明式只声明“应该发生什么”,执行交给工具
esmini / CARLA 支持 OpenSCENARIO 的开源场景播放器 / 自动驾驶仿真器
Foretify Foretellix 的验证平台,首个原生支持 OSC2 的商业工具
keep / keep(soft) / cover OSC2 的三个关键字:硬约束、软约束、覆盖目标
约束求解器 在约束圈出的合法空间里自动挑参数取值的引擎;具体场景由它生成
双重解释 同一份场景描述既能驱动仿真、也能当监控器判定场景是否发生
OpenDRIVE / OpenCRG / OSI ASAM OpenX 家族成员:静态路网 / 路面细节 / 传感器接口
Prescan 西门子旗下的自动驾驶仿真器
SIL / HIL 软件在环 / 硬件在环:前者纯软件跑、便宜快,后者接真实 ECU 与台架、贵慢
维度灾难 参数维度稍多,全组合数量就爆炸到物理上跑不完的现象
pairwise(成对组合测试) 只保证任意 2 个参数的取值组合各出现一次的采样法,规模从指数降到对数级
NIST 美国国家标准与技术研究院;Kuhn 等人的组合测试研究是 pairwise 的理论依据
NDD(自然驾驶数据) 量产车队在日常驾驶中采集的真实路况数据
鬼探头 行人或非机动车从遮挡后突然窜出的高危场景
Euro NCAP / CCRs 欧洲新车安全评价体系;CCRs 是其前车静止直行追尾测试场景,速度点按风险选定
falsification(证伪式搜索) 把“找危险场景”形式化为优化问题:目标函数是“离失败还有多远”,专往快出事的方向搜
贝叶斯优化 用代理模型指导搜索方向的全局优化方法,适合仿真这种昂贵目标函数
覆盖引导 / fuzzing 借自软件模糊测试:监控被测系统内部状态覆盖,引导输入往新状态空间钻
影子模式 新功能在量产车上静默运行、只记录不控车,用于挖真实发生过的场景

下一步:

查看全部文章