ubuntu16.04下ROS操作系统学习笔记(三 / 二)ROS基础-ROS通信编程

200
0
2021年2月16日 09时12分

1.话题编程

 

ubuntu16.04下ROS操作系统学习笔记(三 / 二)ROS基础-ROS通信编程插图

 

首先我们要有一个发布话题的Talker,还要有一个订阅话题的Listener,然后就是负责管理整个系统的ROS Master。

 

话题编程的流程主要是以下四个步骤:

 

  • 创建发布者
  • 创建订阅者
  • 添加编译选项
  • 运行可执行程序

 

上面的前两步是编程实现的,第三步是通过编译的方式生成可执行文件。最后一步就是去运行一下这个可执行的程序。

 

我们之前创建的功能包learning_communication里面是没有代码的:

 

ubuntu16.04下ROS操作系统学习笔记(三 / 二)ROS基础-ROS通信编程插图(1)

 

然后在这个文件下面创建一个talker.cpp文件

 

ubuntu16.04下ROS操作系统学习笔记(三 / 二)ROS基础-ROS通信编程插图(2)

 

里面的代码解释也非常清晰。通过句柄.advertise发布消息,里面需要传入发布消息的具体类型,以及队列的长度。

 

代码的流程如下:

 

  • 初始化ROS节点
  • 向ROS Master注册节点信息,包括发布的话题名和话题中的消息类型。
  • 按照一定频率循环发布消息。

 

有了发布者之后,我们接下来需要去定义一个订阅者,步骤如下:

 

  • 初始化ROS节点
  • 订阅需要的话题
  • 循环等待话题消息,接收到消息后进入回调函数。
  • 在回调函数里面完成消息处理。

 

源码如下:

 

ubuntu16.04下ROS操作系统学习笔记(三 / 二)ROS基础-ROS通信编程插图(3)

 

现在的话我们就已经写好了c++文件,我们需要对其进行编译,如果我们使用的是python文件的话,我们就不用对其进行编译了。编译代码主要有以下三个步骤:

 

  • 设置需要编译的代码和生成的可执行文件;
  • 设置链接库;
  • 设置依赖。

 

ubuntu16.04下ROS操作系统学习笔记(三 / 二)ROS基础-ROS通信编程插图(4)

 

在上面这个文件夹下面的CMakeLists.txt就是我们具体需要编译的选项的。接下来我们需要在这个文件下面设置我们需要编译的选项。在这个文件里面很多都是被注释掉了,我们很多时候去掉其中的注释然后再改一点就可以了,并不需要我们自己写。将代码生成可执行文件就是需要使用add_executable这个配置。

 

ubuntu16.04下ROS操作系统学习笔记(三 / 二)ROS基础-ROS通信编程插图(5)

 

这里我们在下面再粘贴一下:

 

ubuntu16.04下ROS操作系统学习笔记(三 / 二)ROS基础-ROS通信编程插图(6)

 

这里我们只需要看未被注释的,第一行的意思就是将talker.cpp生成可执行文件。如果需要更多的文件来生成可执行文件的话,需要在后面再多加几个c++文件。

 

因为我们需要依赖第三方的库,所以我们需要添加target_link_libraries来与第三方的库做一个链接。之后我们回到工作空间对其进行编译。

 

ubuntu16.04下ROS操作系统学习笔记(三 / 二)ROS基础-ROS通信编程插图(7)

 

编译成功之后就会有以下提示:显示达到1005并且没有报错的话就说明编译成功了。

 

ubuntu16.04下ROS操作系统学习笔记(三 / 二)ROS基础-ROS通信编程插图(8)

 

我们在下面这个文件里面就可以找到我们编译生成的可执行文件了。

 

ubuntu16.04下ROS操作系统学习笔记(三 / 二)ROS基础-ROS通信编程插图(9)

 

之后我们启动roscore

 

ubuntu16.04下ROS操作系统学习笔记(三 / 二)ROS基础-ROS通信编程插图(10)

 

再运行发送“hello world”可执行文件:

 

ubuntu16.04下ROS操作系统学习笔记(三 / 二)ROS基础-ROS通信编程插图(11)

 

再运行接收文件的话,就可以看到下面的结果:

 

ubuntu16.04下ROS操作系统学习笔记(三 / 二)ROS基础-ROS通信编程插图(12)

 

如果我们需要自己定义话题消息的话,我们可以采取以下方式自定义话题消息

 

string name

uint8 sex

unit8 age

unit8 unknown = 0

unit8 male = 1

unit8 female = 2

 

具体操作步骤如下:

 

  • 定义msg文件
  • 在package.xml中添加功能包依赖

 

<build_depend>message_generation</build_depend>

<exec_depend>message_runtime</exec_depend>

  • 在CMakeList.txt添加编译选项

接下来具体操作一下:

首先创建一个文件夹,命名为msg文件

 

ubuntu16.04下ROS操作系统学习笔记(三 / 二)ROS基础-ROS通信编程插图(13)

 

在这个文件夹下面创建一个具体的Person.msg文件

 

ubuntu16.04下ROS操作系统学习笔记(三 / 二)ROS基础-ROS通信编程插图(14)

 

之后我们在package.xml文件里面去添加依赖。部分的ROS版本中的exec_depend需要改成run_depend。

 

ubuntu16.04下ROS操作系统学习笔记(三 / 二)ROS基础-ROS通信编程插图(15)

 

之后的话我们需要在CMakeLists.txt文件里面添加编译选项,在下面添加message_generation功能包。

 

ubuntu16.04下ROS操作系统学习笔记(三 / 二)ROS基础-ROS通信编程插图(16)

 

然后添加编译时候的依赖:

 

ubuntu16.04下ROS操作系统学习笔记(三 / 二)ROS基础-ROS通信编程插图(17)

 

接下来添加是哪一个具体的msg文件:

 

ubuntu16.04下ROS操作系统学习笔记(三 / 二)ROS基础-ROS通信编程插图(18)

 

之后对其进行编译:

 

ubuntu16.04下ROS操作系统学习笔记(三 / 二)ROS基础-ROS通信编程插图(19)

 

我们可以在代码终端里面验证一下:

 

ubuntu16.04下ROS操作系统学习笔记(三 / 二)ROS基础-ROS通信编程插图(20)

 

2.服务编程

 

listener通过请求的形式来完成跟talker的一个通讯,talker把处理完成之后的数据处理完成之后再发布给listener,整个服务编程流程可以大致分为以下四个步骤:

 

  • 创建服务器
  • 创建客户端
  • 添加编译选项
  • 运行可执行程序

 

假设如下场景,listener发布某两个加数给talker,talker接收到这两个加数之后将这两个加数进行相加,并且把求和的结果告诉listener。具体步骤如下:

 

  • 定义srv文件
  • 在package.xml中添加功能包依赖
  • 在CMakeLists.txt添加编译选项

 

首先创建一个srv文件:

 

ubuntu16.04下ROS操作系统学习笔记(三 / 二)ROS基础-ROS通信编程插图(21)

 

然后在下面定义以下文件:

 

ubuntu16.04下ROS操作系统学习笔记(三 / 二)ROS基础-ROS通信编程插图(22)

 

中间的三条横线将数据分成两部分,上面的是服务的请求部分,下面的是服务的应答部分。

 

之后我们需要在pacaage.xml文件中添加功能包依赖

 

<build_depend>message_generation</build_depend>

<exec_depend>message_runtime</exec_depend>

这个和之前的talker-listener是一样的,因为我们刚才添加好了,这里就不用去做任何修改:

之后修改CMakeLists.txt文件,和之前的也差不多:

首先修改message_generation,和message_runtime。

之后再修改add_service_files:

 

ubuntu16.04下ROS操作系统学习笔记(三 / 二)ROS基础-ROS通信编程插图(23)

 

之后进入工作空间下面,对其进行编译:

 

ubuntu16.04下ROS操作系统学习笔记(三 / 二)ROS基础-ROS通信编程插图(24)

 

我们接下来看一下怎么实现一个服务端,实现服务器的编程

我们在这个功能包下面的src文件夹下面创建一个server.cpp文件:

 

ubuntu16.04下ROS操作系统学习笔记(三 / 二)ROS基础-ROS通信编程插图(25)

 

一个服务器的实现也需要分成四个步骤:

 

  • 初始化ROS节点;
  • 创建Server实例;
  • 循环等待服务请求,进入回调函数;
  • 在回调函数中完成服务功能的处理,并反馈应答数据。

 

ubuntu16.04下ROS操作系统学习笔记(三 / 二)ROS基础-ROS通信编程插图(26)

 

其代码与之前的比较类似。再回调函数里面,由于之前是将数据分成了两个部分,所以这个也是做两个部分,一个是request,一个是response。

 

之后我们还要创建一个客户端

 

ubuntu16.04下ROS操作系统学习笔记(三 / 二)ROS基础-ROS通信编程插图(27)

 

具体代码如下:

 

ubuntu16.04下ROS操作系统学习笔记(三 / 二)ROS基础-ROS通信编程插图(28)

 

之后需要对其进行编译:

 

  • 设置需要编译的代码和生成的可执行文件;
  • 设置链接库;
  • 设置依赖;

 

add_executable(server src/server.cpp)

target_link_libraries(server ${catkin_LIBRARIES})

add_dependencies(server ${PROJECT_NAME}_gencpp)

add_executable(client src/client.cpp)

target_link_libraries(client ${catkin_LIBRARIES})

add_dependencies(client ${PROJECT_NAME}_gencpp)

 

ubuntu16.04下ROS操作系统学习笔记(三 / 二)ROS基础-ROS通信编程插图(29)

 

设置完成之后,需要回到工作空间的根目录下面对其进行编译:

 

ubuntu16.04下ROS操作系统学习笔记(三 / 二)ROS基础-ROS通信编程插图(30)

 

ubuntu16.04下ROS操作系统学习笔记(三 / 二)ROS基础-ROS通信编程插图(31)

 

接下来我们运行编译成功之后的可执行文件:

首先我们roscore启动master,之后启动服务端,再启动客户端,传入参数:

 

roscore

 

rosrun learning_communication server

 

rosrun learning_communication client 1 1

 

ubuntu16.04下ROS操作系统学习笔记(三 / 二)ROS基础-ROS通信编程插图(32)

 

ubuntu16.04下ROS操作系统学习笔记(三 / 二)ROS基础-ROS通信编程插图(33)

 

3.动作编程

 

动作也是话题服务的一种机制,但是跟话题服务又有一些区别。比如说我们想让机器人前往一个目标点,并且让机器人不断地返回自己的实时状态,甚至说在机器人运动过程当中,我们不想让机器人前往这个目标点了,给他发布他一个信息,让它停止下来。像这种需要维持一段时间,并且有反馈的这样一种通讯是没有办法用话题或者服务来完成的。动作的实现也是通过ROS的消息机制来实现的。

 

实现原理图如下所示:

 

ubuntu16.04下ROS操作系统学习笔记(三 / 二)ROS基础-ROS通信编程插图(34)

 

同样也是分为服务端与客户端,通过二者之间的通讯来实现。

 

Action的接口有:

 

  • goal:发布任务目标。客户端可以给服务端发送一个动作的目标。
  • cancel:请求取消任务。在运行的过程当中,也可以将其取消。
  • status:通知客户端当前的状态。通知客户端当前服务器的状态。
  • feedback:周期反馈任务运行的监控数据。周期性地反馈,告诉机器人当前服务器的状态。
  • result:向客户端发送任务的执行结果,只发布一次。当完成客户端的命令之后会执行一次。

 

ubuntu16.04下ROS操作系统学习笔记(三 / 二)ROS基础-ROS通信编程插图(35)

 

那么我们如何来实现这样一个具体的动作编程呢:

 

  • 定义action文件
  • 在package.xml中添加功能包依赖

 

<build_depend>actionlib</build_depend>

<build_depend>actionlib_msgs</build_depend>

<exec_depend>actionlib</exec_depend>

<exec_depend>actionlib_msgs</exec_depend>

 

  • 在CMakeLists.txt中添加编译选项

 

find_package(catkin REQUIRED actionlib_msgs actionlib)

add_action_files(DIRECTORY action FILES DoDishes.action)

generate_messages(DEPENDENCIES actionlib_msgs)

 

同样,如果ROS中有自定义的工作消息给我们的话我么可以直接调用,如果没有的话那我们就需要自己来定义这样一个自定义的动作消息。

 

我们现在来假设一个洗盘子这样的任务,客户端发送一个洗盘子的命令给服务端,服务端接收到这个命令之后开始洗盘子,然后反馈给客户端洗了多少了,客户端也可以让服务端终止洗盘子这个命令。盘子洗碗之后返回一个洗碗的信号给客户端。

 

如果我们想要创建一个动作消息,我们需要在功能包里面创建一个文件夹action。然后在action里面创建具体的动作消息。

 

ubuntu16.04下ROS操作系统学习笔记(三 / 二)ROS基础-ROS通信编程插图(36)

 

这里有两个三横杠,把这整个数据内容分成了三个部分。

第一部分是定义目标数据的,也就是客户端发送什么样的一个动作的目的给服务端。

第二部分定义的是结果的,也就是说我们整个动作执行完成之后到底是一个什么样的结果。

第三部分是一定周期内反馈给客户端的数据内容。这里的话就是反馈洗盘子的百分比。

定义完成之后需要在package.xml里面去添加功能包的依赖。

 

ubuntu16.04下ROS操作系统学习笔记(三 / 二)ROS基础-ROS通信编程插图(37)

 

package.xml改完之后要去改CMakeLists.txt文件。

 

ubuntu16.04下ROS操作系统学习笔记(三 / 二)ROS基础-ROS通信编程插图(38)

 

ubuntu16.04下ROS操作系统学习笔记(三 / 二)ROS基础-ROS通信编程插图(39)

 

之后我们编译一下工作空间,看看定义的这些action是否是正确的

 

ubuntu16.04下ROS操作系统学习笔记(三 / 二)ROS基础-ROS通信编程插图(40)

 

编译是没有错误的,所以我们刚才的操作是没有错误的。

我们现在来看一下如何实现一个动作的服务器,主要是以下步骤:

 

  • 初始化ROS节点
  • 创建动作服务器实例
  • 启动服务器,等待动作请求
  • 在回调函数中完成动作服务功能的处理,并反馈进度信息
  • 动作完成,发送结束信息。

 

我们从视频资源中把源码拷贝过来:

 

ubuntu16.04下ROS操作系统学习笔记(三 / 二)ROS基础-ROS通信编程插图(41)

 

我们首先看一下服务端代码:

 

ubuntu16.04下ROS操作系统学习笔记(三 / 二)ROS基础-ROS通信编程插图(42)

 

在main函数里面,程序流程大致都差不多。启动服务器之后服务器就会一直循环等待命令。一旦接收到命令之后,服务器就会进入到回调函数里面。回调函数里面就会开始具体的服务处理。

 

完成服务端之后我们需要去完成客户端的功能:

 

  • 初始化ROS节点
  • 创建动作客户端实例
  • 连接动作服务端
  • 发送动作目标
  • 根据不同类型的服务端反馈处理回调函数

 

ubuntu16.04下ROS操作系统学习笔记(三 / 二)ROS基础-ROS通信编程插图(43)

 

代码完成之后就是来编译这些代码:

 

add_executable(DoDishes_client src/DoDishes_client.cpp)

target_link_libraries( DoDishes_client ${catkin_LIBRARIES})

add_dependencies(DoDishes_client ${${PROJECT_NAME}_EXPORTED_TARGETS})

add_executable(DoDishes_server src/DoDishes_server.cpp)

target_link_libraries( DoDishes_server ${catkin_LIBRARIES})

add_dependencies(DoDishes_server ${${PROJECT_NAME}_EXPORTED_TARGETS})

 

ubuntu16.04下ROS操作系统学习笔记(三 / 二)ROS基础-ROS通信编程插图(44)

 

之后进入工作空间目录下对其进行编译

 

ubuntu16.04下ROS操作系统学习笔记(三 / 二)ROS基础-ROS通信编程插图(45)

 

我们接下来对其进行验证测试:

 

roscore

 

rosrun learning_communication DoDishes_client

 

rosrun learning_communication DoDishes_client

 

ubuntu16.04下ROS操作系统学习笔记(三 / 二)ROS基础-ROS通信编程插图(46)

 

我的微信公众号名称:深度学习与先进智能决策
微信公众号ID:MultiAgent1024
公众号介绍:主要研究强化学习、计算机视觉、深度学习、机器学习等相关内容,分享学习过程中的学习笔记和心得!期待您的关注,欢迎一起学习交流进步!

 

发表评论

后才能评论