ROS launch

简介

如果rosrun是执行一个节点的命令,那么roslaunch是运行多个节点的概念。该命令允许运行多个确定的节点。其他功能还包括一些专为执行具有诸多选项的节点的ROS命令,比如包括更改功能包参数或节点名称、配置节点命名空间、设置ROS_ROOTROS_PACKAGE_PATH以及更改环境变量等。

roslaunch使用*.launch文件来设置可执行节点,它基于可扩展标记语言(XML),并提供XML标记形式的多种选项。像许多ROS包会有相应的启动配置,通过运行下面的指令来进行启动

roslaunch package_name file.launch

XML

计算次序

roslaunch与XML文件单一传递。include是按照深度优先遍历的顺序处理。标签tag进行串行处理并且最后的设置有效。因此,若一个参数被多次设置,最后指定的值将被使用。 比较推荐的是使用$(arg)/<arg>设置来进行重写行为。

替代参数(Substitution args)

launch文件支持替代参数,roslaunch将在启动节点之前对其进行解析。当前支持的替代参数有:

  1. $(env ENVIRONMENT_VARIABLE):用环境变量替换变量的值。如果未设置环境变量,则启动将失败。此值不能被标记覆盖。

  2. $(optenv ENVIRONMENT_VARIABLE):如果设置了环境变量的值,则替换该值。若提供default_value,则在未设置环境变量的情况下使用default_value。若未提供default_value,则将使用空字符串。default_value可以是多个单词,并用空格分隔。

例如:

<param name="foo" value="$(optenv NUM_CPUS 1)" />
<param name="foo" value="$(optenv CONFIG_PATH /home/marvin/ros_workspace)" />
<param name="foo" value="$(optenv VARIABLE ros rocks)" />

NUM_CPUS的default_value为1;VARIABLE的default_value为ros和rocks。

  1. $(find pkg): 指定相对于软件包的路径。

例如:查找rospy子目录下的manifest.xml文件。

$(find rospy)/manifest.xml
  1. $(anon name):根据名称生成匿名id,id不能重名。例如:
<node name="$(anon foo)" pkg="rospy_tutorials" type="talker.py" />
  1. $(eval ):用于计算任意复杂的python表达式。例如:
<param name="circumference" value="$(eval 2.* 3.1415 * arg('radius'))"/>
  1. $(dirname):返回启动文件所在目录的绝对路径。例如:
<include file="$(dirname)/other.launch" />

file指向当前launch文件所在目录下的other.launch文件。

  1. $(arg foo): 计算由标签指定的值,在声明arg的同一启动文件中必须有对应的标签。例如
<param name="foo" value="$(arg my_foo)" />

将指定 my_foo 到 foo 参数, 另外一个例子:

<node name="add_two_ints_server" pkg="beginner_tutorials" type="add_two_ints_server" />

<node name="add_two_ints_client" pkg="beginner_tutorials" type="add_two_ints_client" args="$(arg a) $(arg b)" />

将会从 <add_tow_ints> 例子中启动server和client,作为参数值a和传递。产生的启动项目能用如下语句调用:

roslaunch beginner tutorials launch_file.launch a:=1 b:=5

If和unless属性

所有标签都支持if和unless属性,这些属性基于值的评估包含或不包含在标签内。 “ 1”和“ true”被视为真实值。 “ 0”和“ false”被视为错误值。 其他值将出错。

if=value (optional):如果value评估为true,则包含标记及其内容。
unless=value (optional):如果value的值为false,则包含标记及其内容。

<group if="$(arg foo)">
<!-- 此处的代码仅当foo为true时才被读取 -->
</group>

<!-- 满足unless条件时不会设置此参数 -->
<param name="foo" value="bar" unless="$(arg foo)" />

launch文件案例

简单案例

以下案例具备最基本的启动文件配置。它启动一个单独的“talker”节点,该节点是“rospy_tutorials”软件包的一部分。 该节点将使用当前配置的ROS环境(即ROS_ROOT等)在本地计算机上启动。

<launch>
<node name="talker" pkg="rospy_tutorials" type="talker" />
</launch>

重映射机制

ROS提供一种重映射的机制,简单来说就是取别名,类似于C++中的别名机制,不需要修改别人功能包的接口,只需要将接口名称重映射一下,取个别名。launch文件中的标签可以帮我们实现这个重映射的功能。 比如turtlebot的键盘控制节点,发布的速度控制指令话题可能是/turtlebot/cmd_vel,但是我们自己的机器人订阅的速度控制话题是/cmd_vel,这个时候使用remap就可以轻松解决问题,将/turtlebot /cmd_vel重映射为/cmd_vel,机器人就可以接收到速度控制指令了:

<remap from="/turtlebot/cmd_vel"to="/cmd_vel"/>

重映射机制在ROS中的使用非常广泛,也非常重要,方法不止这一种,也可以在终端rosrun命令中实现重映射;

复杂案例

<launch>
<!-- local machine already has a definition by default.
This tag overrides the default definition with
specific ROS_ROOT and ROS_PACKAGE_PATH values -->
<machine name="local_alt" address="localhost" default="true" ros-root="/user/ros/" ros-package-path="/user/ros/ros-pkg" />
<!-- a basic listener node -->
<node name="listener-1" pkg="rospy_tutorials" type="listener" />
<!-- pass args to the listener node -->
<node name="listener-2" pkg="rospy_tutorials" type="listener" args="-foo arg2" />
<!-- a respawn-able listener node -->
<node name="listener-3" pkg="rospy_tutorials" type="listener" respawn="true" />
<!-- start listener node in the 'wg1' namespace -->
<node ns="wg1" name="listener-wg1" pkg="rospy_tutorials" type="listener" respawn="true" />
<!-- start a group of nodes in the 'wg2' namespace -->
<group ns="wg2">
<!-- remap applies to all future statements in this scope. -->
<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">
<!-- set a private parameter for the node -->
<param name="talker_1_param" value="a value" />
<!-- nodes can have their own remap args -->
<remap from="chatter" to="hello-1"/>
<!-- you can set environment variables for a node -->
<env name="ENV_EXAMPLE" value="some value" />
</node>
</group>
</launch>

参数服务器

可以在参数服务器上设置参数,这些参数将在启动任何节点之前存储在参数服务器上。如果值是明确的,则可以省略type属性。支持的类型为str,int,double,bool。例子如下

<launch>
<param name="somestring1" value="bar" />
<!-- force to string instead of integer -->
<param name="somestring2" value="10" type="str" />

<param name="someinteger1" value="1" type="int" />
<param name="someinteger2" value="2" />

<param name="somefloat1" value="3.14159" type="double" />
<param name="somefloat2" value="3.0" />

<!-- you can set parameters in child namespaces -->
<param name="wg/childparam" value="a child namespace parameter" />

<!-- upload the contents of a file to the server -->
<param name="configfile" textfile="$(find roslaunch)/example.xml" />
<!-- upload the contents of a file as base64 binary to the server -->
<param name="binaryfile" binfile="$(find roslaunch)/example.xml" />

</launch>

参考

[1]. 《ROS机器人编程–从基本概念到机器人应用程序编程实战》

[2]. ROS入门(二):launch文件解析

[3]. ROS探索总结(五十六)—— launch文件

知识共享许可协议