这是我对ROS官方ROS2教程的翻译,纯个人理解,对于文中的关键词汇或不确定的语句标注了原文,如有错误或翻译问题还请指出。
原文:https://index.ros.org/doc/ros2/Concepts/About-ROS-Interfaces/
日期:2019年1月20日
关于ROS2 接口
1. 背景
ROS应用通过两种类型的接口来实现通信:消息和服务。ROS使用一种简单的描述性语言来描述这些接口,通过描述性语言可以很容易的让ROS工具来自动地生成不同目标语言的接口类型的源码。
这篇文档我们将会去说明ROS2支持的接口类型以及如何去创建自己的消息、服务文件。
2. 消息描述说明
消息描述在.msg
文件中定义,.msg
文件位于ROS包中的msg/
路径下。.msg
文件由两部分组成:域(fields)和常量(constants)。
2.1 域
每个域包括一个类型和一个名称,用一个空格分开,格式为:
fieldtype1 fieldname1
fieldtype2 fieldname2
fieldtype3 fieldname3
例如:
int32 my_int
string my_string
2.1.1 域类型
域类型可以是:
- 一个内建类型
- 自定义的消息描述名称,如“geometory_msgs/PoseStamped”
内建类型现在支持情况如下:
类型名 | C++ | Python | DDS类型 |
---|---|---|---|
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 |
每一个内建类型都可以用于定义数组:
类型名 | C++ | Python | DDS类型 |
---|---|---|---|
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约束。(All types that are more permissive than their ROS definition enforce the ROS constraints in range and length by software)
一个使用数组和有边界类型的例子如下:
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 域名
域名必须是由小写的字母或数字的字符以及下划线组成。必须以字母字符开头,不能以下划线结尾,而且不能有连续的两个下划线。
2.1.3 域默认值
消息类型中,默认值可以在任何域中设置。当前的默认值不支持string数组以及复杂的类型(比如不属于上边表中指定的内建类型,可以应用于所有嵌套消息(that applies to all nested messages))
通过在域定义行中增加第三个元素项来定义一个默认消息,格式为:
fieldtype fieldname fielddefaultvalue
比如:
uint8 x 42
int16 y -2000
string full_name "John Doe"
int32[] samples [-200, -100, 0, 100, 200]
注:
- string类型的默认值必须由
'
或"
包含 - 当前string值不会被转义
2.2 常量
常量的定义就像是带默认值的域描述,区别在于它的值不会被程序改变。这个值通过等号=
来赋给常量,格式为:
constanttype CONSTANTNAME=constantvalue
比如:
int32 X=123
int32 Y=-123
string FOO="foo"
string EXAMPLE='bar'
注:
- 常量名称必须是大写的
3. 服务描述说明
服务描述在.srv
文件中定义,.srv
文件在ROS包中的srv/
路径下。
一个服务描述文件包含了请求和响应的消息类型,由---
分隔。任何两个.msg
文件都可以由---
连接起来而形成合法的服务描述文件。
一个最简单的服务例子如下,它获得一个string消息,返回一个string消息:
string str
---
string str
我们当然可以让服务描述更复杂(如果你需要引用一个相同包里的消息,则不应当提及包名),例如:
#请求常量
int8 FOO=1
int8 BAR=2
#请求域
int8 foobar
another_pkg/AnotherMessage msg
---
#响应常量
uint32 SECRET=123456
#响应域
another_pkg/YetAnotherMessage val
CustomMessageDefinedInThisPackage value
uint32 an_integer
不可以在一个服务中嵌入其他的服务。