ROS2 launch介绍

  •  个人主页:linux_嵌入式大师之路的博客-CSDN博客
  • 欢迎 点赞✍评论⭐收藏
  • 希望本文能对你有所帮助,欢迎在评论区交流讨论!

前言

在大多数入门教程中,运行的每个新节点打开新的终端。随着创建越来越多的节点同时运行的更复杂的系统,需要重复的打开终端和重新输入。
launch文件允许同时启动和配置许多包含ROS 2节点的可执行文件。 
使用 ros2 launch 命令运行单个launch文件将立即启动整个系统所有节点及其配置。

1. 创建节点

启动一个名为test_node的节点,并指定了该节点的可执行文件所属包、名称、日志输出、参数等选项。

test_node = launch_ros.actions.Node(
package='demo',
executable='test_node',
output='screen',
parameters=[{
'hz': launch.substitutions.LaunchConfiguration('hz'),
}])

2. LaunchDescription

LaunchDescription可以包含 参数、其他launch文件和ros节点。

LaunchDescription是ROS 2中用于描述launch文件的主要对象之一。它是一个Python类,用于组织和描述launch文件中的各个启动操作。

在ROS 2中,launch文件用于同时启动和配置多个ROS节点。LaunchDescription对象允许你将多个启动操作组合在一起,并定义它们之间的依赖关系和顺序。通过使用LaunchDescription,可以以可编程的方式构建复杂的启动配置。

以下是LaunchDescription的一些重要特性和用法:

  1. 组织和组合启动操作:可以使用LaunchDescription来组织和描述launch文件中的各个启动操作,例如启动节点、加载参数文件、设置环境变量等。通过添加不同类型的启动操作,可以构建出完整的启动配置。
  2. 设置启动操作的依赖关系:可以使用add_action()方法将启动操作添加到LaunchDescription对象中,并设置它们之间的依赖关系。这样可以确保在启动时按照正确的顺序执行各个操作。
  3. 设置全局选项:LaunchDescription对象还可以设置全局选项,如设置launch文件的名称、描述、命名空间等。这些选项可以影响所有的启动操作。
  4. 启动操作的执行方式:通过LaunchDescription可以设置启动操作的执行方式,例如设置启动操作是否在新的命名空间中执行、是否在新的Shell中执行等。
  5. 启动文件的编程接口:可以通过编写Python脚本来创建和配置LaunchDescription对象,从而以编程方式生成launch文件。这样可以更灵活地处理各种复杂的启动配置需求。

下面是一个简单的示例,展示了如何使用LaunchDescription来创建一个包含两个节点的launch文件描述:

from launch import LaunchDescription
from launch.actions import ExecuteProcess

def generate_launch_description():
    ld = LaunchDescription()

    node1_action = ExecuteProcess(
        cmd=['/path/to/node1'],
        output='screen'
    )
    node2_action = ExecuteProcess(
        cmd=['/path/to/node2'],
        output='screen'
    )

    ld.add_action(node1_action)
    ld.add_action(node2_action)

    return ld

在上述示例中,generate_launch_description函数返回一个LaunchDescription对象,该对象描述了一个包含两个节点的launch文件。通过添加ExecuteProcess(ROS2中用于执行外部进程)操作,指定节点的可执行文件路径,并将它们添加到LaunchDescription对象中。

需要注意的是,LaunchDescription仅用于描述launch文件的结构和内容,要真正运行launch文件,还需要使用ROS 2的启动工具,如ros2 launch命令行工具或者使用Python API进行启动。

总之,LaunchDescription提供了一种灵活且强大的方式来描述和组织ROS 2的launch文件,使得启动多个ROS节点变得更加方便和可控。

3. GroupAction

在ROS 2的launch文件中,GroupAction是一种用于组合多个动作(action)的特殊类型动作。它允许将多个动作作为一个整体来执行,以便更好地控制和管理节点启动顺序、参数设置和节点之间的依赖关系。

GroupAction可以包含各种类型的动作,如启动节点、设置参数、等待条件等。通过使用GroupAction,可以实现复杂的启动逻辑和依赖管理,以确保节点按照所需的顺序和条件启动。

# 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 IncludeLaunchDescription
from launch.actions import GroupAction
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


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_ns_launch_arg = DeclareLaunchArgument(
        "chatter_ns", default_value=TextSubstitution(text="my/chatter/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 another launch file in the chatter_ns namespace
    launch_include_with_namespace = GroupAction(
        actions=[
            # push_ros_namespace to set namespace of included nodes
            PushRosNamespace('chatter_ns'),
            IncludeLaunchDescription(
                PythonLaunchDescriptionSource(
                    os.path.join(
                        get_package_share_directory('demo_nodes_cpp'),
                        'launch/topics/talker_listener.launch.py'))
            ),
        ]
    )

    # 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_ns_launch_arg,
        launch_include,
        launch_include_with_namespace,
        turtlesim_node,
        turtlesim_node_with_parameters,
        forward_turtlesim_commands_to_second_turtlesim_node,
    ])

4. ComposableNodeContainer

是一种特殊的节点容器,用于组合多个节点(ComposableNode)为一个整体。个人理解和GroupAction的区别为:ComposableNodeContainer组合为一个新的节点(一个新的进程);而GroupAction只是强调了依赖关系,其中一个节点运行失败则整个组失败,但仍然是多个节点(多个进程)。

import launch
from launch_ros.actions import ComposableNodeContainer
from launch_ros.descriptions import ComposableNode



def generate_launch_description():
    container = ComposableNodeContainer(
            name='image_container',
            namespace='',
            package='rclcpp_components',
            executable='component_container',
            composable_node_descriptions=[
                ComposableNode(
                    package='image_tools',
                    plugin='image_tools::Cam2Image',
                    name='cam2image',
                    remappings=[('/image', '/burgerimage')],
                    parameters=[{'width': 320, 'height': 240, 'burger_mode': True, 'history': 'keep_last'}],
                    extra_arguments=[{'use_intra_process_comms': True}]),
                ComposableNode(
                    package='image_tools',
                    plugin='image_tools::ShowImage',
                    name='showimage',
                    remappings=[('/image', '/burgerimage')],
                    parameters=[{'history': 'keep_last'}],
                    extra_arguments=[{'use_intra_process_comms': True}])
            ],
            output='both',
    )

    return launch.LaunchDescription([container])

5. IncludeLaunchDescription

注意参数传递和Node存在区别,传递的不是字典,而是元组。

PathJoinSubstitution用于拼接目录

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

6 导入yaml文件

import os

from ament_index_python.packages import get_package_share_directory

from launch import LaunchDescription
from launch_ros.actions import Node


def generate_launch_description():
   config = os.path.join(
      get_package_share_directory('launch_tutorial'),
      'config',
      'turtlesim.yaml'
      )

   return LaunchDescription([
      Node(
         package='turtlesim',
         executable='turtlesim_node',
         namespace='turtlesim2',
         name='sim',
         parameters=[config]
      )
   ])

你可能感兴趣的:(ROS2,嵌入式硬件,linux,ROS2,c++)