ros_sugar.core._action_registry#
What a running stack can be asked to do, by name.
At launch an action is a Python callable a recipe already holds. At runtime a caller has only a string, and no way of knowing which component owns the thing it names. This registry is the translation between the two: it is built once from the components the Launcher knows about, and every runtime reference is resolved against it.
A reference is "owner/name" – the component’s node name and one of the
things it exposes:
registry = SystemActionRegistry.from_components([planner, driver])
registry.get("driver/move_to_unblock") # a @component_action method
registry.get("planner/plan_path") # its main action server
registry.get("planner/save_plan_to_file") # an additional service
registry.get("controller/track_vision_target") # an additional action server
Resolution stops here: turning an entry into something callable needs the Monitor’s clients, so it lives on the Monitor. This module stays ROS free.
Everything a component exposes is registered, including the lifecycle actions
every component inherits: a mission routine legitimately wants
driver/restart. A consumer that must not offer some of them filters for
itself, on whatever it considers dangerous.
NOTE: unrelated to :class:ros_sugar.robot.ActionRegistry, which is a registry
of factories producing Actions for robot plugins.
Module Contents#
Classes#
One thing the running stack can be asked to do. |
|
One condition the running stack can be asked to watch for. |
|
Every action the running stack exposes, addressable by name. |
API#
- class ros_sugar.core._action_registry.RegisteredAction#
Bases:
ros_sugar.config.base_attrs.BaseAttrsOne thing the running stack can be asked to do.
- Parameters:
ref – How a caller names it, as “owner/name”
owner – Node name of the component that runs it, or “monitor”
name – The short name within that owner. Never contains a slash, so a reference always splits cleanly
kind – Which resolution path applies, one of the module constants. The Monitor dispatches on this
description – What it does, for a caller listing what is available
schema – Its tool schema, whole, for a caller that builds tool calls from it. A component method has one when
@component_action(description=...)was given a dict, and none when it was described in prose; a plugin’s action always has one, since the plugin’s own registry makes a whole schema of however it was describedsignature – Its call signature, with the bound instance dropped
interface_type – Name of the action or service type, for the kinds that have one
server_name – The ROS name to address, for the kinds that have one. Needed because a server’s name is not derivable from the reference
in_process – False when the owner runs as its own process, which is the case a caller cannot reach by holding the object
- asdict(filter: Optional[Callable] = None) Dict#
- to_dict() Dict#
- asdict_explicit() Dict#
- from_dict(dict_obj: Dict) None#
- from_file(file_path: str, nested_root_name: Union[str, None] = None, get_common: bool = False) bool#
- to_json() Union[str, bytes, bytearray]#
- from_json(json_obj: Union[str, bytes, bytearray]) None#
- has_attribute(attr_name: str) bool#
- get_attribute_type(attr_name: str) Optional[type]#
- update_value(attr_name: str, attr_value: Any) bool#
- classmethod get_fields_info(class_object) Dict[str, Dict[str, Any]]#
- class ros_sugar.core._action_registry.RegisteredEvent#
Bases:
ros_sugar.config.base_attrs.BaseAttrsOne condition the running stack can be asked to watch for.
Contributed by a plugin, which offers it as a factory building a fresh
Event. Unlike an action it is not run: it is registered, together with the actions it is to trigger.- Parameters:
ref – How a caller names it, as “owner/name”
owner – Id of the plugin that offers it
name – The short name within that owner
description – What it watches for
signature – What its factory takes, such as a threshold
- asdict(filter: Optional[Callable] = None) Dict#
- to_dict() Dict#
- asdict_explicit() Dict#
- from_dict(dict_obj: Dict) None#
- from_file(file_path: str, nested_root_name: Union[str, None] = None, get_common: bool = False) bool#
- to_json() Union[str, bytes, bytearray]#
- from_json(json_obj: Union[str, bytes, bytearray]) None#
- has_attribute(attr_name: str) bool#
- get_attribute_type(attr_name: str) Optional[type]#
- update_value(attr_name: str, attr_value: Any) bool#
- classmethod get_fields_info(class_object) Dict[str, Dict[str, Any]]#
- class ros_sugar.core._action_registry.SystemActionRegistry(actions: Optional[Iterable[ros_sugar.core._action_registry.RegisteredAction]] = None)#
Every action the running stack exposes, addressable by name.
- Parameters:
actions – Entries to start with, defaults to empty
- static parse_ref(ref: str) Tuple[str, str]#
Split “owner/name” into its two halves.
- Parameters:
ref – The reference to split. A leading slash is tolerated, since a caller used to ROS topic names will write one
- Raises:
ValueError – If it is not exactly one owner and one name
- Return type:
Tuple[str, str]
- classmethod normalize(ref: str) str#
The canonical spelling of a reference, so lookups agree
- static short_name(server_name: str, owner: str) str#
Reduce a ROS server name to something a reference can carry.
Components name their entry points inconsistently: some prefix the node name, some do not. Both have to end up addressable, and a reference holds exactly one name, so what is left of the path is flattened.
- add(action: ros_sugar.core._action_registry.RegisteredAction, interface: Any = None) None#
Register one action.
- Parameters:
action – What to register
interface – The live action or service class, for the kinds that are reached through a client rather than by method name
- Raises:
ValueError – If the reference is taken by a different action. Silently keeping one of them would make which one a caller reaches a matter of ordering
- interface_for(ref: str) Any#
The live action or service class behind a reference.
- Returns:
The class, or None for a kind that is reached by method name
- add_event_factory(event: ros_sugar.core._action_registry.RegisteredEvent, factory: Callable) None#
Register one condition a plugin offers.
- Parameters:
event – What to register
factory – Builds a fresh
Event, given whatever its signature asks for
- Raises:
ValueError – If the reference is taken by a different event
- event_factory_for(ref: str) Optional[Callable]#
The factory behind an event reference, or None if it is unknown
- events(owner: Optional[str] = None) List[ros_sugar.core._action_registry.RegisteredEvent]#
Every registered event, sorted by reference, optionally one owner’s
- property events_dictionary: List[Dict]#
Serialized form, for a caller asking what can be watched for
- get_event(ref: str) ros_sugar.core._action_registry.RegisteredEvent#
Look one up.
- Raises:
KeyError – If unknown, naming what is registered
- remove_event(ref: str) ros_sugar.core._action_registry.RegisteredEvent#
Drop one condition and its factory.
- Returns:
The entry that was removed
- Raises:
KeyError – If unknown, as
get_eventdoes
- get(ref: str) ros_sugar.core._action_registry.RegisteredAction#
Look one up.
- Raises:
KeyError – If unknown, naming what the owner does offer, or the known owners when the owner itself is unknown
- remove(ref: str) ros_sugar.core._action_registry.RegisteredAction#
Drop one action, and the live class or factory kept beside it.
Something built from the entry before, such as an event’s action, keeps what it was built with; only new lookups stop finding it.
- Returns:
The entry that was removed
- Raises:
KeyError – If unknown, as
getdoes
- owners() List[str]#
Every owner that has at least one action, sorted
- refs(owner: Optional[str] = None) List[str]#
Every reference, sorted, optionally only one owner’s
- list(owner: Optional[str] = None, kind: Optional[str] = None) List[ros_sugar.core._action_registry.RegisteredAction]#
Every action, sorted by reference, narrowed by owner and/or kind
- property dictionary: List[Dict]#
Serialized form, for a caller asking what is available
- classmethod from_components(components: Iterable, monitor_methods: Optional[Iterable[str]] = None, monitor_class: Optional[type] = None, out_of_process: Optional[Iterable[str]] = None, plugins: Optional[Iterable] = None) ros_sugar.core._action_registry.SystemActionRegistry#
Build the registry from what the Launcher knows.
- Parameters:
components – The components in the stack
monitor_methods – Names of Monitor methods a runtime caller may use. An allowlist, not introspection: the Monitor holds lifecycle power over every component, and most of its methods take Python objects no JSON payload could carry
monitor_class – Class to read those methods’ signatures off. The registry is built before the Monitor exists, so this is the class rather than an instance
out_of_process – Node names launched as their own process, which is what makes an owner unreachable by holding its object
plugins – The plugins attached to the recipe, robot and sensor alike. What each contributes is registered under its plugin id
- Return type: