2. SOTIF基础

做SOTIF场景库,最头疼的问题是什么?我个人的经验是——场景太多、太杂,不知道怎么管。

你想想看,一个十字路口,晴天是一种场景,雨天是另一种,晚上再来个远光灯对向车,组合就爆炸了。如果每个场景都当独立个体去采集、标注、存储,那场景库很快就会变成一团乱麻。

所以,我们需要一套分类体系。把场景按抽象程度分层,每一层干每一层的事。这样,场景才能复用,迭代才有抓手。

四层场景模型:从抽象到具体

业内公认的分层方式,是PEGASUS项目提出的四层模型。我直接说人话:

  • 功能场景——用自然语言描述的场景。比如“车辆在城市道路直行,前方有静止障碍物”。
  • 抽象场景——把功能场景里的要素提取出来,变成带标签的参数列表。比如“道路类型=城市道路,主车动作=直行,目标物=静止车辆”。
  • 逻辑场景——给参数加上取值范围和分布。比如“主车速度∈[0, 60] km/h,目标物距离∈[10, 100] m”。
  • 具体场景——从逻辑场景里采样出一组具体的参数值。比如“主车速度=40 km/h,目标物距离=30 m”。

说白了,就是从“讲个故事”到“定个参数”再到“跑个用例”的逐步细化过程。

核心观点:场景库的复用能力,取决于你在哪一层做抽象。抽象得越好,复用的面就越宽。

四层场景模型层级关系与转换路径 功能场景 自然语言描述 · 故事板 · 用例 要素提取 抽象场景 参数化标签 · 要素列表 · 本体 参数化 + 取值范围 逻辑场景 参数空间 · 分布定义 · 边界 采样 / 组合 具体场景 可执行测试用例 · 仿真/路测输入 抽象程度 从高到低 复用性 从高到低

功能场景:起点是“讲故事”

功能场景是场景库的入口。它不需要精确的参数,只需要把“发生了什么”说清楚。

举个例子:

场景:主车在城市双向两车道直行,前方约50米处有一辆静止的故障车辆,
      占用部分车道。对向有来车。天气晴朗,白天。

这个描述,工程师看得懂,测试经理看得懂,甚至产品经理也能参与讨论。这就是功能场景的价值——它是跨团队沟通的通用语言。

我的习惯:功能场景用模板写。固定结构是“道路环境 + 主车状态 + 目标物状态 + 环境条件”。这样写出来的场景,转成抽象场景时不会漏要素。

抽象场景:把故事变成标签

功能场景写好了,下一步就是把它结构化。抽象场景的核心工作,是“要素提取”。

还是上面那个例子,提取出来就是:

要素类别 标签
道路类型 城市双向两车道
主车动作 直行
目标物类型 静止车辆
目标物位置 前方,部分占用本车道
对向交通 有来车
天气 晴天
光照 白天

抽象场景的好处是什么?它让场景变得可检索、可分类、可组合。你可以在场景库里搜“目标物类型=静止车辆”,一下子拉出所有相关场景。

我曾经踩过的坑:一开始做抽象场景时,我把标签定义得太细。比如“目标物位置”分了“正前方10米、正前方20米、正前方30米……”结果标签数量爆炸,根本管不过来。后来我改成“前方近距离、前方中距离、前方远距离”这种区间标签,复用性一下子提高了。

逻辑场景:给参数加上边界

抽象场景只有标签,没有数值。逻辑场景要干的事,就是给每个参数定义取值范围和分布。

比如:

  • 主车速度:[0, 60] km/h,均匀分布
  • 目标物距离:[10, 80] m,重点在 [10, 30] m 区间加密采样
  • 对向车速度:[30, 60] km/h
  • 车道宽度:[3.0, 3.75] m

逻辑场景是测试设计的核心。它定义了“我们要测哪些情况”,而不是“具体测哪一组值”。

我个人习惯把逻辑场景分成两类:

  1. 边界逻辑场景——参数取极端值,比如速度上限、距离下限。用来找系统在边界处的行为。
  2. 覆盖逻辑场景——参数在范围内均匀或按分布采样。用来评估系统在典型工况下的表现。

具体场景:跑起来的那一下

具体场景就是从逻辑场景的参数空间里,取出一组具体的值。它可以直接喂给仿真器,或者写成路测脚本。

举个例子:

具体场景实例:
- 主车速度: 45 km/h
- 目标物距离: 28 m
- 对向车速度: 50 km/h
- 车道宽度: 3.5 m
- 天气: 晴天
- 光照: 白天

一个逻辑场景,可以生成成千上万个具体场景。这就是“场景复用”的真正含义——你不需要为每个测试用例单独写场景描述,只需要在逻辑层定义好参数空间,然后批量采样。

关键认知:场景库的迭代,主要在逻辑场景层进行。功能场景和抽象场景相对稳定,具体场景是消耗品——跑完就扔,但逻辑场景要持续维护和优化。

层级间的转换方法

四层模型不是摆设,它们之间的转换有固定的方法。我总结了三步走:

转换步骤 输入 输出 关键动作
功能 → 抽象 自然语言场景描述 结构化标签列表 要素提取、本体映射
抽象 → 逻辑 标签列表 参数空间定义 参数化、取值范围设定、分布定义
逻辑 → 具体 参数空间 具体参数值组合 采样策略(随机/边界/正交/组合)

这里有个细节要注意:从抽象到逻辑的转换,是最容易出问题的环节。为什么?因为取值范围定得太宽,测试成本高;定得太窄,又可能漏掉危险场景。

我的建议:取值范围先参考行业标准(比如ISO 21448里提到的典型工况),再结合你们自己采集的真实路测数据去校准。别拍脑袋定范围,我见过太多团队因为范围定得离谱,导致场景库里的用例要么跑不出问题,要么根本跑不通。

场景库的复用逻辑

讲完层级关系,我想聊聊复用。很多人以为场景复用就是“把同一个场景文件复制粘贴到不同项目里”。其实不是。

真正的复用,发生在抽象层和逻辑层:

  • 抽象场景复用:同一个“前方静止车辆”的抽象场景,可以复用到城市道路、高速公路、乡村道路等多个功能场景里。只需要改一下道路类型的标签值。
  • 逻辑场景复用:同一个逻辑场景,可以通过不同的采样策略,生成适用于仿真测试、HIL测试、路测的不同具体场景集。
  • 具体场景不直接复用:具体场景是绑定到特定测试环境的。换了传感器配置、换了算法版本,原来的具体场景可能就不适用了。但它的“父级”逻辑场景可以继续用。

嗯,这一点想明白了,场景库的架构就不会走偏。

避坑指南:不要试图把所有具体场景都存下来。我见过一个团队,跑了10万次仿真,存了10万个具体场景文件。结果想查一个特定工况时,根本找不到。正确的做法是:存逻辑场景 + 采样种子,具体场景随用随生成。

好了,场景分类体系这部分就讲到这里。四层模型是场景库的骨架,理解清楚每一层的定位和转换方法,后面的复用和迭代才有基础。下一层,我们会聊场景库的构建流程——怎么从零开始搭一个能用的场景库。