河南网站建设技术公司,关于科技园区建设文章的网站,防蚊手环移动网站建设,龙岩网址大全方法链或流式接口是一种编程模式或设计模式。核心思想是通过返回对象自身的应用#xff0c;使得可以在一个表达式中连续调用多个方法。
c中实现这种模式
1.基本语法规则
#xff08;1#xff09;每个可链接的方法都返回对象自身的引用#xff08;通常是*this#xff09…方法链或流式接口是一种编程模式或设计模式。核心思想是通过返回对象自身的应用使得可以在一个表达式中连续调用多个方法。
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::functionbool(const rosbag::MessageInstance m);/// 一些方便直接使用的topics, messagesusing Scan2DHandle std::functionbool(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.instantiatesensor_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::mapstd::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::functionbool(const rosbag::MessageInstance m); std::mapstd::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::functionvoid(const IMU );using OdomProcessFuncType std::functionvoid(const Odom );using GNSSProcessFuncType std::functionvoid(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技术从理论到实践