ros2_medkit_param_beacon

This section contains design documentation for the ros2_medkit_param_beacon plugin.

Overview

The ros2_medkit_param_beacon package implements a gateway discovery plugin that collects beacon hints from ROS 2 nodes via their parameter servers. Nodes declare discovery metadata as ROS 2 parameters under a configurable prefix (default ros2_medkit.discovery), and the plugin polls these parameters periodically to build BeaconHint structs.

This plugin implements both the GatewayPlugin and IntrospectionProvider interfaces. It uses the shared ros2_medkit_beacon_common library for hint storage, validation, entity mapping, and response building. See the beacon common design for details on those components.

How It Works

  1. During each poll cycle, the plugin retrieves the current list of ROS 2 nodes from the gateway’s entity cache

  2. For each node, it creates (or reuses) an AsyncParametersClient and fetches all parameters matching the configured prefix

  3. Parameters are parsed into a BeaconHint: entity_id, stable_id, function_ids, metadata.* keys, etc.

  4. Validated hints are stored in the BeaconHintStore

  5. On each introspect() call, the store is snapshot and mapped to an IntrospectionResult via BeaconEntityMapper

Key Design Points

Polling Model

Unlike the topic beacon (push-based), the parameter beacon uses a pull model. A background thread polls nodes at a configurable interval (default 5 seconds). This is appropriate for parameters because they change infrequently and nodes do not need to actively publish discovery information - they only need to set their parameters once at startup.

Client Management

The plugin maintains a cache of AsyncParametersClient instances keyed by node FQN. Clients for nodes that disappear from the graph are evicted after a configurable timeout. A lock ordering protocol (nodes_mutex_ then clients_mutex_ then param_ops_mutex_) prevents deadlocks between the poll thread and the introspection callback.

Backoff and Budget

Nodes that fail to respond (timeout, unavailable) accumulate a backoff counter. Subsequent poll cycles skip backed-off nodes with exponentially increasing skip counts. A per-cycle time budget (default 10 seconds) prevents a few slow nodes from starving the rest of the poll targets. The start offset rotates each cycle so that all nodes eventually get polled even under budget pressure.

Injectable Client Factory

The plugin constructor accepts an optional ParameterClientFactory for dependency injection. Unit tests provide a mock factory that returns ParameterClientInterface stubs, enabling full testing without a running ROS 2 graph.

Integration with Gateway

The plugin registers the x-medkit-beacon vendor extension capability on Apps and exposes HTTP endpoints for querying individual beacon metadata. Route registration and capability handling follow the standard gateway plugin pattern via PluginContext.