Class NativeTopicSampler
Defined in File native_topic_sampler.hpp
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.
-
std::set<std::string> namespaces