客户端库

概述

客户端库是允许用户实现其 ROS 2 代码的 API。 使用客户端库,用户可以访问 ROS 2 概念,例如节点、主题、服务等。 客户端库有多种编程语言,因此用户可以使用最适合其应用程序的语言编写 ROS 2 代码。 例如,您可能更喜欢用 Python 编写可视化工具,因为它可以加快原型迭代速度,而对于系统中与效率相关的部分,节点可能最好用 C++ 实现。

使用不同客户端库编写的节点能够相互共享消息,因为所有客户端库都实现了代码生成器,为用户提供了使用相应语言与 ROS 2 接口文件交互的能力。

除了特定于语言的通信工具外,客户端库还向用户展示了使 ROS 成为“ROS”的核心功能。 例如,以下是通常可以通过客户端库访问的功能列表:

  • Names and namespaces

  • Time (real or simulated)

  • Parameters

  • Console logging

  • Threading model

  • Intra-process communication

支持的客户端库

C++ 客户端库(“rclcpp”)和 Python 客户端库(“rclpy”)都是利用“rcl”中通用功能的客户端库。

rclcpp

C++ 版 ROS 客户端库 (rclcpp) 是面向用户的 C++ 惯用接口,提供所有 ROS 客户端功能,如创建节点、发布者和订阅。 rclcpp 建立在 rclrosidl API 之上,旨在与 rosidl_generator_cpp 生成的 C++ 消息一起使用。

rclcpp 利用 C++ 和 C++17 的所有功能使接口尽可能易于使用,但由于它重用了 rcl 中的实现,因此它能够与使用 rcl API 的其他客户端库保持一致的行为。

rclcpp 存储库位于 GitHub 上的 ros2/rclcpp ,包含 package rclcpp。 生成的 API 文档在此处:

api/rclcpp/index.html

rclpy

适用于 Python 的 ROS 客户端库 (rclpy) 是 C++ 客户端库的 Python 对应库。

与 C++ 客户端库一样,rclpy 也基于 rcl C API 实现。

该接口提供惯用的 Python 体验,使用本机 Python 类型和模式,如列表和上下文对象。

通过在实现中使用 rcl API,它在功能奇偶校验和行为方面与其他客户端库保持一致。

除了为每条消息提供围绕 rcl API 和 Python 类的 Python 惯用绑定之外,Python 客户端库还负责执行模型,使用 threading.Thread 或类似程序来运行 rcl API 中的函数。

与 C++ 类似,它会为用户与之交互的每条 ROS 消息生成自定义 Python 代码,但与 C++ 不同的是,它最终会将原生 Python 消息对象转换为 C 版本的消息。 所有操作都发生在 Python 版本的消息上,直到需要将它们传递到 rcl 层,此时它们被转换为纯 C 版本的消息,以便可以将其传递到 rcl C API。 如果可能的话,在同一进程中发布者和订阅者之间进行通信时应避免这种情况,以减少 Python 的转换。

rclpy 存储库位于 GitHub 上的 ros2/rclpy 并包含 package rclpy。 生成的 API 文档在此处:

api/rclpy/index.html

社区维护

虽然 C++ 和 Python 客户端库由核心 ROS 2 团队维护,但 ROS 2 社区成员还维护其他客户端库:

  • Ada 这是一组软件包(绑定到 rcl、消息生成器、绑定到 tf2、示例和教程),允许为 ROS 2 编写 Ada 应用程序。

  • C rclc 不会在 rcl 之上添加一层,而是对 rcl 进行补充,使 rcl+rclc 成为功能齐全的 C 语言客户端库。有关教程,请参阅 micro.ros.org

  • JVM 和 Android 用于 ROS 2 的 Java 和 Android 绑定。

  • .NET Core、UWP 和 C# 这是用于为 .NET Core 和 .NET Standard 编写 ROS 2 应用程序的项目集合(绑定、代码生成器、示例等)。

  • Node.js rclnodejs 是 ROS 2 的 Node.js 客户端。它为 ROS 2 编程提供了简单易用的 JavaScript API。

  • Rust 这是一组项目(rclrs 客户端库、代码生成器、示例等),使开发人员能够用 Rust 编写 ROS 2 应用程序。

  • Flutter 和 Dart ROS 2 的 Flutter 和 Dart 绑定。

较旧的、未维护的客户端库包括:

Common functionality: rcl

客户端库中的大多数功能并不特定于客户端库的编程语言。 例如,参数的行为和命名空间的逻辑在所有编程语言中都应该相同。 因此,客户端库不是从头开始实现通用功能,而是使用通用核心 ROS 客户端库 (RCL) 接口,该接口实现不特定于语言的 ROS 概念的逻辑和行为。 因此,客户端库只需使用外部函数接口将通用功能包装在 RCL 中。 这使客户端库更薄,更易于开发。 因此,通用 RCL 功能通过 C 接口公开,因为 C 语言通常是客户端库最容易包装的语言。 除了使客户端库轻量级之外,拥有通用核心的一个优点是语言之间的行为更加一致。 如果对核心 RCL 中功能的逻辑/行为(例如命名空间)进行了任何更改,则所有使用 RCL 的客户端库都将反映这些更改。 此外,拥有通用核心意味着在修复错误时,维护多个客户端库的工作量会减少。

rcl 的 API 文档可以在 此处 找到。

特定于语言的功能

需要特定于语言的功能/属性的客户端库概念未在 RCL 中实现,而是在每个客户端库中实现。

例如,“spin”函数使用的线程模型将具有特定于客户端库语言的实现。

演示

要了解使用 rclpy 的发布者和使用 rclcpp的订阅者之间的消息交换,我们建议您从 17:25 开始观看 这个 ROSCon 演讲 <https://vimeo.com/187696091>`__(`在此处查看幻灯片)。

与 ROS 1 的比较

在 ROS 1 中,所有客户端库都是“从头开始”开发的。 例如,这允许 ROS 1 Python 客户端库纯粹用 Python 实现,从而带来无需编译代码等好处。 但是,客户端库之间的命名约定和行为并不总是一致的,必须在多个地方进行错误修复,并且有很多功能仅在一个客户端库中实现(例如 UDPROS)。

摘要

通过利用通用核心 ROS 客户端库,用各种编程语言编写的客户端库更容易编写,并且行为更一致。