|
| 1 | +# Native ROS 2 topic reference |
| 2 | + |
| 3 | +This page lists every topic the native ROS 2 interface publishes and |
| 4 | +subscribes to when CARLA runs with `--ros2` (middleware selectable with |
| 5 | +`--rmw=fastdds|cyclonedds|zenoh`). The interface follows one scope rule: |
| 6 | +it exposes the data a real drive-by-wire vehicle would produce and accepts |
| 7 | +the control commands such a vehicle would accept. Simulation control |
| 8 | +(spawning, weather, synchronous ticking) stays in the Python API. |
| 9 | + |
| 10 | +Standard message types ship with every ROS 2 distribution. The |
| 11 | +`carla_msgs/*` types are the ones published from the bridge era in |
| 12 | +[ros-carla-msgs](https://github.com/carla-simulator/ros-carla-msgs); |
| 13 | +install that package on the ROS side to deserialize them. |
| 14 | + |
| 15 | +Topic names below are the ROS names. On the DDS wire each topic carries |
| 16 | +the standard `rt/` prefix (for example `rt/carla/map`), which ROS 2 tools |
| 17 | +hide. |
| 18 | + |
| 19 | +## Simulation-wide topics |
| 20 | + |
| 21 | +Published as soon as the simulator starts; no actor opt-in needed. |
| 22 | + |
| 23 | +| Topic | Type | QoS | Cadence | |
| 24 | +|-------|------|-----|---------| |
| 25 | +| `/clock` | `rosgraph_msgs/Clock` | volatile | every frame | |
| 26 | +| `/carla/map` | `std_msgs/String` | transient_local | once per episode | |
| 27 | +| `/carla/traffic_lights/info` | `carla_msgs/CarlaTrafficLightInfoList` | transient_local | once per episode | |
| 28 | +| `/carla/traffic_lights/status` | `carla_msgs/CarlaTrafficLightStatusList` | transient_local | on state change | |
| 29 | +| `/tf_static` | `tf2_msgs/TFMessage` | transient_local | on hero registration | |
| 30 | +| `/tf` | `tf2_msgs/TFMessage` | volatile | every frame | |
| 31 | + |
| 32 | +- `/carla/map` carries the full OpenDRIVE description of the current map, |
| 33 | + the same string `carla.Map.to_opendrive()` returns. Latched, so late |
| 34 | + joiners receive it without waiting for a map change. |
| 35 | +- `/carla/traffic_lights/info` describes every traffic light once per |
| 36 | + episode: actor id, world pose, and the trigger volume as a center |
| 37 | + relative to that pose plus a full box size, matching what the Python API |
| 38 | + exposes as `actor.trigger_volume`. |
| 39 | +- `/carla/traffic_lights/status` carries the state of every light |
| 40 | + (`RED=0, YELLOW=1, GREEN=2, OFF=3, UNKNOWN=4`). The full list is |
| 41 | + republished only when at least one light changed state; the latched |
| 42 | + sample keeps the current state available to late joiners between |
| 43 | + changes. |
| 44 | + |
| 45 | +## Ego vehicle topics |
| 46 | + |
| 47 | +Created when a vehicle with `role_name` `hero` is spawned. `<ros_name>` |
| 48 | +is the vehicle's `ros_name` attribute (defaults to `actor<id>` when |
| 49 | +unset). Destroying the vehicle removes the topics. |
| 50 | + |
| 51 | +| Topic | Direction | Type | QoS | Cadence | |
| 52 | +|-------|-----------|------|-----|---------| |
| 53 | +| `/carla/<ros_name>/odometry` | publish | `nav_msgs/Odometry` | volatile | every frame | |
| 54 | +| `/carla/<ros_name>/vehicle_status` | publish | `carla_msgs/CarlaEgoVehicleStatus` | volatile | every frame | |
| 55 | +| `/carla/<ros_name>/vehicle_info` | publish | `carla_msgs/CarlaEgoVehicleInfo` | transient_local | once at spawn | |
| 56 | +| `/carla/<ros_name>/vehicle_control_cmd` | subscribe | `carla_msgs/CarlaEgoVehicleControl` | volatile | consumer-driven | |
| 57 | +| `/carla/<ros_name>/ackermann_control_cmd` | subscribe | `ackermann_msgs/AckermannDriveStamped` | volatile | consumer-driven | |
| 58 | + |
| 59 | +- Odometry pose is ground truth in ROS coordinates with |
| 60 | + `frame_id: odom` and `child_frame_id: <ros_frame_id>`; the twist is |
| 61 | + expressed in the vehicle body frame. |
| 62 | +- Vehicle status carries speed, acceleration (computed from the velocity |
| 63 | + history), world orientation, and an echo of the last applied control. |
| 64 | +- Vehicle info is the latched static description from the vehicle physics |
| 65 | + control: mass, wheels, gearbox, center of mass. |
| 66 | + |
| 67 | +## TF tree |
| 68 | + |
| 69 | +The transform topics compose a REP-105 tree: |
| 70 | + |
| 71 | +``` |
| 72 | +map -> odom -> <vehicle frame> -> <sensor frames> |
| 73 | +``` |
| 74 | + |
| 75 | +- `map -> odom`: identity, latched on `/tf_static` when the hero vehicle |
| 76 | + registers. CARLA publishes ground truth, so the `odom` frame never |
| 77 | + drifts from `map`. |
| 78 | +- `odom -> <vehicle frame>`: published on `/tf` every frame for the hero |
| 79 | + vehicle. |
| 80 | +- `<parent frame> -> <sensor frame>`: published on `/tf` every frame for |
| 81 | + each sensor with ROS 2 enabled, where the parent is the actor the |
| 82 | + sensor is attached to (or `map` for unattached sensors). |
| 83 | + |
| 84 | +A sensor's frame defaults to its `ros_name` and can be overridden with |
| 85 | +the `ros_frame_id` attribute; per-actor TF publishing can be disabled |
| 86 | +with the `ros_publish_tf` attribute. |
| 87 | + |
| 88 | +## Sensor topics |
| 89 | + |
| 90 | +Sensor publishing is opt-in per actor: call `enable_for_ros()` on the |
| 91 | +sensor from the Python API (`ros2_native.py` in `PythonAPI/examples/ros2` |
| 92 | +does this for a whole sensor stack). The base name composes the |
| 93 | +attachment hierarchy: `/carla/<parent ros_name>/<sensor ros_name>` for an |
| 94 | +attached sensor, `/carla/<sensor ros_name>` otherwise. All sensor topics |
| 95 | +are volatile and publish at the sensor's own tick rate. |
| 96 | + |
| 97 | +| Sensor | Topics | Types | |
| 98 | +|--------|--------|-------| |
| 99 | +| RGB camera | `<base>/image`, `<base>/camera_info` | `sensor_msgs/Image`, `sensor_msgs/CameraInfo` | |
| 100 | +| Depth camera | `<base>/image`, `<base>/camera_info` | `sensor_msgs/Image`, `sensor_msgs/CameraInfo` | |
| 101 | +| Semantic segmentation camera | `<base>/image`, `<base>/camera_info` | `sensor_msgs/Image`, `sensor_msgs/CameraInfo` | |
| 102 | +| Instance segmentation camera | `<base>/image`, `<base>/camera_info` | `sensor_msgs/Image`, `sensor_msgs/CameraInfo` | |
| 103 | +| Normals camera | `<base>/image`, `<base>/camera_info` | `sensor_msgs/Image`, `sensor_msgs/CameraInfo` | |
| 104 | +| Optical flow camera | `<base>/image`, `<base>/camera_info` | `sensor_msgs/Image`, `sensor_msgs/CameraInfo` | |
| 105 | +| DVS camera | `<base>/image`, `<base>/camera_info`, `<base>/point_cloud` | `sensor_msgs/Image`, `sensor_msgs/CameraInfo`, `sensor_msgs/PointCloud2` | |
| 106 | +| LiDAR (ray cast) | `<base>/point_cloud` | `sensor_msgs/PointCloud2` | |
| 107 | +| Semantic LiDAR | `<base>/point_cloud` | `sensor_msgs/PointCloud2` | |
| 108 | +| Hybrid solid-state LiDAR | `<base>/point_cloud` | `sensor_msgs/PointCloud2` | |
| 109 | +| Radar | `<base>/point_cloud` | `sensor_msgs/PointCloud2` | |
| 110 | +| GNSS | `<base>` | `sensor_msgs/NavSatFix` | |
| 111 | +| IMU | `<base>` | `sensor_msgs/Imu` | |
| 112 | +| Collision | `<base>` | `carla_msgs/CarlaCollisionEvent` | |
| 113 | + |
| 114 | +Lane invasion, obstacle detection and RSS sensors have no native ROS 2 |
| 115 | +publisher; read them through the Python API. |
| 116 | + |
| 117 | +## QoS summary |
| 118 | + |
| 119 | +Every publisher is reliable with keep-last history. Topics marked |
| 120 | +transient_local above are latched with depth 1: a subscriber that joins |
| 121 | +late immediately receives the last published sample. Match the |
| 122 | +durability when echoing them, for example: |
| 123 | + |
| 124 | +```sh |
| 125 | +ros2 topic echo --qos-durability transient_local --qos-reliability reliable /carla/map |
| 126 | +``` |
0 commit comments