接口
背景
ROS 应用程序通常通过以下三种类型的接口进行通信: topics, services, or actions. ROS 2 使用一种简化的描述语言,即接口定义语言 (IDL) 来描述这些接口。 此描述使 ROS 工具可以轻松地自动生成多种目标语言的接口类型源代码。
在本文档中,我们将描述支持的类型:
msg:“.msg”文件是描述 ROS 消息字段的简单文本文件。它们用于生成不同语言的消息源代码。
srv:“.srv”文件描述服务。它们由两部分组成:请求和响应。请求和响应是消息声明。
action:“.action”文件描述操作。它们由三部分组成:目标、结果和反馈。
每个部分本身都是一个消息声明。
消息
消息是 ROS 2 节点通过网络向其他 ROS 节点发送数据的一种方式,无需响应。 例如,如果 ROS 2 节点从传感器读取温度数据,则它可以使用“温度”消息在 ROS 2 网络上发布该数据。 ROS 2 网络上的其他节点可以订阅该数据并接收“温度”消息。
消息在 ROS 包的“msg/”目录中的“.msg”文件中描述和定义。 “.msg”文件由两部分组成:字段和常量。
字段
每个字段由一个类型和一个名称组成,以空格分隔,即:
fieldtype1 fieldname1
fieldtype2 fieldname2
fieldtype3 fieldname3
例如:
int32 my_int
string my_string
字段类型
字段类型可以是:
内置类型
自行定义的消息描述名称,例如“geometry_msgs/PoseStamped”
当前支持的内置类型:
Type name |
|||
---|---|---|---|
bool |
bool |
builtins.bool |
boolean |
byte |
uint8_t |
builtins.bytes* |
octet |
char |
char |
builtins.int* |
char |
float32 |
float |
builtins.float* |
float |
float64 |
double |
builtins.float* |
double |
int8 |
int8_t |
builtins.int* |
octet |
uint8 |
uint8_t |
builtins.int* |
octet |
int16 |
int16_t |
builtins.int* |
short |
uint16 |
uint16_t |
builtins.int* |
unsigned short |
int32 |
int32_t |
builtins.int* |
long |
uint32 |
uint32_t |
builtins.int* |
unsigned long |
int64 |
int64_t |
builtins.int* |
long long |
uint64 |
uint64_t |
builtins.int* |
unsigned long long |
string |
std::string |
builtins.str |
string |
wstring |
std::u16string |
builtins.str |
wstring |
每个内置类型都可以用来定义数组:
Type name |
|||
---|---|---|---|
static array |
std::array<T, N> |
builtins.list* |
T[N] |
unbounded dynamic array |
std::vector |
builtins.list |
sequence |
bounded dynamic array |
custom_class<T, N> |
builtins.list* |
sequence<T, N> |
bounded string |
std::string |
builtins.str* |
string |
所有比其 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]
Note
string values must be defined in single
'
or double"
quotescurrently string values are not escaped
常量
每个常量定义都类似于具有默认值的字段描述,但该值永远无法通过编程更改。 此值分配通过使用等号“=”来表示,例如
constanttype CONSTANTNAME=constantvalue
例如:
int32 X=123
int32 Y=-123
string FOO="foo"
string EXAMPLE='bar'
Note
Constants names have to be UPPERCASE
服务
服务是一种请求/响应通信,其中客户端(请求者)等待服务器(响应者)进行简短计算并返回结果。
服务在 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
这是一个动作定义,其中动作客户端发送一个“int32”字段,表示要采取的斐波那契步骤数,并期望动作服务器生成一个包含完整步骤的“int32”数组。 在此过程中,动作服务器还可以提供一个中间“int32”数组,其中包含在某个点之前完成的步骤。