接口(Interfaces)¶
目录¶
- 背景
- 消息(Messages)
- 字段(Fields)
- 字段类型(Field types)
- 字段名称(Field names)
- 字段默认值(Field default value)
- 常量(Constants)
- 服务(Services)
- 动作(Actions)
背景¶
ROS 应用通常通过三种类型的接口进行通信:话题(topics)、服务(services)或动作(actions)。
ROS 2 使用一种简化的描述语言——接口定义语言(Interface Definition Language, IDL)来描述这些接口。这种描述使得 ROS 工具能够自动为多种目标语言生成该接口类型的源代码。
本文档将介绍以下支持的类型:
- msg:
.msg文件是简单的文本文件,用于描述 ROS 消息的字段。它们用于为不同语言生成消息的源代码。 - srv:
.srv文件描述一个服务,由两部分组成:请求(request)和响应(response)。请求和响应均为消息声明。 - action:
.action文件描述一个动作,由三部分组成:目标(goal)、结果(result)和反馈(feedback)。每一部分本身都是一个消息声明。
消息(Messages)¶
消息是 ROS 2 节点在无响应预期的情况下向网络中其他 ROS 节点发送数据的方式。
例如,若一个 ROS 2 节点从传感器读取温度数据,它可以使用 Temperature 消息将该数据发布到 ROS 2 网络上。网络中的其他节点可订阅该数据并接收 Temperature 消息。
消息在 ROS 包的 msg/ 目录中通过 .msg 文件进行描述和定义。.msg 文件包含两部分:字段(fields)和常量(constants)。
字段(Fields)¶
每个字段由一个类型和一个名称组成,中间用空格分隔,例如:
示例:
字段类型(Field types)¶
字段类型可以是:
- 内建类型(built-in type)
- 独立定义的消息类型名称,例如
geometry_msgs/PoseStamped
当前支持的内建类型如下:
| 类型名 | C++ | Python | DDS 类型 |
|---|---|---|---|
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 |
() 所有比 ROS 定义更宽松的类型(如 Python 中的
list或str)通过软件强制执行* ROS 规定的范围和长度限制。
所有内建类型均可用于定义数组:
| 类型 | C++ | Python | DDS 类型 |
|---|---|---|---|
| 静态数组 | std::array<T, N> |
builtins.list* |
T[N] |
| 无界动态数组 | std::vector |
builtins.list |
sequence |
| 有界动态数组 | custom_class<T, N> |
builtins.list* |
sequence<T, N> |
| 有界字符串 | std::string |
builtins.str* |
string |
消息定义示例(使用数组和有界类型):
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
字段名称(Field names)¶
字段名称必须满足: - 由小写字母、数字和下划线组成 - 必须以字母开头 - 不能以下划线结尾 - 不能包含两个连续的下划线
字段默认值(Field default value)¶
可为消息中的任意字段设置默认值。当前不支持为字符串数组和复杂类型(即非内建类型,包括嵌套消息)设置默认值。
通过在字段定义行中添加第三个元素来设置默认值:
示例:
注意:
- 字符串值必须使用单引号'或双引号"定义
- 当前不支持字符串转义
常量(Constants)¶
常量定义类似于带默认值的字段描述,但其值在程序中不可更改。使用等号 = 表示赋值:
示例:
注意:常量名称必须为大写字母(UPPERCASE)
服务(Services)¶
服务是一种请求/响应式通信,客户端(请求方)等待服务端(响应方)执行一个短时计算并返回结果。
服务在 ROS 包的 srv/ 目录中通过 .srv 文件定义。
服务描述文件由请求消息类型和响应消息类型组成,中间用 --- 分隔。任意两个 .msg 文件用 --- 连接即构成合法的服务描述。
简单示例(输入一个字符串,返回一个字符串):
复杂示例:
# 请求常量
int8 FOO=1
int8 BAR=2
# 请求字段
int8 foobar
another_pkg/AnotherMessage msg
---
# 响应常量
uint32 SECRET=123456
# 响应字段
another_pkg/YetAnotherMessage val
CustomMessageDefinedInThisPackage value
uint32 an_integer
注意:服务中不能嵌套其他服务。
若引用同一包中的消息,不得包含包名。
动作(Actions)¶
动作是一种长时间运行的请求/响应通信。动作客户端(请求方)等待动作服务器(响应方)执行某项操作并返回结果。与服务不同,动作具有以下特点: - 可长时间运行(数秒至数分钟) - 执行过程中可提供反馈(feedback) - 可被中断
动作定义格式如下:
<request_type> <request_fieldname>
---
<response_type> <response_fieldname>
---
<feedback_type> <feedback_fieldname>
- 第一个
---之前为请求字段 - 第一个与第二个
---之间为响应字段 - 第二个
---之后为反馈字段
请求、响应和反馈字段的数量均可为零或任意多个。
各部分的类型和字段名遵循与消息相同的规则。
示例:Fibonacci 动作定义
- 客户端发送一个
int32字段order,表示要计算的斐波那契数列项数 - 服务器返回一个
int32[]数组sequence,包含完整的数列 - 执行过程中,服务器可发送中间结果(已计算的部分数列)作为反馈