Parameter - Persistent Configuration

The Parameter-class manages persistent configuration data, which is stored in a SQLite database. Concept ——-

Parameter are permanent configuration values, which:

  • Are stored in a SQLite database

  • Persist between module restarts

  • Are accessible via ROS2 services

  • Are automatically validated

  • Support change events

Access via Entity

The easiest access is done via the VyraEntity:

from vyra_base.core.entity import VyraEntity

entity = VyraEntity(...)

# External access via ROS2 services (requires request/response objects)
value = await entity.param_manager.get_parameter(request, response)

# Internal access via _impl methods (direct, without ROS2 overhead)
result = await entity.param_manager.get_parameter_impl("max_speed")

Internal vs. External API

Parameter functions are available in two variants:

1. ROS2 Service Interface (@remote_service)
  • For external access via ROS2 services

  • Requires request and response objects

  • Used by other modules or external systems

  • Example: get_parameter(request, response)

2. Internal Implementation (_impl suffix)
  • For internal module use (Python code)

  • Direct function calls without ROS2 overhead

  • Returns Python dictionaries

  • Example: get_parameter_impl(key)

Tipp

When to use which?

  • Use _impl methods when calling from within your module

  • Use ROS2 services when calling from other modules or external systems

The _impl methods are faster as they skip the ROS2 serialization layer.

Read parameter

Single Parameter (Internal API)

For use within your module, use the _impl method:

# Direct internal call
result = await entity.param_manager.get_parameter_impl("max_speed")

if result and result["success"]:
    param_data = json.loads(result["value"])
    print(f"Max Speed: {param_data['value']}")
else:
    print(f"Error: {result['message'] if result else 'Unknown error'}")

Single Parameter (ROS2 Service)

For external access via ROS2 services:

# Request prepare
request = type('obj', (object,), {
    'key': 'max_speed'
})()
response = type('obj', (object,), {})()

# Call ROS2 service
await entity.param_manager.get_parameter(request, response)

if response.success:
    print(f"Value: {response.json_value}")

ROS2 CLI:

ros2 service call /module_name/get_parameter \\
    vyra_base_interfaces/srv/GetParameter \\
    "{key: 'max_speed'}"

All parameters (Internal API)

# Direct internal call
result = await entity.param_manager.read_all_params_impl()

if result:
    params = json.loads(result["all_params_json"])
    for param in params:
        print(f"{param['name']}: {param['value']}")

All parameters (ROS2 Service)

request = type('obj', (object,), {})()
response = type('obj', (object,), {})()

# Call ROS2 service
await entity.param_manager.read_all_params(request, response)

# Parse JSON response
params = json.loads(response.all_params_json)
for param in params:
    print(f"{param['name']}: {param['value']}")

Set parameter

Set Parameter (Internal API)

# Direct internal call
result = await entity.param_manager.set_parameter_impl(
    key="max_speed",
    value="120.0"
)

if result and result["success"]:
    print(f"✅ {result['message']}")
else:
    print(f"❌ Error: {result['message'] if result else 'Unknown error'}")

Set Parameter (ROS2 Service)

request = type('obj', (object,), {
    'key': 'max_speed',
    'value': '120.0'
})()
response = type('obj', (object,), {})()

# Call ROS2 service
await entity.param_manager.set_parameter(request, response)

if response.success:
    print(f"✅ {response.message}")
else:
    print(f"❌ {response.message}")

ROS2 CLI:

ros2 service call /module_name/set_parameter \\
    vyra_base_interfaces/srv/SetParameter \\
    "{key: 'max_speed', value: '120.0'}"

default values load

Parameter can be initialized from JSON files with default values:

# default values from JSON load
await entity.parameter.load_defaults(
    storage_access_default,  # optional: custom DB session, default: None
    reset  # optional: True = overwrite existing values, default: False
)

Example JSON structure:

{
    "parameters": [
        {
            "name": "max_speed",
            "value": "100.0",
            "description": "Maximale Geschwindigkeit"
        },
        {
            "name": "timeout",
            "value": "30",
            "description": "Timeout in seconds"
        }
    ]
}

Change-Events

Monitor parameter changes in real-time:

Get Event Topic (Internal API)

# Direct internal call
result = await entity.param_manager.param_changed_topic_impl()

if result:
    event_topic = result["topic"]
    print(f"Parameter change topic: {event_topic}")

    # Subscribe to topic
    entity.node.create_subscription(
        UpdateParamEvent,
        event_topic,
        callback=on_param_changed,
        qos_profile=10
    )

Get Event Topic (ROS2 Service)

# Query event topic via ROS2 service
request = type('obj', (object,), {})()
response = type('obj', (object,), {})()

await entity.param_manager.param_changed_topic(request, response)
event_topic = response.topic

# Subscribe to the topic (via ROS2)
# The event is triggered on every parameter change

Storage

Storage Location: /workspace/storage/data/<module_name>.db

The SQLite database stores parameters in the following structure:

  • Table name: tb_parameters (See Storage - Data Storage)

  • Columns: name, value, description, timestamp

  • Access: Via SQLAlchemy ORM

Bemerkung

Parameter database tables follow the naming convention tb_<name>. Further information about table structure can be found under Storage - Data Storage.

Use Cases

Parameter are suitable for:

Recommended:

  • Configuration values (Timeouts, Limits, thresholds)

  • calibration data

  • user preferences

  • system settings

Not recommended:

Performance Notes

Warnung

Database accesses are relatively slow (~1-10ms). Avoid frequent parameter updates in real-time loops.

Tipp

Cache frequently read parameters in local variables:

max_speed = await entity.parameter.get_parameter(...)

# In loop use (without DB-Access)
for i in range(1000):
    if speed > max_speed:
        # ...

Further Information