slam中经常需要更改激光雷达适配算法,最近在学习设计模式,这里使用策略模式,做一些处理,纯粹瞎写,欢迎拍砖。
在不同的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. 把需要变动的部分抽象成接口,纯虚函数,让实现类去继承他
一般需要三个类:使用类,接口类(策略定义)和实现类(策略实现)。
我们先看最终使用情况:
int main()
{
Strategy *strategy = new Strategy(ROBOSENSE16); //接口类和实现类
LidarProcess lidarProcess(strategy);
// 上面两句可以合成一句 LidarProcess lidarProcess(new Strategy(ROBOSENSE16));
lidarProcess->process(msg); //msg 为激光雷达的数据结构
}
接口(策略)类要做成纯虚类:
class Stategy {
virtual int lidarPreprocess(const sensor_msgs::PointCloud2::ConstPtr &msg);
} ;
使用类,这部分是不会改变的,有两点要求
第一:要包含接口类作为成员变量,构造函数要传入接口类对其初始化;
第二:类中应有方法,可操作接口类的方法,完成动态绑定。
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.新激光雷达加入,需要 新的类去继承Stategy,重写对应的函数
class NEWlidar:Stategy{
virtual int lidarPreprocess(const sensor_msgs::PointCloud2::ConstPtr &msg) override
{
}
};
2.需要更改main函数的第一句,
Strategy *strategy = new Strategy(NEWlidar); //接口类和实现类
//示例1
#include
#include
#include
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
#include
#include
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;
}