ROS2 callback回调不成功问题(转)

【ROS】在回调函数中发布消息 在ROS中,想在回调函数中发布消息,有两个思路:(1)把函数写成类的形式,把需要的一些变量在类中声明为全局变量。【推荐,模块化好】(2)在函数中,把回调函数需要调用的变量声明为全局变量。也可以解决这个问题。【不好,不符合面向对象的风格】 #include <ros/ros.h> class SubscribeAndPublish { ... 阅读详情

结论:

ROS2 的 node中使用的如果node不添加到spin中,则timer、service、action等的callback函数无法正常回调。

但是如果在service、action调用之后,调用如下函数则可正常回调。原因是spin_until_future_complete函数内部会创建一个executor,添加nh_这个Node

rclcpp::spin_until_future_complete(this->get_node_base_interface(), future_goal_handle, std::chrono::seconds(5));


文章目录
1.node的构成
2.executor
3.出错的程序
        3.1 node_main.cpp,正常执行
        3.2 照抄官方文档中client 的response报错
1.node的构成
rclcpp::Node的成员变量有一些interface,例如
node_base:可以记录node的基本状态,例如:
        node的name;
        node的call_back_group
        node的associated_with_executor_,即是否与executor绑定,以此确定只跟一个executor有关系
node_graph
node_services
node_topics:显而易见用来创建publisher,subscriber等
2.executor
用来在node 调用spin(内部循环)时,执行node内部的callback函数。
一个executor可以添加多个node,及为不同的node执行callback函数
executor分singleThreadExecutor和multiThreadExecutor。即单线程执行和多线程执行。
singleThreadExecutor添加多个node时,顺序执行call_back
multiThreadExecutor添加多个node时,多线程执行call_back
一个node只能被一个executor添加,
在executor.add(node)函数中会检查
node是否已经被其他executor添加(即查看node.node_base.associated_with_executor_是否为true)
或node是否已被此executor添加过
3.出错的程序
3.1 node_main.cpp,正常执行

rclcpp::init(argc, argv);
rclcpp::executors::SingleThreadedExecutor executor;
 
auto node = std::make_shared<robotis::localization::LocalizationNode>(rclcpp::NodeOptions());
executor.add_node(node);
std::atomic_bool & has_executor  =  node->get_node_base_interface()->get_associated_with_executor_atomic();
//此时会成功输出,因为上面的executor已成功添加node
if (has_executor.exchange(true)) {
    printf("yes yes yes yes yes yes\n");
}
executor.spin();
rclcpp::shutdown();
return EXIT_SUCCESS;

3.2 照抄官方文档中client 的response报错
我的service定义

string data
---
Int32 num

接收到一个随便的std_msgs::msg::Int32数据后调用mySubCallback函数,在其中call service

void mySubCallback(const std_msgs::msg::Int32::SharedPtr msg){
    printf("recieve a msg:%d\n",msg->data);
    std::string data =std::to_string(pose_msg->data);
    auto request = std::make_shared<my_msgs::srv::MyService::Request>();
    request->data = data;
    while (!my_client_->wait_for_service(std::chrono::seconds(1))) {
        if (!rclcpp::ok()) {
            RCLCPP_ERROR(nh_->get_logger(), "Interrupted while waiting for the service. Exiting.");
            return;
        }
        RCLCPP_INFO(nh_->get_logger(), "service not available, waiting again...");
    }
    auto result = my_client_->async_send_request(request);
    //以下报错
    if (rclcpp::spin_until_future_complete(nh_, result) == rclcpp::executor::FutureReturnCode::SUCCESS){
        int num= int(result.get()->num);
        printf("result:num:%d\n",num);
    }
    else {
        RCLCPP_ERROR(nh_->get_logger(), "Failed to call service");
    }
 
}


执行到rclcpp::spin_until_future_complete(nh_, result)时会报错"Node has already been added to an executor"。原因是spin_until_future_complete函数内部会创建一个executor,添加nh_这个Node,但一个node不允许被多个executor添加,所以报了错。

由于这个Node已经在main函数中被添加,所以直接接收response即可

void mySubCallback(const std_msgs::msg::Int32::SharedPtr msg){
    printf("recieve a msg:%d\n",msg->data);
    std::string data =std::to_string(pose_msg->data);
    auto request = std::make_shared<my_msgs::srv::MyService::Request>();
    request->data = data;
    while (!my_client_->wait_for_service(std::chrono::seconds(1))) {
        if (!rclcpp::ok()) {
            RCLCPP_ERROR(nh_->get_logger(), "Interrupted while waiting for the service. Exiting.");
            return;
        }
        RCLCPP_INFO(nh_->get_logger(), "service not available, waiting again...");
    }
    //成功执行
    using ServiceResponseFuture =
        rclcpp::Client<my_msgs::srv::MyService>::SharedFuture;
      auto response_received_callback = [this](ServiceResponseFuture future) {
          RCLCPP_INFO(nh_->get_logger(), "Got result: [%d]", future.get()->num);
        };
      auto future_result = my_client_->async_send_request(request, response_received_callback);

}

ROS2 Executor与Callback Group深度解析:回调调度与并发控制实战 在机器人开发中,节点回调的执行效率直接决定系统的实时性与稳定性。很多开发者遇到订阅频率骤降、回调互相阻塞甚至死锁时,往往首先排查QoS、网络或消息大小,却忽略了底层调度机制。ROS2的Executor作为调度中枢,负责从等待队列中取出回调并分配线程执行;而Callback Group则约定哪些回调可以并行,两者共同决定了并发行为。理解这两种机制,是掌握ROS2多线程编程、突破单线程瓶颈的关键。本文将拆解Executor调度原理、互斥组与可重入组的区别,提供C++与Python的分组配置范例,并结合工程实践给 阅读详情

相关推荐

【ROS2】spin、spinOnce、spin_some、spin_until_future_complete

【ROS2】spin、spinOnce、spin_some、spin_until_future_complete函数示例

郭老二 799

ROS2(三) -一个报错引发的executor,node的思考

本人使用版本为ROS2-dashing版本。 由于学习ROS2时十分匆忙,只把它当成一个通讯工具,所以看官方文档时并没有仔细思考,目的是能用就行,到具体报错时才不得不去看源代码找答案。即便写代码时知道Node,Executor如何定义,但对于这两个东西的内部实现并不了解。直到使用官方文档(service and client)的Client代码抄出了问题… 以下是我浅显的想法,如果有问题欢迎指正。 文章目录1.node的构成2.executor3.出错的程序3.1 node_main.cpp,正常执行3.2

虎哥的铲屎员 3957

【ROS2开发】关于节点的回调函数

ROS2是用C11以上的工具开发的,内容晦涩难懂,必须处处深挖,才能自己编程。本篇主要对最简单的Topic程序做了一个分解。这只是个开篇,至于更深刻的,还在后面。

gongdiwudu的专栏 8271

ROS回调函数进不去的可能原因

ROS回调函数进不去的可能原因

guaijie0530的博客 2310

ENU坐标系实战:5分钟搞定无人机导航中的站心坐标转换

本文针对无人机导航中GPS坐标与视觉感知不匹配的定位漂移问题,提供了基于ENU坐标系的实战解决方案。通过Python代码演示了如何快速、精准地实现地心地固坐标与站心坐标之间的转换,并详细解释了转换原理、精度对比及工程优化技巧,帮助开发者从根本上解决局部相对定位不准的难题。

mqtt6iot的博客 552

单细胞基因可视化之热图的根本改造2

我们前面已经说过了单细胞marker/或者其他任意基因的热图的简单修饰(单细胞基因可视化之热图改造修饰1),仅仅是基于颜色和DoHeatmap函数的参数修饰。那么要对热图进行根本的改造,关键点在于提取表达矩阵,然后对分组进行注释,就可以使用heatmap或者ComplexHeatmap来做图了。 首先计算marker基因,然后选择自己需要展示的基因。 library(Seurat) library(stringr) library(dplyr) all.markers <- Find

qq_42090739的博客 6675

ROS学习(2)( service and client)

无

qq_44632658的博客 1397

螺丝锁付系统软件设计 C# Winform

视觉螺丝锁付系统软件设计 C# Winform ,这是其中通信子模块设计

weixin_42522973的博客 340

ROS2 callback回调不成功问题

ROS2 callback回调不成功问题

jixiangwangzi的博客 3065

ITKMontage---ITK自动拼接模块

本文分享ITK中Remote中的ITKMontage拼接模块,希望对各位小伙伴有所帮助!1. ITKMontage介绍在医疗图像处理过程中,图像拼接有很多用处,比如DR图像的拼接。ITKMontage可以快速稳定的处理数据量较大的拼接图像。强度不均匀性校正配准全局优化融合2. ITKMontage安装ITKMontageITKMontage可脱离ITK进行单独安装,也可在ITK安装时作为模块进行安装。单独安装ITK模块安装在ITK编译时,选择ITKMontage模块。

qq_40041064的博客 449

从零到一:Python+Playwright 实现动态网站全量数据采集实战(附反爬对抗与性能优化)

在动手之前,先明确武器优势: 2. 项目结构规划 为了代码可维护性,我们采用模块化结构: 三、核心实战:构建动态采集器 第一步:初始化“隐身”浏览器 普通启动容易被检测,我们需要注入一段 JS 脚本来抹除自动化特征。 第二步:处理无限滚动与动态加载 这是动态网站的核心难点。我们需要模拟人类滚动,并等待新数据加载完成。 第三步:登录态保持与复用 避免每次运行都重新登录。我们将 Cookie 保存到本地,下次直接加载。 第四步:主流程编排 将上述模块串联起来,并加入异常重试机制。 四、进阶优化:性能与反爬

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 1161

ROS2 执行器(Executor)与回调组(Callback Group)

ROS2执行器与回调组核心机制解析 摘要:ROS2框架通过执行器(Executor)和回调组(Callback Group)协同实现事件驱动模型。执行器负责调度节点回调函数,分为单线程、多线程和静态单线程三种类型,分别适用于不同并发场景。回调组则定义回调的并发规则,包括互斥型(MutuallyExclusive)和可重入型(Reentrant),前者保证组内串行执行,后者允许并行但需手动处理线程安全。多线程执行器下,不同回调组的回调可并行执行,而单线程执行器则强制所有回调串行。实际开发中,应根据任务特性合理

MzKyle的博客 1576

uniapp - 实现手机端H5网页直播功能效果,拿到后端推流地址或播放资源后进行前端的流畅播放和画面展示功能,uniapp实时推流/拉流直播系统详细教程(提供完整示例代码,一键复制开箱即用!)

uniapp,h5网页,手机端H5网页,uniapp h5直播功能页面,uniapp直播实时推送显示,uniapp h5直播怎么做,怎么使用uniapp去实现移动端手机H5直播,h5 vue+uniapp怎么做直播,uniapp中使用videojs构建H5直播播放器,uniappH5端怎么实现直播推流,uniapp如何实现直播,直播聊天功能,h5平台端直播用什么插件,uniapp手机网页直播用什么组件插件播放器,uniapp手机H5直播播放器详细教程,直播项目,怎么使用vue+uniapp怎么做H5实时直播

✅ 精选推荐文章 8792

【ROS】回调的多线程问题

从执行结果中可以看到,进程中包括四个线程:主线程、全局队列Spinner线程1、全局队列Spinner线程2,以及本地队列Spinner线程3。这就说明了单线程的不足,不管有多少个Subscriber,节点都只能顺序执行回调,这在某些时候是不能忍受的,因此,多线程有了用武之地,我们要做的事情就是增加spinner thread。在实际项目中,如果订阅回调中有耗时操作,那么可以用户可以启用多个Spinner线程并发从Callback队列中取出已可用的回调并执行,这样可以加快Callback队列被执行的速度。

lemonxiaoxiao的博客 3926

提示词编写:从新手到专家的进阶之路

本文旨在为提示词编写者提供一条从新手到专家的进阶之路。我们将详细探讨提示词编写的背景与意义、基础与进阶技巧、实战应用以及最佳实践。通过逐步深入的分析与实操,读者将掌握提示词编写的核心要点,提高编写效率和作品质量。提示词是用于引导人工智能生成文本的关键词或短语,它包含了作者想要传达的主题、情感和细节。随着人工智能技术的普及,自动化写作工具逐渐应用于各行各业。为了提高写作效率,项目团队决定开发一款基于人工智能的自动化写作工具。成功开发了一款自动化写作工具,生成文本质量较高。

AI天才研究院 1085

OpenCV实例(八)车牌字符识别技术(三)汉字识别

相较于数字和英文字符的识别,汽车牌照中的汉字字符识别的难度更大,主要原因有以下4个方面:(1)字符笔画因切分误差导致非笔画或笔画流失。(2)汽车牌照被污染导致字符上出现污垢。(3)采集所得车辆图像分辨率低导致多笔画的汉字较难分辨。(4)车辆图像采集时所受光照影响的差异导致笔画较淡。综合汉字识别时的这些难点来看,很难被直接提取的是字符的局部特征。笔画作为最重要的特征而仅存在于汉字中,这由先验知识可知。一旦捺、横、竖、撇这些笔画特征被提取到,对于汉字字符识别的工作就完成了许多。

小幽余生不加糖 1649

ROS从callback中获取数据在回调函数以外使用

ROS回调函数中的数据如何在回调函数以外使用 关于回调函数的理解或者示例请自行谷歌吧。由于回调函数的定义,其处理的是被调用者的数据,所以一般在调用者那里无法获得回调函数里面的数据,要想在回调函数以外使用回调函数内的数据,目前好像只能借助类来实现了。下面是是根据ROS官方教程-使用类方法作为回调函数稍加改动实现的。 #include <ros/ros.h> #include <st...

xinwenfei的专栏 1万+

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

ros callback 回调机制 & 订阅队列长度

实验程序: talker.cc #include <std_msgs/Int32.h> #include <ros/ros.h> int main(int argc, char **argv) { ros::init(argc, argv, "talker"); ros::NodeHandle nh; std_msgs::Int32 data; data.data = 0; ros::Publisher pub = nh.adve.

A_L_A_N 6595

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

ROS 2系统Callback Group概念笔记

ROS 2中的回调组(Callback Group)是管理回调函数执行规则的容器,决定回调函数是并行还是串行执行。它解决了多个回调函数相互干扰的问题,如高频数据处理阻塞其他回调。ROS 2提供两种回调组类型:互斥型(默认,串行执行)和可重入型(并行执行,需确保线程安全)。使用时需在创建订阅者/定时器等对象时指定所属回调组,并与执行器(SingleThreaded/MultiThreadedExecutor)配合使用。回调组是优化节点响应性和性能的重要工具,合理使用可避免不必要阻塞。

yinminsumeng的博客 1184

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

ROS2(四)- MultiThreadedExecutor多线程调用callback funcs

如何多线程调用callback funcs1.callback_group2.node默认的组别3.使用singleThreadedExecutor,想要多线程调用callback3.1 可设置不同的MutuallyExclusive callback_group3.2 设置同一个Reentrant callback_group 本想使用多线程executor执行node,没想到简单的创建Subscription之后callback funcs竟然是顺序执行的,所以仔细看了一下,原来node中还有callb

虎哥的铲屎员 9253

如何在 ROS 2 中使用多线程执行器(Multi-Threaded Executor)和回调组(Callback Groups)

在 ROS 2 中,回调组(Callback Groups)主要用于管理节点中的各种回调,以控制它们的执行方式和并发行为。订阅者(Subscribers)当你创建一个订阅者时,可以指定一个回调组。这样可以控制订阅者回调的执行方式,例如是否与其他回调并行执行。计时器(Timers)计时器的回调也可以通过回调组来管理。这对于需要定期执行的任务非常有用,你可以通过回调组来控制这些任务的并发执行。服务服务器(Service Servers)服务服务器的回调可以使用回调组来管理。

qq_53044655的博客 3528

ROS的多线程2-调度机制

ROS 共有四种类型的回调,分别绑在不同的对象上:订阅回调:ros::subscriber请求回调:ros::servivceserver行动回调:ros::simpleactionserver定时器回调:ros::Timer而callback 一般是在ros框架下,我们来写的,为了实现自己的某种功能的实现。

ZPC8210的博客 1704

ros话题订阅成功,但是callback不触发

如上图所示,加上判断语句之后,虽然话题订阅成功但是不触发callback。 解决方法,把ros::Subscriber sub_sensor1_等写在.h文件中,在该图呈现的效果为

weixin_45024226的博客 3308

ROS2回调处理机制executor+callbackgroup

rclpy中有SingleThreadedExecutor和MultiThreadedExecutor两种类型的executor。SingleThreadedExecutor使用一个线程排队处理多个消息或事件。MultiThreadedExecutor可创建多个线程(可配置)以并行处理多个消息或事件。ROS2 以组的形式组织节点的回调。ROS2提供两种类型的回调组:互斥回调组Mutually Exclusive Callback Group。重入回调组Reentrant Callback Group

weixin_60864335的博客 5404

【代码学习】ROS2参数声明与回调执行顺序解析

的,只要声明在回调触发前完成(本例中必然满足),就能安全访问参数。的操作,而定时器回调是。

wuwu_csdn的博客 966

ROS2 Executor 与 Callback Group 关系分析

本文分析了ROS2中Executor与Callback Group的关系。Executor是核心调度组件,负责管理通信任务的执行顺序,包含单线程、多线程等不同类型。Callback Group用于组织相关回调逻辑,分为互斥(MutuallyExclusive)和可重入(Reentrant)两种类型,分别控制回调的串行和并行执行。文章通过类图和数据流展示了二者的架构关系,并详细介绍了创建回调组和注册回调实体的方法。不同类型的Executor和Callback Group组合可满足不同场景的并发需求。

liu-yonggang的专栏 436
上一篇: 录包磁盘IO高导致系统卡顿问题排查&&解决
下一篇: ROS2录包---工程疑难问题解决&&性能优化&&个人反思总结
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值