1介绍
slam中经常需要更改激光雷达适配算法,最近在学习设计模式,这里使用策略模式,做一些处理,纯粹瞎写,欢迎拍砖。
1.1原始需求
在不同的slam算法里面经常要做算法适配,会有传感器坐标系的适配、数据格式的适配,,激光雷达的类型也比较多,有些需要pcl中注册生成新的数据类型。
这里是激光雷达数据适配的一部分代码。
void CloudConvert::Process(const sensor_msgs::PointCloud2::ConstPtr &msg,
std::vector<point3D> &pcl_out)
{
switch (lidar_type_)
{
case LidarType::OUST64:
Oust64Handler(msg);
break;
case LidarType::VELO32:
VelodyneHandler(msg);
break;
case LidarType::ROBOSENSE16:
RobosenseHandler(msg);
break;
case LidarType::PANDAR:
PandarHandler(msg);
break;
default:
LOG(ERROR) << "Error LiDAR Type: " << int(lidar_type_);
break;
}
pcl_out = cloud_out_;
}
可以看到是swich case 的结构,那么下面用策略模式改一下。
1.2 策略模式
1.2.1策略模式介绍
策略模式是生成模式的一种,
1. 是为了维持逻辑稳定
2. 把需要变动的部分抽象成接口,纯虚函数,让实现类去继承他
一般需要三个类:使用类,接口类(策略定义)和实现类(策略实现)。
- 按照变化部分和稳定部分的切分,应该有一个类是不变的,我一般都认为是使用类
- 有一个策略类作为接口(纯虚函数),
- 另外是一个 策略实现类 是可变的;
在使用的时候,生成相关的策略实现类,传递给使用类的构造函数。然后用多态,动态加载去调用相关的函数,代码如下:
1.2.2 最终使用
我们先看最终使用情况:
int main()
{
Strategy *strategy = new Strategy(ROBOSENSE16); //接口类和实现类
LidarProcess lidarProcess(strategy);
// 上面两句可以合成一句 LidarProcess lidarProcess(new Strategy(ROBOSENSE16));
lidarProcess->process(msg); //msg 为激光雷达的数据结构
}
1.2.3 接口类(策略定义)
接口(策略)类要做成纯虚类:
class Stategy {
virtual int lidarPreprocess(const sensor_msgs::PointCloud2::ConstPtr &msg);
} ;
1.2.4 使用类
使用类,这部分是不会改变的,有两点要求
第一:要包含接口类作为成员变量,构造函数要传入接口类对其初始化;
第二:类中应有方法,可操作接口类的方法,完成动态绑定。
class LidarProcess {
Stategy *stategy ;
//void LidarProcess( StrategyFactory *strategyFactory){ 也可以用工厂方法生成对象
//this->stategy = strategyFactory.creat();
//}
void LidarProcess( Stategy *stategy){
this->stategy = stategy;
}
void process(const sensor_msgs::PointCloud2::ConstPtr &msg ){
if(stategy!= nullptr)) //通常要判断是不是为空。
stategy->lidarPreprocess(const sensor_msgs::PointCloud2::ConstPtr &msg);
}
} ;
class OUST64lidar:Stategy
{
virtual int lidarPreprocess(const sensor_msgs::PointCloud2::ConstPtr &msg) override
{
}
};
class VELO32:Stategy{
virtual int lidarPreprocess(const sensor_msgs::PointCloud2::ConstPtr &msg) override
{
}
};
class ROBOSENSE16:Stategy{
virtual int lidarPreprocess(const sensor_msgs::PointCloud2::ConstPtr &msg) override
{
}
};
1.3新激光雷达加入
1.新激光雷达加入,需要 新的类去继承Stategy,重写对应的函数
class NEWlidar:Stategy{
virtual int lidarPreprocess(const sensor_msgs::PointCloud2::ConstPtr &msg) override
{
}
};
2.需要更改main函数的第一句,
Strategy *strategy = new Strategy(NEWlidar); //接口类和实现类
2 其他实例
//示例1
#include <iostream>
#include <string>
#include <memory>
using namespace std;
//高层策略接口
class Strategy
{
public:
virtual double CalcPrice(double goodsPrice){return 0;}
};
//具体策略
//普通客户策略
class NormalCustomerStrategy : public Strategy
{
public:
double CalcPrice(double goodsPrice) override
{
//普通客户没有折扣
std::cout<<"普通客户没有折扣"<<std::endl;
return goodsPrice;
}
};
//老客户策略
class OldCustomerStrategy : public Strategy
{
public:
double CalcPrice(double goodsPrice) override
{
//老客户 统一折扣5%
std::cout<<"老客户折扣5%"<<std::endl;
return goodsPrice * (1 - 0.05);
}
};
//大客户策略
class LargeCustomerStrategy : public Strategy
{
double CalcPrice(double goodsPrice) override
{
//大客户 统一折扣10%
std::cout<<"大客户折扣10%"<<std::endl;
return goodsPrice * (1 - 0.1);
}
};
//策略上下文
class Price
{
public:
Price(Strategy* strategy) : pStrategy(strategy){}
double Quote(double goodsPrice)
{
if(pStrategy != nullptr)
{
return pStrategy->CalcPrice(goodsPrice);
}
return 0;
}
private:
std::unique_ptr<Strategy> pStrategy {nullptr};
};
int main()
{
{
Price price(new NormalCustomerStrategy);
double goodsPrice = price.Quote(100);
std::cout<<"普通客户最终价:"<<goodsPrice<<std::endl;
}
{
Price price(new OldCustomerStrategy);
double goodsPrice = price.Quote(100);
std::cout<<"老客户最终价:"<<goodsPrice<<std::endl;
}
{
Price price(new LargeCustomerStrategy);
double goodsPrice = price.Quote(100);
std::cout<<"大客户最终价:"<<goodsPrice<<std::endl;
}
return 0;
}
//示例2
#include <iostream>
#include <string>
#include <memory>
using namespace std;
//策略模式扩展方式
//1.扩展上下文:通过继承上下文方式,然后在子类中添加相关数据
//2.扩展策略算法:在具体策略算法中添加相关数据
//高层策略接口
class PayStrategy
{
public:
//virtual void Pay(PayContext* pPayContext){} //c++ 没有反射 不能直接传入context 然后获取上下文相关数据 适用于扩展方式1
virtual void Pay(const std::string& user, double money){}
};
//具体策略
//人民币现金支付
class RMBCashStrategy : public PayStrategy
{
public:
void Pay(const std::string& user, double money) override
{
std::cout<<user<<"人民币现金支付:"<<money<<std::endl;
}
};
//美元支付
class DollarCashStrategy : public PayStrategy
{
public:
void Pay(const std::string& user, double money) override
{
std::cout<<user<<"美元现金支付:"<<money<<std::endl;
}
};
//RMB账户支付 扩展方式2
class RMBAccountStrategy : public PayStrategy
{
private:
std::string account;
public:
RMBAccountStrategy(std::string account) : account(account){}
public:
void Pay(const std::string& user, double money) override
{
std::cout<<user<<"RMB账户"<<account<<"支付:"<<money<<std::endl;
}
};
//策略上下文
class PayContext
{
private:
std::string user;
double money;
public:
PayContext(std::string user, double money, PayStrategy* payStrategy) : user(user), money(money), pPayStrategy(payStrategy){}
public:
void PayNow()
{
if(pPayStrategy != nullptr)
{
return pPayStrategy->Pay(this->user, this->money);
}
}
private:
std::unique_ptr<PayStrategy> pPayStrategy {nullptr};
};
int main()
{
{
PayContext* payContext = new PayContext("张三", 100.0, new RMBCashStrategy());
payContext->PayNow();
}
{
PayContext* payContext = new PayContext("petter", 200.0, new DollarCashStrategy());
payContext->PayNow();
}
{
PayContext* payContext = new PayContext("李四", 300.0, new RMBAccountStrategy("123456789"));
payContext->PayNow();
}
return 0;
}
原文地址:https://blog.csdn.net/u010647296/article/details/134666989
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.7code.cn/show_5655.html
如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。