ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question
1

Specify the order in which nodes should start up in ROS2 launch file [closed]

asked 2022-08-01 10:51:44 -0500

sampreets3 gravatar image

updated 2022-08-01 10:53:34 -0500

Hi everyone,

I have a launch file which starts up my entire ROS2 application. This includes a planner node, a GUI node, a database node, and a vision node, amongst other things. What I observe most of the time is that even though my GUI node has started, I have to wait quite some time for the database node to come online. Is there a way I could specify the order in which the nodes should start?

I tried to edit the order in which I pushed them into the LaunchDescription object, but that did not really affect much.


I illustrate my problem with an example below:

 import os
 import yaml
 from launch import LaunchDescription
 from launch_ros.actions import Node
 from launch.actions import DeclareLaunchArgument
 from launch.substitutions import LaunchConfiguration, Command
 from launch.launch_description_sources import PythonLaunchDescriptionSource
 from ament_index_python.packages import get_package_share_directory
 from launch.launch_context import LaunchContext
 from typing import List

 def generate_launch_description():

    # Static TF (to emulate the TF between world and end-effector)
    static_tf = Node(package='tf2_ros',
                     executable='static_transform_publisher',
                     name='static_transform_publisher',
                     output='log',
                     arguments=['0.0', '0.0', '1.0', '1.57', '0.0', '0.0', 'world', 'link8'])

    # HMI node
    gui_node = Node(
                   package="my_awesome_application",
                   executable="ros2_hmi_node",
                   output="screen"
    )

     # database node
     db_node = Node(
                   package="my_awesome_db",
                   executable="ros2_db_node",
                   output="screen"
     )

     return LaunchDescription([static_tf, gui_node, db_node])

Let's say that I want my database node to start up first, and the GUI node should not start until the database is up and running. Do you guys have any idea on how/if I can enforce that in the launch file?

Thanks for the help!

edit retag flag offensive reopen merge delete

Closed for the following reason the question is answered, right answer was accepted by sampreets3
close date 2023-08-04 06:41:41.937144

2 Answers

Sort by ยป oldest newest most voted
1

answered 2022-08-02 01:39:34 -0500

ljaniec gravatar image

You can try using Licycle Nodes:

Introduction

ROS2 introduces the concept of managed nodes, also called LifecycleNodes. In the following tutorial, we explain the purpose of these nodes, what makes them different from regular nodes and how they comply to a lifecycle management. Managed nodes are scoped within a state machine of a finite amount of states. These states can be changed by invoking a transition id which indicates the succeeding consecutive state. The state machine is implemented as described at the ROS2 design page.

Our implementation differentiates between Primary States and Transition States. Primary States are supposed to be steady states in which any node can do the respected task. On the other hand, Transition States are meant as temporary intermediate states attached to a transition. The result of these intermediate states are used to indicate whether a transition between two primary states is considered successful or not. Thus, any managed node can be in one of the following states:

Primary States (steady states):

unconfigured
inactive
active
shutdown

Transition States (intermediate states):

configuring
activating
deactivating
cleaningup
shuttingdown

The possible transitions to invoke are:

configure
activate
deactivate
cleanup
shutdown
edit flag offensive delete link more

Comments

1

Hi, thanks for your answer. I am going to try using LifeCycle nodes to see if it makes my life easier. There is also something called event handlers which I found out yesterday that might help me achieve this. I am going to try out the two approaches and maybe come back in a couple weeks to let you guys know which one worked best for my use case.

sampreets3 gravatar image sampreets3  ( 2022-08-02 04:38:46 -0500 )edit

Yes, your feedback will be valuable for future readers for sure!

ljaniec gravatar image ljaniec  ( 2022-08-02 05:20:21 -0500 )edit

@sampreets3: Did you have some luck using the event handlers to achieve your task

TinyTurtle gravatar image TinyTurtle  ( 2023-03-14 05:27:18 -0500 )edit

Hey @TinyTurtle, yes I did find a way to exactly what I wanted with event handlers. Since it's a part of the launch file, I only had to modify a very small section of my code.

sampreets3 gravatar image sampreets3  ( 2023-03-15 22:21:56 -0500 )edit

@sampreets3: Can you share an example launch file here please

TinyTurtle gravatar image TinyTurtle  ( 2023-03-16 13:08:13 -0500 )edit
2

Hey @TinyTurtle, here you go. I just prepared two very simple ROS2 nodes called simple_ros_node and another_ros_node, and used the following launch file:

from launch_ros.actions import Node
from launch import LaunchDescription
from launch.actions import LogInfo, RegisterEventHandler
from launch.event_handlers import OnProcessStart

def generate_launch_description():
    simple_node = Node(
          package='test_pkg',
          executable='simple_ros_node',
          output='both'
    ) 

    another_node = Node(
          package='test_pkg',
          executable='another_ros_node',
          output='both'
    ) 

return LaunchDescription(
      [simple_node, 
       RegisterEventHandler(
             OnProcessStart(
                     target_action=simple_node,
                     on_start=[LogInfo(msg="Started the simple node. "), 
                                     another_node]
             )
       )]
   )
sampreets3 gravatar image sampreets3  ( 2023-03-27 09:11:57 -0500 )edit
1

answered 2023-03-31 09:24:36 -0500

sampreets3 gravatar image

As @ljaniec has mentioned before, we can use Lifecycle nodes to achieve the behaviour required. I did a bit more reading on this, and found a very simple example in ros2_control's controller_manager node.

Since I essentially needed a timeout to ensure that the database node has started before the GUI node in my example provided in the question, I chose to go ahead with event handlers in ROS 2. This decision was mainly influenced by the fact that event handlers are implemented on the launch file, so we do not have to change the source code of the ROS node in any way. Also, at some point if we want to roll back to a simpler launch file - let's consider that we have done some magic on the database node and now we can guarantee that it will always start before the gui starts, we can simply continue to reuse the previous launch file.

Maybe if I had to do the entire thing all over again, I would end up using Lifecycle nodes, because I like the finer grain of control we have over the node's behaviour that way.

I would also like to mention that these two methods are not interchangeable AFAIK, it's just two methods of acheiving the same result. Proceed with caution. Thanks again to @ljaniec for introducing me to Lifecycle nodes.

edit flag offensive delete link more

Question Tools

1 follower

Stats

Asked: 2022-08-01 10:51:44 -0500

Seen: 1,130 times

Last updated: Mar 31 '23