设计模式——方法链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协调的分布式消息系统,它的最大的特性就是可以…...
postgresql|数据库|只读用户的创建和删除(备忘)
CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...
今日科技热点速览
🔥 今日科技热点速览 🎮 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售,主打更强图形性能与沉浸式体验,支持多模态交互,受到全球玩家热捧 。 🤖 人工智能持续突破 DeepSeek-R1&…...
Linux系统部署KES
1、安装准备 1.版本说明V008R006C009B0014 V008:是version产品的大版本。 R006:是release产品特性版本。 C009:是通用版 B0014:是build开发过程中的构建版本2.硬件要求 #安全版和企业版 内存:1GB 以上 硬盘…...
【java面试】微服务篇
【java面试】微服务篇 一、总体框架二、Springcloud(一)Springcloud五大组件(二)服务注册和发现1、Eureka2、Nacos (三)负载均衡1、Ribbon负载均衡流程2、Ribbon负载均衡策略3、自定义负载均衡策略4、总结 …...
Docker、Wsl 打包迁移环境
电脑需要开启wsl2 可以使用wsl -v 查看当前的版本 wsl -v WSL 版本: 2.2.4.0 内核版本: 5.15.153.1-2 WSLg 版本: 1.0.61 MSRDC 版本: 1.2.5326 Direct3D 版本: 1.611.1-81528511 DXCore 版本: 10.0.2609…...
CppCon 2015 学习:Simple, Extensible Pattern Matching in C++14
什么是 Pattern Matching(模式匹配) ❝ 模式匹配就是一种“描述式”的写法,不需要你手动判断、提取数据,而是直接描述你希望的数据结构是什么样子,系统自动判断并提取。❞ 你给的定义拆解: ✴ Instead of …...
Android Framework预装traceroute执行文件到system/bin下
文章目录 Android SDK中寻找traceroute代码内置traceroute到SDK中traceroute参数说明-I 参数(使用 ICMP Echo 请求)-T 参数(使用 TCP SYN 包) 相关文章 Android SDK中寻找traceroute代码 设备使用的是Android 11,在/s…...
LSTM-XGBoost多变量时序预测(Matlab完整源码和数据)
LSTM-XGBoost多变量时序预测(Matlab完整源码和数据) 目录 LSTM-XGBoost多变量时序预测(Matlab完整源码和数据)效果一览基本介绍程序设计参考资料 效果一览 基本介绍 普通的多变量时序已经用腻了,审稿人也看烦了&#…...
比较数据迁移后MySQL数据库和PostgreSQL数据仓库中的表
设计一个MySQL数据库和PostgreSQL数据库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较两…...
浅谈未来汽车电子电气架构发展趋势中的通信部分
目录 一、引入 1.1市场占比演化 1.2未来发展趋势 二、纯电动汽车与传统汽车的区别 2.1 纯电车和燃油车的架构(干货) 2.2 新能源汽车的分类 ⚡ 1. 纯电动汽车(BEV) 🔋 2. 插电式混合动力(PHEV&#…...
