关于 roadrunner-build-scenario-from-osc
解析 OpenSCENARIO 1.x 的 `.xosc` 文件,并生成用于在 RoadRunner 中重建情景的描述。保留源文件中的位置、相对引用和阶段逻辑,待用户确认后再交由相关技能构建。
主要功能
- 01解析并验证 `.xosc` 输入
- 02解析参数和目录引用
- 03依据关联的 `.xodr` 转换位置
- 04将动作映射为情景阶段
- 05标记不支持的结构供审阅
适用场景
- 01重建合作方提供的 `.xosc` 情景
- 02生成 RoadRunner 情景描述
- 03在 MATLAB 构建前审阅情景逻辑
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ matlab/ matlab-agentic-toolkit --skill roadrunner-build-scenario-from-osc安装后在 Claude Code 中输入/roadrunner-build-scenario-from-osc确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
manifest.yamlreferences/openscenario-mapping.mdscripts/xoscPositionToWorld.p详细介绍
根据 OpenSCENARIO 构建 RoadRunner 场景
解读 OpenSCENARIO 1.x(.xosc)文件,并使用 roadrunner-scenario-authoring 技能在
RoadRunner 中重建场景。转换位置,映射构造,保留相对引用,并构建正确的阶段逻辑。
适用场景
- 用户有一个 .xosc 文件,并希望在 RoadRunner 中重建场景
- 用户希望以编程方式根据 OpenSCENARIO 构建场景
- 用户说“在 RoadRunner 中构建此 .xosc”或“重建此场景”
- 用户有来自合作方或标准组织(例如 Euro NCAP、ALKS)的 OpenSCENARIO 文件
- 用户希望根据 .xosc 文件生成 MATLAB 脚本
- 用户说“将此 xosc 转换为 matlab”或“用 matlab 脚本重建”
不适用场景
- 用户说要“导入” .xosc 文件——他们需要的是
importScenario(rrApp, xoscPath),而不是此技能。直接调用 API 即可。 - 用户希望使用 RoadRunner 内置的
importScenario(让他们使用即可,它适用于简单情况) - 用户希望从头创建场景,且没有 .xosc 文件(使用
roadrunner-scenario-authoring) - 用户希望将场景导出为 OpenSCENARIO(使用
roadrunner-export-scenario)
关键规则
-
绝不臆造源 XOSC 中不存在的动作或条件。 如果某个构造无法映射,请跳过并警告用户。
-
绝不提出变通方案。 不要用 DurationCondition 替换 DistanceToPointCondition,不要用 SimulationTimeCondition 替代不受支持的触发器,也不要添加源文件中不存在的任何构造。
-
绝不简化或复制轨迹顶点。 精确提取源 XOSC 中的折线顶点,不多不少。不要将 90 个顶点缩减为 5 个。提取时不要复制起点或终点。
-
绝不猜测场景。 只报告
<LogicFile>中的 .xodr 文件名。 导入该文件,不要搜索名称相似的场景。 -
绝不将相对引用转换为绝对引用。 如果源文件使用
RelativeTargetSpeed delta=-8,请将其保留为SpeedReference="actor"、Direction="slower"、Speed=8。不要计算并硬编码7 m/s。 -
绝不默默省略不受支持的功能。 始终在场景描述的“Unsupported Constructs”部分明确标出。
-
描述意图,而不是 XOSC 结构。 将占位 Act(MW_WaitAction)合并为结束条件。不要为没有实际参与者动作的脚手架元素创建阶段。
工作流
此技能分两步执行。先完成步骤 1,将描述提交给用户审核,然后仅在获得批准后继续步骤 2。
步骤 1:分析 .xosc 并生成场景描述
按照以下严格逻辑顺序解析 .xosc 及其引用的 .xodr。
1a. 验证输入
读取 .xosc XML。如果文件不是有效 XML、缺少必需元素或未通过基本结构检查,请停止并报告错误。不要猜测或假设缺失的数据。如果数据有歧义,请明确说明所采用的假设。
1b. 解析参数、表达式和目录
解读任何值之前,先解析所有引用:
- ParameterDeclarations / VariableDeclarations:将
${...}表达式求值为具体数值。按声明顺序处理(后续参数可能引用先前参数)。 - CatalogReferences:读取引用的目录 XML 文件(来自
<CatalogLocations>),通过catalogName+entryName查找条目,并提取车辆/行人定义(model3d 路径、类别、边界框)。
% Parameter expression resolution example
params.HostSpeed_kph = 80;
params.LeadTime_s = 6;
params.hostSpeed_ms = params.HostSpeed_kph / 3.6; % 22.2222
params.leadSpeed_ms = params.hostSpeed_ms * 0.5; % 11.1111
params.initSeparation = (params.hostSpeed_ms + params.leadSpeed_ms) * params.LeadTime_s; % 200
1c. 描述 Init 阶段
针对 <Init> 中每个参与者的 Private 动作:
-
TeleportAction — 将位置转换为世界坐标 [x, y, z]:
- WorldPosition:直接使用
- LanePosition:使用 .xodr 转换(参见
scripts/xoscPositionToWorld.p) - RoadPosition:使用 .xodr 转换(参见
scripts/xoscPositionToWorld.p) - 重要:传递给
xoscPositionToWorld的所有参数都必须是数值。 XML 属性始终是字符串——调用前请使用str2double()转换:
传递字符串会在不报错的情况下产生错误坐标(误差最高可达 12 m)。pos = xoscPositionToWorld(xodrPath, 'LanePosition', ... 'roadId', str2double(roadId), 'laneId', str2double(laneId), ... 's', str2double(s), 'offset', str2double(offset)); - RelativeObjectPosition:根据实体朝向旋转 dx/dy,并加到基准位置
- RelativeRoadPosition:反向查找基准实体的道路坐标,并偏移 s/t
- RelativeLanePosition:反向查找基准车道,计算目标车道和 s (当 dLane 从负 ID 跨到正 ID 时,跳过中心车道)
- 按依赖顺序处理实体:先解析被引用的实体
-
Heading — RoadRunner API 不支持设置参与者朝向。 参与者始终与其锚点处的道路方向对齐。请勿在场景描述中包含 朝向,因为无法应用该设置。 注意:XOSC 中的
h属性仍需用于 RelativeObjectPosition 转换(在实体局部坐标系中旋转 dx/dy),但不会应用于放置的参与者。 -
SpeedAction — 记录速度值,并注明其为绝对速度还是相对速度。 对于相对速度:描述为
<abs(delta)> m/s <direction> relative to <ref actor>, 其中 direction 为 "slower"(delta < 0)、"faster"(delta > 0)或 "same"(0)。 -
FollowTrajectoryAction — 仅当其实际在 t=0 开始时才受支持。 这意味着以下任一情况:(a) 位于 Init 中;或 (b) 位于 Story 中,且触发器链 解析为 t=0。通过追踪解析:如果 Event StartTrigger 是
StoryboardElementStateCondition(Act, runningState),则检查 Act 的 StartTrigger;如果它引用了 Story 的 runningState,则检查 Story 的 StartTrigger。如果触发器链最终指向SimulationTimeCondition >= 0, 则视为 t=0。如果链中的任何环节使用了非零时间、持续时间、距离或其他条件, 则不受支持。跳过并发出警告。在受支持时,准确提取折线顶点作为路线航点 (不得减少顶点,也不得重复起点或终点)。确定速度参考:
- TimeReference 中有
<Timing>→ Speed Reference: "route-time-data"。 在描述中包含每个顶点的time属性。 忽略 SpeedAction——时间信息优先于速度。 - TimeReference 中有
<None/>→ Speed Reference: absolute(使用 SpeedAction 值) 使用scripts/xoscPositionToWorld.p转换所有非 WorldPosition 顶点。
- TimeReference 中有
-
AssignRouteAction — 与 FollowTrajectoryAction 使用相同的 t=0 规则(解析 触发器链)。在受支持时,提取所有航点(LanePosition 或 WorldPosition)。始终使用 SpeedAction 中的绝对速度。如果触发器链无法解析为 t=0,则不受支持。跳过并发出警告。
-
AddEntityAction — 通常与 SpeedAction 配对使用(设置位置和初始速度,与 TeleportAction + SpeedAction 相同)。也可以与 FollowTrajectoryAction 或 AssignRouteAction 组合使用——在这些情况下,适用现有规则(第 4 和第 5 项)。从嵌套的
<Position>元素中提取位置,并转换为世界坐标 [x, y, z]。在 Actors 部分中描述该参与者,以便创作技能通过addActor放置它。 不要在 Actors 部分中包含 Initial Speed——该参与者没有初始化。速度在 WaitAction 之后的阶段逻辑中定义。由于addActor会将所有参与者放置在场景开始时(不支持场景中途生成),因此要通过阶段逻辑复现延迟出现:- 查看 AddEntityAction 事件/动作的 StartTrigger 条件
- 将 WaitAction 阶段(SystemActionPhase)描述为该参与者的第一个阶段——插入到自动创建的初始化阶段之前
- 将等待阶段的结束条件设为 XOSC 开始条件
- 参与者自动创建的初始化阶段位于 WaitAction 之后——在此处配置速度/行为(例如 ChangeSpeedAction)
- 不要在 WaitAction 之前添加直通阶段——WaitAction 就是第一个阶段。每个参与者仅有两个阶段:WaitAction → 行为
- AddEntityAction 参与者的速度设置位置: WaitAction 阶段不带速度——它只等待生成条件。速度(例如 17.88 m/s 时的 ChangeSpeedAction)必须放在 WaitAction 之后的自动创建初始化阶段上。切勿在 WaitAction 上或之前设置速度。
-
移动模式约束——如果参与者在 Story 中包含
ChangeLaneAction或ChangeLateralOffsetAction,则必须处于车道跟随模式(无路线)。不要为这类参与者添加路线航点。
忽略不影响参与者的全局初始化动作(例如 EnvironmentAction)。
1d. 描述 Story 阶段
目标是描述意图——每个参与者做什么、由什么触发,以及什么条件会结束。不要保留 XOSC 的结构层级(Acts、Events、ManeuverGroups)。将结构性内容简化为简单的动作描述。
处理 MW_WaitAction(占位 Act):
- 包含真实动作 + MW_WaitAction 的 Act: 将其描述为主要动作,并以该 Act 的 StopTrigger 作为结束条件。忽略 MW_WaitAction。
- 仅包含 MW_WaitAction(无真实动作)的 Act: 该 Act 的 StopTrigger 是串行链中前一个阶段的结束条件。直接将此条件设为前一个阶段的条件——不要单独创建 WaitAction 阶段。**例外:**如果不存在前一个阶段,或者前一个阶段已有结束条件,则创建一个 WaitAction 阶段,并将该 Act 的 StopTrigger 设为结束条件。
确定执行顺序:
查看 StartTriggers,以确定串行/并行关系:
StoryboardElementStateCondition(X, completeState)→ 在 X 结束后运行StoryboardElementStateCondition(X, runningState)→ 与 X 并行运行SimulationTimeCondition >= 0→ 立即开始
并行组和串行后续动作:
当一个 Act 包含多个并行运行的 Event 时,它们构成一个 ParallelPhase。如果后续动作由该 Act 的 completeState 触发,则它在ParallelPhase(容器)之后串行执行,而不是在任何单个子阶段之后执行。只有所有 Event 都结束后,Act 才会完成——因此后续动作必须等待整个并行组结束。
每个动作需要记录的内容:
- 参与者、动作类型、动作属性
- 阶段名称:使用 XOSC
<Action>标签中的name属性 - 触发条件(开始条件)
- 结束条件(来自 Act StopTrigger 或 MW_WaitAction Act)
- 与其他动作之间的串行/并行关系
1e. 编写场景描述
使用 roadrunner-scenario-authoring 术语编写结构化描述,以便创作技能可以直接执行:
## Scene
- OpenDRIVE file: <filename from LogicFile>
- Import required: yes (use `roadrunner-import-scene` with format "OpenDRIVE")
## Parameters (if any)
- <name> = <resolved value> (original expression: <expr>)
## Actors
For each actor:
- Name: <XOSC entity name>
- Type: Vehicle / Pedestrian
- Asset: <model3d path> (AssetType: "VehicleAsset" or "CharacterAsset")
- Initial Position: [x, y, z] (translated from <original position type>)
- Anchoring:
- Lane-following (no route): autoAnchor (actor must be anchored to road for lane following)
- **Exception:** If the actor's translated position is on a junction connector road,
do NOT autoAnchor — anchoring on junctions shifts the position to an
unpredictable anchor point. Place the actor at the exact world coordinates instead.
- Path-following (has route): do NOT autoAnchor (positions are precise world coordinates)
- Movement Mode: path-following (has route) or lane-following (no route)
- **Anchoring and Movement Mode are REQUIRED fields.** Every actor description
must explicitly state the anchoring decision (autoAnchor or NOT autoAnchor)
and movement mode. Do not omit these even when the choice seems obvious from
context — the downstream authoring skill needs them stated explicitly.
- Initial Speed: <value> m/s (absolute)
OR: <delta> m/s <direction> relative to <reference actor>
- Route (if path-following):
- Waypoints: [x, y, z] per row (ALL vertices — never simplify)
- Timestamps: [t0, t1, t2, ...] (if timed trajectory — sets Point.Time)
- Speed Reference: "route-time-data" (timed) or absolute value (untimed)
- Freeform: true (route follows exact waypoint positions, not road geometry)
- Do NOT autoAnchor route waypoints
## Phase Logic
Use RoadRunner action/condition type names (see references/openscenario-mapping.md):
For each meaningful action (skip MW_WaitAction placeholders):
- Actor: <who>
- Phase Name: <from XOSC Action name attribute>
- Action: <RoadRunner action type> (e.g., ChangeSpeedAction, ChangeLaneAction)
- Properties: Speed=X, DynamicsShape="step", Direction="left", etc.
- Trigger: <RoadRunner condition type> (e.g., SimulationTimeCondition, DurationCondition)
- Properties: Time=X, Duration=X, Distance=X, Rule="ge", etc.
- End Condition: <RoadRunner condition type> with properties
- Topology: serial after <previous> / parallel with <sibling>
## Scenario End Conditions
- End: <condition type> on RootPhase (e.g., SimulationTimeCondition, Time=60)
- Fail: <condition type> on RootPhase (e.g., CollisionCondition)
## Unsupported Constructs
- <construct>: <why it cannot be mapped>
1f. 提交审核
向用户展示场景描述。询问: “这是我提取的场景描述。请检查参与者、位置、阶段逻辑和相对引用。生成 MATLAB 脚本前,是否需要我进行调整?”
等待用户批准后,再继续执行步骤 2。
步骤 2:通过依赖技能构建场景
用户批准场景描述后,将执行工作委派给依赖技能。**此技能不会生成 MATLAB 代码。**它只负责解读 .xosc 并生成描述。
2a. 导入场景
导入到一个新场景中并创建新场景方案:
- 调用
newScene(rrApp)获取干净的场景(不含遗留道路) - 使用
ProjectionMode = "noprojection"导入,以保留 .xodr 的原生坐标系:importOpts = openDriveImportOptions; importOpts.ProjectionMode = "noprojection"; importScene(rrApp, xodrPath, "OpenDRIVE", importOpts); - 调用
newScenario(rrApp),在导入的场景中创建新的场景方案
2b. 构建场景方案
重要:你必须调用 /roadrunner-scenario-authoring 来构建场景方案。不要直接编写 MATLAB 代码。不要自行调用 MCP MATLAB 工具(mcp__matlab__evaluate_matlab_code、mcp__matlab__run_matlab_file)。创作技能会处理所有代码生成和执行工作。
调用 /roadrunner-scenario-authoring,并将完整的已批准场景描述作为参数。前缀如下:
在 RoadRunner 中构建以下场景。场景已导入,并且已创建新的场景方案。
然后粘贴完整的场景描述(参与者、阶段逻辑、结束条件等),以便创作技能直接执行。
在指令中包含以下映射细节,确保创作技能正确应用:
锚定规则:
- **车道跟随型参与者(无路线/轨迹):**必须执行 autoAnchor;参与者需要锚定到道路,才能正确跟随车道。
- **路径跟随型参与者(有路线):**不要对参与者或路线航点执行 autoAnchor;位置是精确的世界坐标,autoAnchor 会使它们偏离预期位置,导致轨迹错位。
CollisionCondition 模式(包含在结束条件中):
| XOSC 模式 | 指定内容 |
|---|---|
<EntityRef entityRef="ActorB"/>(特定参与者对) | “[Actor] 与 [ActorB] 之间发生碰撞” |
<ByType type="vehicle"/>(任意车辆) | “[Actor] 与任意车辆发生碰撞” |
多个 <ConditionGroup> 元素(StopTrigger 中的 OR 逻辑):将每个元素分别描述为 RootPhase 上的结束/失败条件。
参考资料
在步骤 1 中查阅以下资料,将 XOSC 构造映射到 RoadRunner 术语:
references/openscenario-mapping.md— XOSC 动作/条件类型 → RoadRunner API 类型名称、状态映射、规则映射、属性映射scripts/xoscPositionToWorld.p— MATLAB 函数:使用 .xodr 文件调用此函数,将任意 XOSC 位置类型转换为世界坐标 [x, y, z]
常见错误
| 错误 | 错误原因 | 正确做法 |
|---|---|---|
| 对没有路线的车道跟随型参与者跳过 autoAnchor | 未锚定到道路时,参与者无法正确沿车道行驶 | 车道跟随型参与者(无路线/轨迹)必须使用 autoAnchored——但在交叉路口连接道路上除外,因为锚定会改变位置 |
| 在交叉路口连接道路上使用 autoAnchor | 在交叉路口锚定会将参与者移到不可预测的锚点,导致位置错位 | 如果转换后的位置位于交叉路口,应使用精确的世界坐标放置,不使用 autoAnchor |
| 对带有路线的路径跟随型参与者使用 autoAnchor | 会改变位置,导致轨迹错位 | 路径跟随型参与者及其路线航点不应使用 autoAnchored——位置已经是精确的世界坐标 |
向 xoscPositionToWorld 传递字符串参数 | 函数会悄然返回错误坐标(误差最高可达 12m) | 调用前,务必对 XML 属性值使用 str2double():'roadId', str2double(id), 'laneId', str2double(lane), 's', str2double(s), 'offset', str2double(off) |
| 为 AddEntityAction 参与者在 WaitAction 前添加一个过渡初始化阶段 | 增加了不必要的阶段;参与者应在生成时间到达前保持不动 | WaitAction 就是第一个阶段——仅有两个阶段:WaitAction → 行为 |
| 在 Actors 部分为 AddEntityAction 参与者包含初始速度 | 等待期间,参与者尚未初始化 | 速度在 WaitAction 之后的阶段逻辑中设置,而不是在 Actors 部分 |
| 为 WaitAction 使用 ActorActionPhase | WaitAction 不是参与者动作 | WaitAction 必须放在 SystemActionPhase 中 |
约定
- 此技能仅生成场景描述——绝不生成 MATLAB 代码
- 场景导入委托给
roadrunner-import-scene,场景构建委托给roadrunner-scenario-authoring - 转换位置前,务必将参数/表达式解析为具体值
- 描述参与者前,务必将 CatalogReferences 解析为资源路径
- 资源路径使用项目扩展名:车辆为
.fbx,角色为.rrchar
版权所有 2026 The MathWorks, Inc.