executing-plans
executing-plans
Use when executing an implementation plan in the current session as the implementer yourself — your human partner chose inline execution, or no subagent tool is available
roadrunner-scenario-authoringProgrammatically author RoadRunner scenarios from MATLAB using roadrunnerAPI. Use when adding actors, creating routes, building scenario logic (phases, conditions, actions), placing vehicles/pedestrians, defining cut-in/crossing/ follow scenarios, or any programmatic scenario creation in RoadRunner. Triggers on: roadrunnerAPI, scenario authoring, add actor,…
Independent GitHub snapshot · Automated classification · Original documentation governs
Programmatically create RoadRunner scenarios from MATLAB: actors, routes, phase logic, and validation — all via roadrunnerAPI.
roadrunner-corematlab-use-scenario-builderroadrunner-rrhd-authoringroadrunner-import-sceneroadrunner-scenario-simulatingVerify rrApp exists. If not, ensure RoadRunner is connected first (e.g., via roadrunner-core or manually).
if ~exist('rrApp', 'var') || ~isvalid(rrApp)
error("No active RoadRunner session. Use the roadrunner-core skill.");
end
Path setup: Before calling helper functions, ensure the scripts directory is on the MATLAB path:
addpath('<path-to-skill>/scripts');
openScene(rrApp, sceneName);
newScenario(rrApp);
rrApi = roadrunnerAPI(rrApp);
rrs = rrApi.Scenario;
phaseLogic = rrs.PhaseLogic;
rrprj = rrApi.Project;
Before placing actors, survey the scene to find valid lane positions. Use the helperSceneAwareness script for automated analysis, or query manually via HD Map export:
sceneInfo = helperSceneAwareness(rrApp, NumActors=2, ScenarioType="cut-in");
See references/scene-awareness.md for manual HD Map query patterns when the helper is unavailable.
Option A — Batch placement (recommended for 2+ actors):
actorSpecs(1) = struct(Name="Ego", AssetPath="Vehicles/Sedan.fbx", ...
AssetType="VehicleAsset", LaneIndex=1, Fraction=0.1, Speed=15);
[actors, report] = helperPlaceActors(rrs, rrprj, phaseLogic, sceneInfo.HDMap, actorSpecs);
ego = actors{1}; % cell array — use curly braces
Option B — Manual placement:
vehicleAsset = getAsset(rrprj, "Vehicles/Sedan.fbx", "VehicleAsset");
actor = addActor(rrs, vehicleAsset, position);
actor.Name = "Ego";
autoAnchor(actor.InitialPoint); % Snaps to nearest road
Post-placement check: Verify actor.InitialPoint.WorldPosition is NOT [0 0 0].
See references/asset-catalog.md for available vehicle/character paths.
Option A — Scene anchors available:
anchors = getAnchors(rrApp);
% Use remapAnchor for cross-scene portability (not findSceneAnchor)
anchorPt = findSceneAnchor(rrs, anchors(1).Name);
anchorToPoint(actor.InitialPoint, anchorPt);
actor.InitialPoint.ForwardOffset = 20;
actor.InitialPoint.LaneOffset = 1;
Option B — No scene anchors (use autoAnchor):
actor = addActor(rrs, asset, approximatePosition);
autoAnchor(actor.InitialPoint); % Must be within 5m of road
Option C — Relative to another actor:
anchorToPoint(target.InitialPoint, ego.InitialPoint);
target.InitialPoint.ForwardOffset = 30;
target.InitialPoint.LaneOffset = 1;
Routes put actors in path-following mode. Actors without routes drive in lane-following mode along their anchored lane.
route = actor.InitialPoint.Route;
fwdPt = addPoint(route, actor.InitialPoint.WorldPosition + [20 0 0]);
autoAnchor(fwdPt);
% For vehicles: disable freeform so route follows road surface
% (Do NOT do this for pedestrians — they need freeform to cross roads)
for i = 1:numel(route.Segments)
route.Segments(i).Freeform = false;
end
When to add routes:
ChangeLaneActionWhen NOT to add routes:
ChangeLaneAction — they MUST be in lane-following mode (no routes)ChangeLateralOffsetAction — same requirementRoute point rules:
autoAnchor for route points — position must be within 5m of roadanchorToPoint + ForwardOffset on route points — causes validation failureseg.Freeform = false on each segment to follow road geometry (freeform routes ignore road surface and may float above/below the road)See references/actions-and-conditions.md for the complete catalog.
% Get actor's initial phase (auto-created with addActor)
initPhase = initialPhaseForActor(phaseLogic, actor);
% Modify default speed (initial phase already has ChangeSpeedAction)
initPhase.Actions(1).Speed = 20;
% Add sequential phase
nextPhase = addPhaseInSerial(phaseLogic, initPhase, "ActorActionPhase");
nextPhase.Actor = actor; % REQUIRED — never omit
% Set trigger condition on initial phase
cond = setEndCondition(initPhase, "LongitudinalDistanceToActorCondition");
cond.Actor = actor; % REQUIRED
cond.ReferenceActor = otherActor;
cond.Distance = 10;
% Add action to next phase
action = addAction(nextPhase, "ChangeLaneAction");
action.Direction = "left";
Multi-actor phase logic: Each actor's phase chain is independent. Any phase that has a subsequent phase MUST have an end condition — without one, the phase runs indefinitely and subsequent phases never execute. For multi-actor scenarios, ensure EVERY phase with a successor has an appropriate end condition set via setEndCondition.
validate(rrs);
After validation passes, present a summary of what was created — never simulate unless explicitly asked.
MANDATORY: Before writing ANY code, complete Steps 0–1 below and present your plan to the user for confirmation. Do not skip this — scenarios built without pre-analysis frequently fail due to wrong timing, missed collisions, or impossible trigger conditions.
Step 0 — Clarify intent: If the user's prompt is ambiguous about ANY of the following, ASK before proceeding:
Step 1 — Physics-first design (REQUIRED for timed interactions): For collisions, near-misses, cut-ins, pedestrian crossings, and any scenario where actors must arrive at the same point at a specific time — you MUST derive kinematic parameters before writing code. Follow the full 5-step process in references/physics-first-design.md:
Present your decomposition to the user — show actors, placement, speeds, trigger timing, and expected outcome. Get confirmation before executing code.
helperSceneAwareness type to use:
ScenarioType="following") — leader/follower, overtake start, emergency brakeScenarioType="cut-in") — lane changes, merges, parallel drivingLongitudinalDistanceToActorCondition) — requires speed differential between actorsDurationCondition) — works regardless of speeds, simplerSimulationTimeCondition) — absolute time, good for choreographed sequencesrequired_gap = lane_change_distance + closing_rate × (lane_change_distance / actor_speed) + 5mWhen newScenario() is called, RoadRunner automatically creates:
Do NOT duplicate these. To modify the default collision condition:
rootPhase = phaseLogic.RootPhase;
% The fail condition already exists — access it directly
% To change the end time:
rootEndCond = setEndCondition(rootPhase, "SimulationTimeCondition");
rootEndCond.Time = 30; % Override default 60s
.Actor on ActorActionPhase and condition objects — never omitphase.Actions(1) insteadautoAnchor requires proximity — point must be within 5m of road surface"le" and "ge" are valid (not "lt", "gt")"eq", "gt", "lt", "ge", "le", "ne"setEndCondition not addEndCondition — only one end condition per phaseChangeLaneAction requires lane-following mode — do NOT add routes to actors that need lane changesanchorToPoint + ForwardOffset on route points — causes validation failure; use autoAnchor onlyLaneOffset can land on junction connectors — for lane-change scenarios, place actors on verified parallel lanes using HD Map positions + autoAnchor instead of LaneOffsetLaneChangeReference="actor" + Direction="same-lane" when targeting another actor's lane, or compute direction via cross product (see references/scenario-templates.md).ParentPhase, not on child phases[0 0 0] means anchoring failed silentlyremoveActor does not exist; WorldPosition is read-only after anchoring. Placement mistakes require newScenario() and rebuilding. Plan placement carefully before executing.autoAnchor unreliable at lane boundaries — Use fraction ≥ 0.2 and ≤ 0.8 when querying HD Map positions. At lane start/end points, multiple lanes converge and autoAnchor may snap to the wrong lane.lane_change_distance + (closing_rate × maneuver_time) + vehicle_length. A 20m lane change at 5 m/s closing rate needs ≥ 30m initial gap.seg.Freeform = false on each segment so the route follows road geometry. Do NOT disable freeform on pedestrian routes — pedestrians cross roads and need freeform paths.bumper_gap = center_distance - (vehicle1_length/2 + vehicle2_length/2). Timing: t_collision = bumper_gap / closing_rate. Account for ~1s acceleration ramp from rest (vehicles don't reach target speed instantly).LaneOffset must be positive; you cannot place two vehicles facing each other on the same road segment via the programmatic API. Use rear-end or crossing-path collision designs instead.setEndCondition — setEndCondition(phase,"Type").Property = N fails on ActorActionPhase (works only on InitialPhase). Always store the result first: c = setEndCondition(phase, "Type"); c.Property = N;. This two-line pattern works on ALL phase types.ActorActionPhase — call addAction only once per phase. The auto-created initial phase (from initialPhaseForActor) is the only exception. For concurrent actions, use a ParallelPhase with one ActorActionPhase child per action.egoPos + [X, Y, 0] only works on world-axis-aligned roads. For pedestrians and crossing actors, always use helperGetPositionFromHDMap to get position and heading, then compute the perpendicular crossing direction: hdg2D = hdg(1:2)/norm(hdg(1:2)); perpDir = [-hdg2D(2), hdg2D(1), 0];FourWaySignal, FourWayStop, and T_Intersection, approach lanes do not connect to opposing exit lanes via the routing API. Use single-arm routes (approach → connected exit lane in the same corridor) or lane-following mode only. Cross-arm routes fail validate.helperSceneAwareness the parameter is MinLaneLength (default 30); for helperSurveyLanes/helperGetPositionFromHDMap use MinLength. On intersection scenes use 30 since approach lanes are short. Compute needed length: max_speed × scenario_duration + 20m. Using 80+ on small scenes leaves fewer lanes than expected.| Wrong (hallucinated) | Correct |
|---|---|
RelativeLaneOffset | NumLanesOffset |
SimulationTime | SimulationTimeCondition |
addEndCondition | setEndCondition |
listAssets / getAssets | getAsset(proj, path, type) |
getActors / listActors | rrs.Actors |
actor.Speed | initPhase.Actions(1).Speed |
route.addWaypoint | addPoint(route, position) |
removeActor / deleteActor | Does not exist — use newScenario() |
actor.WorldPosition = ... | Read-only — reposition via newScenario() + re-place |
cond.Comparison | Does not exist on SimulationTimeCondition (just set .Time) |
rrApp.ProjectFolder | Not a public property — use status(rrApp) |
DistanceType = "gap" | Use "space" (spatial) or "time" (time-gap) |
ConstraintType = "acceleration" | Use "asset", "custom", or "none" |
PhaseState = "completed" | Use "end" (valid: "idle", "start", "run", "end") |
MeasureDistance = "euclidean" | Use "lane" or "actor" |
"MovableObjects/..." | Use "Props/TrafficControl/..." with "MovableObjectAsset" type |
syncAction.TargetPoint = actor.InitialPoint | Shared reference trap — use route waypoints as independent Points |
LateralOffsetAction | ChangeLateralOffsetAction (full name required) |
.Offset (on ChangeLateralOffsetAction) | .LateralOffset |
laneTable.LaneIndex | laneTable.Index (column name from helperSurveyLanes) |
action.Rate | Use .DynamicsDimension = "rate"; .DynamicsValue = N; |
setEndCondition(...).Property = N | c = setEndCondition(...); c.Property = N; (two-line pattern) |
MinLength (on helperSceneAwareness) | MinLaneLength — only lower-level helpers use MinLength |
"text" + status(rrApp) | status(rrApp) returns a struct — use s = status(rrApp); s.Scene.Filename |
actors(i) from helperPlaceActors | actors{i} — returns a cell array, use curly-brace indexing |
| Function | Purpose | Since |
|---|---|---|
roadrunnerAPI(rrApp) | Create authoring API handle | R2025a |
addActor(rrs, asset, pos) | Add actor to scenario | R2025a |
getAsset(proj, path, type) | Load asset by path | R2025a |
autoAnchor(point) | Snap point to nearest road | R2025a |
anchorToPoint(pt, anchor) | Anchor point to reference | R2025a |
addPoint(route, pos) | Add waypoint to route | R2025a |
initialPhaseForActor(logic, actor) | Get actor's init phase | R2025a |
addPhaseInSerial(logic, phase, type) | Add sequential phase | R2025a |
addPhaseInParallel(logic, phase, type) | Add concurrent phase | R2025a |
setEndCondition(phase, type) | Set phase trigger | R2025a |
addAction(phase, type) | Add behavior action | R2025a |
validate(rrs) | Check scenario validity | R2025a |
validate(rrs, ObjectRoot=obj) | Validate specific object (phase, actor, route) | R2025a |
findActions(phase, type) | Find actions of a type in a phase | R2025a |
createAsset(proj, path, type) | Create new asset (vehicle, character, behavior) | R2025a |
getAnchors(rrApp) | List scene anchors | R2024a |
getAsset with "CharacterAsset" | Load pedestrian asset | R2025a |
| Mode | Trigger | Behavior | Compatible Actions |
|---|---|---|---|
| Lane-following | No route waypoints | Follows anchored lane at set speed | ChangeLaneAction, ChangeLateralOffsetAction |
| Path-following | Has route waypoints | Follows waypoint path | ChangeSpeedAction, ChangeLongitudinalDistanceAction |
ChangeLaneAction ONLY works in lane-following mode (no routes)[X Y Z]"Vehicles/Sedan.fbx").fbx_rrx, API uses .fbx; disk shows .rrchar_rrx, API uses .rrchar"Ego", "TargetVehicle", "Pedestrian1")ScenarioBasic.rrscene (310 forward lanes, ScenarioStart anchor)FourWaySignal, FourWayStop, T_IntersectionDeploy these helpers into the user's MATLAB path for automated scene analysis and batch placement. They depend on each other: helperSceneAwareness calls helperSurveyLanes and helperGetPositionFromHDMap.
| Script | Purpose | When to use |
|---|---|---|
scripts/helperSceneAwareness.m | Export HD Map, survey lanes, classify road features, recommend placements | First step before placing actors — provides positions, lane context, and feature classification |
scripts/helperSurveyLanes.m | Filter/sort lanes by type, direction, length | When you need lane geometry data without full scene analysis |
scripts/helperGetPositionFromHDMap.m | Arc-length interpolation along lanes, nearest-point queries | When you need precise positions at specific fractions along a lane |
scripts/helperPlaceActors.m | Batch place, anchor, set speed, verify multiple actors | When placing 2+ actors — automates the manual add/anchor/verify loop |
scripts/helperClassifyRoadFeatures.m | Elevation-based road feature classification (bridge, ground, ramp) | Used internally by helperSceneAwareness; call directly for custom feature queries |
Usage pattern:
% 1. Run scene awareness to get lane data and recommended positions
sceneInfo = helperSceneAwareness(rrApp, NumActors=2, ScenarioType="cut-in");
% 2. Define actor specs (do NOT pre-initialize with actorSpecs=[])
actorSpecs(1) = struct(Name="Ego", AssetPath="Vehicles/Sedan.fbx", ...
AssetType="VehicleAsset", LaneIndex=1, Fraction=0.1, Speed=15);
actorSpecs(2) = struct(Name="Target", AssetPath="Vehicles/Sedan.fbx", ...
AssetType="VehicleAsset", LaneIndex=2, Fraction=0.2, Speed=20);
% 3. Batch place and verify (actors is a cell array)
[actors, report] = helperPlaceActors(rrs, rrprj, phaseLogic, sceneInfo.HDMap, actorSpecs);
assert(report.AllValid, "Placement failed: " + report.Summary);
ego = actors{1}; target = actors{2}; % curly braces required
For scenes with multiple elevation levels (bridges, overpasses, underpasses), use the RoadFeature parameter to target a specific road structure:
% Place actors specifically on the bridge deck
sceneInfo = helperSceneAwareness(rrApp, NumActors=2, ScenarioType="following", ...
RoadFeature="bridge");
% LaneIndex=1 now refers to the longest BRIDGE lane, not the longest overall lane
actorSpecs(1) = struct(Name="Leader", AssetPath="Vehicles/Sedan.fbx", ...
AssetType="VehicleAsset", LaneIndex=1, Fraction=0.3, Speed=15, ...
FilterLaneIDs=sceneInfo.FilteredLaneIDs);
Available feature labels: "bridge", "ground", "ramp", "overpass"
When to use RoadFeature:
When RoadFeature="" (default): The summary shows all detected features so you can ask the user which one they mean:
Road features detected:
bridge: 10 lanes, total 700m, connected path 192m, elevation 7.9-8.6m
ground: 3 lanes, total 490m, connected path 165m, elevation 2.4-2.8m
Output fields for feature-aware placement:
sceneInfo.RoadFeatures — full feature classification structsceneInfo.FilteredLaneIDs — lane IDs matching the requested feature (pass to actorSpecs.FilterLaneIDs)sceneInfo.LaneNetwork — full lane connectivity from helperAnalyzeHDMapLanesRoadRunner ships example helpers at <RoadRunner-Install>/Tools/MATLAB/api/scenario/common (e.g., helperAddCutInAndSlowCar, helperAddPedestrian). These use anchorToPoint + LaneOffset for actor placement.
When built-in helpers are suitable: Simple scenes with clearly separated lanes (straight roads, known layouts).
When to prefer this skill's approach instead: Scenes with junctions, complex layouts, or unknown geometry — LaneOffset can land actors on junction connectors that don't support lane changes. HD Map positions + autoAnchor works reliably on any scene.
Key pattern from built-in helpers: ChangeLaneAction supports LaneChangeReference="actor" with Direction="same-lane" — the actor moves to the reference actor's lane automatically, eliminating cross-product direction computation. See references/scenario-templates.md Cut-In section for usage.
references/actions-and-conditions.md — Complete catalog of all action types, condition types, their properties and valid values. Consult when building phase logic.references/routes-and-points.md — Full Point properties, RouteSegment configuration, time-based trajectories, and route read-only properties. Consult for precise positioning, trajectory timing, or curve configuration.references/collision-utility.md — CollisionUtility configuration for collision analysis between specific actor pairs. Consult when setting up collision monitoring.references/asset-catalog.md — Available vehicle and character asset paths with naming conventions. Consult when adding actors.references/scene-awareness.md — HD Map export pattern for querying lane geometry when helperSceneAwareness is unavailable. Consult when placing actors on unknown scenes.references/lane-connectivity.md — Lane network topology, road feature classification, and connected path queries. Consult when placing actors on specific road features (bridge, ramp) or when you need lane connectivity information.references/scenario-templates.md — Tested code patterns for cut-in, pedestrian crossing, lead-follow, emergency brake. Consult when building specific scenario types.references/physics-first-design.md — Pre-authoring kinematic analysis: derive speeds, gaps, and timing before writing code. Consult for collision/near-miss/timed-interaction scenarios.Copyright 2026 The MathWorks, Inc.