ROS 2系统Callback Group概念笔记

核心概念

Callback Group(回调组)是一个管理一个或多个回调函数执行规则的容器。它决定了这些回调函数是如何被节点(Node)的 executor 调度的,特别是当多个回调函数同时就绪时,它们之间是并行执行还是必须串行执行。

理解回调组的关键在于理解它与 Executor 的交互。Executor 是 ROS 2 中负责检查订阅、定时器、服务、动作服务器等是否就绪,并调用其对应回调函数的组件。


为什么需要 Callback Group?

例如一个节点,它有以下组件:

  • 一个激光雷达(Lidar)订阅者:回调函数 lidar_callback,处理高频、数据量大的点云数据。
  • 一个键盘输入订阅者:回调函数 keyboard_callback,处理用户偶尔的按键输入。
  • 一个服务服务器:回调函数 save_data_service_callback,处理保存数据的请求。

如果没有回调组,所有回调函数默认都在同一个组里。当 Executor 发现多个回调函数同时就绪时(例如,正在处理激光数据时用户按下了键),它会将它们全部放入一个队列,然后逐个执行。

这可能会导致一个问题:处理庞大的激光雷达数据可能会阻塞 keyboard_callbacksave_data_service_callback 很长时间,导致用户输入或服务请求响应非常迟钝,体验很差。

回调组就是为了解决这种回调函数之间的相互干扰问题而设计的。


回调组的类型

ROS 2 主要提供了两种类型的回调组:

1. Mutually Exclusive (互斥型) - 默认类型
  • 行为:属于同一个互斥组的所有回调函数不能同时执行。Executor 会像处理一个队列一样,一次只执行其中一个。
  • 类比:单线程。任务一个接一个地做。
  • 适用场景:这是最常用也是默认的类型。适用于回调函数之间没有严格的实时性要求,或者它们会访问共享资源需要互斥锁保护的情况。
2. Reentrant (可重入型)
  • 行为:属于同一个可重入组的所有回调函数可以同时被执行。Executor 会尽可能同时调用它们(如果系统有多个CPU核心,则真正并行)。
  • 警告:使用此类型需要非常小心。你必须确保回调函数是线程安全的。如果它们会访问共享的变量或资源,你必须自己使用锁(如 std::mutex)来保护,否则会导致数据竞争和未定义行为。
  • 类比:多线程。多个任务可以同时进行。
  • 适用场景:适用于那些相互独立、没有共享数据、且对实时性要求很高的回调函数。例如,一个控制电机的高频定时器回调和一个发布状态的低频定时器回调。

使用回调组

你需要在创建订阅者、定时器、服务等之前先创建回调组,然后在创建这些对象时将回调组作为参数传入。

以下是 C++ 和 Python 的示例代码:

C++ 示例
#include “rclcpp/rclcpp.hpp”class MyNode : public rclcpp::Node {
public:MyNode() : Node(”my_node”) {// 1. 创建回调组// 互斥型 (默认就是这个,显式写出更清晰)mutually_exclusive_group_ = this- >create_callback_group(rclcpp::CallbackGroupType::MutuallyExclusive);// 可重入型reentrant_group_ = this- >create_callback_group(rclcpp::CallbackGroupType::Reentrant);// 2. 设置选项,在创建对象时指定所属的回调组rclcpp::SubscriptionOptions options;options.callback_group = mutually_exclusive_group_;// 创建订阅者,并指定它属于 mutually_exclusive_group_lidar_sub_ = this- >create_subscription< sensor_msgs::msg::LaserScan >(/scan”, 10,std::bind(&MyNode::lidar_callback, this, std::placeholders::_1),options); // 传入 options// 对于不需要特殊选项的对象,可以直接传递 callback_group 参数// 这个定时器属于 reentrant_group_,可以和上面的订阅者并行执行timer_ = this- >create_wall_timer(std::chrono::seconds(1),std::bind(&MyNode::timer_callback, this),reentrant_group_); // 直接传入回调组}private:void lidar_callback(const sensor_msgs::msg::LaserScan::SharedPtr msg) {// 处理激光数据,可能很耗时}void timer_callback() {// 定时执行的任务}rclcpp::CallbackGroup::SharedPtr mutually_exclusive_group_;rclcpp::CallbackGroup::SharedPtr reentrant_group_;rclcpp::Subscription< sensor_msgs::msg::LaserScan >::SharedPtr lidar_sub_;rclcpp::TimerBase::SharedPtr timer_;
};int main(int argc, char * argv[]) {rclcpp::init(argc, argv);auto node = std::make_shared< MyNode >();rclcpp::spin(node);rclcpp::shutdown();return 0;
}

回调组与执行器(Executor)的配合

  • SingleThreadedExecutor:即使是可重入组,回调函数也无法真正并行,因为只有一个线程。但 Executor 会通过技巧(如在等待服务响应时切换到其他可执行回调)来模拟并发,提高响应效率。
  • MultiThreadedExecutor:这是发挥可重入组威力的地方。该执行器内部有一个线程池。当一个可重入组有多个回调就绪时,执行器可以从线程池中取出多个线程来真正并行地执行它们。

最佳实践:如果你使用了可重入回调组,通常应该配合 MultiThreadedExecutor 来使用,以实现真正的并行处理。

总结

特性Mutually Exclusive (互斥)Reentrant (可重入)
执行方式串行并行
线程安全不需要额外考虑(默认安全)必须自行保证线程安全
性能可能因长回调导致阻塞响应性更好,资源利用率更高
适用场景默认选择,共享资源需保护实时性要求高,回调间完全独立

核心:Callback Group 是一种强大的工具,让你能够精细地控制节点内部回调函数的执行流程,从而优化节点的响应性和性能,避免不必要的阻塞。在设计复杂的节点时,合理地使用回调组是非常重要的一环。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/93777.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/93777.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Qt——主窗口 mainWindow

主窗口 mainWindow 前面学习的所有代码&#xff0c;都是基于QWidget控件&#xff0c;其更多的是作为别的窗口的部分 现在来学习QMainWindow&#xff0c;即主窗口&#xff0c;其包含以下属性 Window Title&#xff1a;标题栏Menu Bar&#xff1a;菜单栏Tool Bar Area&#xff1a…

无训练神经网络影响下的智能制造

摘要 未训练神经网络&#xff08;Untrained Neural Networks, UNNs&#xff09;作为近年来人工智能领域的新兴范式&#xff0c;正在逐步改变智能制造的发展路径。不同于传统深度学习依赖大规模标注数据与高性能计算资源的模式&#xff0c;UNNs 借助网络结构自身的归纳偏置与初…

微服务自动注册到ShenYu网关配置详解

一、配置逐行详解 shenyu:register:registerType: http # 注册中心类型:使用 HTTP 协议进行注册serverLists: ${shenyu-register-serverLists} # ShenYu Admin 的地址列表props:username: ${shenyu-register-props-username} # 注册认证用户名password: ${shenyu-regi…

时序数据库IoTDB的列式存储引擎

在大数据时代&#xff0c;工业物联网&#xff08;IIoT&#xff09;场景正以前所未有的速度生成着海量的时间序列数据。这些数据通常由成千上万的传感器&#xff08;如温度、压力、转速传感器&#xff09;持续不断采集产生&#xff0c;它们具备鲜明的特点&#xff1a;数据时间属…

JavaScript手录18-ajax:异步请求与项目上线部署

前言&#xff1a;软件开发流程 AJAX&#xff1a;前端与后端的数据交互 前后端协作基础 Web应用的核心是“数据交互”&#xff0c;前端负责展示与交互&#xff0c;后端负责处理逻辑与数据存储&#xff0c;二者通过网络请求协作。 &#xff08;1&#xff09;项目开发流程与岗…

HTB 赛季7靶场 - Enviroment

最近所幸得点小闲&#xff0c;补个档嘞&#xff01;~nmap扫描 nmap -F -A 10.10.11.67dirsearch扫描发现login接口 http://environment.htb/login构造如下payload&#xff0c;让程序报错&#xff0c;其原理在于缺失了rember后会导致报错&#xff0c;从而告诉我们一个新的参数ke…

源码编译部署 LAMP 架构详细步骤说明

源码编译部署 LAMP 架构详细步骤说明 一、环境准备 1. 关闭防火墙和SELinux [roothrz ~]# systemctl stop firewalld [roothrz ~]# systemctl disable firewalld [roothrz ~]# setenforce 02. 配置YUM网络源 [roothrz ~]# curl -o /etc/yum.repos.d/CentOS-Base.repo https://m…

机器学习----PCA降维

一、PCA是什么&#xff1f;主成分分析&#xff08;Principal Component Analysis&#xff0c;PCA&#xff09;是机器学习中最常用的降维技术之一&#xff0c;它通过线性变换将高维数据投影到低维空间&#xff0c;同时保留数据的最重要特征。PCA由卡尔皮尔逊于1901年发明&#x…

ReactNative开发实战——React Native开发环境配置指南

一、开发前准备 1. macOS平台基础工具安装 brew install node18 brew install watchman brew install cocoapods2. 代理配置 npm config set proxy http://127.0.0.1:7890 npm config set https-proxy http://127.0.0.1:7890# 新增扩展建议&#xff08;可选配置&#xff09; ec…

差速转向机器人研发:创新驱动的未来移动技术探索

在科技日新月异的今天&#xff0c;机器人技术作为智能制造与自动化领域的核心驱动力&#xff0c;正以前所未有的速度发展。其中&#xff0c;差速转向机器人以其独特的运动机制和广泛的应用前景&#xff0c;成为了科研与工业界关注的焦点。本文旨在探讨差速转向机器人研发进展&a…

Wireshark捕获电脑与路由器通信数据,绘制波形观察

一、准备工作 电脑发出数据的波形图绘制在我的另一篇博客有详细介绍&#xff1a; 根据Wireshark捕获数据包时间和长度绘制电脑发射信号波形-CSDN博客 路由器发送给电脑数据的波形图绘制也在我的另一篇博客有详细介绍&#xff1a; 根据Wireshark捕获数据包时间和长度绘制路由…

汽车ECU实现数据安全存储(机密性保护)的一种方案

一、 综述在车辆ECU中总是有一些密钥或重要数据需进行机密性保护&#xff0c;但因产品选型、成本等考虑&#xff0c;导致一些ECU的芯片不支持硬件安全模块&#xff08;例如HSM、TEE等&#xff09;。此时&#xff0c;为保障数据的机密性&#xff0c;可考虑通过软件实现数据的安全…

AI 效应: GPT-6,“用户真正想要的是记忆”

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

云计算学习100天-第25天

部署LNMP环境安装软件#在前一天已经安装nginx的基础上安装MariaDB&#xff0c;php和php-fpm yum -y install mariadb mariadb-server mariadb-devel php php-mysqlnd php-fpm #mariadb&#xff08;数据库客户端软件&#xff09;、mariadb-server&#xff08;数据库服务器软件&…

细化的 Spring Boot 和 Spring Framework 版本对应关系

注:本文由ai辅助,个人整理,有问题可留言 Spring Boot 3.x 系列 (基于 Spring Framework 6.x) Spring Boot 版本 对应的 Spring Framework 版本 Java 支持版本 3.1.5 (最新) 6.0.15 Java 17+ 3.1.4 6.0.14 Java 17+ 3.1.3 6.0.12 Java 17+ 3.1.2 6.0.11 Java 17+ 3.1.1 6.0.…

PyTorch API 1

文章目录torch张量创建操作索引、切片、连接与变异操作加速器生成器随机采样原地随机采样准随机采样序列化并行计算局部禁用梯度计算数学运算常量逐点运算归约操作比较运算频谱操作其他操作BLAS 和 LAPACK 运算遍历操作实用工具符号数字导出路径控制流优化方法操作符标签torch.…

基于FPGA的实时图像处理系统(2)——VGA显示彩条和图片

VGA显示彩条和图片 文章目录VGA显示彩条和图片一、VGA简介二、功能设计1、彩条设计2、图片设计三、结果展示四、代码一、VGA简介 VGA(Video Graphics Array)是IBM在1987年随PS/2机⼀起推出的⼀种视频&#xff0c;具有分辨率⾼、显⽰速率快、颜⾊丰富等优点&#xff0c;在彩 ⾊…

【网络运维】Linux 文本处理利器:sed 命令

Linux 文本处理利器&#xff1a;sed 命令 sed 简介 sed&#xff08;Stream Editor&#xff09;是一款非交互式的流编辑器&#xff0c;诞生于 1973–1974 年间的贝尔实验室&#xff0c;由 McMahon 开发。它专为文本处理而生&#xff0c;功能强大&#xff0c;是 Linux 文本处理常…

week2-[一维数组]出现次数

week2-[一维数组]出现次数 题目描述 给定 NNN 个整数A1,A2,…,ANA_1,A_2,\ldots,A_NA1​,A2​,…,AN​。请求出这 NNN 个数中出现次数最多的数的出现次数&#xff0c;以及出现次数最少的数的出现次数。 输入格式 读入包括 222 行。第一行只有 111 个整数 NNN&#xff0c;表示数…

力扣 hot100 Day79

215. 数组中的第K个最大元素 给定整数数组 nums 和整数 k&#xff0c;请返回数组中第 k 个最大的元素。 请注意&#xff0c;你需要找的是数组排序后的第 k 个最大的元素&#xff0c;而不是第 k 个不同的元素。 你必须设计并实现时间复杂度为 O(n) 的算法解决此问题。 class…