3. 场景与场景库概念
在CARLA大规模场景批量验证工程中,“场景”不是随手写的一段仿真脚本,而是可被描述、可被复用、可被批量执行、可被结果追溯的最小验证单元。理解场景的定义方式、标准格式、执行引擎以及场景库的组织逻辑,是后续搭建批量验证流水线的前提。本章围绕场景定义、OpenSCENARIO、CARLA ScenarioRunner、场景分类、参数化场景与场景库组织方式展开。
一、什么是场景:从“一次仿真”到“可复用验证单元”
场景(Scenario)是对一段交通情境的完整描述,通常包含道路环境、静态要素、动态参与者、初始状态、触发条件、行为序列以及成功/失败判据。它回答的是“在什么环境下,谁在什么时刻做了什么,系统应如何响应,结果如何判定”。
一个可工程化的场景至少应具备四个属性:
- 可描述性:用结构化语言或参数表达,而非仅存在于工程师脑中。
- 可复现性:给定相同随机种子与版本,能稳定重放。
- 可参数化:关键变量(车速、距离、触发时刻)可外部注入。
- 可判定性:有明确的通过/失败/无效判据。
在CARLA中,场景可以由Python API直接编写,也可以由OpenSCENARIO描述后交由ScenarioRunner执行。前者灵活但难复用,后者标准化但需要转换与适配。
二、OpenSCENARIO:场景的标准化描述语言
OpenSCENARIO是ASAM制定的场景描述标准,采用XML结构,核心由Storyboard、Init、Story、Act、Maneuver、Event、Action等层级组成。它把“谁在何时做什么”拆解为可组合的语义单元。
<ScenarioDefinition>
<ParameterDeclarations>
<ParameterDeclaration name="EgoSpeed" value="8.0"/>
<ParameterDeclaration name="Gap" value="15.0"/>
</ParameterDeclarations>
<Storyboard>
<Init>...</Init>
<Story name="CutIn">
<Act>
<ManeuverGroup>
<Actors><EntityRef entityRef="NPC"/></Actors>
<Maneuver>
<Event name="StartCutIn">
<Action><LaneChange .../></Action>
</Event>
</Maneuver>
</ManeuverGroup>
</Act>
</Story>
</Storyboard>
</ScenarioDefinition>
OpenSCENARIO的优势在于跨仿真器可移植、便于版本管理与参数注入;局限在于CARLA对部分动作的支持需要ScenarioRunner做映射,复杂交互仍需自定义扩展。
三、CARLA ScenarioRunner:场景执行引擎
ScenarioRunner是CARLA官方提供的场景执行框架,负责解析OpenSCENARIO或Python场景定义,在仿真世界中生成参与者、绑定触发条件、执行动作并收集判据。其典型运行命令如下:
python scenario_runner.py \
--scenario MyCutInScenario \
--openscenario scenarios/cutin.xosc \
--route routes/route_01.xml \
--agent roach \
--output results/run_001
ScenarioRunner的核心职责包括:场景加载、Actor生成与销毁、触发条件评估、行为执行、判据计算、结果输出。批量验证时,通常由外部调度器循环调用ScenarioRunner,或使用其Python API在单进程内批量执行,以减少启动开销。
四、场景分类与参数化场景
场景可按功能、交互形态、危险程度、来源等维度分类。工程中常用分类如下:
| 分类维度 | 典型类别 | 示例 |
|---|---|---|
| 功能场景 | 跟车、换道、交叉口、行人横穿 | 前车急刹、旁车切入 |
| 逻辑场景 | 参数区间描述 | 切入车速 5~15 m/s,间距 10~30 m |
| 具体场景 | 固定参数实例 | 切入车速 8 m/s,间距 15 m |
| 危险程度 | 常规、边界、极端 | 正常跟车、临界制动、鬼探头 |
| 来源 | 法规、事故、专家、随机 | ECE R152、CIDAS事故库 |
参数化场景是把逻辑场景中的变量抽为参数,通过采样生成大量具体场景。例如切入场景可参数化为:ego_speed、npc_speed、gap、trigger_time、weather。批量验证的本质,就是在参数空间中进行有策略的采样与执行。
params:
ego_speed: [6, 8, 10]
npc_speed: [5, 8, 12]
gap: [10, 15, 25]
weather: [ClearNoon, HardRainNoon]
# 组合后共 3×3×3×2 = 54 个具体场景
五、场景库组织方式
场景库不是场景文件的简单堆叠,而应有清晰的目录结构、元数据与索引。推荐组织方式如下:
- 按功能域分目录:
cut_in/、follow/、intersection/、pedestrian/。 - 场景文件与参数分离:
.xosc或.py描述结构,.yaml描述参数集。 - 元数据索引:记录场景ID、版本、地图、标签、判据、责任人。
- 结果归档:按
run_id保存日志、判据、轨迹与失败截图。
scenario_library/
├── cut_in/
│ ├── cutin_base.xosc
│ ├── cutin_params.yaml
│ └── meta.json
├── follow/
│ ├── follow_brake.xosc
│ └── follow_params.yaml
├── intersection/
└── index/
└── scenario_index.csv
在批量验证工程中,场景库还应支持按标签筛选、按参数采样、按优先级排序,并与CI/CD流水线对接,实现“提交代码→自动采样→批量执行→生成报告”的闭环。
六、常见误区与复盘
- 误区一:把场景等同于测试用例。场景描述情境,测试用例还需绑定判据、阈值与预期结果。
- 误区二:参数越多越好。参数爆炸会导致组合数失控,应优先筛选高敏感参数并采用正交或边界采样。
- 误区三:忽略版本与种子。CARLA、地图、ScenarioRunner任一变化都可能改变结果,必须记录完整环境指纹。
- 误区四:场景库无索引。没有元数据索引,场景无法被批量调度与结果追溯,规模一大就失控。
复盘建议:每次批量验证后,统计场景通过率、失败聚类与参数敏感度,将高价值失败场景反哺回场景库,形成持续演进的场景资产。
综上,场景是验证的基本单元,OpenSCENARIO提供标准描述,ScenarioRunner负责执行,分类与参数化决定覆盖策略,场景库组织决定工程可扩展性。只有把四者打通,才能支撑CARLA大规模场景批量验证的稳定运行。