C++ API Reference
This section contains the automatically generated API documentation for the ros2_medkit C++ codebase.
Note
This documentation is generated from source code comments using Doxygen and Breathe.
Run the “Docs: Build Doxygen” VS Code task or doxygen Doxyfile in the docs/ directory
before building Sphinx locally. In CI, Doxygen XML is generated automatically.
ros2_medkit_gateway
The HTTP/REST gateway that exposes ROS 2 graph via SOVD-compatible API.
Classes
-
class GatewayNode : public rclcpp::Node
Public Functions
-
explicit GatewayNode(const rclcpp::NodeOptions &options = rclcpp::NodeOptions{})
-
~GatewayNode() override
-
GatewayNode(const GatewayNode&) = delete
-
GatewayNode &operator=(const GatewayNode&) = delete
-
GatewayNode(GatewayNode&&) = delete
-
GatewayNode &operator=(GatewayNode&&) = delete
-
const ThreadSafeEntityCache &get_thread_safe_cache() const
Get the thread-safe entity cache with O(1) lookups.
- Returns:
Reference to ThreadSafeEntityCache
-
DataAccessManager *get_data_access_manager() const
Get the DataAccessManager instance.
Note
The returned pointer is valid as long as the GatewayNode exists. REST server is stopped before GatewayNode destruction to ensure safe access.
- Returns:
Raw pointer to DataAccessManager (valid for lifetime of GatewayNode)
Attach a TopicDataProvider to route topic sampling through.
Called by main() after the rclcpp::Executor is constructed and the gateway node added to it, so the provider can build its subscription node. Stores the shared_ptr to keep the provider alive for the gateway node’s lifetime and forwards the raw pointer into DataAccessManager. The pool-backed provider is the single sampling path (issue #375 race fix).
-
inline TopicDataProvider *get_topic_data_provider() const
- Returns:
Non-owning pointer to the currently attached TopicDataProvider, or nullptr when no provider has been wired up yet.
-
OperationManager *get_operation_manager() const
Get the OperationManager instance.
- Returns:
Raw pointer to OperationManager (valid for lifetime of GatewayNode)
-
DiscoveryManager *get_discovery_manager() const
Get the DiscoveryManager instance.
- Returns:
Raw pointer to DiscoveryManager (valid for lifetime of GatewayNode)
-
ConfigurationManager *get_configuration_manager() const
Get the ConfigurationManager instance.
- Returns:
Raw pointer to ConfigurationManager (valid for lifetime of GatewayNode)
-
FaultManager *get_fault_manager() const
Get the FaultManager instance.
- Returns:
Raw pointer to FaultManager (valid for lifetime of GatewayNode)
-
BulkDataStore *get_bulk_data_store() const
Get the BulkDataStore instance.
- Returns:
Raw pointer to BulkDataStore (valid for lifetime of GatewayNode)
-
LogManager *get_log_manager() const
Get the LogManager instance.
- Returns:
Raw pointer to LogManager (valid for lifetime of GatewayNode)
-
SubscriptionManager *get_subscription_manager() const
Get the SubscriptionManager instance.
- Returns:
Raw pointer to SubscriptionManager (valid for lifetime of GatewayNode)
-
UpdateManager *get_update_manager() const
Get the UpdateManager instance.
- Returns:
Raw pointer to UpdateManager (valid for lifetime of GatewayNode), or nullptr if disabled
-
LockManager *get_lock_manager() const
Get the LockManager instance.
- Returns:
Raw pointer to LockManager (valid for lifetime of GatewayNode), or nullptr if locking disabled
-
ScriptManager *get_script_manager() const
Get the ScriptManager instance.
- Returns:
Raw pointer to ScriptManager (valid for lifetime of GatewayNode), or nullptr if not initialized
-
PluginManager *get_plugin_manager() const
Get the PluginManager instance.
- Returns:
Raw pointer to PluginManager (valid for lifetime of GatewayNode)
-
ResourceSamplerRegistry *get_sampler_registry() const
Get the ResourceSamplerRegistry instance.
- Returns:
Raw pointer to ResourceSamplerRegistry (valid for lifetime of GatewayNode)
-
TransportRegistry *get_transport_registry() const
Get the TransportRegistry instance.
- Returns:
Raw pointer to TransportRegistry (valid for lifetime of GatewayNode)
-
std::shared_ptr<SSEClientTracker> get_sse_client_tracker() const
Get the SSEClientTracker instance.
- Returns:
Shared pointer to SSEClientTracker
-
ResourceChangeNotifier *get_resource_change_notifier() const
Get the ResourceChangeNotifier instance.
- Returns:
Raw pointer to ResourceChangeNotifier (valid for lifetime of GatewayNode)
-
TriggerManager *get_trigger_manager() const
Get the TriggerManager instance.
- Returns:
Raw pointer to TriggerManager (valid for lifetime of GatewayNode), or nullptr if disabled
-
ConditionRegistry *get_condition_registry() const
Get the ConditionRegistry instance.
- Returns:
Raw pointer to ConditionRegistry (valid for lifetime of GatewayNode)
-
AggregationManager *get_aggregation_manager() const
Get the AggregationManager instance.
- Returns:
Raw pointer to AggregationManager (valid for lifetime of GatewayNode), or nullptr if disabled
-
void handle_entity_change_notification(const EntityChangeScope &scope)
Handle a plugin’s
PluginContext::notify_entities_changedrequest.Runs a single
refresh_cache()pass synchronously. The scope hint is accepted and logged but the current implementation ignores it and always does a full refresh - future work may limit the rediscovery to the indicated area / component. The entry point is safe to call from any thread: refresh passes triggered by plugin notifications, the periodic refresh timer, and startup are serialized by an internal mutex insiderefresh_cache()because refresh touches discovery state (e.g.,HybridDiscoveryStrategy::refresh()) that itself assumes single-threaded execution -ThreadSafeEntityCache’s own mutex is not sufficient.
-
void trigger_reentrant_notification_for_testing(const EntityChangeScope &scope)
Test hook: simulate a plugin calling notify_entities_changed from within its own IntrospectionProvider::introspect() callback.
Sets the per-thread in-refresh flag (the same flag the real refresh path uses) and invokes
handle_entity_change_notification(scope). The gateway is expected to short-circuit the call with a warning log and return without reloading the manifest.Exists purely to let unit tests exercise the reentrancy guard without spinning up a full plugin with a real IntrospectionProvider. Do NOT call this from production code.
-
explicit GatewayNode(const rclcpp::NodeOptions &options = rclcpp::NodeOptions{})
-
class DiscoveryManager
Orchestrates entity discovery using pluggable strategies.
This class delegates discovery to strategy implementations based on the configured mode:
RUNTIME_ONLY: Uses RuntimeDiscoveryStrategy (traditional ROS graph)
MANIFEST_ONLY: Uses manifest as sole source of truth
HYBRID: Combines manifest definitions with runtime linking
The DiscoveryManager provides a unified interface for discovering:
Areas: Logical groupings (ROS 2 namespaces or manifest areas)
Components: Software/hardware units (ROS 2 nodes)
Apps: Software applications (manifest-defined)
Functions: Functional groupings (manifest-defined)
See also
discovery::RuntimeDiscoveryStrategy
See also
discovery::HybridDiscoveryStrategy
See also
discovery::ManifestManager
Public Functions
-
explicit DiscoveryManager(rclcpp::Node *node)
Construct the discovery manager.
- Parameters:
node – ROS 2 node for graph introspection (must outlive this manager)
-
bool initialize(const DiscoveryConfig &config)
Initialize with configuration.
Loads manifest if configured, creates appropriate strategy. For RUNTIME_ONLY mode, this is a no-op.
- Parameters:
config – Discovery configuration
- Returns:
true if initialization succeeded
-
std::vector<Component> discover_components()
Discover all components.
- Returns:
Vector of discovered Component entities
-
std::vector<App> discover_apps()
Discover all apps.
- Returns:
Vector of discovered App entities (empty in runtime-only mode)
-
std::vector<Function> discover_functions()
Discover all functions.
- Returns:
Vector of discovered Function entities (empty in runtime-only mode)
-
std::vector<Function> discover_functions(const std::vector<App> &apps)
Discover functions using pre-discovered apps.
Avoids redundant ROS 2 graph introspection when apps have already been discovered in the same refresh cycle. Falls back to the no-arg overload for modes that don’t support this optimization (manifest-only, hybrid).
- Parameters:
apps – Pre-discovered apps (used only in RUNTIME_ONLY mode)
- Returns:
Vector of discovered Function entities
-
std::optional<App> get_app(const std::string &id)
Get app by ID.
- Parameters:
id – App identifier
- Returns:
App if found
-
std::optional<Function> get_function(const std::string &id)
Get function by ID.
- Parameters:
id – Function identifier
- Returns:
Function if found
-
std::vector<Area> get_subareas(const std::string &area_id)
Get subareas of an area.
- Parameters:
area_id – Parent area ID
- Returns:
Vector of child areas
-
std::vector<Component> get_subcomponents(const std::string &component_id)
Get subcomponents of a component.
- Parameters:
component_id – Parent component ID
- Returns:
Vector of child components
-
std::vector<Component> get_components_for_area(const std::string &area_id)
Get components in an area.
- Parameters:
area_id – Area ID
- Returns:
Vector of components in the area
-
std::vector<App> get_apps_for_component(const std::string &component_id)
Get apps for a component.
- Parameters:
component_id – Component ID
- Returns:
Vector of apps associated with the component
-
std::vector<std::string> get_hosts_for_function(const std::string &function_id)
Get host component IDs for a function.
- Parameters:
function_id – Function ID
- Returns:
Vector of component IDs that host the function
-
std::vector<ServiceInfo> discover_services()
Discover all services in the system.
- Returns:
Vector of ServiceInfo with schema information
-
std::vector<ActionInfo> discover_actions()
Discover all actions in the system.
- Returns:
Vector of ActionInfo with schema information
-
std::optional<ServiceInfo> find_service(const std::string &component_ns, const std::string &operation_name) const
Find a service by component namespace and operation name.
- Parameters:
component_ns – Component namespace
operation_name – Service name
- Returns:
ServiceInfo if found, nullopt otherwise
-
std::optional<ActionInfo> find_action(const std::string &component_ns, const std::string &operation_name) const
Find an action by component namespace and operation name.
- Parameters:
component_ns – Component namespace
operation_name – Action name
- Returns:
ActionInfo if found, nullopt otherwise
-
void set_topic_data_provider(TopicDataProvider *provider)
Set the topic sampler for component-topic mapping.
- Parameters:
provider – Pointer to TopicDataProvider (must outlive DiscoveryManager)
-
void set_type_introspection(TypeIntrospection *introspection)
Set the type introspection for operation schema enrichment.
- Parameters:
introspection – Pointer to TypeIntrospection (must outlive DiscoveryManager)
-
void refresh_topic_map()
Refresh the cached topic map.
-
bool is_topic_map_ready() const
Check if topic map has been built at least once.
- Returns:
true if topic map is ready, false if not yet built
-
void add_plugin_layer(const std::string &plugin_name, IntrospectionProvider *provider)
Add a plugin layer to the merge pipeline.
Wraps an IntrospectionProvider as a PluginLayer and adds it to the pipeline. Only works in HYBRID mode.
- Parameters:
plugin_name – Name of the plugin
provider – Non-owning pointer to IntrospectionProvider
-
void refresh_pipeline()
Re-execute the merge pipeline (hybrid mode only)
Call after adding plugin layers to trigger a single pipeline refresh.
-
discovery::ManifestManager *get_manifest_manager()
Get the manifest manager.
- Returns:
Pointer to manifest manager (nullptr if not using manifest)
-
bool has_host_info_provider() const
Check if a host info provider is active.
- Returns:
true if default component is enabled and provider exists
-
std::optional<Component> get_default_component() const
Get the default Component from HostInfoProvider.
- Returns:
Component entity representing the local host, or nullopt if not enabled
-
inline DiscoveryMode get_mode() const
Get current discovery mode.
- Returns:
Active discovery mode
-
std::string get_strategy_name() const
Get the current discovery strategy name.
- Returns:
Strategy name (e.g., “runtime”, “manifest”, “hybrid”)
-
std::optional<discovery::MergeReport> get_merge_report() const
Get the last merge pipeline report (hybrid mode only)
- Returns:
MergeReport if in hybrid mode, nullopt otherwise
-
std::optional<discovery::LinkingResult> get_linking_result() const
Get the last linking result (hybrid mode only)
- Returns:
LinkingResult if in hybrid mode, nullopt otherwise
-
class DataAccessManager
Public Functions
-
explicit DataAccessManager(rclcpp::Node *node)
-
json publish_to_topic(const std::string &topic_path, const std::string &msg_type, const json &data, double timeout_sec = 5.0)
Publish data to a specific topic.
- Parameters:
topic_path – Full topic path (e.g., /chassis/brakes/command)
msg_type – ROS 2 message type (e.g., std_msgs/msg/Float32)
data – JSON data to publish
timeout_sec – Timeout for the publish operation
- Returns:
JSON with publish status
-
json get_topic_sample_with_fallback(const std::string &topic_name, double timeout_sec = -1.0)
Get topic sample with fallback to metadata on timeout.
If the topic is publishing, returns actual data with type info. If the topic times out, returns metadata (type, schema, pub/sub counts) instead of error.
- Parameters:
topic_name – Full topic path (e.g., “/powertrain/engine/temperature”)
timeout_sec – Timeout for data retrieval. Use -1.0 to use the topic_sample_timeout_sec parameter (default)
- Throws:
TopicNotAvailableException – if topic doesn’t exist or metadata cannot be retrieved
- Returns:
JSON object with one of two structures:
status=”data”: {topic, timestamp, data, status, type, type_info, publisher_count, subscriber_count}
status=”metadata_only”: {topic, timestamp, status, type, type_info, publisher_count, subscriber_count}
-
inline TypeIntrospection *get_type_introspection() const
Get the type introspection instance.
-
inline void set_topic_data_provider(TopicDataProvider *provider)
Attach a TopicDataProvider for sampling.
The provider owns the pool-backed subscription path (issue #375 race fix). Non-owning pointer; caller retains ownership. Safe to call once at wiring time; no concurrent access to the setter.
-
inline TopicDataProvider *get_topic_data_provider() const
-
json get_topic_sample_native(const std::string &topic_name, double timeout_sec = 1.0)
Get single topic sample using native rclcpp APIs.
Fast path for single topic sampling with publisher count check.
- Parameters:
topic_name – Full topic path
timeout_sec – Timeout for sampling (only used if topic has publishers)
- Returns:
JSON with topic data or metadata
-
inline double get_topic_sample_timeout() const
Get the configured topic sample timeout.
- Returns:
Timeout in seconds for topic sampling
-
explicit DataAccessManager(rclcpp::Node *node)
-
class OperationManager
Manager for ROS2 operations (services and actions) Handles service calls synchronously and action calls asynchronously.
Public Functions
-
explicit OperationManager(rclcpp::Node *node, DiscoveryManager *discovery_manager)
-
~OperationManager()
-
OperationManager(const OperationManager&) = delete
-
OperationManager &operator=(const OperationManager&) = delete
-
OperationManager(OperationManager&&) = delete
-
OperationManager &operator=(OperationManager&&) = delete
-
void shutdown()
Explicitly release subscriptions, clients, and tracked goals.
Call while executor is still running to allow safe callback cleanup. Called automatically by destructor, but GatewayNode calls it earlier during its shutdown sequence.
-
void set_notifier(ResourceChangeNotifier *notifier)
Set optional notifier for broadcasting operation status changes to trigger subsystem.
-
ServiceCallResult call_service(const std::string &service_path, const std::string &service_type, const json &request)
Call a ROS2 service synchronously.
- Parameters:
service_path – Full service path (e.g., “/powertrain/engine/calibrate”)
service_type – Service type (e.g., “std_srvs/srv/Trigger”)
request – JSON request body
- Returns:
ServiceCallResult with response or error
-
ServiceCallResult call_component_service(const std::string &component_ns, const std::string &operation_name, const std::optional<std::string> &service_type, const json &request)
Find and call a service by component and operation name Uses discovery cache to resolve service path and type if not provided.
- Parameters:
component_ns – Component namespace (e.g., “/powertrain/engine”)
operation_name – Operation name (e.g., “calibrate”)
service_type – Optional service type override
request – JSON request body
- Returns:
ServiceCallResult with response or error
-
ActionSendGoalResult send_action_goal(const std::string &action_path, const std::string &action_type, const json &goal, const std::string &entity_id = "")
Send a goal to an action server using native rclcpp_action internal services.
- Parameters:
action_path – Full action path (e.g., “/powertrain/engine/long_calibration”)
action_type – Action type (e.g., “example_interfaces/action/Fibonacci”)
goal – JSON goal data
entity_id – SOVD entity ID for trigger notifications (e.g., “engine”)
- Returns:
ActionSendGoalResult with goal_id or error
-
ActionSendGoalResult send_component_action_goal(const std::string &component_ns, const std::string &operation_name, const std::optional<std::string> &action_type, const json &goal, const std::string &entity_id = "")
Send a goal to an action using component namespace and operation name Uses discovery cache to resolve action path and type if not provided.
- Parameters:
component_ns – Component namespace (e.g., “/powertrain/engine”)
operation_name – Operation name (e.g., “long_calibration”)
action_type – Optional action type override
goal – JSON goal data
entity_id – SOVD entity ID for trigger notifications (e.g., “engine”)
- Returns:
ActionSendGoalResult with goal_id or error
-
ActionCancelResult cancel_action_goal(const std::string &action_path, const std::string &goal_id)
Cancel a running action goal using ros2 action cancel.
- Parameters:
action_path – Full action path
goal_id – Goal UUID hex string
- Returns:
ActionCancelResult
-
ActionGetResultResult get_action_result(const std::string &action_path, const std::string &action_type, const std::string &goal_id)
Get the result of a completed action This is a blocking call that waits for the action to complete.
- Parameters:
action_path – Full action path
action_type – Action type
goal_id – Goal UUID hex string
- Returns:
ActionGetResultResult with result or error
-
std::optional<ActionGoalInfo> get_tracked_goal(const std::string &goal_id) const
Get tracked goal info by goal_id.
- Parameters:
goal_id – Goal UUID hex string
- Returns:
Optional ActionGoalInfo if found
-
std::vector<ActionGoalInfo> list_tracked_goals() const
List all tracked goals.
- Returns:
Vector of all tracked goals
-
std::vector<ActionGoalInfo> get_goals_for_action(const std::string &action_path) const
Get all goals for a specific action path.
- Parameters:
action_path – Full action path (e.g., “/powertrain/engine/long_calibration”)
- Returns:
Vector of goals for that action, sorted by last_update (newest first)
-
std::optional<ActionGoalInfo> get_latest_goal_for_action(const std::string &action_path) const
Get the most recent goal for a specific action path.
- Parameters:
action_path – Full action path
- Returns:
Optional ActionGoalInfo if any goal exists for this action
-
void update_goal_status(const std::string &goal_id, ActionGoalStatus status)
Update goal status in tracking.
- Parameters:
goal_id – Goal UUID hex string
status – New status
-
void update_goal_feedback(const std::string &goal_id, const json &feedback)
Update goal feedback in tracking.
- Parameters:
goal_id – Goal UUID hex string
feedback – New feedback JSON
-
void cleanup_old_goals(std::chrono::seconds max_age = std::chrono::seconds(300))
Remove completed goals older than specified duration.
- Parameters:
max_age – Maximum age of completed goals to keep
-
void subscribe_to_action_status(const std::string &action_path)
Subscribe to action status topic for real-time updates Called automatically when a goal is sent.
- Parameters:
action_path – Full action path (e.g., “/powertrain/engine/long_calibration”)
-
void unsubscribe_from_action_status(const std::string &action_path)
Unsubscribe from action status topic Called when no more active goals exist for this action.
- Parameters:
action_path – Full action path
Public Static Functions
-
static bool is_valid_message_type(const std::string &type)
Validate message type format (package/srv/Type or package/action/Type)
-
static bool is_valid_uuid_hex(const std::string &uuid_hex)
Validate UUID hex string format (32 hex characters)
-
static bool is_service_type(const std::string &type)
Check if type is a service type (contains /srv/)
-
static bool is_action_type(const std::string &type)
Check if type is an action type (contains /action/)
-
explicit OperationManager(rclcpp::Node *node, DiscoveryManager *discovery_manager)
-
class ConfigurationManager
Manager for ROS2 node parameters Provides CRUD operations on node parameters via native rclcpp APIs Also caches initial parameter values as “defaults” for reset operations.
Public Functions
-
explicit ConfigurationManager(rclcpp::Node *node)
-
~ConfigurationManager()
-
ConfigurationManager(const ConfigurationManager&) = delete
-
ConfigurationManager &operator=(const ConfigurationManager&) = delete
-
ConfigurationManager(ConfigurationManager&&) = delete
-
ConfigurationManager &operator=(ConfigurationManager&&) = delete
-
void shutdown()
Clean up shared param node and cached clients before ROS 2 context shutdown.
Must be called before rclcpp::shutdown() to prevent use-after-free. Idempotent - safe to call multiple times.
-
ParameterResult list_parameters(const std::string &node_name)
List all parameters for a node.
- Parameters:
node_name – Fully qualified node name (e.g., “/powertrain/engine/engine_temp_sensor”)
- Returns:
ParameterResult with array of {name, value, type} objects
-
ParameterResult get_parameter(const std::string &node_name, const std::string ¶m_name)
Get a specific parameter value.
- Parameters:
node_name – Fully qualified node name
param_name – Parameter name
- Returns:
ParameterResult with {name, value, type, description, read_only}
-
ParameterResult set_parameter(const std::string &node_name, const std::string ¶m_name, const json &value)
Set a parameter value.
- Parameters:
node_name – Fully qualified node name
param_name – Parameter name
value – New value (JSON type will be converted to appropriate ROS2 type)
- Returns:
ParameterResult with {name, value, type}
-
ParameterResult reset_parameter(const std::string &node_name, const std::string ¶m_name)
Reset a specific parameter to its default (initial) value.
- Parameters:
node_name – Fully qualified node name
param_name – Parameter name
- Returns:
ParameterResult with reset parameter info
-
ParameterResult reset_all_parameters(const std::string &node_name)
Reset all parameters of a node to their default (initial) values.
- Parameters:
node_name – Fully qualified node name
- Returns:
ParameterResult with count of reset parameters
-
explicit ConfigurationManager(rclcpp::Node *node)
Data Models
-
struct QosProfile
QoS profile information for a topic endpoint.
Public Functions
-
inline json to_json() const
Public Members
-
std::string reliability
“reliable”, “best_effort”, “system_default”, “unknown”
-
std::string durability
“volatile”, “transient_local”, “system_default”, “unknown”
-
std::string history
“keep_last”, “keep_all”, “system_default”, “unknown”
-
size_t depth = {0}
History depth (for keep_last)
-
std::string liveliness
“automatic”, “manual_by_topic”, “system_default”, “unknown”
-
inline json to_json() const
-
struct TopicEndpoint
Information about an endpoint (publisher or subscriber) on a topic.
Public Functions
-
inline std::string fqn() const
Get fully qualified node name.
-
inline json to_json() const
Public Members
-
std::string node_name
Name of the node (e.g., “controller_server”)
-
std::string node_namespace
Namespace of the node (e.g., “/navigation”)
-
std::string topic_type
Message type (e.g., “geometry_msgs/msg/Twist”)
-
QosProfile qos
QoS profile of this endpoint.
-
inline std::string fqn() const
-
struct TopicConnection
Topic with its publishers and subscribers.
Public Functions
-
inline json to_json() const
Public Members
-
std::string topic_name
Full topic path (e.g., “/cmd_vel”)
-
std::string topic_type
Message type.
-
std::vector<TopicEndpoint> publishers
-
std::vector<TopicEndpoint> subscribers
-
inline json to_json() const
-
struct Area
SOVD Area entity - represents a logical grouping (ROS 2 namespace)
Areas are derived from ROS 2 namespaces or defined in manifests. They provide a hierarchical organization of components.
Public Functions
-
inline json to_json() const
Convert to JSON representation.
SOVD EntityReference fields: id, name, href, translation_id, tags ROS 2 extensions in x-medkit: namespace, type, description, parentAreaId
- Returns:
JSON object with area data
-
inline json to_entity_reference(const std::string &base_url) const
Create SOVD EntityReference format (strictly compliant)
- Parameters:
base_url – Base URL for self links
- Returns:
JSON object in EntityReference format: id, name, href, [translationId, tags]
-
inline json to_capabilities(const std::string &base_url) const
Create SOVD Entity Capabilities format (strictly compliant)
- Parameters:
base_url – Base URL for capability links
- Returns:
JSON object listing available sub-resources
Public Members
-
std::string id
Unique identifier (e.g., “powertrain”)
-
std::string name
Human-readable name (e.g., “Powertrain System”)
-
std::string namespace_path
ROS 2 namespace path (e.g., “/powertrain”)
-
std::string type = "Area"
Entity type (always “Area”)
-
std::string translation_id
Internationalization key.
-
std::string description
Human-readable description.
-
std::vector<std::string> tags
Tags for filtering.
-
std::string parent_area_id
Parent area ID for sub-areas.
-
std::string source
Origin of this area (e.g., “manifest”, “heuristic”)
-
std::vector<std::string> contributors
Aggregation provenance: “local” and/or “peer:<name>”.
-
inline json to_json() const
-
struct Component
SOVD Component entity - represents a software/hardware component (ROS 2 node)
Components are derived from ROS 2 nodes or defined in manifests. They expose operations (services/actions), data (topics), and configurations (parameters).
Public Functions
-
inline json to_json() const
Convert to JSON representation.
SOVD EntityReference fields: id, name, href, translation_id, tags ROS 2 extensions in x-medkit: namespace, fqn, entityType, area, source, variant, etc.
- Returns:
JSON object with component data
-
inline json to_entity_reference(const std::string &base_url) const
Create SOVD EntityReference format (strictly compliant)
- Parameters:
base_url – Base URL for self links
- Returns:
JSON object in EntityReference format: id, name, href, [translationId, tags]
-
inline json to_capabilities(const std::string &base_url) const
Create SOVD Entity Capabilities format (strictly compliant)
- Parameters:
base_url – Base URL for capability links
- Returns:
JSON object listing available sub-resources
Public Members
-
std::string id
Unique identifier (node name)
-
std::string name
Human-readable name.
-
std::string namespace_path
ROS 2 namespace path.
-
std::string fqn
Fully qualified name (namespace + id)
-
std::string type = "Component"
Entity type (always “Component”)
-
std::string area
Parent area ID.
-
std::string source = "node"
Discovery source: “node”, “topic”, or “manifest”.
-
std::string translation_id
Internationalization key.
-
std::string description
Human-readable description.
-
std::string variant
Hardware variant identifier.
-
std::vector<std::string> tags
Tags for filtering.
-
std::string parent_component_id
Parent component ID for sub-components.
-
std::vector<std::string> contributors
Aggregation provenance: “local” and/or “peer:<name>”.
-
std::vector<ServiceInfo> services
Services exposed by this component.
-
std::vector<ActionInfo> actions
Actions exposed by this component.
-
ComponentTopics topics
Topics this component publishes/subscribes.
-
std::optional<json> host_metadata
Host system metadata (for runtime default component)
-
inline json to_json() const
ros2_medkit_fault_manager
Central fault storage and management node.
-
class FaultManagerNode : public rclcpp::Node
Central fault manager node.
Provides service interfaces for fault reporting, querying, and clearing. Supports configurable storage backends (memory or SQLite) via ROS parameters.
Parameters:
storage_type (string): “memory” or “sqlite” (default: “sqlite”)
database_path (string): Path to SQLite database file (default: “/var/lib/ros2_medkit/faults.db”) Use “:memory:” for in-memory SQLite database (useful for testing)
Public Functions
-
explicit FaultManagerNode(const rclcpp::NodeOptions &options = rclcpp::NodeOptions())
-
~FaultManagerNode() override
-
FaultManagerNode(const FaultManagerNode&) = delete
-
FaultManagerNode &operator=(const FaultManagerNode&) = delete
-
FaultManagerNode(FaultManagerNode&&) = delete
-
FaultManagerNode &operator=(FaultManagerNode&&) = delete
-
inline const FaultStorage &get_storage() const
Get read-only access to fault storage (for testing)
-
inline const std::string &get_storage_type() const
Get the storage type being used.
Public Static Functions
-
static bool matches_entity(const std::vector<std::string> &reporting_sources, const std::string &entity_id)
Check if entity matches any reporting source.
- Parameters:
reporting_sources – List of reporting sources from fault
entity_id – Entity ID to match (exact match or as suffix of FQN)
- Returns:
true if entity_id matches any source
-
class FaultStorage
Abstract interface for fault storage backends.
Subclassed by ros2_medkit_fault_manager::InMemoryFaultStorage, ros2_medkit_fault_manager::SqliteFaultStorage
Public Functions
-
virtual ~FaultStorage() = default
-
virtual void set_debounce_config(const DebounceConfig &config) = 0
Set debounce configuration.
-
virtual DebounceConfig get_debounce_config() const = 0
Get current debounce configuration.
-
virtual bool report_fault_event(const std::string &fault_code, uint8_t event_type, uint8_t severity, const std::string &description, const std::string &source_id, const rclcpp::Time ×tamp, const DebounceConfig &config) = 0
Report a fault event (FAILED or PASSED)
- Parameters:
fault_code – Global fault identifier
event_type – EVENT_FAILED (0) or EVENT_PASSED (1)
severity – Fault severity level (only used for FAILED events)
description – Human-readable description (only used for FAILED events)
source_id – Reporting source identifier
timestamp – Current time for tracking
config – Debounce configuration to apply for this event (resolved per-entity by the node)
- Returns:
true if this is a new occurrence (new fault or reactivated CLEARED fault), false if existing active fault was updated
-
virtual std::vector<ros2_medkit_msgs::msg::Fault> list_faults(bool filter_by_severity, uint8_t severity, const std::vector<std::string> &statuses) const = 0
Get faults matching filter criteria.
- Parameters:
filter_by_severity – Whether to filter by severity
severity – Severity level to filter (if filter_by_severity is true)
statuses – List of statuses to include (empty = CONFIRMED only)
- Returns:
Vector of matching faults
-
virtual std::optional<ros2_medkit_msgs::msg::Fault> get_fault(const std::string &fault_code) const = 0
Get a single fault by fault_code.
- Parameters:
fault_code – The fault code to look up
- Returns:
The fault if found, nullopt otherwise
-
virtual bool clear_fault(const std::string &fault_code) = 0
Clear a fault by fault_code (manual acknowledgment)
- Parameters:
fault_code – The fault code to clear
- Returns:
true if fault was found and cleared, false if not found
-
virtual size_t size() const = 0
Get total number of stored faults.
-
virtual bool contains(const std::string &fault_code) const = 0
Check if a fault exists.
-
virtual size_t check_time_based_confirmation(const rclcpp::Time ¤t_time) = 0
Check and confirm PREFAILED faults that have been pending too long (time-based confirmation)
- Parameters:
current_time – Current timestamp for age calculation
- Returns:
Number of faults that were confirmed
-
inline virtual void set_max_snapshots_per_fault(size_t)
Set maximum snapshots per fault code (0 = unlimited)
-
virtual void store_snapshot(const SnapshotData &snapshot) = 0
Store a snapshot captured when a fault was confirmed.
- Parameters:
snapshot – The snapshot data to store
-
virtual std::vector<SnapshotData> get_snapshots(const std::string &fault_code, const std::string &topic_filter = "") const = 0
Get snapshots for a fault.
- Parameters:
fault_code – The fault code to get snapshots for
topic_filter – Optional topic filter (empty = all topics)
- Returns:
Vector of snapshots for the fault
-
virtual void store_rosbag_file(const RosbagFileInfo &info) = 0
Store rosbag file metadata for a fault.
- Parameters:
info – The rosbag file info to store (replaces any existing entry for fault_code)
-
virtual std::optional<RosbagFileInfo> get_rosbag_file(const std::string &fault_code) const = 0
Get rosbag file info for a fault.
- Parameters:
fault_code – The fault code to get rosbag for
- Returns:
Rosbag file info if exists, nullopt otherwise
-
virtual bool delete_rosbag_file(const std::string &fault_code) = 0
Delete rosbag file record and the actual file for a fault.
- Parameters:
fault_code – The fault code to delete rosbag for
- Returns:
true if record was deleted, false if not found
-
virtual size_t get_total_rosbag_storage_bytes() const = 0
Get total size of all stored rosbag files in bytes.
- Returns:
Total size in bytes
-
virtual std::vector<RosbagFileInfo> get_all_rosbag_files() const = 0
Get all rosbag files ordered by creation time (oldest first)
- Returns:
Vector of rosbag file info
-
virtual std::vector<RosbagFileInfo> list_rosbags_for_entity(const std::string &entity_fqn) const = 0
Get rosbags for all faults associated with an entity.
- Parameters:
entity_fqn – The entity’s fully qualified name to filter by
- Returns:
Vector of rosbag file info for faults reported by this entity
-
virtual std::vector<ros2_medkit_msgs::msg::Fault> get_all_faults() const = 0
Get all stored faults regardless of status (for filtering)
- Returns:
Vector of all faults in storage
-
virtual ~FaultStorage() = default
-
class InMemoryFaultStorage : public ros2_medkit_fault_manager::FaultStorage
Thread-safe in-memory fault storage implementation.
Public Functions
-
InMemoryFaultStorage() = default
-
virtual void set_debounce_config(const DebounceConfig &config) override
Set debounce configuration.
-
virtual DebounceConfig get_debounce_config() const override
Get current debounce configuration.
-
virtual bool report_fault_event(const std::string &fault_code, uint8_t event_type, uint8_t severity, const std::string &description, const std::string &source_id, const rclcpp::Time ×tamp, const DebounceConfig &config) override
Report a fault event (FAILED or PASSED)
- Parameters:
fault_code – Global fault identifier
event_type – EVENT_FAILED (0) or EVENT_PASSED (1)
severity – Fault severity level (only used for FAILED events)
description – Human-readable description (only used for FAILED events)
source_id – Reporting source identifier
timestamp – Current time for tracking
config – Debounce configuration to apply for this event (resolved per-entity by the node)
- Returns:
true if this is a new occurrence (new fault or reactivated CLEARED fault), false if existing active fault was updated
-
virtual std::vector<ros2_medkit_msgs::msg::Fault> list_faults(bool filter_by_severity, uint8_t severity, const std::vector<std::string> &statuses) const override
Get faults matching filter criteria.
- Parameters:
filter_by_severity – Whether to filter by severity
severity – Severity level to filter (if filter_by_severity is true)
statuses – List of statuses to include (empty = CONFIRMED only)
- Returns:
Vector of matching faults
-
virtual std::optional<ros2_medkit_msgs::msg::Fault> get_fault(const std::string &fault_code) const override
Get a single fault by fault_code.
- Parameters:
fault_code – The fault code to look up
- Returns:
The fault if found, nullopt otherwise
-
virtual bool clear_fault(const std::string &fault_code) override
Clear a fault by fault_code (manual acknowledgment)
- Parameters:
fault_code – The fault code to clear
- Returns:
true if fault was found and cleared, false if not found
-
virtual size_t size() const override
Get total number of stored faults.
-
virtual bool contains(const std::string &fault_code) const override
Check if a fault exists.
-
virtual size_t check_time_based_confirmation(const rclcpp::Time ¤t_time) override
Check and confirm PREFAILED faults that have been pending too long (time-based confirmation)
- Parameters:
current_time – Current timestamp for age calculation
- Returns:
Number of faults that were confirmed
-
virtual void set_max_snapshots_per_fault(size_t max_count) override
Set maximum snapshots per fault code (0 = unlimited)
-
virtual void store_snapshot(const SnapshotData &snapshot) override
Store a snapshot captured when a fault was confirmed.
- Parameters:
snapshot – The snapshot data to store
-
virtual std::vector<SnapshotData> get_snapshots(const std::string &fault_code, const std::string &topic_filter = "") const override
Get snapshots for a fault.
- Parameters:
fault_code – The fault code to get snapshots for
topic_filter – Optional topic filter (empty = all topics)
- Returns:
Vector of snapshots for the fault
-
virtual void store_rosbag_file(const RosbagFileInfo &info) override
Store rosbag file metadata for a fault.
- Parameters:
info – The rosbag file info to store (replaces any existing entry for fault_code)
-
virtual std::optional<RosbagFileInfo> get_rosbag_file(const std::string &fault_code) const override
Get rosbag file info for a fault.
- Parameters:
fault_code – The fault code to get rosbag for
- Returns:
Rosbag file info if exists, nullopt otherwise
-
virtual bool delete_rosbag_file(const std::string &fault_code) override
Delete rosbag file record and the actual file for a fault.
- Parameters:
fault_code – The fault code to delete rosbag for
- Returns:
true if record was deleted, false if not found
-
virtual size_t get_total_rosbag_storage_bytes() const override
Get total size of all stored rosbag files in bytes.
- Returns:
Total size in bytes
-
virtual std::vector<RosbagFileInfo> get_all_rosbag_files() const override
Get all rosbag files ordered by creation time (oldest first)
- Returns:
Vector of rosbag file info
-
virtual std::vector<RosbagFileInfo> list_rosbags_for_entity(const std::string &entity_fqn) const override
Get rosbags for all faults associated with an entity.
- Parameters:
entity_fqn – The entity’s fully qualified name to filter by
- Returns:
Vector of rosbag file info for faults reported by this entity
-
virtual std::vector<ros2_medkit_msgs::msg::Fault> get_all_faults() const override
Get all stored faults regardless of status (for filtering)
- Returns:
Vector of all faults in storage
-
InMemoryFaultStorage() = default
ros2_medkit_fault_reporter
Client library for reporting faults to the fault manager.
-
class FaultReporter
Client library for reporting faults to the central FaultManager.
Provides a simple API for ROS 2 nodes to report faults with optional local filtering to reduce noise from repeated fault occurrences.
Example usage:
class MyNode : public rclcpp::Node { public: MyNode() : Node("my_node") { reporter_ = std::make_unique<FaultReporter>( shared_from_this(), get_fully_qualified_name()); } void on_error() { reporter_->report("SENSOR_FAILURE", Fault::SEVERITY_ERROR, "Sensor timeout"); } private: std::unique_ptr<FaultReporter> reporter_; };
Public Functions
Construct a FaultReporter.
- Parameters:
node – The ROS 2 node to use for service client and parameters
source_id – Identifier for this reporter (typically node’s FQN)
service_name – Name of the ReportFault service (default: /fault_manager/report_fault)
-
void report(const std::string &fault_code, uint8_t severity, const std::string &description)
Report a FAILED event (fault occurrence)
The fault will be forwarded to the FaultManager if local filtering allows it (threshold met within time window, or high severity).
- Parameters:
fault_code – Global fault identifier (e.g., “MOTOR_OVERHEAT”)
severity – Severity level (use Fault::SEVERITY_* constants)
description – Human-readable fault description
-
void report_passed(const std::string &fault_code)
Report a PASSED event (fault condition cleared)
PASSED events bypass local filtering and are always forwarded to FaultManager. Use this when the condition that caused a fault is no longer present.
- Parameters:
fault_code – Global fault identifier (must match a previously reported fault)
-
bool is_service_ready() const
Check if the FaultManager service is available.
-
inline const LocalFilter &filter() const
Get read-only access to the local filter (for testing)
-
class LocalFilter
Local filter for fault reports.
Tracks fault occurrences per fault_code and determines whether a report should be forwarded to the central FaultManager. Implements threshold-based filtering within a sliding time window.
Thread-safe: All public methods can be called from multiple threads.
Public Functions
-
explicit LocalFilter(const FilterConfig &config = FilterConfig{})
-
bool should_forward(const std::string &fault_code, uint8_t severity)
Check if a fault report should be forwarded.
- Parameters:
fault_code – The fault identifier
severity – The fault severity level
- Returns:
true if the report should be sent to FaultManager
-
bool should_forward_passed(const std::string &fault_code)
Check if a PASSED event should be forwarded.
-
void reset(const std::string &fault_code)
Reset tracking for a specific fault code.
-
void reset_all()
Reset all tracking state.
-
inline FilterConfig config() const
Get the current configuration (thread-safe copy)
-
void set_config(const FilterConfig &config)
Update configuration (clears existing state)
-
explicit LocalFilter(const FilterConfig &config = FilterConfig{})
ros2_medkit_diagnostic_bridge
Bridge node that converts ROS 2 /diagnostics messages to FaultManager faults.
-
class DiagnosticBridgeNode : public rclcpp::Node
Bridge node that converts ROS2 /diagnostics messages to FaultManager faults.
Subscribes to /diagnostics topic and forwards diagnostic status messages to the FaultManager via the ReportFault service.
Severity mapping:
OK (0) -> PASSED event (healing)
WARN (1) -> WARN severity (1)
ERROR (2) -> ERROR severity (2)
STALE (3) -> CRITICAL severity (3)
Example launch configuration:
diagnostic_bridge: ros__parameters: diagnostics_topic: "/diagnostics" auto_generate_codes: true # Custom mappings: "name_to_code.<diagnostic_name>": "<FAULT_CODE>" "name_to_code.motor_controller: Status": "MOTOR_001"
Public Functions
-
explicit DiagnosticBridgeNode(const rclcpp::NodeOptions &options = rclcpp::NodeOptions())
-
std::string map_to_fault_code(const std::string &diagnostic_name) const
Map diagnostic name to fault code Uses custom mapping if available, otherwise auto-generates from name.
Public Static Functions
-
static std::optional<uint8_t> map_to_severity(uint8_t diagnostic_level)
Map DiagnosticStatus level to Fault severity Returns std::nullopt if level is OK (should send PASSED instead)
-
static bool is_ok_level(uint8_t diagnostic_level)
Check if diagnostic level indicates OK status.
ros2_medkit_serialization
Runtime JSON ↔ ROS 2 message serialization library.
-
class JsonSerializer
JSON serializer for ROS 2 messages using dynmsg.
This class provides the main API for converting between JSON and ROS 2 messages at runtime. It uses dynmsg’s YAML capabilities internally and converts between JSON and YAML formats.
Note
This class is stateless and thread-safe.
Public Functions
-
JsonSerializer() = default
-
~JsonSerializer() = default
-
JsonSerializer(const JsonSerializer&) = delete
-
JsonSerializer &operator=(const JsonSerializer&) = delete
-
JsonSerializer(JsonSerializer&&) = default
-
JsonSerializer &operator=(JsonSerializer&&) = default
-
nlohmann::json to_json(const TypeInfo_Cpp *type_info, const void *message_data) const
Convert a ROS 2 message to JSON.
- Parameters:
type_info – Type introspection info
message_data – Pointer to the message data
- Throws:
JsonConversionError – if conversion fails
- Returns:
JSON representation of the message
-
nlohmann::json to_json(const std::string &type_string, const void *message_data) const
Convert a ROS 2 message to JSON using type string.
- Parameters:
type_string – Full type string (e.g., “std_msgs/msg/String”)
message_data – Pointer to the message data
- Throws:
TypeNotFoundError – if type cannot be loaded
JsonConversionError – if conversion fails
- Returns:
JSON representation of the message
-
RosMessage_Cpp from_json(const TypeInfo_Cpp *type_info, const nlohmann::json &json) const
Convert JSON to a ROS 2 message.
Note
Caller is responsible for calling ros_message_destroy_with_allocator
- Parameters:
type_info – Type introspection info
json – JSON data to convert
- Throws:
JsonConversionError – if conversion fails
- Returns:
RosMessage_Cpp containing allocated message data
-
RosMessage_Cpp from_json(const std::string &type_string, const nlohmann::json &json) const
Convert JSON to a ROS 2 message using type string.
Note
Caller is responsible for calling ros_message_destroy_with_allocator
- Parameters:
type_string – Full type string (e.g., “std_msgs/msg/String”)
json – JSON data to convert
- Throws:
TypeNotFoundError – if type cannot be loaded
JsonConversionError – if conversion fails
- Returns:
RosMessage_Cpp containing allocated message data
-
void from_json_to_message(const TypeInfo_Cpp *type_info, const nlohmann::json &json, void *message_data) const
Populate an existing message from JSON.
- Parameters:
type_info – Type introspection info
json – JSON data to convert
message_data – Pointer to pre-allocated message to populate
- Throws:
JsonConversionError – if conversion fails
-
nlohmann::json get_schema(const TypeInfo_Cpp *type_info) const
Generate a JSON schema for a ROS 2 type.
- Parameters:
type_info – Type introspection info
- Returns:
JSON schema object
-
nlohmann::json get_schema(const std::string &type_string) const
Generate a JSON schema using type string.
- Parameters:
type_string – Full type string
- Throws:
TypeNotFoundError – if type cannot be loaded
- Returns:
JSON schema object
-
nlohmann::json get_defaults(const TypeInfo_Cpp *type_info) const
Get default values for a ROS 2 type as JSON.
- Parameters:
type_info – Type introspection info
- Returns:
JSON object with default values
-
nlohmann::json get_defaults(const std::string &type_string) const
Get default values using type string.
- Parameters:
type_string – Full type string
- Throws:
TypeNotFoundError – if type cannot be loaded
- Returns:
JSON object with default values
-
rclcpp::SerializedMessage serialize(const std::string &type_string, const nlohmann::json &json) const
Serialize JSON to CDR format for use with GenericClient.
- Parameters:
type_string – Full type string (e.g., “std_srvs/srv/SetBool_Request”)
json – JSON data to serialize
- Throws:
TypeNotFoundError – if type cannot be loaded
SerializationError – if serialization fails
- Returns:
SerializedMessage containing CDR data
-
nlohmann::json deserialize(const std::string &type_string, const rclcpp::SerializedMessage &serialized_msg) const
Deserialize CDR data to JSON.
- Parameters:
type_string – Full type string
serialized_msg – SerializedMessage containing CDR data
- Throws:
TypeNotFoundError – if type cannot be loaded
SerializationError – if deserialization fails
- Returns:
JSON representation of the message
Public Static Functions
-
static nlohmann::json yaml_to_json(const YAML::Node &yaml)
Convert YAML node to JSON.
- Parameters:
yaml – YAML node to convert
- Returns:
JSON representation
-
static YAML::Node json_to_yaml(const nlohmann::json &json)
Convert JSON to YAML node.
- Parameters:
json – JSON to convert
- Returns:
YAML node representation
-
JsonSerializer() = default
-
class TypeCache
Thread-safe cache for ROS 2 type introspection data.
This class wraps dynmsg’s type loading functions and caches the results to avoid repeated dynamic library lookups. It is implemented as a singleton for global access throughout the gateway.
Note
All public methods are thread-safe.
Public Functions
-
const TypeInfo_Cpp *get_message_type_info(const std::string &package_name, const std::string &type_name)
Get type info for a message type (C++ introspection)
- Parameters:
package_name – Package name (e.g., “std_msgs”)
type_name – Type name without prefix (e.g., “String”)
- Returns:
Pointer to type info, or nullptr if not found
-
const TypeInfo_Cpp *get_message_type_info(const std::string &package_name, const std::string &interface_type, const std::string &type_name)
Get type info for any interface type (msg/srv/action)
- Parameters:
package_name – Package name (e.g., “std_srvs”)
interface_type – Interface type (“msg”, “srv”, or “action”)
type_name – Type name (e.g., “Trigger_Request”)
- Returns:
Pointer to type info, or nullptr if not found
-
const TypeInfo_Cpp *get_message_type_info(const std::string &full_type)
Get type info from full type string.
- Parameters:
full_type – Full type string (e.g., “std_msgs/msg/String” or “std_srvs/srv/Trigger_Request”)
- Returns:
Pointer to type info, or nullptr if not found
-
bool is_cached(const std::string &package_name, const std::string &type_name) const
Check if a type is cached.
- Parameters:
package_name – Package name
type_name – Type name
- Returns:
true if the type is in the cache
-
void clear()
Clear the cache.
-
size_t size() const
Get the number of cached types.
Public Static Functions
-
static std::optional<std::tuple<std::string, std::string, std::string>> parse_type_string(const std::string &full_type)
Parse a full type string into package, interface type, and type name.
- Parameters:
full_type – Full type string (e.g., “std_msgs/msg/String”)
- Returns:
Tuple of (package_name, interface_type, type_name), or nullopt if invalid format
-
const TypeInfo_Cpp *get_message_type_info(const std::string &package_name, const std::string &type_name)
-
class SerializationError : public std::runtime_error
Base class for all serialization errors.
Subclassed by ros2_medkit_serialization::JsonConversionError, ros2_medkit_serialization::MissingFieldError, ros2_medkit_serialization::TypeMismatchError, ros2_medkit_serialization::TypeNotFoundError, ros2_medkit_serialization::YamlConversionError
Public Functions
-
inline explicit SerializationError(const std::string &message)
-
inline explicit SerializationError(const std::string &message)
-
class TypeNotFoundError : public ros2_medkit_serialization::SerializationError
Error when type cannot be found or loaded.
-
class JsonConversionError : public ros2_medkit_serialization::SerializationError
Error during JSON parsing or conversion.
Public Functions
-
inline explicit JsonConversionError(const std::string &message)
-
inline explicit JsonConversionError(const std::string &message)