• ROS2的launch有何不同?


    一、提要

            在launch多节点执行方面,ROS2与ROS1有很大不同。首先,ros2与ros1不同之处,在于ROS2不再有*.launch脚本文件,取而代之的是 3 种格式得以实现: ​

    1. python 脚本
    2. xml 文件
    3. yaml 文件

    二、启动launch文件

    2.1 xml文件yaml文件启动方式

    ros2 launch <package_name> <launch_file_name>

    2.2 对于py文件,也可以直接启动 launch 文件,

    像这样: ​

    ros2 launch turtlesim_mimic_launch.py

    三、launch文件的内容

    3.1 launch 文件内容描述

    因为launch file 文件毕竟是多节点执行脚本,因此,与“ ros2 run ” 指令的内容大致相同,如包名、节点名。当然,要丰富一些。如:

    1. "turtlesim" exec="turtlesim_node" name="sim" namespace="turtlesim2">
    2.     "background_r" value="$(var background_r)"/>
    3.     "background_g" value="$(var background_g)"/>
    4.     "background_b" value="$(var background_b)"/>
    5.   

    3.2 关于include

         include 可以在一个 launch file 中包含另外的 launch file ​

    3.3 关于group

    group 可以把多个 node 组合在一起 ​

    四、实践编写一个 launch file

    4.1 必要的套路

    无论是 python、xml 还是 yaml,编写 launch file 的步骤差不多一样。 ​

    1. 设置命令行参数的默认值,
    2. 设置 launch file 的包含关系,通过 标签
    3. 设置 Node 信息,包括 name、namespace、parameter
    4. 如果需要设置 remmaping 则设置 remapping 关系

    ​4.2 举个例子

    以下是官方文档 一个例子,是针对海龟turtlesim的例子:

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

    以上代码很清晰,就是启动两个海龟节点,一个mimic节点;上述有些需要解释的概念有:命名空间啥作用?重映射有什么要点?(需要执行后,用指令行进行分析)

    4.3  remap 起什么作用

    remap 是一个非常有用的技巧,一般用来做 Topic 的映射的。某节点本来不认识这个Topic,但通过重起名,或叫伪名,或叫重新伪装(注意,这里订阅者只收某种名称的Topic),使某些接收到该Topic。

    from="/different_topic" to="/needed_topic"/>

    把 from 中的 topic,转换成 to 指定的 topic ​

    有 2 种用途:

    1. 把一个 node 原本来发布的 topic,映射为另外一个名字
    2. 把其他的 node 发布的原始 topic,映射为所需要的 topic

     4.4 带着参数执行 launch

    我们注意到上面的 launch file 中有 args,比如 background_r,命令行启动时可以将数据透传过去,通过 key:=value 形式。 如:

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

    五、参考:三种写法

    以下代码用于参考,是同样内容的三种文件实现方法,因为比较长,希望大家慢慢对照阅读。

    5.1 基于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. ])

    这是用 python 写的,最后返回的是 LaunchDescription 信息,这个等同于 xml 中 标签中的内容

    5.2 基于xml的写法

    1. <launch>
    2. <arg name="background_r" default="0"/>
    3. <arg name="background_g" default="255"/>
    4. <arg name="background_b" default="0"/>
    5. <arg name="chatter_ns" default="my/chatter/ns"/>
    6. <include file="$(find-pkg-share demo_nodes_cpp)/launch/topics/talker_listener.launch.py"/>
    7. <group>
    8. <push-ros-namespace namespace="$(var chatter_ns)"/>
    9. <include file="$(find-pkg-share demo_nodes_cpp)/launch/topics/talker_listener.launch.py"/>
    10. group>
    11. <node pkg="turtlesim" exec="turtlesim_node" name="sim" namespace="turtlesim1"/>
    12. <node pkg="turtlesim" exec="turtlesim_node" name="sim" namespace="turtlesim2">
    13. <param name="background_r" value="$(var background_r)"/>
    14. <param name="background_g" value="$(var background_g)"/>
    15. <param name="background_b" value="$(var background_b)"/>
    16. node>
    17. <node pkg="turtlesim" exec="mimic" name="mimic">
    18. <remap from="/input/pose" to="/turtlesim1/turtle1/pose"/>
    19. <remap from="/output/cmd_vel" to="/turtlesim2/turtle1/cmd_vel"/>
    20. node>
    21. launch>

    5.3 基于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"

    参考文章:

    Using Python, XML, and YAML for ROS 2 Launch Files — ROS 2 Documentation: Foxy documentation

    ROS2 中的 launch 文件入门的 6 个疑问 - 知乎 (zhihu.com)

  • 相关阅读:
    Nexus私服(三)
    uni-app:实现时钟自走(动态时钟效果)
    JDBC:获取数据库连接(一)
    Nginx安装
    Java反编译工具 JD-GUI安装使用
    SpringBoot集成Lettuce客户端操作Redis
    使用Docker发布部署C# .NET core WebApi到服务器
    STM32CubeMX学习笔记-RTC实时时钟使用
    Springboot集成RabbitMQ【消费者接收消息的确认】
    【乱码】记一次C#调用Java乱码
  • 原文地址:https://blog.csdn.net/gongdiwudu/article/details/125984181