Skip to main content

drawtonomy-cr

image

CommonRoad connector for drawtonomy. Bring your own planner.

scenario.xml  (CommonRoad 2020a, exported from drawtonomy)
      |
      v
[your planner]  -- required --> solution.xml   (CommonRoadSolution, commonroad-io)
      |
      +-- optional --> solution.planning-trace.json   (drawtonomy_cr.trace.TraceWriter)
      |
      v (drawtonomy-cr post-processes)
solution.verdict.json   (drawtonomy-verdict/1, the official checker's 7 verdicts)

The solution XML is the only required file. Everything else is optional: replay and drawtonomy's own collision badge work without them.

Install

pip install drawtonomy-commonroad                 # TraceWriter and `open`
pip install "drawtonomy-commonroad[checker]"      # + verdict, needs Linux x86_64
pip install "drawtonomy-commonroad[boundary]"     # + the road boundary check

The [boundary] extra adds Shewchuk's Triangle, which boundary_collision triangulates the road with. It is not a default dependency because Triangle is free for non-commercial use but needs the author's permission for commercial use. Without it boundary_collision is reported as SKIP rather than FAIL and the other six checks still run.

drawtonomy-cr verdict

drawtonomy-cr verdict scenario.xml solution.xml [-o out.json]

Runs the same seven tests the official valid_solution runs, in the same order (solved_all_problems, goal_reached, starts_at_correct_state, obstacle_collision, boundary_collision, ego_collision, solution_feasible), one by one, and writes the result as a drawtonomy-verdict/1 sidecar next to the solution (<solution stem>.verdict.json when -o is omitted). Drop it into drawtonomy together with the solution to see PASS / FAIL badges, the colliding time steps and the obstacle involved.

Exit codes: 0 when the sidecar was written (a FAIL verdict lives inside the JSON, it is not an error), 3 when the checker is not installed.

The sidecar also records scenarioFingerprint and solutionFingerprint: sha256: plus 64 lowercase hex digits over each input, read as UTF-8 with one leading BOM removed and CRLF or CR turned into LF. They let the app confirm that the files you loaded are the files that were checked; it shows Checker unchecked for a verdict that has none. They identify content, not authenticity, so re-run the checker after editing an input rather than copying a fingerprint across.

Format: docs/verdict-sidecar.md.

drawtonomy_cr.trace.TraceWriter

A planning trace records what the planner intended at every replanning cycle, not just the trajectory it ended up driving. Only the planner's author can produce one, so it is a library, not a command.

from drawtonomy_cr.trace import TraceWriter

w = TraceWriter(dt=0.1, vehicle=dict(length=4.508, width=1.61, refToCenter=1.4227,
                                     type="BMW_320i"))
for cycle in my_planner_loop():
    w.plan(t=cycle.t, states=cycle.trajectory,   # one entry per replanning cycle
           candidates=cycle.evaluated)           # optional: what it did not drive
w.driven(executed_states)                        # what the ego actually drove
w.write("solution.planning-trace.json",
        solution="solution.xml", scenario="scenario.xml")

vehicle is the body the planner planned with. Only length, width and refToCenter are used; type is a free label shown in the replay tooltip. Use whatever body your planner uses, or omit vehicle to fall back to the size the ego was drawn with.

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

candidates are the trajectories a sampling planner evaluated and did not drive, as {"states":, "cost":, "feasible":, "reason":} dicts of which only states is required. drawtonomy draws them as a fan behind the chosen plan. They dominate the size of a trace, so TraceWriter(..., candidate_stride=n) keeps every n-th candidate state and leaves driven and plans alone.

Passing solution= and scenario= as paths records their fingerprints in the trace, the same values a verdict of the same files carries. That is what lets a verdict dropped next to a trace count as the official result for that run instead of being shown as unchecked.

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, and the whole file against planning-trace-v1.schema.json, which ships with the package as drawtonomy_cr.trace.SCHEMA_PATH. A failure raises instead of writing a trace that would replay differently from the solution it claims to describe. solutionFingerprint is written only after that check passes.

Format: docs/planning-trace-format.md.

drawtonomy-cr open

drawtonomy-cr open ./results            # a directory, or the scenario XML inside it

Sniffs the directory for the four files by content (<commonRoad, <CommonRoadSolution, drawtonomy-verdict/1, drawtonomy-planning-trace-v1), computes the verdict if it is missing and the checker is installed, serves the directory on http://127.0.0.1:<port>, prints the drawtonomy URL and opens it.

solution: planner_solution.xml
serving /home/me/results at http://127.0.0.1:53101
https://drawtonomy.com/?open=http%3A%2F%2F127.0.0.1%3A53101%2Fscenario.xml&solution=planner_solution.xml
Open the URL in Chrome or Firefox (Safari blocks http://127.0.0.1 from an https page).
Watching for changes. Press Ctrl+C to stop.

Then it watches: rerun your planner and the open tab reloads the solution, verdict and trace on its own (the scenario is not reloaded, the drawing is drawtonomy's side). The page subscribes to /events (Server-Sent Events); the CLI waits until a file's size and mtime hold still for 500 ms so a half-written solution is never served. A verdict the CLI computed is recomputed after every solution change; a verdict you placed yourself is never touched, so when only the solution changes the page drops the old checker result (it belonged to the previous solution) and shows it again once your verdict file is updated.

Only 127.0.0.1 is bound, only GET / HEAD / OPTIONS are answered, only the served directory is reachable (.. and absolute paths give 404), and Access-Control-Allow-Origin names one origin, never *.

flag
--solution / --verdict / --trace override the sniffed pick
--port N fixed port (default: a free one)
--no-browser print the URL without opening a browser
--copy print the file paths instead of serving them, for browsers that block http://127.0.0.1 from an https page (Safari); drop those files onto drawtonomy.com
--app-origin URL the origin allowed to read the files (default https://drawtonomy.com)

Without the checker there is simply no verdict: one line says so and the scenario opens with drawtonomy's own collision badge.

Protocol: docs/open-server-protocol.md.

Examples

examples/idm_planner/ is a one-file planner written for this package: the ego follows the centreline of its starting lanelet and IDM car-following sets its speed, with commonroad-io and numpy as the only dependencies. It is the smallest thing that can be connected, and its README explains the two modes it ships with.

examples/reactive_planner/ connects commonroad-reactive-planner end to end. Both are examples: replace the planner half with yours and keep the hand-off half.

Open the results in your browser

The output of both examples is committed under tests/fixtures/, and drawtonomy can open a CommonRoad file straight from GitHub through the ?open= URL parameter. Use the result link for solution/verdict identity checks, or the trace link to inspect the planner's plans. Nothing to install:

example scenario result result replay planning trace
reactive planner cut-in (cutin_commonroad.xml) PASS 7/7 result trace · trace with candidates
IDM planner, idm mode straight road (straight_commonroad.xml) FAIL, starts one step after the initial state (6/7) result trace
IDM planner, naive mode straight road FAIL, obstacle collision at 3.7 s (5/7) result trace
reactive planner cut-in as OpenSCENARIO (esmini cut-in.xosc) trace only — trace

Result links use ?open=<GitHub file URL>&solution=<file>&verdict=<file>. Trace links use &trace=<file> without a verdict: a trace alone cannot establish that a verdict belongs to the replayed solution. Combining a trace and verdict still shows the verdict as unverified. Companion paths are relative to the opened file. See tests/fixtures/ATTRIBUTION.md for fixture provenance and regeneration details.

The "trace with candidates" link replays the same cut-in with every candidate the reactive planner considered: 63 replanning cycles, 30 candidates each (20 feasible, 10 rejected), shown as a rank-coloured fan through the Candidates toggle; a trace without candidates simply shows no fan.

The last row opens the same planner result on the OpenSCENARIO original the CommonRoad scenario was converted from. A trace is not tied to CommonRoad: it says which actor it drives, and drawtonomy matches that against the scene. Address the track by "role": "ego" for a CommonRoad scenario (a planning problem is the ego, so it carries no name) and by "name": "<entity>" for an OpenSCENARIO one ("Ego" here). cutin_openscenario.planning-trace.json is planner_solution.planning-trace.json with that one field changed. Companions in another repository are given as full GitHub URLs, as that row does.

Contract documents

document what it specifies
docs/verdict-sidecar.md the drawtonomy-verdict/1 sidecar written by drawtonomy-cr verdict
docs/planning-trace-format.md the drawtonomy-planning-trace-v1 file written by TraceWriter
docs/open-server-protocol.md what drawtonomy-cr open serves, the URL it prints, and the /events stream

Development

pip install "drawtonomy-commonroad[test]"
pytest

Tests that need the official checker are skipped where it cannot be installed, so the suite runs everywhere. No Node toolchain is involved.

When the checker cannot be installed

If the [checker] extra cannot be installed on your machine, run the verdict step in a Linux x86_64 container:

docker run --rm --platform linux/amd64 -v "$PWD:/work" -w /work python:3.11 sh -c \
  'pip install "drawtonomy-commonroad[checker]" &&
   drawtonomy-cr verdict scenario.xml planner_solution.xml'

Without the checker, drawtonomy-cr verdict exits with code 3 and one line saying so, and drawtonomy-cr open serves the scenario without a verdict. open keeps watching for the verdict file under its expected name, so writing it from a container after open has started makes it appear in the tab.

License

Apache-2.0. See LICENSE.

日本語

Metadata

Release files for drawtonomy-commonroad 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for drawtonomy-commonroad 0.3.0
File Size Uploaded
drawtonomy_commonroad-0.3.0.tar.gz 964.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for drawtonomy-commonroad 0.3.0
File Interpreter ABI Platform
drawtonomy_commonroad-0.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 1.0 MB

Release files / drawtonomy_commonroad-0.3.0.tar.gz

Download URL drawtonomy_commonroad-0.3.0.tar.gz
Size 964.7 kB
Tags Source
SHA-256 checksum
How to use checksums
2c05d552b6bd27dcf789deead7c24652cde9da9b164111249302c792ba334478
BLAKE2b-256 checksum
How to use checksums
f1ea05898ebde11db11da75a0cd3caa6b7a92fb263178811a151c69c8c163c59
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.

Transparency log

Release files / drawtonomy_commonroad-0.3.0-py3-none-any.whl

Download URL drawtonomy_commonroad-0.3.0-py3-none-any.whl
Size 46.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
1dd0f1721bc26ebcf91ed1aa2a483169f263945fa197216413fe8b5d8d34252d
BLAKE2b-256 checksum
How to use checksums
db872076d9b1424f7c4e56a9a9012d42d4b7d1f0db288a33635c8a15cb15e11e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page