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

[ROS2][foxy][launch] Restart node every time it exits - launch file

asked 2021-04-14 01:53:35 -0500

anastasiaPan gravatar image

updated 2021-04-14 01:55:26 -0500

Hello
I have a ros launch file that starts a few nodes. One of them exits under some conditions and I want to restart it every time when that happens. The whole idea is that I have a process that runs my simulator (specifically Webots). I have another process that starts a controller for my robot and whenever I reset the simulation I want to be able to restart my controller node without everything shutting down. What I have now is (it is a bit 'stupid' but I do not have any better ideas):

   controller =  Node(
        package=my_package,
        executable=my_executable,
    )

   cmd = ['ros2', 'run', 'my_package', 'my_executable']
   restart_controller = ExecuteProcess(cmd=cmd,shell=True)

   launch_description = LaunchDescription(ARGUMENTS + [
           robot_state_publisher,
           simulator,
           controller,

        # Restart controller when it breaks
        RegisterEventHandler(
            event_handler=launch.event_handlers.OnProcessExit(
                target_action=controller,
                on_exit=[restart_controller],
            )
        ),     

        RegisterEventHandler(
            event_handler=launch.event_handlers.OnProcessExit(
                target_action=restart_controller,
                on_exit=[controller],
            )
        ), 

        # Shutdown launch when Webots exits.
        RegisterEventHandler(
            event_handler=launch.event_handlers.OnProcessExit(
                target_action=simulator,
                on_exit=[EmitEvent(event=launch.events.Shutdown())],
            )
        )
    ])

If I start the controller node again and again from a terminal it works every time but here I see that in the ExecuteProcess method whenever I try to run the same process it crashes and raises a runtime error that says "ExecuteProcess action executed more than once".

Another thing is that the ros package is in Python (it cannot be in cpp for now at least) so it is not possible to make it a managed node and use the lifecycle utilities (configure-activate-shutdown etc.) which was my original idea.

I am also open to a better idea to do what I want if it is impossible to re-execute a process.

edit retag flag offensive close merge delete

2 Answers

Sort by ยป oldest newest most voted
3

answered 2021-04-15 01:42:05 -0500

anastasiaPan gravatar image

I have fixed this by switching to ROS rolling. Rolling distro has the option respawn in the ExecuteProcess.

edit flag offensive delete link more
1

answered 2021-06-18 12:15:09 -0500

yura_somatic gravatar image

To handle the problem you can create function for controller description, and call it from on_exit() function, passed to the Event handler. Just don't use target_action argument, because it's comparing, using object. Than your on_exit_restart() function willl be called for each process, so just filter by name which process you want to restart:

    from launch_ros.actions import Node
    from launch.launch_context import LaunchContext
    from launch.events.process.process_exited import ProcessExited
    from launch.actions import RegisterEventHandler
    from launch import LaunchDescription
    from launch.event_handlers.on_process_exit import OnProcessExit


    def controller_description():
        return Node(
            package    = my_package,
            executable = my_executable
        )


    def on_exit_restart(event:ProcessExited, context:LaunchContext):
        print("\n\nProcess [{}] exited, pid: {}, return code: {}\n\n".format(
            event.action.name, event.pid, event.returncode))
        if event.returncode != 0 and 'controller' in event.action.name:
            return controller_description() # respawn node action


    ld = LaunchDescription([
        robot_state_publisher,
        simulator,
        controller,
        RegisterEventHandler(event_handler=OnProcessExit(on_exit=on_exit_restart))
    ])
edit flag offensive delete link more

Comments

Thank you for the answer! I am using the respawn feature for quite some time now and it works fine but I might try your solution too - just to verify!

anastasiaPan gravatar image anastasiaPan  ( 2021-06-21 02:28:50 -0500 )edit

Question Tools

2 followers

Stats

Asked: 2021-04-14 01:53:35 -0500

Seen: 2,622 times

Last updated: Jun 18 '21