警告

您正在阅读的 ROS 2 文档版本已达到 EOL(生命周期结束),不再受官方支持。如果您想了解最新信息,请访问 Jazzy.

关于 ROS 2 内部接口

ROS 内部接口为公共 C 应用程序接口 的开发人员使用。 客户端库 或添加新的底层中间件,但并不适合 ROS 的典型用户使用。ROS 客户端库 提供面向用户的 应用程序接口 这些编程语言是大多数 ROS 用户所熟悉的,可能采用多种编程语言。

内部应用程序接口架构概述

主要有两个内部接口:

"(《世界人权宣言》) rmw 应用程序接口 是 ROS 2 软件栈与底层中间件实现之间的接口。ROS 2 使用的底层中间件是 DDS 或 RTPS 实现,负责服务的发现、发布和订阅机制、请求-回复机制以及信息类型的序列化。

"(《世界人权宣言》) rcl 应用程序接口 略高 应用程序接口 用于实现 客户端库 并不直接接触中间件实现,而是通过 ROS 中间件接口 (rmw 应用程序接口)的抽象。

ros2 软件栈

如图所示,这些 应用程序接口 堆叠在一起,典型的 ROS 用户会使用 客户端库 应用程序接口例如 rclcpp,以实现其代码(可执行代码或库)。执行 客户端库例如 rclcpp使用 rcl 接口,可访问 ROS 图形和图形事件。图 rcl 实现反过来使用 rmw 应用程序接口 来访问 ROS 图形。其目的是 rcl 实现的目的是为更复杂的 ROS 概念和实用程序提供一个通用的实现,这些概念和实用程序可能会被各种 客户端库同时与所使用的底层中间件无关。其目的是 rmw 接口是为了获取支持 ROS 客户端库所需的最基本中间件功能。最后,实现 rmw 应用程序接口 由特定的中间件实现提供 包装例如 rmw_fastrtps_cpp该库是根据供应商特定的 DDS 接口和类型编译的。

上图中还有一个标有 ros_too_dds这个方框的目的是代表一类可能的软件包,允许用户使用 ROS 的等价物访问 DDS 厂商特定的对象和设置。这个抽象接口的目标之一是将 ROS 用户空间代码与所使用的中间件完全隔离,这样,更换 DDS 供应商甚至中间件技术对用户代码的影响就会降到最低。不过,我们也认识到,尽管可能会产生一些后果,但有时手动调整设置还是非常有用的。通过要求使用这些软件包之一来访问底层 DDS 供应商的对象,我们可以避免在正常接口中暴露供应商特定的符号和头文件。此外,通过检查软件包的依赖关系,查看这些软件包中是否有一个 ros_too_dds 正在使用的软件包。

特定类型接口

一路走来,有些地方 应用程序接口 这些代码必须针对所交换的信息类型,例如发布信息或订阅主题,因此需要为每种信息类型生成代码。下图显示了从用户定义的 rosidl 文件,例如 .msg 文件,到用户和系统用来执行特定类型功能的特定类型代码:

ros2 idl 静态类型支持栈

图:"静态 "类型支持生成流程图,来自 rosidl 文件到面向用户的代码。

图的右侧显示了 .msg 文件直接传递给特定语言的代码生成器,例如 rosidl_generator_cppROSIDL_GENERATOR_PY.这些生成器负责创建用户将包含(或导入)的代码,并将其用作在 .msg 文件。例如,请看以下信息 std_msgs/String用户可以在 C++ 中使用该文件,语句为 #include <std_msgs/msg/string.hpp>;或者他们可以使用以下语句 std_msgs.msg 舶来品 字符串 在 Python 中。这些语句之所以能运行,是因为这些特定语言(但与中间件无关)生成器软件包生成了文件。

另外 .msg 文件用于为每种类型生成类型支持代码。在这里,类型支持是指:特定于给定类型的元数据或函数,系统使用它们来执行给定类型的特定任务。给定报文的类型支持可能包括报文中每个字段的名称和类型列表等内容。它还可能包含可为该类型执行特定任务(如发布消息)的代码引用。

静态类型支持

当类型支持引用代码为特定消息类型执行特定功能时,该代码有时需要执行中间件特定的工作。例如,考虑到特定类型的发布函数,当使用 "供应商 A "时,该函数将需要调用 "供应商 A "的一些 应用程序接口但在使用 "供应商 B "时,需要调用 "供应商 B "的 应用程序接口.为了允许中间件供应商的特定代码,用户定义的 .msg 文件可能导致生成供应商专用代码。通过类型支持抽象,这些厂商特定代码仍然不会被用户发现,这与 "私有实现"(或 Pimpl)模式的工作原理类似。

使用 DDS 支持静态类型

对于基于 DDS 的中间件供应商来说,特别是那些根据 OMG IDL 文件 (.idl 文件)、用户定义的 rosidl 文件 (.msg 文件)转换为等效的 OMG IDL 文件 (.idl 文件)。通过这些 OMG IDL 文件,可以创建供应商特定代码,然后在特定类型的函数中使用,这些函数由给定类型的类型支持引用。上图左侧显示了这一点,其中的 .msg 文件由 rosidl_dds 软件包,以产生 .idl 文件,然后这些 .idl 文件给特定语言和特定 DDS 供应商的类型支持生成包。

例如,快速 DDS 实现中有一个名为 rosidl_typesupport_fastrtps_cpp.该软件包负责生成代码,以处理将 C++ 消息对象转换为序列化八进制缓冲区并通过网络写入等事宜。这些代码虽然是 Fast DDS 所特有的,但由于类型支持代码的抽象性,它们仍然不会暴露给用户。

动态类型支持

实现类型支持的另一种方法是使用通用函数,而不是为每种消息类型生成一个函数版本。为了实现这一点,通用函数需要一些关于要发布的消息类型的元信息,比如字段名称和类型列表,以及它们在消息类型中出现的顺序。然后,要发布一条信息,你需要调用一个通用发布函数,并传递一条要发布的信息以及一个包含信息类型必要元数据的结构。这被称为 "动态 "类型支持,而 "静态 "类型支持则需要为每种类型生成不同版本的函数。

ros2 idl 动态类型支持栈

图:"动态 "类型支持生成流程图,来自 rosidl 文件到面向用户的代码。

上图显示了从用户定义的 rosidl 文件来生成面向用户的代码。它与静态类型支持的示意图非常相似,区别仅在于类型支持的生成方式,即示意图的左侧。在动态类型支持中 .msg 文件直接转换为面向用户的代码。

这段代码也与中间件无关,因为它只包含信息的元信息。实际执行工作的函数(如发布到主题)是消息类型的通用函数,会对特定的中间件进行必要的调用。 应用程序接口.请注意,这种方法不是由 dds 供应商特定的软件包提供类型支持代码(静态类型支持就是这种情况),而是为每种语言提供与中间件无关的软件包,例如:.............. ROSIDL_Typesupport_introspection_Crosidl_typesupport_introspection_cpp.......。 反省 指的是使用为消息类型生成的元数据反省任何消息实例的能力。这是实现 "发布到主题 "等通用功能的基本能力。

这种方法的优点是,所有生成的代码都与中间件无关,这意味着只要允许动态类型支持,就可以在不同的中间件实现中重复使用。它还能减少生成代码的数量,从而缩短编译时间,减小代码大小。

然而,动态类型支持需要底层中间件支持类似形式的动态类型支持。就 DDS 而言,DDS-XTypes 标准允许使用元信息而不是生成的代码来发布消息。为了支持动态类型支持,底层中间件中需要 DDS-XTypes 或类似的东西。此外,这种类型支持方法通常比静态类型支持方法慢。静态类型支持中的特定类型生成代码可以编写得更高效,因为它不需要遍历消息类型的元数据来执行序列化等操作。

"(《世界人权宣言》) rcl 存储库

ROS 客户端库接口 (rcl 应用程序接口)可由 客户端库 例如 rclc, rclcpp, rclpy等),以避免重复逻辑和功能。通过重复使用 rcl 应用程序接口这样,客户机库就可以更小、更一致。客户端库的某些部分被有意地排除在 rcl 应用程序接口 因为应该使用语言惯用法来实现系统的这些部分。执行模型就是一个很好的例子。 rcl 根本无法解决。相反,客户端库应提供一种语言惯用的解决方案,如 pthreads 在C、 std::threadthreading.Thread 在 Python 中。一般来说 rcl 接口提供的功能既不特定于某种语言模式,也不特定于某种信息类型。

"(《世界人权宣言》) rcl 应用程序接口 位于 ros2/rcl 存储库 GitHub 并包含作为 C 标头的接口。接口 rcl C 实现由 rcl 包装 在同一个资源库中。这种实现方式避免了与中间件的直接接触,而是通过使用 rmwrosidl 应用程序接口.

有关 rcl 应用程序接口见其 API 文档:

"(《世界人权宣言》) rmw 存储库

ROS 中间件接口 (rmw 应用程序接口)是在其上构建 ROS 所需的一套最基本的中间件功能。不同中间件实现的提供者必须实现这个接口,才能在上面支持整个 ROS 堆栈。目前,所有中间件都是为不同的 DDS 供应商实现的。

"(《世界人权宣言》) rmw 应用程序接口 位于 ROS2/RMW 存放处。该 rmw 包装 包含定义接口的 C 头文件,接口的实现由不同的 套餐 不同 DDS 供应商的 rmw 实现。

关于 rmw 应用程序接口应用程序接口 文档:

api/rmw/index.html

"(《世界人权宣言》) rosidl 存储库

"(《世界人权宣言》) rosidl 应用程序接口 包括一些与报文相关的静态函数和类型,以及报文在不同语言中应生成哪些代码的定义。在 应用程序接口 是针对特定语言的,但可能会也可能不会重复使用为其他语言生成的代码。在 应用程序接口 包含信息数据结构、构建和销毁函数等内容。消息 应用程序接口 还将实现一种获取消息类型的类型支持结构的方法,该结构在发布或订阅该消息类型的主题时使用。

有几个资源库在 rosidl 应用程序接口 和实施。

"(《世界人权宣言》) rosidl 存储库,位于 GitHubros2/rosidl定义了报文 IDL 语法,即 .msg 文件 .srv 文件等,并包含 套餐 用于解析文件、提供 CMake 基础设施以从信息中生成代码、生成与实现无关的代码(头文件和源文件),以及建立默认生成器集。该资源库包含以下内容 套餐:

  • rosidl_cmake提供 CMake 函数和 CMake 模块,用于从 rosidl 文件,例如 .msg 文件 .srv 文件等。

  • 默认生成器:定义了默认生成器列表,确保将它们作为依赖项安装,但也可以使用其他注入的生成器。

  • 生成器 CC 语言:提供了生成 C 语言头文件的工具 (.h)为 rosidl 文件

  • rosidl_generator_cppC++:提供生成 C++ 头文件的工具 (.hpp)为 rosidl 文件

  • ROSIDL_GENERATOR_PYPython:提供了为以下应用程序生成 Python 模块的工具 rosidl 文件

  • 解析器提供 Python 应用程序接口 用于解析 rosidl 文件

其他语言的生成器,例如 ROSIDL_Generator_JAVA在外部(不同的资源库)托管,但会使用与上述生成器相同的机制将自己 "注册 "为 rosidl 发电机。

除了上述 套餐 用于为 rosidl 文件 rosidl 存储库还包含 套餐 ROS 报文类型支持是指对文件中定义的报文类型的 "类型支持"。类型支持指的是解释和处理特定类型的 ROS 消息实例所代表的信息(例如发布消息)的能力。类型支持既可以由编译时生成的代码提供,也可以通过编程根据 rosidl 文件,例如 .msg.srv ROS 2 还可以通过对数据的内省来对 ROS 文件和接收到的数据进行类型支持。对于后者,类型支持是通过运行时对报文的解释来完成的,因此 ROS 2 生成的报文代码与 rmw 的实现无关。通过内省数据提供这种类型支持的软件包有

  • ROSIDL_Typesupport_introspection_CC++:提供生成 C 语言代码的工具,以支持 rosidl 信息数据类型。

  • rosidl_typesupport_introspection_cppC++:提供生成 C++ 代码的工具,以支持 rosidl 信息数据类型。

如果要在编译时生成类型支持,而不是以编程方式生成,则需要使用针对 rmw 实现的软件包。这是因为特定的 rmw 实现通常要求以 DDS 供应商特有的方式存储和处理数据,以便 DDS 实现使用这些数据。请参见 特定类型接口 如需了解更多详情,请参阅上文。

更多信息 rosidl 应用程序接口 (静态和生成),请参见本页:

警告

TODO: 链接到 rosidl 应用程序接口

"(《世界人权宣言》) rcutils 存储库

ROS 2 C 语言实用程序 (rcutils) 是一个 C 应用程序接口 由整个 ROS 2 代码库中使用的宏、函数和数据结构组成。这些宏和数据结构主要用于错误处理、命令行参数解析和日志记录,它们不是客户层或中间件层所特有的,可由客户层和中间件层共享。

"(《世界人权宣言》) rcutils 应用程序接口 和实施位于 ros2/rcutils 存储库 GitHub 其中包含作为 C 标头的接口。

有关 rcutils 应用程序接口其应用程序接口文件