diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b1d8e25..fec0edd4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ Release Versions: - fix(controllers): move predicate publishing rate parameter to BaseControllerInterface (#168) - feat(components): get clproto message type from attribute (#175) - fix(components): add missing test case (#181) + - fix(components): clean up lifecycle nodes properly (#178) ## 5.0.2 diff --git a/source/modulo_components/modulo_components/lifecycle_component.py b/source/modulo_components/modulo_components/lifecycle_component.py index c65e5dd3..89437997 100644 --- a/source/modulo_components/modulo_components/lifecycle_component.py +++ b/source/modulo_components/modulo_components/lifecycle_component.py @@ -4,6 +4,7 @@ from lifecycle_msgs.msg import State from modulo_components.component_interface import ComponentInterface from modulo_core.exceptions import AddSignalError +from rclpy.callback_groups import CallbackGroup from rclpy.lifecycle import LifecycleNodeMixin, LifecycleState from rclpy.lifecycle.node import TransitionCallbackReturn @@ -11,7 +12,16 @@ LIFECYCLE_NODE_MIXIN_KWARGS = ["enable_communication_interface", "callback_group"] -class LifecycleComponent(ComponentInterface, LifecycleNodeMixin): +class _LifecycleNodeMixin(LifecycleNodeMixin): + def __init__(self, enable_communication_interface: bool = True, callback_group: Optional[CallbackGroup] = None): + super().__init__(enable_communication_interface=enable_communication_interface, callback_group=callback_group) + + def destroy(self): + self._state_machine = None + self._callbacks = {} + + +class LifecycleComponent(ComponentInterface, _LifecycleNodeMixin): """ Class to represent a LifecycleComponent in python, following the same logic pattern as the C++ modulo_components::LifecycleComponent class. @@ -25,9 +35,16 @@ def __init__(self, node_name: str, *args, **kwargs): """ lifecycle_node_kwargs = {key: value for key, value in kwargs.items() if key in LIFECYCLE_NODE_MIXIN_KWARGS} ComponentInterface.__init__(self, node_name, *args, **kwargs) - LifecycleNodeMixin.__init__(self, *args, **lifecycle_node_kwargs) + _LifecycleNodeMixin.__init__(self, **lifecycle_node_kwargs) self.__has_error = False + def destroy_node(self): + """ + Cleanly destroy the node by cleaning up the Mixin class. + """ + _LifecycleNodeMixin.destroy(self) + ComponentInterface.destroy_node(self) + def get_lifecycle_state(self) -> LifecycleState: """ Get the current state of the component.