ROS系统学习2---ROS最小系统的制作

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/oHanTanYanYing/article/details/83026236

上一篇文章我们讲了ros的安装,并且运行了ros自带的一个简单程序。

下面,我们将从一个空的文件夹开始,一步步创建工作空间,包,和节点,并让该节点输出“Hello ros”。

本文主要参考这篇文章,部分内容基本照抄(哈哈哈哈,链接的文章已经写的很好了,本人只是习惯把别人实现的东西重现出来再写一下自己的体会),故在此说明下。

在开始之前,先看看ros的几个重要概念。

node(节点)

node是ROS里面最小的执行单位,你可以把node看成是一个main函数,当你启动一个node,就相当于启动了一个main函数,通常这个main函数会不停循环监听某个消息,或者执行一系列操作,直至你关闭它,或者执行完退出。

从上面的描述基本可以看出,其实ros系统就是一套管理多个进程的系统。打个比方,就像是电脑上运行了QQ和微信,然后腾讯突然脑洞大开做了个管理程序把它们管理了起来,让它们可以互相通信,被同时打开或关闭之类的。

package(包)

package是ROS里面最小的编译单位,也是ROS里面的搜索单位,你可以把package看成是一个有结构的文件夹,它包含多个node以及一些结构性质文件。ROS里面的node,是以package为单位进行编译的,一次编译package里面多个node。

通常一条ROS的node执行命令具有以下结构:

rosrun <package_name> <node_name>

即执行某个node的时候,要标识这个node是属于哪个package的,ROS会先通过package的名字检索到package,再通过node名字找这个package下对应的node去执行。

从描述上看,包相当于我们通常用的程序的文件夹,比如在Windows上我们装QQ这个软件,虽然我们运行的是exe文件,但如果去看它的安装目录,就会发现里面有很多dll之类的东西,如果离开了这些,则exe是运行不起来的。而且如果我们发神经装了一堆QQ,则有时候只能通过文件夹的不同来区分我们要打开的到底是哪一个。

workspace(工作空间)

首先思考一个问题:package都被放在什么地方?

package存在于两个地方。一个是ROS库,即你安装ROS的地方,通常在 opt/ros/<distro>/share/ (<distro>指你的ROS版本,如hydro, groovy)里面(hydro以前的版本还会有stack),你无需关心,这些都是从ROS远程仓库下载下来的。另外一个地方,就是我们自己建的workspace了,我们自己的package,或者网上下载的别人的package都必须放在workspace里面编译,才可以使用。

workspace是ROS里面最小环境配置单位,你可以把workspace看成是一个有结构的文件夹,它包含多个package以及一些结构性质文件。将一个workspace配置进环境变量里面,你才能使用ROS命令执行与这个workspace里面的package相关的操作。

我想这个概念是程序猿初学者最难理解的一个了。但其实很简单,看下面这个命令

rosrun <package_name> <node_name>

我们可以简单的看到ros在调用包里面的内容的时候通常只需要写一个包的名字就可以了。这个时候,假设你很随意的把包扔在了某个神秘的文件夹下,你要他去哪里找这个包。因此让你统一把包扔在一个地方是非常合理的。另外,结合我们上面“节点”那一段所描述的内容,ros本质上是一个管理多进程的管理程序,假设管理的这些程序这里来一下那里来一下显然很要命。

build system(系统创建)

前面提到的package和workspace都是有结构的,那么这些结构到底是怎么规定的呢?

这些结构,就是由build system(编译系统)规定的。当你运行workspace相关的命令,它会在一个你指定的空文件夹下面放很多功能性质的文件,并将这个空文件夹变成一个workspace。当你运行package相关的命令,它会在你指定的路径下面创建出package。

目前,ROS的build system有两种,一种叫做catkin,另外一种叫做rosbuild。利用不同的build system创建出来的workspace和package因此也分为两种。

rosbuild是ROS传统的编译系统,从最初沿用至今,但面临被抛弃的状态。catkin源于ROS fuerte,当时只是被一小部分人使用,在fuerte的下一个版本groovy开始被正式使用,用于取代rosbuild。为什么要用catkin取代rosbuild?当然是因为catkin比rosbuild好很多,在实际应用过程中会感受到的,具体理由可以看看这个 [catkin_conceptual_overview] 。基于catkin编写的package叫做wet package,基于rosbuild编写的package叫做dry package,在ROS相关的问答里面会常常看到这种说法的。

这个就没啥说的了,本质上来说就是做各种条条框框的规定,相当苹果的接口,不管你是什么东西要连上去一定要满足它的协议,不然就没得玩。而ros的build system可以帮你生成这些东西,你就可以不用自己去搞了,省心。

另外不同版本的build system也可以类比苹果的雷电接口和以前那个很扁很长的接口,虽然两者都可以传数据,但历史的潮流把很扁很长的那个扔进了垃圾桶!本文后面用的是历史的潮流,不是会被扔进垃圾桶的那个。

source setup.bash(登记)

在workspace部分介绍了package存在的两个地方,那么,是不是我们打开terminal,就能使用ROS命令,系统就能找到那些package呢?

这里,就要了解 source setup.bash 的功能。 source setup.bash 就是执行 setup.bash 脚本,而这个脚本,就会在环境中配置一些数据。

通常我们安装完ROS后,要先 source /opt/ros/<distro>/setup.bash ,这条语句的目的就是将ROS相关的命令配置在当前terminal工作的环境中,我们在这个环境中就能使用ROS命令了,否则系统是无法知道ROS命令的存在的。同时,这条语句也会让ROS库中的package能够被找到。

当我们创建一个workspace后,同样系统也是不会知道这个workspace存在的,一切与这个workspace相关的ROS命令都会失效——这个workspace里面的package不会被ROS命令发现。要想将这个workspace的信息配置到环境里面,就必须执行这个workspace里面的 setup.bash 脚本,例如catkin的就是 source ~/catkin_ws/devel/setup.bash ,rosbuild的就是 source ~/rosbuild_ws/setup.bash 。

这个就是告诉linux操作系统,我们有个ros系统,系统在这个位置有个空间,空间里面有个包,这些包应该怎么样怎么样。如同公安局的户口登记,如果家里生了个小孩,也要去那边说一声。

overlay(选择覆盖逻辑)

再来思考一个问题:你有一个或者多个catkin workspace,同时你也有一个或者多个rosbuild workspace;而某个名字叫example_package的package在ROS库,在每个workspace里面都存在,当你运行 rosrun example_package example_package 的时候,到底会运行哪个位置的example_package呢?

这就关系到overlay的概念。overlay就是一种操作,可以让不同的workspace层层覆盖,最底层的是ROS库。通过这种覆盖关系,当寻找某个package的时候,ROS会先从顶层的workspace找,如果找不到再依次往下找。也可以看成是一个路径链条,当我们想把通过overlay链接起来的workspace和ROS库的路径配入环境的时候,我们只需要source overlay链条顶层的workspace的setup.bash脚本即可。

个人感觉用不上,除非做一个非常庞大的系统,然后用了很多自己都不知道的东西才会有覆盖问题。但要十分注意的是,一旦出现了这样的问题,然后还在此产生错误,调试的难度是极大的,不要问我为什么知道的。。。


好了,上面介绍了ros的6个概念。说实话,本来看了一些书和别的文章,对ros一知半解的,但看完这些概念的解释后豁然开朗。如果您是和我一样的初学者,建议仔细体会这几个概念。

下面我们来创建工作空间

首先创建文件夹(不管你用命令行还是图像界面创建的都可以,Linux上很多人喜欢用命令行,而本人比较喜欢直接操作),名称为“HelloRos”。然后在文件夹中再创建一个次级文件夹名称为“src”。

接下来我们把终端cd到“src”的路径下(当然右键直接在该文件夹下打开终端“在终端打开(T)”显然更方便),输入下面的命令:

catkin_init_workspace

得到如下所示输出

该命令的作用是初始化工作空间,指定src路径是package存放的路径,为后面工作空间的真正生成做准备。

可以看到在“src”路径下生成了一个“CMakeLists.txt”文件,里面就记录了所以相关的信息。

接下来cd到“HelloRos”路径下,输入下面的命令

catkin_make

该命令编译并生成整个工作空间,并编译“src”文件夹下的所有“package”(当然我们现在还没有包,但可以知道的信息就是,我们的包要存放在工作空间的“src”文件夹下面)

经过上面的操作,我们已经创建了工作空间,但该空间还没有备案,也就是上面所说的孩子出生还没去公安局登记一波,因此操作系统或者ros系统不知道还有这事。下面的命令则会帮我们完成这个工作。

有两种方式,第一种为当前终端有效:

source ~/HelloRos/devel/setup.bash

第二种为永久有效:

sudo gedit .bashrc

把source ~/HelloRos/devel/setup.bash加到文档的最后面,搞定!

好了,到此工作空间的创建就结束了。当然,里面毛都没有,我们需要接着往下走,创建一个包,然后在包里面放一个节点来输出“HelloRos”。

我们需要做的是,先cd到“src”文件夹下面,然后用ros提供的命令创建一个叫做“printHelloRosPK”的包。具体的命令如下:

catkin_create_pkg printHelloRosPK std_msgs rospy roscpp

第二个参数是包名,第三个到第五个则是依赖库,如果我们只想用C++来编写,则第四个参数就可以不要了。变成下面这样:

catkin_create_pkg printHelloRosPK std_msgs roscpp

运行结果如下:

到此,我们就空间有了,包也有了。但包里面还没内容,只是一个空包。

我们在包里面的“src”文件夹(注意,是包里面的src,也就是我们刚刚运行命令之后ros帮我们建的那个src)下新建并编写一个节点。具体的就是建一个叫做"printHelloRosPK.cpp"的文件,然后写入如下的代码:

#include <ros/ros.h>
int main(int argc, char **argv)
{
    ros::init(argc,argv,"printHelloRosPK");//初始化ros系统,注意这里的printHelloRosPK是节点的名称,不要搞成别的
    ros::NodeHandle n;//创建一个ros节点
    ROS_INFO("Hello ROS");//打印信息,类似于printf,但据说强很多
    ros::spinOnce();//消息回调处理函数,也就是系统等在这里,直到有回调消息进入,当然在我们这个程序中它永远等不到,只是习惯性的写一下
}

到此,我们节点的描述代码也有了。然而因为这个东西是我们自己创建的,ros的包还不知道它里面竟有此物,因此需要告诉它。具体的操作就是在包文件夹下:

找到“CMakeList.txt”文件,告诉它我们弄了个东西在你的“src”里面,你要去编译它。操作就是在文件的最后面加上:

add_executable(printHelloRosPK /home/weixin/HelloRos/src/printHelloRosPK/src/printHelloRosPK.cpp)
target_link_libraries(printHelloRosPK ${catkin_LIBRARIES})

到此基本完成,回到我们的工作空间,然后再次编译一波(我们之前编译的是空包,现在可是有内容的包,哈哈哈)

catkin_make

结果如下:

大功告成,接下来把该节点运行起来就可以了:

在一个终端输入:

roscore

另一个终端输入:

rosrun printHelloRosPK printHelloRosPK

则会得到“Hello ROS”

搞定收工~!

下篇文章,我们将介绍:ROS最小话题系统的制作


 

 

 

猜你喜欢

转载自blog.csdn.net/oHanTanYanYing/article/details/83026236