Skip to content

RMW API Proposal: Generic Middleware Context Access #413

@YuanYuYuan

Description

@YuanYuYuan

Background

This PR provides a Zenoh-specific API to expose the underlying Zenoh session. But it comes with limitations:

  • Only works for rmw_zenoh
  • Doesn't benefit other RMW implementations
  • Uses Zenoh-specific terminology ("session")

This proposal extends the RMW API in a generic way that benefits all RMW implementations.

Investigation: What RMW Implementations Can Expose

1. rmw_zenoh_cpp

Internal Context Structure: rmw_context_impl_s::Data

  • Location: rmw_zenoh_cpp/src/detail/rmw_context_impl_s.hpp
  • Key object: std::shared_ptr<zenoh::Session>

What it provides:

  • Zenoh session for creating custom publishers, subscribers, queryables
  • Direct access to Zenoh APIs for advanced operations (customized shared memory provider)

2. rmw_cyclonedds_cpp

Internal Context Structure: rmw_context_impl_s

  • Location: rmw_cyclonedds_cpp/src/rmw_node.cpp
  • Key object: dds_entity_t ppant (DDS Participant)

Key Entities Stored:

Entity Type Purpose
ppant dds_entity_t DDS Domain Participant (main entry point)
domain_id dds_domainid_t ROS domain ID
rd_participant dds_entity_t Built-in topic reader for participant discovery
rd_subscription dds_entity_t Built-in topic reader for subscription discovery
rd_publication dds_entity_t Built-in topic reader for publication discovery
dds_pub dds_entity_t Global DDS Publisher
dds_sub dds_entity_t Global DDS Subscriber

What would be useful to expose:

  • Primary: DDS Participant (ppant) - root entity for all DDS operations
  • Secondary: Global publisher/subscriber entities

3. rmw_fastrtps_cpp

Internal Context Structure: rmw_context_impl_sCustomParticipantInfo

  • Location: rmw_fastrtps_shared_cpp/include/rmw_fastrtps_shared_cpp/custom_participant_info.hpp
  • Key object: eprosima::fastdds::dds::DomainParticipant*

Key Entities Stored:

struct CustomParticipantInfo {
  std::shared_ptr<DomainParticipantFactory> factory_;
  DomainParticipant* participant_;
  ParticipantListener* listener_;
  std::map<std::string, std::unique_ptr<UseCountTopic>> topic_name_to_topic_;
  Publisher* publisher_;
  Subscriber* subscriber_;
};

Proposal

Extend rmw/rmw/include/rmw/rmw.h by

/// Get the underlying middleware context handle.
/**
 * Returns a type-erased pointer to the middleware-specific context/session
 * object. The actual type depends on the RMW implementation:
 *
 * - rmw_zenoh_cpp: Returns std::shared_ptr<zenoh::Session>*
 * - rmw_cyclonedds_cpp: Returns dds_entity_t* (DDS Participant)
 * - rmw_fastrtps_cpp: Returns eprosima::fastdds::dds::DomainParticipant**
 *
 * Users must cast the returned pointer to the appropriate type based on
 * rmw_get_implementation_identifier().
 */
RMW_PUBLIC
RMW_WARN_UNUSED
void *
rmw_get_implementation_handle(const rmw_context_t * context);

Example Usage

void* handle = rmw_get_implementation_handle(rmw_context);
const char* impl_id = rmw_get_implementation_identifier();

if (strcmp(impl_id, "rmw_zenoh_cpp") == 0) {
  auto session = *static_cast<std::shared_ptr<zenoh::Session>*>(handle);
  // Use Zenoh session...
} else if (strcmp(impl_id, "rmw_cyclonedds_cpp") == 0) {
  dds_entity_t participant = *static_cast<dds_entity_t*>(handle);
  // Use CycloneDDS participant...
} else if (strcmp(impl_id, "rmw_fastrtps_cpp") == 0) {
  auto participant = *static_cast<eprosima::fastdds::dds::DomainParticipant**>(handle);
  // Use FastDDS participant...
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions