Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
7 changes: 7 additions & 0 deletions LibCarla/cmake/fast_dds/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ file(GLOB libcarla_carla_fastdds_headers
"${libcarla_source_path}/carla/ros2/subscribers/*.h"
"${libcarla_source_path}/carla/ros2/listeners/*.h"
"${libcarla_source_path}/carla/ros2/types/*.h"
"${libcarla_source_path}/carla/ros2/dds/*.h"
"${libcarla_source_path}/carla/ros2/dds/fastdds/*.h"
)
install(FILES ${libcarla_carla_fastdds_headers} DESTINATION include/carla/ros2)

Expand All @@ -30,6 +32,7 @@ file(GLOB libcarla_fastdds_sources
if (LIBCARLA_BUILD_RELEASE)
add_library(carla_fastdds STATIC ${libcarla_fastdds_sources})

target_compile_definitions(carla_fastdds PRIVATE CARLA_ROS2_DDS_FASTDDS)
target_compile_options(carla_fastdds PRIVATE -fexceptions)

target_include_directories(carla_fastdds SYSTEM PRIVATE
Expand All @@ -48,11 +51,15 @@ if (LIBCARLA_BUILD_DEBUG)

add_library(carla_fastdds_debug STATIC ${libcarla_fastdds_sources})

target_compile_definitions(carla_fastdds_debug PRIVATE CARLA_ROS2_DDS_FASTDDS)
target_compile_options(carla_fastdds_debug PRIVATE -fexceptions)

target_include_directories(carla_fastdds_debug SYSTEM PRIVATE
"${BOOST_INCLUDE_PATH}"
"${RPCLIB_INCLUDE_PATH}")

target_include_directories(carla_fastdds_debug PRIVATE "${FASTDDS_INCLUDE_PATH}")
target_include_directories(carla_fastdds_debug PRIVATE "${libcarla_source_path}/carla/ros2")
install(TARGETS carla_fastdds_debug DESTINATION lib)
set_target_properties(carla_fastdds_debug PROPERTIES COMPILE_FLAGS "${CMAKE_CXX_FLAGS_DEBUG}")
target_compile_definitions(carla_fastdds_debug PUBLIC -DBOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
Expand Down
56 changes: 56 additions & 0 deletions LibCarla/source/carla/ros2/dds/DDSMiddleware.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Copyright (c) 2025 Computer Vision Center (CVC) at the Universitat Autonoma de Barcelona (UAB).
// This work is licensed under the terms of the MIT license.
// For a copy, see <https://opensource.org/licenses/MIT>.

#pragma once

#include <string>

namespace carla {
namespace ros2 {

/// Enumeration of available DDS middleware implementations.
/// Passed to ROS2::Enable() to select the middleware at startup.
/// Once set, the middleware cannot be changed without restarting.
enum class DDSMiddleware {
FastDDS
};

/// Convert a DDSMiddleware enum value to a readable string.
inline const char* DDSMiddlewareToString(DDSMiddleware middleware) {
switch (middleware) {
case DDSMiddleware::FastDDS:
return "FastDDS";
}
return "Unknown";
}

/// Result of parsing a middleware name string.
struct DDSMiddlewareParseResult {
bool valid;
DDSMiddleware middleware;
};

/// Parse a middleware name string (lowercase). Returns {true, middleware} on match,
/// {false, FastDDS} for unrecognized values.
inline DDSMiddlewareParseResult DDSMiddlewareFromString(const std::string& name) {
if (name == "fastdds") {
return {true, DDSMiddleware::FastDDS};
}
return {false, DDSMiddleware::FastDDS};
}

/// Return a readable list of middleware implementations compiled into this binary.
inline std::string GetAvailableMiddlewareString() {
std::string result;
#if defined(CARLA_ROS2_DDS_FASTDDS)
result += "FastDDS";
#endif
if (result.empty()) {
result = "none";
}
return result;
}

} // namespace ros2
} // namespace carla
119 changes: 119 additions & 0 deletions LibCarla/source/carla/ros2/dds/DDSMiddlewareFactory.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
// Copyright (c) 2025 Computer Vision Center (CVC) at the Universitat Autonoma de Barcelona (UAB).
// This work is licensed under the terms of the MIT license.
// For a copy, see <https://opensource.org/licenses/MIT>.

#pragma once

#include <memory>
#include <string>

#include "carla/ros2/dds/DDSMiddleware.h"
#include "carla/ros2/dds/IDDSPublisherMiddleware.h"
#include "carla/ros2/dds/IDDSSubscriberMiddleware.h"
#include "carla/Logging.h"

#if defined(CARLA_ROS2_DDS_FASTDDS)
# include "carla/ros2/dds/fastdds/FastDDSPublisherMiddleware.h"
# include "carla/ros2/dds/fastdds/FastDDSSubscriberMiddleware.h"
#endif

namespace carla {
namespace ros2 {

/// Factory that creates DDS publisher/subscriber middleware based on the active middleware selection.
/// The middleware is set once at startup via SetMiddleware() before any DDS entities are created.
/// After the first entity is created, changing the middleware has undefined behavior.
class DDSMiddlewareFactory {
public:
/// Select the DDS middleware for all subsequent publisher/subscriber creation.
/// Must be called before any publisher or subscriber is initialized.
static void SetMiddleware(DDSMiddleware middleware) {
GetActiveMiddleware() = middleware;
}

/// @return The currently selected DDS middleware.
static DDSMiddleware GetMiddleware() {
return GetActiveMiddleware();
}

/// Check whether a specific middleware was compiled into this binary.
static bool IsMiddlewareAvailable(DDSMiddleware middleware) {
switch (middleware) {
case DDSMiddleware::FastDDS:
#if defined(CARLA_ROS2_DDS_FASTDDS)
return true;
#else
return false;
#endif
}
return false;
}

/// Result of middleware resolution — whether resolution succeeded and which middleware to use.
struct MiddlewareResolution {
bool success;
DDSMiddleware middleware;
};

/// Resolve the requested middleware strictly — no fallback to other middleware.
/// Returns {true, requested} if available, {false, requested} otherwise.
static MiddlewareResolution ResolveMiddleware(DDSMiddleware requested) {
if (IsMiddlewareAvailable(requested)) {
return {true, requested};
}
return {false, requested};
}

/// Return a readable list of middleware implementations compiled into this binary.
/// Delegates to the free function in DDSMiddleware.h.
static std::string GetAvailableMiddlewareString() {
return carla::ros2::GetAvailableMiddlewareString();
}

/// Create a publisher middleware for traits type T.
/// T must provide:
/// T::msg_type — the message type
template<typename T>
static std::unique_ptr<IDDSPublisherMiddleware> CreatePublisher() {
switch (GetActiveMiddleware()) {
case DDSMiddleware::FastDDS:
#if defined(CARLA_ROS2_DDS_FASTDDS)
return std::unique_ptr<IDDSPublisherMiddleware>(
new FastDDSPublisherMiddleware<T>());
#else
log_error("DDSMiddlewareFactory: FastDDS not compiled in");
return nullptr;
#endif
}
return nullptr;
}

/// Create a subscriber middleware for traits type S.
/// S must provide:
/// S::msg_type — the message type
template<typename S>
static std::unique_ptr<IDDSSubscriberMiddleware> CreateSubscriber() {
switch (GetActiveMiddleware()) {
case DDSMiddleware::FastDDS:
#if defined(CARLA_ROS2_DDS_FASTDDS)
return std::unique_ptr<IDDSSubscriberMiddleware>(
new FastDDSSubscriberMiddleware<S>());
#else
log_error("DDSMiddlewareFactory: FastDDS not compiled in");
return nullptr;
#endif
}
return nullptr;
}

private:
/// Returns reference to the active middleware selection
/// (function-local static for C++11 thread safety).
static DDSMiddleware& GetActiveMiddleware() {
static DDSMiddleware active_middleware = DDSMiddleware::FastDDS;
return active_middleware;
}
};

} // namespace ros2
} // namespace carla
37 changes: 37 additions & 0 deletions LibCarla/source/carla/ros2/dds/IDDSPublisherMiddleware.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright (c) 2025 Computer Vision Center (CVC) at the Universitat Autonoma de Barcelona (UAB).
// This work is licensed under the terms of the MIT license.
// For a copy, see <https://opensource.org/licenses/MIT>.

#pragma once

#include <string>

namespace carla {
namespace ros2 {

/// Type-erased abstract interface for a DDS publisher middleware.
/// Concrete implementations handle all vendor-specific DDS entity creation,
/// type registration, and data writing.
class IDDSPublisherMiddleware {
public:
virtual ~IDDSPublisherMiddleware() = default;

/// Initialize DDS entities (participant, publisher, topic, writer).
/// @param topic_name Full DDS topic name including "rt/" prefix.
/// @return true on success.
virtual bool Init(const std::string& topic_name) = 0;

/// Serialize and write a message to the DDS network.
/// @param message_data Pointer to the message object (type-erased, cast internally).
/// @return true if the write succeeded.
virtual bool Publish(void* message_data) = 0;

/// @return true if at least one subscriber is matched.
virtual bool IsAlive() const = 0;

/// @return The DDS topic name this publisher is bound to.
virtual std::string GetTopicName() const = 0;
};

} // namespace ros2
} // namespace carla
38 changes: 38 additions & 0 deletions LibCarla/source/carla/ros2/dds/IDDSSubscriberMiddleware.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright (c) 2025 Computer Vision Center (CVC) at the Universitat Autonoma de Barcelona (UAB).
// This work is licensed under the terms of the MIT license.
// For a copy, see <https://opensource.org/licenses/MIT>.

#pragma once

#include <string>

namespace carla {
namespace ros2 {

/// Type-erased abstract interface for a DDS subscriber middleware.
/// Concrete implementations write received messages directly into the caller-provided
/// storage (message_ptr / new_message_flag) to avoid an extra copy.
class IDDSSubscriberMiddleware {
public:
virtual ~IDDSSubscriberMiddleware() = default;

/// Initialize DDS entities (participant, subscriber, topic, reader).
/// The middleware writes incoming messages to *message_ptr and sets *new_message_flag = true.
/// @param topic_name Full DDS topic name.
/// @param message_ptr Pointer to the message storage owned by SubscriberImpl<S>.
/// @param new_message_flag Pointer to the new-message flag owned by SubscriberImpl<S>.
/// @return true on success.
virtual bool Init(
const std::string& topic_name,
void* message_ptr,
bool* new_message_flag) = 0;

/// @return true if at least one publisher is matched.
virtual bool IsAlive() const = 0;

/// @return The DDS topic name this subscriber is bound to.
virtual std::string GetTopicName() const = 0;
};

} // namespace ros2
} // namespace carla
Loading
Loading