Class NativeTopicSampler

Nested Relationships

Nested Types

Class Documentation

class NativeTopicSampler

Native rclcpp-based topic sampler that avoids CLI overhead.

This class provides fast topic discovery and sampling using native rclcpp APIs instead of shelling out to ros2 CLI commands. Key benefits:

  • No process spawn overhead (~100ms per CLI call saved)

  • Requires GNU timeout command only for topics with active publishers

  • Faster timeout detection for idle topics (return instantly)

  • Publisher count check before attempting to sample (skip idle topics immediately)

Usage:

NativeTopicSampler sampler(node);
auto topics = sampler.discover_topics("/powertrain/engine");
auto sample = sampler.sample_topic("/powertrain/engine/temperature", 1.0);

Public Functions

explicit NativeTopicSampler(rclcpp::Node *node)

Construct a new NativeTopicSampler.

Parameters:

node – Pointer to the owning node (must outlive sampler)

~NativeTopicSampler() = default
NativeTopicSampler(const NativeTopicSampler&) = delete
NativeTopicSampler &operator=(const NativeTopicSampler&) = delete
NativeTopicSampler(NativeTopicSampler&&) = delete
NativeTopicSampler &operator=(NativeTopicSampler&&) = delete
std::vector<TopicInfo> discover_all_topics()

Discover all topics in the ROS 2 graph.

Returns:

Vector of TopicInfo for all available topics

std::vector<TopicInfo> discover_topics(const std::string &namespace_prefix)

Discover topics under a specific namespace.

Parameters:

namespace_prefix – Namespace to filter by (e.g., “/powertrain/engine”)

Returns:

Vector of TopicInfo for matching topics

std::optional<TopicInfo> get_topic_info(const std::string &topic_name)

Get metadata for a specific topic (type, pub/sub counts)

This is very fast as it only queries the graph, no message waiting.

Parameters:

topic_name – Full topic path

Returns:

TopicInfo with metadata, or nullopt if topic doesn’t exist

bool has_publishers(const std::string &topic_name)

Check if a topic has active publishers.

Fast check to determine if sampling would be useful.

Parameters:

topic_name – Full topic path

Returns:

true if at least one publisher exists

TopicSampleResult sample_topic(const std::string &topic_name, double timeout_sec = 1.0)

Sample a topic to get one message.

Creates a temporary subscription, waits for a message, and returns. If no message arrives within timeout, returns result with has_data=false.

Important: This method handles topics without publishers gracefully by checking publisher count first and returning immediately with metadata if no publishers are available.

Parameters:
  • topic_name – Full topic path

  • timeout_sec – Maximum time to wait for a message

Returns:

TopicSampleResult with data (if received) or metadata only

std::vector<TopicSampleResult> sample_topics_parallel(const std::vector<std::string> &topic_names, double timeout_sec = 1.0, int max_parallel = 10)

Sample multiple topics in parallel with metadata fallback.

Efficiently samples multiple topics, returning metadata immediately for topics without publishers and only waiting for active topics.

Parameters:
  • topic_names – List of topic paths to sample

  • timeout_sec – Timeout per topic

  • max_parallel – Maximum concurrent sampling operations

Returns:

Vector of TopicSampleResult for each topic

std::vector<TopicEndpoint> get_topic_publishers(const std::string &topic_name)

Get all publishers for a specific topic.

Uses native rclcpp API to discover which nodes publish to a topic.

Parameters:

topic_name – Full topic path (e.g., “/cmd_vel”)

Returns:

Vector of TopicEndpoint describing each publisher

std::vector<TopicEndpoint> get_topic_subscribers(const std::string &topic_name)

Get all subscribers for a specific topic.

Uses native rclcpp API to discover which nodes subscribe to a topic.

Parameters:

topic_name – Full topic path (e.g., “/cmd_vel”)

Returns:

Vector of TopicEndpoint describing each subscriber

TopicConnection get_topic_connection(const std::string &topic_name)

Get full connection info for a topic (publishers + subscribers)

Parameters:

topic_name – Full topic path

Returns:

TopicConnection with all endpoint information

std::map<std::string, ComponentTopics> build_component_topic_map()

Build a map of component FQN -> topics it publishes/subscribes.

Scans all topics in the graph and builds a mapping from each node (component) to the topics it publishes and subscribes to. This is the core function for the new topic-to-component association approach.

Returns:

Map from component FQN (e.g., “/navigation/controller_server”) to ComponentTopics

ComponentTopics get_component_topics(const std::string &component_fqn)

Get topics for a specific component.

Parameters:

component_fqn – Fully qualified node name (e.g., “/navigation/controller_server”)

Returns:

ComponentTopics with publishes/subscribes lists

TopicDiscoveryResult discover_topics_by_namespace()

Discover namespaces and their topics in a single graph query.

This method performs a single call to get_topic_names_and_types() and processes all topics to extract namespaces and group topics by namespace. This avoids the N+1 query problem of calling discover_topic_namespaces() followed by get_topics_for_namespace() for each namespace.

Example: Topics [“/carter1/odom”, “/carter1/cmd_vel”, “/carter2/imu”] Returns: { namespaces: {“carter1”, “carter2”}, topics_by_ns: { “/carter1”: {publishes: [“/carter1/odom”, “/carter1/cmd_vel”]}, “/carter2”: {publishes: [“/carter2/imu”]} } }

Returns:

TopicDiscoveryResult with namespaces and topics grouped by namespace

std::set<std::string> discover_topic_namespaces()

Discover unique namespace prefixes from all topics.

Extracts the first segment of each topic path to identify namespaces. Used for topic-based component discovery when nodes are not available (e.g., Isaac Sim publishing topics without creating ROS 2 nodes).

Example: Topics [“/carter1/odom”, “/carter2/cmd_vel”, “/tf”] Returns: {“carter1”, “carter2”} (root topics like /tf are excluded)

Note

Consider using discover_topics_by_namespace() instead to avoid N+1 queries

Returns:

Set of unique namespace prefixes (without leading slash)

ComponentTopics get_topics_for_namespace(const std::string &ns_prefix)

Get all topics under a specific namespace prefix.

Returns ComponentTopics containing all topics that start with the given namespace prefix. For topic-based discovery, all matched topics are placed in the ‘publishes’ list since direction cannot be determined without node information.

Note

Consider using discover_topics_by_namespace() instead to avoid N+1 queries

Parameters:

ns_prefix – Namespace prefix including leading slash (e.g., “/carter1”)

Returns:

ComponentTopics with matching topics in publishes list

Public Static Functions

static bool is_system_topic(const std::string &topic_name)

Check if a topic is a ROS 2 system/infrastructure topic.

System topics are filtered out during topic-based discovery to avoid creating spurious components. Filtered topics include:

  • /parameter_events

  • /rosout

  • /clock

Note: /tf and /tf_static are NOT filtered (useful for diagnostics).

Parameters:

topic_name – Full topic path

Returns:

true if this is a system topic that should be filtered

struct TopicDiscoveryResult

Result of topic-based discovery containing namespaces and their topics.

This struct aggregates all topic-based discovery results to avoid multiple ROS 2 graph queries (N+1 query problem).

Public Members

std::set<std::string> namespaces

Unique namespace prefixes.

std::map<std::string, ComponentTopics> topics_by_ns

Topics grouped by namespace.