1. 程式人生 > 其它 >位置式\增量式PID、模糊PID、BRF-PID的Matlab實現以及封裝

位置式\增量式PID、模糊PID、BRF-PID的Matlab實現以及封裝

位置式\增量式PID、模糊PID、BRF-PID的Matlab實現以及封裝

位置式\增量式PID、模糊PID、BRF-PID的Matlab實現以及封裝

簡要

PID控制由於結構簡單,控制效果好,在工業上有廣泛的應用,從出現到至今已經有一百多年的歷史;PID控制本質是一種線性控制器,它是比例(P)、積分(I)、微分(D)的線性組合,所以一旦引數確定,控制效果就已經確定,在面對非線性系統時候,控制效果不是太理想。所謂的智慧PID就是通過把智慧演算法與PID相結合,各取所長得到智慧PID演算法,其演算法本質就是通過規則或者學習演算法來線上的改變PID的三個引數,從而面對時變、非線性系統時,能有較強的魯棒性。

本文主要包括位置式\增量式PID、模糊PID、BRF-PID的Matlab實現以及封裝,其中包括了完整的程式碼。Matlab也是一門面向物件語言,利用面向物件的強大功能,本文通過策略模式把演算法經行了封裝,方便以後使用。以下是完整的程式碼實現:

Model類

此類負責儲存資料

classdef Model < handle
% 策略模式:定義一系列的演算法,把它們一個個封裝起來,並且使它們可以互相替換
% 此類物件中存放資料,而在Strategy中存放演算法,此類可以選擇不同的演算法
    properties
         sampleTime      % 取樣時間
         simTime         % 模擬時間
         rin             % 輸入
         sys_Plant       % 被控物件傳遞函式
         dsys            % 離散模型
         den             % 離散模型分母
         num             % 離散訊號分子
         ui
         yi
         i
         strategyObj     % 策略物件
    end

    methods 
        function obj = Model(sampleTime,simTime,rin,plant)
            % 初始化資料。
            obj.initialize(sampleTime,simTime,rin)
            % 建立模型及初始化其他引數
            obj.buildPlant(plant);
        end
 
        function initialize(obj,sampleTime,simTime,rin)
            obj.sampleTime = sampleTime;
            obj.simTime = simTime;
            obj.i =  obj.simTime/obj.sampleTime;
            if strcmp(rin,'step')
                obj.rin = ones(obj.i,1);
            elseif strcmp(rin,'impulse')
                obj.rin = zeros(obj.i,1);
                obj.rin(1) = 1/obj.sampleTime;
            elseif strcmp(rin,'square wave')
                x = 1:obj.i;
                obj.rin = sign(sin(2*pi*obj.sampleTime.*x));
            end
        end
        
        % 被控物件傳遞函式建立及其他引數初始化。
        function buildPlant(obj,plant)
            s = tf('s');
            obj.sys_Plant = eval(plant);
            % 零階保持器離散化
            obj.dsys = c2d(obj.sys_Plant,obj.sampleTime,'z');
            [obj.num,obj.den] = tfdata(obj.dsys,'v');
            % 其他初始化
            obj.initialize_other();
        end

        function initialize_other(obj)
            n = length(obj.den);
            obj.ui = zeros(n-1,1);
            obj.yi = zeros(n-1,1);
        end

        function progress(obj)
            obj.initialize_other()
            obj.strategyObj.progress(obj);
        end
    end
end

Strategy 類

此類為抽象類,定義演算法介面

classdef Strategy < handle
% 策略模式
% 策略抽象基類,定義演算法介面,有PID_Strategy,FuzzyPID_Strategy,BRF_PID_Strategy,SingleNeuralPID_Strategy等子類。
    properties
         PID_param = [0 0 0];   % 向量依次代表pid三個引數
         yout                   % 輸出
         stepTime               % 離散時間
         stepRin                % 離散輸入
         error                  % 誤差變化
         PID                    % PID三個引數變化過程
    end
    methods
        function obj = Strategy(P,I,D)
            obj.PID_param = [P I D];
        end
    end
    methods(Abstract)
        progress(obj) 
    end
end

PID_Strategy類

此類為位置式、增量式PID演算法的具體實現。

classdef PID_Strategy < Strategy
    properties
        displacementPID             % 位置式PID和增量式PID切換,0代表增量式PID,1代表位置式PID
    end
    methods
        function obj = PID_Strategy(P,I,D,displacementPID)
            obj = [email protected](P,I,D);
            obj.displacementPID = displacementPID;
        end

        function progress(obj,modelObj)
            x = [0 0 0]';
            i = modelObj.i;
            obj.stepRin = modelObj.rin;
            obj.yout = zeros(i,1);
            time = zeros(i,1);
            % 位置式PID
            u = zeros(i,1);                 % 控制器輸出
            e = zeros(i,1);                 % 誤差
            e_1 = 0;                        % 上一時刻誤差
            % 增量式PID
            du = u;
            u_1 = 0;
            e_2 = 0;
            for k = 1:i
                time(k) = k*modelObj.sampleTime;
                % 輸出
                obj.yout(k) = modelObj.num(2:end)*modelObj.ui - modelObj.den(2:end)*modelObj.yi;
                % 誤差
                e(k) = obj.stepRin(k) - obj.yout(k);
                % 位置式PID演算法
                if obj.displacementPID 
                    u(k) = obj.PID_param*x;
                    if u(k) >= 10
                        u(k) = 10;
                    end
                    if u(k) <= -10
                        u(k) = -10;
                    end
                    x(1) = e(k);
                    x(2) = x(2) + e(k)*modelObj.sampleTime; 
                    x(3) = e(k) - e_1;
                % 增量式PID演算法
                else
                    du(k) = obj.PID_param*x;
                    u(k) = u_1 + du(k);
                    if u(k) >= 10
                        u(k) = 10;
                    end
                    if u(k) <= -10
                        u(k) = -10;
                    end
                    x(1) = e(k) - e_1;
                    x(2) = e(k);
                    x(3) = e(k) - 2*e_1 + e_2; 
                    u_1 = u(k);
                    e_2 = e_1;
                end              
                % 跟新資料
                modelObj.ui(2:end) = modelObj.ui(1:end-1);
                modelObj.ui(1) = u(k);
                modelObj.yi(2:end) = modelObj.yi(1:end-1);
                modelObj.yi(1) = obj.yout(k); 
                e_1 = e(k);
            end
            obj.stepTime = time;
            figure
            plot(time,obj.yout)
            grid on
            obj.error = e;
        end
    end
end

Fuzzy_PID_Strategy類

此類為模糊PID的具體實現

classdef Fuzzy_PID_Strategy < Strategy
% 模糊PID控制演算法。二輸入,三輸出
    properties
        fid 				            % 模糊邏輯控制檔案
    end
    
    methods
        function obj = Fuzzy_PID_Strategy(P,I,D,file)
            obj = [email protected](P,I,D);
            obj.fid = readfis(file);
        end

        function progress(obj,modelObj)
            x = [0 0 0]';
            i = modelObj.i;
            obj.PID = zeros(i,3);
            obj.stepRin = modelObj.rin;
            obj.yout = zeros(i,1);
            time = zeros(i,1);
            u = zeros(i,1);                 % 控制器輸出
            e = zeros(i,1);                 % 誤差
            e_1 = 0;                        % 上一時刻誤差
            ec_1 = 0;                       % 上一時刻誤差變化           
            for k = 1:i
                time(k) = k*modelObj.sampleTime;
                % 根據模糊規則輸出PID變化
                deltaPID = evalfis(obj.fid,[e_1,ec_1]);
                obj.PID(k,:) = obj.PID_param + deltaPID;
                u(k) = obj.PID(k,:)*x;
                if u(k) >= 10
                    u(k) = 10;
                end
                if u(k) <= -10
                    u(k) = -10;
                end
                % 輸出
                obj.yout(k) = modelObj.num(2:end)*modelObj.ui - modelObj.den(2:end)*modelObj.yi;
                % 誤差
                e(k) = obj.stepRin(k) - obj.yout(k);
                x(1) = e(k);
                x(2) = x(2) + e(k)*modelObj.sampleTime; 
                x(3) = e(k) - e_1; 
                % 跟新資料
                modelObj.ui(2:end) = modelObj.ui(1:end-1);
                modelObj.ui(1) = u(k);
                modelObj.yi(2:end) = modelObj.yi(1:end-1);
                modelObj.yi(1) = obj.yout(k); 
                e_1 = e(k);
                ec_1 = x(3);
            end
            obj.stepTime = time;
            figure
            plot(time,obj.yout)
            grid on
            obj.error = e;
        end
    end
end

BRF_PID_Strategy類

此類為徑向基函式PID的具體實現

classdef BRF_PID_Strategy < Strategy
% 徑向基函式網路PID演算法,核函式為高斯基函式,網路為3-6-1形式
    properties
        alpha                            % RBF網路學習效率
        eta                              % RBF網路動量因子
        b = 4                            % 高斯基函式寬度
        c                                % 高斯基函式中心矩陣
        hide_num = 6                     % 隱含層個數
        out_range                        % 模型輸出範圍
        etaPID = [0.2 0.2 0.2]           % PID三個引數學習效率
        ymout                            % BRF網路逼近輸出
        dyout                            % BRF網路雅可比陣
        displacementPID                  % 位置式PID和增量式PID切換,0代表增量式PID,1代表位置式PID
    end
    
    methods
        function obj = BRF_PID_Strategy(P,I,D,etaPID,alpha,eta,b,out_range,hide_num,displacementPID)
            obj = [email protected](P,I,D);  
            obj.etaPID = etaPID;
            obj.alpha = alpha;
            obj.eta = eta;
            obj.b = b;
            obj.out_range = out_range;
            obj.hide_num = hide_num;
            obj.displacementPID = displacementPID;
            obj.c = [linspace(out_range(1),out_range(2),obj.hide_num);
                    linspace(out_range(1),out_range(2),obj.hide_num);
                    linspace(out_range(1),out_range(2),obj.hide_num)];
        end

        function progress(obj,modelObj)
            x = [0 0 0]';  
            y_1 = 0;                        % 上一時刻輸出
            % 初始化神經網路各引數
            w = zeros(obj.hide_num,1);      % 初始權矩陣
            w_1 = w;
            w_2 = w_1;
            h = zeros(obj.hide_num,1);      % 初始化高斯基函式輸出
            RBF_input = [0 0 0]';           % 初始化神經網路輸入
            % 初始化模型輸入輸出引數
            i = modelObj.i;
            obj.PID = zeros(i,3);
            obj.stepRin = modelObj.rin;
            obj.yout = zeros(i,1);
            obj.ymout = zeros(i,1);
            obj.dyout = zeros(i,1);
            time = zeros(i,1);
            % 位置式PID
            u = zeros(i,1);                 % 控制器輸出
            e = zeros(i,1);                 % 誤差
            e_1 = 0;                        % 上一時刻誤差
            % 增量式PID
            du = u;
            u_1 = 0;
            e_2 = 0;
            
            for k = 1:i
                time(k) = k*modelObj.sampleTime;
                % 輸出
                obj.yout(k) = modelObj.num(2:end)*modelObj.ui - modelObj.den(2:end)*modelObj.yi;
                for j = 1:obj.hide_num
                    h(j) = exp(-norm(RBF_input - obj.c(:,j))^2/(2*obj.b^2));
                end
                obj.ymout(k) =  w'*h;
                d_w = obj.alpha*(obj.yout(k) - obj.ymout(k))*h;
                w = w_1 + d_w + obj.eta*(w_1 - w_2);
                yu = w.*h.*(-x(1) + obj.c(1,:))'/obj.b^2;
                obj.dyout(k) = sum(yu);
                % 誤差
                e(k) = obj.stepRin(k) - obj.yout(k);
                obj.PID_param = obj.PID_param + e(k)*obj.dyout(k)*x'.*obj.etaPID;
                obj.PID(k,:) = obj.PID_param;
                % 位置式PID演算法
                if obj.displacementPID
                    u(k) = obj.PID_param*x;
                    if u(k) >= 10
                        u(k) = 10;
                    end
                    if u(k) <= -10
                        u(k) = -10;
                    end
                    x(1) = e(k);
                    x(2) = x(2) + e(k)*modelObj.sampleTime; 
                    x(3) = e(k) - e_1;
                    RBF_input = [u(k) obj.yout(k) y_1]';
                % 增量式PID演算法
                else
                    du(k) = obj.PID_param*x;
                    u(k) = u_1 + du(k);
                    if u(k) >= 10
                        u(k) = 10;
                    end
                    if u(k) <= -10
                        u(k) = -10;
                    end
                    x(1) = e(k) - e_1;
                    x(2) = e(k);
                    x(3) = e(k) - 2*e_1 + e_2; 
                    RBF_input = [du(k) obj.yout(k) y_1]';
                    u_1 = u(k);
                    e_2 = e_1;
                end
                % 跟新資料
                modelObj.ui(2:end) = modelObj.ui(1:end-1);
                modelObj.ui(1) = u(k);
                modelObj.yi(2:end) = modelObj.yi(1:end-1);
                modelObj.yi(1) = obj.yout(k); 
                e_1 = e(k);
                w_2 = w_1;
                w_1 = w;
                y_1 = obj.yout(k);
            end
            obj.stepTime = time;
            obj.error = e;
            figure
            plot(time,obj.yout)
            grid on
            figure
            plot(time,obj.yout,'r',time,obj.ymout,'b');
        end
    end
end

測試

測試物件為三階的一型系統,取樣時間 T S = 0.001 s T_S=0.001s TS=0.001s,模擬時長 T = 0.5 s T=0.5s T=0.5s,輸入為單位越階。

%%  PID演算法/增量式PID演算法除錯
a = Model(0.001,0.5,'step','523500/(s^3+87.35*s^2+10470*s)');
a.strategyObj = PID_Strategy(1,0,0,1);
% a.strategyObj = PID_Strategy(1,0,0,0);
a.progress()
%%  神經網路PID/神經網路增量式PID演算法除錯
% a = Model(0.001,0.5,'step','523500/(s^3+87.35*s^2+10470*s)');
% isa(a.strategyObj,'Strategy')
% a.strategyObj = BRF_PID_Strategy(0.8,0,0,[0.9,0.9,0.2],0.4,0.01,2,[-1,1],6,1);
% a.progress()