• ROS2学习笔记:Launch脚本


    Launch可以实现同时启动多节点,这一不需要在终端一个一个窗口进行ros2 run

    运行launch文件:

    ros2 launch (功能包)(launch文件)

    1 编写一个launch文件:

    from launch import LaunchDescription
    from launch_ros.actions import Node
    
    def generate_launch_description():
    	return LaunchDescription([
    		Node(
    			package = 'learning_topic',
    			executable = 'topic_helloworld_pub',
    		),
    		Node(
    			package = 'learning_topic',
    			executable = 'topic_helloworld_sub',
    		),
    	])
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    1 from launch import LaunchDescription
    from launch_ros.actions import Node
    引入launch相关库,LaunchDescription描述了需要运行的节点

    2 Node(
    package = ‘learning_topic’,
    executable = ‘topic_helloworld_pub’,
    ),
    在LaunchDescription里声明要调用的节点,这里的调用内容可见(https://blog.csdn.net/Raine_Yang/article/details/125349724?spm=1001.2014.3001.5501)

    3 def generate_launch_description():
    generate_launch_description为自动生成Launch文件的函数

    2 launch文件作为软件启动配置文件
    (以rviz2为例)

    ros2 run rviz2 rviz2 -d (launch文件完整路径)

    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():
    	rviz_config = os.path.join(
    		get_package_share_directory('learning_launch'),
    		'rviz',
    		'turtle_rviz.rviz'
    	)
    
    	return LaunchDescription([
    		Node(
    			package = 'rviz2',
    			executable = 'rviz2',
    			name = 'rviz2',
    			arguments = ['-d', rviz_config]
    		)
    	]) 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    1 rviz_config = os.path.join(
    get_package_share_directory(‘learning_launch’),
    ‘rviz’,
    ‘turtle_rviz.rviz’
    )
    在这里标明配置文件路径,类似于使用-d后面的文件完整路径

    2 name = ‘rviz2’,
    对节点重命名为rviz2。在launch文件里可以覆盖节点在源码里的名称,进行重命名

    3 launch文件对节点和话题的重命名

    该程序会打开两个turtlesim程序

    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'),
    			]
    		)
    	])
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    1 命名空间
    namespace = ‘turtlesim1’,
    namespace = ‘turtlesim2’,

    ROS2里不允许同名节点,因此直接打开两个turtlesim会报错。可以在launch文件里加入namespace进行区分,如下图
    在这里插入图片描述

    2 话题重定向
    remappings = [
    (‘/input/pose’, ‘/turtlesim1/turtle1/pose’),
    (‘/output/cmd_vel’, ‘/turtlesim2/turtle1/cmd_vel’),
    ]
    用remappings可以对话题发布者和接受者进行重定向。这里把输入话题名/input/pose改为/turtlesim1/turtle1/pose,把输出话题’/output/cmd_vel改为/turtlesim2/turtle1/cmd_vel

    这样turtlesim1的pose会被mimic节点订阅,再由mimic发布到turtlesim2.turtlesim2会执行和turtlesim1一样的动作
    在这里插入图片描述

    4 在launch文件里配置参数

    from launch import LaunchDescription
    from launch.actions import DeclareLaunchArgument
    from launch.substitutions import LaunchConfiguration, TextSubstitution
    
    from launch_ros.actions import Node
    
    def generate_launch_description():
    	background_r_launch_arg = DeclareLaunchArgument(
    		'background_r', default_value = TextSubstitution(text = "0")
    	)
    	background_g_launch_arg = DeclareLaunchArgument(
    		'background_g', default_value = TextSubstitution(text = "84")
    	)
    	background_b_launch_arg = DeclareLaunchArgument(
    		'background_b', default_value = TextSubstitution(text = "122")
    	)
    
    	return LaunchDescription([
    		background_r_launch_arg,
    		background_g_launch_arg,
    		background_b_launch_arg,
    		Node(
    			package = 'turtlesim',
    			executable = 'turtlesim_node',
    			name = 'sim',
    			parameters = [{
    				'background_r': LaunchConfiguration('background_r'),
    				'background_g': LaunchConfiguration('background_g'),
    				'background_b': LaunchConfiguration('background_b'),
    			}]
    		),
    	])
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    1 def generate_launch_description():
    background_r_launch_arg = DeclareLaunchArgument(
    ‘background_r’, default_value = TextSubstitution(text = “0”)
    )
    background_g_launch_arg = DeclareLaunchArgument(
    ‘background_g’, default_value = TextSubstitution(text = “84”)
    )
    background_b_launch_arg = DeclareLaunchArgument(
    ‘background_b’, default_value = TextSubstitution(text = “122”)
    )
    创建launch文件内参数修改R G B数值

    2 parameters = [{
    ‘background_r’: LaunchConfiguration(‘background_r’),
    ‘background_g’: LaunchConfiguration(‘background_g’),
    ‘background_b’: LaunchConfiguration(‘background_b’),
    }]
    在返回值里parameters修改参数

    对参数yaml文件修改可以简化以上代码

    import os
    
    from ament_index_python.packages import get_package_share_directory  # 查询功能包路径的方法
    
    from launch import LaunchDescription   # launch文件的描述类
    from launch_ros.actions import Node    # 节点启动的描述类
    
    
    def generate_launch_description():     # 自动生成launch文件的函数
       config = os.path.join(              # 找到参数文件的完整路径
          get_package_share_directory('learning_launch'),
          'config',
          'turtlesim.yaml'
          )
    
       return LaunchDescription([          # 返回launch文件的描述信息
          Node(                            # 配置一个节点的启动
             package='turtlesim',          # 节点所在的功能包
             executable='turtlesim_node',  # 节点的可执行文件名
             namespace='turtlesim2',       # 节点所在的命名空间
             name='sim',                   # 对节点重新命名
             parameters=[config]           # 加载参数文件
          )
       ])
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    1 config = os.path.join(
    get_package_share_directory(‘learning_launch’),
    ‘config’,
    ‘turtlesim.yaml’
    )
    找到参数yaml文件的路径,我这里在learning_launch功能包,config文件夹,turtlesim.yaml文件

    2 parameters=[config]
    在返回值里加入parameters来加载参数文件

    turtlesim.yaml参数文件:

    /turtlesim2/sim:
       ros__parameters:
          background_b: 0
          background_g: 0
          background_r: 0
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    注意这里命名空间turtlesim2,节点名称sim都要和launch文件里保持一致,否则无法运行

    5 在launch文件里包含其他launch文件

    在一些大型系统可能会有多个launch文件,可以把多个launch文件嵌套在一个launch文件会更方便

    import os
    
    from ament_index_python.packages import get_package_share_directory  # 查询功能包路径的方法
    
    from launch import LaunchDescription                 # launch文件的描述类
    from launch.actions import IncludeLaunchDescription  # 节点启动的描述类
    from launch.launch_description_sources import PythonLaunchDescriptionSource
    from launch.actions import GroupAction               # launch文件中的执行动作
    from launch_ros.actions import PushRosNamespace      # ROS命名空间配置
    
    def generate_launch_description():                   # 自动生成launch文件的函数
       parameter_yaml = IncludeLaunchDescription(        # 包含指定路径下的另外一个launch文件
          PythonLaunchDescriptionSource([os.path.join(
             get_package_share_directory('learning_launch'), 'launch'),
             '/parameters_nonamespace.launch.py'])
          )
      
       parameter_yaml_with_namespace = GroupAction(      # 对指定launch文件中启动的功能加上命名空间
          actions=[
             PushRosNamespace('turtlesim2'),
             parameter_yaml]
          )
    
       return LaunchDescription([                        # 返回launch文件的描述信息
          parameter_yaml_with_namespace
       ])
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    1 parameter_yaml = IncludeLaunchDescription( # 包含指定路径下的另外一个launch文件
    PythonLaunchDescriptionSource([os.path.join(
    get_package_share_directory(‘learning_launch’), ‘launch’),
    ‘/parameters_nonamespace.launch.py’])
    )
    获取另一个launch文件的完整地址。文件在learning_launch功能包,launch文件夹下parameters_nonamespace.launch.py文件

    2 actions=[
    PushRosNamespace(‘turtlesim2’),
    parameter_yaml]
    对加载的launch文件重命名功能空间turtlesim2。这样可以防止原launch文件命名出现冲突

    在setup里面对launch文件进行声明

    from setuptools import setup
    import os
    from glob import glob
    
    package_name = 'learning_launch'
    
    setup(
        name=package_name,
        version='0.0.0',
        packages=[package_name],
        data_files=[
            ('share/ament_index/resource_index/packages',
                ['resource/' + package_name]),
            ('share/' + package_name, ['package.xml']),
            (os.path.join('share', package_name, 'launch'), glob(os.path.join('launch', '*.launch.py'))),
            (os.path.join('share', package_name, 'config'), glob(os.path.join('config', '*.*'))),
            (os.path.join('share', package_name, 'rviz'), glob(os.path.join('rviz', '*.*'))),
        ],
        install_requires=['setuptools'],
        zip_safe=True,
        maintainer='hcx',
        maintainer_email='huchunxu@guyuehome.com',
        description='TODO: Package description',
        license='TODO: License declaration',
        tests_require=['pytest'],
        entry_points={
            'console_scripts': [
            ],
        },
    )
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    1 data_files=[
    (‘share/ament_index/resource_index/packages’,
    [‘resource/’ + package_name]),
    (‘share/’ + package_name, [‘package.xml’]),
    (os.path.join(‘share’, package_name, ‘launch’), glob(os.path.join(‘launch’, ‘.launch.py’))),
    (os.path.join(‘share’, package_name, ‘config’), glob(os.path.join(‘config’, '
    .'))),
    (os.path.join(‘share’, package_name, ‘rviz’), glob(os.path.join(‘rviz’, '
    .*’))),
    ],

    这一步把所有launch文件夹下,config文件夹下,和rviz文件夹下的文件进行声明( * 代表所有文件),这样编译器会把这些文件复制到install文件夹下,可以后续运行

  • 相关阅读:
    使用libmodbus库开发modbusTcp从站(支持多个主站连接)
    「小白学Python」Windows安装Python
    《Boosting Object Detection with Zero-Shot Day-Night Domain Adaptation》2024CVPR
    MacOS怎么安装Nacos(附带:Windows系统)
    I/O模型之非阻塞IO
    Qt下使用OpenCV的鼠标回调函数进行圆形/矩形/多边形的绘制
    计算机毕业设计ssm基于web的暗香小店系统的设计与实现80041系统+程序+源码+lw+远程部署
    JAVA毕业设计好物网站计算机源码+lw文档+系统+调试部署+数据库
    #力扣:14. 最长公共前缀@FDDLC
    springboot整合ES
  • 原文地址:https://blog.csdn.net/Raine_Yang/article/details/125885266