本文章转自:https://charlyhuangrostutorial.wordpress.com/2015/08/12/20/

前面已经提过关于launch 档的角色,很类似bash 档,基本上就是把所有为了执行某个特定功能所需要的指令都写在一张纸上,交给ROS 一次执行开来。举例来说,今天我想执行SLAM (即时建图及定位)的功能,但是这个演算法并不简单,我必须喂好几个输入资料进去,所以,在不知道launch 档好处的情况下,我就必须在终端机上个别开分页这样操作:

  • 把雷射打开
  • 把里程计(odometry)打开
  • 把tf 程式打开
  • 把gmapping 节点打开
  • 把马达驱动器打开
  • 把teleoperation 节点打开,因为我想直接操作机器人
  • 把图形介面打开,因为我像直接看结果

这如果是在同一台电脑上操作还好,但是如果今天如果是远端怎么办?尤其是碰到频宽有限的问题,那么远端频频断线,工作起来真的会要人命。所以,睿智且聪明的设计者们便设计了launch 档。只要执行它一次,便会call所有需要的launch 档和节点,并且可以自订输入的参数,可以说是相当方便。但是怎么个方便法?让我们继续看下去。

内容一览

  • 撰写第一份Launch 档

    • 宣告launch 档<launch> … </launch>
    • 引数<arg>
    • 注解<!– –>
    • 呼叫节点<node />
    • 呼叫其他launch 档<include>
    • 逻辑判断式if & unless
  • 开发一个大型专案的Launch 写法
  • 怎么在终端机下指令
  • 实际范例

撰写第一份Launch 档

如果你有机会下载一个别人写好的包裹,并且打开资料夹进里面看,可能会找到一个Launch资料夹,这里就是存放所有Launch档的地方,这种存放方法我把它视为某种约定俗成的习惯,因为方便管理嘛,哈!
我们将以Spencer People Tracking为范例,将这个专案中一部份的Launch file拿出来参考。但是在开始看之前,让我们先了解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=”….”/> 
<!—记得后面要写成/>要不然执行的时候会出错!–>

里面的参数及其公用:

参数 功用
pkg 表示该节点所在的包裹
type 表示这个节点实际的名称,也就是开发的时候取的名字
name 虽然也是指该节点的名称,不过你可以再另外帮这个节点取名字,那么该节点便会把原名给覆盖掉,以这个名称表示。你可以在执行时,用rqt或者
rosnode list, rosnode info等指令查看到。
respawn/required 是当该节点由于不明原因停止执行的时候,会自动重新启动。而required比较霸道一点,当该节点停止执行的时候,会让整个launch 
档都停止执行、关闭。
ns 指明在哪一个工作区间(workspace)的时候执行该节点,当你必须在多个子类别的实体(instance)中执行同一个节点的时候会很用。

若要设定该节点的印用参数,可以在节点内下以下指令:

<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>以外,还有其他选项,如以下:

参数 功用
<remap> 用法是<remap from=”…” to=”…”>。将原本节点的输入管道,接"到"新的topics 
上面。我都这样想像,把节点想像成大象,把他那条长长的鼻子(输入的topics,from=”…”)拉到我要他吃进去的topics 
上面去(to=”target topic”) 。
<env> 让该节点读入环境变数
<rosparam> 让该节点读进参数设定档
<param> 设定该节点所需的参数

这边只是列举几个比较常见参数。当然,还有更多参数选项,可以参考ROS Wiki文件。

呼叫其他launch 档<include>

它的语法其实就是让ROS去找目标launch档的路径,一个很有用的写法,是用$(find 
<pkg>)这种语法来直接找包裹下的路径,所以不管这个包裹的路径被更改,程式照样能找得到目标。请看下面范例:

<include file="$(find openni2_launch)/launch/openni2.launch">

<arg name="camera" value="rgbd_front_top"/>

<arg name="d​​evice_id" value="#1″/>

<arg name="d​​epth_registration" default="true"/>

</include>

以上是一个启动openni2.launch这个launch 
档的语法,包含在<include>里面的则是其引数。那又要怎么知道设定那些引数呢?最简单的方法就是去看看目标launch档一开头的<arg> 
标签,看看有那些设定可以更改。

逻辑判断式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档,请输入:


$ roslaunch pkg node load_driver:=false


或者


$ roslaunch pkg node load_driver:=true


这样就能决定是否执行或跳过某部分不执行。还有,要打”:=”,否则launch档要不就不理你继续执行,或者是跳出语法错误的讯息。

开发一个大型专案的Launch 写法

其实我尚未真的开发过一个大型专案,不过我们可以结合前人的智慧结晶以及自己的开发经验。

最重要的,就是专案由于功能众多,有许多节点互相连结,所以会被隔成一层层的,所以,一个rule of thumb就是最上层的节点尽量解结的呼叫下一层的
launch 
档,然后下一层的launch档在呼叫下一层的launch档。而参数的设定尽量不要越级,该层级的参数设定就直接写在该层的launch档内,而不要上面好几层的launch档直接介入。这样的方法在除错和阅读上会清晰不少。

另外一个我之前开发碰到的问题就是,直接将他人的包裹直接加进自己的专案内部。站在版本控制的观念而言,每个包裹都是一个档案库(repository),除了在本地端维护外,更新的版本也会随时上传到云端。问题就发上在,一旦你将别人的档案库加进自己的专案,然后推上远端自己的档案库后,这些档案库变成你专案的一部分,再也不是他人的档案库,因此也无法更新成最新的版本。当我要把我的这个拥肿的包裹下载到另外一台电脑编译时,又与我之前安装的他人的同样的包裹名称起冲突。在把他人的包裹去掉,安装自己的包裹后,发现编译出错,但是密密麻麻的讯息,已经让我很难知道错误的源头。因此,后来也就决定把他人的智慧结晶从我的专案中移除,往后有需要使用到他人包裹中的某些功能时,直接用launch档呼叫即可。

从这个错误中我学到的教训是,不要把别人的档案库直接加进自己的档案库内,而是各别克隆(git 
clone)和编译,然后自己的档案库只负责自己写的程式和launch档。这样做的好处有四:

  1. 可以独立测试各包裹,方便除错
  2. 由于每个包裹仍然是个别的档案库,因此仍然可以更新成最新版本,也方便维护与同步
  3. 在不同的平台编译的时候,方便除错与维护。
  4. 我们不应该很大喇喇地窃取人家的智慧结晶,占为己有却不说声谢谢。(啊!这算是我个人观感,就别算在原因内了吧!)

怎么在终端机下指令

像上面的错误反省有提到的,Launch档可以在自己的包裹内呼叫其他包裹的launch档或节点,在实用上更方便。那么在终端机时,只要用roslaunch指令即可,语法是:


$ roslaunch <pkg name> <launch file> <arg1>:=… <arg2>:=… <arg3>:=…


先宣告launch档所在的包裹名称,再来是launch档名称,后面的引数arg则是前面小节已经提到过的标签,其值可以被终端机上的指令覆盖掉。实际的例子:


$ roslaunch rtabmap_ros rgbd_mapping.launch rviz:=true rtabmapviz:=false


让我们来细看上面这行指令。

Pkg name rtabmap_ros
Launch file rgbd_mapping.launch
<arg 1> rviz:=true
<arg 2> rtabmapviz:=false

为了加快并简化launch的指令,其实可以直接把自打到一半,按Tab键,会自动补齐,按两下Tab键则会跳出更多选项让使用者输入正确的launch档,但是注意,有时候电脑不会帮你写后面的.launch,需要自己写完或在按Tab补齐。如果你按Tab老半天,电脑都没有反应,有两个选项,一个就是把名字自己打完执行看看,要不然就是直接source,让ROS连结到正在使用的工作空间上,如下 然后再试试看roslaunch一次。
$ souce ~/your_ws/devel/setup.bash

实际范例

好了,大概讲完了,我们来看launch档实际范例,这是spencer_people_tracking中的tracking_single_rgbd_senosr.launch 
在终端机执行时,请打: 以下是Launch档:
$ roslaunch spencer_people_tracking tracking_single_rgbd_sensor.launch


<launch>

<!– Launch file arguments –>

<arg name="height_above_ground" default="1.6″/> <!– in meters, assumes a 
horizontally oriented RGB-D sensor; important for accurate detection –>

<arg name="load_driver" default="true"/> <!– set to false if you are already 
running OpenNi from elsewhere –>

<arg name="visualization" default="true"/>

<arg name="d​​ummy_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="d​​evice_id" value="#1″/>

<arg name="d​​epth_registration" default="true"/>

</include>

</group>

<!– Set ground plane distance –>

<rosparam 
param="/spencer/perception_internal/people_detection/ground_plane/distance" 
subst_value="true">$(arg height_above_ground)</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" 
args="0 0 $(arg height_above_ground) 0 0 0 base_footprint rgbd_front_top_link 
10″/>

<node name="tf_odom" pkg="tf" type="static_transform_publisher" args="0 0 0 0 0 
0 odom base_footprint 10″/>

</group> 
<!– Detectors –>

<include file="$(find 
spencer_people_tracking_launch)/launch/detectors/front_rgbd_detectors.launch"/>

<!– People tracking –>

<include file="$(find 
spencer_people_tracking_launch)/launch/tracking/people_tracking.launch">

<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 
we are not using laser, tracks may get deleted too quickly in case of missed 
detections.

To deal with this, for the moment, we increase the maximum number of occluded 
frames to be a bit more tolerant towards missed detections.

This works fine in uncrowded environments which are not very dynamic. –>

<rosparam 
param="/spencer/perception_internal/people_tracking/srl_nearest_neighbor_tracker/max_occlusions_before_deletion">50</rosparam>

<rosparam 
param="/spencer/perception_internal/people_tracking/srl_nearest_neighbor_tracker/max_occlusions_before_deletion_of_mature_track">200</rosparam>

<!– Group tracking –>

<include file="$(find 
spencer_people_tracking_launch)/launch/tracking/group_tracking.launch"/>

<!– RViz visualization –>

<node name="tracking_visualization_rviz" pkg="rviz" type="rviz" args="-d $(find 
spencer_people_tracking_launch)/rviz/ tracking-single-rgbd-sensor.rviz " if="$(arg 
visualization)"/ >

ROS launch文档介绍相关推荐

  1. 本篇文档介绍如何手动在ECS实例上部署Java web项目

    本篇文档介绍如何手动在ECS实例上部署Java web项目.适用于刚开始使用阿里云进行建站的个人用户. 项目配置 { .section} 本篇教程在示例步骤中使用了以下版本的软件.操作时,请您以实际软 ...

  2. 1、ABP 文档介绍

    ABP 文档介绍 Quick Start Getting Started Architecture Infrastructure ABP是一个开源且文档友好的应用程序框架.ABP不仅仅是一个框架,它还 ...

  3. 标准的VESA文档介绍

    标准的VESA文档介绍    来源:中国自学编程网   发布日期:2007-05-12      概述:      该标准提供一系列应用程序能够使用的函数集.      1.获取某一指定超级VGA设备 ...

  4. Linux SDIO WIFI Marvell8801/Marvell88w8801(一) --- 代码及文档介绍

    代码工程的GITHUB连接:点进进入GITHUB仓库 https://github.com/sj15712795029/stm32f1_marvell88w8801_marvell8801_wifi ...

  5. 【2】PRD文档介绍

    首先,我想说,题主是一个不严肃的人(严肃脸),所以每次干个啥事之前我都喜欢唠唠嗑,说说废话,沟通沟通感情,曾经以为自己将会成为一个幻想中的产品经理那般大展身手,作为非计算机专业出身的应届生,后来才发现 ...

  6. CARLA传感器详细文档介绍+python实例(持续更新ing)

    CARLA中有两种类型的传感器:每帧都工作的传感器(相机,点云等)和只有特定环境下才接收数据的传感器(触发检测).都属于carla.Sensor类,从carla.BlueprintLibrary类中实 ...

  7. PRD(产品需求说明文档)与MRD(市场需求文档)介绍

    文章目录 目录 一.PRD(产品需求文档) 1.确定PRD文档格式 2.确定项目概述 3.项目功能描述 4.产品经理的思维体现在这几个方面: 5.大厂PRD常见规范: 6.PRD的最终目的: 二.MR ...

  8. Hi3798M V200 SDK文档介绍

    目录 下载SDK并解压 解压后主要的文件夹 下载SDK并解压 步骤1:下载Hi3798M V200 SDK. 大家如果有下载路径可以直接下载,如果没有的话可以使用我这个路径. 链接:https://p ...

  9. 百度分享插件实现方法以及详细文档介绍

    百度分享插件使用方法:复制div到页面对应位置即可 <div class="bdsharebuttonbox"><a href="#" cla ...

最新文章

  1. 主流浏览器js 引擎内核市场份额attialx总结vOa9
  2. 如何查看 phtml文件 并有代码颜色提示
  3. 2012百度之星冬季赛第二场第二题 消去游戏I
  4. 带有AngularJS资源的Spring Rest Controller
  5. 【Breadth-first Search 】752. Open the Lock
  6. linux 直接映射 页表大小,linux 启动过程临时页表到底映射了多大内存?
  7. element table表格里的多选按钮,根据条件判断是否可以被选中
  8. Android+Jquery Mobile学习系列(3)-创建Android项目
  9. python征程3.1(列表,迭代,函数,dic,set,的简单应用)
  10. 数据结构-----双向链表笔记
  11. 六石管理学:谈管理的前提,要有一点的胸量
  12. 软考--软件设计师--下午题数据库设计
  13. abaqus中python怎么建立参考点_怎么在abaqus中选定中心为参考点
  14. WSO2身份服务中的关键概念一: 单点登录与身份联合
  15. 微信公众平台php开发包
  16. 基于ZYNQ的开源CANopen协议栈CANFestival移植
  17. 阿里云全站加速是什么?与CDN有什么区别
  18. SQL必知必会 - 创建表的联结
  19. vant 引进单个样式_记一次webpack打包样式加载问题
  20. 遗忘线代知识,导致应力第三不变量对应力的导数求不出来

热门文章

  1. JS 判断手机操作系统代码
  2. Android端实时音视频开发指南
  3. SaaS窘境[欣赏然后翻译之]
  4. WF4.0 基础篇 (二十九) WorkflowInspectionServices
  5. [Java]中[this][super]用法总结
  6. Java学习笔记12——JVM入门
  7. ihtml2document能不能根据id获取dom_一段监视 DOM 的神奇代码
  8. 操作系统进程调度先来先服务FCFS
  9. ext4fs error mysql_请教一个 Linux 挂在磁盘阵列报错 EXT4-fs error 问题
  10. 一个项目部署多个节点会导致锁失效么_Redis分布式锁