ROS学习笔记(四)- ROS的launch文件

书接上回,上次已经介绍到launch文件的一些内容了,这次详细记录学习一下。

在ROS中,launch文件是一种XML文件,用于描述ROS系统中的节点、话题、参数等信息,可以用来自动化启动多个节点和启动参数服务器。在实际应用中,launch文件可以让用户非常方便地组织ROS系统的启动和配置。下面详细介绍ROS的launch文件及其所有的使用方法和场景。

一,launch文件的基本结构

一个最简单的launch文件如下所示:

<launch>
    <node name="my_node" pkg="my_package" type="my_node.py" />
</launch>

这个launch文件中包含了一个节点的描述信息。它的基本结构包含两个部分:

  • <launch></launch>:用来标记launch文件的开始和结束。
  • <node>标签:用来描述一个ROS节点。这个标签包含了节点的名称、所在包、执行文件等信息。

在一个launch文件中可以包含多个节点的描述,这些节点可以相互连接,形成一个完整的ROS系统。

二,launch文件的使用方法

在ROS中,可以使用roslaunch命令来启动一个launch文件。命令格式如下:

roslaunch package_name launch_file_name.launch [arg_name:=arg_value]

其中,package_name是节点所在的ROS软件包的名称,launch_file_name是要启动的launch文件的名称。可以通过[arg_name:=arg_value]的方式向launch文件中传递参数。

在launch文件中,可以使用<arg>标签来定义参数,如下所示:

<launch>
    <arg name="my_arg" default="hello" />
    <node name="my_node" pkg="my_package" type="my_node.py" my_arg="$(arg my_arg)" />
</launch>

这个launch文件中定义了一个名为my_arg的参数,它的默认值是hello。然后在node标签中使用$(arg my_arg)的方式来引用这个参数。当使用roslaunch命令启动这个launch文件时,可以通过my_arg:=world的方式修改这个参数的值。

三,launch文件的高级用法

除了基本的节点描述和参数传递,launch文件还支持一些高级用法。下面介绍一些常用的高级用法。

3.1. 组合多个launch文件

在ROS中,可以使用<include>标签来组合多个launch文件。如下所示:

<launch>
    <include file="$(find my_package)/launch/my_subsystem.launch" />
    <node name="my_node" pkg="my_package" type="my_node.py" />
</launch>

这个launch文件包含了另外一个名为my_subsystem.launch的launch文件,同时还启动了一个节点。在实际应用中,这种组合多个launch文件的方式可以让用户非常方便地组织ROS系统。

3.2. 使用节点组

在ROS launch文件中,可以通过group标签来定义节点组。节点组是指一组节点,这些节点将同时启动或停止,可以一起进行管理。使用节点组可以方便地启动和停止多个节点,从而减少手动操作和出错的可能性。如下所示:

<launch>
  <group ns="robot1">
    <node pkg="robot1" name="node1" type="node1" />
    <node pkg="robot1" name="node2" type="node2" />
  </group>
  <group ns="robot2">
    <node pkg="robot2" name="node1" type="node1" />
    <node pkg="robot2" name="node2" type="node2" />
  </group>
</launch>

在这个例子中,定义了两个节点组,robot1robot2。每个节点组都包含两个节点。在这个例子中,ns属性用于设置节点组的命名空间,以便在运行时可以区分不同的节点组。通过在命令行中指定命名空间,可以只启动或停止一个节点组。

在启动这个launch文件时,所有的节点将同时启动。可以使用rosnode list命令来列出当前运行的所有节点。可以使用rosnode info命令来查看特定节点的详细信息。

除了使用命名空间来区分节点组之外,还可以使用其他参数来进一步控制节点组的行为。例如,可以使用respawn="true"参数来指定节点组中的节点是否应该在崩溃后自动重启。可以使用required="true"参数来指定节点组中的节点是否是必需的,如果一个节点失败,整个节点组都将停止。

3.3. 参数替换。

可以在launch文件中定义参数,然后在节点的参数中使用这些参数进行替换,实现动态的配置管理。

假设我们有一个ROS节点my_node,该节点需要在启动时设置一个参数my_param,我们可以在launch文件中定义该参数并传递给该节点。

创建一个launch文件my_launch_file.launch,并定义参数my_param

<launch>
    <arg name="my_param" default="default_value" doc="My custom parameter" />
    <node name="my_node" pkg="my_package" type="my_node" output="screen">
        <param name="my_param" value="$(arg my_param)" />
    </node>
</launch>

在上面的launch文件中,我们定义了一个参数my_param,并设置了默认值为default_value。然后我们启动了一个名为my_node的节点,该节点从参数服务器中读取参数my_param的值,并将其设置为节点的参数。

在启动时可以通过以下命令启动该launch文件,并设置参数my_param的值为my_custom_value

roslaunch my_package my_launch_file.launch my_param:=my_custom_value

在上面的命令中,我们使用了:=操作符来指定参数my_param的值为my_custom_value

当launch文件启动时,参数my_param将被替换为my_custom_value,节点my_node将使用新的参数值启动。

使用ROS launch文件实现参数替换可以方便地配置ROS系统,避免了手动修改参数文件的麻烦。

3.4. launch文件的arg和param有什么区别?
 arg用于从命令行传递参数到launch文件中,可以通过${arg 参数名}的方式在launch文件中引用,例如:
<launch>
  <arg name="my_arg" default="hello" />
  <node name="my_node" pkg="my_package" type="my_node" output="screen">
    <param name="my_param" value="${arg my_arg}" />
  </node>
</launch>

在上面的例子中,定义了一个名为my_argarg,默认值为hello。在my_node节点的参数中,使用${arg my_arg}的方式引用了这个参数,也就是说,my_param参数的值将会是从命令行传递过来的my_arg参数的值,如果没有从命令行传递,则使用默认值。

param则是用于在launch文件内部传递参数的机制,可以通过${param 参数名}的方式在launch文件中引用,例如:

<launch>
  <param name="my_param" value="hello" />
  <node name="my_node" pkg="my_package" type="my_node" output="screen">
    <param name="my_param" value="${param my_param}" />
  </node>
</launch>

在上面的例子中,定义了一个名为my_paramparam,值为hello。在my_node节点的参数中,使用${param my_param}的方式引用了这个参数,也就是说,my_param参数的值将会是my_param参数的值,如果没有定义,则使用默认值。

简单说,arg标签是用于将参数从命令行传递到launch文件中,param标签是用于将参数从launch文件传递到ROS节点代码中,从而可以在python代码里通过rospy.get_param()获取到该参数。

 3.5. 实现条件判断
可以使用ifunless来实现条件判断。if表示条件成立时执行,unless表示条件不成立时执行。

下面是一个简单的例子,该例子实现了一个根据参数选择是否启动一个节点的功能:

<launch>
    <!-- 设置参数 -->
    <arg name="enable_node" default="false" />
    <!-- 根据参数决定是否启动节点 -->
    <node name="my_node" pkg="my_package" type="my_node" output="screen" if="$(arg enable_node)">
    </node>
</launch>

在上面的例子中,首先通过arg标签设置了一个参数enable_node,默认值为false。然后在node标签中使用了if参数,当enable_nodetrue时,节点my_node才会启动。

另外,unless参数可以用于在某个条件不成立时执行某个节点。例如,下面的例子会在参数roscore_runningfalse时启动节点my_node

<launch>
    <!-- 检查roscore是否正在运行 -->
    <node pkg="rosmon" type="rosmon" name="rosmon" args="-d 2" respawn="true">
        <remap from="rosmon/monitoring" to="rosmon" />
        <param name="max_processes" type="int" value="1" />
        <param name="nodes/my_node/type" value="my_node" />
        <param name="nodes/my_node/paused" value="false" />
        <param name="nodes/my_node/unless" value="$(arg roscore_running)" />
    </node>
    <!-- 启动节点my_node -->
    <node pkg="my_package" type="my_node" name="my_node" output="screen" unless="$(arg roscore_running)">
    </node>
</launch>

在这个例子中,首先通过rosmon节点检查roscore是否正在运行,并根据参数roscore_running的值确定是否启动节点my_node。然后在node标签中使用了unless参数,当roscore_runningtrue时,节点my_node才会启动。

 



 


posted @ 2023-04-21 17:24  透明飞起来了  阅读(1649)  评论(0编辑  收藏  举报