ROS2软件架构全面解析-rclpy软件框架

news/2025/1/7 23:00:01/

前言

本章是详细介绍ROS2通信中间件rclpy模块软件框架。
不了解背景的同学请先看:

  • ROS2软件架构全面解析-学习如何设计通信中间件框架: link

rclpy_4">rclpy软件框架

rclpy :ROS Client Library for the Python language.
上面这句话清楚的描述rclpy对于ROS的功能定位。
ROS2提供三种通信模式:Topics、Services、Actions,我们就以这三种视角进行代码架构学习
<a class=rclpy communication" />

总体软件层级

下面展示我划分的rclpy 软件架构图,先以Services的通信方式为例(后面我会把所有模块补上)进行讲解
<a class=rclpy module architecture" />
我把rclpy module划分三层,Application API、API Python Business、API C++ Business。

  • Application API:上面对接User Application,对其提供直接调用的接口、比如:create_client。其中__init__比较特殊代表__init__.py文件,这个文件主要功能包含:提供 init 函数,用于初始化 ROS 2 通信,包括设置上下文、处理命令行参数、设置信号处理程序。当写User Application代码时必须写到这样一行代码:
rclpy.init(args=args)

这行代码的目的就是对__init__.py问价中init函数接口初始化。

  • API Python Business:支撑Application API功能层级
  • API C++ Business:通过C++方式实现支撑整个python API功能层级。提供的方式是把整个C++模块编译为_rclpy_pybind11 库让Python使用。其中在_rclpy_pybind11.cpp文件中将 ROS 2 的 C++ 接口绑定到 Python,从而使得 Python 用户可以使用 C++实现业务功能。
// Provide singleton access to the rclpy C modules.
rclpy_implementation = import_c_library('._rclpy_pybind11', package)

Services框架

Services通信方式的功能主要是由Server端和Client端进行实现,
User Application层级中Server和Client主干逻辑代码:

//Client.py
class adderClient(Node):def __init__(self, name):super().__init__(name)                                                    # ROS2节点父类初始化self.client = self.create_client(AddTwoInts, 'add_two_ints')              # 创建服务客户端对象(服务接口类型,服务名)while not self.client.wait_for_service(timeout_sec=1.0):                  # 循环等待服务器端成功启动self.get_logger().info('service not available, waiting again...') self.request = AddTwoInts.Request()                                       # 创建服务请求的数据对象        def send_request(self):                                                       # 创建一个发送服务请求的函数self.request.a = int(sys.argv[1])self.request.b = int(sys.argv[2])self.future = self.client.call_async(self.request)                        # 异步方式发送服务请求//Server.py
class adderServer(Node):def __init__(self, name):super().__init__(name)                                                             # ROS2节点父类初始化self.srv = self.create_service(AddTwoInts, 'add_two_ints', self.adder_callback)    # 创建服务器对象(接口类型、服务名、服务器回调函数)def adder_callback(self, request, response):                                           # 创建回调函数,执行收到请求后对数据的处理response.sum = request.a + request.b                                               # 完成加法求和计算,将结果放到反馈的数据中self.get_logger().info('Incoming request\na: %d b: %d' % (request.a, request.b))   # 输出日志信息,提示已经完成加法求和计算return response                                                                    # 反馈应答信息

其中有有几个重要的接口函数:create_client、create_service、call_async,再加一个在创建Server对象之后会调用的函数接口,rclpy.spin(参数为:Server class对象)。三个函数下面会讲解函数调用流程图。

CLient 调用Server流程

Client call

  • User Application创建调用create_client创建出真正实现功能的class CLient,然后再调用call_async发送消息到Server,通过_rclpy_pybind11 C++ lib中实现的C++ class CLient对象,最后再通过rcl_send_request接口调用进入rcl 层级。

Server回复CLient流程

Server response

  • User Application调用create_service创建出class Service,并且在Service中注册回调函数(如上面代码中的:adder_callback),当执行完回调函数处理数据逻辑之后,return response就会调用send_response、继续调用service_send_response到C++ class Service,最后调用rcl_send_response进入rcl module。

Server回调函数触发流程

这个时候我们就会想弄清楚Server注册的回调函数是怎么样被触发的呢?接下来我们就来继续探究!
Server register trigger

  • Server在创建完对象之后会调用spin,这个接口功能是在init中实现,并且获取到SingleThreadedExecutor实例调用spin_once、_spin_once_impl
  • 再调用wait_for_ready_callbacks进入到基类Executor,最后的主干逻辑是在_wait_for_ready_callbacks函数中实现,其中会调用_rclpy.WaitSet,这个函数实现是在API C++ Business中class WaitSet。
  • class WaitSet会调用rcl_wait_set_init进入到rcl Layer,会对rcl wait实例化分配空间创建初始化为subscriptions(DDS 概念),并且创建一个item,并且加入到wait队列中,去真正的等待CLient发送call请求。

当wait被回调函数唤醒之后,会去遍历收到哪个实例的消息:

# get ready entities
subs_ready = wait_set.get_ready_entities('subscription')
guards_ready = wait_set.get_ready_entities('guard_condition')
timers_ready = wait_set.get_ready_entities('timer')
clients_ready = wait_set.get_ready_entities('client')
services_ready = wait_set.get_ready_entities('service')

当Server接收到是clients发送的消息,会解析其中的内容:

for srv in node.services:if srv.handle.pointer in services_ready:if srv.callback_group.can_execute(srv):handler = self._make_handler(srv, node, self._take_service, self._execute_service)yielded_work = Trueyield handler, srv, node

执行_execute_service函数体,其中会触发Server callback函数调用,返回之后调用send_response进入到Server给Client发送消息的熟悉环节。

#使用await_or_execute触发Server callback执行完毕,接收到response之后把response作为参数,调用send_response发送response到Client
async def _execute_service(self, srv, request_and_header):if request_and_header is None:return(request, header) = request_and_headerif request:response = await await_or_execute(srv.callback, request, srv.srv_type.Response())srv.send_response(response, header)

Topics框架

Actions框架

未完待续!持续更新!欢迎大家关注!!!

参考文献

  • User Application代码都是参考:ROS2入门21讲

http://www.ppmy.cn/news/1561010.html

相关文章

PyTorch Geometric框架下图神经网络的可解释性机制:原理、实现与评估

在机器学习领域存在一个普遍的认知误区&#xff0c;即可解释性与准确性存在对立关系。这种观点认为可解释模型在复杂度上存在固有限制&#xff0c;因此无法达到最优性能水平&#xff0c;神经网络之所以能够在各个领域占据主导地位&#xff0c;正是因为其超越了人类可理解的范畴…

PyTorch 中 coalesce() 函数详解与应用示例

PyTorch 中 coalesce() 函数详解与应用示例 coalesce&#xff1a; 美 [ˌkoʊəˈlɛs] 合并&#xff1b;凝聚&#xff1b;联结&#xff0c;注意发音 引言 在 PyTorch 中&#xff0c;稀疏张量&#xff08;Sparse Tensor&#xff09;是一种高效存储和操作稀疏数据的方式。稀疏…

【车载开发系列】限位开关的概念

【车载开发系列】限位开关的概念 这里写目录标题 【车载开发系列】限位开关的概念一. 基本概念二. 限位开关分类2.1&#xff09;接触式开关2.2&#xff09;非接触式开关 三. 限位开关的作用四. 限位开关的工作原理五. 原点开关六. 限位开关有什么优缺点 一. 基本概念 限位开关…

松鼠状态机流转-@Transit

疑问 状态from to合法性校验&#xff0c;都是在代码中手动进行的吗&#xff0c;不是状态机自动进行的&#xff1f; 注解中from状态&#xff0c;代表当前状态 和谁校验&#xff1a;上下文中初始状态 怎么根据注解找到执行方法的 分析代码&#xff0c;创建运单&#xff0c;怎…

第十一章 图论

/* * 题目名称&#xff1a;连通图 * 题目来源&#xff1a;吉林大学复试上机题 * 题目链接&#xff1a;http://t.cn/AiO77VoA * 代码作者&#xff1a;杨泽邦(炉灰) */#include <iostream> #include <cstdio>using namespace std;const int MAXN 1000 10;int fathe…

uniapp实现后端数据i18n国际化

1.在main.js配置请求获取到数据再设置到i18n中&#xff0c; 我这里是通过后端接口先获取到一个多个数据的的json链接&#xff0c;通过链接再获取数据&#xff0c;拿到数据后通过遍历的方式设置i18n //接口数据示例&#xff1a;{"vi": "http://localhost:8899/…

Java中使用JFreeChart生成甘特图

引言 甘特图是一种流行的项目管理工具&#xff0c;用于显示项目的进度和任务分配。它通过条形图显示任务的开始和结束时间&#xff0c;使项目经理能够直观地了解项目的整体情况。在Java开发中&#xff0c;JFreeChart是一个强大的开源图表库&#xff0c;能够生成各种类型的图表…

springboot568医院病历管理系统(论文+源码)_kaic

摘 要 随着信息时代的发展&#xff0c;计算机迅速普及&#xff0c;传统的医院病历管理方式显得不够快捷&#xff0c;这时我们就需要创造更加便利的管理方法&#xff0c;对医院病历信息进行统计&#xff0c;便于医院病历信息进行统一管理。将管理方式转变为信息化、智能化显得尤…