Skip to content

feat(autoware_demo): add --spawn_pose for maps without usable spawn points - #37

Draft
youtalk wants to merge 1 commit into
feat/ue58-run-map-originfrom
feat/ue58-demo-spawn-pose
Draft

feat(autoware_demo): add --spawn_pose for maps without usable spawn points#37
youtalk wants to merge 1 commit into
feat/ue58-run-map-originfrom
feat/ue58-demo-spawn-pose

Conversation

@youtalk

@youtalk youtalk commented Sep 5, 2026

Copy link
Copy Markdown
Owner

CI status on the fork. Ubicloud-PR runs two jobs and both are green. Python tools and shell scripts exercises exactly one of this PR's four changed files: shellcheck -S warning over run/*.sh lints the edited run_carla_autoware.sh. Its pytest step covers map_tools/tests only, so the three unit tests this PR adds under PythonAPI/test/unit/ are not run by any fork job — they were run locally and their output is quoted below. Ubuntu 24.04 / Build runs inside ghcr.io/youtalk/carla-ue5-toolchain:ue58-24.04 and completes; it compiles LibCarla and runs the gtest binaries, neither of which touches this change. Nothing in the CI configuration was disabled, skipped or weakened.

Description

Problem. autoware_demo.py can place the ego only on one of the level's own spawn points, selected by --spawn_index. A map that ships none therefore offers no way to start at all, and a map that ships exactly one fixes every run to the same start pose. Neither case is unusual for an imported map: spawn points are authored content, and a digital twin imported from OpenDRIVE plus lanelet2 arrives with whatever its converter happened to emit.

The concrete case. The AWSIM Nishi-Shinjuku level exposes exactly one CARLA spawn point (ego_spawn_points: 1, ~/ue58-logs/p3/01-map-probe.txt). Reproducible gate cells need a specific start pose chosen to suit the route being measured — in this work, a pose derived from the map's own lanelet2 geometry so that the start and the goal are expressed in the same frame the stack localises in. With only --spawn_index available there is no way to ask for one.

Change. Add --spawn_pose "X,Y,Z,YAW" to autoware_demo.py — CARLA metres and degrees — which overrides --spawn_index, and pass it through run_carla_autoware.sh as --spawn-pose, mutually exclusive with --spawn-index. Three unit tests cover the new parser. The spawn-selection block continues to prefer the level's ego spawn points and to fall back as before when no pose is given, so the default path is unchanged.

One implementation detail worth a reviewer's attention. The composed command uses the --spawn_pose=<value> form rather than a separate argv word. That is not cosmetic: see the note under "Where has this been tested?".

Where has this been tested?

  • Platform(s): Ubuntu 24.04, x86_64
  • Python version(s): 3.12 (host client), 3.10/3.12 inside the Autoware containers
  • Unreal Engine version(s): UE 5.8, CARLA fork CarlaUnreal/UnrealEngine@ue58-dev-carla cacb25b99f14

Unit tests, run locally. python -m pytest PythonAPI/test/unit/test_autoware_demo_args.py — 3 tests covering parse_spawn_pose, including that "1,2,3" (three fields instead of four) raises argparse.ArgumentTypeError. They were written before the implementation and were confirmed to fail with AttributeError against the parent commit, and to fail again when extracted and run against the unmodified autoware_demo.py. The suite's two pre-existing failures elsewhere in PythonAPI/test/unit (test_vehicle's moi attribute and test_client's version string) are present identically on the parent commit and are untouched by this change. No fork CI job runs this directory, as stated at the top.

Live, three full closed-loop cells on Nishi-Shinjuku. Every cell passed --spawn-pose "-278.383,220.550,-0.975,-33.780" with --goal "-84.114,117.602,-10.442" and reached routing state 3 = ARRIVED: N-content (~/ue58-logs/p3-10-cell-nishi-content/), N-fallback (~/ue58-logs/p3-11-cell-nishi-fallback/) and N-humble (~/ue58-logs/p3-12-cell-nishi-humble/). Gate verdicts are in each cell's gates/gates.txt.

The requested pose is the pose the vehicle got, checked against a second representation of the road. The XY and yaw were derived offline from the lanelet2 centreline (lanelet 255 at s = 7.477, ~/ue58-logs/p3/11-spawn-derivation.txt) and then cross-checked live against CARLA's OpenDRIVE waypoints (Map.get_waypoint, lane_type=Driving, ~/ue58-logs/p3/12-poses.txt): nearest waypoint -278.366, 220.557 on road 108 / lane 2, lateral distance 0.018 m, yaw difference +0.09°, against thresholds of 0.5 m and 5°. The two sides of that comparison are produced by independent pipelines — a lanelet2 reader and CARLA's own OpenDRIVE map — so a frame or converter error would show as a multi-metre gap rather than 18 mm on a ~3.5 m lane. The Z component is the live ground height plus 0.3 m: cast_ray returned ground_z = -1.274694800376892 and the pose carries -0.975.

A defect this feature found in itself, caught only by a live run. The first N-content attempt produced no ego vehicle and no gate verdicts. run_carla_autoware.sh composed ${SPAWN_POSE:+ --spawn_pose $SPAWN_POSE}, so the value arrived as a separate argv word; Nishi's pose begins with - and is not a bare negative number, so argparse rejected it and autoware_demo.py died at parse time with argument --spawn_pose: expected one argument (~/ue58-logs/p3-10-cell-nishi-content-FAILED-argv/autoware_demo.log). A dry run cannot catch this: it prints the composed command string and never hands it to a parser, so a text-level review of the printed line passes while the bug is live — and the printed line is not even a faithful rendering of the executed argv, because the dry-run display re-wraps an already-quoted string. Fixed here by switching to the = form, and verified at the parser level rather than by text match: the command was composed the way the script composes it and the resulting argv fed to autoware_demo.py's real parsers, where the new form parses and the old form splits into four words and raises.

Limits of the live evidence, stated plainly. One map, one pose, one route, one build; three cells differing in level state and ROS distro, not in the pose. N-humble's G3 control gate reports FAIL at 36.33 Hz; that is a property of how the gate scores its measurement — it returns only the last rate window, and an intermittent duplicate-delivery burst on control_cmd contaminates windows in all three cells — and is unrelated to this change.

Possible Drawbacks

  • Z is the caller's responsibility. The demo does not probe the ground height at (X, Y). A Z below the surface drops the vehicle through the map and a Z far above it makes the vehicle fall, in both cases before the stack has anything to localise. The cells above obtained Z from a separate cast_ray probe; nothing in this change does that for the user.
  • YAW is unvalidated beyond being a number. A pose that is geometrically on the road but facing the wrong way produces a route the planner cannot follow, and the failure surfaces well downstream of the flag.
  • The pose grammar is now maintained in two places. run_carla_autoware.sh validates X,Y,Z,YAW with a shell regex and autoware_demo.py validates it again in parse_spawn_pose. This is defence in depth rather than a defect — the demo is usable directly — but the two must be kept in step.
  • Mutual exclusion is enforced, precedence is not silent. --spawn-pose and --spawn-index cannot be given together at the shell level, and --spawn_pose overrides --spawn_index at the Python level. A caller invoking the demo directly with both gets the pose, without a warning.

…oints

autoware_demo.py can only place the ego on one of the level's spawn
points, so a map that ships none offers no way to start at all, and a map
that ships a single one fixes every run to the same start. The AWSIM
Nishi-Shinjuku level is the latter: one spawn point, and no way to aim a
run at a goal derived from the map's own lanelet2 geometry.

Add --spawn_pose "X,Y,Z,YAW" (CARLA metres and degrees), which overrides
--spawn_index, and pass it through run_carla_autoware.sh as --spawn-pose,
mutually exclusive with --spawn-index. Z is the caller's responsibility:
the demo does not probe the ground height at (X, Y).

Signed-off-by: Yutaka Kondo <yutaka.kondo@youtalk.jp>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant