赞
踩
分别有CLI-launch,Python+XML+YAML对比,launch教程三部分:
- docs.ros.org/en/humble/Tutorials/Launch/CLI-Intro.html
-
- docs.ros.org/en/humble/How-To-Guides/Launch-file-different-formats.html
-
- docs.ros.org/en/humble/Tutorials/Launch/Launch-Main.html
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.
例如:
ros2 launch turtlesim multisim.launch.py
其中,multisim.launch.py 如下:
- # turtlesim/launch/multisim.launch.py
-
- from launch import LaunchDescription
- import launch_ros.actions
-
- def generate_launch_description():
- return LaunchDescription([
- launch_ros.actions.Node(
- namespace= "turtlesim1", package='turtlesim', executable='turtlesim_node', output='screen'),
- launch_ros.actions.Node(
- namespace= "turtlesim2", package='turtlesim', executable='turtlesim_node', output='screen'),
- ])
控制其中的小乌龟用rqt工具或如下指令:
1:ros2 topic pub /turtlesim1/turtle1/cmd_vel geometry_msgs/msg/Twist "{linear: {x: 2.0, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: 1.8}}"
2:ros2 topic pub /turtlesim2/turtle1/cmd_vel geometry_msgs/msg/Twist "{linear: {x: 2.0, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: -1.8}}"
启动launch教程
ROS 2 Launch 文件允许同时启动和配置多个包含 ROS 2 节点的可执行文件。
学习启动
1 创建 ROS 2 启动文件。
本教程将展示如何创建一个启动文件,该文件将同时启动节点及其配置。
- 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'),
- ]
- )
- ])
2 使用 Launch 启动和监控多个节点。
关于启动文件如何工作以及可用的资源和文档的更高级概述。
- import platform
-
- import launch
- import launch.actions
- import launch.substitutions
- import launch_ros.actions
-
- env_var_name = 'USER' if platform.system() != 'Windows' else 'USERNAME'
-
- def generate_launch_description():
- return launch.LaunchDescription([
- launch.actions.DeclareLaunchArgument(
- 'node_prefix',
- default_value=[launch.substitutions.EnvironmentVariable(env_var_name), '_'],
- description='Prefix for node names'),
- launch_ros.actions.Node(
- package='demo_nodes_cpp', executable='talker', output='screen',
- name=[launch.substitutions.LaunchConfiguration('node_prefix'), '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 使用事件处理程序。
事件处理程序可用于监视进程的状态或定义一组复杂的规则,这些规则可用于动态修改启动文件。
ROS 2 中的 Launch 是一个执行和管理用户定义流程的系统。 它负责监控它启动的进程的状态,以及报告和响应这些进程的状态变化。 这些更改称为事件,可以通过向启动系统注册事件处理程序来处理。 可以为特定事件注册事件处理程序,并可用于监视进程的状态。 此外,它们可用于定义一组复杂的规则,可用于动态修改启动文件。
本教程展示了 ROS 2 启动文件中事件处理程序的使用示例。
- 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 使用 ROS 2 启动大型项目。
本教程描述了为大型项目编写启动文件的一些技巧。重点是如何构建启动文件,以便在不同情况下尽可能多地重用它们。此外,它还涵盖了不同 ROS 2 启动工具的使用示例,例如参数、YAML 文件、重新映射、命名空间、默认参数和 RViz 配置。
机器人上的大型应用程序通常涉及多个相互连接的节点,每个节点都可以有许多参数。 在海龟模拟器中模拟多只海龟就是一个很好的例子。 海龟模拟由多个海龟节点、世界配置以及 TF 广播器和侦听器节点组成。 在所有节点之间,存在大量影响这些节点行为和外观的 ROS 参数。 ROS 2 启动文件允许我们在一个地方启动所有节点并设置相应的参数。 在教程结束时,将在 launch_tutorial 包中构建 launch_turtlesim.launch.py 启动文件。 这个启动文件会调出不同的节点,负责模拟两个turtlesim模拟,启动TF广播器和监听器,加载参数,启动一个RViz配置。 在本教程中,将介绍这个启动文件和使用的所有相关功能。
Python、XML 或 YAML:应该使用哪个?
提示:ROS 1 中的启动文件是用 XML 编写的,因此来自 ROS 1 的人可能最熟悉 XML。要查看发生了什么变化,可以访问将启动文件从 ROS 1 迁移到 ROS 2。
对于大多数应用程序,选择哪种 ROS 2 启动格式取决于开发人员的偏好。 但是,如果启动文件需要 XML 或 YAML 无法实现的灵活性,可以使用 Python 编写启动文件。 由于以下两个原因,使用 Python 启动 ROS 2 更加灵活:
话虽如此,用 Python 编写的启动文件可能比用 XML 或 YAML 编写的启动文件更复杂和冗长。
同一功能对比如下:
Python
- # 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(LaunchConfiguration('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,
- ])
xml
- <!-- example.launch.xml -->
-
- <launch>
-
- <!-- args that can be set from the command line or a default will be used -->
- <arg name="background_r" default="0"/>
- <arg name="background_g" default="255"/>
- <arg name="background_b" default="0"/>
- <arg name="chatter_ns" default="my/chatter/ns"/>
-
- <!-- include another launch file -->
- <include file="$(find-pkg-share demo_nodes_cpp)/launch/topics/talker_listener.launch.py"/>
- <!-- include another launch file in the chatter_ns namespace-->
- <group>
- <!-- push_ros_namespace to set namespace of included nodes -->
- <push_ros_namespace namespace="$(var chatter_ns)"/>
- <include file="$(find-pkg-share demo_nodes_cpp)/launch/topics/talker_listener.launch.py"/>
- </group>
-
- <!-- start a turtlesim_node in the turtlesim1 namespace -->
- <node pkg="turtlesim" exec="turtlesim_node" name="sim" namespace="turtlesim1"/>
- <!-- start another turtlesim_node in the turtlesim2 namespace
- and use args to set parameters -->
- <node pkg="turtlesim" exec="turtlesim_node" name="sim" namespace="turtlesim2">
- <param name="background_r" value="$(var background_r)"/>
- <param name="background_g" value="$(var background_g)"/>
- <param name="background_b" value="$(var background_b)"/>
- </node>
- <!-- perform remap so both turtles listen to the same command topic -->
- <node pkg="turtlesim" exec="mimic" name="mimic">
- <remap from="/input/pose" to="/turtlesim1/turtle1/pose"/>
- <remap from="/output/cmd_vel" to="/turtlesim2/turtle1/cmd_vel"/>
- </node>
- </launch>
yaml
# example.launch.yaml launch: # args that can be set from the command line or a default will be used - arg: name: "background_r" default: "0" - arg: name: "background_g" default: "255" - arg: name: "background_b" default: "0" - arg: name: "chatter_ns" default: "my/chatter/ns" # include another launch file - include: file: "$(find-pkg-share demo_nodes_cpp)/launch/topics/talker_listener.launch.py" # include another launch file in the chatter_ns namespace - group: - push_ros_namespace: namespace: "$(var chatter_ns)" - include: file: "$(find-pkg-share demo_nodes_cpp)/launch/topics/talker_listener.launch.py" # start a turtlesim_node in the turtlesim1 namespace - node: pkg: "turtlesim" exec: "turtlesim_node" name: "sim" namespace: "turtlesim1" # start another turtlesim_node in the turtlesim2 namespace and use args to set parameters - node: pkg: "turtlesim" exec: "turtlesim_node" name: "sim" namespace: "turtlesim2" param: - name: "background_r" value: "$(var background_r)" - name: "background_g" value: "$(var background_g)" - name: "background_b" value: "$(var background_b)" # perform remap so both turtles listen to the same command topic - node: pkg: "turtlesim" exec: "mimic" name: "mimic" remap: - from: "/input/pose" to: "/turtlesim1/turtle1/pose" - from: "/output/cmd_vel" to: "/turtlesim2/turtle1/cmd_vel"
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。