Utilisation des gestionnaires d’événements

Objectif : En savoir plus sur les gestionnaires d’événements dans les fichiers de lancement de ROS 2

Niveau du didacticiel : Intermédiaire

Durée : 15 minutes

Arrière-plan

Le lancement dans ROS 2 est un système qui exécute et gère des processus définis par l’utilisateur. Il est chargé de surveiller l’état des processus qu’il a lancés, ainsi que de signaler et de réagir aux changements d’état de ces processus. Ces modifications sont appelées événements et peuvent être gérées en enregistrant un gestionnaire d’événements auprès du système de lancement. Les gestionnaires d’événements peuvent être enregistrés pour des événements spécifiques et peuvent être utiles pour surveiller l’état des processus. De plus, ils peuvent être utilisés pour définir un ensemble complexe de règles qui peuvent être utilisées pour modifier dynamiquement le fichier de lancement.

Ce didacticiel montre des exemples d’utilisation de gestionnaires d’événements dans les fichiers de lancement ROS 2.

Conditions préalables

Ce tutoriel utilise le package turtlesim. Ce didacticiel suppose également que vous avez créé un nouveau package de type de construction ament_python appelé ``launch_tutorial ``.

Ce didacticiel étend le code présenté dans le didacticiel Using substitutions in launch files.

Utilisation des gestionnaires d’événements

1 Exemple de fichier de lancement de gestionnaires d’événements

Créez un nouveau fichier nommé example_event_handlers.launch.py dans le dossier launch du package launch_tutorial.

from launch_ros.actions import Node

from launch import LaunchDescription
from launch.actions import (DeclareLaunchArgument, EmitEvent, ExecuteProcess,
                            LogInfo, RegisterEventHandler, TimerAction)
from launch.conditions import IfCondition
from launch.event_handlers import (OnExecutionComplete, OnProcessExit,
                                OnProcessIO, OnProcessStart, OnShutdown)
from launch.events import Shutdown
from launch.substitutions import (EnvironmentVariable, FindExecutable,
                                LaunchConfiguration, LocalSubstitution,
                                PythonExpression)


def generate_launch_description():
    turtlesim_ns = LaunchConfiguration('turtlesim_ns')
    use_provided_red = LaunchConfiguration('use_provided_red')
    new_background_r = LaunchConfiguration('new_background_r')

    turtlesim_ns_launch_arg = DeclareLaunchArgument(
        'turtlesim_ns',
        default_value='turtlesim1'
    )
    use_provided_red_launch_arg = DeclareLaunchArgument(
        'use_provided_red',
        default_value='False'
    )
    new_background_r_launch_arg = DeclareLaunchArgument(
        'new_background_r',
        default_value='200'
    )

    turtlesim_node = Node(
        package='turtlesim',
        namespace=turtlesim_ns,
        executable='turtlesim_node',
        name='sim'
    )
    spawn_turtle = ExecuteProcess(
        cmd=[[
            FindExecutable(name='ros2'),
            ' service call ',
            turtlesim_ns,
            '/spawn ',
            'turtlesim/srv/Spawn ',
            '"{x: 2, y: 2, theta: 0.2}"'
        ]],
        shell=True
    )
    change_background_r = ExecuteProcess(
        cmd=[[
            FindExecutable(name='ros2'),
            ' param set ',
            turtlesim_ns,
            '/sim background_r ',
            '120'
        ]],
        shell=True
    )
    change_background_r_conditioned = ExecuteProcess(
        condition=IfCondition(
            PythonExpression([
                new_background_r,
                ' == 200',
                ' and ',
                use_provided_red
            ])
        ),
        cmd=[[
            FindExecutable(name='ros2'),
            ' param set ',
            turtlesim_ns,
            '/sim background_r ',
            new_background_r
        ]],
        shell=True
    )

    return LaunchDescription([
        turtlesim_ns_launch_arg,
        use_provided_red_launch_arg,
        new_background_r_launch_arg,
        turtlesim_node,
        RegisterEventHandler(
            OnProcessStart(
                target_action=turtlesim_node,
                on_start=[
                    LogInfo(msg='Turtlesim started, spawning turtle'),
                    spawn_turtle
                ]
            )
        ),
        RegisterEventHandler(
            OnProcessIO(
                target_action=spawn_turtle,
                on_stdout=lambda event: LogInfo(
                    msg='Spawn request says "{}"'.format(
                        event.text.decode().strip())
                )
            )
        ),
        RegisterEventHandler(
            OnExecutionComplete(
                target_action=spawn_turtle,
                on_completion=[
                    LogInfo(msg='Spawn finished'),
                    change_background_r,
                    TimerAction(
                        period=2.0,
                        actions=[change_background_r_conditioned],
                    )
                ]
            )
        ),
        RegisterEventHandler(
            OnProcessExit(
                target_action=turtlesim_node,
                on_exit=[
                    LogInfo(msg=(EnvironmentVariable(name='USER'),
                            ' closed the turtlesim window')),
                    EmitEvent(event=Shutdown(
                        reason='Window closed'))
                ]
            )
        ),
        RegisterEventHandler(
            OnShutdown(
                on_shutdown=[LogInfo(
                    msg=['Launch was asked to shutdown: ',
                        LocalSubstitution('event.reason')]
                )]
            )
        ),
    ])

Les actions RegisterEventHandler pour les événements OnProcessStart, OnProcessIO, OnExecutionComplete, OnProcessExit et OnShutdown ont été définies dans la description de lancement.

Le gestionnaire d’événements OnProcessStart est utilisé pour enregistrer une fonction de rappel qui est exécutée lorsque le nœud turtlesim démarre. Il enregistre un message sur la console et exécute l’action spawn_turtle lorsque le nœud turtlesim démarre.

RegisterEventHandler(
    OnProcessStart(
        target_action=turtlesim_node,
        on_start=[
            LogInfo(msg='Turtlesim started, spawning turtle'),
            spawn_turtle
        ]
    )
),

Le gestionnaire d’événements OnProcessIO est utilisé pour enregistrer une fonction de rappel qui est exécutée lorsque l’action spawn_turtle écrit sur sa sortie standard. Il enregistre le résultat de la demande de spawn.

RegisterEventHandler(
    OnProcessIO(
        target_action=spawn_turtle,
        on_stdout=lambda event: LogInfo(
            msg='Spawn request says "{}"'.format(
                event.text.decode().strip())
        )
    )
),

Le gestionnaire d’événements OnExecutionComplete est utilisé pour enregistrer une fonction de rappel qui est exécutée lorsque l’action spawn_turtle se termine. Il consigne un message dans la console et exécute les actions change_background_r et change_background_r_conditioned lorsque l’action spawn est terminée.

RegisterEventHandler(
    OnExecutionComplete(
        target_action=spawn_turtle,
        on_completion=[
            LogInfo(msg='Spawn finished'),
            change_background_r,
            TimerAction(
                period=2.0,
                actions=[change_background_r_conditioned],
            )
        ]
    )
),

Le gestionnaire d’événements OnProcessExit est utilisé pour enregistrer une fonction de rappel qui est exécutée lorsque le nœud turtlesim se termine. Il enregistre un message sur la console et exécute l’action EmitEvent pour émettre un événement Shutdown lorsque le nœud turtlesim se termine. Cela signifie que le processus de lancement s’arrêtera lorsque la fenêtre turtlesim sera fermée.

RegisterEventHandler(
    OnProcessExit(
        target_action=turtlesim_node,
        on_exit=[
            LogInfo(msg=(EnvironmentVariable(name='USER'),
                    ' closed the turtlesim window')),
            EmitEvent(event=Shutdown(
                reason='Window closed'))
        ]
    )
),

Enfin, le gestionnaire d’événements OnShutdown est utilisé pour enregistrer une fonction de rappel qui est exécutée lorsque le fichier de lancement est invité à s’arrêter. Il enregistre un message sur la console expliquant pourquoi le fichier de lancement est invité à s’arrêter. Il enregistre le message avec une raison d’arrêt comme la fermeture de la fenêtre turtlesim ou le signal ctrl-c effectué par l’utilisateur.

RegisterEventHandler(
    OnShutdown(
        on_shutdown=[LogInfo(
            msg=['Launch was asked to shutdown: ',
                LocalSubstitution('event.reason')]
        )]
    )
),

Construire le paquet

Accédez à la racine de l’espace de travail et créez le package :

colcon build

N’oubliez pas non plus de sourcer l’espace de travail après la construction.

Exemple de lancement

Vous pouvez maintenant lancer le fichier example_event_handlers.launch.py en utilisant la commande ros2 launch.

ros2 launch launch_tutorial example_event_handlers.launch.py turtlesim_ns:='turtlesim3' use_provided_red:='True' new_background_r:=200

Cela fera ce qui suit :

  1. Démarrer un nœud turtlesim avec un fond bleu

  2. Faire apparaître la deuxième tortue

  3. Changer la couleur en violet

  4. Changez la couleur en rose après deux secondes si l’argument background_r fourni est 200 et l’argument use_provided_red est True

  5. Arrêter le fichier de lancement lorsque la fenêtre turtlesim est fermée

De plus, il consignera les messages dans la console lorsque :

  1. Le noeud turtlesim démarre

  2. L’action spawn est exécutée

  3. L’action change_background_r est exécutée

  4. L’action change_background_r_conditioned est exécutée

  5. Le noeud turtlesim se ferme

  6. Le processus de lancement est invité à s’arrêter.

Documentation

La documentation de lancement fournit des informations détaillées sur les gestionnaires d’événements disponibles.

Résumé

Dans ce didacticiel, vous avez appris à utiliser des gestionnaires d’événements dans les fichiers de lancement. Vous avez découvert leur syntaxe et des exemples d’utilisation pour définir un ensemble complexe de règles permettant de modifier dynamiquement les fichiers de lancement.