关于ROS 2接口 [待校准@10102]

1. 背景 [Alyssa@10103]

ROS应用程序通常通过三种类型之一的接口进行通信: 消息(messages)、服务(services)和动作(actions)。ROS 2使用简化的描述语言,即接口定义语言 (IDL) 来描述这些接口。这种描述使ROS工具可以轻松地以多种目标语言自动的生成接口类型的源文件。 [Alyssa@10104]

在本文档中,我们将描述ROS2支持的类型。 [Alyssa@10105]

  • msg(消息): .msg 文件是描述ROS消息字段的简单文本文件。它们用于为不同语言的消息生成源文件代码。 [Alyssa@10106]

  • srv(服务): .srv 文件描述了一项服务。它们由两部分组成: 请求和响应。请求和响应是消息声明。 [Alyssa@10107]

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

2. 消息描述规范 [Alyssa@10109]

消息是在ROS包的 msg/ 目录下的 .msg 文件中描述和定义的。 .msg 文件由两部分组成: 字段和常量。 [Alyssa@10110]

2.1 字段 [Alyssa@10111]

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

fieldtype1 fieldname1
fieldtype2 fieldname2
fieldtype3 fieldname3

例如:

int32 my_int
string my_string

2.1.1 字段类型 [Alyssa@10114]

字段类型可以是:

  • 内置类型

  • ROS2自己定义的消息描述的名称,如 "geometry_msgs/PoseStamped" [Alyssa@10117]

目前支持的内置类型: [Alyssa@10118]

类型名称

C++

Python

DDS 类型 [Alyssa@10122]

bool

bool

builtins.bool

boolean

byte

uint8_t

builtins.bytes*

octet

char

char

builtins.str*

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

每个内置类型都可以用来定义数组: [Alyssa@10164]

类型名称

C++

Python

DDS 类型 [Alyssa@10122]

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约束 [待校准@10177]

使用数组和有界类型的消息定义示例: [Alyssa@10178]

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

2.1.2 字段名称 [Alyssa@10179]

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

2.1.3 字段默认值 [Alyssa@10181]

可以为消息类型中的任何字段设置默认值。目前,string数组和复杂类型(即上述内置类型表中不存在的类型,适用于所有嵌套消息)不支持设置默认值 [Alyssa@10182]

定义默认值是通过向字段定义行添加第三个元素来完成的,即: [待校准@10183]

fieldtype fieldname fielddefaultvalue

例如:

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

注意:

2.2 常数 [Alyssa@10187]

每个常量定义都类似于具有默认值的字段描述,不同之处在于该值永远无法通过程序更改。该值通过使用等号 “=” 来赋值,例如 [Alyssa@10188]

constanttype CONSTANTNAME=constantvalue

例如:

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

注解

常量名称必须为大写 [待校准@10189]

3. 服务描述规范 [Alyssa@10190]

服务消息在ROS包的 srv/ 目录下的 .srv 文件中描述和定义。 [Alyssa@10191]

服务描述文件由一个请求和一个响应msg类型组成,以“---”分隔。任何两个用“---” 连接的 .msg 文件都是合法的服务描述。 [Alyssa@10192]

这是一个非常简单的服务示例,该服务接受一个字符串(string)并返回一个字符串(string): [Alyssa@10193]

string str
---
string str

我们当然可以使服务消息变得更加复杂 (如果您想引用来自同一包的消息,您不能提及包名称): [Alyssa@10194]

#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

您不能在服务中嵌入其他服务。 [待校准@10195]

4. ROS 2接口的新功能 [Alyssa@10196]

ROS 2 IDL与 ROS 1 IDL 密切相关。大多数现有的ROS 1 .msg.srv 文件在ROS 2上应该一样可用。在ROS 1现有的特征集上,ROS 2 IDL引入了一些新的特征,即: [Alyssa@10197]

  • 有界数组: 鉴于ROS 1IDL允许无界数组 (例如,int32[] foo) 和固定大小数组 (例如,int32[5] bar),ROS 2 IDL进一步允许有界数组 (例如,int32[<=5] bat)。在某些用例中,重要的是能够在数组大小上设置上限,而不必总是使用太多空间 (例如,在实时系统中,您需要预分配将在执行期间使用的所有内存)。 [Alyssa@10198]

  • 有界字符串: 鉴于ROS 1IDL允许无界字符串 (例如,string foo),ROS 2 IDL进一步允许有界字符串 (例如,string<=5 bar)。 [Alyssa@10199]

  • 默认值: 鉴于ROS 1IDL允许常量字段 (例如,int32 X=123),ROS 2 IDL进一步允许指定默认值 (例如, int32 X 123 )。在构造消息/服务对象时使用默认值,随后可以通过给字段赋值来覆盖默认值。您也可以为动作部分指定默认值。 [Alyssa@10200]