Aller au contenu

Planning trace for motion planner debugging (advanced)

Ce contenu n’est pas encore disponible dans votre langue.

A CommonRoad solution stores one trajectory: the path the ego actually drove. A cyclic planner computes a new trajectory every replanning cycle, each looking seconds ahead, and executes a fraction of a second of it before replanning.

A planning trace keeps those cycles, and keeps the answer too. One file holds both driven (the states the ego actually drove) and plans (what the planner intended at each cycle), which makes it self-contained: drop it alone and the whole run replays.

Only the planner’s author can write one, because the per-cycle trajectories exist nowhere but inside the planner’s loop. That is why it is a library, not a command.

from drawtonomy_cr.trace import TraceWriter
w = TraceWriter(dt=0.1, vehicle=dict(length=4.5, width=1.8, refToCenter=1.4,
type="BMW_320i"))
for cycle in my_planner_loop():
w.plan(t=cycle.t, states=cycle.trajectory) # one entry per replanning cycle
w.driven(executed_states) # what the ego actually drove
w.write("solution.planning-trace.json", solution="solution.xml")

states takes commonroad-io State objects and plain {"x":, "y":, "orientation":, "v":, "time_step":} dicts alike.

write() verifies two identities before writing anything: driven matches the solution’s trajectory within 1e-6 m, and each plan’s executed head matches driven at the same time steps. A mismatch raises instead of writing a trace that would replay differently from the solution it claims to describe.

ArgumentRequiredMeaning
dtyesThe scenario’s time step in seconds, finite and > 0. Used to convert a state’s time_step into the file’s seconds.
vehiclenoThe body the planner planned with, as {"length":, "width":, "refToCenter":, "type":}. A CommonRoad planning problem carries no ego shape, so without this drawtonomy draws and checks the authored box instead of the one the official checker judged.
scenarionoScenario identifier, e.g. str(scenario.scenario_id). Used to pair the trace with the scene.
producerno{"name":, "version":}. Informational only.
roledefaults to "ego"Which actor the track belongs to, by role.
namenoWhich actor the track belongs to, by entity name. Give exactly one of role / name; pass role=None when you use name.
framedefaults to "center"What the positions mean: "center" (the vehicle body centre, which is what CommonRoad’s position means) or "ref" (the reference point, the centre of the rear axle).

write(path, solution=None, replanning_frequency=1, verbose=True): solution (a path, a Solution object, or a state list) enables the driven-matches-the-solution check; replanning_frequency is how many leading states of each plan were actually executed, and therefore how many are compared against driven; verbose prints the one PASS / FAIL line per check.

The distance in metres from the reference point (the centre of the rear axle) to the body centre, measured along the heading. It is a property of the body, not of frame: frame says what the coordinates in the file mean, while refToCenter is the offset drawtonomy uses to convert between the two, so the drawn body centre lands exactly on the file’s positions.

It must be 0 or greater, and a negative value is refused. The example’s 1.4 is a real car’s value (BMW_320i is 1.4227170936); take yours from your planner’s own vehicle parameters, where commonroad-vehicle-models calls it wb_rear_axle. Omit the field and drawtonomy falls back to the authored vehicle’s own offset.

{
"schema": "drawtonomy-planning-trace-v1",
"scenario": "ZAM_Untitled202609011139-1_1_T-1",
"producer": { "name": "my_planner", "version": "0.1" },
"frame": "center",
"tracks": [
{
"role": "ego",
"vehicle": { "length": 4.508, "width": 1.61, "refToCenter": 1.4227170936, "type": "BMW_320i" },
"driven": [
{ "t": 0.0, "x": 8.18, "y": 51.37, "h": 1.567, "v": 30.0 },
{ "t": 0.1, "x": 8.19, "y": 54.37, "h": 1.567, "v": 30.0 }
],
"plans": [
{
"t": 0.0,
"states": [
{ "t": 0.0, "x": 8.18, "y": 51.37, "h": 1.567, "v": 30.0 },
{ "t": 0.1, "x": 8.19, "y": 54.37, "h": 1.567, "v": 30.0 }
]
}
]
}
]
}
FieldRequiredMeaning
schemayesExactly "drawtonomy-planning-trace-v1". Any other value is refused.
frameyes"center" or "ref", as above.
tracksyesOne entry per actor, at least one.
scenarionoScenario identifier this trace was computed for.
producernoFree-form, informational.
tracks[].role / tracks[].nameexactly oneWhich actor the track belongs to.
tracks[].drivenyesThe states the actor actually drove, ascending in t.
tracks[].plansyesThe plans the planner issued, at least one.
tracks[].vehiclenolength / width in metres (both required when vehicle is present, both > 0), optional refToCenter and type.
plans[].tyesSeconds at which the plan was issued. Must equal states[0].t within 1e-6.
plans[].states[]yest (seconds), x, y (metres, ENU with Y up), optional h (radians, counter-clockwise, 0 = +x) and v (m/s).

Two things to note against the verdict sidecar, which is the other file in this exchange: a trace’s times are seconds, not the sidecar’s integer time steps, and the heading key is h, not orientation. Unknown keys are ignored.

Same as a solution: drop it on the canvas, pick it in Import…, or point &trace= at it in the URL. drawtonomy-cr open picks it up automatically when it is named <solution stem>.planning-trace.json next to the solution.

When both a solution and a trace are given, the trace wins. They are both a replay of the same run, so only one can drive the ego, and the trace is the solution plus more (its driven states are the solution’s trajectory). The one that was dropped is named in a single line so it is never a silent choice.

During replay the ego moves along driven, exactly as it would from a solution. What the trace adds is the planned trajectory on the road: at each instant, the plan the planner was holding then, which is the latest plan issued at or before the playhead, sliced forward from the playhead.

So you see where the planner thought it would be several seconds ahead, and the moment it changed its mind about that. Before the first plan’s time, nothing is drawn for that actor.

A checker verdict pairs by scenario id, so it lands on a trace replay exactly as it does on a solution replay.

The planned trajectory is part of the picture, so exporting keeps it. Export video… writes it into every frame the same way it appears on the canvas: under the vehicles, sliced forward from that frame’s time. Image exports (PNG, JPEG, SVG, EPS, PDF) include the trajectory as it is shown at the current playback time. Turn the Trajectory toggle off before exporting if you want an image or video without it.