Rosanswers logo

I am using ROS2 Galactic, and writing Python Launch files.

Let’s say I have a launch file, L1 that starts node L1N1.

Then I have another launch file, L2, that can start node L2N1 on a specific condition.

The way I am running these Launch files is, that I am including the launch description of L1 into L2, this means that L2 starts running L2N1, and now I want to condition the execution of my node L2N2, on the basis of the state of L1N1.

Is there a way to register an event handler on the state of node L1N1, executed by the launch file L1, that was included inside the same launch file L2?

Originally posted by Raza Rizvi on ROS Answers with karma: 95 on 2022-01-19

Post score: 0

Original comments

Comment by msmcconnell on 2022-01-19:
Its difficult to answer this question without knowing exactly what part of your L2N2 node you are trying to condition (the launch itself, its parameters, its arguments, etc) as well what "state" you are conditioning against from L1N1 (lifecycle state, launch/not launched, a publication, etc.)

Can you share the launch files or add more detail?

Comment by Raza Rizvi on 2022-01-20:
Ok so here's what I want to do, in Pseudo code.

This is the launch file L2:

  • Run node L2N1.

  • Include the Launch Description of L1.

  • IF(lifecycleState(L1N1) == 'active'): Run L2N2.

Return the generated launch description of L2, to be launched later.


1 Answer 1


Rosanswers logo

The available event handlers for the launch system can be found in 2 places, the mostly ros agnostic launch framework https://github.com/ros2/launch/tree/galactic/launch/launch/event_handlers

and the ros specific portions of launch found in launch_ros https://github.com/ros2/launch_ros/tree/galactic/launch_ros/launch_ros/event_handlers

In the launch_ros folder we find the OnStateTransition event handler which I believe meets your needs. https://github.com/ros2/launch_ros/blob/galactic/launch_ros/launch_ros/event_handlers/on_state_transition.py

I've not used this before, but there is an example of it in that repo (copied here in case the link brakes) https://github.com/ros2/launch_ros/blob/6370c127868a5056a8a02c9412c59bebdaefcf81/launch_ros/examples/lifecycle_pub_sub_launch.py#L59

# When the talker node reaches the 'active' state, log a message and start the listener node.
register_event_handler_for_talker_reaches_active_state = launch.actions.RegisterEventHandler(
        target_lifecycle_node=talker_node, goal_state='active',
                msg="node 'talker' reached the 'active' state, launching 'listener'."),
                name='listener', namespace='',
                package='lifecycle', executable='lifecycle_listener', output='screen'),
) # Copyright 2018 Open Source Robotics Foundation, Inc. See original source at link for Apache 2 license

Originally posted by msmcconnell with karma: 268 on 2022-01-20

This answer was ACCEPTED on the original site

Post score: 2

Original comments

Comment by Raza Rizvi on 2022-01-21:
Thank you so much for your response.

but, all these examples focus on conditioning on nodes that are initiated in the same Launch file, so we know the object name on which we can condition our actions on easily.

But what about the cases where we load the launch description of another launch file that initiates nodes inside them, and those node objects are not visible to our launch file. how do we condition on those nodes?

Comment by msmcconnell on 2022-01-21:
To make sure I understand the question, you are referring to the "talker_node" object from this line not being available?

arget_lifecycle_node=talker_node, goal_state='active',

Comment by Raza Rizvi on 2022-01-21:
No. So, in this example, the Event Handlers are registered on the node objects defined in the same launch file. What about the case, where for example, the talker_node is defined in a child launch file, that is then included in this description. This makes the word 'talker_node' not defined in this parent launch file. Can we then somehow register the event handler on the 'talker_node's state?

Comment by msmcconnell on 2022-01-21:
There is a get_sub_entities() method on all Actions that might be able to accomplish this. Something along the lines of

my_included_launch = IncludeLaunchDescription(...)
sub_entities = my_included_launch.get_sub_entities()
target_node = None
for entity in sub_entities:
   # Somehow identify the node entity maybe with entity.describe()
   if (some check):
      target_node = entity

handler = launch.actions.RegisterEventHandler(
        target_lifecycle_node=target_node, goal_state='active', ...))

Something like that might conceivably work, but it will take some experimentation on your end and looking at the launch source code. Its possible you may also need to wrap the get_sub_entities() call and for loop search in a new Substitution class in order for all the entities to be properly found.

Comment by Raza Rizvi on 2022-01-21:
This looks promising! Will try it. Thank you very much :)

Comment by msmcconnell on 2022-01-21:
No problem. Hope it works!


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.