使用替代项

**目标:**了解ROS 2启动文件中的替代项。

教程级别: 中级

时间: 15分钟

背景

启动文件用于启动节点、服务和执行进程。这组操作可能有参数,这些参数会影响它们的行为。在参数中可以使用替代项,以提供更多的灵活性,描述可重复使用的启动文件。替代项是仅在启动描述执行期间评估的变量,可以用于获取特定的信息,比如启动配置、环境变量,或者评估任意的Python表达式。

本教程展示了在ROS 2启动文件中使用替代项的用法示例。

先决条件

本教程使用了 turtlesim 包。同时假设你已经熟悉 创建包

如往常一样,在每次打开新的终端时不要忘记在 :doc`每个新终端中启用ROS 2环境 <../../Beginner-CLI-Tools/Configuring-ROS2-Environment>`。

使用替代项

1 创建并设置包

创建一个名为``launch_tutorial``的新构建类型为``ament_python``的软件包:

ros2 pkg create launch_tutorial --build-type ament_python

在该软件包中创建一个名为``launch``的目录:

mkdir launch_tutorial/launch

最后,确保在软件包的``setup.py``中添加更改,以便安装启动文件:

import os
from glob import glob
from setuptools import setup

package_name = 'launch_tutorial'

setup(
    # Other parameters ...
    data_files=[
        # ... Other data files
        # Include all launch files.
        (os.path.join('share', package_name, 'launch'), glob(os.path.join('launch', '*launch.[pxy][yma]*')))
    ]
)

2. 父级启动文件

让我们创建一个启动文件,调用并传递参数给另一个启动文件。为此,在``launch_tutorial``软件包的``launch``文件夹中创建一个名为``example_main.launch.py``的文件。

from launch_ros.substitutions import FindPackageShare

from launch import LaunchDescription
from launch.actions import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch.substitutions import PathJoinSubstitution, TextSubstitution


def generate_launch_description():
    colors = {
        'background_r': '200'
    }

    return LaunchDescription([
        IncludeLaunchDescription(
            PythonLaunchDescriptionSource([
                PathJoinSubstitution([
                    FindPackageShare('launch_tutorial'),
                    'launch',
                    'example_substitutions.launch.py'
                ])
            ]),
            launch_arguments={
                'turtlesim_ns': 'turtlesim2',
                'use_provided_red': 'True',
                'new_background_r': TextSubstitution(text=str(colors['background_r']))
            }.items()
        )
    ])

在``example_main.launch.py``文件中,使用``FindPackageShare``替代找到``launch_tutorial``软件包的路径。然后,使用``PathJoinSubstitution``替代将该软件包路径与``example_substitutions.launch.py``文件名连接起来。

PathJoinSubstitution([
    FindPackageShare('launch_tutorial'),
    'launch',
    'example_substitutions.launch.py'
])

将具有 turtlesim_nsuse_provided_red 参数的 launch_arguments 字典传递给 IncludeLaunchDescription 动作。使用 TextSubstitution 替代方式来定义具有 colors 字典中 background_r 键的值的 new_background_r 参数。

launch_arguments={
    'turtlesim_ns': 'turtlesim2',
    'use_provided_red': 'True',
    'new_background_r': TextSubstitution(text=str(colors['background_r']))
}.items()

3个替代方式示例的启动文件

现在在相同文件夹中创建一个名为 example_substitutions.launch.py 的文件。

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

example_substitutions.launch.py 文件中,定义了 turtlesim_nsuse_provided_rednew_background_r 的启动配置。它们用于在上述变量中存储启动参数的值,并将其传递给所需的动作。这些 LaunchConfiguration 替代方式允许我们在启动描述的任何部分中获取启动参数的值。

使用 DeclareLaunchArgument 定义可以从上述启动文件或控制台传递的启动参数。

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

定义了具有 namespace 设置为 turtlesim_nsturtlesim_node 节点,并使用 LaunchConfiguration 替代方式。

turtlesim_node = Node(
    package='turtlesim',
    namespace=turtlesim_ns,
    executable='turtlesim_node',
    name='sim'
)

之后,定义了``ExecuteProcess``动作``spawn_turtle``,并提供相应的``cmd``参数。此命令调用了turtlesim节点的spawn服务。

此外,使用``LaunchConfiguration``替代方式获取``turtlesim_ns``启动参数的值,以构建命令字符串。

spawn_turtle = ExecuteProcess(
    cmd=[[
        'ros2 service call ',
        turtlesim_ns,
        '/spawn ',
        'turtlesim/srv/Spawn ',
        '"{x: 2, y: 2, theta: 0.2}"'
    ]],
    shell=True
)

同样的方法被用于更改turtlesim背景红色参数的``change_background_r``和``change_background_r_conditioned``动作。区别在于,只有当提供的``new_background_r``参数等于``200``并且``use_provided_red``启动参数设置为``True``时,才会执行``change_background_r_conditioned``动作。在``IfCondition``内部的评估使用``PythonExpression``替代方式完成。

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
)

4 构建软件包

转到工作空间的根目录,并构建软件包:

colcon build

构建完成后,请记得设置工作空间环境。

启动示例

现在可以使用``ros2 launch``命令启动``example_main.launch.py``文件。

ros2 launch launch_tutorial example_main.launch.py

这将执行以下操作:

  1. 启动一个带有蓝色背景的turtlesim节点

  2. 生成第二只乌龟

  3. 如果提供的``background_r``参数为``200``且``use_provided_red``参数为``True``,则将颜色更改为紫色

  4. 如果提供的``background_r``参数为``200``且``use_provided_red``参数为``True``,则在两秒后将颜色更改为粉色

修改启动参数

如果您想要更改提供的启动参数,您可以在``example_main.launch.py``中的``launch_arguments``字典中更新它们,或者使用首选参数启动``example_substitutions.launch.py``。要查看可能提供给启动文件的参数,请运行以下命令:

ros2 launch launch_tutorial example_substitutions.launch.py --show-args

这将显示可能提供给启动文件的参数及其默认值。

Arguments (pass arguments as '<name>:=<value>'):

    'turtlesim_ns':
        no description given
        (default: 'turtlesim1')

    'use_provided_red':
        no description given
        (default: 'False')

    'new_background_r':
        no description given
        (default: '200')

现在,您可以按以下方式传递所需的参数给启动文件:

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

文档

``The launch documentation <https://github.com/ros2/launch/blob/humble/launch/doc/source/architecture.rst>`_ 提供了有关可用替换的详细信息。

总结

在本教程中,您了解了如何在启动文件中使用替换。您了解了它们的可能性和能力,以创建可重用的启动文件。

您现在可以了解更多关于 在启动文件中使用事件处理程序 的信息,它们用于定义一组复杂的规则,可用于动态修改启动文件。