launch文件

launch文件用于启动多个节点并加载运行参数,在运行ros节点时多采用launch文件启动节点。launch文件是一种特殊的XML格式文件,通常以.launch作为文件后缀。

launch文件标签(关键字)

  • <launch>
    所有的launch文件都由<launch>开头,由</launch>结尾,所有的描述标签都要写在<launch></launch>之间
<launch>
……
</launch>
  • <node>
    每个node标签里包括了ROS中节点的名称属性name、该节点所在的包名pkg以及节点的类型type.
属性 属性作用
name=“NODE_NAME” 为节点指派名称,这将会覆盖掉ros::init()定义的node_name
pkg=“PACKAGE_NAME” 节点所在的包名
type=“FILE_NAME” 执行文件的名称如果是用Python编写的就填写xxx.py,如果是cpp就写编译生成的可执行文件名
output=“screen” 终端输出转储在当前的控制台上,而不是在日志文件中
respawn=“true” 当roslaunch启动完所有该启动的节点之后,会监测每一个节点,保证它们正常的运行状态。对于任意节点,当它终止时,roslaunch 会将该节点重启
required=“true” 当被此属性标记的节点终止时,roslaunch会将其他的节点一并终止。注意此属性不可以与respawn="true"一起描述同一个节点
launch-prefix = “command-prefix” 在执行启动命令时加上一段命令前缀
ns = “NAME_SPACE” 这个属性可以让你在自定义的命名空间里运行节点

  • <machine>
    machine通常用于多主机之间启动节点,可以在本机上启动同一局域网下其他主机上的节点,具体用法示例如下:
<launch>
  <!--定义一个machine主机并加载环境变量 -->
  <machine name="foo" address="foo-address" env-loader="/opt/ros/fuerte/env.sh" user="someone"/>
  <!--启动主机machine上的一个节点-->
  <node machine="foo" name="footalker" pkg="test_ros" type="talker.py" />
</launch>
  • <include>
    该标签可以导入另一个roslaunch XML文件到当前文件。
属性 属性作用
file ="$(find pkg-name)/path/filename.xml" 指明我们想要包含进来的文件
ns=“NAME_SPACE” 相对NAME_SPACE命名空间导入文件
  • <remap>
    remap标签顾名思义重映射,ROS支持topic的重映射,remap标签里包含一个original-name和一个new-name,及原名称和新名称。
    比如现在你拿到一个节点,这个节点订阅了"/chatter"topic,然而你自己写的节点只能发布到"/demo/chatter"topic,由于这两个topic的消息类型是一致的,你想让这两个节点进行通讯,那么可以在launch文件中这样写:
<remap from="chatter" to="demo/chatter"/>

这样就可以直接把/chattertopic重映射到/demo/chatter,这样子不用修改任何代码,就可以让两个节点进行通讯。
如果这个 remap标签写在与 node 元素的同一级,而且在launch 元素内的最顶层。 那么这个重映射将会作用于launch文件中所有的节点。

  • <env>
    env通常用于设置环境变量,仅用于标签<launch><node><include><machine>范围内,且只有环境变量定义之后的节点生效。使用方法示例如下:
<env name="demo_env" value="demo_env"/>
  • <param>
    param标签的作用相当于命令行中的rosparam set
    例如现在在参数服务器中添加一个名为demo_param,值为666的参数
<param name="demo_param" type="int" value="666"/>
  • <rosparam>
    rosparam标签允许从YAML文件中一次性导入大量参数。
    使用方法如下:
<rosparam command="load" file="$(find pkg-name)/path/name.yaml"/>
  • <group>
    group标签可以将若干个节点同时划分进某个工作空间。
<group ns="demo_1">
    <node name="demo_1" pkg="demo_1" type="demo_pub_1" output="screen"/>
    <node name="demo_1" pkg="demo_1" type="demo_sub_1" output="screen"/>
</group>
<group ns="demo_2">
    <node name="demo_2" pkg="demo_2" type="demo_pub_2" output="screen"/>
    <node name="demo_2" pkg="demo_2" type="demo_sub_2" output="screen"/>
</group>

group标签还可以做到对node的批量管理。比如我可以同时终止在同一个group中的节点。

<group if="1-or-0">
……
……
……
</group>

<group unless="1-or-0">
……
……
……
</group>

第一种情况,当if属性的值为0的时候将会忽略掉<group></group>之间的标签。
第二种恰好相反,当if属性的值为1的时候将会忽略掉<group></group>之间的标签。
但是我们通常不会直接用1或0来定义if标签。因为这样不够灵活。
通常会搭配$(arg arg_name)来使用。
demo.launch文件

<launch>
    <include file="include.launch">
        <arg name="demo_arg" value="1"/>
    </include>
</launch>

include.launch文件

<launch>
    <arg name="demo_arg"/>
    <group if="$(demo_arg)">
        <node name="demo" pkg="demo" type="demo_pub" output="screen"/>
        <node name="demo" pkg="demo" type="demo_sub" output="screen"/>
    </group>
</launch>
  • <test>
    test标签与node的作用一样,其用于启动测试节点,使用方法示例如下:
<test test-name="test_1_2" pkg="mypkg" type="test_1_2.py" time-limit="10.0" args="--test1 --test2" />
  • <arg>
    arg标签用来在launch文件中定义参数,arg和param在ROS里有根本性的区别,就像局部变量和全局变量的区别一样。arg不储存在参数服务器中,不能提供给节点使用,只能在launch文件中使用。param则是储存在参数服务器中,可以被节点使用。
<arg name="demo"/>

以上就是简单地声明了一个参数,名叫demo,但是声明不等于定义,我们需要给他赋值,在赋值之后参数才能够发挥作用。

<arg name="demo" value="666"/>
<arg name="demo" default="666"/>

以上是两种简单的赋值方法,两者的区别是使用后者赋值的参数可以在命令行中像下面这样被修改,前者则不行。

roslaunch demo demo.launch demo:=6666

arg还有更加高级,也更加灵活的用法:

$(arg arg_name)

当$(arg arg_name)出现在launch文件任意位置时,将会自动替代为所给参数的值。

launch文件实例

<launch>
  <!--定义一个machine主机-->
  <machine name="local_alt" address="localhost" default="true" ros-root="/u/user/ros/ros/" ros-package-path="/u/user/ros/ros-pkg" />
  <!-- 启动节点listener,命名为listener-1 -->
  <node name="listener-1" pkg="rospy_tutorials" type="listener" />
  <!-- 启动节点listener,命名为listener-2,传入参数 -->
  <node name="listener-2" pkg="rospy_tutorials" type="listener" args="-foo arg2" />
  <!-- 启动节点listener,命名为listener-3,节点被kill之后自动重启 -->
  <node name="listener-3" pkg="rospy_tutorials" type="listener" respawn="true" />
  <!--在命名空间wg1中启动listener节点命名为listener-wg1-->
  <node ns="wg1" name="listener-wg1" pkg="rospy_tutorials" type="listener" respawn="true" />
  <!--在命名空间wg2下启动一个group-->
  <group ns="wg2">
    <!-- 映射主题chatter->hello,生效范围为group范围内 -->
    <remap from="chatter" to="hello"/>
    <node pkg="rospy_tutorials" type="listener" name="listener" args="--test" respawn="true" />
    <node pkg="rospy_tutorials" type="talker" name="talker">
      <!-- 设置一个私有变量的值 -->
      <param name="talker_1_param" value="a value" />
      <!-- 映射主题chatter->hello-1,生效范围为node范围内 -->
      <remap from="chatter" to="hello-1"/>
      <!-- 设置环境变量,作用范围为node范围内 -->
      <env name="ENV_EXAMPLE" value="some value" />
    </node>
  </group>
</launch>

启动launch文件

启动launch文件通过roslaunch命令来完成,package_name指功能包的名称,demo.launch表示需要启动的launch文件。

$ roslaunch package_name demo.launch