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

Event handling on ROS2 Nodes across Launch files

asked 2022-01-19 06:51:33 -0500

Raza Rizvi gravatar image

updated 2022-01-20 01:18:47 -0500

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?

edit retag flag offensive close merge delete

Comments

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?

msmcconnell gravatar image msmcconnell  ( 2022-01-19 12:33:59 -0500 )edit

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.

Raza Rizvi gravatar image Raza Rizvi  ( 2022-01-20 01:23:01 -0500 )edit

1 Answer

Sort by » oldest newest most voted
2

answered 2022-01-20 12:12:29 -0500

msmcconnell gravatar image

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/g...

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

In the launch_ros folder we find the OnStateTransition event handler which I believe meets your needs. https://github.com/ros2/launch_ros/bl...

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/bl...

# 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(
    launch_ros.event_handlers.OnStateTransition(
        target_lifecycle_node=talker_node, goal_state='active',
        entities=[
            launch.actions.LogInfo(
                msg="node 'talker' reached the 'active' state, launching 'listener'."),
            launch_ros.actions.LifecycleNode(
                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
edit flag offensive delete link more

Comments

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?

Raza Rizvi gravatar image Raza Rizvi  ( 2022-01-21 02:07:40 -0500 )edit

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',
msmcconnell gravatar image msmcconnell  ( 2022-01-21 08:24:15 -0500 )edit

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?

Raza Rizvi gravatar image Raza Rizvi  ( 2022-01-21 08:52:51 -0500 )edit
1

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(
    launch_ros.event_handlers.OnStateTransition(
        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.

msmcconnell gravatar image msmcconnell  ( 2022-01-21 09:05:57 -0500 )edit

This looks promising! Will try it. Thank you very much :)

Raza Rizvi gravatar image Raza Rizvi  ( 2022-01-21 09:23:51 -0500 )edit

No problem. Hope it works!

msmcconnell gravatar image msmcconnell  ( 2022-01-21 09:39:12 -0500 )edit

Question Tools

2 followers

Stats

Asked: 2022-01-19 06:51:33 -0500

Seen: 1,094 times

Last updated: Jan 20 '22