Repository navigation
Define ROS integration and element registration boundaries #116
Description
Current state
Importing the core requires rclpy and std_msgs, even when debug publishing is disabled. The parser uses a ROS node for %parameter lookup, and logging uses ROS logging. The scheduler, tree representation, and most syntax handling otherwise operate on Python objects.
Registration accepts filesystem paths. Discovery temporarily changes sys.path, imports modules by names derived from those paths, and reloads an already imported module with the same name. Registries use class names as keys; duplicate names overwrite earlier entries. Import failures are logged and discovery continues, so a missing class may only become an error during behavior binding. #122 restores sys.path reliably but retains these discovery semantics.
Problem and relevance
Non-ROS applications and isolated core tests must install ROS despite not using its integration features. Conversely, removing ROS directly would break imports, parameter lookup, and existing debug-topic behavior.
Path discovery can select or reload the wrong module when packages share names. Duplicate element names make binding depend on discovery order. Reloading also executes module-level code again. These issues affect applications loading multiple behavior packages, reproducibility, and the reliability of hot reload.
Options for ROS integration
- Keep ROS in the core. Continue testing with the small ROS Pixi environment.
- Benefits: least API and packaging disruption; reflects current robot usage.
- Caveats: ROS remains mandatory for every consumer and core test.
- Extract an optional ROS adapter. Keep scheduling/parsing independent; inject logging, parameter resolution, and debug observation through small interfaces. Supply a ROS adapter and a compatibility constructor/facade.
- Benefits: ordinary Python consumers can use the core; tests can exercise scheduling without ROS; integration remains explicitly tested.
- Caveats: requires ownership and lifecycle rules for adapters, packaging changes, and a migration path for the existing
node/debug_topicAPI.
Options for element registration
- Harden path discovery. Reject duplicate class names and module-origin conflicts; provide an explicit policy for import failures and reload.
- Benefits: existing callers retain their registration style; ambiguous behavior becomes an actionable error.
- Caveats: still executes discovery imports and depends on filesystem/module-cache behavior.
- Add explicit class registration and qualified module discovery. For example, register an action class directly; discover installed packages by full Python module name. Keep path discovery as a compatibility API.
- Benefits: deterministic registration, straightforward typing/testing, and no
sys.pathmutation for explicitly registered classes. - Caveats: requires caller changes to gain the benefits; DSL class-name collisions still need a rejection or alias policy.
- Benefits: deterministic registration, straightforward typing/testing, and no
- Add packaging entry points for plugins. Installed behavior packages advertise their elements, alongside explicit registration.
- Benefits: convenient discovery across independently installed packages.
- Caveats: adds packaging/configuration machinery and collision handling; entry points still import code and do not solve hot reload.
Recommendation
Implement explicit class registration first, rejecting duplicate names unless replacement is explicitly requested. Retain path discovery while adding origin/collision checks. Establish whether consumers actually require hot reload before preserving or removing automatic reload.
For ROS, prefer option 2 if a consumer audit confirms demand for independent core use: introduce the interfaces internally, retain the existing public facade, then move the ROS implementation behind the adapter. Keep real ROS integration tests. Defer entry points until multiple independently distributed behavior packages demonstrate the need.
I am working on behalf of @jaagut.
Activity