No BSD License  

Highlights from
doflq.m

from doflq.m by Leonardo Kammer
Designed to compute a Linear Quadratic optimal output feeback controller for discrete-time systems.

doflq(par1,par2,par3,par4,par5)
function [out1,out2,out3] = doflq(par1,par2,par3,par4,par5)
%DOFLQ  Linear quadratic output feedback design for SISO discrete-time systems.
%
%       [Cfb,clP] = DOFLQ(P,H,lambda,Fy,Fu)  calculates the optimal output
%       feedback transfer function such that the control law
%               u[k] = -Cfb(q) y[k]
%       minimises the (frequency weighted) cost function
%               J = E {(Fy*y)^2 + lambda*(Fu*u)^2}
%       subject to the constraint equation:
%               y[k] = P(q)u[k] + H(q)e[k],
%       where e[k] is a zero mean white noise.
%       
%       Also returned is clP(q), the closed loop characteristic equation.
%       The frequency weights, Fy and Fu, are optional.
%
%       Constraints: * P(q), H(q), Fy(q) and Fu(q) must be transfer functions.
%                    * Lambda must be a non-negative scalar.
%
%
%       [S,R,clP] = DOFLQ(A,B,C,lambda)  calculates the optimal output feedback
%       transfer function such that the control law  u[k] = -S(q)/R(q) y[k]
%       minimises the cost function
%               J = E {y^2 + lambda*u^2}
%       subject to the constraint equation:
%               A(q)y[k] = B(q)u[k] + C(q)e[k],
%       where e[k] is a zero mean white noise.
%       
%       Also returned is clP(q), the closed loop characteristic equation.
%
%       Constraints: * A(q), B(q) and C(q) must be polynomials described by row
%                      vectors with the same length. Obs: Use leading zeros.
%                    * The first element of B(q) must be zero.
%                    * The first element of A(q) cannot be zero.
%                    * The polynomials cannot be zero.
%                    * Lambda must be a non-negative scalar.
%
%
%       See also: DLQR.

%       L.C. Kammer 13 Feb 96
%       $Date: 1997/12/01 00:25:25 $ - $Revision: 2.1 $
%       Copyright (c) 1996-97 by Leonardo C. Kammer.
%       Contact address: leonardo@syseng.anu.edu.au


% Verification of calling method: transfer functions or polynomials.
if isa(par1, 'tf')
   % Tests for conditions of error.
   error(nargchk(3,5,nargin));
   if nargin < 5
      Fu = 1;
   elseif isa(par5, 'tf')
      Fu = par5;
   else
      error('Parameter Fu must be a transfer function.');
   end
   if nargin < 4
      Fy = 1;
   elseif isa(par4, 'tf')
      Fy = par4;
   else
      error('Parameter Fy must be a transfer function.');
   end
   lb = par3;
   if ~isa(par2, 'tf')
      error('Parameter H must be a transfer function.');
   end
   P = par1;
   H = par2;
   
   Pbar = minreal(Fy * inv(Fu) * P);
   Hbar = minreal(Fy * H);
   
   PHbar = minreal([ss(Pbar) ss(Hbar)]);
   [B, A] = tfdata(tf(PHbar(1,1)), 'v');
   [C, D] = tfdata(tf(PHbar(1,2)), 'v');
   
   rC = dsort(roots(C));
   while max(abs(rC)) > 1
      rC(1) = 1/rC(1);
      rC = dsort(rC);
   end
   C = poly(rC);
   
   if A ~= D
      error('Not an appropriate ARMAX model.');
   end
   
   [Slq,Rlq, PC] = doflq(A, B, C, lb);
   out1 = minreal(tf(Slq, Rlq, -1) * Fy * inv(Fu));
   out2 = PC;
   
else
   % Tests for conditions of error.
   error(nargchk(4,4,nargin));
   A = par1;
   B = par2;
   C = par3;
   lb = par4;
   [mA,nA] = size(A);
   [mB,nB] = size(B);
   [mC,nC] = size(C);
   if (mA ~= 1) | (mB ~= 1) | (mC ~= 1)
      error('A, B and C must be polynomials described by row vectors')
   end
   if ~nA
      error('A, B and C polynomials cannot be empty.')
   end
   if (nB ~= nA) | (nC ~= nA) | (B(1) ~= 0)
      error('Degrees of polynomials must be equal and B[1]=0.')
   end
   if length(lb) > 1 | lb < 0
      error('Lambda must be a non-negative scalar.')
   end
   if A(1) == 0
      error('A[1] cannot be zero.')
   end
   if (max(abs(C)) == 0) | (max(abs(B)) == 0)
      error('B and C polynomials cannot be zero.')
   end
   
   % Adjusting data for computations. Polynomials A and C must be monic.
   if A(1) ~= 1
      C = C / A(1);
      B = B / A(1);
      A = A / A(1);
   end
   while C(1) == 0
      C = [C(2:nC) 0];
   end
   if C(1) ~= 1
      C = C / C(1);
   end
   
   
   rPP = lb*conv(A,fliplr(A))+conv(B,fliplr(B));
   rts = flipud(dsort(roots(rPP)));
   P = poly(rts(1:nA-1));
   PC=conv(P,C);
   
   PP = conv(P,fliplr(P));
   r = sum(abs(rPP))/sum(abs(PP));
   
   As = fliplr(A);
   rP = r*P;
   
   M = zeros(2*nA-2);
   for i=1:nA-1
      M(i:i+nA-1,i) = As';
      M(i:i+nA-1,i+nA-1) = rP';
   end
   BCs = conv(B(2:nA),fliplr(C));
   XSs = M \ BCs';
   
   X(1:nA) = [0 XSs(1:nA-1)'];
   Ss = [0 XSs(nA:2*nA-2)'];
   S = real(fliplr(Ss));
   
   
   B1 = B;
   while B1(1) == 0
      B1 = B1(2:length(B1));
   end
   [Rs,res1] = deconv(conv(fliplr(P),X)+lb*conv(A,Ss), B1);
   R = real(fliplr(Rs(length(Rs)-nA+1:length(Rs))));
   
   res2 = sum(abs(conv(A,R)+conv(B,S)-PC));
   if (sum(abs(res1)) > 1e-5) | (res2 > 1e-5)
     disp('Warning: Residuals of the spectral factorisation are too big. (?!)')
   end
   
   out1 = S;
   out2 = R;
   out3 = PC;
   
end

Contact us at files@mathworks.com