Lifecycle interface

Core lifecycle for modular robotics systems

Configure · Activate · Run · Transition · Shutdown

Changelog

The authoritative changelog lives at the repository root in CHANGELOG.md. Versioned entries below the version list marker are generated by python-semantic-release from conventional commits.

First public release — planned v0.4.0

lifecore_ros2 v0.4.0 will be the first public release of the library. It establishes a small, predictable surface for composing lifecycle-aware ROS 2 nodes without layering a hidden state machine on top of native ROS 2 lifecycle semantics.

What this release provides

Public API (re-exported from lifecore_ros2):

  • LifecycleComponentNode — lifecycle node that owns and drives registered components as native ROS 2 managed entities.

  • LifecycleComponent — base class for lifecycle-aware components (abstract by convention); propagates transitions through _on_configure, _on_activate, _on_deactivate, _on_cleanup, _on_shutdown, _on_error.

  • TopicComponent — base class for topic-oriented components; allocates ROS pub/sub during configure, releases during cleanup.

  • LifecyclePublisherComponent — generic publisher ([MsgT]) gated by activation state.

  • LifecycleTimerComponent — periodic timer component whose on_tick callback is gated by activation state; the underlying ROS timer is created on configure and released on cleanup.

  • LifecycleSubscriberComponent — generic subscriber ([MsgT]) whose on_message callback is gated by activation state.

  • when_active — decorator that guards component methods on activation state.

  • LifecoreError and the typed boundary-violation subclasses RegistrationClosedError, DuplicateComponentError, ComponentNotAttachedError, ComponentNotConfiguredError, InvalidLifecycleTransitionError, ConcurrentTransitionError.

  • LifecycleHookError — typed exception that wraps any uncaught exception raised inside a _on_* hook (chained via __cause__); never propagated to the caller of trigger_*, used for diagnostic context only.

Error propagation contract (ratified Sprint 2):

  • Composite transitions follow rollback policy B (all-or-nothing); the node returns the worst component result without replaying hooks in reverse.

  • Caught hook exceptions and invalid hook return values both map to TransitionCallbackReturn.ERROR with a structured error log; rclpy then drives ErrorProcessing and invokes _on_error exactly once.

  • Strict mode is the default and is non-configurable.

See Error handling contract and the Error Policy section of Architecture for the authoritative matrix.

Unified activation-gating primitive (Sprint 6):

  • New module lifecore_ros2.core.activation_gating exposes require_active(is_active, *, component_name) — the single shared check used by all activation-gating paths in the library.

  • LifecycleComponent.require_active() — new public method; a façade over the primitive. Use it in _on_* extension points or try/except handlers that need component-specific inactive behavior.

  • @when_active default-raise path refactored to delegate to the same primitive; error message and behavior are unchanged.

  • LifecycleServiceServerComponent._on_request_wrapper refactored to call self.require_active() via try/except RuntimeError; warning log and annotated default response are preserved exactly.

  • No raw if not self._is_active: check remains in component files outside LifecycleComponent internals.

Examples: examples/minimal_node.py, examples/minimal_publisher.py, examples/minimal_subscriber.py, examples/telemetry_publisher.py.

Testing utilities (Sprint 3): lifecore_ros2.testing provides lifecycle fakes, pytest-compatible fixtures, assertion helpers, log helpers, and small concurrency probes for library and application tests. The standard fakes use std_msgs.msg.String and std_srvs.srv.Trigger to stay concrete while keeping test setup compact.

Documentation: getting-started guide, architecture overview, recommended patterns and anti-patterns, testing utilities guide, migration notes from raw rclpy, and a Sphinx-buildable API reference.

Quality baseline: Ruff formatting and linting, Pyright in strict mode for the core package, reusable lifecycle testing utilities, and a pytest suite covering nominal transitions, edge transitions, activation gating, failure propagation, resource handling, and the Sprint 3 testing package itself.

What this release does not provide yet

  • Companion examples repository (lifecore_ros2_examples).

  • Visual demo asset (terminal recording or GIF).

  • Extended FAQ section.

  • Advanced patterns beyond the recommended/anti-pattern pairs already documented.

Supported baseline

  • Python 3.12 or newer.

  • ROS 2 Jazzy.

  • rclpy is required at runtime and is expected to come from the system ROS installation; it is intentionally not declared as a PyPI dependency.

Known limitations

  • composed_pipeline.py demonstrates multi-component composition inside a single node; multi-node or domain-specific examples live in the planned companion repository.

  • The MsgT type parameter on topic components is unbounded by design — no stable ROS 2 message base class is exported by rosidl to constrain it without coupling.

  • No companion examples repository, visual asset, or FAQ ships with this release.

  • Lifecycle observability beyond standard rclpy logging (e.g. /diagnostics integration) is out of scope for the core library.