mcpField
R
roadrunner-build-scenario-from-osc

roadrunner-build-scenario-from-osc

github.com/matlab其他1.2k46 次安装2 天前更新
代码仓库

关于 roadrunner-build-scenario-from-osc

解析 OpenSCENARIO 1.x 的 `.xosc` 文件,并生成用于在 RoadRunner 中重建情景的描述。保留源文件中的位置、相对引用和阶段逻辑,待用户确认后再交由相关技能构建。

主要功能

  1. 01解析并验证 `.xosc` 输入
  2. 02解析参数和目录引用
  3. 03依据关联的 `.xodr` 转换位置
  4. 04将动作映射为情景阶段
  5. 05标记不支持的结构供审阅

适用场景

  1. 01重建合作方提供的 `.xosc` 情景
  2. 02生成 RoadRunner 情景描述
  3. 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.yaml
references/
openscenario-mapping.md
scripts/
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)

关键规则

  1. 绝不臆造源 XOSC 中不存在的动作或条件。 如果某个构造无法映射,请跳过并警告用户。

  2. 绝不提出变通方案。 不要用 DurationCondition 替换 DistanceToPointCondition,不要用 SimulationTimeCondition 替代不受支持的触发器,也不要添加源文件中不存在的任何构造。

  3. 绝不简化或复制轨迹顶点。 精确提取源 XOSC 中的折线顶点,不多不少。不要将 90 个顶点缩减为 5 个。提取时不要复制起点或终点。

  4. 绝不猜测场景。 只报告 <LogicFile> 中的 .xodr 文件名。 导入该文件,不要搜索名称相似的场景。

  5. 绝不将相对引用转换为绝对引用。 如果源文件使用 RelativeTargetSpeed delta=-8,请将其保留为 SpeedReference="actor"、 Direction="slower"、Speed=8。不要计算并硬编码 7 m/s。

  6. 绝不默默省略不受支持的功能。 始终在场景描述的“Unsupported Constructs”部分明确标出。

  7. 描述意图,而不是 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 动作:

  1. TeleportAction — 将位置转换为世界坐标 [x, y, z]:

    • WorldPosition:直接使用
    • LanePosition:使用 .xodr 转换(参见 scripts/xoscPositionToWorld.p)
    • RoadPosition:使用 .xodr 转换(参见 scripts/xoscPositionToWorld.p)
    • 重要:传递给 xoscPositionToWorld 的所有参数都必须是数值。 XML 属性始终是字符串——调用前请使用 str2double() 转换:
      pos = xoscPositionToWorld(xodrPath, 'LanePosition', ...
          'roadId', str2double(roadId), 'laneId', str2double(laneId), ...
          's', str2double(s), 'offset', str2double(offset));
      
      传递字符串会在不报错的情况下产生错误坐标(误差最高可达 12 m)。
    • RelativeObjectPosition:根据实体朝向旋转 dx/dy,并加到基准位置
    • RelativeRoadPosition:反向查找基准实体的道路坐标,并偏移 s/t
    • RelativeLanePosition:反向查找基准车道,计算目标车道和 s (当 dLane 从负 ID 跨到正 ID 时,跳过中心车道)
    • 按依赖顺序处理实体:先解析被引用的实体
  2. Heading — RoadRunner API 不支持设置参与者朝向。 参与者始终与其锚点处的道路方向对齐。请勿在场景描述中包含 朝向,因为无法应用该设置。 注意:XOSC 中的 h 属性仍需用于 RelativeObjectPosition 转换(在实体局部坐标系中旋转 dx/dy),但不会应用于放置的参与者。

  3. SpeedAction — 记录速度值,并注明其为绝对速度还是相对速度。 对于相对速度:描述为 <abs(delta)> m/s <direction> relative to <ref actor>, 其中 direction 为 "slower"(delta < 0)、"faster"(delta > 0)或 "same"(0)。

  4. 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 顶点。
  5. AssignRouteAction — 与 FollowTrajectoryAction 使用相同的 t=0 规则(解析 触发器链)。在受支持时,提取所有航点(LanePosition 或 WorldPosition)。始终使用 SpeedAction 中的绝对速度。如果触发器链无法解析为 t=0,则不受支持。跳过并发出警告。

  6. 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 上或之前设置速度。
  7. 移动模式约束——如果参与者在 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. 导入场景

导入到一个新场景中并创建新场景方案:

  1. 调用 newScene(rrApp) 获取干净的场景(不含遗留道路)
  2. 使用 ProjectionMode = "noprojection" 导入,以保留 .xodr 的原生坐标系:
    importOpts = openDriveImportOptions;
    importOpts.ProjectionMode = "noprojection";
    importScene(rrApp, xodrPath, "OpenDRIVE", importOpts);
    
  3. 调用 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 使用 ActorActionPhaseWaitAction 不是参与者动作WaitAction 必须放在 SystemActionPhase 中

约定

  • 此技能仅生成场景描述——绝不生成 MATLAB 代码
  • 场景导入委托给 roadrunner-import-scene,场景构建委托给 roadrunner-scenario-authoring
  • 转换位置前,务必将参数/表达式解析为具体值
  • 描述参与者前,务必将 CatalogReferences 解析为资源路径
  • 资源路径使用项目扩展名:车辆为 .fbx,角色为 .rrchar

版权所有 2026 The MathWorks, Inc.


评论

支持 Markdown