ROS AsyncSpinner 的多线程行为

2023-11-26

我试图了解 ROS 中的 AsyncSpinner 是如何工作的,因为我可能有一些误解。你可以找到类似的问题here.

As seen here它的定义提到:

异步旋转器:产生几个线程(可配置) 将并行执行回调,同时不会阻塞执行该操作的线程 叫它。启动/停止方法允许控制回调的时间 开始处理以及何时应停止。

并且在官方文档中hereAsyncSpinning也被称为多线程Spinning的一种。

因此,我有一个非常简单的示例,其中发布者和订阅者使用 AsyncSpinner 来测试多线程行为。

#include "ros/ros.h"
#include "std_msgs/String.h"

int main(int argc, char **argv)
{
  ros::init(argc, argv, "publisher");
  ros::NodeHandle nh;

  ros::Publisher chatter_pub = nh.advertise<std_msgs::String>("chatter", 1000);

  ros::Rate loop_rate(10);
  while (ros::ok())
  {
    std_msgs::String msg;
    msg.data = "hello world";

    chatter_pub.publish(msg);

    ros::spinOnce();

    loop_rate.sleep();
  }

  return 0;
}

以及定义和使用微调器的订阅者:

#include "ros/ros.h"
#include "std_msgs/String.h"
#include <boost/thread.hpp>

int count = 0;

void chatterCallback(const std_msgs::String::ConstPtr& msg)
{
  count++;
  ROS_INFO("Subscriber %i callback: I heard %s", count, msg->data.c_str());
  sleep(1);
}

int main(int argc, char **argv)
{
  ros::init(argc, argv, "subscriber");
  ros::NodeHandle nh;

  ros::Subscriber sub = nh.subscribe("chatter", 1000, chatterCallback);

  ros::AsyncSpinner spinner(boost::thread::hardware_concurrency());
  ros::Rate r(10);

  spinner.start();
  ros::waitForShutdown();

  return 0;
}

当我运行这两个程序时,我得到以下输出:

[ INFO] [1517215527.481856914]: Subscriber 1 callback: I heard hello world
[ INFO] [1517215528.482005146]: Subscriber 2 callback: I heard hello world
[ INFO] [1517215529.482204798]: Subscriber 3 callback: I heard hello world

正如您所看到的,回调每秒运行一次,并且没有并行调用其他回调。我知道全局回调队列正在履行,因为如果我停止发布者,订阅者将继续从队列中弹出累积的消息。

我知道我不应该阻止回调,但在上面的定义中指出,这不会停止调用它的线程,我猜旋转器创建的其他线程也不会停止。我是否仅仅因为阻止回调而阻止下一个回调?难道我有什么误解?我有点困惑,无法证明回调是并行运行的。也许你还有另一个例子?


简短回答:

ROS 回调默认是线程安全的。这意味着注册的回调只能由一个线程处理,并且并发调用被禁用。第二个线程无法同时访问同一回调。

如果您注册第二个回调,您将看到微调器按预期工作,并且多个线程同时调用您的回调。

ros::Subscriber sub1 = nh.subscribe("chatter", 1000, chatterCallback);
ros::Subscriber sub2 = nh.subscribe("chatter", 1000, chatterCallback);

扩展答案:

异步旋转器尝试call回调队列中的可用回调以速率允许的速度进行。如果回调已经在处理中(由另一个线程)CallResult is TryAgain。这意味着稍后将开始新的尝试。

The 这个锁的实现使用变量allow_concurrent_callbacks_这意味着此行为是可选的。

解决方案:

通过设置正确的值可以允许并发调用SubscribeOptions.allow_concurrent_callbacks默认情况下为 false。因此您需要定义自己的SubscribeOptions。以下是您需要订阅并允许并发回调调用的代码:

ros::SubscribeOptions ops;
ops.template init<std_msgs::String>("chatter", 1000, chatterCallback);
ops.transport_hints = ros::TransportHints();
ops.allow_concurrent_callbacks = true;
ros::Subscriber sub = nh.subscribe(ops);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ROS AsyncSpinner 的多线程行为 的相关文章

随机推荐

  • 窗口卸载事件的本地存储

    我使用本地存储来存储一些数据 用户发出 ajax 请求来获取信息 我将结果存储在存储中 以便下次他请求相同的信息时 我首先在存储中查看它是否存在 现在我意识到 将数据保存在内存中的对象中 并在需要时循环该数据 而不是循环本地存储 实际上更有
  • Delphi 的 WebSocket 客户端实现

    Delphi 有免费的 WebSocket 客户端实现吗 我只找到了这个 WebSockets Delphi 组件 但它不是免费的 这是我的开源库 https github com andremussche DelphiWebsockets
  • Django 2.1 - 'functools.partial' 对象没有属性 '__name__'

    我最近将 Django 从 2 0 7 升级到 2 1 1 出现了一个新错误 其中出现此错误 functools partial object has no attribute name 我想了解我的修复是否正确以及是什么导致了这个新错误的
  • 对核心数据实体进行排序的最佳方法是什么?

    我有一个完全正常工作的核心数据模型 但是当我使用获取请求返回数据时 它的顺序看似随机 对这些数据进行排序的最佳方法是什么 是使用核心数据模型中的另一个表 然后 查询 第一个表吗 或者是将数据拉入数组中 然后以这种方式排序 我不太确定如何做其
  • ggplot 函数在图例下方添加文本

    在 R 中 我想创建一个函数 它接受 ggplot 对象和一些文本并返回 ggplot 对象 方法是在图例下方添加文本 在图的右侧 同时将图例保留在右侧 myplot ggplot iris aes x Sepal Length y Sep
  • 单一来源项目结构有哪些缺点?

    我是目前公司的新人 正在从事由我的直接团队领导编写的项目 该公司通常不使用 C 但我的同事用 C C 编写了高效的代码 只有我们知道如何用 C 编码 我和我的领导 所以没有第三种意见可以涉及 在我对这个项目有了足够的了解之后 我意识到整个结
  • 什么是无界数组?

    什么是无界数组 无界数组和动态分配数组有什么区别 与无界数组相关的常见操作有哪些 就像我们有堆栈数据结构的弹出和推送 无界数组可以 并且通常是 静态分配 实现无界数组时的主要关注点是提供类似动态数组的自由来在运行时决定数组大小 而不会因运行
  • 与序列化相比,使用 MarshalByRefObject 的成本有多高?

    在我的 Azure Web 角色代码中 我有一个CustomIdentity类派生自System Security Principal IIdentity 在某些时候 NET 运行时尝试序列化该类 and 序列化不起作用 试图解决我搜索了很
  • 为什么 range-for 找不到 std::istream_iterator 的 begin 和 end 重载?

    我有这样的代码 std ifstream file filename std ios base in if file good file imbue std locale std locale new delimeter tokens fo
  • 扩展此类以在列表视图中撤消/重做

    我正在使用第三方代码来管理 Windows 窗体项目中的撤消 重做操作 我需要扩展该类来管理列表视图中的撤消 重做操作 这意味着 撤消 重做添加 删除项目和子项目 撤消 重做检查 取消检查行 撤消 重做一些我可能错过的其他重要事情 我不知道
  • 环回模型中的动态属性或聚合函数

    我将如何在环回模型中使用聚合函数 如果我有一个由 mysql 数据库支持的模型 我是否可以让 Model1 与 Model2 具有 hasMany 关系 具有给定的数字属性 并在 Model1 中拥有一个从 Model2 获取该字段的 SU
  • 如何从 php 中的字符串中获取确定数量的单词?

    这就是我正在尝试做的事情 我有一段文本 我想从字符串中提取前 50 个单词 而不切断中间的单词 这就是为什么我更喜欢单词而不是字符 然后我可以使用 left 函数 我知道 str word count var 函数将返回字符串中的单词数 但
  • PL/SQL中如何查看变量的类型?

    PL SQL 中是否有函数可以显示变量的确切类型 例如 SQL 中的 DUMP 函数 我尝试过以下方法 DECLARE l variable INTEGER 1 BEGIN DBMS OUTPUT PUT LINE DUMP l varia
  • 单击文件上传按钮后出现延迟?

    当我单击 选择要上传的文件 即输入类型 文件 时 从单击按钮和选择文件到在按钮旁边显示所选文件之间存在延迟 浏览器是否正在尝试将文件加载到浏览器中 为什么有延迟 接下来 我如何显示 请稍候 消息立即地选择文件后 我尝试了各种 JQ 选项 似
  • javascript 如何判断对象是否存在于数组中

    我有一个 JavaScript 对象数组 与此类似的东西 var objectArray Name A Id 1 Name B Id 2 Name C Id 3 Name D Id 4 现在我试图找出一个对象是否具有给定的属性Name值存在
  • 如何在 jQuery 中选择“this”内的元素?

    我知道我可以这样选择一个元素 ul topnav gt li target css border 3px double red 但我该怎么做 this gt li target css border 3px double red this
  • 将图像存储到 Access 数据库的附件字段中

    我正在编写一个 VB 应用程序 需要在数据库中存储图像 用户在计算机上选择图像 这会以字符串形式提供路径 这是我的尝试 但是我收到错误 INSERT INTO 查询不能包含多值字段 这是我的代码 Dim buff As Byte Nothi
  • 从 SKlearn 决策树中检索决策边界线(x,y 坐标格式)

    我正在尝试在外部可视化平台上创建曲面图 我正在使用 iris 数据集sklearn 决策树文档页面 我还使用相同的方法来创建决策曲面图 但我的最终目标不是 matplot lib 视觉效果 因此从这里我将数据输入到我的可视化软件中 为此 我
  • 为什么我会收到 AttributeError: 'NoneType' object has no attribute 'something'?

    我收到一条错误消息 AttributeError NoneType object has no attribute something 我该如何理解这个消息 哪些一般情况可能会导致这种情况AttributeError 以及如何识别问题 Th
  • ROS AsyncSpinner 的多线程行为

    我试图了解 ROS 中的 AsyncSpinner 是如何工作的 因为我可能有一些误解 你可以找到类似的问题here As seen here它的定义提到 异步旋转器 产生几个线程 可配置 将并行执行回调 同时不会阻塞执行该操作的线程 叫它