这如果是在同一台电脑上操作还好,但是如果今天如果是远端怎么办?尤其是碰到频宽有限的问题,那么远端频频断线,工作起来真的会要人命。所以,睿智且聪明的设计者们便设计了launch 档。只要执行它一次,便会call所有需要的launch 档和节点,并且可以自订输入的参数,可以说是相当方便。但是怎么个方便法?让我们继续看下去。 内容一览撰写第一份Launch 档如果你有机会下载一个别人写好的包裹,并且打开资料夹进里面看,可能会找到一个Launch资料夹,这里就是存放所有Launch档的地方,这种存放方法我把它视为某种约定俗成的习惯,因为方便管理嘛,哈! Launch 档实际上使用YAML 格式,说穿了,Launch 档就是一种脚本语言(Duh!)所以如果你有碰过XML, XAML, HTML等语言过,便可驾轻就熟。有几种关键语法: 宣告launch 档<launch> … </launch>在launch文件一开头和结尾都必须用这个宣告框出来,像这样: <launch> … </launch> 引数<arg>引数通常用来作为执行各节点或launch 档所需要的输入参数,换句话说,设定区域变数,通常需要使用者输入所需的数值,但也可以事先写好预设的数值。另外一种用法,是用引数作为一个逻辑判断,决定那些节点要执行,哪些不用。 引数的语法会像这样: <arg name="…" value="…"> 其中name是参数的名称。Value 是参数的值。有时候也用default=”…”来设定预设值。以下举几个例子: <arg name=”max_value” value=”0.5”> <arg name=”height_above_ground” default=”1.6”> <arg name=”camera_input” value=”/camera”> <arg name=”sensors_on” value=”true”> <!—下面章节会再提及这个指令的用法–> 注解<!– –>举几个例子: <!—Turn on laser–> <!—Fire up Rviz–> <!—Just want to comment out this line–> <!–<node name=”foo” pkg=”foo_pkg” type=”foo”>–> 呼叫节点<node />呼叫节点会包含以下几个参数: <node pkg="…" type="…" name="…" respawn=true ns="…" args=”….”/> 里面的参数及其公用:
若要设定该节点的印用参数,可以在节点内下以下指令: <args name=”” value=””> 基本上跟上述的引数用法差不多,但是当要引用使用者在上面小节给的数值的话,记得这样打: <arg name=”camera” value=”/camera/rgb/image_raw”> <!—这是文件一开头时的引数–>…. <node pkg=”foo_pkg” type=”foo” name=”foo”> <args name=”camera_namespace” value=”$(arg camera)”> </node> 其中,$(arg ….) 会自动去前面的<arg>找数值读进去。 除了<args>以外,还有其他选项,如以下:
这边只是列举几个比较常见参数。当然,还有更多参数选项,可以参考ROS Wiki文件。 呼叫其他launch 档<include>它的语法其实就是让ROS去找目标launch档的路径,一个很有用的写法,是用$(find <include file="$(find openni2_launch)/launch/openni2.launch"> <arg name="camera" value="rgbd_front_top"/> <arg name="device_id" value="#1″/> <arg name="depth_registration" default="true"/> </include> 以上是一个启动openni2.launch这个launch 逻辑判断式if & unless讲到这边,可能你会有一个疑问。那这样的脚本语言有没有判断式,在某个情况下执行特定节点,另外一个特定情况不要执行呢?有的,但是并不像是你看过的任何高阶语言那样: If (foo=true){ Return yes ; } Else { Return no ; } 那怎么办?其实只要转念一想,我们可以拿作为逻辑判断的方式,但是必须搭配标签使用,写法如下: <arg name="load_driver" default="true"/> <group if="$(arg load_driver)"> <include file="$(find openni2_launch)/launch/openni2.launch"/> </group> 同样的,也可以把<group>标签中的if 换成unless,整个设定就变得像是"直到收到值为真或1时,执行该节点或launch档"。 到时候在终端机执行这个launch 档的时候,如果要关闭或执行某节点或launch档,请输入:
或者
这样就能决定是否执行或跳过某部分不执行。还有,要打”:=”,否则launch档要不就不理你继续执行,或者是跳出语法错误的讯息。 开发一个大型专案的Launch 写法其实我尚未真的开发过一个大型专案,不过我们可以结合前人的智慧结晶以及自己的开发经验。 最重要的,就是专案由于功能众多,有许多节点互相连结,所以会被隔成一层层的,所以,一个rule of thumb就是最上层的节点尽量解结的呼叫下一层的 另外一个我之前开发碰到的问题就是,直接将他人的包裹直接加进自己的专案内部。站在版本控制的观念而言,每个包裹都是一个档案库(repository),除了在本地端维护外,更新的版本也会随时上传到云端。问题就发上在,一旦你将别人的档案库加进自己的专案,然后推上远端自己的档案库后,这些档案库变成你专案的一部分,再也不是他人的档案库,因此也无法更新成最新的版本。当我要把我的这个拥肿的包裹下载到另外一台电脑编译时,又与我之前安装的他人的同样的包裹名称起冲突。在把他人的包裹去掉,安装自己的包裹后,发现编译出错,但是密密麻麻的讯息,已经让我很难知道错误的源头。因此,后来也就决定把他人的智慧结晶从我的专案中移除,往后有需要使用到他人包裹中的某些功能时,直接用launch档呼叫即可。 从这个错误中我学到的教训是,不要把别人的档案库直接加进自己的档案库内,而是各别克隆(git
怎么在终端机下指令像上面的错误反省有提到的,Launch档可以在自己的包裹内呼叫其他包裹的launch档或节点,在实用上更方便。那么在终端机时,只要用roslaunch指令即可,语法是:
先宣告launch档所在的包裹名称,再来是launch档名称,后面的引数arg则是前面小节已经提到过的标签,其值可以被终端机上的指令覆盖掉。实际的例子:
让我们来细看上面这行指令。
为了加快并简化launch的指令,其实可以直接把自打到一半,按Tab键,会自动补齐,按两下Tab键则会跳出更多选项让使用者输入正确的launch档,但是注意,有时候电脑不会帮你写后面的.launch,需要自己写完或在按Tab补齐。如果你按Tab老半天,电脑都没有反应,有两个选项,一个就是把名字自己打完执行看看,要不然就是直接source,让ROS连结到正在使用的工作空间上,如下 然后再试试看roslaunch一次。 实际范例好了,大概讲完了,我们来看launch档实际范例,这是spencer_people_tracking中的tracking_single_rgbd_senosr.launch <launch> <!– Launch file arguments –> <arg name="height_above_ground" default="1.6″/> <!– in meters, assumes a <arg name="load_driver" default="true"/> <!– set to false if you are already <arg name="visualization" default="true"/> <arg name="dummy_transforms" default="true"/> <!– Run OpenNi2 driver –> <group ns="spencer/sensors" if="$(arg load_driver)"> <include file="$(find openni2_launch)/launch/openni2.launch"> <arg name="camera" value="rgbd_front_top"/> <arg name="device_id" value="#1″/> <arg name="depth_registration" default="true"/> </include> </group> <!– Set ground plane distance –> <rosparam <!– Set up dummy transforms into an imaginary robot and odom frame –> <group if="$(arg dummy_transforms)"> <node name="tf_base_footprint" pkg="tf" type="static_transform_publisher" <node name="tf_odom" pkg="tf" type="static_transform_publisher" args="0 0 0 0 0 </group> <include file="$(find <!– People tracking –> <include file="$(find <arg name="rgbd" default="true"/> <arg name="laser_low_confidence_detections" default="false"/> </include> <!– As there is not yet any high-recall/low-confidence detector for RGB-D, and To deal with this, for the moment, we increase the maximum number of occluded This works fine in uncrowded environments which are not very dynamic. –> <rosparam <rosparam <!– Group tracking –> <include file="$(find <!– RViz visualization –> <node name="tracking_visualization_rviz" pkg="rviz" type="rviz" args="-d $(find |
|
来自: 许文强1234 > 《ros相关学习文件》