Mercurial > hg > octave-lyh
view scripts/control/hinf/hinfsyn.m @ 7131:a184bc985c37
[project @ 2007-11-08 15:55:02 by jwe]
author | jwe |
---|---|
date | Thu, 08 Nov 2007 15:55:02 +0000 |
parents | a1dbe9d80eee |
children | df9519e9990c |
line wrap: on
line source
## Copyright (C) 1996, 1998, 2000, 2004, 2005, 2006, 2007 ## Auburn University. All rights reserved. ## ## This file is part of Octave. ## ## Octave is free software; you can redistribute it and/or modify it ## under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or (at ## your option) any later version. ## ## Octave is distributed in the hope that it will be useful, but ## WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with Octave; see the file COPYING. If not, see ## <http://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{k}, @var{g}, @var{gw}, @var{xinf}, @var{yinf}] =} hinfsyn (@var{asys}, @var{nu}, @var{ny}, @var{gmin}, @var{gmax}, @var{gtol}, @var{ptol}, @var{tol}) ## ## @strong{Inputs} input system is passed as either ## @table @var ## @item asys ## system data structure (see @command{ss}, @command{sys2ss}) ## @itemize @bullet ## @item controller is implemented for continuous time systems ## @item controller is @strong{not} implemented for discrete time systems (see ## bilinear transforms in @command{c2d}, @command{d2c}) ## @end itemize ## @item nu ## number of controlled inputs ## @item ny ## number of measured outputs ## @item gmin ## initial lower bound on ## @iftex ## @tex ## $ { \cal H }_\infty $ ## @end tex ## @end iftex ## @ifinfo ## H-infinity ## @end ifinfo ## optimal gain ## @item gmax ## initial upper bound on ## @iftex ## @tex ## $ { \cal H }_\infty $ ## @end tex ## @end iftex ## @ifinfo ## H-infinity ## @end ifinfo ## Optimal gain. ## @item gtol ## Gain threshold. Routine quits when @var{gmax}/@var{gmin} < 1+tol. ## @item ptol ## poles with @code{abs(real(pole))} ## @iftex ## @tex ## $ < ptol \Vert H \Vert $ ## @end tex ## @end iftex ## @ifinfo ## < ptol*||H|| ## @end ifinfo ## (@var{H} is appropriate ## Hamiltonian) are considered to be on the imaginary axis. ## Default: 1e-9. ## @item tol ## threshold for 0. Default: 200*@code{eps}. ## ## @var{gmax}, @var{min}, @var{tol}, and @var{tol} must all be positive scalars. ## @end table ## @strong{Outputs} ## @table @var ## @item k ## System controller. ## @item g ## Designed gain value. ## @item gw ## Closed loop system. ## @item xinf ## @acronym{ARE} solution matrix for regulator subproblem. ## @item yinf ## @acronym{ARE} solution matrix for filter subproblem. ## @end table ## ## References: ## @enumerate ## @item Doyle, Glover, Khargonekar, Francis, @cite{State-Space Solutions ## to Standard} ## @iftex ## @tex ## $ { \cal H }_2 $ @cite{and} $ { \cal H }_\infty $ ## @end tex ## @end iftex ## @ifinfo ## @cite{H-2 and H-infinity} ## @end ifinfo ## @cite{Control Problems}, @acronym{IEEE} @acronym{TAC} August 1989. ## ## @item Maciejowksi, J.M., @cite{Multivariable feedback design}, ## Addison-Wesley, 1989, @acronym{ISBN} 0-201-18243-2. ## ## @item Keith Glover and John C. Doyle, @cite{State-space formulae for all ## stabilizing controllers that satisfy an} ## @iftex ## @tex ## $ { \cal H }_\infty $@cite{norm} ## @end tex ## @end iftex ## @ifinfo ## @cite{H-infinity-norm} ## @end ifinfo ## @cite{bound and relations to risk sensitivity}, ## Systems & Control Letters 11, Oct. 1988, pp 167--172. ## @end enumerate ## @end deftypefn ## Author: A. S. Hodel <a.s.hodel@eng.auburn.edu> ## Created: August 1995 ## Updated for Packed system structures December 1996 by John Ingram ## ## Revised by Kai P. Mueller April 1998 to solve the general H_infinity ## problem using unitary transformations Q (on w and z) ## and non-singular transformations R (on u and y). function [K, g, GW, Xinf, Yinf] = hinfsyn (Asys, nu, ny, gmin, gmax, gtol, ptol, tol) if (nargin < 1 || nargin > 8) print_usage (); endif ## set default arguments if (nargin < 8) tol = 200*eps; elseif (! is_sample (tol)) error ("tol must be a positive scalar.") endif if (nargin < 7) ptol = 1e-9; elseif (! is_sample (ptol)) error ("hinfsyn: ptol must be a positive scalar"); endif if (! is_sample (gmax) || ! is_sample (gmin) || ! is_sample (gtol)) error ("hinfsyn: gmax=%g, gmin=%g, gtol=%g must be positive scalars", gmax, gmin, gtol); endif [chkdgkf, dgs] = is_dgkf (Asys, nu, ny, tol); if (! chkdgkf ) error ("hinfsyn: system does not meet required assumptions") endif ## extract dgs information nw = dgs.nw; nu = dgs.nu; nz = dgs.nz; ny = dgs.ny; A = dgs.A; B1 = dgs.Bw; B2 = dgs.Bu; C1 = dgs.Cz; C2 = dgs.Cy; D11 = dgs.Dzw; D12 = dgs.Dzu; D21 = dgs.Dyw; D22 = dgs.Dyu; d22nz = dgs.Dyu_nz; dflg = dgs.dflg; ## recover i/o transformations R12 = dgs.Ru; R21 = dgs.Ry; [ncstates, ndstates, nin, nout] = sysdimensions (Asys); Atsam = sysgettsam (Asys); [Ast, Ain, Aout] = sysgetsignals (Asys); BB = [B1, B2]; CC = [C1 ; C2]; DD = [D11, D12 ; D21, D22]; if (dflg == 0) n = ncstates; ## perform binary search to find gamma min ghi = gmax; ## derive a lower lower bound for gamma from D matrices xx1 = norm ((eye(nz) - (D12/(D12'*D12))*D12')*D11); xx2 = norm (D11*(eye(nw)-(D21'/(D21*D21'))*D21)); glo = max (xx1, xx2); if (glo > gmin) warning (" *** D matrices indicate a greater value of gamma min."); warning (" gamma min (%f) superseeded by %f.", gmin, glo); glo = xx1; else glo = gmin; endif if (glo > ghi) error (" *** lower bound of gamma greater than upper bound (%g, %g)", glo, ghi); endif de = ghi - glo; g = glo; search_state = 0; iteration_finished = 0; disp(" o structural tests passed, start of iteration..."); disp(" o <-> test passed # <-> test failed - <-> cannot test"); printf("----------------------------------------"); printf("--------------------------------------\n"); ## ------123456789012345678901234567890123456789012345678901234567890 printf(" .........X......... .........Y......... "); printf(".Z. PASS REMARKS\n"); printf(" ga iax nev ene sym pos iax nev ene sym pos "); printf("rho y/n ======>\n"); printf("----------------------------------------"); printf("--------------------------------------\n"); ## set up error messages errmesg = {" o o o o o ", ... " # - - - - ", ... " o # - - - ", ... " o o # - - ", ... " o o o # - ", ... " o o o o # ", ... " - - - - - "}; errdesx = {"", ... "X im eig.", ... "Hx not Ham.", ... "X inf.eig", ... "X not symm.", ... "X not pos", ... "R singular"}; errdesy = {" ", ... "Y im eig.", ... "Hy not Ham.", ... "Y inf.eig", ... "Y not symm.", ... "Y not pos", ... "Rtilde singular"}; ## now do the search while (! iteration_finished) switch (search_state) case 0 g = ghi; case 1 g = glo; case 2 g = 0.5 * (ghi + glo); otherwise error (" *** This should never happen!"); endswitch printf ("%10.4f ", g); ## computing R and R~ d1dot = [D11, D12]; R = zeros (nin, nin); R(1:nw,1:nw) = -g*g*eye(nw); R = R + d1dot' * d1dot; ddot1 = [D11; D21]; Rtilde = zeros (nout, nout); Rtilde(1:nz,1:nz) = -g*g*eye(nz); Rtilde = Rtilde + ddot1 * ddot1'; [Xinf, x_ha_err] = hinfsyn_ric (A, BB, C1, d1dot, R, ptol); [Yinf, y_ha_err] = hinfsyn_ric (A', CC', B1', ddot1', Rtilde, ptol); ## assume failure for this gamma passed = 0; rerr = ""; if (! x_ha_err && ! y_ha_err) ## test spectral radius condition rho = max (abs (eig (Xinf * Yinf))); if (rho < g*g) ## spectral radius condition passed passed = 1; else rerr = sprintf ("rho=%f",rho); endif endif if (x_ha_err >= 0 && x_ha_err <= 6) printf ("%s", errmesg{x_ha_err+1}); xerr = errdesx{x_ha_err+1}; else error (" *** Xinf fail: this should never happen!"); endif if (y_ha_err >= 0 && y_ha_err <= 6) printf ("%s", errmesg{y_ha_err+1}); yerr = errdesy{y_ha_err+1}; else error (" *** Yinf fail: this should never happen!"); endif if (passed) printf (" y all tests passed.\n"); else printf (" n %s/%s%s\n", xerr, yerr, rerr); endif if (passed && (de/g < gtol)) search_state = 3; endif switch (search_state) case 0 if (! passed) ## upper bound must pass but did not fprintf(" *** the upper bound of gamma (%f) is too small.\n", g); iteration_finished = 2; else search_state = 1; endif case 1 if (! passed) search_state = 2; else ## lower bound must not pass but passed fprintf (" *** the lower bound of gamma (%f) passed.\n", g); iteration_finished = 3; endif case 2 ## Normal case; must check that singular R, Rtilde wasn't the problem. if (! passed && x_ha_err != 6 && y_ha_err != 6) glo = g; else ghi = g; endif de = ghi - glo; case 3 iteration_finished = 1; # done otherwise error (" *** This should never happen!"); endswitch endwhile printf ("----------------------------------------"); printf ("--------------------------------------\n"); if (iteration_finished != 1) K = []; else ## success: compute controller fprintf (" hinfsyn final: glo=%f ghi=%f, test gain g=%f\n", glo, ghi, g); printf ("----------------------------------------"); printf ("--------------------------------------\n"); Z = inv (eye(ncstates) - Yinf*Xinf/g/g); F = -R \ (d1dot'*C1 + BB'*Xinf); H = -(B1*ddot1' + Yinf*CC') / Rtilde; K = hinf_ctr (dgs, F, H, Z, g); Kst = strappend (Ast, "_K"); Kin = strappend (Aout((nout-ny+1):(nout)),"_K"); Kout = strappend (Ain((nin-nu+1):(nin)),"_K"); [Ac, Bc, Cc, Dc] = sys2ss (K); K = ss (Ac, Bc, Cc, Dc, Atsam, ncstates, ndstates, Kst, Kin, Kout); if (nargout >= 3) GW = starp (Asys, K); endif endif elseif (ndstates) ## discrete time solution error ("hinfsyn: discrete-time case not yet implemented") endif endfunction