ROS文件系统
ROS文件系统中的两个最基本的概念:Package和Manifest,即包和清单文件。
(1)Package是组织ROS代码的最基本单位,每一个Package都可以包括库文件,可执行文件,脚本及其它的一些文件。
(2)Manifest文件是对Package的相关信息的一个描述。他提供了Package之间的依赖性,以及一个包的元信息,比如版本、维护着和许可证等信息。
catkin 编译构建系统的功能包 ——编译产生的可执行文件并未存放在功能包目录下,而是存放在一个单独的标准化目录层次结构中。对于使用 apt-get 安装的功能包,其所在根目录为/opt/ros/indigo。可执行文件存储在这个根目录下的 lib 子目录里。同样,在自动生成的头文件存储在 include 子目录下。当有需要时,ROS通过搜索 CMAKE_PREFIX_PATH 环境变量列出的目录,这个环境变量由 setup.bash 自动设置。
注意:你有可能在一些文档中看到功能包集( stack)的概念。功能包集是紧密相关的功能包的集合。从ROS的 groovy版本开始,功能包集的概念被逐步淘汰,取而代之的是元功能包( metapackages),元功能包像其他功能包一样有功能包清单,但其目录下没有其他的功能包,而功能包集则将其包含的功能包存放在其目录下。
节点管理器(The Master)
ROS 的一个基本目标是使机器人的很多节点node(可执行文件,几乎相对独立的小程序)能够同时运行。为此,这些节点必须能够彼此通信。ROS 中实现通信的关键部分就是ROS 节点管理器。要启动节点管理器,使用如下命令:roscore 。节点管理器应该在使用 ROS 的全部时间内持续运行。一个合理的工作流程是在一个终端启动roscore,然后打开其他终端运行其他程序。当结束时可以通过在 roscore 终端键入Ctrl-C 停止节点管理器。如果roscore 被终止,当前运行的其他节点将无法建立新的连接,即使 稍后重启 roscore 也无济于事。
roslaunch 是个启动文件,其目的是一次性启动多个节点。每一个启动文件都应该和一个特定的功能包关联起来。通常的命名方案是以.launch 作为启动文件的后缀。这是一个自适应工具,如果启动多节点时没有节点管理器运行,它会自动启动节点管理器;如果已经有一个节点 管理器在运行,则会使用已有的。rosrun 一次只能启动 一个节点,而 roslaunch 可以同时启动多个节点。一般launch文件会放在功能包的根目录中。
节点(Nodes)
一旦启动roscore后,便可以运行ROS程序了。 ROS程序的运行实例被称为节点(node) ,例如 rosrun turtlesim turtlesim_node 这个节点是可执行文件 turtlesim_node 的实例化,负责创建 turtlesim窗口和模拟海龟的运动。可以看出rosrun 命令有两个参数,其中第一个参数是功能包的名称,第二个参数是该软件包中的可执行文件的名称。还要注意的是通过节点管理器注册成为 ROS 节点发生在程序的内部,而不是通过 rosrun 命令。
启动roscore后运行rosnode list 可以看到出现节点/ rosout 。rosout 节点是一个特殊的节点,通过 roscore 自动启动。其作用有点类似于控制台程序中使用的标准输出(即 std::cout)。
/rosout也是话题,所有的节点发布都向话题/rosout 发布消息,该话题由同名的 /rosout 节点订阅。这个话题的作用是用来生成各个节点的文本日志消息。在某些地方/rosout 既指节点又指话题。但 ROS 并不会这种重复的名字而混淆,因为 ROS 会根据上下文来推测我们讨论的是/rosout节点,还是/rosout话题。
举个例子来说明也许会更好,这个例子将在话题和消息里说明。
读者还要注意的是rosrun 命令中可执行文件的名称与节点名称并不一定相同。节点名称是在代码中命名的例如ros::init (argc, argv, "odom");而可执行文件名称是在CMakeLists.txt中命名的。但可以使用 rosrun 命令显式设置节点的名称,语法如下:rosrun package-name executable-name _ _name:=node-name 这种方法将使用 node-name 参数给出的名称覆盖节点的默认名。因为 ROS 中要求每个节点有不同的名称,因此该方法很重要尤其是移植程序中。
话题和消息
ROS节点之间进行通信所利用的最重要的机制就是消息传递。在ROS中,消息有组织地存放在话题里。消息传递的理念是:当一个节点想要分享信息时,它就会发布(publish)消息到对应的一个或者多个话题;当一个节点想要接收信息时,它就会订阅(subscribe)它所需要的一个或者多个话题。ROS节点管理器负责确保发布节点和订阅节点能找到对方;而且消息是直接地从发布节点传递到订阅节点,中间并不经过节点管理器转交。
查看节点构成的计算图:先介绍个工具rqt_graph,要查看节点之间的连接关系,恐怕将其表示为图形是最便于查看的。在ROS 系统中查看节点之间的发布-订阅关系的最简单方式就是在终端输入如下令:rqt_graph。r 代表ROS,qt 指的是用来实现这个可视化程序的Qt 图形界面(GUI)工具包。
在该图中,椭圆形表示节点,有向边表示其两端节点间的发布-订阅关系。该计算图告诉们,/teleop_turtle节点向话题/turtle1/cmd_vel发布消,而/turtlesim 节点订阅了这些消息(“cmd_vel”是“command velocity”的缩写)。但是其中省略了调试节点,包括 rosout 节点,这是因为在默认情况下,rqt_graph 隐藏了其认为只在调试过程中使用的节点。你可以通过取消“Hide debug”选项来禁止这个特性,下图是完整的:
请注意 rqt_graph 本身就是一个节点。所有的节点发布都向话题/rosout 发布消息,该话题由同名的 /rosout 节点订阅。正如之前讲过的,这个话题的作用是用来生成各个节点的文本日志消息,此处的名称/rosout 既指节点又指话题。但 ROS 并不会因这种重复的名字而混淆,因为 ROS 会根据上下文来推测我们讨论是/rosout 节点还是/rosout 话题。
与ROS服务不同,ROS 节点通常设计成了只管发布它们有用的信息,而不需要担心是否有其他节点来订阅
这些消息。这样有助于减少各个节点之间的耦合度。