Actions¶
Executable context-aware behaviors for your robotic system.
Actions are not just static function calls; they are dynamic, context-aware routines that can adapt their parameters in real-time based on live system data.
They can represent:
Component Behaviors - Routines defined within your components. e.g., Stopping the robot, executing a motion pattern, or saying a sentence.
System Behaviors - Lifecycle management, configuration and plumbing. e.g., Reconfiguring a node, restarting a driver, or re-routing input streams.
User Custom Behaviors - Arbitrary Python functions. e.g., Calling an external REST API, logging to a file, or sending a slack notification.
Trigger Mechanisms¶
Actions sit dormant until activated by one of two mechanisms:
Event-Driven (Reflexive) - Triggered instantly when a specific Event condition is met. Example: “Obstacle Detected” \(\rightarrow\)
stop_robot()Fallback-Driven (Restorative) - Triggered automatically by a Component when its internal Health Status degrades. Example: “Camera Driver Failed” \(\rightarrow\)
restart_driver()
The Action Class¶
At its core, the Action class is a wrapper around any Python callable. It packages a function along with its arguments, preparing them for execution at runtime.
But unlike standard Python functions, Sugarcoat Actions possess a superpower: Dynamic Data Injection. You can bind their arguments directly to live ROS2 Topics, allowing the Action to fetch the latest topic message or a specific message argument the moment it triggers.
class Action:
def __init__(self, method: Callable, args: tuple = (), kwargs: Optional[Dict] = None):
method: The function or routine to execute.
args: Positional arguments (can be static values OR dynamic Topic values).
kwargs: Keyword arguments (can be static values OR dynamic Topic values).
Basic Usage¶
from ros_sugar.component import BaseComponent
from ros_sugar.core import Action
import logging
def custom_routine():
logging.info("I am executing an action!")
my_component = BaseComponent(node_name='test_component')
# 1. Component Method
action1 = Action(method=my_component.start)
# 2. Method with keyword arguments
action2 = Action(method=my_component.update_parameter, kwargs={"param_name": "fallback_rate", "new_value": 1000})
# 3. External Function
action3 = Action(method=custom_routine)
Dynamic Data Injection¶
This is Sugarcoat’s superpower.
You can create complex, context-aware behaviors without writing any “glue code” or custom parsers.
When you bind an Action argument to a Topic, the system automatically resolves the binding at runtime, fetching the current value from the topic attributes and injecting it into your function.
Example: Cross-Topic Data Access¶
Scenario: An event occurs on Topic 1. You want to log a message that includes the current status from Topic 2 and a sensor reading from Topic 3.
from ros_sugar.core import Event, Action
from ros_sugar.io import Topic
# 1. Define Topics
topic_1 = Topic(name="system_alarm", msg_type="Bool")
topic_2 = Topic(name="robot_mode", msg_type="String")
topic_3 = Topic(name="battery_voltage", msg_type="Float32")
# 2. Define the Event
# Trigger when Topic 1 becomes True
event_on_first_topic = Event(topic_1.msg.data.is_true())
# 3. Define the Target Function
def log_context_message(mode, voltage):
print(f"System Alarm! Current Mode: {mode}, Voltage: {voltage}V")
# 4. Define the Dynamic Action
# We bind the function arguments directly to the data fields of Topic 2 and Topic 3
my_action = Action(
method=log_context_message,
# At runtime, these are replaced by the actual values from the topics
args=(topic_2.msg.data, topic_3.msg.data)
)
Pre-defined Actions¶
Sugarcoat provides a suite of pre-defined, thread-safe actions for managing components and system resources via the ros_sugar.actions module.
Import Note
All pre-defined actions are keyword-only arguments. They can be imported directly:
from ros_sugar.actions import start, stop, reconfigure
Component-Level Actions¶
These actions directly manipulate the state or configuration of a specific BaseComponent derived object.
Action Method |
Arguments |
Description |
|---|---|---|
|
|
Triggers the component’s Lifecycle transition to Active. |
|
|
Triggers the component’s Lifecycle transition to Inactive. |
|
|
Stops the component, waits |
|
|
Reloads the component with a new configuration object or file path. |
|
|
Updates a single configuration parameter. |
|
|
Updates multiple configuration parameters simultaneously. |
|
|
Sends a request to the component’s main service with a specific message. |
|
|
Triggers the component’s main service. |
|
|
Sends a goal to the component’s main action server with a specific message. |
|
|
Triggers the component’s main action server. |
System-Level Actions¶
These actions interact with the broader ROS2 system and are executed by the central Monitor.
Action Method |
Arguments |
Description |
|---|---|---|
|
|
Logs a message to the ROS console. |
|
|
Publishes a specific message to a topic. Can be single-shot or periodic. |
|
|
Sends a request to a ROS 2 Service with a specific message. |
|
|
Triggers the a given ROS2 service. |
|
|
Sends a specific goal to a ROS 2 Action Server. |
|
|
Triggers a given ROS2 action server. |
Automatic Data Conversion
When using trigger_* actions paired with an Event, Sugarcoat attempts to create the required service/action request from the incoming Event topic data automatically via duck typing.
If automatic conversion is not possible, or if the action is not paired with an Event, it sends a default (empty) request.