ROS2 学习09--ros 中的通信接口的定义以及如何创建自定义msg、srv和action文件

在ROS系统中,无论话题还是服务,或者我们后续将要学习的动作,都会用到一个重要的概念——通信接口。

通信并不是一个人自言自语,而是两个甚至更多个人,你来我往的交流,交流的内容是什么呢?为了让大家都好理解,我们可以给传递的数据定义一个标准的结构,这就是通信接口。

接口的定义
接口的概念在各个领域随处可见,无论是硬件结构还是软件开发,都有广泛的应用。
在这里插入图片描述比如生活中最为常见的插头和插座,两者必须匹配才能使用,电脑和手机上的USB接口也是,什么Micro-USB、TypeC等等,都是关于接口的具体定义。

在这里插入图片描述

软件开发中,接口的使用就更多了,比如我们在编写程序时,使用的函数和函数的输入输出也称之为接口,每一次调用函数的时候,就像是把主程序和调用函数通过这个接口连接到一起,系统才能正常工作。

更为形象的是图形化编程中使用的程序模块,每一个模块都有固定的结构和形状,只有两个模块相互匹配,才能在一起工作,这就很好的讲代码形象化了。

所以什么是接口,它是一种相互关系,只有彼此匹配,才能建立连接。

在这里插入图片描述
回到ROS的通信系统,它的主要目的就是传输数据,那就得让大家高效的建立连接,并且准确包装和解析传输的数据内容,话题、服务等机制也就诞生了,他们传输的数据,都要符合通信接口的标准定义。

比如摄像头驱动发布的图像话题,由每个像素点的R、G、B三原色值组成,控制机器人运动的速度指令,由线速度和角速度组成,进行机器人配置的服务,有配置的参数和反馈的结果组成等等,类似这些常用的定义,在ROS系统中都有提供,我们也可以自己开发。

这些接口看上去像是给我们加了一些约束,但却是ROS系统的精髓所在。举个例子,我们使用相机驱动节点的时候,完全不用关注它是如何驱动相机的,只要一句话运行,我们就可以知道发布出来的图像数据是什么样的了,直接开始我们的应用开发;类似的,键盘控制我们也可以安装一个ROS包,如何实现的呢?不用关心,反正它发布出来的肯定是线速度和角速度。

ROS通信接口 接口可以让程序之间的依赖降低,便于我们使用别人的代码,也方便别人使用我们的代码,这就是ROS的核心目标,减少重复造轮子。

在这里插入图片描述
ROS有三种常用的通信机制,分别是话题、服务、动作,通过每一种通信种定义的接口,各种节点才能有机的联系到一起。

语言无关

为了保证每一个节点可以使用不同语言编程,ROS将这些接口的设计做成了和语言无关的,比如这里看到的int32表示32位的整型数,int64表示64位的整型数,bool表示布尔值,还可以定义数组、结构体,这些定义在编译过程中,会自动生成对应到C++、Python等语言里的数据结构。

在这里插入图片描述

  • 话题通信接口的定义使用的是.msg文件,由于是单向传输,只需要描述传输的每一帧数据是什么就行,比如在这个定义里,会传输两个32位的整型数,x、y,我们可以用来传输二维坐标的数值。

  • 服务通信接口的定义使用的是.srv文件,包含请求和应答两部分定义,通过中间的“—”区分,比如之前我们学习的加法求和功能,请求数据是两个64位整型数a和b,应答是求和的结果sum。

  • 动作是另外一种通信机制,用来描述机器人的一个运动过程,使用.action文件定义,比如我们让小海龟转90度,一边转一边周期反馈当前的状态,此时接口的定义分成了三个部分,分别是动作的目标,比如是开始运动,运动的结果,最终旋转的90度是否完成,还有一个周期反馈,比如每隔1s反馈一下当前转到第10度、20度还是30度了,让我们知道运动的进度。

标准接口

大家可能好奇ROS系统到底给我们定义了哪些接口呢?我们可以在ROS安装路径中的share文件夹中找到,涵盖众多标准定义,大家可以打开几个看看。

在这里插入图片描述
在这里插入图片描述

一、ROS2创建自定义msg、srv和action文件的思路

ROS2通过自带rosidl_default_generators包来为自定义的msg、srv和action文件生成各个语言的头文件!

ROS2通过在CMakeLists.txt中调用新增的宏rosidl_generate_interfaces来为msg、srv和action文件生成各个语言的头文件!而这个宏的实现定义在rosidl_default_generators包。

二、基本数据类型

利用ROS2的原始基本数据类型和已有的数据类型,可以自定义需要的数据类型。

2.1 ROS2的基本原始数据类型
ROS2目前支持的内置类型:
在这里插入图片描述
每种内置类型都可以用来定义数组:

在这里插入图片描述
所有比其ROS定义更宽松的类型均由软件强制执行ROS的范围和长度约束。

使用数组和有界类型的消息定义示例:

int32[] unbounded_integer_array
int32[5] five_integers_array
int32[<=5] up_to_five_integers_array

string string_of_unbounded_size
string<=10 up_to_ten_characters_string

string[<=5] up_to_five_unbounded_strings
string<=10[] unbounded_array_of_string_up_to_ten_characters each
string<=10[<=5] up_to_five_strings_up_to_ten_characters_each

三、创建自定义的msg、srv和action

3.1 创建功能包

在本文中,将在自己的包中创建自定义的.msg、.srv和.action文件,然后在另外的包中使用它们,这两个包应该在同一个工作空间dev_ws/src目录中,然后运行以下命令创建一个新包。

ros2 pkg create --build-type ament_cmake learning_inteface

tutorial_interfaces是新包的名称。注意,它是一个CMake包,目前还没有办法在纯Python包中生成.msg、.srv和.action文件。但是,可以在CMake包中创建自定义接口,然后在Python节点中使用它。

将.msg、.srv和.action文件保存在自己的包中是一种很好的做法。在dev_ws/src/learning_inteface 目录下创建:

mkdir msg srv action

3.2 创建自定义接口文件

3.2.1 自定义msg文件
在learning_inteface/msg文件夹下,创建一个名为Num.msg的新文件,用一行代码声明它的数据结构:

int64 num

这是自定义的消息,它传输一个名称为num的64位整数。

3.2.2 自定义srv文件

srv文件和msg文件相似,除了它包含两个部分:请求和响应。这两部分用“—”线分隔。

在learning_inteface/srv文件夹下,创建一个名为AddThreeInts.srv的新文件,并声明他的请求和响应结构:

int64 a
int64 b

---
int64 sum

这是自定义的服务,它请求三个名为a、b 的整数,并以一个名为sum的整数进行响应。

3.2.3 自定义action文件
按照以下格式定义.action文件:

Request
---
Result
---
Feedback

动作定义由三个消息定义组成,它们之间用–分隔。

  • 请求(request)消息从动作客户端发送到动作服务器,初始化一个新目标。

  • 当目标完成时,结果(result)消息从动作服务器发送到动作客户端。

  • 反馈(feedback)消息定期从动作服务器发送到动作客户端,其中包含关于目标的更新。

一个动作的实例通常被称为目标(goal)。

假设想要定义一个新的动作“Fibonacci”来计算Fibonacci序列。

在learning_inteface/action目录中,创建一个名为Fibonacci.action的文件,内容如下:

int32 order
---
int32[] sequence
---
int32[] partial_sequence

目标请求是想要计算的斐波那契数列的order,结果是最终的sequence,而反馈是到目前为止计算的partial_sequence。

3.3 编译生成

3.3.1 CMakeLists.txt

要将自定义的接口(interface)转换成基于语言的代码(如C++和Python),以便它们可以在这些语言中使用,请将以下代码添加到CMakeLists.txt中:

find_package(rosidl_default_generators REQUIRED)

rosidl_generate_interfaces(${
    
    PROJECT_NAME}
  "msg/Num.msg"
  "srv/AddThreeInts.srv"
  "action/Fibonacci.action"
 )

注意:需要依赖于action_msgs,因为动作定义包括额外的元数据(例如目标id)。

3.3.2 package.xml

因为接口依赖于rosidl_default_generators来生成基于语言的代码,所以需要声明对它的依赖关系。提供其他包使用,将以下行添加到package.xml中:

<depend>action_msgs</depend>

<build_depend>rosidl_default_generators</build_depend>
<exec_depend>rosidl_default_runtime</exec_depend>
<member_of_group>rosidl_interface_packages</member_of_group>

3.3.3 编译
在工作空间的根目录(~/dev_ws)中,运行以下命令:

colcon build --packages-select learning_inteface
source install/setup.bash

现在接口将被其他ROS 2包发现。

猜你喜欢

转载自blog.csdn.net/hai411741962/article/details/135127241