48#if defined(WITH_ROS2_DEMO)
119 const char* domain_source =
124 "', domain id: ", resolved.
id,
" (", domain_source,
")");
129 std::lock_guard<std::mutex> lock(
_mutex);
132#if defined(WITH_ROS2_DEMO)
133 _basic_publisher = std::make_shared<BasicPublisher>();
134 _basic_publisher->Init();
143 std::vector<std::pair<std::shared_ptr<BaseSubscriber>,
ActorCallback>> pending;
145 std::lock_guard<std::mutex> lock(
_mutex);
149 pending.emplace_back(element.second, callback_it->second);
153 for (
auto &element : pending) {
154 element.first->ProcessMessages(element.second);
156#if defined(WITH_ROS2_DEMO)
157 if (_basic_subscriber) {
158 void *actor = _basic_subscriber->GetActor();
159 if (!_basic_subscriber->IsAlive()) {
162 if (actor && _basic_subscriber->HasNewMessage()) {
163 auto it = _actor_message_callbacks.find(actor);
164 if (it != _actor_message_callbacks.end()) {
166 control.
message = _basic_subscriber->GetMessage();
167 it->second(actor, control);
176 const double fractional = std::modf(timestamp, &integral);
177 const double multiplier = 1000000000.0;
179 static_cast<int32_t
>(integral),
180 static_cast<uint32_t
>(fractional * multiplier)};
181 std::shared_ptr<CarlaClockPublisher> clock_publisher;
183 std::lock_guard<std::mutex> lock(
_mutex);
187 if (clock_publisher) {
188 clock_publisher->Write(stamp.seconds, stamp.nanoseconds);
189 clock_publisher->Publish();
191#if defined(WITH_ROS2_DEMO)
192 _basic_publisher->SetData(
"Hello from Carla!");
193 _basic_publisher->Publish();
198 std::lock_guard<std::mutex> lock(
_mutex);
213 void *actor, std::string ros_name, std::string frame_id,
bool publish_tf) {
214 std::lock_guard<std::mutex> lock(
_mutex);
226 std::lock_guard<std::mutex> lock(
_mutex);
237 void *actor, std::string ros_name, std::string frame_id,
ActorCallback callback,
238 bool enable_ackermann_control,
239 bool enable_autoware_control) {
240 std::lock_guard<std::mutex> lock(
_mutex);
263 if (enable_autoware_control) {
265 _subscribers.insert({actor, std::make_shared<AutowareControlSubscriber>(actor, std::move(frame_id))});
266 }
else if (enable_ackermann_control) {
267 _subscribers.insert({actor, std::make_shared<AckermannControlSubscriber>(actor, base_topic_name, std::move(frame_id))});
269 _subscribers.insert({actor, std::make_shared<CarlaEgoVehicleControlSubscriber>(actor, base_topic_name, std::move(frame_id))});
274 std::lock_guard<std::mutex> lock(
_mutex);
283 std::lock_guard<std::mutex> lock(
_mutex);
289 std::lock_guard<std::mutex> lock(
_mutex);
297 std::lock_guard<std::mutex> lock(
_mutex);
308 std::lock_guard<std::mutex> lock(
_mutex);
311 it->second.push_back(parent);
318 [[maybe_unused]]
void *actor,
319 [[maybe_unused]] std::string ros_name,
321#if defined(WITH_ROS2_DEMO)
322 _actor_message_callbacks.insert_or_assign(actor, std::move(callback));
323 _basic_subscriber.reset();
324 _basic_subscriber = std::make_shared<BasicSubscriber>(actor, ros_name.c_str());
325 _basic_subscriber->Init();
330#if defined(WITH_ROS2_DEMO)
331 _basic_subscriber.reset();
332 _actor_message_callbacks.erase(actor);
338 return it !=
_registrations.end() ? it->second.ros_name : std::string{};
343 return it !=
_registrations.end() ? it->second.frame_id : std::string{};
349 return std::string{};
352 std::string parent_name;
353 for (
auto *parent : it->second) {
355 if (name.empty() || name == current_actor_name) {
358 parent_name = name +
'/' + parent_name;
360 if (!parent_name.empty() && parent_name.back() ==
'/') {
361 parent_name.pop_back();
372 const std::string &custom = override_it->second;
373 std::string base_topic_name =
"rt";
374 if (custom.front() !=
'/') {
375 base_topic_name +=
'/';
377 base_topic_name += custom;
378 return base_topic_name;
382 if (ros_name.empty()) {
383 return std::string{};
386 std::string base_topic_name =
"rt/carla/";
387 if (!parent_chain.empty()) {
388 base_topic_name += parent_chain +
"/";
390 base_topic_name += ros_name;
391 return base_topic_name;
396 const std::string &prefix,
402 const std::string placeholder = prefix +
"__";
403 if (it->second.ros_name != placeholder) {
406 std::string resolved = prefix + std::to_string(
id);
407 it->second.ros_name = resolved;
408 if (it->second.frame_id == placeholder) {
409 it->second.frame_id = std::move(resolved);
413template <
typename CameraT>
417 const std::string &default_prefix) {
418 std::lock_guard<std::mutex> lock(
_mutex);
428 auto typed = std::dynamic_pointer_cast<CameraT>(it_camera->second);
429 if (typed ==
nullptr) {
431 "ROS2 camera publisher type mismatch for actor", actor,
432 "- the actor was dispatched as two different camera types; ignoring this sample.");
445 auto new_publisher = std::make_shared<CameraT>(base_topic_name, frame_id);
447 return new_publisher;
452 std::lock_guard<std::mutex> lock(
_mutex);
455 return it_publishers->second;
464 auto resolve = [
this, actor, id](
const std::string &prefix) {
468 std::shared_ptr<BasePublisher> publisher;
471 resolve(
"collision");
472 publisher = std::make_shared<CarlaCollisionPublisher>(
478 publisher = std::make_shared<CarlaDVSCameraPublisher>(
484 publisher = std::make_shared<CarlaGNSSPublisher>(
490 publisher = std::make_shared<CarlaIMUPublisher>(
496 publisher = std::make_shared<CarlaRadarPublisher>(
501 resolve(
"ray_cast_semantic");
502 publisher = std::make_shared<CarlaSemanticLidarPublisher>(
509 resolve(
"hss_lidar");
510 publisher = std::make_shared<CarlaLidarPublisher>(
515 resolve(
"autoware_gnss");
520 publisher = std::make_shared<AutowareGNSSPublisher>(
534 log_error(
"ROS2::GetOrCreateSensor: unknown sensor type", type);
555 if (registration_it ==
_registrations.end() || !registration_it->second.publish_tf) {
558 auto transform = std::make_shared<CarlaTransformPublisher>();
567std::string ParentFrameOrMap(
const std::string &parent_chain) {
568 return parent_chain.empty() ? std::string{
"map"} : parent_chain;
575 std::shared_ptr<CarlaTransformPublisher> transform_publisher;
576 std::string parent_frame;
577 std::string frame_id;
579 std::lock_guard<std::mutex> lock(
_mutex);
581 if (!transform_publisher) {
587 transform_publisher->Write(
591 transform_publisher->Publish();
595 uint64_t sensor_type,
598 int W,
int H,
float Fov,
610 std::shared_ptr<CarlaCameraPublisher> publisher;
611 switch (sensor_type) {
613 publisher = GetOrCreateCameraSensor<CarlaRGBCameraPublisher>(stream_id, actor,
"rgb");
616 publisher = GetOrCreateCameraSensor<CarlaDepthCameraPublisher>(stream_id, actor,
"depth");
619 publisher = GetOrCreateCameraSensor<CarlaNormalsCameraPublisher>(stream_id, actor,
"normals");
622 publisher = GetOrCreateCameraSensor<CarlaSSCameraPublisher>(stream_id, actor,
"semantic_segmentation");
625 publisher = GetOrCreateCameraSensor<CarlaISCameraPublisher>(stream_id, actor,
"instance_segmentation");
628 publisher = GetOrCreateCameraSensor<CarlaOpticalFlowCameraPublisher>(
629 stream_id, actor,
"optical_flow");
638 "Sensor to ROS data: frame.",
_frame.load(),
"sensor.", sensor_type,
"stream.", stream_id,
639 "buffer.", buffer->size());
644 const auto *header_ptr = buffer->data();
649 const auto *header =
reinterpret_cast<
651 publisher->WriteCameraInfo(
652 stamp.
seconds, stamp.
nanoseconds, 0, 0, header->height, header->width, header->fov_angle,
true);
653 publisher->WriteImage(
657 const auto *header =
reinterpret_cast<
659 publisher->WriteCameraInfo(
660 stamp.
seconds, stamp.
nanoseconds, 0, 0, header->height, header->width, header->fov_angle,
true);
661 publisher->WriteImage(
665 publisher->Publish();
679 auto publisher = std::dynamic_pointer_cast<CarlaGNSSPublisher>(base);
681 publisher->Publish();
696 auto publisher = std::dynamic_pointer_cast<CarlaIMUPublisher>(base);
699 accelerometer.
x, accelerometer.
y, accelerometer.
z,
700 gyroscope.
x, gyroscope.
y, gyroscope.
z,
702 publisher->Publish();
716 auto publisher = std::dynamic_pointer_cast<CarlaDVSCameraPublisher>(base);
717 const auto *header =
reinterpret_cast<
722 constexpr std::size_t header_offset =
725 const std::size_t event_count = (buffer->size() - header_offset) / event_size;
726 const std::uint8_t *event_bytes = buffer->data() + header_offset;
728 publisher->WriteCameraInfo(
729 stamp.
seconds, stamp.
nanoseconds, 0, 0, header->height, header->width, header->fov_angle,
true);
730 publisher->WriteImage(
732 event_count, event_bytes, event_size);
733 publisher->WritePointCloud(
734 stamp.
seconds, stamp.
nanoseconds, 1,
static_cast<std::uint32_t
>(event_count), event_bytes);
735 publisher->Publish();
741 uint64_t sensor_type,
749 sensor_type, stream_id, sensor_transform,
750 0u, 0.0f, 0.0f, data, actor);
757 uint32_t channel_count,
758 float upper_fov_limit,
759 float lower_fov_limit,
764 auto publisher = std::dynamic_pointer_cast<CarlaLidarPublisher>(base);
768 const auto width =
static_cast<std::uint32_t
>(data.
_points.size() / 4u);
769 if (channel_count >= 2u) {
774 const float upper_rad = upper_fov_limit *
static_cast<float>(M_PI) / 180.0f;
775 const float lower_rad = lower_fov_limit *
static_cast<float>(M_PI) / 180.0f;
776 std::vector<float> vertical_angles;
777 vertical_angles.reserve(channel_count);
778 const float vertical_step =
779 (upper_rad - lower_rad) /
static_cast<float>(channel_count - 1u);
780 for (uint32_t i = 0u; i < channel_count; ++i) {
781 vertical_angles.push_back(upper_rad -
static_cast<float>(i) * vertical_step);
783 publisher->WriteExtendedPointCloud(
785 reinterpret_cast<const std::uint8_t *
>(data.
_points.data()),
790 publisher->WritePointCloud(
792 reinterpret_cast<const std::uint8_t *
>(data.
_points.data()));
794 publisher->Publish();
807 auto publisher = std::dynamic_pointer_cast<CarlaSemanticLidarPublisher>(base);
808 const auto width =
static_cast<std::uint32_t
>(data.
_ser_points.size());
809 publisher->WritePointCloud(
811 reinterpret_cast<const std::uint8_t *
>(data.
_ser_points.data()));
812 publisher->Publish();
825 auto publisher = std::dynamic_pointer_cast<CarlaRadarPublisher>(base);
827 publisher->WritePointCloud(
829 reinterpret_cast<const std::uint8_t *
>(data.
_detections.data()));
830 publisher->Publish();
836 uint64_t sensor_type,
844 "Sensor ObstacleDetector to ROS data: frame.",
_frame.load(),
"sensor.", sensor_type,
845 "stream.", stream_id,
"distance.",
distance);
852 uint32_t other_actor,
857 auto publisher = std::dynamic_pointer_cast<CarlaCollisionPublisher>(base);
859 publisher->Publish();
875 std::shared_ptr<AutowareVehicleStatusPublisher> publisher;
877 std::lock_guard<std::mutex> lock(
_mutex);
880 "ROS2::ProcessDataFromStatusSensor: the Vehicle Status Sensor is attached to a "
881 "vehicle that is not registered for Autoware control - not publishing the data.");
886 publisher = it->second;
888 publisher = std::make_shared<AutowareVehicleStatusPublisher>();
893 constexpr uint8_t reverse_mask = 0b00000001;
894 constexpr uint8_t manual_gear_mask = 0b00000010;
896 constexpr uint8_t left_blinker_mask = 0b00000001;
897 constexpr uint8_t right_blinker_mask = 0b00000010;
898 constexpr uint8_t hazard_lights_mask = 0b00000100;
901 const bool is_reverse = (data.
control_flags & reverse_mask) != 0;
902 const bool is_manual_gear = (data.
control_flags & manual_gear_mask) != 0;
904 (void)is_manual_gear;
906 const bool is_left_blinker_on = (data.
turn_mask & left_blinker_mask) != 0;
907 const bool is_right_blinker_on = (data.
turn_mask & right_blinker_mask) != 0;
908 const bool is_hazard_lights_on = (data.
turn_mask & hazard_lights_mask) != 0;
916 publisher->SetSteering(-data.
steer);
924#define CASE(GEAR_VALUE, GEAR_ENUM) \
926 publisher->SetGear(GEAR_ENUM); \
928 static_assert(true, "")
956 if (!is_left_blinker_on && !is_right_blinker_on) {
958 }
else if (is_left_blinker_on && !is_right_blinker_on) {
960 }
else if (is_right_blinker_on && !is_left_blinker_on) {
963 log_error(
"ROS2::ProcessDataFromStatusSensor: both blinkers are on; this should not happen.");
966 publisher->SetHazardLights(is_hazard_lights_on);
977 const double mgrs_offset_position[3],
981 if (
auto publisher = std::dynamic_pointer_cast<AutowareGNSSPublisher>(base)) {
990 mgrs_offset_position[0], mgrs_offset_position[1], mgrs_offset_position[2]);
991 publisher->Publish();
994 "ROS2::ProcessDataFromAutowareGNSS: publisher type mismatch for actor", actor,
995 "- the actor was dispatched as both regular and Autoware GNSS; ignoring this sample.");
1002 std::lock_guard<std::mutex> lock(
_mutex);
1015#if defined(WITH_ROS2_DEMO)
1016 _basic_publisher.reset();
1017 _basic_subscriber.reset();
std::unordered_map< void *, std::shared_ptr< CarlaTransformPublisher > > _transforms
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)
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)
static std::shared_ptr< ROS2 > _instance
std::string GetActorRosTopicName(void *actor) const
std::atomic< bool > _enabled
std::string LookupRosName(void *actor) const
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)
void UnregisterVehicle(void *actor)
void RemoveBasicSubscriberCallback(void *actor)
std::string BuildParentChain(void *actor) const
void AddActorRosTopicName(void *actor, std::string ros_topic_name)
void RemoveActorRosTopicName(void *actor)
void RegisterSensor(void *actor, std::string ros_name, std::string frame_id, bool publish_tf)
std::unordered_set< void * > _autoware_vehicles
std::unordered_map< void *, std::shared_ptr< BasePublisher > > _publishers
std::unordered_map< void *, std::vector< void * > > _actor_parents
std::shared_ptr< BasePublisher > GetOrCreateSensor(int type, carla::streaming::detail::stream_id_type id, void *actor)
std::unordered_map< void *, std::string > _actor_ros_topic_names
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)
bool IsKnownActorLocked(void *actor) const
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)
std::unordered_map< void *, std::shared_ptr< AutowareVehicleStatusPublisher > > _autoware_status_publishers
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)
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)
bool HasTopicOverride(void *actor) const
std::unordered_map< void *, ActorCallback > _actor_callbacks
std::string LookupFrameId(void *actor) const
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)
std::unordered_multimap< void *, std::shared_ptr< BaseSubscriber > > _subscribers
std::shared_ptr< CarlaClockPublisher > _clock_publisher
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)
void RegisterVehicle(void *actor, std::string ros_name, std::string frame_id, ActorCallback callback, bool enable_ackermann_control=false, bool enable_autoware_control=false)
std::atomic< bool > _publish_tf
std::atomic< uint64_t > _frame
std::shared_ptr< CarlaTransformPublisher > GetOrCreateTransformPublisherLocked(void *actor)
bool Enable(bool enable, Middleware middleware=Middleware::FastDDS, int domain_id=kUnsetDomainId)
Enable or disable ROS 2 publishing.
void AddActorParentRosName(void *actor, void *parent)
std::unordered_map< void *, ActorRegistration > _registrations
void AddBasicSubscriberCallback(void *actor, std::string ros_name, ActorMessageCallback callback)
void SetTimestamp(double timestamp)
void UnregisterSensorLocked(void *actor)
std::shared_ptr< CarlaCameraPublisher > GetOrCreateCameraSensor(carla::streaming::detail::stream_id_type id, void *actor, const std::string &default_prefix)
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)
void SetFrame(uint64_t frame)
std::string BuildBaseTopicName(void *actor) const
void ResolveAutoStreamSuffix(void *actor, const std::string &prefix, carla::streaming::detail::stream_id_type id)
void PublishTransform(void *actor, const Stamp &stamp, const carla::geom::Transform &sensor_transform)
void DropPublishersLocked(void *actor)
std::unordered_map< void *, std::shared_ptr< CarlaCameraPublisher > > _camera_publishers
void UnregisterSensor(void *actor)
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)
std::vector< float > _points
size_t GetDetectionCount() const
Returns the number of current detections.
std::vector< RadarDetection > _detections
std::vector< SemanticLidarDetection > _ser_points
std::vector< uint32_t > _header
static constexpr auto header_offset
static constexpr auto header_offset
std::string GetAvailableMiddleware()
const char * MiddlewareToString(Middleware middleware)
Convert a Middleware enum value to a readable string.
std::function< void(void *actor, ROS2CallbackData data)> ActorCallback
Middleware
Enumeration of available middleware implementations.
std::function< void(void *actor, ROS2MessageCallbackData data)> ActorMessageCallback
bool SetActiveMiddleware(Middleware requested)
DDS-free bridge for selecting the active middleware across the shared-library boundary.
@ InstanceSegmentationCamera_WideAngleLens
@ InstanceSegmentationCamera
@ DepthCamera_WideAngleLens
@ SemanticSegmentationCamera_WideAngleLens
@ SceneCaptureCamera_WideAngleLens
@ SemanticSegmentationCamera
@ InertialMeasurementUnit
@ ObstacleDetectionSensor
@ Environment
From the ROS_DOMAIN_ID environment variable.
@ CommandLine
From the –ros-domain-id command line option.
ResolvedDomainId SetActiveDomainId(int domain_id)
Store the domain id in the shared library's MiddlewareConfig and return the effective domain id resol...
This file contains definitions of common data structures used in traffic manager.
std::shared_ptr< BufferView > SharedBufferView
static void log_error(Args &&... args)
static void log_info(Args &&... args)
static void log_warning(Args &&... args)
The resolved domain id together with the source it came from.
Snapshot of a vehicle's kinematic + control state, streamed each tick by the Autoware VehicleStatusSe...