移动机器人开发流程

在机器人操作系统ROS环境中,无论是移动机器人还是其他类型的机器人,那这个流程是什么样的呢?我们先来了解一下:

图1 ROS机器人开发的主要流程

这里我们直接给出ROS机器人开发的主要流程,共分为五个步骤。

  • 第一步,类似于我们使用任何软件写代码之前,都需要进行的一个步骤,建立工程,也就是new project。在ROS开发中,这一步叫做创建工作空间,也就是保存后续开发工作涉及到所有文件的一个空间,在计算机中的体现其实就是文件夹,未来开发用到的文件都会保存在这个文件夹中。
  • 第二步,是在工作空间中创建写代码用的功能包,类似我们在其他软件写代码时,会把同一功能的多个代码文件放置在一个文件夹中,这个文件夹在ROS中叫做功能包,每个功能包就是实现机器人某一功能的组织单元,多个功能包就组成了机器人应用的代码库。
  • 第三步是最重要的一步,也就是写代码,ROS开发常用的编码方式是C++和Python,无论我们使用哪种语言编写代码,都需要将代码放置在功能包中。
  • 第四步,C++代码需要编译,我们需要在功能包的CMakeLists.txt文件中设置如何编译代码的规则,python代码就不需要编译了,可以跳过这一步。
  • 第五步,也就是最后一步,我们把整个工程,也就是工作空间编译,将代码变成可执行文件,编译成功后就可以开心的运行了,假设运行出现问题,有可能就要回到代码编写的这一步,修改代码后再次编译运行,直到功能全部正常。

了解了这五个步骤的主要目的,接下来我们就可以按照以下步骤来操作一下。


一、工作空间的创建和编译

创建工作空间:

$ mkdir -p ~/catkin_ws/src

$ cd ~/catkin_ws/src

$ catkin_init_workspace

编译工作空间:

$ cd ~/catkin_ws/

$ catkin_make

设置环境变量:

$ source ~/catkin_ws/devel/setup.bash

检查环境变量:

$ echo $ROS_PACKAGE_PATH

以上是工作空间创建和编译的流程。接下来我们来一步一步操作下。

首先我们先来创建工作空间,工作空间的创建方式有两种,第一种就是以上按照命令的方式进行创建,首先我们先来一个终端,输入以下命令行,就可以完成两个文件夹的创建,如图3所示,这里catkin_ws是默认工作空间创建的名字,大家也可以自己定义,里面src文件夹主要放置未来我们的功能包,也就是代码空间,这个命令大家需要注意一下,src是不能随便进行修改的,一定要用src这个三个字母组成的名字,以上就是一个最基本的工作空间创建方法。

$ mkdir -p ~/catkin_ws/src 

图2 创建文件夹

图3文件夹创建成功

为了能让它具备工作空间的属性,我们还需要去进入它的src文件夹下面,用catkin_init_workspace这个指令把当前整个文件夹初始化为一个ROS里面的工作空间,让它具备工作空间的属性。也就是在src文件夹里面创建一个CMakeList.txt文件,这个文件也就是表示当前文件夹是ROS里面的一个工作空间。

通过上面操作,第一个工作空间就已经创建完成。

$ catkin_init_workspace 

图4初始化工作空间

图5 CMakeList.txt文件

大家如果觉得第一种创建工作空间的方法比较麻烦,就可以采用第二种方法,直接在home下面右键进行创建一个新的文件夹,命名为catkin_ws,双击进入后再进行创建一个文件夹,命名为src,进入src文件夹后,右键打开终端输入以下命令进行初始化工作空间,如图7所示。

$ catkin_init_workspace 

注意:初始化工作空间命令是可选的,后续在编译功能包的时候也会默认进行初始化。

图6 catkin_ws和src文件夹

图7 初始化工作空间

以上我们就完成了开发流程中的第一步创建工作空间,但里面还没有任何的代码和功能包,那接下来我们就来学习下如何去编译工作空间。

在未来,我们的代码会放置在src里面,接下来要编译代码就需要在工作空间的根目录下去进行编译,进入工作空间根目录后点击右键打开终端,输入如下命令进行编译空间。

$ catkin_make 

 图8 编译工作空间

编译完成后,会新生成两个文件夹,如图7-9所示,分别是build和devel文件夹,build是编译空间,主要用来放置编译的中间文件,devel是开发空间,主要来放置我们编译完成后的结果、程序的头文件、库等,另外src是代码空间,主要用来放置我们的源代码。 

图9 build、devel、src文件夹

图10 devel文件夹 

图11 build文件夹

以上就是我们工作空间中的三个子空间,空间这个概念,其实就是文件夹,也就是三个放置不同目的文件的文件夹。

当功能包编译完成后,我们就去需要设置环境变量,也就是在我们的工作空间里会开发很多功能,生成一些可执行文件,当我们后续去运行这些功能包和可执行文件时从哪去找系统我们并不知道,所以我们需要去设置环境变量,让Ubuntu知道我们的功能包和工作空间在哪个路径下面,未来在运行rosrun、roslaunch的时候就可以找到对应路径,所以环境变量的设置也就是让Ubuntu知道当前功能包、开发内容的位置,打开终端,输入如下命令即可设置环境变量。

$ source ~/catkin_ws/devel/setup.bash

图12 设置环境变量

但是sorce这样一个指令只在当前终端生效,如果终端关闭就没有效了,所以我们需要放置到bashrc里面,输入指令,打开bashrc,如图13所示,在该文件里把对应的工作空间、变量放置进来,在文件最后的位置加上对应指令,如图14所示,添加完成后保存并退出。

图12 bashrc

图13 bashrc

图14 bashrc指令添加

然后在终端里面进行source脚本,让脚本在当前终端里面立刻生效。或者关闭当前终端,重新打开终端也可以重新运行所有的脚本。

图15 source脚本

如果想要验证之前设置的环境变量有没有生效,就可以输入如下命令进行验证,如图16所示,环境变量里面保存的就是我们所有ROS功能包的路径,未来运行功能包的时候就会通过该路径查找我们的功能包。如果大家未来发现运行功能包的时候会报错,反应找不到路径等,就可能是我们环境变量没有设置,Ubuntu根本不知道去哪里找功能包。

$ echo $ROS_PACKAGE_PATH

图16 环境变量验证


二、创建功能包

开发流程的第二步,是创建功能包,创建过程需要使用ROS的一个命令——catkin_create_pkg。

这个命令后边紧跟的第一个参数是要创建的功能包名字,再之后的参数就是该功能包需要依赖的其他功能包,一般是各种ROS提供的代码库、消息定义库或者需要用到的其他功能包,比如这里的rospy和roscpp分别对应python和C++语言的ROS接口库,std_msgs、std_srvs是ROS官方定义的各种标准话题和服务消息,比如整型数、浮点数、字符串等基础消息类型。

$ catkin_create_pkg <package_name> [depend1] [depend2] [depend3]

这句指令输入完成后,就创建好了一个功能包,之后就可以在里边愉快的写代码了。这里需要强调一点,在同一个工作空间中,不允许创建两个同名的功能包,不然就会冲突报错,毕竟我们运行的时候都是通过功能包找到可执行文件的,如果两个包名字一样,系统就不知道该选谁了。

代码写完之后的编译任务,需要使用catkin_make这个指令,就类似其他开发环境中的“Build All”按键,输入之后,就可以把工作空间里所有功能包的代码一次性编译完成了。

创建功能包:

$ cd ~/catkin_ws/src

$ catkin_create_pkg limo_demo rospy roscpp std_msgs std_srvs

编译功能包:

$ cd ~/catkin_ws

$ catkin_make

$ source ~/catkin_ws/devel/setup.bash

接下来,我们来熟悉操作这里的一系列指令。

首先,我们先进入到src里面,右键打开终端,输入如下命令来创建功能包,如图7-17所示。

$ catkin_create_pkg limo_demo rospy roscpp std_msgs std_srvs

图17 创建功能包

创建完成后,会显示很多日志信息,表明我们已经创建了对应的功能包,可以看到新生成了几个文件夹,如图18所示,其中CMakeList.txt文件是用来后续设定一些编译规则的文件,如图19所示,package.xml是用来编写功能包相关的描述内容,核心目的告诉我们功能包的一些基本信息,如图20所示。后续我们的代码开发也可以放置到src文件夹下面,单独创建文件夹放置代码也是可以的。

图18创建功能包完成 

图19 CMakeList.txt文件

图20 package.xml

功能包创建完成后,我们就可以回到根目录进行编译功能包,打开终端,输入如下命令进行编译功能包。

$ catkin_make

图21 编译功能包

ROS的工作空间中,功能包不仅不能重名,还不能嵌套,比如把一个功能包放在另外一个功能包中,编译就会报错,但是文件夹是可以嵌套的,比如把一些同样类别的功能包放在一个文件夹中,是允许的。

那如何判断一个文件夹到底是普通文件夹,还是功能包呢,就是看它有没有上面我们介绍到的CMakeList.txt和package.xml两个文件,如果有的话,就是功能包,没有的话,就是文件夹,大家需要记住这一点。