Managing and Creating Lifecycle Nodes in ROS 2

When developing complex robotic systems, the ability to precisely control the operational state of each node is essential to ensure reliability, safety, and maintainability. ROS 2 addresses this need through a key concept: Lifecycle Nodes.

Unlike regular nodes that start operating as soon as they are launched, Lifecycle Nodes allow you to manage their life cycle through well-defined states and transitions. This means you can decide when a node should start working, when it should pause, and when it should shut down, giving you complete control over the system’s behavior.

🧐 What Is a Lifecycle Node?

A Lifecycle Node – also known as a Managed Node – is a ROS 2 node that follows a structured life cycle composed of multiple operational phases.

When launched, the node starts in the Unconfigured state, meaning the code is loaded but resources are not yet initialized. From there, it can transition to the Inactive state, where the node is configured but not yet active—publishers, timers, and actions remain disabled. Then, with another transition, it enters the Active state, becoming fully operational, publishing data, and communicating with other system components.

When the node needs to stop or restart, it can move to the Deactivated or Finalized states, releasing resources in a safe and controlled manner.

These transitions can be triggered manually through the ROS 2 CLI or automatically by other nodes in the system. Each transition can be linked to a callback, a function defining what happens when the node enters or leaves a specific state.

This approach allows developers to orchestrate the system’s behavior predictably, preventing race conditions or initialization errors.

</> Creating a Lifecycle Node in Python

To better understand how this mechanism works, let’s look at a practical example.
In ROS 2, we can implement a Lifecycle Node in Python using the rclpy API.

Here’s a complete example:

				
					from rclpy.lifecycle import Node
from rclpy.lifecycle import State
from rclpy.lifecycle import TransitionCallbackReturn
import rclpy

class MyLifecycleNode(Node):

    def __init__(self):
        super().__init__('my_lifecycle_node')

    def on_configure(self, state: State):
        self.get_logger().info('Configuring...')
        return TransitionCallbackReturn.SUCCESS

    def on_activate(self, state: State):
        self.get_logger().info('Activating...')
        return TransitionCallbackReturn.SUCCESS

    def on_deactivate(self, state: State):
        self.get_logger().info('Deactivating...')
        return TransitionCallbackReturn.SUCCESS

    def on_cleanup(self, state: State):
        self.get_logger().info('Cleaning up...')
        return TransitionCallbackReturn.SUCCESS

    def on_shutdown(self, state: State):
        self.get_logger().info('Shutting down...')
        return TransitionCallbackReturn.SUCCESS


def main(args=None):
    rclpy.init(args=args)
    lc_node = MyLifecycleNode()
    rclpy.spin(lc_node)
    rclpy.shutdown()

				
			

🧠 Breaking Down the Code

Importing the Required Modules
				
					from rclpy.lifecycle import Node
from rclpy.lifecycle import State
from rclpy.lifecycle import TransitionCallbackReturn
import rclpy

				
			

These lines import all the necessary modules for working with Lifecycle Nodes in ROS 2.
Node is the base class for all Lifecycle Nodes, State represents the current node state, and TransitionCallbackReturn is used to report the outcome of a transition.

Defining the Lifecycle Node Class
				
					class MyLifecycleNode(Node):

				
			

Here, we define a class called MyLifecycleNode that inherits from Node.
This inheritance gives our class all the functionalities of a managed Lifecycle Node.

Initializing the Node
				
					def __init__(self):
    super().__init__('my_lifecycle_node')

				
			

The constructor initializes the node and assigns it the name my_lifecycle_node, which is how it will appear in the ROS 2 system.

Configuring the Node
				
					def on_configure(self, state: State):
    self.get_logger().info('Configuring...')
    return TransitionCallbackReturn.SUCCESS

				
			

The on_configure() callback is executed when the node transitions from unconfigured to inactive.
This is where you typically load parameters, open connections, or initialize sensors and resources.
The return value communicates whether the transition succeeded.

Activating the Node
				
					def on_activate(self, state: State):
    self.get_logger().info('Activating...')
    return TransitionCallbackReturn.SUCCESS

				
			

The on_activate() callback runs when the node becomes active, meaning it is now fully operational.
Here, the node starts publishing data, executing timers, or performing actions.

Deactivating the Node
				
					def on_deactivate(self, state: State):
    self.get_logger().info('Deactivating...')
    return TransitionCallbackReturn.SUCCESS

				
			

on_deactivate() is triggered when the node transitions from active to inactive.
At this stage, publishers and periodic operations are suspended while keeping resources allocated.

Cleaning Up the Node
				
					def on_cleanup(self, state: State):
    self.get_logger().info('Cleaning up...')
    return TransitionCallbackReturn.SUCCESS

				
			

The on_cleanup() callback releases resources and returns the node to the unconfigured state.
This is useful when you want to reconfigure a node without restarting the whole system.

Shutting Down the Node
				
					def on_shutdown(self, state: State):
    self.get_logger().info('Shutting down...')
    return TransitionCallbackReturn.SUCCESS

				
			

The on_shutdown() callback executes when the node is shutting down permanently.
Here, you can save data, close files, or safely disconnect hardware components.

Running the Main Function
				
					def main(args=None):
    rclpy.init(args=args)
    lc_node = MyLifecycleNode()
    rclpy.spin(lc_node)
    rclpy.shutdown()

				
			

The main() function initializes ROS 2, creates the node instance, keeps it running with rclpy.spin(), and shuts it down cleanly when finished.

📋 Managing Lifecycle Nodes from the Command Line

Once the node is running, you can control its state directly from the terminal.
ROS 2 provides a dedicated CLI tool for managing Lifecycle Nodes, allowing you to configure, activate, deactivate, clean up, or shut down nodes easily.

For example, to manage a node named /my_lifecycle_node, you can use:

				
					ros2 lifecycle set /my_lifecycle_node configure
ros2 lifecycle set /my_lifecycle_node activate
ros2 lifecycle set /my_lifecycle_node deactivate
ros2 lifecycle set /my_lifecycle_node cleanup
ros2 lifecycle set /my_lifecycle_node shutdown

				
			

Each command triggers the corresponding callback defined in the code and moves the node to its new state.
To check the node’s current state, you can use:

				
					ros2 lifecycle get /my_lifecycle_node

				
			

This management system makes it extremely easy to coordinate multiple nodes running simultaneously — a key advantage in distributed systems where modules must activate in the correct order or safely deactivate when required.

🤔 Why Lifecycle Nodes Matter

The introduction of Lifecycle Nodes makes ROS 2 far more mature and professional compared to its predecessors.
This feature enables predictable and controlled management of node behavior.

In real projects, this means sensors are never activated before the network is ready, actuators can be safely suspended, and resources are always released correctly — preventing memory leaks and race conditions.
A system that fully leverages Lifecycle Nodes is not only more stable and scalable but also easier to debug and maintain.

In industrial environments, this approach has become the standard for coordinating complex robotic systems with precision and determinism.
In research and prototyping, it provides the flexibility to test and modify behaviors without compromising overall system stability.

🎯 Conclusion

In this article, we explored how ROS 2 Lifecycle Nodes provide a structured and reliable way to manage the life cycle of nodes.
We saw how to create a managed node in Python, attach transition callbacks, and control its state directly through the ROS 2 CLI.

The ability to decide exactly when a node activates or deactivates is one of the foundations of building professional, safe, and dependable robots.
And this is just the beginning: in complex systems, Lifecycle Nodes are integrated with automatic supervisors, error-handling mechanisms, and recovery logic that make robots more autonomous and resilient.

If you want to learn how to design and build professional robotic systems leveraging the full power of ROS 2 Lifecycle Nodes, check out our complete ROS 2 course.

It includes step-by-step lessons, practical examples, and ready-to-use materials that will help you apply these techniques directly in your projects.
Scroll down to discover how to access the course today and take your ROS 2 skills to the next level.

Want to learn more?

If you want to learn how to design and build professional robotic systems leveraging the full power of ROS 2 Lifecycle Nodes, check out our "Self Driving and ROS 2 - Learn by doing! Plan & Navigation" course
DISCOUNT
es_ES

Discover BumperBot Kit

Assemble your robot and get started to learn Robotics!