目录

ROS 元功能包

1、新建launch文件

launch文件标签之node

launch文件标签之include

launch文件标签之param

launch文件标签之rosparam

launch文件标签之group

launch文件标签之arg

ROS工作空间覆盖

ROS是多进程(节点)的分布式框架,一个完整的ROS系统实现:

可能包含多台主机

每台主机又有多个工作空间(workspace)

每个的工作空间又包含多个功能包(package)

每个功能包又包含多个节点(Node),不同节点都有自己的节点名称

每个节点可能还会设置一个或者多个话题(topic)

ROS 元功能包

场景:完成ROS中的一个系统性功能、可能涉及到多个功能包,比如实现了机器人导航模块,该模块下有地图、定位、路径规划...等不同的子集功能包。那么调用者安装该模块时,需要逐一的安装每一个功能包吗?

显而易见,逐一安装功能包的效率低下,在ROS中,提供了一种方式可以将不同的功能包打包成一个功能包,当安装某个功能模块时,直接调用了打包后的功能包即可,该包又称之为元功能包。

概念

MetaPackage是Linux的一个文件管理系统的概念。是ROS中的一个虚包,里面没有实质性的内容,但是它依赖了其他的软件包,通过这种方法可以把其他包组合起来,我们可以认为它是一本书的目录索引,告诉我们这个包集合中有哪些子包,并且该去哪里下载,

例如

  • sudo apt install ros-noetic-desktop-full命令安装ros时就使用了元功能包,该元功能包依赖于ROS中的一些其他功能包,安装该包时会一并安装依赖。

还有一些常见的MetaPackage:navigation moveit!turtlebot3

作用:方便用户的安装,我们只需要这一个包就可以把其他相关的软件包组织到一起安装了

实现

首先:新建一个安装包

然后,修改package.xml,内容如下:

<exec_depend>被集成的功能包</exec_depend>

.....

<export>

<metapackage/>

</export>

最后修改:CMakeLists.txt,内容如下;

cmake_minimum_required(VERISON 3.0.2)

project(demo)

find_package(catkin REQUIRED)

catkin_metapackage()

PS:CMakeLists.txt中部可以有换行

另请参考官网的ROS WIKI:http://wiki.ros.org/catkin/package.xml#Metapackages

ROS节点运行管理launch文件

关于launch文件之前已经提过了,一个程序中可能需要启动多个节点,比如:ROS内置的小乌龟案例,如果要控制乌龟运动,要启动多个窗口,分别启动roscore、乌龟节点、键盘控制节点。如果每次都调用rosrun逐一启动,显然效率低下,如何优化?

采用的优化策略就是使用launch命令集合launch文件启动管理节点,并且在后续教程中,也使用到了launch文件

概念

launch文件是一个xml格式的文件,可以启动本地和远程的多个节点,还可以在参数服务器中设置参数

作用

简化节点的配置与启动,提高ROS程序的启动效率。

使用

以turtlesim为例演示

1、新建launch文件

在功能包下添加launch目录,目录下新建launch文件,编辑launch文件

<launch>

<node pkg= "turtlesim" type= "turtlesim_node " name = "myTurtle" output=“screen”/>

<node pkg = "turtlesim" type="turtle_teleop_key" name ="nyTurtleContorl" output="screen"/>

</launch>

调用launch文件

roslaunch 包名 xxx.launch

注意:roslaunch命令执行launch文件时,首先会判断是否启动了roscore,如果启动了,则不在启动,否则,会自动调用roscore

launch文件标签之launch

<launch>标签是所有launch文件的根标签,充当其他标签的容器

  • 属性

deprecated=“弃用声明”
告知当前用户当前的launch文件已经启用, 不建议使用

子集标签

所有其他标签都是launch的子级

launch文件标签之node

<node>标签用于指定ROS节点,是最常见的标签,需要注意的是:roslaunch命令不能保证按照node的声明顺序来启动节点(节点的启动是多进程的)

属性

  • pkg=“包名” 节点所属的包
  • type=“node Type”节点类型(与之相同名称的可执行文件)
  • name="nodeName"节点名称(在ROS网络拓扑中节点的名称)
  • args="xxxx xxx xxx"(可选)将参数传递给节点
  • machine="机器名" 在指定机器上启动节点
  • repawn="true|false"(可选)如果节点退出,是否自动重启
  • repawn_delay="N"(可选)如果respawn为true,那么延迟N秒后启动节点
  • required="true | false"该节点是否必须,如果为true,那么如果该节点退出,将杀死整个roslaunch
  • ns=“xxx”(可选)在指定命名空间xxx中启动节点
  • clear_params="true|false"(可选)再启动前,删除节点的私有空间的所有参数
  • output=“log|screen”(可选)日志发送目标,可以设置为log日志文件,或者screen屏幕,默认是log

子级标签

  • env环境变量设置
  • remap重映射节点名称
  • rosparam参数设置
  • param参数设置

launch文件标签之include

include标签用于将另一个xml格式的launch文件导入到当前文件

属性

  • file=“$(find 包名)/xxx/xxx.launch”  要包含的文件路径
  • ns="xxx"(可选)在指定命名空间导入文件

子级标签

  • env环境变量设置
  • arg将参数传递给被包含的文件

launch文件标签之remap

用于话题重命名

属性

  • from="xxx"  原始话题名称
  • to="yyy"     目标名称

子级标签

launch文件标签之param

<param>标签主要用于在参数服务器上设置参数,参数源可以在标签中通过value指定,特可以通过外部文件加载,在<node>标签中时,相当于私有命名空间

属性

  • name=“命名空间/参数名”

参数名称,可以包含命名空间

value="xxx"(可选)

定义参数值,如果此处省略,必须指定外部文件作为参数源

type=“str|int|double|bool|yaml”(可选)

指定参数类型,如果未指定,roslaunch会尝试确定参数类型,规则如下:

如果包含‘.’的数字解析为浮点型,否则为整型

”true“和”false”是bool值(不区分大小写)

其他是字符串

子级标签

launch文件标签之rosparam

<rosparam>标签可以从YAML文件导入参数,或将参数导出到yaml文件,也可以用来删除参数,<rosparam>标签在<node>标签中时被视为私有

属性

command=“load | dump | delete”(可选,默认为load)

加载、导出或删除参数

file="$(find xxxxx)/xxx/yyy..."

加载或导出到yaml文件

param=“参数名称”

ns=“命名空间(可选)”

子级标签

launch文件标签之group

<group>标签可以对节点分组,具有ns属性,可以让节点归属某个命名空间

属性

ns=“名称空间”(可选)

clear_params="true | false"(可选)

启动前,是否删除组名称空间的所有参数(慎用,此功能危险)

子级标签

除了launch标签外的其他标签

launch文件标签之arg

<arg>标签是用于动态传参,类似于函数的参数,可以增强launch文件的灵活性、

属性

name=“参数名称”

default=“默认值”(可选)

value=“数值”(可选)

不可以与default并存

doc=“描述”

参数说明

子级标签

示例

launch文件传参语法实现

<launch>

        <arg name="xxx"/>

        <param name = "param" value ="$(arg xxx)" />

</launch>

命令行调用launch传参

roslaunch hello.launch xxx:=值

ROS工作空间覆盖

所谓工作空间覆盖,是指不同工作空间中,存在同名的功能包的情形

ROS 开发中,会自定义工作空间且自定义工作空间可以同时存在多个,可能会出现一种情况: 虽然特定工作空间内的功能包不能重名,但是自定义工作空间的功能包与内置的功能包可以重名或者不同的自定义的工作空间中也可以出现重名的功能包,那么调用该名称功能包时,会调用哪一个呢?比如:自定义工作空间A存在功能包 turtlesim,自定义工作空间B也存在功能包 turtlesim,当然系统内置空间也存在turtlesim,如果调用turtlesim包,会调用哪个工作空间中的呢?

实现

0.新建工作空间A与工作空间B,两个工作空间都创建功能包:turtlesim

1.在~/.bashrc文件下追加当前工作空间的bash格式如下:

source /home/用户/路径/工作空间A/devel/setup.bash

source /home/用户/路径/工作空间B/devel/setup.bash

2.新开命令行source.bashrc加载环境变量

3.查看ROS环境变量echo $ROS_PACKAGE_PATH

结果:自定义工作空间B:自定义工作空间A:系统内置空间

4.调用命令:roscd turtlesim会进入自定义工作空间B

原因

ROS 会解析 .bashrc 文件,并生成 ROS_PACKAGE_PATH ROS包路径,该变量中按照 .bashrc 中配置设置工作空间优先级,在设置时需要遵循一定的原则:ROS_PACKAGE_PATH 中的值,和 .bashrc 的配置顺序相反--->后配置的优先级更高,如果更改自定义空间A与自定义空间B的source顺序,那么调用时,将进入工作空间A。

结论

功能包重名时,会按照 ROS_PACKAGE_PATH 查找,配置在前的会优先执行。

隐患

存在安全隐患,比如当前工作空间B优先级更高,意味着当程序调用 turtlesim 时,不会调用工作空间A也不会调用系统内置的 turtlesim,如果工作空间A在实现时有其他功能包依赖于自身的 turtlesim,而按照ROS工作空间覆盖的涉及原则,那么实际执行时将会调用工作空间B的turtlesim,从而导致执行异常,出现安全隐患。

BUG 说明:

当在 .bashrc 文件中 source 多个工作空间后,可能出现的情况,在 ROS PACKAGE PATH 中只包含两个工作空间,可以删除自定义工作空间的 build 与 devel 目录,重新 catkin_make,然后重新载入 .bashrc 文件,问题解决。