Skip to content
Draft
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions Docs/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
## Table of Contents
* [Unreleased — CARLA 0.10.0 / UE5 compatibility](#unreleased--carla-0100--ue5-compatibility)
* [CARLA ScenarioRunner 0.9.16](#carla-scenariorunner-0916)
* [CARLA ScenarioRunner 0.9.15](#carla-scenariorunner-0915)
* [CARLA ScenarioRunner 0.9.13](#carla-scenariorunner-0913)
Expand All @@ -13,6 +14,35 @@
* [CARLA ScenarioRunner 0.9.5](#carla-scenariorunner-095)
* [CARLA ScenarioRunner 0.9.2](#carla-scenariorunner-092)

## Unreleased — CARLA 0.10.0 / UE5 compatibility

This release extends ScenarioRunner to run against the **CARLA 0.10.0** server (UE5 / Chaos physics) while keeping full compatibility with **CARLA 0.9.x** (UE4 / PhysX). The default supported map on UE5 is `Town10HD_Opt`; other UE5 maps remain reachable for users who explicitly target them via their own configs, `--configFile`, or `--additionalScenario`.

### :rocket: New Features
* New `srunner/tools/carla_compat.py` runtime version-detection layer. Auto-detects the installed CARLA wheel and exposes `IS_UE5` / `IS_UE4` flags plus version-keyed lookup tables. The `SR_CARLA_VERSION` environment variable can force a version when the wheel disagrees with the running server.
* `CarlaDataProvider.create_blueprint` consults a version-keyed alias table on UE5, translating legacy blueprint ids (`vehicle.lincoln.mkz_2017`, `vehicle.audi.tt`, `vehicle.dodge.charger_police_2020`, `vehicle.carlamotors.carlacola`, …) to the 0.10.0 catalogue. The per-category fallback dict is also version-keyed so missing models degrade to a documented substitute instead of crashing.
* New `srunner/examples_ue5/` directory for Town10HD_Opt-targeted scenario configs. `srunner/tools/scenario_parser.py` reads `examples_ue5/*.xml` first on UE5 servers, then falls back to `examples/*.xml`, with per-scenario-name dedup so UE5 entries override their legacy siblings. Initial UE5 configs added for `FollowLeadingVehicle_1`, `FollowLeadingVehicleWithObstacle_1`, and `OtherLeadingVehicle_1`.

### :ghost: Maintenance
* `VehicleVelocityControl.__init__` skips the wheel-friction-zeroing setup on UE5. The Chaos `WheelPhysicsControl.friction_force_multiplier` parameter is documented but `apply_physics_control` silently discards wheel-attribute writes on the current 0.10.0 build, and no other documented UE5 API exposes per-wheel friction-override for this controller's kinematic-injection use. The UE4 `tire_friction = 0` path is unchanged.
* `RouteLightsBehavior` (in `srunner/scenariomanager/lights_sim.py`, used by `--route` mode) is now engine-aware. On UE5 it skips the removed `LightManager` API entirely: no `set_day_night_cycle` calls (UE5 has no auto sun motion to disable — `weather.sun_altitude_angle` is the documented day/night control, which `_get_night_mode` already drives off) and no per-street-light `turn_on`/`turn_off` enumeration (UE5 exposes no documented per-`Light` runtime toggle). Vehicle-light control (`Vehicle.set_light_state` / `get_light_state`) is preserved on both engines. On UE5 the behavior emits a one-time INFO log at construction so users know street lights are not being controlled.
* `MetricsParser` and `Osc2TraceParser` (in `srunner/metrics/tools/`) now branch the Physics Control block parsing on `IS_UE5`. On 0.9.x the existing PhysX path is unchanged. On 0.10.0 the new `srunner/metrics/tools/recorder_chaos.py` walker handles the rewritten Chaos serialization — scalar fields, `forward_gear_ratios` / `reverse_gear_ratios` lists, and the per-wheel `friction_force_multiplier` / `cornering_stiffness` / `max_brake_torque` / `affected_by_*` / `suspension_axis` set documented at `carla-ue5/Docs/python_api.md` §`carla.VehiclePhysicsControl` and §`carla.WheelPhysicsControl`. The parsers also walk past the new top-level recorder sections introduced by the 0.10.0 server (`Vehicle door animations`, `Weathers`, `Walkers Bones`) so downstream blocks remain reachable. PhysX-only fields (`MOI`, `damping_rate*`, `clutch_strength`, `use_gear_autobox`) are not invented out of Chaos data — they are absent from the resulting `VehiclePhysicsControl` on UE5.
* `RosAgent.publish_can` (in `srunner/autoagents/ros_agent.py`) drops the PhysX-only physics block on UE5. The `CarlaEgoVehicleInfo` message schema is modelled on the removed PhysX fields (`tire_friction`, `damping_rate`, `moi`, `damping_rate_full_throttle`, `damping_rate_zero_throttle_clutch_disengaged`, `use_gear_autobox`, `clutch_strength`); the Chaos struct exposes a different set with different semantics, so there is no faithful field-by-field port — downstream ROS consumers parse PhysX semantics. On UE5 the agent emits a one-time deprecation warning pointing at the native CARLA ROS 2 bridge (the supported ROS path going forward) and populates only the fields that survived (`mass`, `drag_coefficient`, `center_of_mass`). UE4 behavior is unchanged.
* New carla-free unit suites — `tests/test_carla_compat.py` (16 tests: env override, `IS_UE5` thresholding, blueprint-id aliases, category fallbacks across both engines) and `tests/test_recorder_chaos.py` (25 tests: Chaos wheel-line tokenizer, Physics Control block walker, end-to-end `MetricsParser` / `Osc2TraceParser` runs against a committed 0.10.0 recorder fixture at `tests/fixtures/recorder_ue5_town10.txt`). Installs a stub `carla` module so the tests run in any Python env without a CARLA wheel installed.

### :wrench: Behavior delta on UE5
* `VehicleVelocityControl` on UE5 continues to track heading-aligned `set_target_velocity` calls tightly (measured 101% of target over 5 s @ 1 m/s along the vehicle's forward axis); sharp lateral / cornering motion tracks less faithfully than on UE4 because wheel lateral friction cannot currently be suppressed. Tracked upstream in carla-ue5.
* `RouteLightsBehavior` no longer controls street lights on UE5. Vehicle headlights / position lights still flip on and off based on `weather.sun_altitude_angle` (validated live: state `Position|LowBeam` set under sun_altitude=-30°, cleared under sun_altitude=75°).
* Legacy bicycle / motorbike blueprints are absent from the 0.10.0 catalogue; the alias table substitutes a four-wheel vehicle so spawns succeed, but two-wheeler scenarios lose their visual identity until upstream content lands.
* The offline `MetricsParser` / `Osc2TraceParser` `physics_control` shape differs between engines. On 0.9.x it returns a `VehiclePhysicsControl` populated with PhysX fields (`tire_friction`, `damping_rate`, `forward_gears`, …). On 0.10.0 it returns a Chaos-shaped `VehiclePhysicsControl` (`friction_force_multiplier`, `cornering_stiffness`, `max_brake_torque`, `forward_gear_ratios`, …). Metric scripts that read these structs must branch on `srunner.tools.carla_compat.IS_UE5` to interpret the right field set. A subset of Chaos list fields (`forward_gear_ratios`, `reverse_gear_ratios`) is settable but currently not readable from Python on the 0.10.0 wheel under test — an upstream `boost::python` to-Python converter gap, not a parser issue.
* The legacy `RosAgent` (`srunner/autoagents/ros_agent.py`) omits PhysX-only vehicle-info fields on UE5 and logs a one-time deprecation warning. Users on 0.10.0 should consume telemetry via the native CARLA ROS 2 bridge instead of the legacy `CarlaEgoVehicleInfo` schema.

### :bug: Bug Fixes
* Fixed a latent bug in `CarlaDataProvider.create_blueprint`: when the requested model id was missing and the per-category fallback id was also missing (empty filter result), the fallback path raised an uncaught `ValueError: 'a' cannot be empty` from `np.random.choice([])`. The fallback now degrades gracefully (fallback → `vehicle.*` → explicit diagnostic `ValueError`).

### :white_check_mark: Validation
* End-to-end validated on a live CARLA 0.10.0 server (Town10HD_Opt) with the full compat stack integrated: `FollowLeadingVehicle_1` (60.05s game), `FollowLeadingVehicleWithObstacle_1` (120.05s game), and `OtherLeadingVehicle_1` (80.05s game) all run spawn → behavior-tree tick → criteria evaluation → result reporting. `CollisionTest` reports `SUCCESS` on every run; the `TIMEOUT` global result is expected in `--scenario` mode without `--agent`.

## CARLA ScenarioRunner 0.9.16

### :rocket: New Features
Expand Down
37 changes: 37 additions & 0 deletions Docs/getting_scenariorunner.md
Original file line number Diff line number Diff line change
Expand Up @@ -254,5 +254,42 @@ python scenario_runner.py --help

---

## Running against CARLA 0.10.0 (UE5)

ScenarioRunner supports both **CARLA 0.9.x** (UE4 / PhysX) and **CARLA 0.10.0+** (UE5 / Chaos) from the same source tree. The engine is auto-detected at runtime from the installed `carla` wheel; no code path needs to be selected by hand.

__1. Install the matching CARLA 0.10.0 wheel.__ Use a Python ≥ 3.8 environment and install the `carla-0.10.0-*.whl` shipped with the 0.10.0 server build, then `pip install -r requirements.txt` from this repository.

__2. Default supported map: `Town10HD_Opt`.__ The bundled UE5 example configs target `Town10HD_Opt` only. Other UE5 maps that ship with the server (e.g. `Town15`, `Mine_01`) remain reachable: target them with your own configs via `--configFile` / `--additionalScenario`.

__3. Auto-detected blueprint translation.__ Legacy 0.9.x blueprint ids (e.g. `vehicle.lincoln.mkz_2017`, `vehicle.audi.tt`, `vehicle.dodge.charger_police_2020`) are translated to their 0.10.0 catalogue equivalents on the fly. Bicycle / motorbike blueprints are absent in 0.10.0 and substituted with a four-wheel vehicle so spawns succeed.

__4. Version override (advanced).__ If the running server disagrees with the installed wheel, force the detection with the `SR_CARLA_VERSION` environment variable:

```sh
export SR_CARLA_VERSION=0.10.0 # force UE5 / Chaos code path
export SR_CARLA_VERSION=0.9.16 # force UE4 / PhysX code path
```

__5. Example run against a UE5 server.__

```sh
# Launch the 0.10.0 server in another terminal first
python scenario_runner.py --scenario FollowLeadingVehicle_1 --reloadWorld --sync
```

The runner picks up `srunner/examples_ue5/FollowLeadingVehicle.xml` (Town10HD_Opt) on a UE5 server, and falls back to `srunner/examples/FollowLeadingVehicle.xml` (Town01) on a 0.9.x server.

### Behavior deltas on UE5

A small number of UE4-only APIs have no working UE5 replacement and are dropped on the UE5 code path. See [CHANGELOG](CHANGELOG.md) for the full inventory.

* `VehicleVelocityControl` (used by the OpenSCENARIO 2.0 `follow_trajectory` modifier with `control: "velocity"`) tracks heading-aligned trajectories tightly on UE5 but degrades on sharp lateral / cornering moves because Chaos exposes no working API to zero wheel friction.
* `RouteLightsBehavior` (used by `--route` mode) does not control street lights on UE5. The removed `LightManager` API has no UE5 replacement. Vehicle headlights / position lights still respond to night vs. day weather (via `weather.sun_altitude_angle`).
* The offline `MetricsParser` / `Osc2TraceParser` `physics_control` event returns a Chaos-shaped `VehiclePhysicsControl` on UE5 (`friction_force_multiplier`, `cornering_stiffness`, `max_brake_torque`, `forward_gear_ratios`, …) instead of the PhysX-shaped one on 0.9.x. Metric scripts that read these structs must branch on `srunner.tools.carla_compat.IS_UE5` to interpret the right field set.
* The legacy `RosAgent` (`srunner/autoagents/ros_agent.py`) omits PhysX-only `CarlaEgoVehicleInfo` fields on UE5 (`tire_friction`, `damping_rate`, `moi`, `clutch_strength`, `use_gear_autobox`, `damping_rate_*`) and emits a one-time deprecation warning. Use the native CARLA ROS 2 bridge that ships with 0.10.0 for full physics telemetry.

---

Thus concludes the installation process for ScenarioRunner. In case any unexpected error or issue occurs, the [CARLA forum](https://forum.carla.org/c/using-carla/scenario-runner) is open to everybody. There is an _ScenarioRunner_ category to post problems and doubts regarding this module.

62 changes: 44 additions & 18 deletions srunner/autoagents/ros_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
)

from srunner.autoagents.autonomous_agent import AutonomousAgent
from srunner.tools.carla_compat import IS_UE5


class RosAgent(AutonomousAgent):
Expand Down Expand Up @@ -358,24 +359,49 @@ def publish_can(self, sensor_id, data):
self.vehicle_info_publisher = rospy.Publisher(
'/carla/ego_vehicle/vehicle_info', CarlaEgoVehicleInfo, queue_size=1, latch=True)
info_msg = CarlaEgoVehicleInfo()
for wheel in data['wheels']:
wheel_info = CarlaEgoVehicleInfoWheel()
wheel_info.tire_friction = wheel['tire_friction']
wheel_info.damping_rate = wheel['damping_rate']
wheel_info.steer_angle = wheel['steer_angle']
wheel_info.disable_steering = wheel['disable_steering']
info_msg.wheels.append(wheel_info)
info_msg.max_rpm = data['max_rpm']
info_msg.moi = data['moi']
info_msg.damping_rate_full_throttle = data['damping_rate_full_throttle']
info_msg.damping_rate_zero_throttle_clutch_disengaged = data['damping_rate_zero_throttle_clutch_disengaged']
info_msg.use_gear_autobox = data['use_gear_autobox']
info_msg.clutch_strength = data['clutch_strength']
info_msg.mass = data['mass']
info_msg.drag_coefficient = data['drag_coefficient']
info_msg.center_of_mass.x = data['center_of_mass']['x']
info_msg.center_of_mass.y = data['center_of_mass']['y']
info_msg.center_of_mass.z = data['center_of_mass']['z']
if IS_UE5:
# CARLA 0.10.0 (UE5 / Chaos) removed every PhysX-shaped field this
# message schema was modelled on (tire_friction, damping_rate, moi,
# damping_rate_full_throttle, damping_rate_zero_throttle_clutch_disengaged,
# use_gear_autobox, clutch_strength). The Chaos struct exposes a
# different set with different semantics (friction_force_multiplier,
# cornering_stiffness, max_brake_torque, forward_gear_ratios, ...) so
# there is no faithful field-by-field port — downstream ROS consumers
# parse PhysX semantics. We populate only the fields that survived
# (mass, drag_coefficient, center_of_mass) and leave the rest at
# their CarlaEgoVehicleInfo defaults. CARLA 0.10.0 ships a native
# ROS 2 bridge that is the supported ROS path going forward.
if not getattr(self, "_ros_agent_ue5_warned", False):
rospy.logwarn(
"RosAgent: omitting PhysX-only vehicle info fields on "
"CARLA 0.10.0 (UE5/Chaos) — use the native CARLA ROS 2 "
"bridge for full physics telemetry."
)
self._ros_agent_ue5_warned = True
info_msg.mass = data['mass']
info_msg.drag_coefficient = data['drag_coefficient']
info_msg.center_of_mass.x = data['center_of_mass']['x']
info_msg.center_of_mass.y = data['center_of_mass']['y']
info_msg.center_of_mass.z = data['center_of_mass']['z']
else:
for wheel in data['wheels']:
wheel_info = CarlaEgoVehicleInfoWheel()
wheel_info.tire_friction = wheel['tire_friction']
wheel_info.damping_rate = wheel['damping_rate']
wheel_info.steer_angle = wheel['steer_angle']
wheel_info.disable_steering = wheel['disable_steering']
info_msg.wheels.append(wheel_info)
info_msg.max_rpm = data['max_rpm']
info_msg.moi = data['moi']
info_msg.damping_rate_full_throttle = data['damping_rate_full_throttle']
info_msg.damping_rate_zero_throttle_clutch_disengaged = data['damping_rate_zero_throttle_clutch_disengaged']
info_msg.use_gear_autobox = data['use_gear_autobox']
info_msg.clutch_strength = data['clutch_strength']
info_msg.mass = data['mass']
info_msg.drag_coefficient = data['drag_coefficient']
info_msg.center_of_mass.x = data['center_of_mass']['x']
info_msg.center_of_mass.y = data['center_of_mass']['y']
info_msg.center_of_mass.z = data['center_of_mass']['z']
self.vehicle_info_publisher.publish(info_msg)
msg = CarlaEgoVehicleStatus()
msg.header = self.get_header()
Expand Down
23 changes: 23 additions & 0 deletions srunner/examples_ue5/FollowLeadingVehicle.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0"?>
<!--
CARLA 0.10.0 / UE5 overrides for the FollowLeadingVehicle scenario set.
The legacy srunner/examples/FollowLeadingVehicle.xml targets Town01-Town05,
which do not ship with 0.10.0. Spawn points below were picked from
Town10HD_Opt with >= 35 m of clear road before the next junction so the
lead vehicle has room to be placed ahead via
get_waypoint_in_distance(stop_at_junction=True).

The ego model keeps the legacy id 'vehicle.lincoln.mkz_2017'; the
srunner/tools/carla_compat alias map translates it to
'vehicle.lincoln.mkz' on UE5, so this config also works unchanged on
0.9.x servers if you point SCENARIO_RUNNER_ROOT at this directory.
-->
<scenarios>
<scenario name="FollowLeadingVehicle_1" type="FollowLeadingVehicle" town="Town10HD_Opt">
<ego_vehicle x="-110.96" y="59.69" z="0.60" yaw="90.64" model="vehicle.lincoln.mkz_2017" />
<weather cloudiness="0" precipitation="0" precipitation_deposits="0" wind_intensity="0" sun_azimuth_angle="0" sun_altitude_angle="75" />
</scenario>
<scenario name="FollowLeadingVehicleWithObstacle_1" type="FollowLeadingVehicleWithObstacle" town="Town10HD_Opt">
<ego_vehicle x="-110.96" y="59.69" z="0.60" yaw="90.64" model="vehicle.lincoln.mkz_2017" />
</scenario>
</scenarios>
14 changes: 14 additions & 0 deletions srunner/examples_ue5/LeadingVehicle.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0"?>
<!--
CARLA 0.10.0 / UE5 overrides for the OtherLeadingVehicle scenario set.
The legacy srunner/examples/LeadingVehicle.xml targets Town04, which does
not ship with 0.10.0. Spawn points below were picked from Town10HD_Opt
with >= 35 m of clear road AND a same-direction left lane so the parallel
lane vehicle can be placed alongside the ego.
-->
<scenarios>
<scenario name="OtherLeadingVehicle_1" type="OtherLeadingVehicle" town="Town10HD_Opt">
<ego_vehicle x="-24.34" y="-57.79" z="0.60" yaw="0.60" model="vehicle.lincoln.mkz_2017" />
<weather cloudiness="0" precipitation="0" precipitation_deposits="0" wind_intensity="0" sun_azimuth_angle="0" sun_altitude_angle="75" />
</scenario>
</scenarios>
Loading