使用 Python、XML 和 YAML 生成 ROS 2 启动文件

ROS 2 启动文件可以用 Python、XML 和 YAML 编写。 本指南介绍了如何使用这些不同的格式来完成相同的任务,并讨论了何时使用每种格式。

启动文件示例

下面是用 Python、XML 和 YAML 实现的启动文件。 每个启动文件执行以下操作:

  • 使用默认值设置命令行参数

  • 包含另一个启动文件

  • 在另一个命名空间中包含另一个启动文件

  • 启动一个节点并设置其命名空间

  • 启动一个节点,设置其命名空间,并在该节点中设置参数(使用参数)

  • 创建一个节点以将消息从一个主题重新映射到另一个主题

# example_launch.py

import os

from ament_index_python import get_package_share_directory

from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument
from launch.actions import GroupAction
from launch.actions import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch.substitutions import LaunchConfiguration
from launch.substitutions import TextSubstitution
from launch_ros.actions import Node
from launch_ros.actions import PushROSNamespace
from launch_xml.launch_description_sources import XMLLaunchDescriptionSource
from launch_yaml.launch_description_sources import YAMLLaunchDescriptionSource


def generate_launch_description():

    # args that can be set from the command line or a default will be used
    background_r_launch_arg = DeclareLaunchArgument(
        "background_r", default_value=TextSubstitution(text="0")
    )
    background_g_launch_arg = DeclareLaunchArgument(
        "background_g", default_value=TextSubstitution(text="255")
    )
    background_b_launch_arg = DeclareLaunchArgument(
        "background_b", default_value=TextSubstitution(text="0")
    )
    chatter_py_ns_launch_arg = DeclareLaunchArgument(
        "chatter_py_ns", default_value=TextSubstitution(text="chatter/py/ns")
    )
    chatter_xml_ns_launch_arg = DeclareLaunchArgument(
        "chatter_xml_ns", default_value=TextSubstitution(text="chatter/xml/ns")
    )
    chatter_yaml_ns_launch_arg = DeclareLaunchArgument(
        "chatter_yaml_ns", default_value=TextSubstitution(text="chatter/yaml/ns")
    )

    # include another launch file
    launch_include = IncludeLaunchDescription(
        PythonLaunchDescriptionSource(
            os.path.join(
                get_package_share_directory('demo_nodes_cpp'),
                'launch/topics/talker_listener_launch.py'))
    )
    # include a Python launch file in the chatter_py_ns namespace
    launch_py_include_with_namespace = GroupAction(
        actions=[
            # push_ros_namespace first to set namespace of included nodes for following actions
            PushROSNamespace('chatter_py_ns'),
            IncludeLaunchDescription(
                PythonLaunchDescriptionSource(
                    os.path.join(
                        get_package_share_directory('demo_nodes_cpp'),
                        'launch/topics/talker_listener_launch.py'))
            ),
        ]
    )

    # include a xml launch file in the chatter_xml_ns namespace
    launch_xml_include_with_namespace = GroupAction(
        actions=[
            # push_ros_namespace first to set namespace of included nodes for following actions
            PushROSNamespace('chatter_xml_ns'),
            IncludeLaunchDescription(
                XMLLaunchDescriptionSource(
                    os.path.join(
                        get_package_share_directory('demo_nodes_cpp'),
                        'launch/topics/talker_listener_launch.xml'))
            ),
        ]
    )

    # include a yaml launch file in the chatter_yaml_ns namespace
    launch_yaml_include_with_namespace = GroupAction(
        actions=[
            # push_ros_namespace first to set namespace of included nodes for following actions
            PushROSNamespace('chatter_yaml_ns'),
            IncludeLaunchDescription(
                YAMLLaunchDescriptionSource(
                    os.path.join(
                        get_package_share_directory('demo_nodes_cpp'),
                        'launch/topics/talker_listener_launch.yaml'))
            ),
        ]
    )

    # start a turtlesim_node in the turtlesim1 namespace
    turtlesim_node = Node(
        package='turtlesim',
        namespace='turtlesim1',
        executable='turtlesim_node',
        name='sim'
    )

    # start another turtlesim_node in the turtlesim2 namespace
    # and use args to set parameters
    turtlesim_node_with_parameters = Node(
        package='turtlesim',
        namespace='turtlesim2',
        executable='turtlesim_node',
        name='sim',
        parameters=[{
            "background_r": LaunchConfiguration('background_r'),
            "background_g": LaunchConfiguration('background_g'),
            "background_b": LaunchConfiguration('background_b'),
        }]
    )

    # perform remap so both turtles listen to the same command topic
    forward_turtlesim_commands_to_second_turtlesim_node = Node(
        package='turtlesim',
        executable='mimic',
        name='mimic',
        remappings=[
            ('/input/pose', '/turtlesim1/turtle1/pose'),
            ('/output/cmd_vel', '/turtlesim2/turtle1/cmd_vel'),
        ]
    )

    return LaunchDescription([
        background_r_launch_arg,
        background_g_launch_arg,
        background_b_launch_arg,
        chatter_py_ns_launch_arg,
        chatter_xml_ns_launch_arg,
        chatter_yaml_ns_launch_arg,
        launch_include,
        launch_py_include_with_namespace,
        launch_xml_include_with_namespace,
        launch_yaml_include_with_namespace,
        turtlesim_node,
        turtlesim_node_with_parameters,
        forward_turtlesim_commands_to_second_turtlesim_node,
    ])

从命令行使用 Launch 文件

启动

上述任何启动文件都可以使用“ros2 launch”运行。 要在本地试用它们,您可以创建一个新包并使用

ros2 launch <package_name> <launch_file_name>

或者通过指定启动文件的路径直接运行该文件

ros2 launch <path_to_launch_file>

设置参数

要设置传递给启动文件的参数,您应该使用“key:=value”语法。 例如,您可以按以下方式设置“background_r”的值:

ros2 launch <package_name> <launch_file_name> background_r:=255

或者

ros2 launch <path_to_launch_file> background_r:=255

控制海龟

要测试重新映射是否有效,您可以通过在另一个终端中运行以下命令来控制海龟:

ros2 run turtlesim turtle_teleop_key --ros-args --remap __ns:=/turtlesim1

Python、XML 还是 YAML:我应该使用哪一个?

Note

ROS 1 中的启动文件是用 XML 编写的,因此对于来自 ROS 1 的人来说,XML 可能是最熟悉的。 要查看更改的内容,您可以访问:doc:迁移启动文件

对于大多数应用程序,选择哪种 ROS 2 启动格式取决于开发人员的偏好。 但是,如果您的启动文件需要 XML 或 YAML 无法实现的灵活性,则可以使用 Python 编写启动文件。 使用 Python 进行 ROS 2 启动更加灵活,原因如下:

  • Python 是一种脚本语言,因此您可以在启动文件中利用该语言及其库。

  • `ros2/launch <https://github.com/ros2/launch>`_(常规启动功能)和 `ros2/launch_ros <https://github.com/ros2/launch_ros>`_(ROS 2 特定启动功能)是用 Python 编写的,因此您可以以较低级别的权限访问 XML 和 YAML 可能无法公开的启动功能。

话虽如此,用 Python 编写的启动文件可能比用 XML 或 YAML 编写的启动文件更复杂、更冗长。