当前位置: 首页 > news >正文

ROS2 中的轻量级、自动化、受控回放

一、说明

这篇文章描述了一种在 ROS2 中实现受控重播器的轻量级方法。用以测试中将现象重新播放一遍,以实现调参或故障定位的目的。所有源代码都可以在这里找到。该帖子也可在此处获得。

二、问题:不同步重播

        任何曾经认真开发过 ROS2 的人都会知道这个问题:我们想调试我们的管道或改进算法的微小部分,但当我们反复运行管道时,我们得到了不同的结果。如果我们处于开发的早期阶段,并且我们的管道运行速度不够快,无法实时处理所有数据,我们最终会丢失消息。如果我们在代码中放置断点,我们最终会丢失消息。如果我们在后台的同一台机器上发生了一些完全不相关但半繁重的处理,我们最终会丢失消息。最糟糕的是,症状在每次运行之间可能会有所不同,从完全系统故障到对结果的影响最小,因此我们通常不会直接意识到消息丢失可能是问题所在。

        当然,我们可以非常缓慢地重播所有数据。但是,我们最终会永远等待,直到重播达到我们感兴趣的点。同样,如果我们想在CI服务器上运行管道,我们通常不知道有多少计算资源可用以及我们可以多快地运行我们的系统。

        总结:重播器以固定速率重播其消息,对于算法管道来说,这可能是快或慢。因此,我们要么失去时间,要么得到不确定的结果。

三、方法:受控回放

        解决这个问题的基本思想非常简单:我们需要一个考虑到管道当前状态的受控重放。然而,由于ROS2s的异步和松散耦合设计,实现这一点并非易事。特别是因为我们不想用“仅”开发所需的机制来混淆整个系统。

        不幸的是,ROS2 没有针对这个(在我看来非常明显)问题的构建解决方案。当然,它是开源的,我们可以着手实现我们自己的 ros bag 重播器。但是,如上所述,我们希望在框架内开发一种算法。我们不想先实现框架。幸运的是,到目前为止,ROS2工具已经发展了很多,并且只需相对较少的努力,我们就可以应用一种在实践中可以很好地工作的解决方法。

        这个概念是有一个额外的节点,就像重播者的遥控器一样。每当所有节点通知远程节点它们已准备就绪时,它都会触发新消息的重播。

四、实施

        使用服务客户端体系结构可以相对直接地完成实现,如下所述。包括一个小示例在内的所有代码都可以在这里找到。它也可以很容易地作为 ROS 包包含在内。

        远程是一个附加节点,充当rosbag2_replayer的代理。它使用“突发”服务每 T 秒触发接下来的 N 条消息,并等待每个节点的确认。实现自定义服务确实在调用方的身份旁边传输“就绪”信号。不幸的是,当我们使用突发调用“跳过”袋子时,重播者不会自动关闭。因此,额外的计时器会定期检查模拟时间是否仍在增加,以确定重播是否已结束。这要求重播者发布时钟(-clock),并使用 use-sim-time 参数集运行遥控器。然后,节点可以在重放结束时关闭自身/其整个组合。

        我们可以将其作为可组合节点包含,也可以通过以下方式启动它:

ros2 run controllable_replay remote --ros-args -p use_sim_time:=True -p batch_size:=10 -p period:=0.01 -p automatic_shutdown:=5

这将每 10 毫秒播放 10 条消息,并在重播者处于非活动状态 5 秒后关闭节点。

五、算法节点

        在算法方面,我们需要一些逻辑来通知遥控器我们已经准备好了。在简单节点中,我们可以在每个回调的末尾添加它。在更复杂的节点中,消息和回调之间可能没有一对一的映射。在这种情况下,需要一些额外的逻辑来监视节点的工作负载,例如通过观察输入队列大小。

        对于一个简单的示例,我们将创建一个字符串侦听器节点,该节点计算收到的消息数并模拟具有特定时间长度的繁重任务。任务完成后,它将发布自己的消息并通知远程设备已准备就绪。

#include "Listener.h"
using namespace std::chrono_literals; 
namespace controlled_replay_example { 
Listener::Listener(const rclcpp::NodeOptions& options) : 
rclcpp::Node("Listener", options),
_cliReady{create_client<controlled_replay_interfaces::srv::Ready>("/ready")},
_pub{create_publisher<std_msgs::msg::String>("/hearsay", 10)},
_sub{create_subscription<std_msgs::msg::String>( "/chatter", 10, [&](std_msgs::msg::String::ConstSharedPtr msg) { _ctr++; std::this_thread::sleep_for(get_parameter("task_time").as_double() * 1000ms); // heavy taskauto rq = std::make_shared<controlled_replay_interfaces::srv::Ready::Request>();rq->isready = true; _cliReady->async_send_request(rq); // inform replayer})}, _timer{create_wall_timer(1s, [&]() { RCLCPP_INFO(get_logger(), "Received messages: %ld", _ctr); })} 
{ declare_parameter("task_time", 1.0); } } 
// namespace controlled_replay_example 
#include "rclcpp_components/register_node_macro.hpp" 
RCLCPP_COMPONENTS_REGISTER_NODE(controlled_replay_example::Listener)

我们使用一个包含 464 个字符串消息的包以 100hz 的速率测试上面的示例。我们将模拟一个算法管道,其中包含两个具有不同时间长度的链节点。第一个节点将以 100hz 运行,但第二个节点仅以 2hz 运行。因此,从理论上讲,第一个节点应该能够处理所有消息,但第二个节点会错过一些消息。

在第一次运行中,我们将在没有远程的情况下简单地运行管道。

#!/bin/bash 
ros2 run controlled_replay_example listener --ros-args -p task_time:=0.01 -r __node:=listener1 & 
ros2 run controlled_replay_example listener --ros-args -p task_time:=0.5 -r __node:=listener2 -r chatter:=hearsay -r hearsay:=hearsay1& 
ros2 bag play bag

重放期间的节点图

[INFO] [1695973373.033875499] [listener2]: Received messages: 8 
[INFO] [1695973373.732552274] [listener1]: Received messages: 445

我们可以看到,即使是第一个节点也丢失了一些消息。但是,第一个只处理了8个!

在第二次运行中,我们将使用远程运行管道。


#!/bin/bash
ros2 run controlled_replay_example listener --ros-args -p task_time:=0.01 -r __node:=listener1 &
ros2 run controlled_replay_example listener --ros-args -p task_time:=0.5 -r __node:=listener2 -r chatter:=hearsay -r hearsay:=hearsay1 &
ros2 run controlled_replay remote --ros-args -p batch_size:=1 -p use_sim_time:=True &
ros2 bag play --clock --start-paused bag

具有受控回放的节点图

[INFO] [1695973373.033875499] [listener2]: Received messages: 464 
[INFO] [1695973373.732552274] [listener1]: Received messages: 464

我们可以看到两个节点都收到了所有消息。

六、结论

        我们已经看到了一种在 ROS2 中获得可控重放的简单方法。通过添加一个额外的远程节点,我们可以将大部分任务封装在远离实际管道的地方。遥控器将重播速度减慢到节点可以处理的任何速度,从而避免丢失消息。

此处提供的远程,可以通过 ROS2 包管理包含在内。

七、未解决的问题和未来工作

  • 很快,重播者应该可以作为可组合节点使用。我希望这将进一步提高重播速度。它应该与上述实现顺利配合。
  • 使用这些服务时,ros bag 重播器会向终端发送垃圾邮件,其中包含每个服务的消息,我没有找到一种方法来阻止日志记录部分将其重定向到 /dev/null。但是,这超过了重播者的所有输出
  • 最好找到更简单的方法来监视节点的工作负载,甚至可能是外部的工作负载。例如,如果我们能以某种方式访问待处理的回调,这已经有所帮助,但我没有找到做到这一点的方法。

相关文章:

ROS2 中的轻量级、自动化、受控回放

一、说明 这篇文章描述了一种在 ROS2 中实现受控重播器的轻量级方法。用以测试中将现象重新播放一遍&#xff0c;以实现调参或故障定位的目的。所有源代码都可以在这里找到。该帖子也可在此处获得。 二、问题&#xff1a;不同步重播 任何曾经认真开发过 ROS2 的人都会知道这个问…...

Egg使用jwt拦截jtoken验证

安装 npm install egg-jwt注册插件 在config文件夹子下 plugin,js下 use strict;module.exports {//mysqlmysql: {enable: true,package: egg-mysql},//jwtjwt: {enable: true,package: egg-jwt} };使用中间件 在app文件下创建 middleware 文件夹 在middleware 文件下创建…...

装饰器模式详解和实现(设计模式 二)

装饰器模式&#xff08;Decorator Pattern&#xff09;是一种结构型设计模式&#xff0c;它允许你动态地将对象添加到现有对象中&#xff0c;以提供额外的功能&#xff0c;同时又不影响其他对象。 实现示例 1.定义一个接口或抽象类&#xff0c;表示被装饰对象的公共接口 //抽…...

面试问到MySQL模块划分与架构体系怎么办

面试问到Mysql模块划分与架构体系怎么办 文章目录 1. 应用层连接管理器&#xff08;Connection Manager&#xff09;安全性和权限模块&#xff08;Security and Privilege Module&#xff09; 2. MySQL服务器层2.1. 服务支持和工具集2.2. SQL Interface2.3. 解析器举个解析器 …...

并查集及其优化

1.并查集 #define SIZE 100 int UFSets[SIZE];void Initial(int S[]) {for (int i 0; i < SIZE; i)S[i]-1; }int Find(int S[], int x) {//查while(S[x] > 0)x S[x];return x; }void Union(int S[], int Root1, int Root2) {//并if(Root1 Root2)return;S[Root2] Roo…...

LeetCode 周赛上分之旅 #48 一道简单的树上动态规划问题

⭐️ 本文已收录到 AndroidFamily&#xff0c;技术和职场问题&#xff0c;请关注公众号 [彭旭锐] 和 BaguTree Pro 知识星球提问。 学习数据结构与算法的关键在于掌握问题背后的算法思维框架&#xff0c;你的思考越抽象&#xff0c;它能覆盖的问题域就越广&#xff0c;理解难度…...

mysql报错:Column Count Doesn‘t Match Value Count at Row 1

mysql中执行insert、update、delete报错&#xff1a;Column Count Doesnt Match Value Count at Row 1 的解决方案 通常情况&#xff1a;字段不匹配 如&#xff1a;student有id, name, age字段 -- 错误写法 INSERT INTO student VALUES(5,horse)-- 正确写法 INSERT INTO stu…...

安卓 kuaishou 设备did和egid 学习分析

did和egid注册 接口 https://gdfp.ksapisrv.com/rest/infra/gdfp/report/kuaishou/android did 是本地生成的16进制 或者 获取的 android_id public static final Random f16237a new Random(System.currentTimeMillis()); public static long m19668a() { return f1623…...

基于Vue+ELement实现增删改查案例与表单验证(附源码)

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是Java方文山&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的专栏《ELement》。&#x1f3af;&#x1f3af; &#x1…...

webpack:使用externals配置来排除打包后的某个依赖插件IgnorePlugin的使用

背景 假设&#xff0c;我们写了一个库并使用 webpack 打包输出 bundle&#xff0c;但是这个库依赖一个第三方包&#xff0c;比如依赖 lodash&#xff0c;这时候我们不想把这个库打包进 bundle 里因为体积会变大&#xff0c;而且我们的主项目里已经安装了这个 lodash&#xff0…...

2023年中国工业脱水机行业供需分析:随着自动化和智能化技术的快速发展,销量同比增长4.9%[图]

工业脱水机行业是指专门从湿润的固体物料中去除水分的设备制造和相关服务。它广泛应用于食品加工、化工、制药、纺织、环保等行业&#xff0c;用于去除物料中的水分&#xff0c;提高产品质量和降低能耗。 工业脱水机行业分类 资料来源&#xff1a;共研产业咨询&#xff08;共研…...

[论文笔记]MacBERT

引言 今天带来MacBERT的阅读笔记。论文题目是 重新审视中文自然语言处理的预训练模型。 本篇主要是探讨中文预训练语言模型在非英文语言中的有效性,然后提出了一种简单而有效的模型,称为MacBERT,它在多个方面改进了RoBERTa,特别是采用纠错型掩码语言模型(MLM as correcti…...

AI发展目前最大挑战是什么?

影响AI成本的因素包括多个方面&#xff1a; 首先&#xff0c;AI技术的复杂性是其成本高昂的一个重要原因。AI技术需要进行大量数据处理、模型训练和优化&#xff0c;这需要耗费大量的计算资源和时间。同时&#xff0c;AI技术需要高水平的专业人才进行设计、开发和维护&#xf…...

自然语言处理NLP:LTP、SnowNLP、HanLP 常用NLP工具和库对比

文章目录 常见NLP任务常见NLP工具英文NLP工具中文NLP工具 常见NLP任务 Word Segmentation 分词 – Tokenization Stem extraction 词干提取 - Stemming Lexical reduction 词形还原 – Lemmatization Part of Speech Tagging 词性标注 – Parts of Speech Named entity rec…...

百度交易中台之内容分润结算系统架构浅析

作者 | 交易中台团队 导读 随着公司内容生态的蓬勃发展&#xff0c;内容产出方和流量提供方最关注的“收益结算”的工作&#xff0c;也就成为重中之重。本文基于内容分润结算业务为入口&#xff0c;介绍了实现过程中的重难点&#xff0c;比如千万级和百万级数据量下的技术选型和…...

【索引】常见的索引、B+树结构、什么时候需要使用索引、优化索引方法、索引主要的数据结构、聚簇索引、二级索引、创建合适的索引等重点知识汇总

目录 索引的分类 什么时候需要 / 不需要创建索引&#xff1f; 有什么优化索引的方法 MySQL索引主要使用的两种数据结构是什么 为什么 MySQL 采用 B 树作为索引 聚簇索引和二级索引 根据给定的表&#xff0c;如何创建索引比较好 索引的分类 普通索引&#xff1a;最基本的…...

Egg 封装接口返回信息

中间件封装 代码 const msgArr {"200":成功,"401":token失效 } module.exports (option, app) > {return async function(ctx, next) {try{//成功是返回的信息ctx.emit(code,data,msg)>{console.log(1111,code,data,msg)ctx.body {code,data:dat…...

Android AMS——创建APP进程(五)

接上一篇,在 ActivityTaskSupervisor 中会判断进程是否存在,如果进程不存在,则会创建进程,执行 startProcessAsync() 方法。如果进程存在,则执行 realStartActivityLocked() 方法。在APP 的启动时,进程是不存在的。所以我们先来分析一下进程不存在的情况。 一、创建进程…...

凉鞋的 Unity 笔记 102. 场景层次 与 GameObject 的增删改查

102. 场景层次 与 GameObject 的增删改查 在上一篇&#xff0c;我们完成了 Unity 引擎的 Hello world 输出&#xff0c;并且完成了第一个基本循环&#xff1a; 通过这次基本循环的完成&#xff0c;我们获得了一点点的 Unity 使用经验&#xff0c;这非常重要。 有实践经验后再…...

信息安全:网络安全审计技术原理与应用.

信息安全&#xff1a;网络安全审计技术原理与应用. 网络安全审计是指对网络信息系统的安全相关活动信息进行获取、记录、存储、分析和利用的工作。网络安全审计的作用在于建立“事后“安全保障措施&#xff0c;保存网络安全事件及行为信息&#xff0c;为网络安全事件分析提供线…...

ES6从入门到精通:前言

ES6简介 ES6&#xff08;ECMAScript 2015&#xff09;是JavaScript语言的重大更新&#xff0c;引入了许多新特性&#xff0c;包括语法糖、新数据类型、模块化支持等&#xff0c;显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var&#xf…...

MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例

一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...

FastAPI 教程:从入门到实践

FastAPI 是一个现代、快速&#xff08;高性能&#xff09;的 Web 框架&#xff0c;用于构建 API&#xff0c;支持 Python 3.6。它基于标准 Python 类型提示&#xff0c;易于学习且功能强大。以下是一个完整的 FastAPI 入门教程&#xff0c;涵盖从环境搭建到创建并运行一个简单的…...

Java - Mysql数据类型对应

Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...

WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)

一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解&#xff0c;适合用作学习或写简历项目背景说明。 &#x1f9e0; 一、概念简介&#xff1a;Solidity 合约开发 Solidity 是一种专门为 以太坊&#xff08;Ethereum&#xff09;平台编写智能合约的高级编…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA

浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求&#xff0c;本次涉及的主要是收费汇聚交换机的配置&#xff0c;浪潮网络设备在高速项目很少&#xff0c;通…...

Caliper 负载(Workload)详细解析

Caliper 负载(Workload)详细解析 负载(Workload)是 Caliper 性能测试的核心部分,它定义了测试期间要执行的具体合约调用行为和交易模式。下面我将全面深入地讲解负载的各个方面。 一、负载模块基本结构 一个典型的负载模块(如 workload.js)包含以下基本结构: use strict;/…...

Caliper 配置文件解析:fisco-bcos.json

config.yaml 文件 config.yaml 是 Caliper 的主配置文件,通常包含以下内容: test:name: fisco-bcos-test # 测试名称description: Performance test of FISCO-BCOS # 测试描述workers:type: local # 工作进程类型number: 5 # 工作进程数量monitor:type: - docker- pro…...

HTML前端开发:JavaScript 获取元素方法详解

作为前端开发者&#xff0c;高效获取 DOM 元素是必备技能。以下是 JS 中核心的获取元素方法&#xff0c;分为两大系列&#xff1a; 一、getElementBy... 系列 传统方法&#xff0c;直接通过 DOM 接口访问&#xff0c;返回动态集合&#xff08;元素变化会实时更新&#xff09;。…...

Vue3 PC端 UI组件库我更推荐Naive UI

一、Vue3生态现状与UI库选择的重要性 随着Vue3的稳定发布和Composition API的广泛采用&#xff0c;前端开发者面临着UI组件库的重新选择。一个好的UI库不仅能提升开发效率&#xff0c;还能确保项目的长期可维护性。本文将对比三大主流Vue3 UI库&#xff08;Naive UI、Element …...