第 6 节

Launch

概述

rosbag2的作用是来序列化储存数据的,是一个数据库。


ros2 launch 功能包名 launch文件名

ros2 pkg create cpp01_launch --build-type ament_cmake --dependencies rclcpp

ros2 pkg create cpp01_launch --build-type ament_cmake --dependencies rclcpp

from launch import LaunchDescription
from launch_ros.actions import Node

封装终端指令相关类
from launch.actions import ExecuteProcess
from launch.substitutions import FindExecutable
参数声明与获取
from launch.actions import DeclareLaunchArgument
from launch.substitutions import LaunchConfiguration
文件包含相关
from launch.actions import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
分组相关
from launch_ros.actions import PushRosNamespace
from launch.actions import GroupAction
事件相关
from launch.event_handlers import OnProcessStart,OnProcessExit
from launch.actions import ExecuteProcess,RegisterEventHandler,LogInfo
获取功能包下share目录或路径
from ament_index_python.packages import get_package_share_directory

def generate_launch_description():
    return LaunchDescription([])

launch基本使用流程(C++)


配置完这个,不管我launch目录下有多少launch文件,只需要配置这一次就行了。

这样说明我们cmake配置对了

from launch import LaunchDescription
from launch_ros.actions import Node
封装终端指令相关类
from launch.actions import ExecuteProcess
from launch.substitutions import FindExecutable
参数声明与获取
from launch.actions import DeclareLaunchArgument
from launch.substitutions import LaunchConfiguration
文件包含相关
from launch.actions import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
分组相关
from launch_ros.actions import PushRosNamespace
from launch.actions import GroupAction
事件相关
from launch.event_handlers import OnProcessStart,OnProcessExit
from launch.actions import ExecuteProcess,RegisterEventHandler,LogInfo
获取功能包下share目录或路径
from ament_index_python.packages import get_package_share_directory

def generate_launch_description():
    return LaunchDescription([])

<launch>
    <node pkg = "turtlesim" exec = "turtlesim_node" name = "t1" />
    <node pkg = "turtlesim" exec = "turtlesim_node" name = "t2" />
</launch>

launch:
node:
  pkg: "turtlesim"
  exec: "turtlesim_node"
  name: "t1"
node:
  pkg: "turtlesim"
  exec: "turtlesim_node"
  name: "t2"

最好添加一个依赖

Launch_Python_Node

这个是标签exec_name

这俩参数传参的区别在于--ros-args的区别

在launch里写更简单

这样是等价的

{}里是yaml格式的。

有另一种更常用的方法,就是上来读取yaml文件,把数据都存在yaml里,用到的时候直接读取。

把yaml文件放到config里

ros2 param dump haha --output-dir src/cpp01_launch/config/

还需要再配置cmakelists

我们要读就读install目录下的。

直接复制路径

可以进一步优化代码

这个就是来获取某个功能包的share目录路径

from launch import LaunchDescription
from launch_ros.actions import Node

封装终端指令相关类
from launch.actions import ExecuteProcess
from launch.substitutions import FindExecutable
参数声明与获取
from launch.actions import DeclareLaunchArgument
from launch.substitutions import LaunchConfiguration
文件包含相关
from launch.actions import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
分组相关
from launch_ros.actions import PushRosNamespace
from launch.actions import GroupAction
事件相关
from launch.event_handlers import OnProcessStart,OnProcessExit
from launch.actions import ExecuteProcess,RegisterEventHandler,LogInfo
获取功能包下share目录或路径
from ament_index_python.packages import get_package_share_directory

import os

def generate_launch_description():

    # turtle1 = Node(

    #     package="turtlesim",

    #     executable="turtlesim_node",

    #     exec_name="my_label",

    #     ros_arguments=["--remap","__ns:=/t2"]

    #     )
    turtle2 = Node(
        package="turtlesim",
        executable="turtlesim_node",
        name="haha",
        parameters=[os.path.join(get_package_share_directory("cpp01_launch"),"config","haha.yaml")]
        )
    return LaunchDescription([turtle2])

建议采用第三种 动态获取路径

respawn是自动重启的意思,这样运行后的节点,你用鼠标关闭小乌龟窗口后,也会自动重启节点,再把小乌龟窗口打开一个新的。

按Ctrl+C可以终止。

from launch import LaunchDescription
from launch_ros.actions import Node

封装终端指令相关类
from launch.actions import ExecuteProcess
from launch.substitutions import FindExecutable
参数声明与获取
from launch.actions import DeclareLaunchArgument
from launch.substitutions import LaunchConfiguration
文件包含相关
from launch.actions import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
分组相关
from launch_ros.actions import PushRosNamespace
from launch.actions import GroupAction
事件相关
from launch.event_handlers import OnProcessStart,OnProcessExit
from launch.actions import ExecuteProcess,RegisterEventHandler,LogInfo
获取功能包下share目录或路径
from ament_index_python.packages import get_package_share_directory

import os

def generate_launch_description():

    # turtle1 = Node(

    #     package="turtlesim",

    #     executable="turtlesim_node",

    #     exec_name="my_label",

    #     ros_arguments=["--remap","__ns:=/t2"]

    #     )
    turtle2 = Node(
        package="turtlesim",
        executable="turtlesim_node",
        name="haha",

        # parameters=[{"background_r": 255,"background_g": 0,"background_b": 0}],

        # parameters=["/home/tungchiahui/mysource/ros2src/4.ws02_tools/install/cpp01_launch/share/cpp01_launch/config/haha.yaml"],
        parameters=[os.path.join(get_package_share_directory("cpp01_launch"),"config","haha.yaml")],
        respawn=True
        )
    return LaunchDescription([turtle2])

第一个是原话题名称,第二个是新话题名称

Launch_Python_执行命令

这是个列表,列表里面写我们的指令

这样是把日志既输出到终端也输出到日志,如果不写则只会输出到日志。

这样就是把命令当成终端指令来执行

from launch import LaunchDescription
from launch_ros.actions import Node

封装终端指令相关类
from launch.actions import ExecuteProcess
from launch.substitutions import FindExecutable
参数声明与获取
from launch.actions import DeclareLaunchArgument
from launch.substitutions import LaunchConfiguration
文件包含相关
from launch.actions import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
分组相关
from launch_ros.actions import PushRosNamespace
from launch.actions import GroupAction
事件相关
from launch.event_handlers import OnProcessStart,OnProcessExit
from launch.actions import ExecuteProcess,RegisterEventHandler,LogInfo
获取功能包下share目录或路径
from ament_index_python.packages import get_package_share_directory

def generate_launch_description():
    turtle = Node(
        package="turtlesim",
        executable="turtlesim_node"
    )
    cmd = ExecuteProcess(
        cmd = ["ros2 topic echo /turtle1/pose"],
        output = "both",
        shell = True
    )

    return LaunchDescription([turtle,cmd])

如果指令过长,可以分到多个字符串里运行。


这样也是可以运行的。

from launch import LaunchDescription
from launch_ros.actions import Node

封装终端指令相关类
from launch.actions import ExecuteProcess
from launch.substitutions import FindExecutable
参数声明与获取
from launch.actions import DeclareLaunchArgument
from launch.substitutions import LaunchConfiguration
文件包含相关
from launch.actions import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
分组相关
from launch_ros.actions import PushRosNamespace
from launch.actions import GroupAction
事件相关
from launch.event_handlers import OnProcessStart,OnProcessExit
from launch.actions import ExecuteProcess,RegisterEventHandler,LogInfo
获取功能包下share目录或路径
from ament_index_python.packages import get_package_share_directory

def generate_launch_description():
    turtle = Node(
        package="turtlesim",
        executable="turtlesim_node"
    )
    cmd = ExecuteProcess(
        cmd = [FindExecutable(name="ros2"),"topic","echo","/turtle1/pose"],
        output = "both",
        shell = True
    )

    return LaunchDescription([turtle,cmd])

Launch_Python_参数设置

没传值的话,乌龟红色是满的,那就是粉红色背景

也可以传值,比如传backg_r:=0

这样背景色就变的更偏蓝绿了。

from launch import LaunchDescription
from launch_ros.actions import Node

封装终端指令相关类
from launch.actions import ExecuteProcess
from launch.substitutions import FindExecutable
参数声明与获取
from launch.actions import DeclareLaunchArgument
from launch.substitutions import LaunchConfiguration
文件包含相关
from launch.actions import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
分组相关
from launch_ros.actions import PushRosNamespace
from launch.actions import GroupAction
事件相关
from launch.event_handlers import OnProcessStart,OnProcessExit
from launch.actions import ExecuteProcess,RegisterEventHandler,LogInfo
获取功能包下share目录或路径
from ament_index_python.packages import get_package_share_directory

def generate_launch_description():

    bg_r = DeclareLaunchArgument(name="backg_r",default_value="255")
    bg_g = DeclareLaunchArgument(name="backg_g",default_value="255")
    bg_b = DeclareLaunchArgument(name="backg_b",default_value="255")
    turtle = Node(
        package="turtlesim",
        executable="turtlesim_node",
        parameters=[{"background_r" : LaunchConfiguration("backg_r"),"background_g" : LaunchConfiguration("backg_g"),"background_b" : LaunchConfiguration("backg_b")}]
    )
    return LaunchDescription([bg_r,bg_g,bg_b,turtle])

Launch_Python_文件包含

假设我要编写一个机器人启动相关的launch文件,在这个launch文件中,我可能要启动雷达,启动IMU,启动底盘等等,我们需要把这些launch文件都包含进机器人启动的launch文件中。

这个值是由被包含的launch文件封装而来的对象。

这个对象对应的类就是PythonLaunchDescriptionSource,

类里面还得设置一个参数。

这个参数是launch_file_path就是文件路径。

建议用这个来获取路径。

也可以为其传参

from launch import LaunchDescription
from launch_ros.actions import Node

封装终端指令相关类
from launch.actions import ExecuteProcess
from launch.substitutions import FindExecutable
参数声明与获取
from launch.actions import DeclareLaunchArgument
from launch.substitutions import LaunchConfiguration
文件包含相关
from launch.actions import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
分组相关
from launch_ros.actions import PushRosNamespace
from launch.actions import GroupAction
事件相关
from launch.event_handlers import OnProcessStart,OnProcessExit
from launch.actions import ExecuteProcess,RegisterEventHandler,LogInfo
获取功能包下share目录或路径
from ament_index_python.packages import get_package_share_directory

import os

def generate_launch_description():
    include = IncludeLaunchDescription(
        launch_description_source=PythonLaunchDescriptionSource(
            launch_file_path=os.path.join(
                get_package_share_directory("cpp01_launch"),
                "launch/py",
                "py04_args_launch.py"
            )
        ),
        launch_arguments=[("backg_r","80"),("backg_g","10"),("backg_b","200")]
    )
    return LaunchDescription([include])

Launch_Python_分组设置

from launch import LaunchDescription
from launch_ros.actions import Node

封装终端指令相关类
from launch.actions import ExecuteProcess
from launch.substitutions import FindExecutable
参数声明与获取
from launch.actions import DeclareLaunchArgument
from launch.substitutions import LaunchConfiguration
文件包含相关
from launch.actions import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
分组相关
from launch_ros.actions import PushRosNamespace
from launch.actions import GroupAction
事件相关
from launch.event_handlers import OnProcessStart,OnProcessExit
from launch.actions import ExecuteProcess,RegisterEventHandler,LogInfo
获取功能包下share目录或路径
from ament_index_python.packages import get_package_share_directory

def generate_launch_description():
    turtle1 = Node(
    package="turtlesim",
    executable="turtlesim_node",
    name="t1"
    )
    turtle2 = Node(
    package="turtlesim",
    executable="turtlesim_node",
    name="t2"
    )
    turtle3 = Node(
    package="turtlesim",
    executable="turtlesim_node",
    name="t3"
    )

    group1 = GroupAction(actions=[PushRosNamespace("g1"),turtle1,turtle2])
    group2 = GroupAction(actions=[PushRosNamespace("g2"),turtle3])

    return LaunchDescription([group1,group2])

Launch_Python_事件设置

第一个主要用于注册事件,第二个是开始事件,第三个是节点退出。


这个是在终端中生成新小乌龟的命令

第一个参数是针对哪个事件进行注册。

target_action是事件源,你要为哪个节点注册事件。

on_start是等到事件被触发,你要做哪些操作?

from launch import LaunchDescription
from launch_ros.actions import Node

封装终端指令相关类
from launch.actions import ExecuteProcess
from launch.substitutions import FindExecutable
参数声明与获取
from launch.actions import DeclareLaunchArgument
from launch.substitutions import LaunchConfiguration
文件包含相关
from launch.actions import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
分组相关
from launch_ros.actions import PushRosNamespace
from launch.actions import GroupAction
事件相关
from launch.event_handlers import OnProcessStart,OnProcessExit
from launch.actions import ExecuteProcess,RegisterEventHandler,LogInfo
获取功能包下share目录或路径
from ament_index_python.packages import get_package_share_directory

def generate_launch_description():
    turtle = Node(
    package="turtlesim",
    executable="turtlesim_node",
    )
    spawn = ExecuteProcess(
        cmd=["ros2 service call /spawn turtlesim/srv/Spawn \"{'x': 8.0,'y': 3.0}\""],
        output="both",
        shell=True
    )

    event_start = RegisterEventHandler(
        event_handler=OnProcessStart(
            target_action=turtle,
            on_start=spawn
        )
    )

    event_exit = RegisterEventHandler(
        event_handler=OnProcessExit(
            target_action=turtle,
            on_exit=[LogInfo(msg="turtlesim_node:退出!")]
        )
    )
    return LaunchDescription([turtle,event_start,event_exit])

on_exit可以创建一个对象,也可以放在列表里。

可以只学Python版本的Launch,XML和Yaml版本的Launch可以了解就行,自己写就写Python版本的,当你要用到别人开源的功能包用的Launch是Xml或者yaml版本一般不影响正常使用。

Launch_XML_YAML_Node

Launch_XML_YAML_执行命令

Launch_XML_YAML_参数设置

Launch_XML_YAML_分组设置

Launch_XML_YAML_文件包含