看了一半重构的书,真心感觉以前写的代码很烂。耦合严重,维护困难。于是重构第一刀就是刚写的重复控制器实验平台。
由于CCS编译器中对C++ template 支持不是很完善,所以只能使用较常用的,先前的代码已经贴了,现在讲讲改进后的。
原先程序中最大的缺陷在于重复控制器被我写成了两个类,由于gamma轴与alpha、beta轴中无差拍部分不一样,gamma轴需要在电感和电阻的系数上乘以4,所以只好分了两个类来实现。
class CFControler;
class CF4Controler;
这样做虽然可以成功,但存在严重的维护问题,由于是重复控制附加在无差拍上的,一旦重复控制器的结构和参数有所改变,两个类里面的都得改变,copy/paste的手法一直是写程序最忌讳的手法(重构给我带来的第一个也是最重要的启发),如果能够将相同的提取出来,不同的分离出来,便是一个很好的策略。
【做法/步骤】
原来的调用过程是这样的:
CFControler<_iq> CtrlA;//alpha
CFControler<_iq>CtrlB;//beta
CF4Controler<_iq>CtrlG;//gamma
ctrlOutA = CtrlA(referenceA, feedbackA, voltageA);
ctrlOutB = CtrlB(referenceB, feedbackB, voltageB);
ctrlOutG = CtrlG(referenceG, feedbackG, voltageG);
重构的基本原则是不改变外部结构,因此我想这些调用也保持不变。
如果先写测试代码,我想是这样一个效果:
CFControler<_iq,ctrlAB> CtrlA;//alpha
CFControler<_iq,ctrlAB>CtrlB;//beta
CFControler<_iq,ctrlG>CtrlG;//gamma
ctrlOutA = CtrlA(referenceA, feedbackA, voltageA);
ctrlOutB = CtrlB(referenceB, feedbackB, voltageB);
ctrlOutG = CtrlG(referenceG, feedbackG, voltageG);
因为我想只保持一个类,因此声明类时,我只需在template中第二参数指明是哪种类型的控制器即可。
下面进行修改:
先声明两个空类,用来函数的分流:
classctrlAB{}; //for controler of alpha and beta
classctrlG{}; //for controler of gamma
然后在类中增加GetDeadbeat函数,这两个函数在不同的控制器不同,因此需要分开写。
template
class CFControler
{
typedef ctlType __ctlType;
public:
CFControler():jiaozheng_y(0),jiaozheng_x(0){}
T operator()(T ref,T feedback,T voltage);
private:
queuey;
queuex;
T GetDeadbeat(T current, T feedback, T voltage,ctrlAB) // alpha and beta
{
T result = current * 40 ;
result = voltage - result - _IQmpy(feedback,_IQ(0.3));
return result;
}
T GetDeadbeat(T current, T feedback, T voltage,ctrlG) //gamma
{
T result = current * 160 ;
result = voltage - result - _IQmpy(feedback,_IQ(1.2));
return result;
}
T jiaozheng_y;
T jiaozheng_x;
};
这样对于operator () 函数可以完全一致:
template
T CFControler::operator ()(T ref,T feedback,T voltage)
{
T e,ctlOut;
e =ref - feedback;
//这是最终的重复控制器
/*
ctlOut = _IQmpy(y.Get(1),_IQ(0.7408));
ctlOut += _IQmpy(y.Get(199),_IQ(0.25));
ctlOut += _IQmpy(y.Get(200),_IQ(0.3148));
ctlOut -= _IQmpy(y.Get(201),_IQ(0.1204));
ctlOut -= _IQmpy(y.Get(202),_IQ(0.1852));
ctlOut += _IQmpy(x.Get(197),_IQ(0.125));
ctlOut += _IQmpy(x.Get(198),_IQ(0.12625));
ctlOut -= _IQmpy(x.Get(199),_IQ(0.1225));
ctlOut -= _IQmpy(x.Get(200),_IQ(0.125));
*/
//这是未加校正环节的重复控制器
ctlOut = _IQmpy(y.Get(199),_IQ(0.25));
ctlOut += _IQmpy(y.Get(200),_IQ(0.5));
ctlOut += _IQmpy(y.Get(201),_IQ(0.25));
ctlOut += x.Get(198);
x.Push(e);
y.Push(ctlOut);
//校正环节
T currentOut = _IQmpy(jiaozheng_y,_IQ(0.7408));
currentOut += ctlOut;
currentOut -= _IQmpy(jiaozheng_x,_IQ(0.99));
jiaozheng_y = currentOut;
jiaozheng_x = ctlOut;
ctlOut = currentOut;
ctlOut = _IQmpy(ctlOut,_IQ(0.2));
ctlOut = ctlOut + e;
//ctlOut = ctlOut + 20 * e;
//无差拍控制
ctlOut = GetDeadbeat(ctlOut,feedback,voltage,__ctlType());
return ctlOut;
}
ctlOut = GetDeadbeat(ctlOut,feedback,voltage,__ctlType());
这句代码是整个分流的核心,也是本次重构的关键技术。
【技术效果】
通过这样的修改,如果重复控制的结构或者参数有所变化,就可以直接在这个类进行修改,没有其他相关联的地方,调试时及其方便,改参数——编译链接——下载——运行,整个过程可能一分钟都不到,比MATLAB仿真调试还要来得方便!~这就是效果!~