CARLA
Loading...
Searching...
No Matches
ROS2.h
Go to the documentation of this file.
1// Copyright (c) 2026 Computer Vision Center (CVC) at the Universitat Autonoma
2// de Barcelona (UAB).
3//
4// This work is licensed under the terms of the MIT license.
5// For a copy, see <https://opensource.org/licenses/MIT>.
6
7#pragma once
8
9#include "carla/Buffer.h"
10#include "carla/BufferView.h"
16
17#include <atomic>
18#include <memory>
19#include <mutex>
20#include <string>
21#include <unordered_map>
22#include <unordered_set>
23#include <vector>
24
25// forward declarations
26class AActor;
27namespace carla {
28 namespace geom {
29 class GeoLocation;
30 struct Vector3D;
31 }
32 namespace sensor {
33 namespace data {
34 struct DVSEvent;
35 class LidarData;
37 class RadarData;
38 }
39 namespace s11n {
40 struct VehicleStatusData;
41 }
42 }
43}
44
45namespace carla {
46namespace ros2 {
47
48class BasePublisher;
49class BaseSubscriber;
50class AutowareVehicleStatusPublisher;
51class CarlaCameraPublisher;
52class CarlaClockPublisher;
53class CarlaTransformPublisher;
54class BasicSubscriber;
55class BasicPublisher;
56
57class ROS2 {
58public:
59 // deleting copy constructor for singleton
60 ROS2(const ROS2 &obj) = delete;
61 static std::shared_ptr<ROS2> GetInstance() {
62 if (!_instance)
63 _instance = std::shared_ptr<ROS2>(new ROS2);
64 return _instance;
65 }
66
67 // general
68 /// Enable or disable ROS 2 publishing. When enabling, @a middleware selects the
69 /// DDS middleware; it must have been compiled into the shared library.
70 /// @a domain_id selects the ROS 2 domain id for the chosen middleware;
71 /// kUnsetDomainId (the default) keeps each middleware's native default.
72 /// @return true on success, false if the requested middleware is unavailable
73 /// (ROS 2 is then left disabled).
74 bool Enable(bool enable, Middleware middleware = Middleware::FastDDS,
75 int domain_id = kUnsetDomainId);
76 void Shutdown();
77 bool IsEnabled() { return _enabled; }
78 void SetFrame(uint64_t frame);
79 void SetTimestamp(double timestamp);
80
81 // Global TF gate (tier4 port): when false, no sensor broadcasts its
82 // transform on /tf. Complements the per-sensor publish_tf flag set at
83 // RegisterSensor time; both must be true for a transform to go out.
84 // Exposed to the client through World.set_publish_tf (later phase).
85 void SetPublishTF(bool publish_tf) { _publish_tf = publish_tf; }
86 bool GetPublishTF() const { return _publish_tf.load(); }
87
88 // actor registration API: replaces the legacy AddActorRosName /
89 // GetActorRosName / GetActorParentRosName surface that PR-2 stubbed and
90 // PR-4 retired. The plugin calls RegisterSensor / RegisterVehicle when an
91 // actor spawns and Unregister* when it destroys; ROS2 builds the topic
92 // names, owns per-sensor publishers + TF, and routes subscriber
93 // callbacks. The vehicle gets exactly one control subscriber: the Ackermann
94 // subscriber when enable_ackermann_control is true, otherwise the direct
95 // VehicleControl one. The two control topics are mutually exclusive so they
96 // cannot contend frame to frame.
97 void RegisterSensor(
98 void *actor, std::string ros_name, std::string frame_id, bool publish_tf);
99 void UnregisterSensor(void *actor);
100 // The vehicle gets exactly one control subscriber. enable_autoware_control
101 // wins over enable_ackermann_control (tier4 gave the Autoware command path
102 // priority); it wires the six /control/command/* + /vehicle/engage
103 // subscribers and marks the vehicle as the Autoware ego so
104 // ProcessDataFromStatusSensor accepts its status stream. Default behavior
105 // (both flags false) is unchanged for non-Autoware users.
106 void RegisterVehicle(
107 void *actor, std::string ros_name, std::string frame_id, ActorCallback callback,
108 bool enable_ackermann_control = false,
109 bool enable_autoware_control = false);
110 void UnregisterVehicle(void *actor);
111
112 // Exact-topic-name override (tier4 port of the ros_topic_name attribute
113 // flow). When set (non-empty), the actor's publishers/subscribers bind to
114 // "rt[/]<ros_topic_name>" instead of the "rt/carla/[parent/]ros_name"
115 // convention; multi-topic sensors still append their per-topic suffixes.
116 // The UE side reads the blueprint's "ros_topic_name" attribute and calls
117 // AddActorRosTopicName before the first data tick (next phase); Remove also
118 // drops the actor's cached publishers so a re-registration rebinds cleanly.
119 void AddActorRosTopicName(void *actor, std::string ros_topic_name);
120 void RemoveActorRosTopicName(void *actor);
121 std::string GetActorRosTopicName(void *actor) const;
122
123 // Topic-hierarchy seam used by the plugin's attach_actor path: tells ROS2
124 // that `actor` should publish under `parent`'s ros_name prefix. Walking
125 // the parent chain is the publisher-side concern.
126 void AddActorParentRosName(void *actor, void *parent);
127
128 // Demo subscriber callbacks (only compiled when WITH_ROS2_DEMO).
129 void RemoveBasicSubscriberCallback(void *actor);
131 void *actor, std::string ros_name, ActorMessageCallback callback);
132
133 // enabling streams to publish
135 std::lock_guard<std::mutex> lock(_mutex);
136 _publish_stream.insert(id);
137 }
139 std::lock_guard<std::mutex> lock(_mutex);
140 return _publish_stream.count(id) > 0;
141 }
143 std::lock_guard<std::mutex> lock(_mutex);
144 _publish_stream.clear();
145 }
146
147 // receiving data to publish
149 uint64_t sensor_type,
151 const carla::geom::Transform sensor_transform,
152 int W, int H, float Fov,
153 const carla::SharedBufferView buffer,
154 void *actor = nullptr);
156 uint64_t sensor_type,
158 const carla::geom::Transform sensor_transform,
159 const carla::geom::GeoLocation &data,
160 void *actor = nullptr);
162 uint64_t sensor_type,
164 const carla::geom::Transform sensor_transform,
165 carla::geom::Vector3D accelerometer,
166 carla::geom::Vector3D gyroscope,
167 float compass,
168 void *actor = nullptr);
170 uint64_t sensor_type,
172 const carla::geom::Transform sensor_transform,
173 const carla::SharedBufferView buffer,
174 int W, int H, float Fov,
175 void *actor = nullptr);
176 // Legacy overload: publishes the plain XYZI PointCloud2 layout. Kept so
177 // call sites without a sensor description still compile/work.
179 uint64_t sensor_type,
181 const carla::geom::Transform sensor_transform,
183 void *actor = nullptr);
184 // tier4 autoware-support overload: when the caller provides the sensor's
185 // channel count and vertical FOV limits (degrees), the publisher emits the
186 // extended Autoware XYZIRCAEDT layout instead of plain XYZI (requires
187 // channel_count >= 2 to derive per-channel elevations; falls back to XYZI
188 // otherwise).
190 uint64_t sensor_type,
192 const carla::geom::Transform sensor_transform,
193 uint32_t channel_count,
194 float upper_fov_limit,
195 float lower_fov_limit,
197 void *actor = nullptr);
199 uint64_t sensor_type,
201 const carla::geom::Transform sensor_transform,
203 void *actor = nullptr);
205 uint64_t sensor_type,
207 const carla::geom::Transform sensor_transform,
209 void *actor = nullptr);
211 uint64_t sensor_type,
213 const carla::geom::Transform sensor_transform,
214 AActor *first_actor,
215 AActor *second_actor,
216 float distance,
217 void *actor = nullptr);
219 uint64_t sensor_type,
221 const carla::geom::Transform sensor_transform,
222 uint32_t other_actor,
223 carla::geom::Vector3D impulse,
224 void *actor);
225 // Vehicle-status stream (Autoware): decodes the packed status sample into
226 // the six /vehicle/status/* report publishers. `vehicle_actor` is the
227 // parent vehicle the status sensor is attached to (must be registered with
228 // enable_autoware_control); `actor` is the sensor actor itself.
230 uint64_t sensor_type,
232 const carla::geom::Transform sensor_transform,
234 void *vehicle_actor,
235 void *actor);
236 // Autoware GNSS: publishes the sensor world transform (+ MGRS map offset)
237 // as <base>/pose and <base>/pose_with_covariance instead of NavSatFix.
239 uint64_t sensor_type,
241 const carla::geom::Transform sensor_transform,
242 const carla::geom::GeoLocation &data,
243 const carla::geom::Transform &sensor_world_transform,
244 const double mgrs_offset_position[3],
245 void *actor = nullptr);
246
247private:
249 std::string ros_name;
250 std::string frame_id;
251 bool publish_tf{true};
252 };
253
254 struct Stamp {
255 int32_t seconds{0};
256 uint32_t nanoseconds{0};
257 };
258
259 // Takes _mutex.
260 Stamp GetStamp() const;
261
262 // The helpers below up to ResolveAutoStreamSuffix expect _mutex to be held
263 // by the caller, except the GetOrCreate* factories and PublishTransform,
264 // which take it themselves.
265 void UnregisterSensorLocked(void *actor);
266 void DropPublishersLocked(void *actor);
267 // True while the actor is registered or carries a topic override; late
268 // deliveries for destroyed actors must not re-create their publishers.
269 bool IsKnownActorLocked(void *actor) const;
270
271 // Resolves an actor's `rt/carla/[parent/]ros_name` base topic by walking the
272 // parent chain. Returns empty if the actor is not registered.
273 std::string BuildBaseTopicName(void *actor) const;
274 // True when the actor carries a non-empty ros_topic_name override, i.e.
275 // BuildBaseTopicName returns an exact user-chosen topic. Single-topic
276 // publishers then skip their conventional suffix (tier4 semantics).
277 bool HasTopicOverride(void *actor) const;
278 std::string LookupRosName(void *actor) const;
279 std::string LookupFrameId(void *actor) const;
280 std::string BuildParentChain(void *actor) const;
281
282 // Lazy-creates the per-sensor publisher matching `type` (an ESensors enum
283 // declared in ROS2.cpp). Returns the BasePublisher pointer; the caller
284 // dynamic_pointer_casts to the concrete subtype for typed Write() calls.
285 std::shared_ptr<BasePublisher> GetOrCreateSensor(
286 int type, carla::streaming::detail::stream_id_type id, void *actor);
287
288 // Lazy-creates the per-sensor transform publisher, gated on the actor's
289 // publish_tf flag (set at RegisterSensor time). Returns nullptr if the
290 // sensor opted out.
291 std::shared_ptr<CarlaTransformPublisher> GetOrCreateTransformPublisherLocked(void *actor);
292
293 // Broadcasts the sensor transform on /tf. Resolves the publisher and frame
294 // names under the lock, then writes outside it.
295 void PublishTransform(
296 void *actor, const Stamp &stamp, const carla::geom::Transform &sensor_transform);
297
298 // Camera-side counterpart of GetOrCreateSensor for publishers that inherit
299 // CarlaCameraPublisher (the RGB / Depth / SS / IS / Normals / OpticalFlow
300 // unified base). DVS uses its own composite via GetOrCreateSensor.
301 template <typename CameraT>
302 std::shared_ptr<CarlaCameraPublisher> GetOrCreateCameraSensor(
304 void *actor,
305 const std::string &default_prefix);
306
307 // Resolves a `prefix__` placeholder by appending the stream id, persisting
308 // the resolved name in `_registrations` so subsequent lookups see it.
310 void *actor, const std::string &prefix, carla::streaming::detail::stream_id_type id);
311
312 // singleton
313 ROS2() = default;
314
315 static std::shared_ptr<ROS2> _instance;
316
317 // Camera readbacks publish from parallel render-thread workers while the
318 // game thread registers and destroys actors, so the maps below and the
319 // stamp are guarded by this mutex.
320 mutable std::mutex _mutex;
321
322 std::atomic<bool> _enabled{false};
323 std::atomic<bool> _publish_tf{true};
324 std::atomic<uint64_t> _frame{0};
326
327 std::unordered_map<void *, ActorRegistration> _registrations;
328 // Exact-topic overrides; empty string means "no override".
329 std::unordered_map<void *, std::string> _actor_ros_topic_names;
330 // Vehicles registered with enable_autoware_control — the only ones whose
331 // vehicle-status stream is accepted and published.
332 std::unordered_set<void *> _autoware_vehicles;
333 // Lazily-created six-report publisher per Autoware vehicle. NOTE: report
334 // topics are fixed absolute names, so only one Autoware ego per simulation
335 // is supported (tier4 semantics).
336 std::unordered_map<void *, std::shared_ptr<AutowareVehicleStatusPublisher>>
338 std::unordered_map<void *, std::vector<void *>> _actor_parents;
339 std::shared_ptr<CarlaClockPublisher> _clock_publisher;
340 std::unordered_map<void *, std::shared_ptr<BasePublisher>> _publishers;
341 std::unordered_map<void *, std::shared_ptr<CarlaCameraPublisher>> _camera_publishers;
342 std::unordered_map<void *, std::shared_ptr<CarlaTransformPublisher>> _transforms;
343 std::unordered_set<carla::streaming::detail::stream_id_type> _publish_stream;
344 std::unordered_map<void *, ActorCallback> _actor_callbacks;
345 std::unordered_multimap<void *, std::shared_ptr<BaseSubscriber>> _subscribers;
346#if defined(WITH_ROS2_DEMO)
347 std::shared_ptr<BasicSubscriber> _basic_subscriber;
348 std::shared_ptr<BasicPublisher> _basic_publisher;
349 std::unordered_map<void *, ActorMessageCallback> _actor_message_callbacks;
350#endif
351};
352
353} // namespace ros2
354} // namespace carla
float distance
A rigid transform in CARLA's / Unreal's left-handed frame: x forward, y right, z up,...
std::unordered_map< void *, std::shared_ptr< CarlaTransformPublisher > > _transforms
Definition ROS2.h:342
void ProcessDataFromRadar(uint64_t sensor_type, carla::streaming::detail::stream_id_type stream_id, const carla::geom::Transform sensor_transform, const carla::sensor::data::RadarData &data, void *actor=nullptr)
Definition ROS2.cpp:817
void ProcessDataFromDVS(uint64_t sensor_type, carla::streaming::detail::stream_id_type stream_id, const carla::geom::Transform sensor_transform, const carla::SharedBufferView buffer, int W, int H, float Fov, void *actor=nullptr)
Definition ROS2.cpp:707
static std::shared_ptr< ROS2 > _instance
Definition ROS2.h:315
bool GetPublishTF() const
Definition ROS2.h:86
std::string GetActorRosTopicName(void *actor) const
Definition ROS2.cpp:296
std::atomic< bool > _enabled
Definition ROS2.h:322
std::string LookupRosName(void *actor) const
Definition ROS2.cpp:336
void ProcessDataFromStatusSensor(uint64_t sensor_type, carla::streaming::detail::stream_id_type stream_id, const carla::geom::Transform sensor_transform, const carla::sensor::s11n::VehicleStatusData &data, void *vehicle_actor, void *actor)
Definition ROS2.cpp:864
void UnregisterVehicle(void *actor)
Definition ROS2.cpp:273
void RemoveBasicSubscriberCallback(void *actor)
Definition ROS2.cpp:329
static std::shared_ptr< ROS2 > GetInstance()
Definition ROS2.h:61
std::string BuildParentChain(void *actor) const
Definition ROS2.cpp:346
void SetPublishTF(bool publish_tf)
Definition ROS2.h:85
std::unordered_set< carla::streaming::detail::stream_id_type > _publish_stream
Definition ROS2.h:343
void AddActorRosTopicName(void *actor, std::string ros_topic_name)
Definition ROS2.cpp:282
void RemoveActorRosTopicName(void *actor)
Definition ROS2.cpp:288
void RegisterSensor(void *actor, std::string ros_name, std::string frame_id, bool publish_tf)
Definition ROS2.cpp:212
std::unordered_set< void * > _autoware_vehicles
Definition ROS2.h:332
std::unordered_map< void *, std::shared_ptr< BasePublisher > > _publishers
Definition ROS2.h:340
std::unordered_map< void *, std::vector< void * > > _actor_parents
Definition ROS2.h:338
std::shared_ptr< BasePublisher > GetOrCreateSensor(int type, carla::streaming::detail::stream_id_type id, void *actor)
Definition ROS2.cpp:450
std::unordered_map< void *, std::string > _actor_ros_topic_names
Definition ROS2.h:329
void ProcessDataFromIMU(uint64_t sensor_type, carla::streaming::detail::stream_id_type stream_id, const carla::geom::Transform sensor_transform, carla::geom::Vector3D accelerometer, carla::geom::Vector3D gyroscope, float compass, void *actor=nullptr)
Definition ROS2.cpp:686
bool IsKnownActorLocked(void *actor) const
Definition ROS2.cpp:208
void ProcessDataFromObstacleDetection(uint64_t sensor_type, carla::streaming::detail::stream_id_type stream_id, const carla::geom::Transform sensor_transform, AActor *first_actor, AActor *second_actor, float distance, void *actor=nullptr)
Definition ROS2.cpp:835
std::unordered_map< void *, std::shared_ptr< AutowareVehicleStatusPublisher > > _autoware_status_publishers
Definition ROS2.h:337
void ProcessDataFromAutowareGNSS(uint64_t sensor_type, carla::streaming::detail::stream_id_type stream_id, const carla::geom::Transform sensor_transform, const carla::geom::GeoLocation &data, const carla::geom::Transform &sensor_world_transform, const double mgrs_offset_position[3], void *actor=nullptr)
Definition ROS2.cpp:971
void ProcessDataFromCamera(uint64_t sensor_type, carla::streaming::detail::stream_id_type stream_id, const carla::geom::Transform sensor_transform, int W, int H, float Fov, const carla::SharedBufferView buffer, void *actor=nullptr)
Definition ROS2.cpp:594
bool HasTopicOverride(void *actor) const
Definition ROS2.cpp:302
std::unordered_map< void *, ActorCallback > _actor_callbacks
Definition ROS2.h:344
std::string LookupFrameId(void *actor) const
Definition ROS2.cpp:341
ROS2(const ROS2 &obj)=delete
void ProcessDataFromSemanticLidar(uint64_t sensor_type, carla::streaming::detail::stream_id_type stream_id, const carla::geom::Transform sensor_transform, carla::sensor::data::SemanticLidarData &data, void *actor=nullptr)
Definition ROS2.cpp:799
std::unordered_multimap< void *, std::shared_ptr< BaseSubscriber > > _subscribers
Definition ROS2.h:345
std::mutex _mutex
Definition ROS2.h:320
std::shared_ptr< CarlaClockPublisher > _clock_publisher
Definition ROS2.h:339
void ProcessDataFromCollisionSensor(uint64_t sensor_type, carla::streaming::detail::stream_id_type stream_id, const carla::geom::Transform sensor_transform, uint32_t other_actor, carla::geom::Vector3D impulse, void *actor)
Definition ROS2.cpp:848
void RegisterVehicle(void *actor, std::string ros_name, std::string frame_id, ActorCallback callback, bool enable_ackermann_control=false, bool enable_autoware_control=false)
Definition ROS2.cpp:236
std::atomic< bool > _publish_tf
Definition ROS2.h:323
std::atomic< uint64_t > _frame
Definition ROS2.h:324
bool IsEnabled()
Definition ROS2.h:77
std::shared_ptr< CarlaTransformPublisher > GetOrCreateTransformPublisherLocked(void *actor)
Definition ROS2.cpp:544
bool Enable(bool enable, Middleware middleware=Middleware::FastDDS, int domain_id=kUnsetDomainId)
Enable or disable ROS 2 publishing.
Definition ROS2.cpp:101
bool IsStreamEnabled(carla::streaming::detail::stream_id_type id)
Definition ROS2.h:138
void AddActorParentRosName(void *actor, void *parent)
Definition ROS2.cpp:307
Stamp GetStamp() const
Definition ROS2.cpp:197
std::unordered_map< void *, ActorRegistration > _registrations
Definition ROS2.h:327
void AddBasicSubscriberCallback(void *actor, std::string ros_name, ActorMessageCallback callback)
Definition ROS2.cpp:317
void SetTimestamp(double timestamp)
Definition ROS2.cpp:174
void UnregisterSensorLocked(void *actor)
Definition ROS2.cpp:230
void ResetStreams()
Definition ROS2.h:142
std::shared_ptr< CarlaCameraPublisher > GetOrCreateCameraSensor(carla::streaming::detail::stream_id_type id, void *actor, const std::string &default_prefix)
Definition ROS2.cpp:414
void ProcessDataFromLidar(uint64_t sensor_type, carla::streaming::detail::stream_id_type stream_id, const carla::geom::Transform sensor_transform, carla::sensor::data::LidarData &data, void *actor=nullptr)
Definition ROS2.cpp:740
void SetFrame(uint64_t frame)
Definition ROS2.cpp:139
std::string BuildBaseTopicName(void *actor) const
Definition ROS2.cpp:366
void ResolveAutoStreamSuffix(void *actor, const std::string &prefix, carla::streaming::detail::stream_id_type id)
Definition ROS2.cpp:394
void PublishTransform(void *actor, const Stamp &stamp, const carla::geom::Transform &sensor_transform)
Definition ROS2.cpp:573
void DropPublishersLocked(void *actor)
Definition ROS2.cpp:202
std::unordered_map< void *, std::shared_ptr< CarlaCameraPublisher > > _camera_publishers
Definition ROS2.h:341
void EnableStream(carla::streaming::detail::stream_id_type id)
Definition ROS2.h:134
void UnregisterSensor(void *actor)
Definition ROS2.cpp:225
void ProcessDataFromGNSS(uint64_t sensor_type, carla::streaming::detail::stream_id_type stream_id, const carla::geom::Transform sensor_transform, const carla::geom::GeoLocation &data, void *actor=nullptr)
Definition ROS2.cpp:671
std::function< void(void *actor, ROS2CallbackData data)> ActorCallback
Middleware
Enumeration of available middleware implementations.
Definition Middleware.h:15
std::function< void(void *actor, ROS2MessageCallbackData data)> ActorMessageCallback
constexpr int kUnsetDomainId
Sentinel domain id meaning "no domain id was configured on the command line"; each middleware falls b...
geom::Vector3D Vector3D
This file contains definitions of common data structures used in traffic manager.
std::shared_ptr< BufferView > SharedBufferView
Definition BufferView.h:151
Snapshot of a vehicle's kinematic + control state, streamed each tick by the Autoware VehicleStatusSe...