home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / octa21eb.zip / octave / SCRIPTS.ZIP / scripts / control / hinfsyn.m < prev    next >
Text File  |  1999-03-05  |  10KB  |  291 lines

  1. # Copyright (C) 1996,1998 A. Scottedward Hodel 
  2. #
  3. # This file is part of Octave. 
  4. #
  5. # Octave is free software; you can redistribute it and/or modify it 
  6. # under the terms of the GNU General Public License as published by the 
  7. # Free Software Foundation; either version 2, or (at your option) any 
  8. # later version. 
  9. # Octave is distributed in the hope that it will be useful, but WITHOUT 
  10. # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
  11. # FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License 
  12. # for more details.
  13. # You should have received a copy of the GNU General Public License 
  14. # along with Octave; see the file COPYING.  If not, write to the Free 
  15. # Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
  16.  
  17. function [K,g,GW,Xinf,Yinf] = hinfsyn(Asys,nu,ny,gmin,gmax,gtol,ptol,tol)
  18.   # [K,g,GW,Xinf,Yinf] = hinfsyn(Asys,nu,ny,gmin,gmax,gtol[,ptol,tol])
  19.   #
  20.   # [1] Doyle, Glover, Khargonekar, Francis, "State Space Solutions
  21.   #     to Standard H2 and Hinf Control Problems," IEEE TAC August 1989
  22.   #
  23.   # [2] Maciejowksi, J.M.: "Multivariable feedback design,"
  24.   #     Addison-Wesley, 1989, ISBN 0-201-18243-2
  25.   #
  26.   # [3] Keith Glover and John C. Doyle: "State-space formulae for all
  27.   #     stabilizing controllers that satisfy and h-infinity-norm bound
  28.   #     and relations to risk sensitivity,"
  29.   #     Systems & Control Letters 11, Oct. 1988, pp 167-172.
  30.   #
  31.   # inputs: input system is passed as either
  32.   #        Asys: system data structure (see ss2sys, sys2ss)
  33.   #              - controller is implemented for continuous time systems 
  34.   #              - controller is NOT implemented for discrete time systems 
  35.   #        nu: number of controlled inputs
  36.   #        ny: number of measured outputs
  37.   #        gmin: initial lower bound on H-infinity optimal gain
  38.   #        gmax: initial upper bound on H-infinity optimal gain
  39.   #        gtol: gain threshhold.  Routine quits when gmax/gmin < 1+tol
  40.   #        ptol: poles with abs(real(pole)) < ptol*||H|| (H is appropriate
  41.   #              Hamiltonian) are considered to be on the imaginary axis.  
  42.   #              Default: 1e-9
  43.   #        tol: threshhold for 0.  Default: 200*eps
  44.   #
  45.   #        gmax, gmin, gtol, and tol must all be postive scalars.
  46.   # 
  47.   # outputs: 
  48.   #        K:   system controller
  49.   #        g:   designed gain value
  50.   #       GW:   closed loop system
  51.   #     Xinf:   ARE solution matrix for regulator subproblem
  52.   #     Yinf:   ARE solution matrix for filter subproblem
  53.  
  54.  
  55.   # A. S. Hodel August 1995
  56.   # Updated for Packed system structures December 1996 by John Ingram
  57.   #
  58.   # Revised by Kai P Mueller April 1998 to solve the general H_infinity
  59.   # problem using unitary transformations Q (on w and z)
  60.   # and non-singular transformations R (on u and y).
  61.  
  62.   if( (nargin < 1) | (nargin > 8) )
  63.     usage("[K,g,GW,Xinf,Yinf] = hinfsyn(Asys,nu,ny,gmin,gmax,gtol,ptol,tol)");
  64.   endif
  65.   # set default arguments
  66.   if(nargin < 8)
  67.     tol = 200*eps;
  68.   elseif(!is_sample(tol))
  69.     error("tol must be a positive scalar.")
  70.   endif
  71.   if(nargin < 7)
  72.     ptol = 1e-9;
  73.   elseif(!is_sample(ptol))
  74.     error("hinfsyn: ptol must be a positive scalar");
  75.   endif
  76.     
  77.   if(!is_sample(gmax) | !is_sample(gmin) | !is_sample(gtol) )
  78.     error(["hinfsyn: gmax=",num2str(gmax),", gmin=",num2str(gmin), ...
  79.       "gtol=",num2str(gtol), " must be positive scalars."])
  80.   endif
  81.  
  82.   [chkdgkf,dgs] = is_dgkf(Asys,nu,ny,tol);
  83.  
  84.   if (! chkdgkf )
  85.     disp("hinfsyn: system does not meet required assumptions")
  86.     help is_dgkf
  87.     error("hinfsyn: exit");
  88.   endif
  89.  
  90.   # extract dgs information
  91.               nw = dgs.nw;    nu = dgs.nu;
  92.   A = dgs.A;        B1 = dgs.Bw;    B2 = dgs.Bu;
  93.   C1 = dgs.Cz;        D11 = dgs.Dzw;    D12 = dgs.Dzu;        nz = dgs.nz;
  94.   C2 = dgs.Cy;        D21 = dgs.Dyw;    D22 = dgs.Dyu;        ny = dgs.ny;
  95.   d22nz = dgs.Dyu_nz;
  96.   dflg = dgs.dflg;
  97.  
  98.   # recover i/o transformations
  99.   R12 = dgs.Ru;        R21 = dgs.Ry;
  100.   [ncstates, ndstates, nin, nout] = sysdimensions(Asys);
  101.   Atsam = sysgettsam(Asys);
  102.   [Ast, Ain, Aout] = sysgetsignals(Asys);
  103.  
  104.   BB = [B1, B2];
  105.   CC = [C1 ; C2];
  106.   DD = [D11, D12 ; D21,  D22];
  107.  
  108.   if (dflg == 0)
  109.     n = ncstates;
  110.     # perform binary search to find gamma min
  111.     ghi = gmax;
  112.     # derive a lower lower bound for gamma from D matrices
  113.     xx1 = norm((eye(nz) - (D12/(D12'*D12))*D12')*D11);
  114.     xx2 = norm(D11*(eye(nw)-(D21'/(D21*D21'))*D21));
  115.     glo = max(xx1, xx2);
  116.     if (glo > gmin)
  117.       disp(" *** D matrices indicate a greater value of gamma min.");
  118.       fprintf("     gamma min (%f) superseeded by %f.", gmin, glo);
  119.       glo = xx1;
  120.     else
  121.       glo = gmin;
  122.     endif
  123.     if (glo > ghi)
  124.       fprintf(" *** lower bound of gamma greater than upper bound(%f)", ...
  125.           glo, ghi);
  126.       disp(" *** unable to continue, Goodbye.");
  127.       return;
  128.     endif
  129.  
  130.     de = ghi - glo;
  131.     g = glo;
  132.     search_state = 0;
  133.     iteration_finished = 0;
  134.     disp(" o structural tests passed, start of iteration...");
  135.     disp("        o <-> test passed   # <-> test failed   - <-> cannot test");
  136.     printf("----------------------------------------");
  137.     printf("--------------------------------------\n");
  138.  
  139.     # ------123456789012345678901234567890123456789012345678901234567890
  140.     printf("           .........X......... .........Y......... ");
  141.     printf(".Z. PASS REMARKS\n");
  142.     printf("        ga iax nev ene sym pos iax nev ene sym pos ");
  143.     printf("rho  y/n ======>\n");
  144.     printf("----------------------------------------");
  145.     printf("--------------------------------------\n");
  146.  
  147.     # set up error messages
  148.     errmesg = list(" o   o   o   o   o  ", ...
  149.     " #   -   -   -   -  ", ...
  150.     " o   #   -   -   -  ", ...
  151.     " o   o   #   -   -  ", ...
  152.     " o   o   o   #   -  ", ...
  153.     " o   o   o   o   #  ", ...
  154.     " -   -   -   -   -  ");
  155.     errdesx = list("", ...
  156.     "X im eig.", ...
  157.     "Hx not Ham.", ...
  158.     "X inf.eig", ...
  159.     "X not symm.", ...
  160.     "X not pos", ...
  161.     "R singular");
  162.  
  163.     errdesy = list(" ", ...
  164.     "Y im eig.", ...
  165.     "Hy not Ham.", ...
  166.     "Y inf.eig", ...
  167.     "Y not symm.", ...
  168.     "Y not pos", ...
  169.     "Rtilde singular");
  170.  
  171.  
  172.     # now do the search
  173.     while (!iteration_finished)
  174.       switch (search_state)
  175.         case (0)     g = ghi;
  176.         case (1)     g = glo;
  177.         case (2)     g = 0.5 * (ghi + glo);
  178.         otherwise     error(" *** This should never happen!");
  179.       endswitch
  180.       printf("%10.4f ", g);
  181.  
  182.       # computing R and R~
  183.       d1dot = [D11, D12];
  184.       R = zeros(nin, nin);
  185.       R(1:nw,1:nw) = -g*g*eye(nw);
  186.       R = R + d1dot' * d1dot;
  187.       ddot1 = [D11; D21];
  188.       Rtilde = zeros(nout, nout);
  189.       Rtilde(1:nz,1:nz) = -g*g*eye(nz);
  190.       Rtilde = Rtilde + ddot1 * ddot1';
  191.  
  192.       [Xinf,x_ha_err] = hinfsyn_ric(A,BB,C1,d1dot,R,ptol);
  193.       [Yinf,y_ha_err] = hinfsyn_ric(A',CC',B1',ddot1',Rtilde,ptol);
  194.  
  195.       # assume failure for this gamma
  196.       passed = 0;
  197.       rerr="";
  198.       if (!x_ha_err && !y_ha_err)
  199.     # test spectral radius condition
  200.     rho = max(abs(eig(Xinf * Yinf)));
  201.     if (rho < g*g)
  202.       # spectral radius condition passed
  203.       passed = 1;
  204.         else
  205.           rerr = sprintf("rho=%f",rho);
  206.     endif
  207.       endif
  208.  
  209.       if(x_ha_err >= 0 & x_ha_err <= 6)
  210.         printf("%s",nth(errmesg,x_ha_err+1));
  211.         xerr = nth(errdesx,x_ha_err+1);
  212.       else
  213.         error(" *** Xinf fail: this should never happen!");
  214.       endif
  215.  
  216.       if(y_ha_err >= 0 & y_ha_err <= 6)
  217.         printf("%s",nth(errmesg,y_ha_err+1));
  218.         yerr = nth(errdesy,y_ha_err+1);
  219.       else
  220.         error(" *** Yinf fail: this should never happen!");
  221.       endif
  222.  
  223.       if(passed)  printf("  y all tests passed.\n");
  224.       else        printf("  n %s/%s%s\n",xerr,yerr,rerr);          endif
  225.  
  226.       if (passed && (de/g < gtol))
  227.     search_state = 3;
  228.       endif
  229.  
  230.       switch (search_state)
  231.         case (0)
  232.       if (!passed)
  233.         # upper bound must pass but did not
  234.         fprintf(" *** the upper bound of gamma (%f) is too small.\n", g);
  235.         iteration_finished = 2;
  236.       else
  237.             search_state = 1;
  238.       endif
  239.         case (1)
  240.       if (!passed)      search_state = 2;
  241.       else
  242.         # lower bound must not pass but passed
  243.         fprintf(" *** the lower bound of gamma (%f) passed.\n", g);
  244.         iteration_finished = 3;
  245.       endif
  246.         case (2)
  247.           # Normal case; must check that singular R, Rtilde wasn't the problem.
  248.       if ((!passed) & (x_ha_err != 6) & (y_ha_err != 6) ) glo = g;
  249.       else         ghi = g;        endif
  250.       de = ghi - glo;
  251.         case (3)       iteration_finished = 1;        # done
  252.         otherwise      error(" *** This should never happen!");
  253.       endswitch
  254.     endwhile
  255.  
  256.     printf("----------------------------------------");
  257.     printf("--------------------------------------\n");
  258.     if (iteration_finished != 1)
  259.       K = [];
  260.     else
  261.       # success: compute controller
  262.       fprintf("   hinfsyn final: glo=%f ghi=%f, test gain g=%f\n", \
  263.               glo, ghi, g);
  264.       printf("----------------------------------------");
  265.       printf("--------------------------------------\n");
  266.       Z = inv(eye(ncstates) - Yinf*Xinf/g/g);
  267.       F = -R \ (d1dot'*C1 + BB'*Xinf);
  268.       H = -(B1*ddot1' + Yinf*CC') / Rtilde;
  269.       K = hinf_ctr(dgs,F,H,Z,g);
  270.  
  271.       Kst = strappend(Ast,"_K");
  272.       Kin = strappend(Aout((nout-ny+1):(nout)),"_K");
  273.       Kout = strappend(Ain((nin-nu+1):(nin)),"_K");
  274.       [Ac, Bc, Cc, Dc] = sys2ss(K);
  275.       K = ss2sys(Ac,Bc,Cc,Dc,Atsam,ncstates,ndstates,Kst,Kin,Kout);
  276.       if (nargout >= 3)
  277.     GW = starp(Asys, K);
  278.       endif
  279.     endif
  280.     
  281.   elseif(ndstates)
  282.  
  283.     # discrete time solution
  284.     error("hinfsyn: discrete-time case not yet implemented")
  285.  
  286.   endif
  287.  
  288. endfunction
  289.