-Launchers .3.3

Posted zhangrelay

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了-Launchers .3.3相关的知识,希望对你有一定的参考价值。

ROS2机器人编程简述humble-第二章-Publishing and Subscribing .3.2

ros2 run一次只能开启一个node,如果一次开启一组相关node,需要使用ros2 launch。

支持Python, XML, 和 YAML。

推荐Python。

zhangrelay@LAPTOP-5REQ7K1L:~$ ros2 run -h
usage: ros2 run [-h] [--prefix PREFIX] package_name executable_name ...

Run a package specific executable

positional arguments:
  package_name     Name of the ROS package
  executable_name  Name of the executable
  argv             Pass arbitrary arguments to the executable

options:
  -h, --help       show this help message and exit
  --prefix PREFIX  Prefix command, which should go before the executable. Command
                   must be wrapped in quotes if it contains spaces (e.g. --prefix
                   'gdb -ex run --args').
zhangrelay@LAPTOP-5REQ7K1L:~$ ros2 launch -h
usage: ros2 launch [-h] [-n] [-d] [-p | -s] [-a] [--launch-prefix LAUNCH_PREFIX]
                   [--launch-prefix-filter LAUNCH_PREFIX_FILTER]
                   package_name [launch_file_name] [launch_arguments ...]

Run a launch file

positional arguments:
  package_name          Name of the ROS package which contains the launch file
  launch_file_name      Name of the launch file
  launch_arguments      Arguments to the launch file; '<name>:=<value>' (for
                        duplicates, last one wins)

options:
  -h, --help            show this help message and exit
  -n, --noninteractive  Run the launch system non-interactively, with no terminal
                        associated
  -d, --debug           Put the launch system in debug mode, provides more verbose
                        output.
  -p, --print, --print-description
                        Print the launch description to the console without
                        launching it.
  -s, --show-args, --show-arguments
                        Show arguments that may be given to the launch file.
  -a, --show-all-subprocesses-output
                        Show all launched subprocesses' output by overriding their
                        output configuration using the
                        OVERRIDE_LAUNCH_PROCESS_OUTPUT envvar.
  --launch-prefix LAUNCH_PREFIX
                        Prefix command, which should go before all executables.
                        Command must be wrapped in quotes if it contains spaces
                        (e.g. --launch-prefix 'xterm -e gdb -ex run --args').
  --launch-prefix-filter LAUNCH_PREFIX_FILTER
                        Regex pattern for filtering which executables the --launch-
                        prefix is applied to by matching the executable name.
zhangrelay@LAPTOP-5REQ7K1L:~$

启动程序launch文件是用Python编写的,其功能是声明使用哪些选项或参数执行哪些程序。一个启动器可以包含另一个启动器,允许重用现有的启动器。之所以需要launch,是因为一个机器人应用程序有许多节点,它们都应该同时启动。逐个启动并调整每个节点的特定参数,使节点进行协作可能会很乏味。

软件包的启动器位于软件包的启动launch目录中,其名称通常以launch.py结尾。正如ros2运行时使用软件包中可用的程序一样,ros2启动时也使用可用的启动器。从实现的角度来看,启动器是一个python程序,它包含一个返回LaunchDescription对象的generatelaunchdescription()函数。

LaunchDescription对象包含操作,其中突出显示:

•node操作:运行程序。

•IncludeLaunchDescription操作:包括另一个启动器。

•DeclareLaunchArgument操作:声明启动器参数。

•SetEnvironmentVariable操作:设置环境变量。

书中案例如下:

v1

from launch import LaunchDescription
from launch_ros.actions import Node


def generate_launch_description():

    pub_cmd = Node(
        package='br2_basics',
        executable='publisher',
        output='screen'
    )
    sub_cmd = Node(
        package='br2_basics',
        executable='subscriber_class',
        output='screen'
    )

    ld = LaunchDescription()
    ld.add_action(pub_cmd)
    ld.add_action(sub_cmd)

    return ld

v2

from launch import LaunchDescription
from launch_ros.actions import Node


def generate_launch_description():

    return LaunchDescription([
        Node(
            package='br2_basics',
            executable='publisher',
            output='screen'
        ),
        Node(
            package='br2_basics',
            executable='subscriber_class',
            output='screen'
        )
    ])

CMakeLists

install(DIRECTORY launch DESTINATION share/$PROJECT_NAME)

效果如:

ros2 launch br2_basics pub_sub_v2_launch.py
[INFO] [launch]: All log files can be found below /home/zhangrelay/.ros/log/2023-01-20-09-06-49-444970-LAPTOP-5REQ7K1L-7896
[INFO] [launch]: Default logging verbosity is set to INFO
[INFO] [publisher-1]: process started with pid [7897]
[INFO] [subscriber_class-2]: process started with pid [7899]
[subscriber_class-2] [INFO] [1674176809.694879700] [subscriber_node]: Hello 1
[subscriber_class-2] [INFO] [1674176810.195718900] [subscriber_node]: Hello 2
[subscriber_class-2] [INFO] [1674176810.695717000] [subscriber_node]: Hello 3
[subscriber_class-2] [INFO] [1674176811.195712100] [subscriber_node]: Hello 4
[subscriber_class-2] [INFO] [1674176811.695709800] [subscriber_node]: Hello 5
[subscriber_class-2] [INFO] [1674176812.195715200] [subscriber_node]: Hello 6
[subscriber_class-2] [INFO] [1674176812.695273100] [subscriber_node]: Hello 7
[subscriber_class-2] [INFO] [1674176813.195665000] [subscriber_node]: Hello 8
[subscriber_class-2] [INFO] [1674176813.695714300] [subscriber_node]: Hello 9
[subscriber_class-2] [INFO] [1674176814.195719200] [subscriber_node]: Hello 10
[subscriber_class-2] [INFO] [1674176814.695718400] [subscriber_node]: Hello 11
[subscriber_class-2] [INFO] [1674176815.195444600] [subscriber_node]: Hello 12
[subscriber_class-2] [INFO] [1674176815.695682400] [subscriber_node]: Hello 13
[subscriber_class-2] [INFO] [1674176816.195665100] [subscriber_node]: Hello 14
[subscriber_class-2] [INFO] [1674176816.695713200] [subscriber_node]: Hello 15
[subscriber_class-2] [INFO] [1674176817.195601200] [subscriber_node]: Hello 16
[subscriber_class-2] [INFO] [1674176817.695310700] [subscriber_node]: Hello 17
[subscriber_class-2] [INFO] [1674176818.195711000] [subscriber_node]: Hello 18
[subscriber_class-2] [INFO] [1674176818.695683800] [subscriber_node]: Hello 19
[subscriber_class-2] [INFO] [1674176819.195543700] [subscriber_node]: Hello 20
[subscriber_class-2] [INFO] [1674176819.695711400] [subscriber_node]: Hello 21
[subscriber_class-2] [INFO] [1674176820.195726000] [subscriber_node]: Hello 22
[subscriber_class-2] [INFO] [1674176820.695710100] [subscriber_node]: Hello 23
[subscriber_class-2] [INFO] [1674176821.195487200] [subscriber_node]: Hello 24
[subscriber_class-2] [INFO] [1674176821.695709500] [subscriber_node]: Hello 25
[subscriber_class-2] [INFO] [1674176822.195718500] [subscriber_node]: Hello 26
[subscriber_class-2] [INFO] [1674176822.695726100] [subscriber_node]: Hello 27
[subscriber_class-2] [INFO] [1674176823.195704600] [subscriber_node]: Hello 28
[subscriber_class-2] [INFO] [1674176823.695726800] [subscriber_node]: Hello 29
[subscriber_class-2] [INFO] [1674176824.195718300] [subscriber_node]: Hello 30
[subscriber_class-2] [INFO] [1674176824.695579500] [subscriber_node]: Hello 31
[subscriber_class-2] [INFO] [1674176825.195705000] [subscriber_node]: Hello 32
[subscriber_class-2] [INFO] [1674176825.695724000] [subscriber_node]: Hello 33
[subscriber_class-2] [INFO] [1674176826.195724200] [subscriber_node]: Hello 34
[subscriber_class-2] [INFO] [1674176826.695665700] [subscriber_node]: Hello 35

更多内容参考官网:

launch

ROS 2启动文件允许同时启动和配置包含ROS 2节点的多个可执行文件。

1 创建启动文件

了解如何创建一个启动文件,该文件将同时启动节点及其配置。

from launch import LaunchDescription
from launch_ros.actions import Node

def generate_launch_description():
    return LaunchDescription([
        Node(
            package='turtlesim',
            namespace='turtlesim1',
            executable='turtlesim_node',
            name='sim'
        ),
        Node(
            package='turtlesim',
            namespace='turtlesim2',
            executable='turtlesim_node',
            name='sim'
        ),
        Node(
            package='turtlesim',
            executable='mimic',
            name='mimic',
            remappings=[
                ('/input/pose', '/turtlesim1/turtle1/pose'),
                ('/output/cmd_vel', '/turtlesim2/turtle1/cmd_vel'),
            ]
        )
    ])

package

<exec_depend>ros2launch</exec_depend>

2 启动和监视多个节点

获取有关启动文件工作方式的更高级概述。

import launch
import launch_ros.actions

def generate_launch_description():
    return launch.LaunchDescription([
        launch_ros.actions.Node(
            package='demo_nodes_cpp',
            executable='talker',
            name='talker'),
  ])

3 使用替换

在描述可重用的启动文件时,使用替换来提供更大的灵活性。

from launch_ros.actions import Node

from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument, ExecuteProcess, TimerAction
from launch.conditions import IfCondition
from launch.substitutions import LaunchConfiguration, 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=[[
            'ros2 service call ',
            turtlesim_ns,
            '/spawn ',
            'turtlesim/srv/Spawn ',
            '"x: 2, y: 2, theta: 0.2"'
        ]],
        shell=True
    )
    change_background_r = ExecuteProcess(
        cmd=[[
            '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=[[
            '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,
        spawn_turtle,
        change_background_r,
        TimerAction(
            period=2.0,
            actions=[change_background_r_conditioned],
        )
    ])

4 使用事件处理程序

使用事件处理程序监视进程的状态或定义一组复杂的规则,这些规则可用于动态修改启动文件。

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')]
                )]
            )
        ),
    ])

5 管理大型项目

为大型项目构建启动文件,以便在不同的情况下尽可能地重用它们。请参阅不同启动工具的用法示例,如参数、YAML文件、重映射、名称空间、默认参数和RViz配置。

import os

from ament_index_python.packages import get_package_share_directory

from launch import LaunchDescription
from launch.actions import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource


def generate_launch_description():
   turtlesim_world_1 = IncludeLaunchDescription(
      PythonLaunchDescriptionSource([os.path.join(
         get_package_share_directory('launch_tutorial'), 'launch'),
         '/turtlesim_world_1.launch.py'])
      )
   turtlesim_world_2 = IncludeLaunchDescription(
      PythonLaunchDescriptionSource([os.path.join(
         get_package_share_directory('launch_tutorial'), 'launch'),
         '/turtlesim_world_2.launch.py'])
      )
   broadcaster_listener_nodes = IncludeLaunchDescription(
      PythonLaunchDescriptionSource([os.path.join(
         get_package_share_directory('launch_tutorial'), 'launch'),
         '/broadcaster_listener.launch.py']),
      launch_arguments='target_frame': 'carrot1'.items(),
      )
   mimic_node = IncludeLaunchDescription(
      PythonLaunchDescriptionSource([os.path.join(
         get_package_share_directory('launch_tutorial'), 'launch'),
         '/mimic.launch.py'])
      )
   fixed_frame_node = IncludeLaunchDescription(
      PythonLaunchDescriptionSource([os.path.join(
         get_package_share_directory('launch_tutorial'), 'launch'),
         '/fixed_broadcaster.launch.py'])
      )
   rviz_node = IncludeLaunchDescription(
      PythonLaunchDescriptionSource([os.path.join(
         get_package_share_directory('launch_tutorial'), 'launch'),
         '/turtlesim_rviz.launch.py'])
      )

   return LaunchDescription([
      turtlesim_world_1,
      turtlesim_world_2,
      broadcaster_listener_nodes,
      mimic_node,
      fixed_frame_node,
      rviz_node
   ])

以上是关于-Launchers .3.3的主要内容,如果未能解决你的问题,请参考以下文章

如何使节标题中的 UITextView 将其高度调整为其内容

如何使节点画布中图像的大小始终为 128 像素

紧紧地握住自己的命运

Nuxt.js入门安装及灵活使用

Nuxt.js入门安装及灵活使用

CakePHP 教程:PHP 开发框架