接口

背景

ROS应用通常通过以下三种类型的接口进行通信:主题服务。ROS 2使用一种简化的描述语言,接口定义语言(IDL),来描述这些接口。这种描述使得ROS工具能够自动生成多种目标语言的接口类型的源代码变得容易。

在本文档中,我们将描述支持的类型:

  • msg: .msg 文件是描述 ROS 消息字段的简单文本文件。它们用于在不同语言中生成消息的源代码。

  • srv: .srv 文件描述一个服务。它由两部分组成:请求和响应。请求和响应都是消息声明。

  • action: .action 文件描述一个动作。它由三部分组成:目标、结果和反馈。每个部分本身都是消息声明。

消息

消息是ROS 2节点将数据发送到其他ROS节点的一种方式,不需要期望响应。例如,如果一个ROS 2节点从传感器读取温度数据,它可以使用``Temperature``消息将该数据发布到ROS 2网络上。ROS 2网络上的其他节点可以订阅该数据并接收``Temperature``消息。

ROS包的``msg/目录中的.msg``文件描述和定义了消息。``.msg``文件由两个部分组成:字段和常量。

字段

每个字段由类型和名称组成,用空格分隔,例如:

fieldtype1 fieldname1
fieldtype2 fieldname2
fieldtype3 fieldname3

例如:

int32 my_int
string my_string

字段类型

字段类型可以是:

  • 内置类型

  • 独立定义的消息描述的名称,例如 "geometry_msgs/PoseStamped"

当前支持的内置类型:

类型名称

C++

Python

DDS 类型

bool

bool

builtins.bool

boolean

byte

uint8_t

内建字节串*

八位字节

字符

字符

内建字符串*

字符

单精度浮点数

浮点数

内置浮点型*

浮点数

float64

双精度

内置浮点型*

双精度

int8

int8_t

内置整型*

八位字节

无符号8位整数

uint8_t

内置整型*

八位字节

有符号16位整数

有符号16位整数

内置整型*

短整数

无符号16位整数

无符号16位整数

内置整型*

无符号短整型

32位整型

int32_t

内置整型*

长整型

无符号32位整型

uint32_t

内置整型*

无符号长整型

64位整型

int64_t

内置整型*

长长整型

无符号64位整型

uint64_t

内置整型*

无符号长长整型

字符串

std::字符串

内建.字符串

字符串

宽字符串

std::u16字符串

内建.字符串

宽字符串

每个内置类型都可以用来定义数组:

类型名称

C++

Python

DDS 类型

静态数组

std::array<T, N>

内置类型列表*

T[N]

无界动态数组

std::vector

builtins.list

sequence

bounded dynamic array

custom_class<T, N>

内置类型列表*

sequence<T, N>

有界字符串

std::字符串

内建字符串*

字符串

所有比其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_strings_up_to_ten_characters_each
string<=10[<=5] up_to_five_strings_up_to_ten_characters_each

字段名称

字段名称必须是小写字母数字字符,用下划线分隔单词。它们必须以字母字符开头,不能以下划线结尾,也不能有两个连续的下划线。

字段默认值

消息类型中的任何字段都可以设置默认值。目前不支持为字符串数组和复杂类型(即不在上面的内置类型表中的类型,适用于所有嵌套消息)设置默认值。

通过在字段定义行中添加第三个元素来定义默认值,例如:

fieldtype fieldname fielddefaultvalue

例如:

uint8 x 42
int16 y -2000
string full_name "John Doe"
int32[] samples [-200, -100, 0, 100, 200]

注解

  • 字符串值必须用单引号 ' 或双引号 " 定义

  • 当前字符串值不被转义

常量

每个常量定义都类似于具有默认值的字段描述,但是这个值在程序中不能被改变。这个值的赋值通过等号 '=' 来表示,例如。

constanttype CONSTANTNAME=constantvalue

例如:

int32 X=123
int32 Y=-123
string FOO="foo"
string EXAMPLE='bar'

注解

常量名称必须是大写字母。

服务

服务是一种请求/响应通信,客户端(请求方)等待服务器(响应方)进行简短计算并返回结果。

服务在 ROS 包的 'srv/' 目录下的 '.srv' 文件中进行描述和定义。

一个服务描述文件由请求和响应的消息类型组成,用 '---' 分隔。任何两个 '.msg' 文件通过 '---' 连接在一起都构成一个合法的服务描述。

以下是一个非常简单的服务示例,它接收一个字符串并返回一个字符串:

string str
---
string str

当然,我们可以变得更加复杂(如果你想引用同一包中的消息,不需要提及包名):

# request constants
int8 FOO=1
int8 BAR=2
# request fields
int8 foobar
another_pkg/AnotherMessage msg
---
# response constants
uint32 SECRET=123456
# response fields
another_pkg/YetAnotherMessage val
CustomMessageDefinedInThisPackage value
uint32 an_integer

你不能在一个服务中嵌入另一个服务。

动作

动作是一种长时间运行的请求/响应通信,动作客户端(请求方)等待动作服务器(响应方)执行某些操作并返回结果。与服务不同,动作可以是长时间运行的(数秒或数分钟),在执行过程中提供反馈,并可以中断。

动作定义的形式如下:

<request_type> <request_fieldname>
---
<response_type> <response_fieldname>
---
<feedback_type> <feedback_fieldname>

与服务类似,请求字段位于第一个三短线(---)之前,响应字段位于其后。还有第二组字段位于第二个三短线之后,用于在发送反馈时发送的字段。

可以有任意数量的请求字段(包括零个)、任意数量的响应字段(包括零个)以及任意数量的反馈字段(包括零个)。

<request_type>, <response_type>``和``<feedback_type>``都遵循与消息的``<type>``相同的规则。``<request_fieldname>, ``<response_fieldname>``和``<feedback_fieldname>``都遵循与消息的``<fieldname>``相同的规则。

例如,``Fibonacci``动作定义包含以下内容:

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

这是一个动作定义,其中动作客户端发送一个表示要执行的Fibonacci步数的``int32``字段,并期望动作服务器生成包含所有步骤的``int32``数组。在执行过程中,动作服务器还可以提供包含截至某一点的已完成步骤的中间``int32``数组。