设计模式——方法链or流式接口
方法链或流式接口是一种编程模式或设计模式。核心思想是通过返回对象自身的应用,使得可以在一个表达式中连续调用多个方法。
c++中实现这种模式
1.基本语法规则
(1)每个可链接的方法都返回对象自身的引用(通常是*this);
(2)方法通常返回的类型为className&或className*;
2.实现示例
class ChainableClass {
public:ChainableClass& method1(int param) {// 方法1的实现return *this;}ChainableClass& method2(std::string param) {// 方法2的实现return *this;}void finalMethod() {// 最终方法,可能不返回 *this}
};
3.使用示例
ChainableClass obj;
obj.method1(10).method2("hello").finalMethod();
4.实现细节
(1)确保每个可链接的方法都返回 *this。
(2)通常,只有不需要返回特定值的方法才适合这种模式。
(3)最后一个方法可能不返回 *this,而是执行某些最终操作。
5.实际应用实现一
实现从rosbag中读取2d scan并plot的结果
namespace sad {
/*** ROSBAG IO* 指定一个包名,添加一些回调函数,就可以顺序遍历这个包*/
class RosbagIO {public:explicit RosbagIO(std::string bag_file, DatasetType dataset_type = DatasetType::NCLT): bag_file_(std::move(bag_file)), dataset_type_(dataset_type) {assert(dataset_type_ != DatasetType::UNKNOWN);}using MessageProcessFunction = std::function<bool(const rosbag::MessageInstance &m)>;/// 一些方便直接使用的topics, messagesusing Scan2DHandle = std::function<bool(sensor_msgs::LaserScanPtr)>;// 遍历文件内容,调用回调函数void Go();/// 通用处理函数RosbagIO &AddHandle(const std::string &topic_name, MessageProcessFunction func) {process_func_.emplace(topic_name, func);return *this;}/// 2D激光处理RosbagIO &AddScan2DHandle(const std::string &topic_name, Scan2DHandle f) {return AddHandle(topic_name, [f](const rosbag::MessageInstance &m) -> bool {auto msg = m.instantiate<sensor_msgs::LaserScan>();if (msg == nullptr) {return false;}return f(msg);});}/// 多回波2D激光处理RosbagIO &AddMultiScan2DHandle(const std::string &topic_name, MultiScan2DHandle f) {...}.../// 清除现有的处理函数void CleanProcessFunc() { process_func_.clear(); }private:std::map<std::string, MessageProcessFunction> process_func_;std::string bag_file_;DatasetType dataset_type_;...
};} // namespace sadvoid RosbagIO::Go() {rosbag::Bag bag(bag_file_);LOG(INFO) << "running in " << bag_file_ << ", reg process func: " << process_func_.size();if (!bag.isOpen()) {LOG(ERROR) << "cannot open " << bag_file_;return;}auto view = rosbag::View(bag);for (const rosbag::MessageInstance &m : view) {auto iter = process_func_.find(m.getTopic());if (iter != process_func_.end()) {iter->second(m);}if (global::FLAG_EXIT) {break;}}bag.close();LOG(INFO) << "bag " << bag_file_ << " finished.";
}int main(int argc, char** argv) {...sad::RosbagIO rosbag_io(fLS::FLAGS_bag_path);rosbag_io.AddScan2DHandle("/pavo_scan_bottom",[](Scan2d::Ptr scan) {cv::Mat image;sad::Visualize2DScan(scan, SE2(), image, Vec3b(255, 0, 0));cv::imshow("scan", image);cv::waitKey(20);return true;}).Go();return 0;
}
简单几点解释
a.方法链:
每个方法(如AddScan2DHandle)返回RosbagIO对象的引用(*this),这允许我们继续在返回值上调用其他方法。
b.注册过程:
.AddScan2DHandle()方法注册了一个处理函数,用于处理特定话题(“/pavo_scan_bottom”)的2D激光扫描数据。
using MessageProcessFunction = std::function<bool(const rosbag::MessageInstance &m)>;
std::map<std::string, MessageProcessFunction> process_func_;
process_func_是一个map类型,键为话题名字,值为函数指针即注册的话题对应的处理函数。
c.执行过程:
.Go()方法是实际开始处理ROS bag文件的触发器。它会遍历bag文件中的所有消息,并对每个匹配的消息调用相应的处理函数。
总结如下:
Go中变量bag文件中每个消息,每个消息都是一个MessageInstance;
调用AddHandle注册的函数———AddScan2DHandle注册的lambda函数(f)————继续调用f(msg),实现点云scan显示。
6.实际应用实现二
//定义类
class TxtIO {public:TxtIO(const std::string &file_path) : fin(file_path) {}// 定义函数指针using IMUProcessFuncType = std::function<void(const IMU &)>;using OdomProcessFuncType = std::function<void(const Odom &)>;using GNSSProcessFuncType = std::function<void(const GNSS &)>;// 函数注册TxtIO &SetIMUProcessFunc(IMUProcessFuncType imu_proc) {imu_proc_ = std::move(imu_proc);return *this;}TxtIO &SetOdomProcessFunc(OdomProcessFuncType odom_proc) {odom_proc_ = std::move(odom_proc);return *this;}TxtIO &SetGNSSProcessFunc(GNSSProcessFuncType gnss_proc) {gnss_proc_ = std::move(gnss_proc);return *this;}// 执行void Go();private:std::ifstream fin;IMUProcessFuncType imu_proc_;OdomProcessFuncType odom_proc_;GNSSProcessFuncType gnss_proc_;
};void TxtIO::Go() {...while (!fin.eof()) {if (data_type == "IMU" && imu_proc_) {double time, gx, gy, gz, ax, ay, az;ss >> time >> gx >> gy >> gz >> ax >> ay >> az;// imu_proc_(IMU(time, Vec3d(gx, gy, gz) * math::kDEG2RAD, Vec3d(ax, ay, az)));imu_proc_(IMU(time, Vec3d(gx, gy, gz), Vec3d(ax, ay, az)));} else if (data_type == "ODOM" && odom_proc_) {double time, wl, wr;ss >> time >> wl >> wr;odom_proc_(Odom(time, wl, wr));} else if (data_type == "GNSS" && gnss_proc_) {double time, lat, lon, alt, heading;bool heading_valid;ss >> time >> lat >> lon >> alt >> heading >> heading_valid;gnss_proc_(GNSS(time, 4, Vec3d(lat, lon, alt), heading, heading_valid));}}LOG(INFO) << "done.";
}
...
//方法链或流式接口
TEST(PREINTEGRATION_TEST, ESKF_TEST) {sad::TxtIO io(FLAGS_txt_path);io.SetIMUProcessFunc([&](const sad::IMU& imu) {/// IMU 处理函数...}).SetGNSSProcessFunc([&](const sad::GNSS& gnss) {/// GNSS 处理函数...}).SetOdomProcessFunc([&](const sad::Odom& odom) { imu_init.AddOdom(odom); }).Go();
简单几点解释
a.方法链:
每个方法(如SetIMUProcessFunc)返回TxtIO对象的引用(*this)。
b.注册过程:
SetIMUProcessFunc方法注册了一个处理IMU函数;SetOdomProcessFunc、SetGNSSProcessFunc类似。
c.执行过程:
.Go()方法是实际开始处理Txt 文本。它会遍历Txt 文件中的所有数据,并根据关键词“IMU”、“ODOM”、"GNSS"匹配相应的处理函数,直到执行完文本所有数据。
7.参考
<<自动驾驶与机器人中的SLAM技术从理论到实践>>
相关文章:
设计模式——方法链or流式接口
方法链或流式接口是一种编程模式或设计模式。核心思想是通过返回对象自身的应用,使得可以在一个表达式中连续调用多个方法。 c中实现这种模式 1.基本语法规则 (1)每个可链接的方法都返回对象自身的引用(通常是*this)…...
JAVA OPCUA 服务端开发,客户端连接会话监听和订阅事件监听
前言 关于使用milo开源库,开发opc ua服务器,有网友咨询如何设置服务端如何监听客户端的连接或断开事件,如何监听客户端发起订阅事件的代码实现,于是我完善了这部分的空缺整理整了这篇教程,希望能解决有同样需求,但是遇到困难的网友!因为milo没有官方文档的教程且网上详…...
pytest相关总结
1.pytest -v -s -v将测试用例名称和用例中的输出进行展示,将每条用例脚本的内容逐行进行结果展示; -s 参数是为了显示用例执行层级的打印信息 pytest使用总结笔记 - fengf233 - 博客园 2....
cin/cout的性能优化和缓冲区同步问题
目录 背景导入 问题 1.1ios::sync_with_stdio(false) 1.2为什么要解除C/C IO流同步? 1.3使用场景 2.1cin和cout的绑定关系 2.2为什么要解除绑定关系? 2.3注意事项 背景导入 大家可以先看一下这段背景知识;后面我会谈谈自己的理解; 1.在C中,标准输⼊输出流…...
redisson-spring-data与Spring-Data-Redis的版本关系问题
redisson-spring-boot-starter https://github.com/redisson/redisson/tree/master/redisson-spring-boot-starter https://github.com/redisson/redisson/tree/master/redisson-spring-data#spring-data-redis-integration 将 Redisson 与 Spring Boot 库集成。依赖于Spring…...
Puppeteer代理认证的最佳实践和示例
在现代网络环境中,代理服务器的使用越来越普遍,尤其是在数据抓取、网页自动化测试和网络监控等领域。Puppeteer作为一个流行的Node库,它提供了高级的API来控制Chrome或Chromium浏览器。在某些情况下,我们需要通过代理服务器来执行…...
js 字符串 只显示数字
1. 使用正则表达式的match方法 原理:正则表达式\d用于匹配一个或多个数字。match方法会在字符串中查找与正则表达式匹配的部分,并返回一个包含所有匹配结果的数组。示例代码: let str "abc123def456"; let numbers str.match(/…...
STM32标准库-FLASH
FLASH模仿EEPROM STM32本身没有自带EEPROM,但是自带了FLASH存储器。 STM32F103ZET6自带 1M字节的FLASH空间,和 128K64K的SRAM空间。 STM32F4 的 SPI 功能很强大,SPI 时钟最高可以到 37.5Mhz,支持 DMA,可以配置为 SPI协…...
PowerShell:查找并关闭打开的文件
Get-SmbOpenFile 打开 Windows PowerShell 并运行 Get-SmbOpenFile | Format-List 若要仅显示特定文件共享的连接,请使用 Where-Object 运行 Get-SmbOpenFile。 Get-SmbOpenFile | Where-Object Path -eq "C:\Data\" | Format-List Get-SmbSession 显…...
【AI系统】昇腾异构计算架构 CANN
昇腾异构计算架构 CANN 本文将介绍昇腾 AI 异构计算架构 CANN(Compute Architecture for Neural Networks),这是一套为高性能神经网络计算需求专门设计和优化的架构。CANN 包括硬件层面的达芬奇架构和软件层面的全栈支持,旨在提供…...
STM32 HAL库开发学习3.STM32启动浅析
STM32 HAL库开发学习3.STM32启动浅析 一、STM32启动模式(也称自举模式)1. MSP与PC指针赋值2. F1系列的启动模式:3. F4系列启动模式4. F7系列启动模式5. H7系列启动模式 二、STM32启动过程1. MSP 栈顶地址2. PC值3. Reset_Handler4. 启动文件内…...
FakeLocation 1.3.5 BETA 提示校园跑漏洞修复解决
任务一 作者对此又进行了更新,在本次更新中,我们依旧使用hookvip进行破解 本次的更新,使得包名强制写入更加严重,之前靠一些方法已经无法阻止appconfigs.xml的文件的修改,而且使得验证加强,和云端加强&…...
Figma入门-约束与对齐
Figma入门-约束与对齐 前言 在之前的工作中,大家的原型图都是使用 Axure 制作的,印象中 Figma 一直是个专业设计软件。 最近,很多产品朋友告诉我,很多原型图都开始用Figma制作了,并且很多组件都是内置的,…...
腾讯元宝深度搜索AI多线程批量生成TXT原创文章软件
腾讯元宝深度搜索AI多线程批量生成TXT原创文章软件说明: 腾讯元宝深度搜索AI:能够理解用户意图,对搜索结果进行提炼和总结,直接提供用户所需的答案或信息摘要,从而提升用户体验。 腾讯元宝深度搜索AI:通过…...
Git操作学习1
一、一些Linux相关指令 在当前目录下,创建文件并写入内容:echo "这是第一个文件">file1.txt 查看文件的内容: cat file1.txt 会显示:这是第一个文件 修改文件名:mv file.txt file4.txt 把file.txt修改…...
【计算机网络】细说IP
文章目录 概述IP地址的组成IP地址的分类IP地址的作用 分类一、A类IP地址二、B类IP地址三、C类IP地址四、D类IP地址五、E类IP地址 协议报文子网掩码一、定义与功能二、表示方法三、子网掩码与IP地址的关系四、子网掩码的设置与配置五、实例说明 IPv6一、定义与背景二、地址格式与…...
树与图深度优先遍历——acwing
题目一:树的重心 846. 树的重心 - AcWing题库 分析 采用暴力枚举,试探每个点,除去之后,连通分量最大值是多少, 各个点的最大值找最小的 因为可以通过 dfs 来得到 根u以下点数,以及可以求各分树的点数&am…...
vue3.0 根据富文本html页面生成压缩包(含视频在线地址、图片在线地址、前端截图、前端文档)
vue3.0生成压缩包(含在线地址、前端截图、前端文档) 需求描述效果开始下载插件包基本代码构造 点击下载按钮1.截图content元素,并转化为pdfcanvas putImageData、getImageDatagetImageData 获取指定矩形区域的像素信息putImageData 将这些数据…...
WPF+LibVLC开发播放器-LibVLC在C#中的使用
LibVLC在C#中的使用 安装包Nuget使用控件使用播放器初始化加载视频文件 视频教程: 使用WPFLibVLC快速开发一个播放器 安装包Nuget 安装下面两个包,必须安装两个 一个是相关框架对应的包,Winform就安装LibVLCSharp.Winform;WPF就安装LibVLCSharp.WPF&am…...
消息中间件-Kafka1-实现原理
消息中间件-Kafka 一、kafka简介 1、概念 Kafka是最初由Linkedin公司开发,是一个分布式、支持分区(partition)、多副本的(replica),基于zookeeper协调的分布式消息系统,它的最大的特性就是可以…...
超短脉冲激光自聚焦效应
前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应,这是一种非线性光学现象,主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场,对材料产生非线性响应,可能…...
【杂谈】-递归进化:人工智能的自我改进与监管挑战
递归进化:人工智能的自我改进与监管挑战 文章目录 递归进化:人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管?3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...
【JavaEE】-- HTTP
1. HTTP是什么? HTTP(全称为"超文本传输协议")是一种应用非常广泛的应用层协议,HTTP是基于TCP协议的一种应用层协议。 应用层协议:是计算机网络协议栈中最高层的协议,它定义了运行在不同主机上…...
NLP学习路线图(二十三):长短期记忆网络(LSTM)
在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...
优选算法第十二讲:队列 + 宽搜 优先级队列
优选算法第十二讲:队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...
Fabric V2.5 通用溯源系统——增加图片上传与下载功能
fabric-trace项目在发布一年后,部署量已突破1000次,为支持更多场景,现新增支持图片信息上链,本文对图片上传、下载功能代码进行梳理,包含智能合约、后端、前端部分。 一、智能合约修改 为了增加图片信息上链溯源,需要对底层数据结构进行修改,在此对智能合约中的农产品数…...
音视频——I2S 协议详解
I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议,专门用于在数字音频设备之间传输数字音频数据。它由飞利浦(Philips)公司开发,以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...
CVPR2025重磅突破:AnomalyAny框架实现单样本生成逼真异常数据,破解视觉检测瓶颈!
本文介绍了一种名为AnomalyAny的创新框架,该方法利用Stable Diffusion的强大生成能力,仅需单个正常样本和文本描述,即可生成逼真且多样化的异常样本,有效解决了视觉异常检测中异常样本稀缺的难题,为工业质检、医疗影像…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...
绕过 Xcode?使用 Appuploader和主流工具实现 iOS 上架自动化
iOS 应用的发布流程一直是开发链路中最“苹果味”的环节:强依赖 Xcode、必须使用 macOS、各种证书和描述文件配置……对很多跨平台开发者来说,这一套流程并不友好。 特别是当你的项目主要在 Windows 或 Linux 下开发(例如 Flutter、React Na…...
