当前位置:   article > 正文

ROS 2 Humble Hawksbill 启动文件 launch_launch.substitutions

launch.substitutions

分别有CLI-launch,Python+XML+YAML对比,launch教程三部分:

  1. docs.ros.org/en/humble/Tutorials/Launch/CLI-Intro.html
  2. docs.ros.org/en/humble/How-To-Guides/Launch-file-different-formats.html
  3. docs.ros.org/en/humble/Tutorials/Launch/Launch-Main.html

ros2 launch -h

  1. usage: ros2 launch [-h] [-n] [-d] [-p | -s] [-a] [--launch-prefix LAUNCH_PREFIX]
  2. [--launch-prefix-filter LAUNCH_PREFIX_FILTER]
  3. package_name [launch_file_name] [launch_arguments ...]
  4. Run a launch file
  5. positional arguments:
  6. package_name Name of the ROS package which contains the launch file
  7. launch_file_name Name of the launch file
  8. launch_arguments Arguments to the launch file; '<name>:=<value>' (for duplicates, last one wins)
  9. options:
  10. -h, --help show this help message and exit
  11. -n, --noninteractive Run the launch system non-interactively, with no terminal associated
  12. -d, --debug Put the launch system in debug mode, provides more verbose output.
  13. -p, --print, --print-description
  14. Print the launch description to the console without launching it.
  15. -s, --show-args, --show-arguments
  16. Show arguments that may be given to the launch file.
  17. -a, --show-all-subprocesses-output
  18. Show all launched subprocesses' output by overriding their output configuration using the
  19. OVERRIDE_LAUNCH_PROCESS_OUTPUT envvar.
  20. --launch-prefix LAUNCH_PREFIX
  21. Prefix command, which should go before all executables. Command must be wrapped in quotes if
  22. it contains spaces (e.g. --launch-prefix 'xterm -e gdb -ex run --args').
  23. --launch-prefix-filter LAUNCH_PREFIX_FILTER
  24. Regex pattern for filtering which executables the --launch-prefix is applied to by matching
  25. the executable name.

例如:

ros2 launch turtlesim multisim.launch.py

其中,multisim.launch.py 如下:

  1. # turtlesim/launch/multisim.launch.py
  2. from launch import LaunchDescription
  3. import launch_ros.actions
  4. def generate_launch_description():
  5. return LaunchDescription([
  6. launch_ros.actions.Node(
  7. namespace= "turtlesim1", package='turtlesim', executable='turtlesim_node', output='screen'),
  8. launch_ros.actions.Node(
  9. namespace= "turtlesim2", package='turtlesim', executable='turtlesim_node', output='screen'),
  10. ])

控制其中的小乌龟用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 启动文件。

本教程将展示如何创建一个启动文件,该文件将同时启动节点及其配置。

  1. from launch import LaunchDescription
  2. from launch_ros.actions import Node
  3. def generate_launch_description():
  4. return LaunchDescription([
  5. Node(
  6. package='turtlesim',
  7. namespace='turtlesim1',
  8. executable='turtlesim_node',
  9. name='sim'
  10. ),
  11. Node(
  12. package='turtlesim',
  13. namespace='turtlesim2',
  14. executable='turtlesim_node',
  15. name='sim'
  16. ),
  17. Node(
  18. package='turtlesim',
  19. executable='mimic',
  20. name='mimic',
  21. remappings=[
  22. ('/input/pose', '/turtlesim1/turtle1/pose'),
  23. ('/output/cmd_vel', '/turtlesim2/turtle1/cmd_vel'),
  24. ]
  25. )
  26. ])

2 使用 Launch 启动和监控多个节点。

关于启动文件如何工作以及可用的资源和文档的更高级概述。

  1. import platform
  2. import launch
  3. import launch.actions
  4. import launch.substitutions
  5. import launch_ros.actions
  6. env_var_name = 'USER' if platform.system() != 'Windows' else 'USERNAME'
  7. def generate_launch_description():
  8. return launch.LaunchDescription([
  9. launch.actions.DeclareLaunchArgument(
  10. 'node_prefix',
  11. default_value=[launch.substitutions.EnvironmentVariable(env_var_name), '_'],
  12. description='Prefix for node names'),
  13. launch_ros.actions.Node(
  14. package='demo_nodes_cpp', executable='talker', output='screen',
  15. name=[launch.substitutions.LaunchConfiguration('node_prefix'), 'talker']),
  16. ])

3 使用替代品。

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

  1. from launch_ros.actions import Node
  2. from launch import LaunchDescription
  3. from launch.actions import DeclareLaunchArgument, ExecuteProcess, TimerAction
  4. from launch.conditions import IfCondition
  5. from launch.substitutions import LaunchConfiguration, PythonExpression
  6. def generate_launch_description():
  7. turtlesim_ns = LaunchConfiguration('turtlesim_ns')
  8. use_provided_red = LaunchConfiguration('use_provided_red')
  9. new_background_r = LaunchConfiguration('new_background_r')
  10. turtlesim_ns_launch_arg = DeclareLaunchArgument(
  11. 'turtlesim_ns',
  12. default_value='turtlesim1'
  13. )
  14. use_provided_red_launch_arg = DeclareLaunchArgument(
  15. 'use_provided_red',
  16. default_value='False'
  17. )
  18. new_background_r_launch_arg = DeclareLaunchArgument(
  19. 'new_background_r',
  20. default_value='200'
  21. )
  22. turtlesim_node = Node(
  23. package='turtlesim',
  24. namespace=turtlesim_ns,
  25. executable='turtlesim_node',
  26. name='sim'
  27. )
  28. spawn_turtle = ExecuteProcess(
  29. cmd=[[
  30. 'ros2 service call ',
  31. turtlesim_ns,
  32. '/spawn ',
  33. 'turtlesim/srv/Spawn ',
  34. '"{x: 2, y: 2, theta: 0.2}"'
  35. ]],
  36. shell=True
  37. )
  38. change_background_r = ExecuteProcess(
  39. cmd=[[
  40. 'ros2 param set ',
  41. turtlesim_ns,
  42. '/sim background_r ',
  43. '120'
  44. ]],
  45. shell=True
  46. )
  47. change_background_r_conditioned = ExecuteProcess(
  48. condition=IfCondition(
  49. PythonExpression([
  50. new_background_r,
  51. ' == 200',
  52. ' and ',
  53. use_provided_red
  54. ])
  55. ),
  56. cmd=[[
  57. 'ros2 param set ',
  58. turtlesim_ns,
  59. '/sim background_r ',
  60. new_background_r
  61. ]],
  62. shell=True
  63. )
  64. return LaunchDescription([
  65. turtlesim_ns_launch_arg,
  66. use_provided_red_launch_arg,
  67. new_background_r_launch_arg,
  68. turtlesim_node,
  69. spawn_turtle,
  70. change_background_r,
  71. TimerAction(
  72. period=2.0,
  73. actions=[change_background_r_conditioned],
  74. )
  75. ])

4 使用事件处理程序。

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

ROS 2 中的 Launch 是一个执行和管理用户定义流程的系统。 它负责监控它启动的进程的状态,以及报告和响应这些进程的状态变化。 这些更改称为事件,可以通过向启动系统注册事件处理程序来处理。 可以为特定事件注册事件处理程序,并可用于监视进程的状态。 此外,它们可用于定义一组复杂的规则,可用于动态修改启动文件。

本教程展示了 ROS 2 启动文件中事件处理程序的使用示例。

  1. from launch_ros.actions import Node
  2. from launch import LaunchDescription
  3. from launch.actions import (DeclareLaunchArgument, EmitEvent, ExecuteProcess,
  4. LogInfo, RegisterEventHandler, TimerAction)
  5. from launch.conditions import IfCondition
  6. from launch.event_handlers import (OnExecutionComplete, OnProcessExit,
  7. OnProcessIO, OnProcessStart, OnShutdown)
  8. from launch.events import Shutdown
  9. from launch.substitutions import (EnvironmentVariable, FindExecutable,
  10. LaunchConfiguration, LocalSubstitution,
  11. PythonExpression)
  12. def generate_launch_description():
  13. turtlesim_ns = LaunchConfiguration('turtlesim_ns')
  14. use_provided_red = LaunchConfiguration('use_provided_red')
  15. new_background_r = LaunchConfiguration('new_background_r')
  16. turtlesim_ns_launch_arg = DeclareLaunchArgument(
  17. 'turtlesim_ns',
  18. default_value='turtlesim1'
  19. )
  20. use_provided_red_launch_arg = DeclareLaunchArgument(
  21. 'use_provided_red',
  22. default_value='False'
  23. )
  24. new_background_r_launch_arg = DeclareLaunchArgument(
  25. 'new_background_r',
  26. default_value='200'
  27. )
  28. turtlesim_node = Node(
  29. package='turtlesim',
  30. namespace=turtlesim_ns,
  31. executable='turtlesim_node',
  32. name='sim'
  33. )
  34. spawn_turtle = ExecuteProcess(
  35. cmd=[[
  36. FindExecutable(name='ros2'),
  37. ' service call ',
  38. turtlesim_ns,
  39. '/spawn ',
  40. 'turtlesim/srv/Spawn ',
  41. '"{x: 2, y: 2, theta: 0.2}"'
  42. ]],
  43. shell=True
  44. )
  45. change_background_r = ExecuteProcess(
  46. cmd=[[
  47. FindExecutable(name='ros2'),
  48. ' param set ',
  49. turtlesim_ns,
  50. '/sim background_r ',
  51. '120'
  52. ]],
  53. shell=True
  54. )
  55. change_background_r_conditioned = ExecuteProcess(
  56. condition=IfCondition(
  57. PythonExpression([
  58. new_background_r,
  59. ' == 200',
  60. ' and ',
  61. use_provided_red
  62. ])
  63. ),
  64. cmd=[[
  65. FindExecutable(name='ros2'),
  66. ' param set ',
  67. turtlesim_ns,
  68. '/sim background_r ',
  69. new_background_r
  70. ]],
  71. shell=True
  72. )
  73. return LaunchDescription([
  74. turtlesim_ns_launch_arg,
  75. use_provided_red_launch_arg,
  76. new_background_r_launch_arg,
  77. turtlesim_node,
  78. RegisterEventHandler(
  79. OnProcessStart(
  80. target_action=turtlesim_node,
  81. on_start=[
  82. LogInfo(msg='Turtlesim started, spawning turtle'),
  83. spawn_turtle
  84. ]
  85. )
  86. ),
  87. RegisterEventHandler(
  88. OnProcessIO(
  89. target_action=spawn_turtle,
  90. on_stdout=lambda event: LogInfo(
  91. msg='Spawn request says "{}"'.format(
  92. event.text.decode().strip())
  93. )
  94. )
  95. ),
  96. RegisterEventHandler(
  97. OnExecutionComplete(
  98. target_action=spawn_turtle,
  99. on_completion=[
  100. LogInfo(msg='Spawn finished'),
  101. change_background_r,
  102. TimerAction(
  103. period=2.0,
  104. actions=[change_background_r_conditioned],
  105. )
  106. ]
  107. )
  108. ),
  109. RegisterEventHandler(
  110. OnProcessExit(
  111. target_action=turtlesim_node,
  112. on_exit=[
  113. LogInfo(msg=(EnvironmentVariable(name='USER'),
  114. ' closed the turtlesim window')),
  115. EmitEvent(event=Shutdown(
  116. reason='Window closed'))
  117. ]
  118. )
  119. ),
  120. RegisterEventHandler(
  121. OnShutdown(
  122. on_shutdown=[LogInfo(
  123. msg=['Launch was asked to shutdown: ',
  124. LocalSubstitution('event.reason')]
  125. )]
  126. )
  127. ),
  128. ])

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 更加灵活:

  1. Python 是一种脚本语言,因此可以在启动文件中利用该语言及其库。
  2. ros2/launch(一般启动功能)和 ros2/launch_ros(ROS 2 特定启动功能)是用 Python 编写的,因此对 XML 和 YAML 可能未公开的启动功能具有较低级别的访问权限。

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


同一功能对比如下:

Python

  1. # example.launch.py
  2. import os
  3. from ament_index_python import get_package_share_directory
  4. from launch import LaunchDescription
  5. from launch.actions import DeclareLaunchArgument
  6. from launch.actions import IncludeLaunchDescription
  7. from launch.actions import GroupAction
  8. from launch.launch_description_sources import PythonLaunchDescriptionSource
  9. from launch.substitutions import LaunchConfiguration
  10. from launch.substitutions import TextSubstitution
  11. from launch_ros.actions import Node
  12. from launch_ros.actions import PushRosNamespace
  13. def generate_launch_description():
  14. # args that can be set from the command line or a default will be used
  15. background_r_launch_arg = DeclareLaunchArgument(
  16. "background_r", default_value=TextSubstitution(text="0")
  17. )
  18. background_g_launch_arg = DeclareLaunchArgument(
  19. "background_g", default_value=TextSubstitution(text="255")
  20. )
  21. background_b_launch_arg = DeclareLaunchArgument(
  22. "background_b", default_value=TextSubstitution(text="0")
  23. )
  24. chatter_ns_launch_arg = DeclareLaunchArgument(
  25. "chatter_ns", default_value=TextSubstitution(text="my/chatter/ns")
  26. )
  27. # include another launch file
  28. launch_include = IncludeLaunchDescription(
  29. PythonLaunchDescriptionSource(
  30. os.path.join(
  31. get_package_share_directory('demo_nodes_cpp'),
  32. 'launch/topics/talker_listener.launch.py'))
  33. )
  34. # include another launch file in the chatter_ns namespace
  35. launch_include_with_namespace = GroupAction(
  36. actions=[
  37. # push_ros_namespace to set namespace of included nodes
  38. PushRosNamespace(LaunchConfiguration('chatter_ns')),
  39. IncludeLaunchDescription(
  40. PythonLaunchDescriptionSource(
  41. os.path.join(
  42. get_package_share_directory('demo_nodes_cpp'),
  43. 'launch/topics/talker_listener.launch.py'))
  44. ),
  45. ]
  46. )
  47. # start a turtlesim_node in the turtlesim1 namespace
  48. turtlesim_node = Node(
  49. package='turtlesim',
  50. namespace='turtlesim1',
  51. executable='turtlesim_node',
  52. name='sim'
  53. )
  54. # start another turtlesim_node in the turtlesim2 namespace
  55. # and use args to set parameters
  56. turtlesim_node_with_parameters = Node(
  57. package='turtlesim',
  58. namespace='turtlesim2',
  59. executable='turtlesim_node',
  60. name='sim',
  61. parameters=[{
  62. "background_r": LaunchConfiguration('background_r'),
  63. "background_g": LaunchConfiguration('background_g'),
  64. "background_b": LaunchConfiguration('background_b'),
  65. }]
  66. )
  67. # perform remap so both turtles listen to the same command topic
  68. forward_turtlesim_commands_to_second_turtlesim_node = Node(
  69. package='turtlesim',
  70. executable='mimic',
  71. name='mimic',
  72. remappings=[
  73. ('/input/pose', '/turtlesim1/turtle1/pose'),
  74. ('/output/cmd_vel', '/turtlesim2/turtle1/cmd_vel'),
  75. ]
  76. )
  77. return LaunchDescription([
  78. background_r_launch_arg,
  79. background_g_launch_arg,
  80. background_b_launch_arg,
  81. chatter_ns_launch_arg,
  82. launch_include,
  83. launch_include_with_namespace,
  84. turtlesim_node,
  85. turtlesim_node_with_parameters,
  86. forward_turtlesim_commands_to_second_turtlesim_node,
  87. ])

xml

  1. <!-- example.launch.xml -->
  2. <launch>
  3. <!-- args that can be set from the command line or a default will be used -->
  4. <arg name="background_r" default="0"/>
  5. <arg name="background_g" default="255"/>
  6. <arg name="background_b" default="0"/>
  7. <arg name="chatter_ns" default="my/chatter/ns"/>
  8. <!-- include another launch file -->
  9. <include file="$(find-pkg-share demo_nodes_cpp)/launch/topics/talker_listener.launch.py"/>
  10. <!-- include another launch file in the chatter_ns namespace-->
  11. <group>
  12. <!-- push_ros_namespace to set namespace of included nodes -->
  13. <push_ros_namespace namespace="$(var chatter_ns)"/>
  14. <include file="$(find-pkg-share demo_nodes_cpp)/launch/topics/talker_listener.launch.py"/>
  15. </group>
  16. <!-- start a turtlesim_node in the turtlesim1 namespace -->
  17. <node pkg="turtlesim" exec="turtlesim_node" name="sim" namespace="turtlesim1"/>
  18. <!-- start another turtlesim_node in the turtlesim2 namespace
  19. and use args to set parameters -->
  20. <node pkg="turtlesim" exec="turtlesim_node" name="sim" namespace="turtlesim2">
  21. <param name="background_r" value="$(var background_r)"/>
  22. <param name="background_g" value="$(var background_g)"/>
  23. <param name="background_b" value="$(var background_b)"/>
  24. </node>
  25. <!-- perform remap so both turtles listen to the same command topic -->
  26. <node pkg="turtlesim" exec="mimic" name="mimic">
  27. <remap from="/input/pose" to="/turtlesim1/turtle1/pose"/>
  28. <remap from="/output/cmd_vel" to="/turtlesim2/turtle1/cmd_vel"/>
  29. </node>
  30. </launch>

yaml

  1. # example.launch.yaml
  2. launch:
  3. # args that can be set from the command line or a default will be used
  4. - arg:
  5. name: "background_r"
  6. default: "0"
  7. - arg:
  8. name: "background_g"
  9. default: "255"
  10. - arg:
  11. name: "background_b"
  12. default: "0"
  13. - arg:
  14. name: "chatter_ns"
  15. default: "my/chatter/ns"
  16. # include another launch file
  17. - include:
  18. file: "$(find-pkg-share demo_nodes_cpp)/launch/topics/talker_listener.launch.py"
  19. # include another launch file in the chatter_ns namespace
  20. - group:
  21. - push_ros_namespace:
  22. namespace: "$(var chatter_ns)"
  23. - include:
  24. file: "$(find-pkg-share demo_nodes_cpp)/launch/topics/talker_listener.launch.py"
  25. # start a turtlesim_node in the turtlesim1 namespace
  26. - node:
  27. pkg: "turtlesim"
  28. exec: "turtlesim_node"
  29. name: "sim"
  30. namespace: "turtlesim1"
  31. # start another turtlesim_node in the turtlesim2 namespace and use args to set parameters
  32. - node:
  33. pkg: "turtlesim"
  34. exec: "turtlesim_node"
  35. name: "sim"
  36. namespace: "turtlesim2"
  37. param:
  38. -
  39. name: "background_r"
  40. value: "$(var background_r)"
  41. -
  42. name: "background_g"
  43. value: "$(var background_g)"
  44. -
  45. name: "background_b"
  46. value: "$(var background_b)"
  47. # perform remap so both turtles listen to the same command topic
  48. - node:
  49. pkg: "turtlesim"
  50. exec: "mimic"
  51. name: "mimic"
  52. remap:
  53. -
  54. from: "/input/pose"
  55. to: "/turtlesim1/turtle1/pose"
  56. -
  57. from: "/output/cmd_vel"
  58. to: "/turtlesim2/turtle1/cmd_vel"

 


声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号