3. 场景分类体系:功能场景、逻辑场景、具体场景的层级关系与转化
场景分类这件事,说白了就是给自动驾驶的测试对象「建个档」。你想想看,路上跑的工况千千万,如果不分个层级,测试根本没法落地。我个人习惯把场景分成三层:功能场景、逻辑场景、具体场景。这三层不是并列关系,而是从抽象到具体的逐级细化。
3.1 三层场景的定义与定位
先给个直观的定义。我做过好几个项目的经验告诉我,这三层对应的是「需求→参数→实例」的转化过程。
| 层级 | 核心特征 | 表达方式 | 典型用途 |
|---|---|---|---|
| 功能场景 | 语义级描述,不含具体数值 | 自然语言 + 场景图 | 需求分析、功能定义 |
| 逻辑场景 | 参数空间 + 取值范围 | 参数表 + 约束条件 | 测试用例生成、参数探索 |
| 具体场景 | 参数取具体值,可仿真执行 | OSI/OpenSCENARIO | 仿真测试、实车验证 |
关键认知:功能场景是「做什么」,逻辑场景是「在什么范围内做」,具体场景是「怎么做」。三者缺一不可。
3.2 功能场景:从需求出发的语义层
功能场景是最上层的抽象。它用自然语言描述一个交通场景的「本质」。比如:「自车在高速公路上行驶,前方有一辆慢车切入本车道,自车需要减速避让。」
这里没有具体速度、没有距离、没有切入角度。为什么?因为功能场景是用来对齐需求的。我记得有一次,功能安全团队和系统团队因为「切入场景」的定义吵了一周——一个说「切入就是变道」,另一个说「切入必须压线」。后来我们统一用功能场景的语义模板才解决。
功能场景的构成要素,我一般用「5W1H」来拆解:
- Who:自车、目标车、行人、障碍物
- Where:道路类型、车道位置、路口结构
- When:白天/夜晚、天气、光照条件
- What:主行为(跟车、换道、制动)
- Why:触发原因(前车减速、行人横穿)
- How:交互方式(博弈、礼让、强制)
我的习惯:功能场景一定要写「场景标题」+「一句话描述」+「场景图草图」。别偷懒,这一步省了,后面逻辑场景的参数范围会漏掉。
3.3 逻辑场景:参数空间的量化
逻辑场景是功能场景的「参数化版本」。它把语义描述中的每个要素,都变成一个参数变量,并给出取值范围。
举个例子,刚才的「慢车切入」功能场景,到了逻辑场景层就变成:
场景:高速慢车切入
参数:
- 自车速度:80 ~ 120 km/h
- 目标车速度:60 ~ 90 km/h
- 切入角度:5° ~ 30°
- 切入距离(纵向):20 ~ 80 m
- 路面摩擦系数:0.4 ~ 0.9
- 光照强度:0 ~ 100000 lux
这里要注意,逻辑场景的参数范围不是随便写的。我曾经在一个项目中,把切入角度设到了45°,结果仿真里目标车直接横着飘过来——物理上根本不可能。后来我们加了「车辆动力学约束」作为参数范围的边界条件。
逻辑场景的价值在于:它定义了「测试空间」。你想想看,如果每个参数取10个值,6个参数就是10^6 = 100万个组合。逻辑场景帮你划出「有意义」的边界。
避坑指南:逻辑场景的参数范围一定要考虑「物理可行性」和「功能触发条件」。我曾经见过一个团队把自车速度范围设到0~200 km/h,结果生成了大量无效场景——自车静止时根本不会触发切入场景。参数范围要基于ODD(运行设计域)来裁剪。
3.4 具体场景:可执行的测试实例
具体场景是逻辑场景中每个参数取一个具体值后的结果。它是「可执行的」——可以直接丢给仿真软件或实车运行。
比如从上面的逻辑场景中,我们可以生成这样一个具体场景:
具体场景实例 #001:
- 自车速度:100 km/h
- 目标车速度:70 km/h
- 切入角度:15°
- 切入距离:50 m
- 路面摩擦系数:0.8
- 光照强度:50000 lux(白天)
- 天气:晴朗
具体场景的生成方式有两种:
- 组合覆盖法:用正交表或组合测试工具,从逻辑场景的参数空间中采样
- 边界值法:取每个参数的边界值(最小值、最大值、临界值)
- 随机采样法:在参数空间内随机撒点,适合大规模测试
- 场景变异法:基于已知危险场景,微调参数生成变体
我个人更推荐「组合覆盖 + 边界值」的混合策略。为什么?因为纯随机采样容易漏掉边界上的危险点,而纯组合覆盖又可能生成太多冗余场景。
3.5 三层转化:从抽象到具体的映射
这三层不是孤立的,它们之间有明确的转化关系。我画了一张图来说明这个转化过程:
转化过程中有一个容易踩的坑:语义一致性。什么意思?就是具体场景不能违背功能场景的原始意图。比如功能场景是「慢车切入」,结果你生成的具体场景里目标车速度比自车还快——这就不是「慢车」了,变成了「快车超车」。语义变了,测试结论就废了。
3.6 层级间的验证闭环
这三层之间还有一个验证闭环,我习惯叫它「V&V 三角」:
- 正向验证:功能场景 → 逻辑场景 → 具体场景,确保参数化正确
- 反向追溯:具体场景 → 逻辑场景 → 功能场景,确保每个测试实例都能追溯到原始需求
- 覆盖度检查:逻辑场景的参数空间是否覆盖了功能场景的所有语义分支
实战经验:我在做某个L3级高速公路领航项目时,发现功能场景写了「雨天」,但逻辑场景里只设了「降雨强度」一个参数,漏掉了「路面水膜厚度」和「雨刮器状态」。结果仿真测试全过了,实车一跑就出问题——雨刮器没开,摄像头被雨水遮挡。这就是层级转化时「语义丢失」的典型例子。
3.7 工具链与数据格式
实际工程中,这三层场景需要对应不同的数据格式和工具:
| 层级 | 推荐格式 | 常用工具 | 存储方式 |
|---|---|---|---|
| 功能场景 | PEGASUS 6层模型 / 场景模板 | Excel / Confluence / Doors | 文档 + 图片 |
| 逻辑场景 | 参数表(CSV/YAML) | Python / MATLAB / 自研工具 | 数据库 / 配置文件 |
| 具体场景 | OpenSCENARIO / OSI | VTD / CarMaker / dSPACE | XML / 二进制文件 |
我个人建议,团队里一定要有一个「场景管理平台」。别用Excel管几千个场景——我见过有人把场景参数写在Excel里,结果版本一乱,测试结果全对不上。用数据库或者专门的场景管理工具,能省很多麻烦。
小技巧:逻辑场景的参数表里,建议加一列「参数来源」。标注这个参数是来自ODD、功能需求、还是经验值。这样后期排查问题时,能快速定位是哪个环节的参数设错了。
3.8 本章小结
功能场景、逻辑场景、具体场景,这三层构成了SOTIF场景分析的骨架。功能场景管「对不对」,逻辑场景管「全不全」,具体场景管「能不能跑」。三层之间的转化,核心是「参数化」和「实例化」,但别忘了保持语义一致性。
嗯,这里再强调一句:别把这三层当成瀑布流——做完功能场景再做逻辑场景。实际项目中,这三层是迭代的。你从具体场景里发现了一个危险点,可能要回溯到逻辑场景去扩参数范围,甚至修改功能场景的定义。闭环思维,比线性思维更重要。