ROSLAUNCH 的.launch/XML 语法
来源:互联网 发布:熊猫tv小葫芦数据 编辑:程序博客网 时间:2024/05/22 03:24
最近面临一个将ROS与机器人结合起来以扩展现有机器人的功能的任务,譬如将ABB的2400机器人接上ROS的moveit,然后通过ROS去控制机器人的运动,对于IRB2400这样的机器人实现还是蛮简单的,但是这种情况下,只知其然而不知其所以然,感觉就不好了,所以我得将这一套东西彻底的理解清楚,整理明白。在这里码下来记录一下我的学习与经历的过程,在面对这个问题时,首先想弄明白的就是roslaunch使用的.launch文件中到底写了些什么鬼!
对了,roslaunch文件的扩展名为.launch,是按照XML格式编写的,所以XML格式的文件也一样能解析。
- 文件解析顺序
- 置换参数
- 1 env ENVIRONMENT_VARIABLE
- 2 optenv ENVIRONMENT_VARIABLE
- 3 optenv ENVIRONMENT_VARIABLE default_value
- 4 find pkg
- 5 anon name
- 6 arg varible_name
- 7 eval expression
- IF 和 UNLESS 属性
- 参考标签
- 1 launch
- 2 node
- 3 param
- 4 rosparam
- 5 remap
- 6 machine
- 7 include
- 8 env
- 9 test
- 10 arg
- 11 group
- launch文件的例子
- 1 一个简单的例子
- 2 一个复杂一点的例子
- 3 设置参数
1. 文件解析顺序
roslaunch 以单程的方式解析XML格式文件,include是以深度优先的方式解析内容,而标签Tag以串行的方式处理,所以一个参数的最后一次设置被认定为有效值。
也就是说在.launch文件中同样的设置可能存在多处,比如在开头定义了一个变量,遵循着尽量节省空间的想法,在后面的定义中又对这个变量进行了重新赋值,以便重新利用,在这种情况下,在整个launch文件解析完成后,最终进行的那次设置是有效的,但也并不保证一定有效,不排除在其它的文件中对变量进行了重命名,所以推荐使用$(arg)/<arg>
的方式进行覆写。
2. 置换参数
在roslaunch文件中,置换参数也称做置换符,是最常用的,可以提高变量的重用性。下面可用的置换参数如下所示:
2.1 $(env ENVIRONMENT_VARIABLE)
其中的“$”是一个置换处理标志(我是这么理解的),而“env”则是说明后面的变量被当做环境变量处理,毕竟“env”是“environment”(环境)的前面仨字母是吧。这行代码的意思就是用当前环境变量ENVIRONMENT_VARIABLE
的值置换目标变量值,不能被<env>
覆写,为什么不能覆写呢,后面有说明,如果想起来就把说明放这里,想不起来的话就到后面<env>
里找找吧。所以环境变量是比较严肃的,如果用于置换的环境变量未设置,当你启动launch文件时则会显示失败。
对着例子再来啰嗦一下(感觉比较笨怕以后看到理解不了…想像一下这里配了一张悲伤脸的表情)
<param name="variable_name" value="$(env NUM_CPUS)" />
上面例子中param
是launch文件中进行参数定义的关键字,name
属性指定了要定义的变量的名称,value
属性是对你前面指定的变量进行赋值或进行值替代,$(env NUM_CPUS)
就是你指定要用于进行目标变量值替代的选用值,这个时候问题就来了,如果你的电脑环境变量中有名叫NUM_CPUS
的环境变量,那没事,这行代码可以轻松通过,但是如果你的电脑里没有这个环境变量,那你运行这个launch文件的时候就是报错,所以相对来说,optenv
更具有鲁棒性。
2.2 $(optenv ENVIRONMENT_VARIABLE)
optenv
这个标识符就没有env
那么严肃,毕竟它在env
的前面加了opt
,那就变成了optional environment
了是吧,这一行代码就是说如果ENVIRONMENT_VARIABLE
已设置,则用其替代目标变量,若没有设置,则用空字符串表示。但我觉得直接理解下面一条更全面。
2.3 $(optenv ENVIRONMENT_VARIABLE default_value)
此行代码可以这样理解,先看ENVIRONMENT_VARIABLE
环境变量有没有设置, 若ENVIRONMENT_VARIABLE
有设置,就用ENVIRONMENT_VARIABLE
的值替代目标变量值,如果ENVIRONMENT_VARIABLE
没有设置,那就看default_value
是否有设置,如果default_value
设置过了,那就用default_value
的值去替代目标变量的值,如果default_value
未给定则用空字符串去初始化目标变量值。
给以下三个例子:
<param name="variable_name" value="$(optenv NUM_CPUS 1)" />
上面这一行代码中,在我的计算机中NUM_CPUS
这个环境变量不存在,所以最后variable
的值就是1这个缺省值。如果这个缺省值也没有设置,那最后将用空字符串替代目标变量值。
<param name="pkg_path_name" value="$(optenv PATH /home/catkin_ws/src)" />
这一行代码中,PATH
这个环境变量是存在的,所以名为pkg_path
的变量值便为PATH
的值。
<param name="variable_name" value="$(optenv VARIABLE ros rocks)" />
这一行是想说缺省设置的值可以是一个中间有空格隔开的字符串。
2.4 $(find pkg)
这行代码是用来进行相对路径的提取。
例如:
$(find rospy)/manifest.xml
便是找到包rospy的路径,并且会被内联替换。
2.5 $(anon name)
产生基于名称的匿名ID,主要用于节点名称属性中创建匿名节点,并检查是否有相同的匿名名字,因为ROS中名字作为标识符要求具有唯一性。其中的anon是anonymous的简写。
例如:
<node name="$(anon talk_01)" pkg="rospy_tutorials" type="talker.py" /> <node name="$(anon talk_01)" pkg="rospy_tutorials" type="talker.py" />
则会产生错误,因为系统检测到了两个节点具有相同的匿名名字。
2.6 $(arg varible_name)
解析由<arg>
标签指定的变量值。
例如:
<param name="varible_name" value="$(arg my_varible)" />
要求在同一文件中my_varible
已经由<arg>
标签所指定。即在launch文件中存在以下定义:
<arg name="my_varible_name" value="defined_value">
这样在解析my_varible
的值的时候才能正常进行。就如同你在表达式中用一个变量进行计算,你必须在计算之前就已经定义过这个变量才可以。
再如:
<node name="add_client" pkg="beginner" type="add_client" args="$(arg a) $(arg b)" />
其中的$(arg a)
和$(arg b)
则是对节点所需要的变量进行声明,这样你在对节点进行参数传递的时候就可以用以下代码进行:
roslaunch beginner launch_file.launch a:=1 b:=5
假设以上代码是launch_file.launch中的片段,则在调用文件时要按所声明的变量名称要求进行参数的赋值。
2.7 $(eval <expression>)
允许计算任意复杂的表达式,而标识符(Tag)或说是标签eval其实是evaluation的前几个字母,表示计算评估的意思,而后面则可以使用表达式。
例如:
<param name="circumference" value="$(eval 2.* 3.1415 * arg('radius'))"/>
会根据给定的'radius'
进行计算后对circumference
赋值。作为限制,$(eval)
的作用范围要跨越表示整个表达式的字符串,如果在其中插入其它属性是不可行的。
例如:
<param name="a_name" value="$(arg r_dis) $(eval 6*7) bar"/>
是不可行的。但可以:
"$(eval arg('sth') + env('PATH') + 'bar' + find('pkg'))"
在内部进行字符串相加操作。
3. IF 和 UNLESS 属性
所有的标签都支持if和unless属性,此类属性是基于计算的值包含或是排除一个标签的内容。
if = value (optional)
如果value的值为真则包含标签及内容。
unless = value (optional)
如果值为假,则包括此内容。
<group if="$(arg value)"> <!-- 如果值为真,则包含写在group里的内容 --></group><param name="varible_name" value="sth" unless="$(arg value)" /> <!-- 如果判断的值为真则不包含parma定义的变量 -->
4. 参考标签
4.1 <launch/>
<launch>
标签为所有roslaunch文件的根标签,可以将其理解为所有其它标签的容器。以下为<launch>
标签与其它标签的关系:
<launch>
与其它标签的关系:
<launch> <node/> <param/> <remap/> <machine/> <rosparam/> <include/> <env/> <test/> <arg/> <group/></launch>
4.2 <node/>
用来启动节点,但不保证节点的启动顺序。其包含的属性如下所示:
pkg="mypackage"<!--指定所用的包-->type="nodetype"<!--指定对应的可执行程序的名字-->name="nodename"<!--指定节点名称,但不能在这里加入命名空间名称-->args="arg1 arg2 arg3"<!--声明或传递参数(optional)-->machine="machine-name"<!--在指定的机器上启动节点(optional)-->respawn="true"<!--如果节点失败则重新启动(optional)-->respawn_delay="30" <!--如果上rospawn属性为真,则等待一定的时间之后重新启动节点(optional, New in indigo)-->required="true"<!--将节点定义为必需节点,如果本节点失效,则关闭整个文件(optional)-->ns="nnss"<!--在一个命名空间中启动节点(optional)-->clear_params="true|false"<!--在节点启动之前是否清空所在命名空间中的变量(optional)-->output="log|screen"<!--指定输出的对象(optional)-->cwd="ROS_HOME|node"<!--指定node则节点工作路径与其可执行程序路径相同(optional)-->launch-prefix="prefix arguments"<!--预先处理指令或参数(optional,支持多种工具)-->
在<node>
节点作用范围之内可以使用的标签如下:
<node> <env/> <remap/> <rosparam/> <param/></node>
4.3 <param/>
用于在参数服务器中定义参数。其属性参数如下所示:
name="namespace/name"
参数名称。在这个名称定义中是可以使用命名空间的,而在node的名称定义中不能使用命名空间,这个是有区别的。但是应该避免指定全局的名称。
value="value"
定义参数的值,如果这一属性忽略掉了,但必须指定其它的文件或是命令等(optional)。
type="str|int|double|bool|yaml"
指定参数的类型(optional),如果不指定则会自动识别类型,规则如下:
1.有“.”的认为是浮点数,没有的则认为是整型。
2.”true” 和 “false” 被认为是逻辑变量 (not case-sensitive)。
3.其它的所有都为string型。
textfile="$(find pkg-name)/path/file.txt"
文件的内容被存储为string类型用以替代目标变量(optional)。
binfile="$(find pkg-name)/path/file"
内容将被存储为 base64-encoded XML-RPC 二进制对象用以替代目标变量(optional)。
command="$(find pkg-name)/exe '$(find pkg-name)/arg.txt'"(optional)
执行某项命令,命令的输出将被存储为一个string类型以替代目标变量。
举个栗子:
<param name="publish_frequency" type="double" value="10.0" />
以上代码就是在参数服务器中定义一个名为:publish_frequency,类型为:double,值为:10.0 的变量。
如果是加载YAML文件可以用以下代码:
<rosparam command="load" file="FILENAME" />
其中的file属性要指定路径和文件名。
4.4 <rosparam/>
支持从YAML文件进行参数的读取与卸载。其属性如下所示:
command="load|dump|delete" (optional, default=load)
rosparam的命令,可以指定 加载|卸载|删除 对应的参数。
file="$(find pkg-name)/path/my.yaml" (load or dump commands)
指定文件所要求的路径。
举个例子:
<rosparam command="load" file="$(find rosparam)/example.yaml" /><rosparam command="delete" param="my/param" /><rosparam param="a_list">[1, 2, 3, 4]</rosparam>
第一行代码是用来加载对应的YAML文件,第二代码是删除名为my的命名空间下的param变量,第三行代码是定义一个变量,而变量的值即为标签之间的所有内容 ,即将中间的所有内容作为字符串放入到变量a_list中。
param="param-name"
指定参数名称。
ns="namespace" (optional)
将参数设置到指定的命名空间。
subst_value=true|false (optional)
设置在YAML文本中是否允许使用替代标签。
举个栗子:
<arg name="whitelist" default="[3, 2]"/><rosparam param="blacklist" subst_value="True">$(arg whitelist)</rosparam>
如果在上一行代码中subst_value
为false
,则输出的blacklist
只是一个字符串$(arg whitelist)
,表示不允许使用替代标签,但如果为true
则表示允许使用替代标签,则blacklist
输出的值为[3,2]
。
4.5 <remap/>
用来通过名称进行参数之间的映射。其属性如下:
from="original-name"
指定节点原来要监听的话题的名称。
to="new-name"
指定节点实际要监听的话题的名称。
例如:
<remap from="chatter" to="hello"/>
此行代码表明要将原来应监听chatter话题的节点改到监听hello话题。
4.6 <machine/>
如果在本地启动所有节点,则并不需要此标签,且此标签在F版本的ROS前后语法上是不同的,要参考对应的版本,这一标签内容在当前的任务暂时用不到,先挖个坑放这里。
4.7 <include/>
此标签允许在launch文件中包含其它的roslaunch文件或XML文件等。其属性如下所示:
file="$(find pkg-name)/path/filename.xml"
指定要包含的文件路径。
ns="namespace_name" (optional)
指定要导入文件的命名空间。
clear_params="true|false" (optional Default: false)
以上代码意味着在文件加载之前是否要清空所有命名空间中的参数,缺省为false,此参数要谨慎使用,用之前要核对好命名空间名称。
pass_all_args="true|false" (optional Default: false)
这一属性选择是否将当前情景下的参数传递到子情景之中。
在<include>
标签范围内可以使用的标签如下:
<include> <env/> <arg/></include>
4.8 <env/>
此标签用来设置接下来要启动的节点的环境变量,其可以在<launch>
,<include>
,<node>
和<machine>
标签中使用。当在<launch>
中使用时,<env>
标签作用于其后声明的所有节点。但是用此标签声明的环境变量通过$(env …)
不可见,所以并不能用$(env …)
对其它变量的值进行置换,所以<env>
标签不能用来参数化launch文件。其属性如下所示:
name="environment-variable-name"
此属性用来设置环境变量名称。
value="environment-variable-value"
此属性用来设置环境变量值。
4.9 <test/>
<test>
标签在语法上类似于<node>
标签,都是指定一个ROS节点运行,但是<test>
标签表明当前要运行的节点是一个测试节点。
<test>
与 <node>
具有大部分相同的属性,但以下内容是不同的:
• 没有respawn属性 (测试节点必须要被终止,所以它们没有重启属性)
• 没有输出属性,因为测试节点有其输出记录机制。
• Machine属性被忽略。
<test>
标签所必须的几个属性如下:
pkg="mypackage"
这一属性是必需的属性,指定节点的包名称。
test-name="test_name"
必须的属性,指定测试节点的名称。
type="nodetype"
必须的属性,指定测试节点所对应的可执行程序名称。 <test>
标签可选择的属性如下:
name="nodename"
节点名称。PS:名称中不能包含命名空间,如果要指定要使用ns属性,如果此属性未指定,则test-name将被作为节点名称。
args="arg1 arg2 arg3"
用测试节点传递参数。
clear_params="true|false"
如果是true,则在启动之前清空当前节点私有命名空间中的全部参数。
cwd="ROS_HOME|node"
指定工作路径。如果是node则节点的工作目录与节点的可执行程序目录相同。
launch-prefix="prefix arguments"
节点启动之前的预置参数或命令。
ns="namespace_name"
在指定的命名空间中启动节点。
retry="0"
用于有时可能失效的随机过程,设置重新尝试的次数。
time-limit="60.0"
认定节点启动失败之前要经历的时间,缺省为60s。
例如:
<test test-name="test" pkg="mypkg" type="test.py" time-limit="10.0" args="--test1 --test2" />
上行代码指定要测试的节点的名称,包名称,可执行程序名称,测试时间跨度和要传递的参数。
标签的作用范围中可以使用以下标签:
<test> <env/> <remap/> <rosparam/> <param/></test>
4.10 <arg/>
<arg>
指令允许创建可以通过传递参数值进行重复使用与配置的launch文件。但<arg>
标签是非全局的,一个声明只针对一个launch文件,如同局部变量一样,如果要在其它文件中使用,则必须要明确的进行值传递。
标签的属性有以下几种:
name="arg_name"
指定变量名。
default="default value" (optional)
指定变量缺省值,不能与value属性一起使用。
value="value" (optional)
指定变量值,不能与default属性一起使用。
doc="description for this arg" (optional) New in Indigo
进行变量描述。
<arg>
可以通过以下三种方式使用:
(1) 声明变量的存在
<arg name="variable_name" />
对于只进行了变量声明的变量,必须通过参数传递进行使用,通过命令行传递或通过<include>
标签进行传递。
(2) 声明变量,并赋予一个缺省值
<arg name="variable_name" default="1" />
可以通过命令行或<include>
标签进行值传递使用。
(3) 用一个常量定义变量,值不能被覆盖
<arg name="variable_name" value="defined_somevalue" />
这种用法可以内部参数化而不需要将参数化过程暴露于更高层次,意思就是如果你是用value属性对值直接进行定义的,那么你是无法再你其传递参数,即不能对变量值进行覆写。
例如:在test.launch中写入以下代码:
<launch> <include file="$(find your_pkg)/launch/included.launch"> <arg name="s_name" value="rose" /> </include></launch>
而在included.launch中写入以下代码:
<launch> <arg name="s_name" /> <param name="param" value="$(arg s_name)"/></launch>
则当运行test.launch文件时,s_name
参数会从test.launch的<include>
中传递进入included.launch文件中,从而产生一个变量名为param
而值为rose
的变量。但是由于<arg>
定义的为一个文件内部的局部变量(类似于类内的私有变量),无法从更高一级或外部进行访问,即不能通过命令行进行赋值,所以,当运行:
roslaunch %YOUR_ROS_PKG% test.launch s_name:=my_value
时,s_name
的值还是原来设定的value值,而不管你在局部的<arg>
属性中是用value属性还是default属性。如果想用自己的定义值在命令行中进行覆盖,则<arg>
标签要使用更高一层级的default属性指定。即修改test.launch如下所示:
<launch> <arg name=”temp” default=”rose”/> <include file="$(find your_pkg)/launch/included.launch"> <arg name="s_name" value="$(arg temp)" /> </include></launch>
即定义一个更高一层次的<arg>
标签来执行值传递,从更高一层级传递到局部再传递到included.launch文件中。
4.11 <group/>
<group>
标签可以对一组节点进行设置,并且可以通过ns属性将一组节点放到一个隔离开的命名空间中。
其具有以下属性:
ns="namespace" (optional)
将一组节点指定到一个特定的命名空间中,命名空间可以是全局的或是局部的,但并有推荐使用全局的命名空间。
clear_params="true|false" (optional)
在节点启动之前清空<group>
命名空间中的所有参数,谨慎使用。
内部可使用的标签如下所示:
<group> <node/> <param/> <remap/> <machine/> <rosparam/> <include/> <env/> <test/> <arg/><group/>
5. launch文件的例子
5.1 一个简单的例子:
<launch> <node name="talker" pkg="rospy_tutorials" type="talker" /></launch>
在本地使用当前ros环境启动rospy_tutorials
包中的可执行程序为talker
的节点,节点名称定义为talker
。
5.2 一个复杂一点的例子:
<launch> <machine name="local_alt" address="localhost" default="true" ros-root="/u/user/ros/ros/" ros-package-path="/u/user/ros/ros-pkg" /> <!-- 本地的机器已经进行了缺省定义,这个标签的作用是用指定的ROS_ROOT和ROS_PACKAGE_PATH值对其重新赋值--> <node name="listener-1" pkg="rospy_tutorials" type="listener" /> <!-- 启动一个收听节点 --> <node name="listener-2" pkg="rospy_tutorials" type="listener" args="-foo arg2" /> <!-- 向监听节点中传递参数 --> <node name="listener-3" pkg="rospy_tutorials" type="listener" respawn="true" /> <!-- 一个可以重新启动的节点 --> <node ns="wg1" name="listener-wg1" pkg="rospy_tutorials" type="listener" respawn="true" /> <!-- 在 'wg1' 命名空间中启动一个节点 --> <group ns="wg2"> <!-- 在 'wg2' 命名空间中启动一组节点 --> <remap from="chatter" to="hello"/> <!-- remap在group范围内作用于在其后声明的所有节点 --> <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" /> <!-- 设置局部变量 --> <remap from="chatter" to="hello-1"/> <!-- 节点可以有其自己私有的remap指令 --> <env name="ENV_EXAMPLE" value="some value" /> <!-- 为节点设置环境变量 --> </node> </group></launch>
5.3 设置参数
<launch> <param name="somestring1" value="bar" /> <!-- 值类型为string类型 --> <param name="somestring2" value="10" type="str" /> <!-- 强制使用string类型而不是整型定义参数 --> <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" /> <!-- 自动识别为浮点型数据 --> <param name="wg/childparam" value="a child namespace parameter" /> <!-- 在子命名空间中设置参数 --> <param name="configfile" textfile="$(find roslaunch)/example.xml" /> <!-- 向参数服务器中加载文本文件内容 --> <param name="binaryfile" binfile="$(find roslaunch)/example.xml" /> <!-- 向参数服务器中加载二进制文件内容 --></launch>
- ROSLAUNCH 的.launch/XML 语法
- 本地roslaunch远程机器的launch文件
- ROS Learning-032 (提高篇-010 Launch)Launch 深入研究 --- (启动文件编程)ROS 的 XML语法简介
- 成功编译和运行roslaunch qbo_webi qbo_webi.launch(解决qbo_object_recognition之后的其他问题)
- roslaunch xml 11 tags
- roslaunch rbx1_bringup fake_pi_robot.launch 运行报错[fake_turtlebot.launch] is neither a launch file in
- ros源码分析(7)—roslaunch .launch 文件
- ros源码分析(8)—roslaunch .launch文件中的tag
- roslaunch error: ERROR: cannot launch node of type
- rosrun,roslaunch: cannot launch node or is either a launch file in package
- rosrun,roslaunch: cannot launch node or is either a launch file in package
- roslaunch的使用和编写
- 启动出错:roslaunch turtlebot_gazebo amcl_demo.launch map_file:=/tmp/my_map.yaml
- XML的语法
- XML的基本语法
- XML的语法规则
- XML的认识、语法
- xml的基本语法
- redis源码分析(五)、redis命令学习总结—哈希Hash
- 状态栏背景色更改失败
- Spark算子[19]:saveAsHadoopFile、saveAsNewAPIHadoopFile 源码实例详解
- oracle备份之rman_全库备份恢复
- ISE中文件的调用
- ROSLAUNCH 的.launch/XML 语法
- redis源码分析(六)、redis命令学习总结—Redis 集合(Set)
- Java中用Struts2做下载功能遇到的问题
- Android中Intent/Bundle的通信原理及大小限制(Parcelable原理及与Serializable的区别)
- wxWidgets学习
- pip命令使用简介
- redis源码分析(七)、redis命令学习总结—Redis 有序集合(sorted set)
- php 数组去重
- 单链表插入排序