# HG changeset patch # User jwe # Date 947821802 0 # Node ID 65b3519ac3a1fc15785d5b70dd548952e1fdc51e # Parent b9f5829ec843f363cd584e6282d32a18ee341a83 [project @ 2000-01-14 03:44:03 by jwe] diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/Makefile.in --- a/scripts/control/Makefile.in Fri Jan 14 03:18:47 2000 +0000 +++ b/scripts/control/Makefile.in Fri Jan 14 03:50:02 2000 +0000 @@ -20,7 +20,7 @@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_DATA = @INSTALL_DATA@ -SUBDIRS = base hinf obsolete sys +SUBDIRS = base hinf obsolete system DISTSUBDIRS = $(SUBDIRS) diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/dezero.m --- a/scripts/control/dezero.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,59 +0,0 @@ -## Copyright (C) 1996 Kurt Hornik -## -## 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place - Suite 330, Boston, MA -## 02111-1307, USA. - -## -*- texinfo -*- -## @deftypefn {Functin File} {@var{t} =} dezero (@var{s}) -## Remove trailing blank entries and all zero entries from the string s. -## @end deftypefn - -## Author: Kurt Hornik -## Adapted-By: jwe - -## Adapted from deblank by A. S. Hodel (a.s.hodel@eng.auburn.edu) -## (the name dezero is a reference to the Fermilab D0 experiment, -## where my sister did her PhD research) - -function t = dezero (s) - - ## delete the next line if you're stubbornly going to use dezero. - error("dezero is no longer supported."); - - if (nargin != 1) - usage ("dezero (s)"); - elseif (isstr (s)) - - [nr, nc] = size (s); - len = nr * nc; - - if (len == 0) - t = s; - else - - s = reshape (s, 1, len); - - ## need to remove zeros first, then call deblank - s = toascii (s); - t = deblank(setstr(s(find(s != 0) ))); - endif - - else - error ("dezero: expecting string argument"); - endif - -endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/fir2sys.m --- a/scripts/control/fir2sys.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,105 +0,0 @@ -## Copyright (C) 1996, 1998 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## -*- texinfo -*- -## @deftypefn {Function File} {@var{sys} =} fir2sys (@var{num}@{, @var{tsam}, @var{inname}, @var{outname} @}) -## construct a system data structure from FIR description -## -## @strong{Inputs:} -## @table @var -## @item num -## vector of coefficients @math{[c_0 c_1 ... c_n]} -## of the SISO FIR transfer function -## @ifinfo -## -## C(z) = c0 + c1*z^@{-1@} + c2*z^@{-2@} + ... + znz^@{-n@} -## -## @end ifinfo -## @iftex -## @tex -## $$C(z) = c0 + c1*z^{-1} + c2*z^{-2} + ... + znz^{-n}$$ -## @end tex -## @end iftex -## -## @item tsam -## sampling time (default: 1) -## -## @item inname -## name of input signal; may be a string or a list with a single entry. -## -## @item outname -## name of output signal; may be a string or a list with a single entry. -## @end table -## -## @strong{Outputs} -## @var{sys} (system data structure) -## -## @strong{Example} -## @example -## octave:1> sys = fir2sys([1 -1 2 4],0.342,"A/D input","filter output"); -## octave:2> sysout(sys) -## Input(s) -## 1: A/D input -## -## Output(s): -## 1: filter output (discrete) -## -## Sampling interval: 0.342 -## transfer function form: -## 1*z^3 - 1*z^2 + 2*z^1 + 4 -## ------------------------- -## 1*z^3 + 0*z^2 + 0*z^1 + 0 -## @end example -## @end deftypefn - -## Author: R. Bruce Tenison -## Created: July 29, 1994 -## Name changed to TF2SYS July 1995 -## updated for new system data structure format July 1996 -## adapted from tf2sys july 1996 - -function sys = fir2sys (num, tsam, inname, outname) - - ## Test for the correct number of input arguments - if (nargin < 1 | nargin > 4) - usage ("sys = fir2sys(num [, tsam, inname, outname])"); - endif - - ## let tf2sys do the argument checking - den = [1,zeros(1,length(num)-1)]; - - ## check sampling interval (if any) - if (nargin <= 1) - tsam = 1; # default - elseif (isempty(tsam)) - tsam = 1; - endif - - ## Set name of input - if (nargin < 3) - inname = sysdefioname (1, "u"); - endif - - ## Set name of output - if (nargin < 4) - outname = sysdefioname (1, "y"); - endif - - sys = tf2sys (num, den, tsam, inname, outname); - -endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/h2norm.m --- a/scripts/control/h2norm.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,58 +0,0 @@ -## Copyright (C) 1996, 1998 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## -*- texinfo -*- -## @deftypefn {Function Fil} {@var{retval} =} h2norm(@var{sys}) -## Computes the H2 norm of a system data structure (continuous time only) -## -## Reference: -## Doyle, Glover, Khargonekar, Francis, ``State Space Solutions to Standard -## H2 and Hinf Control Problems", IEEE TAC August 1989 -## @end deftypefn - -## Author: A. S. Hodel -## Created: August 1995 -## updated for system data structure by John Ingram November 1996 - -function h2gain = h2norm (sys) - - if((nargin != 1)) - usage("h2gain = h2norm(sys)"); - elseif(!is_struct(sys)) - error("Sys must be in system data structure"); - end - dflg = is_digital(sys); - - if(!is_stable(sys)) - warning("h2norm: unstable input system; returning Inf"); - h2gain = Inf; - else - ## compute gain - [a,b,c,d] = sys2ss(sys); - if(dflg) - M = dlyap(a,b*b'); - else - M = lyap (a,b*b'); - endif - if( min(real(eig(M))) < 0) - error("h2norm: grammian not >= 0 (lightly damped modes?)") - endif - - h2gain = sqrt(trace(d'*d + c*M*c')); - endif -endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/h2syn.m --- a/scripts/control/h2syn.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,169 +0,0 @@ -## Copyright (C) 1996, 1998 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## -*- texinfo -*- -## @deftypefn {Function File} {[K}, @var{gain}, @var{Kc}, @var{Kf}, @var{Pc}, @var{Pf}] = h2syn(@var{Asys}, @var{nu}, @var{ny}, @var{tol}) -## Design H2 optimal controller per procedure in -## Doyle, Glover, Khargonekar, Francis, "State Space Solutions to Standard -## H2 and Hinf Control Problems", IEEE TAC August 1989 -## -## Discrete time control per Zhou, Doyle, and Glover, ROBUST AND OPTIMAL -## CONTROL, Prentice-Hall, 1996 -## -## @strong{Inputs} input system is passed as either -## @table @var -## @item Asys -## system data structure (see ss2sys, sys2ss) -## @itemize @bullet -## @item controller is implemented for continuous time systems -## @item controller is NOT implemented for discrete time systems -## @end itemize -## @item nu -## number of controlled inputs -## @item ny -## number of measured outputs -## @item tol -## threshhold for 0. Default: 200*eps -## @end table -## -## @strong{Outputs} -## @table @var -## @item K -## system controller -## @item gain -## optimal closed loop gain -## @item Kc -## full information control (packed) -## @item Kf -## state estimator (packed) -## @item Pc -## ARE solution matrix for regulator subproblem -## @item Pf -## ARE solution matrix for filter subproblem -## @end table -## @end deftypefn - -## Updated for System structure December 1996 by John Ingram - -function [K, gain, Kc, Kf, Pc, Pf] = h2syn (Asys, nu, ny, tol) - - if ((nargin < 3) | (nargin > 4)) - usage("[K,gain, Kc, Kf, Pc, Pf] = h2syn(Asys,nu,ny[,tol])"); - elseif(nargin == 3 ) - [chkdgkf,dgs] = is_dgkf(Asys,nu,ny); - elseif(nargin == 4) - [chkdgkf,dgs] = is_dgkf(Asys,nu,ny,tol); - endif - - if (!chkdgkf ) - disp("h2syn: system does not meet required assumptions") - help is_dgkf - error("h2syn: exit"); - endif - - ## extract dgs information - nw = dgs.nw; nu = dgs.nu; - A = dgs.A; Bw = dgs.Bw; Bu = dgs.Bu; - Cz = dgs.Cz; Dzw = dgs.Dzw; Dzu = dgs.Dzu; nz = dgs.nz; - Cy = dgs.Cy; Dyw = dgs.Dyw; Dyu = dgs.Dyu; ny = dgs.ny; - d22nz = dgs.Dyu_nz; - dflg = dgs.dflg; - - if(norm(Dzw,Inf) > norm([Dzw, Dzu ; Dyw, Dyu],Inf)*1e-12) - warning("h2syn: Dzw nonzero; feedforward not implemented") - Dzw - D = [Dzw, Dzu ; Dyw, Dyu] - endif - - ## recover i/o transformations - Ru = dgs.Ru; Ry = dgs.Ry; - [ncstates, ndstates, nout, nin] = sysdimensions(Asys); - Atsam = sysgettsam(Asys); - [Ast, Ain, Aout] = sysgetsignals(Asys); - - if(dgs.dflg == 0) - Pc = are(A,Bu*Bu',Cz'*Cz); # solve control, filtering ARE's - Pf = are(A',Cy'*Cy,Bw*Bw'); - F2 = -Bu'*Pc; # calculate feedback gains - L2 = -Pf*Cy'; - - AF2 = A + Bu*F2; - AL2 = A + L2*Cy; - CzF2 = Cz + (Dzu/Ru)*F2; - BwL2 = Bw+L2*(Ry\Dyw); - - else - ## discrete time solution - error("h2syn: discrete-time case not yet implemented") - Pc = dare(A,Bu*Bu',Cz'*Cz); - Pf = dare(A',Cy'*Cy,Bw*Bw'); - endif - - nn = ncstates + ndstates; - In = eye(nn); - KA = A + Bu*F2 + L2*Cy; - Kc1 = ss2sys(AF2,Bw,CzF2,zeros(nz,nw)); - Kf1 = ss2sys(AL2,BwL2,F2,zeros(nu,nw)); - - g1 = h2norm(Kc1); - g2 = h2norm(Kf1); - - ## compute optimal closed loop gain - gain = sqrt ( g1*g1 + g2*g2 ); - - if(nargout) - Kst = strappend(Ast,"_K"); - Kin = strappend(Aout((nout-ny+1):(nout)),"_K"); - Kout = strappend(Ain((nin-nu+1):(nin)),"_K"); - - ## compute systems for return - K = ss2sys(KA,-L2/Ru,Ry\F2,zeros(nu,ny),Atsam,ncstates,ndstates,Kst,Kin,Kout); - endif - - if (nargout > 2) - ## system full information control state names - stname2 = strappend(Ast,"_FI"); - - ## system full information control input names - inname2 = strappend(Ast,"_FI_in"); - - ## system full information control output names - outname2 = strappend(Aout(1:(nout-ny)),"_FI_out"); - - nz = rows (Cz); - nw = columns (Bw); - - Kc = ss2sys(AF2, In, CzF2, zeros(nz,nn), Atsam, ... - ncstates, ndstates, stname2, inname2, outname2); - endif - - if (nargout >3) - ## fix system state estimator state names - stname3 = strappend(Ast,"_Kf"); - - ## fix system state estimator input names - inname3 = strappend(Ast,"_Kf_noise"); - - ## fix system state estimator output names - outname3 = strappend(Ast,"_est"); - - Kf = ss2sys(AL2, BwL2, In, zeros(nn,nw),Atsam, ... - ncstates, ndstates, stname3, inname3,outname3); - endif - -endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/hinf/h2norm.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/hinf/h2norm.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,58 @@ +## Copyright (C) 1996, 1998 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## -*- texinfo -*- +## @deftypefn {Function Fil} {@var{retval} =} h2norm(@var{sys}) +## Computes the H2 norm of a system data structure (continuous time only) +## +## Reference: +## Doyle, Glover, Khargonekar, Francis, ``State Space Solutions to Standard +## H2 and Hinf Control Problems", IEEE TAC August 1989 +## @end deftypefn + +## Author: A. S. Hodel +## Created: August 1995 +## updated for system data structure by John Ingram November 1996 + +function h2gain = h2norm (sys) + + if((nargin != 1)) + usage("h2gain = h2norm(sys)"); + elseif(!is_struct(sys)) + error("Sys must be in system data structure"); + end + dflg = is_digital(sys); + + if(!is_stable(sys)) + warning("h2norm: unstable input system; returning Inf"); + h2gain = Inf; + else + ## compute gain + [a,b,c,d] = sys2ss(sys); + if(dflg) + M = dlyap(a,b*b'); + else + M = lyap (a,b*b'); + endif + if( min(real(eig(M))) < 0) + error("h2norm: grammian not >= 0 (lightly damped modes?)") + endif + + h2gain = sqrt(trace(d'*d + c*M*c')); + endif +endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/hinf/h2syn.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/hinf/h2syn.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,169 @@ +## Copyright (C) 1996, 1998 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## -*- texinfo -*- +## @deftypefn {Function File} {[K}, @var{gain}, @var{Kc}, @var{Kf}, @var{Pc}, @var{Pf}] = h2syn(@var{Asys}, @var{nu}, @var{ny}, @var{tol}) +## Design H2 optimal controller per procedure in +## Doyle, Glover, Khargonekar, Francis, "State Space Solutions to Standard +## H2 and Hinf Control Problems", IEEE TAC August 1989 +## +## Discrete time control per Zhou, Doyle, and Glover, ROBUST AND OPTIMAL +## CONTROL, Prentice-Hall, 1996 +## +## @strong{Inputs} input system is passed as either +## @table @var +## @item Asys +## system data structure (see ss2sys, sys2ss) +## @itemize @bullet +## @item controller is implemented for continuous time systems +## @item controller is NOT implemented for discrete time systems +## @end itemize +## @item nu +## number of controlled inputs +## @item ny +## number of measured outputs +## @item tol +## threshhold for 0. Default: 200*eps +## @end table +## +## @strong{Outputs} +## @table @var +## @item K +## system controller +## @item gain +## optimal closed loop gain +## @item Kc +## full information control (packed) +## @item Kf +## state estimator (packed) +## @item Pc +## ARE solution matrix for regulator subproblem +## @item Pf +## ARE solution matrix for filter subproblem +## @end table +## @end deftypefn + +## Updated for System structure December 1996 by John Ingram + +function [K, gain, Kc, Kf, Pc, Pf] = h2syn (Asys, nu, ny, tol) + + if ((nargin < 3) | (nargin > 4)) + usage("[K,gain, Kc, Kf, Pc, Pf] = h2syn(Asys,nu,ny[,tol])"); + elseif(nargin == 3 ) + [chkdgkf,dgs] = is_dgkf(Asys,nu,ny); + elseif(nargin == 4) + [chkdgkf,dgs] = is_dgkf(Asys,nu,ny,tol); + endif + + if (!chkdgkf ) + disp("h2syn: system does not meet required assumptions") + help is_dgkf + error("h2syn: exit"); + endif + + ## extract dgs information + nw = dgs.nw; nu = dgs.nu; + A = dgs.A; Bw = dgs.Bw; Bu = dgs.Bu; + Cz = dgs.Cz; Dzw = dgs.Dzw; Dzu = dgs.Dzu; nz = dgs.nz; + Cy = dgs.Cy; Dyw = dgs.Dyw; Dyu = dgs.Dyu; ny = dgs.ny; + d22nz = dgs.Dyu_nz; + dflg = dgs.dflg; + + if(norm(Dzw,Inf) > norm([Dzw, Dzu ; Dyw, Dyu],Inf)*1e-12) + warning("h2syn: Dzw nonzero; feedforward not implemented") + Dzw + D = [Dzw, Dzu ; Dyw, Dyu] + endif + + ## recover i/o transformations + Ru = dgs.Ru; Ry = dgs.Ry; + [ncstates, ndstates, nout, nin] = sysdimensions(Asys); + Atsam = sysgettsam(Asys); + [Ast, Ain, Aout] = sysgetsignals(Asys); + + if(dgs.dflg == 0) + Pc = are(A,Bu*Bu',Cz'*Cz); # solve control, filtering ARE's + Pf = are(A',Cy'*Cy,Bw*Bw'); + F2 = -Bu'*Pc; # calculate feedback gains + L2 = -Pf*Cy'; + + AF2 = A + Bu*F2; + AL2 = A + L2*Cy; + CzF2 = Cz + (Dzu/Ru)*F2; + BwL2 = Bw+L2*(Ry\Dyw); + + else + ## discrete time solution + error("h2syn: discrete-time case not yet implemented") + Pc = dare(A,Bu*Bu',Cz'*Cz); + Pf = dare(A',Cy'*Cy,Bw*Bw'); + endif + + nn = ncstates + ndstates; + In = eye(nn); + KA = A + Bu*F2 + L2*Cy; + Kc1 = ss2sys(AF2,Bw,CzF2,zeros(nz,nw)); + Kf1 = ss2sys(AL2,BwL2,F2,zeros(nu,nw)); + + g1 = h2norm(Kc1); + g2 = h2norm(Kf1); + + ## compute optimal closed loop gain + gain = sqrt ( g1*g1 + g2*g2 ); + + if(nargout) + Kst = strappend(Ast,"_K"); + Kin = strappend(Aout((nout-ny+1):(nout)),"_K"); + Kout = strappend(Ain((nin-nu+1):(nin)),"_K"); + + ## compute systems for return + K = ss2sys(KA,-L2/Ru,Ry\F2,zeros(nu,ny),Atsam,ncstates,ndstates,Kst,Kin,Kout); + endif + + if (nargout > 2) + ## system full information control state names + stname2 = strappend(Ast,"_FI"); + + ## system full information control input names + inname2 = strappend(Ast,"_FI_in"); + + ## system full information control output names + outname2 = strappend(Aout(1:(nout-ny)),"_FI_out"); + + nz = rows (Cz); + nw = columns (Bw); + + Kc = ss2sys(AF2, In, CzF2, zeros(nz,nn), Atsam, ... + ncstates, ndstates, stname2, inname2, outname2); + endif + + if (nargout >3) + ## fix system state estimator state names + stname3 = strappend(Ast,"_Kf"); + + ## fix system state estimator input names + inname3 = strappend(Ast,"_Kf_noise"); + + ## fix system state estimator output names + outname3 = strappend(Ast,"_est"); + + Kf = ss2sys(AL2, BwL2, In, zeros(nn,nw),Atsam, ... + ncstates, ndstates, stname3, inname3,outname3); + endif + +endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/hinf/hinf_ctr.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/hinf/hinf_ctr.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,144 @@ +## Copyright (C) 1996 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## -*- texinfo -*- +## @deftypefn {Function File } {@var{K} =} hinf_ctr(@var{dgs}, @var{F}, @var{H}, @var{Z}, @var{g}) +## Called by @code{hinfsyn} to compute the H_inf optimal controller. +## +## @strong{Inputs} +## @table @var +## @item dgs +## data structure returned by @code{is_dgkf} +## @item F +## @itemx H +## feedback and filter gain (not partitioned) +## @item g +## final gamma value +## @end table +## @strong{Outputs} +## controller K (system data structure) +## +## Do not attempt to use this at home; no argument checking performed. +## @end deftypefn + +## Author: A. S. Hodel +## Created: August 1995 +## 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 = hinf_ctr (dgs, F, H, Z, g) + + nw = dgs.nw; + nu = dgs.nu; + nz = dgs.nz; + ny = dgs.ny; + d22nz = dgs.Dyu_nz; + + B1 = dgs.Bw; + B2 = dgs.Bu; + C1 = dgs.Cz; + C2 = dgs.Cy; + C = [C1; C2]; + D11 = dgs.Dzw; + D12 = dgs.Dzu; + D21 = dgs.Dyw; + D22 = dgs.Dyu; + A = dgs.A; + Ru = dgs.Ru; + Ry = dgs.Ry; + + nout = nz + ny; + nin = nw + nu; + nstates = size(A, 1); + + F11 = F(1:(nw-ny),:); + F12 = F((nw-ny+1):nw,:); + F2 = F((nw+1):nin,:); + H11 = H(:,1:(nz-nu)); + H12 = H(:,(nz-nu+1):nz); + H2 = H(:,(nz+1):nout); + + ## D11 partitions + D1111 = D11(1:(nz-nu),1:(nw-ny)); + D1112 = D11(1:(nz-nu),(nw-ny+1):nw); + D1121 = D11((nz-nu+1):nz,1:(nw-ny)); + D1122 = D11((nz-nu+1):nz,(nw-ny+1):nw); + + ## D11ik may be the empty matrix, don't calculate with empty matrices + [nd1111,md1111] = size(D1111); + md1112 = length(D1112); + md1121 = length(D1121); + + if ((nd1111 == 0) || (md1112 == 0)) + d11hat = -D1122; + else + xx = inv(g*g*eye(nz-nu) - D1111*D1111'); + d11hat = -D1121*D1111'*xx*D1112 - D1122; + endif + if (md1112 == 0) + d21hat = eye(ny); + elseif (nd1111 == 0) + d21hat = chol(eye(ny) - D1112'*D1112/g/g); + else + xx = inv(g*g*eye(nz-nu) - D1111*D1111'); + xx = eye(ny) - D1112'*xx*D1112; + d21hat = chol(xx); + endif + if (md1121 == 0) + d12hat = eye(nu); + elseif (md1111 == 0) + d12hat = chol(eye(nu) - D1121*D1121'/g/g)'; + else + xx = inv(g*g*eye(nw-ny) - D1111'*D1111); + xx = eye(nu)-D1121*xx*D1121'; + d12hat = chol(xx)'; + endif + + b2hat = (B2+H12)*d12hat; + c2hat = -d21hat*(C2+F12)*Z; + b1hat = -H2 + (b2hat/d12hat)*d11hat; + c1hat = F2*Z + (d11hat/d21hat)*c2hat; + ahat = A + H*C + (b2hat/d12hat)*c1hat; + + ## rescale controller by Ru and Ry + b1hat = b1hat/Ry; + c1hat = Ru\c1hat; + bhat = [b1hat, b2hat]; + chat = [c1hat; c2hat]; + dhat = [Ru\d11hat/Ry, Ru\d12hat; d21hat/Ry, 0*d11hat']; + + ## non-zero D22 is a special case + if (d22nz) + if (rank(eye(nu) + d11hat*D22) < nu) + error(" *** cannot compute controller for D22 non-zero."); + endif + + d22new = [D22, zeros(ny,ny); zeros(nu,nu), 0*D22']; + xx = inv(eye(nu+ny) + d22new*dhat); + mhat = inv(eye(nu+ny) + dhat*d22new); + ahat = ahat - bhat*((eye(nu+ny)-xx)/dhat)*chat; + bhat = bhat*xx; + chat = mhat*chat; + dhat = dhat*xx; + + endif + + K = ss2sys(ahat,bhat(:,1:ny),chat(1:nu,:),dhat(1:nu,1:ny)); + +endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/hinf/hinfdemo.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/hinf/hinfdemo.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,330 @@ +## Copyright (C) 1996, 1998 Kai P. Mueller +## +## 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## -*- texinfo -*- +## @deftypefn {Function File} {} hinfdemo () +## +## H_infinity design demos for continuous SISO and MIMO systems and a +## discrete system. The SISO system is difficult to control because it +## is non minimum phase and unstable. The second design example +## controls the "jet707" plant, the linearized state space model of a +## Boeing 707-321 aircraft at v=80m/s (M = 0.26, Ga0 = -3 deg, alpha0 = +## 4 deg, kappa = 50 deg). Inputs: (1) thrust and (2) elevator angle +## outputs: (1) airspeed and (2) pitch angle. The discrete system is a +## stable and second order. +## +## @table @asis +## @item SISO plant +## @display +## @group +## s - 2 +## G(s) = -------------- +## (s + 2)(s - 1) +## +## +----+ +## -------------------->| W1 |---> v1 +## z | +----+ +## ----|-------------+ || T || => min. +## | | vz infty +## | +---+ v y +----+ +## u *--->| G |--->O--*-->| W2 |---> v2 +## | +---+ | +----+ +## | | +## | +---+ | +## -----| K |<------- +## +---+ +## @end group +## @end display +## W1 und W2 are the robustness and performance weighting +## functions +## +## @item MIMO plant +## The optimal controller minimizes the H_infinity norm of the +## augmented plant P (mixed-sensitivity problem): +## @display +## @group +## w +## 1 -----------+ +## | +----+ +## +---------------------->| W1 |----> z1 +## w | | +----+ +## 2 ------------------------+ +## | | | +## | v +----+ v +----+ +## +--*-->o-->| G |-->o--*-->| W2 |---> z2 +## | +----+ | +----+ +## | | +## ^ v +## u (from y (to K) +## controller +## K) +## +## +## + + + + +## | z | | w | +## | 1 | | 1 | +## | z | = [ P ] * | w | +## | 2 | | 2 | +## | y | | u | +## + + + + +## @end group +## @end display +## +## @item DISCRETE SYSTEM +## This is not a true discrete design. The design is carried out +## in continuous time while the effect of sampling is described by +## a bilinear transformation of the sampled system. +## This method works quite well if the sampling period is "small" +## compared to the plant time constants. +## +## @item The continuous plant +## @display +## @group +## 1 +## G (s) = -------------- +## k (s + 2)(s + 1) +## +## @end group +## @end display +## is discretised with a ZOH (Sampling period = Ts = 1 second): +## @display +## @group +## +## 0.199788z + 0.073498 +## G(s) = -------------------------- +## (z - 0.36788)(z - 0.13534) +## +## +----+ +## -------------------->| W1 |---> v1 +## z | +----+ +## ----|-------------+ || T || => min. +## | | vz infty +## | +---+ v +----+ +## *--->| G |--->O--*-->| W2 |---> v2 +## | +---+ | +----+ +## | | +## | +---+ | +## -----| K |<------- +## +---+ +## @end group +## @end display +## W1 and W2 are the robustness and performancs weighting +## functions +## @end table +## @end deftypefn + +## Author: Kai P. Mueller +## Created: April 30, 1998 + +yn = []; +while (length(yn) < 1) + yn = input(" * [s]iso, [m]imo, or [d]iscrete design? [no default]: ","S"); +endwhile +if ((yn(1) == "s") | (yn(1) == 'S')) + sys_type = 1; +elseif ((yn(1) == "m") | (yn(1) == 'M')) + sys_type = 2; +elseif ((yn(1) == "d") | (yn(1) == 'D')) + sys_type = 3; +else + disp(" *** no system type specified, hinfdemo terminated."); + return; +endif + +echo off +switch (sys_type) + + case (1) + ## siso + disp(" "); + disp(" ----------------------------------------------"); + disp(" H_infinity optimal control for the SISO plant:"); + disp(" "); + disp(" s - 2"); + disp(" G(s) = --------------"); + disp(" (s + 2)(s - 1)"); + disp(" "); + disp(" ----------------------------------------------"); + disp(" "); + + ## weighting on actuator u + W1 = wgt1o(0.05, 100.0, 425.0); + ## weighting on controlled variable y + W2 = wgt1o(10.0, 0.05, 0.001); + ## plant + G = tf2sys([1 -2],[1 1 -2]); + + ## need One as the pseudo transfer function One = 1 + One = ugain(1); + disp(" o forming P..."); + psys = buildssic([1 4;2 4;3 1],[3],[2 3 5],[3 4],G,W1,W2,One); + disp(" "); + disp(" o controller design..."); + [K, gfin, GW]=hinfsyn(psys, 1, 1, 0.1, 10.0, 0.02); + disp(" "); + disp("-- OK ----------------------------------------------"); + + disp(" Closed loop poles:"); + damp(GW); + ## disp(" o Testing H_infinity norm: (hinfnorm does not work)"); + ## hinfnorm(GW); + + disp(" "); + yn = input(" * Plot closed loop step response? [n]: ","S"); + if (length(yn) >= 1) + if ((yn(1) == "y") || (yn(1) == 'Y')) + disp(" o step responses of T and KS..."); + GW = buildssic([1 2; 2 1], [], [1 2], [-2], G, K); + figure(1); + step(GW, 1, 10); + endif + endif + + case (2) + ## mimo + disp(" "); + disp(" -----------------------------------------------"); + disp(" H_inf optimal control for the jet707 plant"); + disp(" -----------------------------------------------"); + disp(" "); + + ## Weighting function on u (robustness weight) + ww1 = wgt1o(0.01,5,0.9); + ww2 = wgt1o(0.01,5,2.2); + W1 = buildssic([1 0;2 0],[],[1 2],[1 2],ww1,ww2); + ## Weighting function on y (performance weight) + ww1 = wgt1o(250,0.1,0.0001); + ww2 = wgt1o(250,0.1,0.0002); + W2 = buildssic([1 0;2 0],[],[1 2],[1 2],ww1,ww2); + ## plant (2 x 2 system) + G = jet707; + + disp(" o forming P..."); + One = ugain(2); + Clst = [1 7; 2 8; 3 7; 4 8; 5 1; 6 2]; + P = buildssic(Clst,[5 6],[3:6 9 10],[1 2 5:8],G,W1,W2,One); + + disp(" "); + disp(" o controller design..."); + K = hinfsyn(P, 2, 2, 0.25, 10.0, 0.005); + + disp(" "); + yn = input(" * Plot closed loop step responses? [n]: ","S"); + if (length(yn) >= 1) + if ((yn(1) == "y") || (yn(1) == 'Y')) + disp(" o step responses of T and KS..."); + GW = buildssic([1 3;2 4;3 1;4 2],[],[1 2 3 4],[-3 -4],G,K); + + disp(" "); + disp(" FIGURE 1: speed refence => 1, pitch angle ref. => 0"); + disp(" ==================================================="); + disp(" y1: speed (should be 1)"); + disp(" y2: pitch angle (should remain 0)"); + disp(" y3: thrust (should be a slow transient)"); + disp(" y6: elevator (should be a faster transient)"); + disp(" "); + disp(" FIGURE 2: speed refence => 0, pitch angle ref. => 1"); + disp(" ==================================================="); + disp(" y1: speed (should remain 0)"); + disp(" y2: pitch angle (should be 1)"); + disp(" y3: thrust (should be a slow transient)"); + disp(" y6: elevator (should be a faster transient)"); + disp(" "); + figure(1) + step(GW); + figure(2) + step(GW,2); + endif + endif + + case (3) + ## discrete + disp(" "); + disp(" --------------------------------------------------"); + disp(" Discrete H_infinity optimal control for the plant:"); + disp(" "); + disp(" 0.199788z + 0.073498"); + disp(" G(s) = --------------------------"); + disp(" (z - 0.36788)(z - 0.13533)"); + disp(" --------------------------------------------------"); + disp(" "); + + ## sampling time + Ts = 1.0; + ## weighting on actuator value u + W1 = wgt1o(0.1, 200.0, 50.0); + ## weighting on controlled variable y + W2 = wgt1o(350.0, 0.05, 0.0002); + ## omega axis + ww = logspace(-4.99, 3.99, 100); + if (columns(ww) > 1); ww = ww'; endif + + ## continuous plant + G = tf2sys(2,[1 3 2]); + ## discrete plant with zoh + Gd = c2d(G, Ts); + ## w-plane (continuous representation of the sampled system) + Gw = d2c(Gd, "bi"); + + disp(" "); + disp(" o building P..."); + ## need One as the pseudo transfer function One = 1 + One = ugain(1); + psys = buildssic([1 4;2 4;3 1],[3],[2 3 5],[3 4],Gw,W1,W2,One); + disp(" o controller design..."); + [K, gfin, GWC] = hinfsyn(psys, 1, 1, 0.1, 10.0, 0.02); + + disp(" "); + fig_n = 1; + yn = input(" * Plot magnitudes of W1KS and W2S? [n]: ","S"); + if (length(yn) >= 1) + if ((yn(1) == "y") || (yn(1) == 'Y')) + disp(" o magnitudes of W1KS and W2S..."); + gwx = sysprune(GWC, 1, 1); + mag1 = bode(gwx, ww); + if (columns(mag1) > 1); mag1 = mag1'; endif + gwx = sysprune(GWC, 2, 1); + mag2 = bode(gwx, ww); + if (columns(mag2) > 1); mag2 = mag2'; endif + figure(fig_n) + fig_n = fig_n + 1; + gset grid + loglog(ww, [mag1 mag2]); + endif + endif + + Kd = c2d(K, "bi", Ts); + GG = buildssic([1 2; 2 1], [], [1 2], [-2], Gd, Kd); + disp(" o closed loop poles..."); + damp(GG); + + disp(" "); + yn = input(" * Plot closed loop step responses? [n]: ","S"); + if (length(yn) >= 1) + if ((yn(1) == "y") || (yn(1) == 'Y')) + disp(" o step responses of T and KS..."); + figure(fig_n) + step(GG, 1, 10); + endif + endif + +endswitch + +disp(" o hinfdemo terminated successfully."); + +## KPM-hinfdemo/End diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/hinf/hinfnorm.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/hinf/hinfnorm.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,160 @@ +## Copyright (C) 1996, 1998 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## -*- texinfo -*- +## @deftypefn {Function File} {[@var{g}, @var{gmin}, @var{gmax}] =} hinfnorm(@var{sys}@{, @var{tol}, @var{gmin}, @var{gmax}, @var{ptol}@}) +## Computes the H infinity norm of a system data structure. +## +## @strong{Inputs} +## @table @var +## @item sys +## system data structure +## @item tol +## H infinity norm search tolerance (default: 0.001) +## @item gmin +## minimum value for norm search (default: 1e-9) +## @item gmax +## maximum value for norm search (default: 1e+9) +## @item ptol +## pole tolerance: +## @itemize @bullet +## @item if sys is continuous, poles with +## |real(pole)| < ptol*||H|| (H is appropriate Hamiltonian) +## are considered to be on the imaginary axis. +## +## @item if sys is discrete, poles with +## |abs(pole)-1| < ptol*||[s1,s2]|| (appropriate symplectic pencil) +## are considered to be on the unit circle +## +## @item Default: 1e-9 +## @end itemize +## @end table +## +## @strong{Outputs} +## @table @var +## @item g +## Computed gain, within @var{tol} of actual gain. @var{g} is returned as Inf +## if the system is unstable. +## @item gmin +## @itemx gmax +## Actual system gain lies in the interval [@var{gmin}, @var{gmax}] +## @end table +## +## References: +## Doyle, Glover, Khargonekar, Francis, "State space solutions to standard +## H2 and Hinf control problems", IEEE TAC August 1989 +## Iglesias and Glover, "State-Space approach to discrete-time Hinf control," +## Int. J. Control, vol 54, #5, 1991 +## Zhou, Doyle, Glover, "Robust and Optimal Control," Prentice-Hall, 1996 +## @end deftypefn + +function [g, gmin, gmax] = hinfnorm (sys, tol, gmin, gmax, ptol) + + if((nargin == 0) || (nargin > 4)) + usage("[g gmin gmax] = hinfnorm(sys[,tol,gmin,gmax,ptol])"); + elseif(!is_struct(sys)) + error("Sys must be a system data structure"); + endif + + ## set defaults where applicable + if(nargin < 5) + ptol = 1e-9; # pole tolerance + endif + if(nargin < 4) + gmax = 1e9; # max gain value + endif + + dflg = is_digital(sys); + sys = sysupdate(sys,"ss"); + [A,B,C,D] = sys2ss(sys); + [n,nz,m,p] = sysdimensions(sys); + + ## eigenvalues of A must all be stable + if(!is_stable(sys)) + warning(["hinfnorm: unstable system (is_stable, ptol=",num2str(ptol), ... + "), returning Inf"]); + g = Inf; + endif + + Dnrm = norm(D); + if(nargin < 3) + gmin = max(1e-9,Dnrm); # min gain value + elseif(gmin < Dnrm) + warning(["hinfnorm: setting Gmin=||D||=",num2str(Dnrm)]); + endif + + if(nargin < 2) + tol = 0.001; # convergence measure for gmin, gmax + endif + + ## check for scalar input arguments 2...5 + if( ! (is_scalar(tol) && is_scalar(gmin) + && is_scalar(gmax) && is_scalar(ptol)) ) + error("hinfnorm: tol, gmin, gmax, ptol must be scalars"); + endif + + In = eye(n+nz); + Im = eye(m); + Ip = eye(p); + ## find the Hinf norm via binary search + while((gmax/gmin - 1) > tol) + g = (gmax+gmin)/2; + + if(dflg) + ## multiply g's through in formulas to avoid extreme magnitudes... + Rg = g^2*Im - D'*D; + Ak = A + (B/Rg)*D'*C; + Ck = g^2*C'*((g^2*Ip-D*D')\C); + + ## set up symplectic generalized eigenvalue problem per Iglesias & Glover + s1 = [Ak , zeros(nz) ; -Ck, In ]; + s2 = [In, -(B/Rg)*B' ; zeros(nz) , Ak' ]; + + ## guard against roundoff again: zero out extremely small values + ## prior to balancing + s1 = s1 .* (abs(s1) > ptol*norm(s1,"inf")); + s2 = s2 .* (abs(s2) > ptol*norm(s2,"inf")); + [cc,dd,s1,s2] = balance(s1,s2); + [qza,qzb,zz,pls] = qz(s1,s2,"S"); # ordered qz decomposition + eigerr = abs(abs(pls)-1); + normH = norm([s1,s2]); + Hb = [s1, s2]; + + ## check R - B' X B condition (Iglesias and Glover's paper) + X = zz((nz+1):(2*nz),1:nz)/zz(1:nz,1:nz); + dcondfailed = min(real( eig(Rg - B'*X*B)) < ptol); + else + Rinv = inv(g*g*Im - (D' * D)); + H = [A + B*Rinv*D'*C, B*Rinv*B'; ... + -C'*(Ip + D*Rinv*D')*C, -(A + B*Rinv*D'*C)']; + ## guard against roundoff: zero out extremely small values prior + ## to balancing + H = H .* (abs(H) > ptol*norm(H,"inf")); + [DD,Hb] = balance(H); + pls = eig(Hb); + eigerr = abs(real(pls)); + normH = norm(H); + dcondfailed = 0; # digital condition; doesn't apply here + endif + if( (min(eigerr) <= ptol * normH) | dcondfailed) + gmin = g; + else + gmax = g; + endif + endwhile +endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/hinf/hinfsyn.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/hinf/hinfsyn.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,314 @@ +## Copyright (C) 1996, 1998 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## -*- 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 ss2sys, sys2ss) +## @itemize @bullet +## @item controller is implemented for continuous time systems +## @item controller is NOT implemented for discrete time systems (see +## bilinear transforms in @code{c2d}, @code{d2c}) +## @end itemize +## @item nu +## number of controlled inputs +## @item ny +## number of measured outputs +## @item gmin +## initial lower bound on H-infinity optimal gain +## @item gmax +## initial upper bound on H-infinity optimal gain +## @item gtol +## gain threshhold. Routine quits when gmax/gmin < 1+tol +## @item ptol +## poles with abs(real(pole)) < ptol*||H|| (H is appropriate +## Hamiltonian) are considered to be on the imaginary axis. +## Default: 1e-9 +## @item tol +## threshhold for 0. Default: 200*eps +## +## @var{gmax}, @var{min}, @var{tol}, and @var{tol} must all be postive scalars. +## @end table +## @strong{Outputs} +## @table @var +## @item K +## system controller +## @item g +## designed gain value +## @item GW +## closed loop system +## @item Xinf +## ARE solution matrix for regulator subproblem +## @item Yinf +## ARE solution matrix for filter subproblem +## @end table +## +## @enumerate +## @item Doyle, Glover, Khargonekar, Francis, "State Space Solutions +## to Standard H2 and Hinf Control Problems," IEEE TAC August 1989 +## +## @item Maciejowksi, J.M., "Multivariable feedback design," +## Addison-Wesley, 1989, ISBN 0-201-18243-2 +## +## @item Keith Glover and John C. Doyle, "State-space formulae for all +## stabilizing controllers that satisfy and h-infinity-norm bound +## and relations to risk sensitivity," +## Systems & Control Letters 11, Oct. 1988, pp 167-172. +## @end enumerate +## @end deftypefn + +## Author: A. S. Hodel +## 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) ) + usage("[K,g,GW,Xinf,Yinf] = hinfsyn(Asys,nu,ny,gmin,gmax,gtol,ptol,tol)"); + 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=",num2str(gmax),", gmin=",num2str(gmin), ... + "gtol=",num2str(gtol), " must be positive scalars."]) + endif + + [chkdgkf,dgs] = is_dgkf(Asys,nu,ny,tol); + + if (! chkdgkf ) + disp("hinfsyn: system does not meet required assumptions") + help is_dgkf + error("hinfsyn: exit"); + endif + + ## extract dgs information + nw = dgs.nw; nu = dgs.nu; + A = dgs.A; B1 = dgs.Bw; B2 = dgs.Bu; + C1 = dgs.Cz; D11 = dgs.Dzw; D12 = dgs.Dzu; nz = dgs.nz; + C2 = dgs.Cy; D21 = dgs.Dyw; D22 = dgs.Dyu; ny = dgs.ny; + 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) + disp(" *** D matrices indicate a greater value of gamma min."); + fprintf(" gamma min (%f) superseeded by %f.", gmin, glo); + glo = xx1; + else + glo = gmin; + endif + if (glo > ghi) + fprintf(" *** lower bound of gamma greater than upper bound(%f)", ... + glo, ghi); + disp(" *** unable to continue, Goodbye."); + return; + 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 = list(" o o o o o ", ... + " # - - - - ", ... + " o # - - - ", ... + " o o # - - ", ... + " o o o # - ", ... + " o o o o # ", ... + " - - - - - "); + errdesx = list("", ... + "X im eig.", ... + "Hx not Ham.", ... + "X inf.eig", ... + "X not symm.", ... + "X not pos", ... + "R singular"); + + errdesy = list(" ", ... + "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",nth(errmesg,x_ha_err+1)); + xerr = nth(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",nth(errmesg,y_ha_err+1)); + yerr = nth(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 = ss2sys(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 diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/hinf/hinfsyn_chk.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/hinf/hinfsyn_chk.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,102 @@ +## Copyright (C) 1996 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## -*- texinfo -*- +## @deftypefn {Function File} {[@var{retval}, @var{Pc}, @var{Pf}] =} hinfsyn_chk(@var{A}, @var{B1}, @var{B2}, @var{C1}, @var{C2}, @var{D12}, @var{D21}, @var{g}, @var{ptol}) +## Called by @code{hinfsyn} to see if gain @var{g} satisfies conditions in +## Theorem 3 of +## Doyle, Glover, Khargonekar, Francis, "State Space Solutions to Standard +## H2 and Hinf Control Problems", IEEE TAC August 1989 +## +## @strong{Warning} Do not attempt to use this at home; no argument +## checking performed. +## +## @strong{Inputs} as returned by @code{is_dgkf}, except for: +## @table @var +## @item g +## candidate gain level +## @item ptol +## as in @code{hinfsyn} +## @end table +## +## @strong{Outputs} +## @table @var +## @item retval +## 1 if g exceeds optimal Hinf closed loop gain, else 0 +## @item Pc +## solution of "regulator" H-inf ARE +## @item Pf +## solution of "filter" H-inf ARE +## @end table +## Do not attempt to use this at home; no argument checking performed. +## @end deftypefn + +## Author: A. S. Hodel +## Created: August 1995 + +function [retval, Pc, Pf] = hinfsyn_chk (A, B1, B2, C1, C2, D12, D21, g, ptol) + + Pc = Pf = []; + + ## Construct the two Hamiltonians + g2 = 1/(g*g); + Hc = [ A , g2*B1*B1' - B2*B2'; -C1'*C1 , -A']; + Hf = [ A' , g2*C1'*C1 - C2'*C2; -B1*B1' , -A]; + + ## check if Hc, Hf are in dom(Ric) + Hcminval = min(abs(real(eig(Hc)))); + Hfminval = min(abs(real(eig(Hf)))); + if(Hcminval < ptol); + disp("hinfsyn_chk: Hc is not in dom(Ric)"); + retval = 0; + return + endif + if(Hfminval < ptol) + disp("hinfsyn_chk: Hf is not in dom(Ric)"); + retval = 0; + return + endif + + ## Solve ARE's + Pc = are(A, B2*B2'-g2*B1*B1',C1'*C1); + Pf = are(A',C2'*C2-g2*C1'*C1,B1*B1'); + + Pceig = eig(Pc); + Pfeig = eig(Pf); + Pcfeig = eig(Pc*Pf); + + if(min(Pceig) < -ptol) + disp("hinfsyn_chk: Pc is not >= 0"); + retval = 0; + return + endif + if(min(Pfeig) < -ptol) + disp("hinfsyn_chk: Pf is not >= 0"); + retval = 0; + return + endif + if(max(abs(Pcfeig)) >= g*g) + disp("hinfsyn_chk: rho(Pf*Pc) is not < g^2"); + retval = 0; + return + endif + + ## all conditions met. + retval = 1; + +endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/hinf/hinfsyn_ric.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/hinf/hinfsyn_ric.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,80 @@ +## Copyright (C) 1996, 1998 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## -*- texinfo -*- +## @deftypefn {Function File} {[@var{Xinf},@var{x_ha_err}] =} hinfsyn_ric(@var{A},@var{BB}.@var{C1},@var{d1dot},@var{R},@var{ptol}) +## @table +## @item forms +## xx = ([BB; -C1'*d1dot]/R) * [d1dot'*C1 BB']; +## Ha = [A 0*A; -C1'*C1 -A'] - xx; +## @end table +## and solves associated Riccati equation +## returns error code +## @table +## @item x_ha_err +## 0: successful +## 1: Xinf has imaginary eigenvalues +## 2: Hx not Hamiltonian +## 3: Xinf has inf. eigenvalues (numerical overflow) +## 4: Xinf not symmetric +## 5: Xinf not positive definite +## 6: R is singular +## @end table +## @end deftypefn + +function [Xinf, x_ha_err] = hinfsyn_ric (A, BB, C1, d1dot, R, ptol) + + x_ha_err = 0; # assume success + Xinf = []; # default return value + n = is_square(A); + nw = is_square(R); + if(rank(R) != nw) x_ha_err = 6; + else # build hamiltonian Ha for X_inf + xx = ([BB; -C1'*d1dot]/R) * [d1dot'*C1, BB']; + Ha = [A, 0*A; -C1'*C1, -A'] - xx; + x_ha_err = 0; + [d, Ha] = balance(Ha); + [u, s] = schur(Ha, "A"); + rev = real(eig(s)); + + if (any(abs(rev) <= ptol)) # eigenvalues near the imaginary axis + x_ha_err = 1; + elseif (sum(rev > 0) != sum(rev < 0)) + ## unequal number of positive and negative eigenvalues + x_ha_err = 2; + else + ## compute positive Riccati equation solution + u = d * u; + Xinf = u(n+1:2*n,1:n) / u(1:n,1:n); + if (!all(all(finite(Xinf)))) + x_ha_err = 3; + elseif (norm(Xinf-Xinf') >= 10*ptol) + ## solution not symmetric + x_ha_err = 4; + else + ## positive semidefinite? + ## force symmetry (faster, avoids some convergence problems) + Xinf = (Xinf + Xinf')/2; + rev = eig(Xinf); + if (any(rev <= -ptol)) + x_ha_err = 5; + endif + endif + endif + endif +endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/hinf_ctr.m --- a/scripts/control/hinf_ctr.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,144 +0,0 @@ -## Copyright (C) 1996 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## -*- texinfo -*- -## @deftypefn {Function File } {@var{K} =} hinf_ctr(@var{dgs}, @var{F}, @var{H}, @var{Z}, @var{g}) -## Called by @code{hinfsyn} to compute the H_inf optimal controller. -## -## @strong{Inputs} -## @table @var -## @item dgs -## data structure returned by @code{is_dgkf} -## @item F -## @itemx H -## feedback and filter gain (not partitioned) -## @item g -## final gamma value -## @end table -## @strong{Outputs} -## controller K (system data structure) -## -## Do not attempt to use this at home; no argument checking performed. -## @end deftypefn - -## Author: A. S. Hodel -## Created: August 1995 -## 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 = hinf_ctr (dgs, F, H, Z, g) - - nw = dgs.nw; - nu = dgs.nu; - nz = dgs.nz; - ny = dgs.ny; - d22nz = dgs.Dyu_nz; - - B1 = dgs.Bw; - B2 = dgs.Bu; - C1 = dgs.Cz; - C2 = dgs.Cy; - C = [C1; C2]; - D11 = dgs.Dzw; - D12 = dgs.Dzu; - D21 = dgs.Dyw; - D22 = dgs.Dyu; - A = dgs.A; - Ru = dgs.Ru; - Ry = dgs.Ry; - - nout = nz + ny; - nin = nw + nu; - nstates = size(A, 1); - - F11 = F(1:(nw-ny),:); - F12 = F((nw-ny+1):nw,:); - F2 = F((nw+1):nin,:); - H11 = H(:,1:(nz-nu)); - H12 = H(:,(nz-nu+1):nz); - H2 = H(:,(nz+1):nout); - - ## D11 partitions - D1111 = D11(1:(nz-nu),1:(nw-ny)); - D1112 = D11(1:(nz-nu),(nw-ny+1):nw); - D1121 = D11((nz-nu+1):nz,1:(nw-ny)); - D1122 = D11((nz-nu+1):nz,(nw-ny+1):nw); - - ## D11ik may be the empty matrix, don't calculate with empty matrices - [nd1111,md1111] = size(D1111); - md1112 = length(D1112); - md1121 = length(D1121); - - if ((nd1111 == 0) || (md1112 == 0)) - d11hat = -D1122; - else - xx = inv(g*g*eye(nz-nu) - D1111*D1111'); - d11hat = -D1121*D1111'*xx*D1112 - D1122; - endif - if (md1112 == 0) - d21hat = eye(ny); - elseif (nd1111 == 0) - d21hat = chol(eye(ny) - D1112'*D1112/g/g); - else - xx = inv(g*g*eye(nz-nu) - D1111*D1111'); - xx = eye(ny) - D1112'*xx*D1112; - d21hat = chol(xx); - endif - if (md1121 == 0) - d12hat = eye(nu); - elseif (md1111 == 0) - d12hat = chol(eye(nu) - D1121*D1121'/g/g)'; - else - xx = inv(g*g*eye(nw-ny) - D1111'*D1111); - xx = eye(nu)-D1121*xx*D1121'; - d12hat = chol(xx)'; - endif - - b2hat = (B2+H12)*d12hat; - c2hat = -d21hat*(C2+F12)*Z; - b1hat = -H2 + (b2hat/d12hat)*d11hat; - c1hat = F2*Z + (d11hat/d21hat)*c2hat; - ahat = A + H*C + (b2hat/d12hat)*c1hat; - - ## rescale controller by Ru and Ry - b1hat = b1hat/Ry; - c1hat = Ru\c1hat; - bhat = [b1hat, b2hat]; - chat = [c1hat; c2hat]; - dhat = [Ru\d11hat/Ry, Ru\d12hat; d21hat/Ry, 0*d11hat']; - - ## non-zero D22 is a special case - if (d22nz) - if (rank(eye(nu) + d11hat*D22) < nu) - error(" *** cannot compute controller for D22 non-zero."); - endif - - d22new = [D22, zeros(ny,ny); zeros(nu,nu), 0*D22']; - xx = inv(eye(nu+ny) + d22new*dhat); - mhat = inv(eye(nu+ny) + dhat*d22new); - ahat = ahat - bhat*((eye(nu+ny)-xx)/dhat)*chat; - bhat = bhat*xx; - chat = mhat*chat; - dhat = dhat*xx; - - endif - - K = ss2sys(ahat,bhat(:,1:ny),chat(1:nu,:),dhat(1:nu,1:ny)); - -endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/hinfdemo.m --- a/scripts/control/hinfdemo.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,330 +0,0 @@ -## Copyright (C) 1996, 1998 Kai P. Mueller -## -## 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## -*- texinfo -*- -## @deftypefn {Function File} {} hinfdemo () -## -## H_infinity design demos for continuous SISO and MIMO systems and a -## discrete system. The SISO system is difficult to control because it -## is non minimum phase and unstable. The second design example -## controls the "jet707" plant, the linearized state space model of a -## Boeing 707-321 aircraft at v=80m/s (M = 0.26, Ga0 = -3 deg, alpha0 = -## 4 deg, kappa = 50 deg). Inputs: (1) thrust and (2) elevator angle -## outputs: (1) airspeed and (2) pitch angle. The discrete system is a -## stable and second order. -## -## @table @asis -## @item SISO plant -## @display -## @group -## s - 2 -## G(s) = -------------- -## (s + 2)(s - 1) -## -## +----+ -## -------------------->| W1 |---> v1 -## z | +----+ -## ----|-------------+ || T || => min. -## | | vz infty -## | +---+ v y +----+ -## u *--->| G |--->O--*-->| W2 |---> v2 -## | +---+ | +----+ -## | | -## | +---+ | -## -----| K |<------- -## +---+ -## @end group -## @end display -## W1 und W2 are the robustness and performance weighting -## functions -## -## @item MIMO plant -## The optimal controller minimizes the H_infinity norm of the -## augmented plant P (mixed-sensitivity problem): -## @display -## @group -## w -## 1 -----------+ -## | +----+ -## +---------------------->| W1 |----> z1 -## w | | +----+ -## 2 ------------------------+ -## | | | -## | v +----+ v +----+ -## +--*-->o-->| G |-->o--*-->| W2 |---> z2 -## | +----+ | +----+ -## | | -## ^ v -## u (from y (to K) -## controller -## K) -## -## -## + + + + -## | z | | w | -## | 1 | | 1 | -## | z | = [ P ] * | w | -## | 2 | | 2 | -## | y | | u | -## + + + + -## @end group -## @end display -## -## @item DISCRETE SYSTEM -## This is not a true discrete design. The design is carried out -## in continuous time while the effect of sampling is described by -## a bilinear transformation of the sampled system. -## This method works quite well if the sampling period is "small" -## compared to the plant time constants. -## -## @item The continuous plant -## @display -## @group -## 1 -## G (s) = -------------- -## k (s + 2)(s + 1) -## -## @end group -## @end display -## is discretised with a ZOH (Sampling period = Ts = 1 second): -## @display -## @group -## -## 0.199788z + 0.073498 -## G(s) = -------------------------- -## (z - 0.36788)(z - 0.13534) -## -## +----+ -## -------------------->| W1 |---> v1 -## z | +----+ -## ----|-------------+ || T || => min. -## | | vz infty -## | +---+ v +----+ -## *--->| G |--->O--*-->| W2 |---> v2 -## | +---+ | +----+ -## | | -## | +---+ | -## -----| K |<------- -## +---+ -## @end group -## @end display -## W1 and W2 are the robustness and performancs weighting -## functions -## @end table -## @end deftypefn - -## Author: Kai P. Mueller -## Created: April 30, 1998 - -yn = []; -while (length(yn) < 1) - yn = input(" * [s]iso, [m]imo, or [d]iscrete design? [no default]: ","S"); -endwhile -if ((yn(1) == "s") | (yn(1) == 'S')) - sys_type = 1; -elseif ((yn(1) == "m") | (yn(1) == 'M')) - sys_type = 2; -elseif ((yn(1) == "d") | (yn(1) == 'D')) - sys_type = 3; -else - disp(" *** no system type specified, hinfdemo terminated."); - return; -endif - -echo off -switch (sys_type) - - case (1) - ## siso - disp(" "); - disp(" ----------------------------------------------"); - disp(" H_infinity optimal control for the SISO plant:"); - disp(" "); - disp(" s - 2"); - disp(" G(s) = --------------"); - disp(" (s + 2)(s - 1)"); - disp(" "); - disp(" ----------------------------------------------"); - disp(" "); - - ## weighting on actuator u - W1 = wgt1o(0.05, 100.0, 425.0); - ## weighting on controlled variable y - W2 = wgt1o(10.0, 0.05, 0.001); - ## plant - G = tf2sys([1 -2],[1 1 -2]); - - ## need One as the pseudo transfer function One = 1 - One = ugain(1); - disp(" o forming P..."); - psys = buildssic([1 4;2 4;3 1],[3],[2 3 5],[3 4],G,W1,W2,One); - disp(" "); - disp(" o controller design..."); - [K, gfin, GW]=hinfsyn(psys, 1, 1, 0.1, 10.0, 0.02); - disp(" "); - disp("-- OK ----------------------------------------------"); - - disp(" Closed loop poles:"); - damp(GW); - ## disp(" o Testing H_infinity norm: (hinfnorm does not work)"); - ## hinfnorm(GW); - - disp(" "); - yn = input(" * Plot closed loop step response? [n]: ","S"); - if (length(yn) >= 1) - if ((yn(1) == "y") || (yn(1) == 'Y')) - disp(" o step responses of T and KS..."); - GW = buildssic([1 2; 2 1], [], [1 2], [-2], G, K); - figure(1); - step(GW, 1, 10); - endif - endif - - case (2) - ## mimo - disp(" "); - disp(" -----------------------------------------------"); - disp(" H_inf optimal control for the jet707 plant"); - disp(" -----------------------------------------------"); - disp(" "); - - ## Weighting function on u (robustness weight) - ww1 = wgt1o(0.01,5,0.9); - ww2 = wgt1o(0.01,5,2.2); - W1 = buildssic([1 0;2 0],[],[1 2],[1 2],ww1,ww2); - ## Weighting function on y (performance weight) - ww1 = wgt1o(250,0.1,0.0001); - ww2 = wgt1o(250,0.1,0.0002); - W2 = buildssic([1 0;2 0],[],[1 2],[1 2],ww1,ww2); - ## plant (2 x 2 system) - G = jet707; - - disp(" o forming P..."); - One = ugain(2); - Clst = [1 7; 2 8; 3 7; 4 8; 5 1; 6 2]; - P = buildssic(Clst,[5 6],[3:6 9 10],[1 2 5:8],G,W1,W2,One); - - disp(" "); - disp(" o controller design..."); - K = hinfsyn(P, 2, 2, 0.25, 10.0, 0.005); - - disp(" "); - yn = input(" * Plot closed loop step responses? [n]: ","S"); - if (length(yn) >= 1) - if ((yn(1) == "y") || (yn(1) == 'Y')) - disp(" o step responses of T and KS..."); - GW = buildssic([1 3;2 4;3 1;4 2],[],[1 2 3 4],[-3 -4],G,K); - - disp(" "); - disp(" FIGURE 1: speed refence => 1, pitch angle ref. => 0"); - disp(" ==================================================="); - disp(" y1: speed (should be 1)"); - disp(" y2: pitch angle (should remain 0)"); - disp(" y3: thrust (should be a slow transient)"); - disp(" y6: elevator (should be a faster transient)"); - disp(" "); - disp(" FIGURE 2: speed refence => 0, pitch angle ref. => 1"); - disp(" ==================================================="); - disp(" y1: speed (should remain 0)"); - disp(" y2: pitch angle (should be 1)"); - disp(" y3: thrust (should be a slow transient)"); - disp(" y6: elevator (should be a faster transient)"); - disp(" "); - figure(1) - step(GW); - figure(2) - step(GW,2); - endif - endif - - case (3) - ## discrete - disp(" "); - disp(" --------------------------------------------------"); - disp(" Discrete H_infinity optimal control for the plant:"); - disp(" "); - disp(" 0.199788z + 0.073498"); - disp(" G(s) = --------------------------"); - disp(" (z - 0.36788)(z - 0.13533)"); - disp(" --------------------------------------------------"); - disp(" "); - - ## sampling time - Ts = 1.0; - ## weighting on actuator value u - W1 = wgt1o(0.1, 200.0, 50.0); - ## weighting on controlled variable y - W2 = wgt1o(350.0, 0.05, 0.0002); - ## omega axis - ww = logspace(-4.99, 3.99, 100); - if (columns(ww) > 1); ww = ww'; endif - - ## continuous plant - G = tf2sys(2,[1 3 2]); - ## discrete plant with zoh - Gd = c2d(G, Ts); - ## w-plane (continuous representation of the sampled system) - Gw = d2c(Gd, "bi"); - - disp(" "); - disp(" o building P..."); - ## need One as the pseudo transfer function One = 1 - One = ugain(1); - psys = buildssic([1 4;2 4;3 1],[3],[2 3 5],[3 4],Gw,W1,W2,One); - disp(" o controller design..."); - [K, gfin, GWC] = hinfsyn(psys, 1, 1, 0.1, 10.0, 0.02); - - disp(" "); - fig_n = 1; - yn = input(" * Plot magnitudes of W1KS and W2S? [n]: ","S"); - if (length(yn) >= 1) - if ((yn(1) == "y") || (yn(1) == 'Y')) - disp(" o magnitudes of W1KS and W2S..."); - gwx = sysprune(GWC, 1, 1); - mag1 = bode(gwx, ww); - if (columns(mag1) > 1); mag1 = mag1'; endif - gwx = sysprune(GWC, 2, 1); - mag2 = bode(gwx, ww); - if (columns(mag2) > 1); mag2 = mag2'; endif - figure(fig_n) - fig_n = fig_n + 1; - gset grid - loglog(ww, [mag1 mag2]); - endif - endif - - Kd = c2d(K, "bi", Ts); - GG = buildssic([1 2; 2 1], [], [1 2], [-2], Gd, Kd); - disp(" o closed loop poles..."); - damp(GG); - - disp(" "); - yn = input(" * Plot closed loop step responses? [n]: ","S"); - if (length(yn) >= 1) - if ((yn(1) == "y") || (yn(1) == 'Y')) - disp(" o step responses of T and KS..."); - figure(fig_n) - step(GG, 1, 10); - endif - endif - -endswitch - -disp(" o hinfdemo terminated successfully."); - -## KPM-hinfdemo/End diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/hinfnorm.m --- a/scripts/control/hinfnorm.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,160 +0,0 @@ -## Copyright (C) 1996, 1998 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## -*- texinfo -*- -## @deftypefn {Function File} {[@var{g}, @var{gmin}, @var{gmax}] =} hinfnorm(@var{sys}@{, @var{tol}, @var{gmin}, @var{gmax}, @var{ptol}@}) -## Computes the H infinity norm of a system data structure. -## -## @strong{Inputs} -## @table @var -## @item sys -## system data structure -## @item tol -## H infinity norm search tolerance (default: 0.001) -## @item gmin -## minimum value for norm search (default: 1e-9) -## @item gmax -## maximum value for norm search (default: 1e+9) -## @item ptol -## pole tolerance: -## @itemize @bullet -## @item if sys is continuous, poles with -## |real(pole)| < ptol*||H|| (H is appropriate Hamiltonian) -## are considered to be on the imaginary axis. -## -## @item if sys is discrete, poles with -## |abs(pole)-1| < ptol*||[s1,s2]|| (appropriate symplectic pencil) -## are considered to be on the unit circle -## -## @item Default: 1e-9 -## @end itemize -## @end table -## -## @strong{Outputs} -## @table @var -## @item g -## Computed gain, within @var{tol} of actual gain. @var{g} is returned as Inf -## if the system is unstable. -## @item gmin -## @itemx gmax -## Actual system gain lies in the interval [@var{gmin}, @var{gmax}] -## @end table -## -## References: -## Doyle, Glover, Khargonekar, Francis, "State space solutions to standard -## H2 and Hinf control problems", IEEE TAC August 1989 -## Iglesias and Glover, "State-Space approach to discrete-time Hinf control," -## Int. J. Control, vol 54, #5, 1991 -## Zhou, Doyle, Glover, "Robust and Optimal Control," Prentice-Hall, 1996 -## @end deftypefn - -function [g, gmin, gmax] = hinfnorm (sys, tol, gmin, gmax, ptol) - - if((nargin == 0) || (nargin > 4)) - usage("[g gmin gmax] = hinfnorm(sys[,tol,gmin,gmax,ptol])"); - elseif(!is_struct(sys)) - error("Sys must be a system data structure"); - endif - - ## set defaults where applicable - if(nargin < 5) - ptol = 1e-9; # pole tolerance - endif - if(nargin < 4) - gmax = 1e9; # max gain value - endif - - dflg = is_digital(sys); - sys = sysupdate(sys,"ss"); - [A,B,C,D] = sys2ss(sys); - [n,nz,m,p] = sysdimensions(sys); - - ## eigenvalues of A must all be stable - if(!is_stable(sys)) - warning(["hinfnorm: unstable system (is_stable, ptol=",num2str(ptol), ... - "), returning Inf"]); - g = Inf; - endif - - Dnrm = norm(D); - if(nargin < 3) - gmin = max(1e-9,Dnrm); # min gain value - elseif(gmin < Dnrm) - warning(["hinfnorm: setting Gmin=||D||=",num2str(Dnrm)]); - endif - - if(nargin < 2) - tol = 0.001; # convergence measure for gmin, gmax - endif - - ## check for scalar input arguments 2...5 - if( ! (is_scalar(tol) && is_scalar(gmin) - && is_scalar(gmax) && is_scalar(ptol)) ) - error("hinfnorm: tol, gmin, gmax, ptol must be scalars"); - endif - - In = eye(n+nz); - Im = eye(m); - Ip = eye(p); - ## find the Hinf norm via binary search - while((gmax/gmin - 1) > tol) - g = (gmax+gmin)/2; - - if(dflg) - ## multiply g's through in formulas to avoid extreme magnitudes... - Rg = g^2*Im - D'*D; - Ak = A + (B/Rg)*D'*C; - Ck = g^2*C'*((g^2*Ip-D*D')\C); - - ## set up symplectic generalized eigenvalue problem per Iglesias & Glover - s1 = [Ak , zeros(nz) ; -Ck, In ]; - s2 = [In, -(B/Rg)*B' ; zeros(nz) , Ak' ]; - - ## guard against roundoff again: zero out extremely small values - ## prior to balancing - s1 = s1 .* (abs(s1) > ptol*norm(s1,"inf")); - s2 = s2 .* (abs(s2) > ptol*norm(s2,"inf")); - [cc,dd,s1,s2] = balance(s1,s2); - [qza,qzb,zz,pls] = qz(s1,s2,"S"); # ordered qz decomposition - eigerr = abs(abs(pls)-1); - normH = norm([s1,s2]); - Hb = [s1, s2]; - - ## check R - B' X B condition (Iglesias and Glover's paper) - X = zz((nz+1):(2*nz),1:nz)/zz(1:nz,1:nz); - dcondfailed = min(real( eig(Rg - B'*X*B)) < ptol); - else - Rinv = inv(g*g*Im - (D' * D)); - H = [A + B*Rinv*D'*C, B*Rinv*B'; ... - -C'*(Ip + D*Rinv*D')*C, -(A + B*Rinv*D'*C)']; - ## guard against roundoff: zero out extremely small values prior - ## to balancing - H = H .* (abs(H) > ptol*norm(H,"inf")); - [DD,Hb] = balance(H); - pls = eig(Hb); - eigerr = abs(real(pls)); - normH = norm(H); - dcondfailed = 0; # digital condition; doesn't apply here - endif - if( (min(eigerr) <= ptol * normH) | dcondfailed) - gmin = g; - else - gmax = g; - endif - endwhile -endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/hinfsyn.m --- a/scripts/control/hinfsyn.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,314 +0,0 @@ -## Copyright (C) 1996, 1998 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## -*- 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 ss2sys, sys2ss) -## @itemize @bullet -## @item controller is implemented for continuous time systems -## @item controller is NOT implemented for discrete time systems (see -## bilinear transforms in @code{c2d}, @code{d2c}) -## @end itemize -## @item nu -## number of controlled inputs -## @item ny -## number of measured outputs -## @item gmin -## initial lower bound on H-infinity optimal gain -## @item gmax -## initial upper bound on H-infinity optimal gain -## @item gtol -## gain threshhold. Routine quits when gmax/gmin < 1+tol -## @item ptol -## poles with abs(real(pole)) < ptol*||H|| (H is appropriate -## Hamiltonian) are considered to be on the imaginary axis. -## Default: 1e-9 -## @item tol -## threshhold for 0. Default: 200*eps -## -## @var{gmax}, @var{min}, @var{tol}, and @var{tol} must all be postive scalars. -## @end table -## @strong{Outputs} -## @table @var -## @item K -## system controller -## @item g -## designed gain value -## @item GW -## closed loop system -## @item Xinf -## ARE solution matrix for regulator subproblem -## @item Yinf -## ARE solution matrix for filter subproblem -## @end table -## -## @enumerate -## @item Doyle, Glover, Khargonekar, Francis, "State Space Solutions -## to Standard H2 and Hinf Control Problems," IEEE TAC August 1989 -## -## @item Maciejowksi, J.M., "Multivariable feedback design," -## Addison-Wesley, 1989, ISBN 0-201-18243-2 -## -## @item Keith Glover and John C. Doyle, "State-space formulae for all -## stabilizing controllers that satisfy and h-infinity-norm bound -## and relations to risk sensitivity," -## Systems & Control Letters 11, Oct. 1988, pp 167-172. -## @end enumerate -## @end deftypefn - -## Author: A. S. Hodel -## 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) ) - usage("[K,g,GW,Xinf,Yinf] = hinfsyn(Asys,nu,ny,gmin,gmax,gtol,ptol,tol)"); - 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=",num2str(gmax),", gmin=",num2str(gmin), ... - "gtol=",num2str(gtol), " must be positive scalars."]) - endif - - [chkdgkf,dgs] = is_dgkf(Asys,nu,ny,tol); - - if (! chkdgkf ) - disp("hinfsyn: system does not meet required assumptions") - help is_dgkf - error("hinfsyn: exit"); - endif - - ## extract dgs information - nw = dgs.nw; nu = dgs.nu; - A = dgs.A; B1 = dgs.Bw; B2 = dgs.Bu; - C1 = dgs.Cz; D11 = dgs.Dzw; D12 = dgs.Dzu; nz = dgs.nz; - C2 = dgs.Cy; D21 = dgs.Dyw; D22 = dgs.Dyu; ny = dgs.ny; - 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) - disp(" *** D matrices indicate a greater value of gamma min."); - fprintf(" gamma min (%f) superseeded by %f.", gmin, glo); - glo = xx1; - else - glo = gmin; - endif - if (glo > ghi) - fprintf(" *** lower bound of gamma greater than upper bound(%f)", ... - glo, ghi); - disp(" *** unable to continue, Goodbye."); - return; - 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 = list(" o o o o o ", ... - " # - - - - ", ... - " o # - - - ", ... - " o o # - - ", ... - " o o o # - ", ... - " o o o o # ", ... - " - - - - - "); - errdesx = list("", ... - "X im eig.", ... - "Hx not Ham.", ... - "X inf.eig", ... - "X not symm.", ... - "X not pos", ... - "R singular"); - - errdesy = list(" ", ... - "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",nth(errmesg,x_ha_err+1)); - xerr = nth(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",nth(errmesg,y_ha_err+1)); - yerr = nth(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 = ss2sys(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 diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/hinfsyn_chk.m --- a/scripts/control/hinfsyn_chk.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,102 +0,0 @@ -## Copyright (C) 1996 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## -*- texinfo -*- -## @deftypefn {Function File} {[@var{retval}, @var{Pc}, @var{Pf}] =} hinfsyn_chk(@var{A}, @var{B1}, @var{B2}, @var{C1}, @var{C2}, @var{D12}, @var{D21}, @var{g}, @var{ptol}) -## Called by @code{hinfsyn} to see if gain @var{g} satisfies conditions in -## Theorem 3 of -## Doyle, Glover, Khargonekar, Francis, "State Space Solutions to Standard -## H2 and Hinf Control Problems", IEEE TAC August 1989 -## -## @strong{Warning} Do not attempt to use this at home; no argument -## checking performed. -## -## @strong{Inputs} as returned by @code{is_dgkf}, except for: -## @table @var -## @item g -## candidate gain level -## @item ptol -## as in @code{hinfsyn} -## @end table -## -## @strong{Outputs} -## @table @var -## @item retval -## 1 if g exceeds optimal Hinf closed loop gain, else 0 -## @item Pc -## solution of "regulator" H-inf ARE -## @item Pf -## solution of "filter" H-inf ARE -## @end table -## Do not attempt to use this at home; no argument checking performed. -## @end deftypefn - -## Author: A. S. Hodel -## Created: August 1995 - -function [retval, Pc, Pf] = hinfsyn_chk (A, B1, B2, C1, C2, D12, D21, g, ptol) - - Pc = Pf = []; - - ## Construct the two Hamiltonians - g2 = 1/(g*g); - Hc = [ A , g2*B1*B1' - B2*B2'; -C1'*C1 , -A']; - Hf = [ A' , g2*C1'*C1 - C2'*C2; -B1*B1' , -A]; - - ## check if Hc, Hf are in dom(Ric) - Hcminval = min(abs(real(eig(Hc)))); - Hfminval = min(abs(real(eig(Hf)))); - if(Hcminval < ptol); - disp("hinfsyn_chk: Hc is not in dom(Ric)"); - retval = 0; - return - endif - if(Hfminval < ptol) - disp("hinfsyn_chk: Hf is not in dom(Ric)"); - retval = 0; - return - endif - - ## Solve ARE's - Pc = are(A, B2*B2'-g2*B1*B1',C1'*C1); - Pf = are(A',C2'*C2-g2*C1'*C1,B1*B1'); - - Pceig = eig(Pc); - Pfeig = eig(Pf); - Pcfeig = eig(Pc*Pf); - - if(min(Pceig) < -ptol) - disp("hinfsyn_chk: Pc is not >= 0"); - retval = 0; - return - endif - if(min(Pfeig) < -ptol) - disp("hinfsyn_chk: Pf is not >= 0"); - retval = 0; - return - endif - if(max(abs(Pcfeig)) >= g*g) - disp("hinfsyn_chk: rho(Pf*Pc) is not < g^2"); - retval = 0; - return - endif - - ## all conditions met. - retval = 1; - -endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/hinfsyn_ric.m --- a/scripts/control/hinfsyn_ric.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,80 +0,0 @@ -## Copyright (C) 1996, 1998 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## -*- texinfo -*- -## @deftypefn {Function File} {[@var{Xinf},@var{x_ha_err}] =} hinfsyn_ric(@var{A},@var{BB}.@var{C1},@var{d1dot},@var{R},@var{ptol}) -## @table -## @item forms -## xx = ([BB; -C1'*d1dot]/R) * [d1dot'*C1 BB']; -## Ha = [A 0*A; -C1'*C1 -A'] - xx; -## @end table -## and solves associated Riccati equation -## returns error code -## @table -## @item x_ha_err -## 0: successful -## 1: Xinf has imaginary eigenvalues -## 2: Hx not Hamiltonian -## 3: Xinf has inf. eigenvalues (numerical overflow) -## 4: Xinf not symmetric -## 5: Xinf not positive definite -## 6: R is singular -## @end table -## @end deftypefn - -function [Xinf, x_ha_err] = hinfsyn_ric (A, BB, C1, d1dot, R, ptol) - - x_ha_err = 0; # assume success - Xinf = []; # default return value - n = is_square(A); - nw = is_square(R); - if(rank(R) != nw) x_ha_err = 6; - else # build hamiltonian Ha for X_inf - xx = ([BB; -C1'*d1dot]/R) * [d1dot'*C1, BB']; - Ha = [A, 0*A; -C1'*C1, -A'] - xx; - x_ha_err = 0; - [d, Ha] = balance(Ha); - [u, s] = schur(Ha, "A"); - rev = real(eig(s)); - - if (any(abs(rev) <= ptol)) # eigenvalues near the imaginary axis - x_ha_err = 1; - elseif (sum(rev > 0) != sum(rev < 0)) - ## unequal number of positive and negative eigenvalues - x_ha_err = 2; - else - ## compute positive Riccati equation solution - u = d * u; - Xinf = u(n+1:2*n,1:n) / u(1:n,1:n); - if (!all(all(finite(Xinf)))) - x_ha_err = 3; - elseif (norm(Xinf-Xinf') >= 10*ptol) - ## solution not symmetric - x_ha_err = 4; - else - ## positive semidefinite? - ## force symmetry (faster, avoids some convergence problems) - Xinf = (Xinf + Xinf')/2; - rev = eig(Xinf); - if (any(rev <= -ptol)) - x_ha_err = 5; - endif - endif - endif - endif -endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/mb.m --- a/scripts/control/mb.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,62 +0,0 @@ -## Copyright (C) 1996, 1998 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## I think that this m-file can be deleted -## a.s.hodel@eng.auburn.edu - 4 Dec. 1998 - -Ap = [0, 1;1960, 0]; -Bp = [0;-6261]; -Cp = [1, 0]; -Dp = 0; - -Gp = ss2sys(Ap,Bp,Cp,Dp,0,2,0,[],"delta_i","delta_y"); -Gp = syssetsignals(Gp,"st","delta_x1",1); -Gp = syssetsignals(Gp,"st","delta_x2",2); - -Ak = [-20, 1;-22160, -200]; -Bk = [-20;-2160]; -Ck = [-3.5074, -0.0319]; -Dk = 0; - -Gk = ss2sys(Ak,Bk,Ck,Dk,0,2,0,[],"y","i"); -Gk = syssetsignals(Gk,"st","x1",1); -Gk = syssetsignals(Gk,"st","x2",2); - -Gc = sysgroup(Gp,Gk); - -Gc = sysdup(Gc,[],[1, 2]); -## Gc = sysscale(Gc,[],diag([1,1,1,1])); - -Gc = sysconnect(Gc,[1, 2],[4, 3]); -Gc = sysprune(Gc,1,[1, 2]); - -disp("after pruning, closed loop system is") -sysout(Gc) - -## Gc = sysdup(Gc,[],2); -## Gc = sysconnect(Gc,1,3); -## Gc = sysprune(Gc,1,1); - -is_stable(Gc) -Gca = sys2ss(Gc); -eig(Gca) - -[Gpa,Gpb,Gpc,Gpd] = sys2ss(Gp); -[Gka,Gkb,Gkc,Gkd] = sys2ss(Gk); -Acl = [Gpa, -Gpb*Gkc; Gkb*Gpc, Gka] -eig(Acl) diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/obsolete/dezero.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/obsolete/dezero.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,59 @@ +## Copyright (C) 1996 Kurt Hornik +## +## 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place - Suite 330, Boston, MA +## 02111-1307, USA. + +## -*- texinfo -*- +## @deftypefn {Functin File} {@var{t} =} dezero (@var{s}) +## Remove trailing blank entries and all zero entries from the string s. +## @end deftypefn + +## Author: Kurt Hornik +## Adapted-By: jwe + +## Adapted from deblank by A. S. Hodel (a.s.hodel@eng.auburn.edu) +## (the name dezero is a reference to the Fermilab D0 experiment, +## where my sister did her PhD research) + +function t = dezero (s) + + ## delete the next line if you're stubbornly going to use dezero. + error("dezero is no longer supported."); + + if (nargin != 1) + usage ("dezero (s)"); + elseif (isstr (s)) + + [nr, nc] = size (s); + len = nr * nc; + + if (len == 0) + t = s; + else + + s = reshape (s, 1, len); + + ## need to remove zeros first, then call deblank + s = toascii (s); + t = deblank(setstr(s(find(s != 0) ))); + endif + + else + error ("dezero: expecting string argument"); + endif + +endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/packedform.m --- a/scripts/control/packedform.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,95 +0,0 @@ -## Copyright (C) 1996, 1998 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -save_var = page_screen_output; -page_screen_output = 1; -disp("Description of system data structure:") -disp("A linear system is stored in a structure, and may be represented in") -disp("ss (state space), tf (transfer function), and/or zp (zero-pole-gain)") -disp("form.") -disp(" ") -disp("variables in all representations:") -disp("inname: list of signal names (strings) containing name(s) of system ") -disp(" inputs; see is_signal_list"); -disp("n: number of continuous states") -disp("nz: number of discrete states") -disp("outname: list of signal names (strings) containing name(s) of system ") -disp(" outputs"); -disp(" ") -disp("variables in all representations:(cont'd)") -disp("sys: system status vector. This vector indicates both what") -disp(" representation was used to initialize the system data structure") -disp(" (called the primary system type) and which other representations") -disp(" are currently up-to-date with the primary system type.") -disp(" sys(0): primary system type") -disp(" =0 for tf form") -disp(" =1 for zp form") -disp(" =2 for ss form") -disp(" sys(1:3): indicate whether tf, zp, or ss, respectively, are") -disp(" \"up to date\" (whether it is safe to use the variables") -disp(" associated with these representations)") -disp(" sys(1): = 1 if tf variables are up to date") -disp(" = 0 else"); -disp(" sys(2): = 1 if zp variables are up to date") -disp(" = 0 else"); -disp(" sys(3): = 1 if ss variables are up to date") -disp(" = 0 else"); -disp("You can update alternative representations internally with the") -disp("sysupdate command:") -disp(" ") -help sysupdate -disp("===============================") -disp("More variables common to all representations in system data structures:"); -disp("tsam: discrete time sampling interval ") -disp(" =0 if system is purely continuous"); -disp(" >0 if system has discrete-time states or outputs"); -disp("yd: vector indicating which outputs are discrete time (i.e.,") -disp(" produced by D/A converters) and which are continuous time.") -disp(" yd(ii) = 0 if output ii is continuous, = 1 if discrete.") -disp(" ") -disp("===============================") -disp("variables in tf representations (SISO only):") -disp("num: vector of numerator coefficients") -disp("den: vector of denominator coefficients") -disp(" ") -disp("===============================") -disp("variables in zp representations (SISO only):") -disp("zer: vector of system zeros") -disp("pol: vector of system poles") -disp("k: system leading coefficient") -disp(" ") -disp("===============================") -disp("variables in ss representations:") -disp("a,b,c,d: usual state-space matrices. If a system has both") -disp(" continuous and discrete states, they are sorted so that") -disp(" continuous states come first, then discrete states") -disp(" ") -disp("WARNING: some functions (e.g., bode) will not accept systems") -disp("with both discrete and continuous states/outputs") -disp("stname: list of signal names (strings) containing name(s) of system ") -disp(" states"); -disp("===============================") -disp("Object oriented programming:") -disp("It is recommended that users do not directly access the internal") -disp("variables themselves, but use the interface functions") -disp(" fir2sys ss2sys tf2sys sys2fir") -disp(" sys2ss sys2tf sys2zp syschtsam") -disp(" sysdimensions sysgetsignals syssetsignals sysgettype") -disp(" zp2sys") -disp("to create/access internal variables. "); -page_screen_output = save_var; diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/parallel.m --- a/scripts/control/parallel.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,66 +0,0 @@ -## Copyright (C) 1996 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## function sysp = parallel(Asys,Bsys) -## Forms the parallel connection of two systems. -## -## ____________________ -## | ________ | -## u ----->|----> | Asys |--->|----> y1 -## | | -------- | -## | | ________ | -## |--->|----> | Bsys |--->|----> y2 -## | -------- | -## -------------------- -## Ksys - -## Author: David Clem -## Created: August 15, 1994 -## completely rewritten Oct 1996 a s hodel -## SYS_INTERNAL accesses members of system structure - -function sysp = parallel (Asys, Bsys) - - if(nargin != 2) - usage("sysp = parallel(Asys,Bsys)"); - endif - if(! is_struct(Asys) ) - error("1st input argument is not a system data structure") - elseif (! is_struct(Bsys) ) - error("2nd input argument is not a system data structure") - endif - [Ann,Anz,mA] = sysdimensions(Asys); - [Bnn,Bnz,mB] = sysdimensions(Bsys); - if(mA != mB) - error(["Asys has ",num2str(mA)," inputs, Bsys has ",num2str(mB)," inputs"]); - endif - - ## save signal names - Ain = sysgetsignals(Asys,"in"); - - ## change signal names to avoid warning messages from sysgroup - Asys = syssetsignals(Asys,"in",sysdefioname(length(Ain),"Ain_u")); - Bsys = syssetsignals(Bsys,"in",sysdefioname(length(Ain),"Bin_u")); - - sysp = sysgroup(Asys,Bsys); - sysD = ss2sys([],[],[],[eye(mA);eye(mA)]); - - sysp = sysmult(sysp,sysD); - sysp = syssetsignals(sysp,"in",Ain); - -endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/ss2sys.m --- a/scripts/control/ss2sys.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,287 +0,0 @@ -## Copyright (C) 1996, 1998 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## -*- texinfo -*- -## @deftypefn {Function File} {@var{sys} =} ss2sys (@var{a}, @var{b}, @var{c}@{,@var{d}, @var{tsam}, @var{n}, @var{nz}, @var{stname}, @var{inname}, @var{outname}, @var{outlist}@}) -## Create system structure from state-space data. May be continous, -## discrete, or mixed (sampeled-data) -## -## @strong{Inputs} -## @table @var -## @item a -## @itemx b -## @itemx c -## @itemx d -## usual state space matrices. -## -## default: @var{d} = zero matrix -## -## @item tsam -## sampling rate. Default: @math{tsam = 0} (continuous system) -## -## @item n -## @itemx nz -## number of continuous, discrete states in the system -## -## If @var{tsam} is 0, @math{n = @code{rows}(@var{a})}, @math{nz = 0}. -## -## If @var{tsam} is greater than zero, @math{n = 0}, -## @math{nz = @code{rows}(@var{a})} -## -## see below for system partitioning -## -## @item stname -## list of strings of state signal names -## -## default (@var{stname}=[] on input): @code{x_n} for continuous states, -## @code{xd_n} for discrete states -## -## @item inname -## list of strings of input signal names -## -## default (@var{inname} = [] on input): @code{u_n} -## -## @item outname -## list of strings of input signal names -## -## default (@var{outname} = [] on input): @code{y_n} -## -## @item outlist -## -## list of indices of outputs y that are sampled -## -## If @var{tsam} is 0, @math{outlist = []}. -## -## If @var{tsam} is greater than 0, @math{outlist = 1:@code{rows}(@var{c})}. -## @end table -## -## Unlike states, discrete/continous outputs may appear in any order. -## -## @strong{Note} @code{sys2ss} returns a vector @var{yd} where -## @var{yd}(@var{outlist}) = 1; all other entries of @var{yd} are 0. -## -## @strong{Outputs} -## @var{outsys} = system data structure -## -## @strong{System partitioning} -## -## Suppose for simplicity that outlist specified -## that the first several outputs were continuous and the remaining outputs -## were discrete. Then the system is partitioned as -## @example -## @group -## x = [ xc ] (n x 1) -## [ xd ] (nz x 1 discrete states) -## a = [ acc acd ] b = [ bc ] -## [ adc add ] [ bd ] -## c = [ ccc ccd ] d = [ dc ] -## [ cdc cdd ] [ dd ] -## -## (cdc = c(outlist,1:n), etc.) -## @end group -## @end example -## with dynamic equations: -## @ifinfo -## @math{ d/dt xc(t) = acc*xc(t) + acd*xd(k*tsam) + bc*u(t)} -## -## @math{ xd((k+1)*tsam) = adc*xc(k*tsam) + add*xd(k*tsam) + bd*u(k*tsam)} -## -## @math{ yc(t) = ccc*xc(t) + ccd*xd(k*tsam) + dc*u(t)} -## -## @math{ yd(k*tsam) = cdc*xc(k*tsam) + cdd*xd(k*tsam) + dd*u(k*tsam)} -## @end ifinfo -## @iftex -## @tex -## $$\eqalign{ -## {d \over dt} x_c(t) -## & = a_{cc} x_c(t) + a_{cd} x_d(k*t_{sam}) + bc*u(t) \cr -## x_d((k+1)*t_{sam}) -## & = a_{dc} x_c(k t_{sam}) + a_{dd} x_d(k t_{sam}) + b_d u(k t_{sam}) \cr -## y_c(t) -## & = c_{cc} x_c(t) + c_{cd} x_d(k t_{sam}) + d_c u(t) \cr -## y_d(k t_{sam}) -## & = c_{dc} x_c(k t_{sam}) + c_{dd} x_d(k t_{sam}) + d_d u(k t_{sam}) -## }$$ -## @end tex -## @end iftex -## -## @strong{Signal partitions} -## @example -## @group -## | continuous | discrete | -## ---------------------------------------------------- -## states | stname(1:n,:) | stname((n+1):(n+nz),:) | -## ---------------------------------------------------- -## outputs | outname(cout,:) | outname(outlist,:) | -## ---------------------------------------------------- -## @end group -## @end example -## where @math{cout} is the list of in 1:@code{rows}(@var{p}) -## that are not contained in outlist. (Discrete/continuous outputs -## may be entered in any order desired by the user.) -## -## @strong{Example} -## @example -## octave:1> a = [1 2 3; 4 5 6; 7 8 10]; -## octave:2> b = [0 0 ; 0 1 ; 1 0]; -## octave:3> c = eye(3); -## octave:4> sys = ss2sys(a,b,c,[],0,3,0,list("volts","amps","joules")); -## octave:5> sysout(sys); -## Input(s) -## 1: u_1 -## 2: u_2 -## -## Output(s): -## 1: y_1 -## 2: y_2 -## 3: y_3 -## -## state-space form: -## 3 continuous states, 0 discrete states -## State(s): -## 1: volts -## 2: amps -## 3: joules -## -## A matrix: 3 x 3 -## 1 2 3 -## 4 5 6 -## 7 8 10 -## B matrix: 3 x 2 -## 0 0 -## 0 1 -## 1 0 -## C matrix: 3 x 3 -## 1 0 0 -## 0 1 0 -## 0 0 1 -## D matrix: 3 x 3 -## 0 0 -## 0 0 -## 0 0 -## @end example -## Notice that the @var{D} matrix is constructed by default to the -## correct dimensions. Default input and output signals names were assigned -## since none were given. -## @end deftypefn - -## Author: John Ingram -## Created: July 20, 1996 - -function retsys = ss2sys (a, b, c, d, tsam, n, nz, stname, inname, outname, outlist) - - ## Test for correct number of inputs - if ((nargin < 3) | (nargin > 11)) - usage("retsys = ss2sys (a,b,c{,d,tsam,n,nz,stname,inname,outname,outlist})"); - endif - - ## verify A, B, C, D arguments - ## If D is not specified, set it to a zero matrix of appriate dimension. - if (nargin == 3) d = zeros(rows(c) , columns(b)); - elseif (isempty(d)) d = zeros(rows(c) , columns(b)); endif - - ## Check the dimensions - [na,m,p] = abcddim(a,b,c,d); - - ## If dimensions are wrong, exit function - if (m == -1) - error("a(%dx%d), b(%dx%d), c(%dx%d), d(%dx%d); incompatible", ... - rows(a), columns(a), rows(b), columns(b), rows(c), columns(c), ... - rows(d), columns(d)); - endif - - ## check for tsam input - if(nargin < 5) tsam = 0; - elseif( !( is_sample(tsam) | (tsam == 0) ) ) - error("tsam must be a nonnegative real scalar"); - endif - - ## check for continuous states - if( (nargin < 6) & (tsam == 0) ) n = na; - elseif(nargin < 6) n = 0; - elseif((!is_matrix(n)) | isstr(n)) - error("Parameter n is not a numerical value."); - elseif( (!is_scalar(n)) | (n < 0 ) | (n != round(n)) ) - if(is_scalar(n)) error("invalid value of n=%d,%e",n,n); - else error("invalid value of n=(%dx%d)", ... - rows(n), columns(n)); endif - endif - - ## check for num discrete states - if( (nargin < 7) & (tsam == 0)) nz = 0; - elseif(nargin < 7) nz = na - n; - elseif((!is_matrix(nz)) | isstr(nz)) - error("Parameter nz is not a numerical value."); - elseif( (!is_scalar(nz)) | (nz < 0 ) | (nz != round(nz)) ) - if(is_scalar(nz)) - error(["invalid value of nz=",num2str(nz)]); - else - error(["invalid value of nz=(",num2str(rows(nz)),"x", ... - num2str(columns(nz)),")"]); - endif - endif - - ## check for total number of states - if( (n + nz) != na ) - error(["invalid: a is ",num2str(na),"x",num2str(na),", n=", ... - num2str(n),", nz=",num2str(nz)]); - endif - - ## construct system with default names - retsys.a = a; - retsys.b = b; - retsys.c = c; - retsys.d = d; - - retsys.n = n; - retsys.nz = nz; - retsys.tsam = tsam; - retsys.yd = zeros(1,p); # default value entered below - - ## Set the system vector: active = 2(ss), updated = [0 0 1]; - retsys.sys = [2, 0, 0, 1]; - - retsys.stname = sysdefstname(n,nz); - retsys.inname = sysdefioname(m,"u"); - retsys.outname = sysdefioname(p,"y"); - - ## check for state names - if(nargin >= 8) - if(!isempty(stname)) retsys = syssetsignals(retsys,"st",stname); endif - endif - - ## check for input names - if(nargin >= 9) - if(!isempty(inname)) retsys = syssetsignals(retsys,"in",inname); endif - endif - - ## check for output names - if(nargin >= 10) - if(!isempty(outname)) retsys = syssetsignals(retsys,"out",outname); endif - endif - - ## set up yd - if(nargin < 11) - retsys = syssetsignals(retsys,"yd",ones(1,p)*(tsam > 0)); - else - if(!isempty(outlist)) - retsys = syssetsignals(retsys,"yd",ones(size(outlist)),outlist); - endif - endif - -endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/ss2tf.m --- a/scripts/control/ss2tf.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,80 +0,0 @@ -## Copyright (C) 1996 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## -*- texinfo -*- -## @deftypefn {Function File} {@var{outputs} =} ss2tf (@var{inputs}) -## @format -## [num,den] = ss2tf(a,b,c,d) -## Conversion from tranfer function to state-space. -## The state space system -## . -## x = Ax + Bu -## y = Cx + Du -## -## is converted to a transfer function -## -## num(s) -## G(s)=------- -## den(s) -## -## used internally in system data structure format manipulations -## @end format -## @end deftypefn - -## Author: R. Bruce Tenison -## Created: June 24, 1994 -## a s hodel: modified to allow for pure gain blocks Aug 1996 - -function [num, den] = ss2tf (a, b, c, d) - - ## Check args - [n,m,p] = abcddim(a,b,c,d); - if (n == -1) - num = []; - den = []; - error("ss2tf: Non compatible matrix arguments"); - elseif ( (m != 1) | (p != 1)) - num = []; - den = []; - error(["ss2tf: not SISO system: m=",num2str(m)," p=",num2str(p)]); - endif - - if(n == 0) - ## gain block only - num = d; - den = 1; - else - ## First, get the denominator coefficients - den = poly(a); - - ## Get the zeros of the system - [zz,g] = tzero(a,b,c,d); - - ## Form the Numerator (and include the gain) - if (!isempty(zz)) - num = g * poly(zz); - else - num = g; - endif - - ## the coefficients must be real - den = real(den); - num = real(num); - endif -endfunction - diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/ss2zp.m --- a/scripts/control/ss2zp.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,59 +0,0 @@ -## Copyright (C) 1996 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## -*- texinfo -*- -## @deftypefn {Function File} {@var{outputs} =} ss2zp (@var{inputs}) -## @format -## Converts a state space representation to a set of poles and zeros. -## -## [pol,zer,k] = ss2zp(a,b,c,d) returns the poles and zeros of the state space -## system (a,b,c,d). K is a gain associated with the zeros. -## -## used internally in system data structure format manipulations -## @end format -## @end deftypefn - -## Author: David Clem -## Created: August 15, 1994 -## Hodel: changed order of output arguments to zer, pol, k. July 1996 -## a s hodel: added argument checking, allow for pure gain blocks aug 1996 - -function [zer, pol, k] = ss2zp (a, b, c, d) - - if(nargin != 4) - usage("[zer,pol,k] = ss2zp(a,b,c,d)"); - endif - - [n,m,p] = abcddim(a,b,c,d); - if (n == -1) - error("ss2tf: Non compatible matrix arguments"); - elseif ( (m != 1) | (p != 1)) - error(["ss2tf: not SISO system: m=",num2str(m)," p=",num2str(p)]); - endif - - if(n == 0) - ## gain block only - k = d; - zer = pol = []; - else - ## First, get the denominator coefficients - [zer,k] = tzero(a,b,c,d); - pol = eig(a); - endif -endfunction - diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/sys2fir.m --- a/scripts/control/sys2fir.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,52 +0,0 @@ -## Copyright (C) 1996 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## -*- texinfo -*- -## @deftypefn {Function File} {[@var{c}, @var{tsam}, @var{input}, @var{output}] =} sys2fir (@var{sys}) -## -## Extract FIR data from system data structure; see @ref{fir2sys} for -## parameter descriptions. -## @end deftypefn -## @seealso{fir2sys} - -## Author: A. S. Hodel -## Created: July 1996 - -function [c, tsam, inname, outname] = sys2fir (sys) - - ## let sys2tf do most of the work - - [num,den,tsam,inname,outname] = sys2tf(sys); - - alph = den(1); # scale to get monic denominator - den = den/alph; - num = num/alph; - l = length(den); - m = length(num); - if( norm(den(2:l)) ) - sysout(sys,"tf"); - error("denominator has poles away from origin"); - elseif( !is_digital(sys) ) - error("system must be discrete-time to be FIR"); - elseif(m != l) - warning(["sys2fir: deg(num) - deg(den) = ",num2str(m-l), ... - "; coefficients must be shifted"]); - endif - c = num; -endfunction - diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/sys2ss.m --- a/scripts/control/sys2ss.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,107 +0,0 @@ -## Copyright (C) 1996, 1998 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## -*- texinfo -*- -## @deftypefn {Function File} {[@var{a}, @var{b}, @var{c}, @var{d}, @var{tsam},@var{n}, @var{nz}, @var{stname}, @var{inname}, @var{outname}, @var{yd}] =} sys2ss (@var{sys}) -## Extract state space representation from system data structure. -## -## @strong{Inputs} -## @var{sys} system data structure (@pxref{sysstruct}) -## -## @strong{Outputs} -## @table @var -## @item a -## @itemx b -## @itemx c -## @itemx d -## state space matrices for sys -## -## @item tsam -## sampling time of sys (0 if continuous) -## -## @item n -## @itemx nz -## number of continuous, discrete states (discrete states come -## last in state vector @var{x}) -## -## @item stname -## @itemx inname -## @itemx outname -## signal names (lists of strings); names of states, -## inputs, and outputs, respectively -## -## @item yd -## binary vector; @var{yd}(@var{ii}) is 1 if output @var{y}(@var{ii})$ -## is discrete (sampled); otherwise @var{yd}(@var{ii}) 0. -## -## @end table -## A warning massage is printed if the system is a mixed -## continuous and discrete system -## -## @strong{Example} -## @example -## octave:1> sys=tf2sys([1 2],[3 4 5]); -## octave:2> [a,b,c,d] = sys2ss(sys) -## a = -## 0.00000 1.00000 -## -1.66667 -1.33333 -## b = -## 0 -## 1 -## c = 0.66667 0.33333 -## d = 0 -## @end example -## @end deftypefn - -## Author: David Clem -## Created: August 19, 1994 -## Updates by John Ingram July 14, 1996 - -function [a, b, c, d, tsam, n, nz, stname, inname, outname, yd] = sys2ss (sys) - - if(nargin != 1) - usage("[a,b,c,d,tsam,n,nz,stname,inname,outname,yd] = sys2ss(sys)") - endif - - if (nargout > 11) - warning(["sys2ss: ",num2str(nargout)," out arguments exceeds max=11"]) - usage("[a,b,c,d,tsam,n,nz,stname,inname,outname,yd] = sys2ss(sys)") - endif - - if( ! is_struct(sys) ) - error("input argument must be a system data structure"); - endif - - sys = sysupdate(sys,"ss"); # make sure state space data is there - [n,nz,m,p] = sysdimensions(sys); - [stname,inname,outname,yd] = sysgetsignals(sys); - tsam = sysgettsam(sys); - - cont = sum(yd == 0) + n; - dig = sum(yd != 0) + nz + tsam; - if(cont*dig) - warning("sys2ss: input system is mixed continuous/discrete"); - endif - - a = sys.a; - b = sys.b; - c = sys.c; - d = sys.d; - -endfunction - diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/sys2tf.m --- a/scripts/control/sys2tf.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -## Copyright (C) 1996 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## -*- texinfo -*- -## @deftypefn {Function File} {[@var{num}, @var{den}, @var{tsam}, @var{inname}, @var{outname}] =} sys2tf (@var{sys}) -## Extract transfer function data from a system data structure -## -## See @ref{tf2sys} for parameter descriptions. -## -## @strong{Example} -## @example -## octave:1> sys=ss2sys([1 -2; -1.1,-2.1],[0;1],[1 1]); -## octave:2> [num,den] = sys2tf(sys) -## num = 1.0000 -3.0000 -## den = 1.0000 1.1000 -4.3000 -## @end example -## @end deftypefn - -## Author: R. Bruce Tenison -## Created: June 24, 1994 -## modified to make sys2tf by A. S. Hodel Aug 1995 -## modified again for updated system format by John Ingram July 1996 - -function [num, den, tsam, inname, outname] = sys2tf (Asys) - - if(nargin != 1) - usage("[num,den,tsam,inname,outname] = sys2tf(Asys)"); - endif - - if( !is_struct(Asys)) - error("Asys must be a system data structure (see ss2sys, tf2sys, zp2sys)"); - elseif (! is_siso(Asys) ) - [n, nz, m, p] = sysdimensions(Asys); - error(["system is not SISO (",num2str(m)," inputs, ... - ", num2str(p)," outputs"]); - endif - - Asys = sysupdate(Asys,"tf"); # just in case - - num = Asys.num; - den = Asys.den; - - tsam = sysgettsam(Asys); - inname = sysgetsignals(Asys,"in"); - outname = sysgetsignals(Asys,"out"); - -endfunction - diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/sys2zp.m --- a/scripts/control/sys2zp.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -## Copyright (C) 1996 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## -*- texinfo -*- -##@deftypefn {Function File} {[@var{zer}, @var{pol}, @var{k}, @var{tsam}, @var{inname}, @var{outname}] =} sys2zp (@var{sys}) -## Extract zero/pole/leading coefficient information from a system data -## structure -## -## See @ref{zp2sys} for parameter descriptions. -## -## @strong{Example} -## @example -## octave:1> sys=ss2sys([1 -2; -1.1,-2.1],[0;1],[1 1]); -## octave:2> [zer,pol,k] = sys2zp(sys) -## zer = 3.0000 -## pol = -## -2.6953 -## 1.5953 -## k = 1 -## @end example -## @end deftypefn - -## Author: John Ingram -## Created: July 15, 1996 - -function [zer, pol, k, tsam, inname, outname] = sys2zp (sys) - - if(nargin != 1) - usage("[zer,pol,k,tsam,inname,outname] = sys2zp(sys)"); - elseif( !is_struct(sys)) - error("sysconnect: sys must be in system data structure form") - elseif (! is_siso(sys) ) - [n, nz, m, p] = sysdimensions(sys); - error(["system is not SISO (",num2str(m)," inputs, ... - ", num2str(p)," outputs"]); - endif - - ## update zero-pole form - sys = sysupdate(sys,"zp"); - - zer = sys.zer; - pol = sys.pol; - k = sys.k; - tsam = sysgettsam(sys); - inname = sysgetsignals(sys,"in"); - outname = sysgetsignals(sys,"out"); - -endfunction - - diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/sysadd.m --- a/scripts/control/sysadd.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,118 +0,0 @@ -## Copyright (C) 1996, 1999 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## -*- texinfo -*- -## @deftypefn {Function File} {@var{sys} =} sysadd (@var{Gsys}, @var{Hsys}) -## returns @var{sys} = @var{Gsys} + @var{Hsys}. -## @itemize @bullet -## @item Exits with -## an error if @var{Gsys} and @var{Hsys} are not compatibly dimensioned. -## @item Prints a warning message is system states have identical names; -## duplicate names are given a suffix to make them unique. -## @item @var{sys} input/output names are taken from @var{Gsys}. -## @end itemize -## @example -## @group -## ________ -## ----| Gsys |--- -## u | ---------- +| -## ----- (_)----> y -## | ________ +| -## ----| Hsys |--- -## -------- -## @end group -## @end example -## @end deftypefn - -## Author: John Ingram -## Created: July 1996 -## Updated for variable number of arguments July 1999 A. S. Hodel - -function sys = sysadd (...) - - if(nargin < 1) - usage("sysadd: sys = sysysadd(Gsys{,Hsys, ...})"); - endif - - ## collect all arguments - arglist = list(); - va_start(); - for kk=1:nargin - arglist(kk) = va_arg(); - if(!is_struct(nth(arglist,kk))) - error("sysadd: argument %d is not a data structure",kk); - endif - endfor - - ## check system dimensions - [n,nz,mg,pg,Gyd] = sysdimensions(nth(arglist,1)); - for kk=2:nargin - [n,nz,mh,ph,Hyd] = sysdimensions(nth(arglist,kk)); - if(mg != mh) - error("arg 1 has %d inputs; arg %d has vs %d inputs",mg,kk,mh); - elseif(pg != ph) - error("arg 1 has %d outputs; arg %d has vs %d outputs",pg,kk,ph); - elseif(norm(Gyd - Hyd)) - warning("cannot add a discrete output to a continuous output"); - error("Output type mismatch: arguments 1 and %d\n",kk); - endif - endfor - - ## perform the add - if(nargin == 2) - Gsys = nth(arglist,1); Hsys = nth(arglist,2); - if( strcmp(sysgettype(Gsys),"tf") | strcmp(sysgettype(Hsys),"tf") ) - ## see if adding transfer functions with identical denominators - [Gnum,Gden,GT,Gin,Gout] = sys2tf(Gsys); - [Hnum,Hden,HT,Hin,Hout] = sys2tf(Hsys); - if(length(Hden) == length(Gden) ) - if( (Hden == Gden) & (HT == GT) ) - sys = tf2sys(Gnum+Hnum,Gden,GT,Gin,Gout); - return - endif - ## if not, we go on and do the usual thing... - endif - endif - - ## make sure in ss form - Gsys = sysupdate(Gsys,"ss"); - Hsys = sysupdate(Hsys,"ss"); - - ## change signal names to avoid warning messages from sysgroup - Gsys = syssetsignals(Gsys,"in",sysdefioname(length(Gin),"Gin_u")); - Gsys = syssetsignals(Gsys,"out",sysdefioname(length(Gout),"Gout_u")); - Hsys = syssetsignals(Hsys,"in",sysdefioname(length(Hin),"Hin_u")); - Hsys = syssetsignals(Hsys,"out",sysdefioname(length(Hout),"Hout_u")); - - sys = sysgroup(Gsys,Hsys); - - eyin = eye(mg); - eyout = eye(pg); - - sys = sysscale(sys,[eyout, eyout],[eyin;eyin],Gout,Gin); - - else - ## multiple systems (or a single system); combine together one by one - sys = nth(arglist,1); - for kk=2:length(arglist) - sys = sysadd(sys,nth(arglist,kk)); - endfor - endif - -endfunction - diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/sysappend.m --- a/scripts/control/sysappend.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,190 +0,0 @@ -## Copyright (C) 1996, 1998 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## -*- texinfo -*- -## @deftypefn {Function File} {@var{retsys} =} sysappend (@var{sys}, @var{b}@{, @var{c}, @var{d}, @var{outname}, @var{inname}, @var{yd}@}) -## appends new inputs and/or outputs to a system -## -## @strong{Inputs} -## @table @var -## @item sys -## system data structure -## -## @item b -## matrix to be appended to sys "B" matrix (empty if none) -## -## @item c -## matrix to be appended to sys "C" matrix (empty if none) -## -## @item d -## revised sys d matrix (can be passed as [] if the revised d is all zeros) -## -## @item outname -## list of names for new outputs -## -## @item inname -## list of names for new inputs -## -## @item yd -## binary vector; @math{yd(ii)=0} indicates a continuous output; -## @math{yd(ii)=1} indicates a discrete output. -## @end table -## -## @strong{Outputs} @var{sys} -## @example -## @group -## sys.b := [sys.b , b] -## sys.c := [sys.c ] -## [ c ] -## sys.d := [sys.d | D12 ] -## [D21 | D22 ] -## @end group -## @end example -## where @var{D12}, @var{D21}, and @var{D22} are the appropriate dimensioned -## blocks of the input parameter @var{d}. -## @itemize @bullet -## @item The leading block @var{D11} of @var{d} is ignored. -## @item If @var{inname} and @var{outname} are not given as arguments, -## the new inputs and outputs are be assigned default names. -## @item @var{yd} is a binary vector of length rows(c) that indicates -## continuous/sampled outputs. Default value for @var{yd} is: -## -## @item @var{sys} = continuous or mixed -## @var{yd} = @code{zeros(1,rows(c))} -## -## @item @var{sys} = discrete -## @var{yd} = @code{ones(1,rows(c))} -## @end itemize -## @end deftypefn - -## Author: John Ingram -## Created: August 1996 - -function retsys = sysappend (sys, b, c, d, outname, inname, yd) - - sav_empty_list_elements_ok = empty_list_elements_ok; - - empty_list_elements_ok = 1; - - ## check input arguments - if ( (nargin < 2) | (nargin > 7) | (!is_struct(sys))) - usage("retsys = sysappend(sys,b,c[,d,outname,inname,yd]) "); - elseif(!is_struct(sys)) - error("sys must be a system data structure"); - endif - - ## default system type must be state space form - [Aa,Ab,Ac,Ad,Ats,Ann,Anz,Ast,Ain,Aout,Ayd] = sys2ss(sys); - [Ann,Anz,Am,Ap] = sysdimensions(sys); - - ## default c - if(nargin < 3) c = []; endif - - ## default d - if(nargin < 4) make_d = 1; - elseif(isempty(d)) make_d = 1; - else make_d = 0; endif - if(make_d) d = zeros(rows(c)+Ap,columns(b) + Am); endif - - ## Append new input(s) if any - Bm = max(columns(d),columns(b)+Am); - if(Bm != Am) - ## construct new signal names - if(nargin >= 6) # new names were passed - if(!isstr(inname)) - error("inname must be a string"); - elseif(rows(inname) != (Bm - Am)) - error(sprintf("%d new inputs requested; inname(%dx%d)", ... - (Bm-Am),rows(inname),columns(inname))); - endif - else - inname = sysdefioname(Bm,"u",(Am+1)); - endif - if(Am) Ain = append(Ain,inname); - else Ain = inname; endif - - ## default b matrix - if(isempty(b)) b = zeros(Ann+Anz,(Bm-Am)); - elseif(rows(b) != Ann+Anz | columns(b) != (Bm-Am)) - error(sprintf("b(%dx%d); should be (%dx%d)", rows(b), columns(b), ... - (Ann+Anz), (Bm-Am))); - endif - - ## append new b matrix - Ab = [Ab,b]; # empty_list_elements_ok=1 makes this ok - endif - - ## Append new output(s) if any - Bp = max(rows(d),rows(c)+Ap); - if(Bp != Ap) - - ## construct new signal names, output classification - if(nargin >= 5) # new names were passed - if(!isstr(outname)) - error("outname must be a string"); - elseif(rows(outname) != (Bp - Ap)) - error(sprintf("%d new outputs requested; outname(%dx%d)", ... - (Bp-Ap),rows(outname),columns(outname))); - endif - else - outname = sysdefioname(Bp,"y",(Ap+1)); - endif - if(Ap) Aout = append(Aout,outname); - else Aout = outname; endif - - ## construct new yd entries - if(nargin == 7) - if(!is_vector(yd)) - error(sprintf("yd(%dx%d) must be a vector",rows(yd),columns(yd))) - elseif(rows(c) != length(yd) & rows(d) != length(yd)) - error(sprintf("length(yd) = %d; c(%dx%d), d(%dx%d); mismatch", ... - length(yd), rows(c), columns(c),rows(d),columns(d))); - endif - else - ## default yd values - yd = ones(1,Bp)*( (Ats > 0) & (Ann == 0) & isempty(find(Ayd == 0)) ) ; - endif - Ayd = [vec(Ayd);vec(yd)]; - - ## default c matrix - if(isempty(c)) c = zeros((Bp-Ap),Ann+Anz); - elseif(columns(c) != Ann+Anz | rows(c) != (Bp-Ap)) - error(sprintf("c(%dx%d); should be (%dx%d)", rows(c), columns(c), ... - (Bp-Ap), (Ann+Anz) )); - endif - - ## append new c matrix - Ac = [Ac;c]; # empty_list_elements_ok=1 makes this ok - endif - - ## check d matrix - if(isempty(d)) d = zeros(Bp,Bm); - elseif(rows(d) != Bp | columns(d) != Bm) - error(sprintf("d(%dx%d) should be (%dx%d)",rows(d), columns(d), Bp, Bp)); - endif - - ## Splice in original D matrix - if(Am & Ap) d(1:Ap, 1:Am) = Ad; endif - Ad = d; - - ## construct return system - retsys = ss2sys(Aa,Ab,Ac,Ad,Ats,Ann,Anz,Ast,Ain,Aout,find(Ayd == 1)); - - empty_list_elements_ok = sav_empty_list_elements_ok; - -endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/syschnamesl.m --- a/scripts/control/syschnamesl.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,116 +0,0 @@ -## Copyright (C) 1996 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## -*- texinfo -*- -## @deftypefn {Function File} {@var{old_names} =} syschnamesl (@var{olist}, @var{old_names}, @var{inames}, @var{listname}) -## used internally in syschnames -## item olist: index list -## old_names: original list names -## inames: new names -## listname: name of index list -## -## combines the two string lists old_names and inames -## @end deftypefn - -function old_names = syschnamesl (olist, old_names, inames, listname) - - probstr = []; - if( max(olist) > rows(old_names) ) - probstr = ["index list value(s) exceed(s) number of signals (", ... - num2str(rows(old_names)),")"]; - - elseif( length(olist) > rows(inames) ) - probstr = ["index list dimension exceeds number of replacement names (", ... - num2str(rows(inames)),")"]; - - elseif(isempty(olist)) - probstr = []; # do nothing, no changes - - elseif(min(size(olist)) != 1 ) - probstr = "index list must be either a vector or an empty matrix"; - - elseif(max(olist) > rows(old_names)) - probstr = ["max(",listname,")=",num2str(max(olist))," > ", ... - num2str(rows(old_names)),", too big"]; - - elseif(min(olist) < 1) - probstr = ["min(",listname,")=",num2str(min(olist))," < 1, too small"]; - - else - if( length(olist) == 1) - len_in = columns(inames); - len_out = columns(old_names); - - if (len_in < len_out) - inames(1,(len_in+1):(len_out)) = zeros(1,(len_out - len_in)); - endif - - old_names(olist,1:length(inames)) = inames; - elseif(length(olist) > 1) - for ii=1:length(olist) - mystr = inames(ii,:); - len_my = columns(mystr); - len_out = columns(old_names); - - if (len_my < len_out) - mystr(1,(len_my+1):(len_out)) = " "*ones(1,(len_out - len_my)); - len_my = len_out; - endif - - old_names(olist(ii),1:len_my) = mystr; - endfor - endif - endif - if(!isempty(probstr)) - ## the following lines are NOT debugging code! - disp("Problem in syschnames: old names are") - outlist(old_names," ") - disp("new names are") - outlist(inames," ") - disp("list indices are") - disp(olist) - error(sprintf("syschnames: \"%s\" dim=(%d x %d)--\n\t%s\n", ... - listname, rows(olist), columns(olist),probstr)); - endif - - ## change zeros to blanks - if( find(old_names == 0) ) - ## disp("syschnamesl: old_names contains zeros ") - ## old_names - ## disp("/syschnamesl"); - - [ii,jj] = find(old_names == 0); - for idx=1:length(ii) - old_names(ii(idx),jj(idx)) = " "; - endfor - - ## disp("syschnamesl: old_names fixed zeros ") - ## old_names - ## disp("/syschnamesl"); - endif - - ## just in case it's not a string anymore - if( !isstr(old_names) ) - old_names = setstr(old_names); - endif - - ## disp("syschnamesl: exit, old_names=") - ## old_names - ## disp("/syschnamesl: exiting") - -endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/syschtsam.m --- a/scripts/control/syschtsam.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ -## Copyright (C) 1996 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## -*- texinfo -*- -## @deftypefn {Function File} {@var{retsys} =} syschtsam (@var{sys}, @var{tsam}) -## This function changes the sampling time (tsam) of the system. Exits with -## an error if sys is purely continuous time. -## @end deftypefn - -## Author: John Ingram -## Created: August 1996 - -function retsys = syschtsam (sys, tsam) - - if (nargin != 2) - usage("retsys = syschtsam(sys,tsam)"); - elseif (!is_struct(sys)) - error("sys must be in system data structure form"); - elseif(!is_scalar(tsam)) - disp("syschtsam:") - tsam - error("tsam must be a scalar") - elseif ( ! (is_sample(tsam) | (tsam == 0) ) ) - error("tsam must be real, scalar, and greater than zero"); - elseif (sysgettsam(sys) == 0) - [nc,nz,mm,pp] = sysdimensions(sys); - warning("syschtsam: continuous system (nc=%d, nz=%d, mm=%d, pp=%d)", ... - nc,nz,mm,pp); - warning("syschtsam: The system is continuous, use c2d to make the system discrete"); - endif - - retsys = sys; - retsys.tsam = tsam; - -endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/sysconnect.m --- a/scripts/control/sysconnect.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,277 +0,0 @@ -## Copyright (C) 1996, 1998 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## -*- texinfo -*- -## @deftypefn {Function File} {@var{retsys} =} sysconnect (@var{sys}, @var{out_idx},@var{in_idx}@{,@var{order}, @var{tol}@}) -## Close the loop from specified outputs to respective specified inputs -## -## @strong{Inputs} -## @table @var -## @item sys -## system data structure -## @item out_idx -## @itemx in_idx -## list of connections indices; @math{y(out_idx(ii))} -## is connected to @math{u(in_idx(ii))}. -## @item order -## logical flag (default = 0) -## @table @code -## @item 0 -## leave inputs and outputs in their original order -## @item 1 -## permute inputs and outputs to the order shown in the diagram below -## @end table -## @item tol -## tolerance for singularities in algebraic loops default: 200@var{eps} -## @end table -## -## @strong{Outputs} -## @var{sys}: resulting closed loop system. -## -## @strong{Method} -## @code{sysconnect} internally permutes selected inputs, outputs as shown -## below, closes the loop, and then permutes inputs and outputs back to their -## original order -## @example -## @group -## ____________________ -## u_1 ----->| |----> y_1 -## | sys | -## old u_2 | | -## u_2* ---->(+)--->| |----->y_2 -## (in_idx) ^ -------------------| | (out_idx) -## | | -## ------------------------------- -## @end group -## @end example -## The input that has the summing junction added to it has an * added to -## the end of the input name. -## @end deftypefn - -## Author: A. S. Hodel -## Created: August 1995 -## modified by John Ingram July 1996 - -function sys = sysconnect (sys, output_list, input_list, order, tol) - - if( (nargin < 3) | (nargin > 5) ) - usage("retsys = sysconnect(sys,output_list,input_list[,order,tol])"); - endif - - ## check order - if(nargin <= 3) - order = 0; - elseif( (order != 0) & (order != 1) ) - error("sysconnect: order must be either 0 or 1") - endif - - if (nargin <= 4) - tol = 200*eps; - elseif( !is_sample(tol) ) - error("sysconnect: tol must be a positive scalar"); - elseif(tol > 1e2*sqrt(eps)) - warning(["sysconnect: tol set to large value=",num2str(tol), ... - ", eps=",num2str(eps)]) - endif - - ## verify sizes,format of input, output lists - if( min(size(output_list))*min(size(input_list)) != 1) - error("output_list and input_list must be vectors"); - else - lo = length(output_list); - li = length(input_list); - if(lo != li) - error("output_list and input_list must be of the same length") - endif - - if(is_duplicate_entry(output_list) | is_duplicate_entry(input_list) ) - error("duplicate entry in input_list and/or output_list"); - endif - endif - - [nc,nz,mm,pp] = sysdimensions(sys); - nn = nc+nz; - - if( !is_struct(sys)) - error("sys must be in structured system form") - elseif(pp < li) - error(["length(output_list)=",num2str(li),", sys has only ", ... - num2str(pp),"system outputs"]) - elseif(mm < li) - error(["length(input_list)=",num2str(li),", sys has only ", ... - num2str(mm),"system inputs"]) - endif - - ## check that there are enough inputs/outputs in the system for the lists - if(max(input_list) > mm) - error("max(input_list) exceeds the number of inputs"); - elseif(max(output_list) > pp) - error("max(output_list) exceeds the number of outputs"); - endif - - output_list = reshape(output_list,1,length(output_list)); - - ## make sure we're in state space form - sys = sysupdate (sys, "ss"); - - ## permute rows and columns of B,C,D matrices into pseudo-dgkf form... - all_inputs = sysreorder(mm,input_list); - all_outputs = sysreorder(pp,output_list); - - [aa,bb,cc,dd] = sys2ss(sys); - bb = bb(:,all_inputs); - cc = cc(all_outputs,:); - dd = dd(all_outputs,all_inputs); - - yd = sysgetsignals(sys,"yd"); - yd = yd(all_outputs); - - ## m1, p1 = number of inputs, outputs that are not being connected - m1 = mm-li; - p1 = pp-li; - - ## m2, p2: 1st column, row of B, C that is being connected - m2 = m1+1; - p2 = p1+1; - - ## partition system into a DGKF-like form; the loop is closed around - ## B2, C2 - if(m1 > 0) - B1 = bb(:,1:m1); - D21= dd(p2:pp,1:m1); - endif - B2 = bb(:,m2:mm); - if(p1 > 0) - C1 = cc(1:p1,:); - D12= dd(1:p1,m2:mm); - endif - C2 = cc(p2:pp,:); - if(m1*p1 > 0) - D11= dd(1:p1,1:m1); - endif - D22= dd(p2:pp,m2:mm); - - if(norm(D22)) - warning("sysconnect: possible algebraic loop, D22 non-zero"); - D22i = (eye(size(D22))-D22); - C2h = D22i\C2; - if(m1 > 0) - D21h = D22i\D21; - endif - D22h = D22i\D22; - else - C2h = C2; - if(m1 > 0) - D21h = D21; - endif - D22h = D22; - - endif - - ## check cont state -> disc output -> cont state - dyi = find(yd(p2:pp)); - - ## disp("sysconnect: dyi=") - ## dyi - ## nc - ## disp("/sysconnect"); - - if( (nc > 0) & find(dyi > 0) ) - B2con = B2(1:nc,dyi); # connection to cont states - C2hd = C2h(dyi,1:nc); # cont states -> outputs - else - B2con = C2hd = []; - endif - - if(max(size(B2con)) & max(size(C2hd)) ) - if(norm(B2con*C2hd)) - warning("sysconnect: cont-state -> disc output -> cont state derivative"); - warning(" connection made; resulting system may not be meaningful"); - endif - endif - - Ac = aa+B2*C2h; - if(m1 > 0) - B1c = B1 + B2*D21h; - endif - B2c = B2*(eye(size(D22h)) + D22h); - if(p1*m1 > 0) - D11c = D11 + D12*D21h; - endif - if(p1 > 0) - C1c = C1+D12*C2h; - D12c = D12*(eye(size(D22h))+D22h); - endif - - ## construct system data structure - if(m1 > 0) - Bc = [B1c, B2c]; - else - Bc = B2c; - endif - - if(p1 > 0) - Cc = [C1c;C2h]; - else - Cc = C2h; - endif - - if(m1*p1 > 0) - Dc = [D11c,D12c; D21h,D22h]; - elseif(m1 > 0) - Dc = [D21h, D22h]; - elseif(p1 > 0) - Dc = [D12c; D22h]; - else - Dc = D22h; - endif - - ## permute rows and columns of Bc, Cc, Dc back into original order - Im = eye(mm,mm); - Pi = Im(:,all_inputs); - back_inputs = Pi*[1:mm]'; - - Ip = eye(pp,pp); - Po = Ip(:,all_outputs); - back_outputs = Po*[1:pp]'; - - Bc = Bc(:,back_inputs); - Cc = Cc(back_outputs,:); - Dc = Dc(back_outputs,back_inputs); - yd = yd(back_outputs); - - ## rebuild system - Ts = sysgettsam(sys); - [stnam,innam,outnam] = sysgetsignals(sys); - sys = ss2sys(Ac,Bc,Cc,Dc,Ts,nc,nz,stnam,innam,outnam,find(yd)); - - ## update connected input names - for ii = 1:length(input_list) - idx = input_list(ii); - strval = sprintf("%s*",nth(sysgetsignals(sys,"in",idx),1) ); - sys = syssetsignals(sys,"in",strval,idx); - endfor - - ## maintain original system type if it was SISO - if (strcmp (sysgettype (sys), "tf")) - sysupdate (sys, "tf"); - elseif (strcmp (sysgettype (sys),"zp")) - sysupdate (sys, "zp"); - endif - -endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/syscont.m --- a/scripts/control/syscont.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,88 +0,0 @@ -## Copyright (C) 1996 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## -*- texinfo -*- -## @deftypefn {Function File} {[@var{csys}, @var{Acd}, @var{Ccd}] =} syscont (@var{sys}) -## Extract the purely continuous subsystem of an input system. -## -## @strong{Inputs} -## @var{sys} is a system data structure -## -## @strong{Outputs} -## @table @var -## @item csys -## is the purely continuous input/output connections of @var{sys} -## @item Acd -## @itemx Ccd -## connections from discrete states to continuous states, -## discrete states to continuous outputs, respectively. -## -## returns @var{csys} empty if no continuous/continous path exists -## @end table -## @end deftypefn - -## Author: John Ingram -## Created: August 1996 - -function [csys, Acd, Ccd] = syscont (sys) - - save_empty = empty_list_elements_ok; - empty_list_elements_ok = 1; - - if (nargin != 1) - usage("[csys,Acd,Ccd,Dcd] = syscont(sys)"); - elseif (!is_struct(sys)) - error("sys must be in system data structure form"); - endif - - sys = sysupdate(sys,"ss"); - [n_tot,st_c,st_d,y_c,y_d] = syscont_disc(sys); # get ranges - - ## assume there's nothing there; build partitions as appropriate - Acc = Acd = Bcc = Ccc = Ccd = Dcc = []; - - if(isempty(st_c) & isempty(y_c)) - error("syscont: expecting continous states and/or continous outputs"); - elseif (isempty(st_c)) - warning("syscont: no continuous states"); - elseif(isempty(y_c)) - warning("syscont: no continuous outputs"); - endif - - [sys_a, sys_b, sys_c, sys_d ] = sys2ss(sys); - [sys_stname, sys_inname, sys_outname] = sysgetsignals(sys); - [sys_n, sys_nz, sys_m, sys_p] = sysdimensions(sys); - if(!isempty(st_c)) - Acc = sys_a(st_c,st_c); - stname = sys_stname(st_c); - Bcc = sys_b(st_c,:); - Ccc = sys_c(y_c,st_c); - Acd = sys_a(st_c,st_d); - else - stname=[]; - endif - outname = sys_outname(y_c); - Dcc = sys_d(y_c,:); - Ccd = sys_c(y_c,st_d); - inname = sys_inname; - - csys = ss2sys(Acc,Bcc,Ccc,Dcc,0,sys_n,0,stname,inname,outname); - - empty_list_elements_ok = save_empty; - -endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/syscont_disc.m --- a/scripts/control/syscont_disc.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -## Copyright (C) 1996, 1998 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## -*- texinfo -*- -## @deftypefn {Function File} {[@var{n_tot}, @var{st_c}, @var{st_d}, @var{y_c}, @var{y_d}] =} syscont_disc(@var{sys}) -## Used internally in syscont and sysdisc. -## -## @strong{Inputs} -## @var{ sys} is a system data structure. -## -## @strong{Outputs} -## @table @var -## @item n_tot -## total number of states -## @item st_c -## vector of continuous state indices (empty if none) -## @item st_d -## vector of discrete state indices (empty if none) -## @item y_c -## vector of continuous output indices -## @item y_d -## vector of discrete output indices -## @end table -## @end deftypefn - -## Author: A. S. Hodel -## Created: February 1997 - -function [n_tot, st_c, st_d, y_c, y_d] = syscont_disc (sys) - - ## get ranges for discrete/continuous states and outputs - [nn,nz,mm,pp,yd] = sysdimensions(sys); - n_tot = nn + nz; - st_c = 1:(nn); - st_d = nn + (1:nz); - y_c = find(yd == 0); # y_c, y_d will be empty if there are none. - y_d = find(yd == 1); - -endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/sysdefioname.m --- a/scripts/control/sysdefioname.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +0,0 @@ -## Copyright (C) 1996, 1998 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## -*- texinfo -*- -## @deftypefn {Function File} {@var{ioname} =} sysdefioname (@var{n},@var{str} @{,@var{m}@}) -## return default input or output names given @var{n}, @var{str}, @var{m}. -## @var{n} is the final value, @var{str} is the string prefix, and @var{m} -## is start value -## -## used internally, minimal argument checking -## -## @strong{Example} @code{ioname = sysdefioname(5,"u",3)} -## returns the list: -## @example -## ioname = -## ( -## [1] = u_3 -## [2] = u_4 -## [3] = u_5 -## ) -## @end example -## @end deftypefn - -function ioname = sysdefioname (n, str, m) - - if (nargin < 2 | nargin > 3) - usage("ioname = sysdefioname(n,str[,m])"); - endif - - if (nargin == 2) m = min(1,n); endif - - ioname = list(); - jj = 1; - if(n > 0 & m > 0 & m <= n) - for ii = m:n - ioname(ii+1-m) = sprintf("%s_%d",str,ii); - endfor - elseif(m > n) - error("str=%s; start value m=%d > final value n=%d",str,m,n); - endif - -endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/sysdefstname.m --- a/scripts/control/sysdefstname.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,42 +0,0 @@ -## Copyright (C) 1996 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## -*- texinfo -*- -## @deftypefn {Function File} {@var{stname} =} sysdefstname (@var{n}, @var{nz}) -## return default state names given @var{n}, @var{nz} -## -## used internally, minimal argument checking -## @end deftypefn - -function stname = sysdefstname (n, nz) - - stname = list(); - if(n > 0) - for ii = 1:n - stname(ii) = sprintf("x_%d",ii); - endfor - endif - - ## Set default names for discrete states - if(nz > 0) - for ii = (n+1):(n+nz) - stname(ii) = sprintf("xd_%d",ii); - endfor - endif - -endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/sysdimensions.m --- a/scripts/control/sysdimensions.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,101 +0,0 @@ -## Copyright (C) 1996, 1998 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## -*- texinfo -*- -## @deftypefn {Function File} {[@var{n}, @var{nz}, @var{m}, @var{p}, @var{yd}] =} sysdimensions (@var{sys}@{, @var{opt}@}) -## return the number of states, inputs, and/or outputs in the system -## @var{sys}. -## -## @strong{Inputs} -## @table @var -## @item sys -## system data structure -## -## @item opt -## String indicating which dimensions are desired. Values: -## @table @code -## @item "all" -## (default) return all parameters as specified under Outputs below. -## -## @item "cst" -## return @var{n}= number of continuous states -## -## @item "dst" -## return @var{n}= number of discrete states -## -## @item "in" -## return @var{n}= number of inputs -## -## @item "out" -## return @var{n}= number of outputs -## @end table -## @end table -## -## @strong{Outputs} -## @table @var -## @item n -## number of continuous states (or individual requested dimension as specified -## by @var{opt}). -## @item nz -## number of discrete states -## @item m -## number of system inputs -## @item p -## number of system outputs -## @item yd -## binary vector; @var{yd}(@var{ii}) is nonzero if output @var{ii} is -## discrete. -## @math{yd(ii) = 0} if output @var{ii} is continous -## @end table -## @end deftypefn -## @seealso{sysgetsignals and sysgettsam} - -function [n, nz, m, p, yd] = sysdimensions (sys, opt) - - if(nargout > 5 | nargin < 1 | nargin > 2) - usage("[n,nz,m,p[,yd]] = sysdimensions(sys{,opt})"); - elseif(!is_struct(sys)) - usage("[n,nz,m,p] = sysdimensions(sys)"); - elseif(nargin == 1) - opt = "all"; - endif - - n = sys.n; - nz = sys.nz; - m = length(sysgetsignals(sys,"in")); - p = length(sysgetsignals(sys,"out")); - yd = sys.yd; - valid_options = list("all","cst","dst","st","in","out"); - valid_values = list(n,n,nz,n+nz,m,p); - - valid_opt = 0; - for ii=1:length(valid_options) - if(strcmp(nth(valid_options,ii),opt)) - n = nth(valid_values,ii); - valid_opt = 1; - if(ii > 1 & nargout > 1) - warning("opt=%s, %d output arguments requested",opt,nargout); - endif - endif - endfor - - if (! valid_opt) - error ("invalid option passed = %s", opt); - endif - -endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/sysdisc.m --- a/scripts/control/sysdisc.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,98 +0,0 @@ -## Copyright (C) 1996 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## -*- texinfo -*- -## @deftypefn {Function File} {[@var{dsys}, @var{Adc}, @var{Cdc}] =} sysdisc (@var{sys}) -## -## @strong{Inputs} -## @var{sys} = system data structure -## -## @strong{Outputs} -## @table @var -## @item dsys -## purely discrete portion of sys (returned empty if there is -## no purely discrete path from inputs to outputs) -## @item Adc -## @itemx Cdc -## connections from continuous states to discrete states and discrete -## outputs, respectively. -## @end table -## @end deftypefn - -function [dsys, Adc, Cdc] = sysdisc (sys) - - save_empty = empty_list_elements_ok; - empty_list_elements_ok = 1; - - if (nargin != 1) - usage("[dsys,Adc,Cdc] = sysdisc(sys)"); - elseif (!is_struct(sys)) - error("sys must be in system data structure form"); - endif - - sys = sysupdate(sys,"ss"); - [n_tot,st_c,st_d,y_c,y_d] = syscont_disc(sys); # get ranges - - ## assume there's nothing there; build partitions as appropriate - Add = Adc = Bdd = Cdd = Cdc = Ddd = []; - - if(isempty(st_d) & isempty(y_d)) - error("sysdisc: expecting discrete states and/or continous outputs"); - elseif (isempty(st_d)) - warning("sysdisc: no discrete states"); - elseif(isempty(y_d)) - warning("sysdisc: no discrete outputs"); - endif - - [aa,bb,cc,dd] = sys2ss(sys); - if(!isempty(st_d) ) - Add = aa( st_d , st_d); - stname = sysgetsignals(sys,"st",st_d); - Bdd = bb( st_d , :); - if(!isempty(st_c)) - Adc = aa( st_d , st_c); - endif - if(!isempty(y_d)) - Cdd = cc(y_d , st_d); - endif - else - stname = []; - endif - if(!isempty(y_d)) - Ddd = dd(y_d , :); - outname = sysgetsignals(sys,"out",y_d); - if(!isempty(st_c)) - Cdc = cc(y_d , st_c); - endif - else - outname=[]; - endif - inname = sysgetsignals(sys,"in"); - outlist = 1:rows(outname); - - if(!isempty(outname)) - tsam = sysgettsam(sys); - [nc,nz] = sysdimensions(sys); - dsys = ss2sys(Add,Bdd,Cdd,Ddd,tsam,0,nz,stname,inname,outname,outlist); - else - dsys=[]; - endif - - empty_list_elements_ok = save_empty; - -endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/sysdup.m --- a/scripts/control/sysdup.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,120 +0,0 @@ -## Copyright (C) 1996, 1998 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## -*- texinfo -*- -## @deftypefn {Function File} {@var{retsys} =} sysdup (@var{Asys}, @var{out_idx}, @var{in_idx}) -## Duplicate specified input/output connections of a system -## -## @strong{Inputs} -## @table @var -## @item Asys -## system data structure (@pxref{ss2sys}) -## @item out_idx -## @itemx in_idx -## list of connections indices; -## duplicates are made of @code{y(out_idx(ii))} and @code{u(in_idx(ii))}. -## @end table -## -## @strong{Outputs} -## @var{retsys}: resulting closed loop system: -## duplicated i/o names are appended with a @code{"+"} suffix. -## -## -## @strong{Method} -## @code{sysdup} creates copies of selected inputs and outputs as -## shown below. u1/y1 is the set of original inputs/outputs, and -## u2,y2 is the set of duplicated inputs/outputs in the order specified -## in @var{in_idx}, @var{out_idx}, respectively -## @example -## @group -## ____________________ -## u1 ----->| |----> y1 -## | Asys | -## u2 ------>| |----->y2 -## (in_idx) -------------------| (out_idx) -## @end group -## @end example -## @end deftypefn - -## Author: A. S. Hodel -## Created: August 1995 -## modified by John Ingram July 1996 - -function retsys = sysdup (Asys, output_list, input_list) - - if( nargin != 3) - usage("retsys = sysdup(Asys,output_list,input_list)"); - endif - - if( !is_struct(Asys)) - error("Asys must be a system data structure (see ss2sys, tf2sys, or zp2sys)") - endif - - Asys = sysupdate(Asys,"ss"); - [nn,nz,mm,pp] = sysdimensions(Asys); - [aa,bb,cc,dd] = sys2ss(Asys); - - ## first duplicate inputs - if(is_vector(input_list)) - for ii=1:length(input_list); - bb(:,mm+ii) = bb(:,input_list(ii)); - dd(:,mm+ii) = dd(:,input_list(ii)); - end - elseif(!isempty(input_list)) - error("input_list must be a vector or empty"); - endif - - - ## now duplicate outputs - osize = min(size(output_list)); - if(osize == 1) - for ii=1:length(output_list); - cc(pp+ii,:) = cc(output_list(ii),:); - dd(pp+ii,:) = dd(output_list(ii),:); - end - elseif(osize != 0) - error("output_list must be a vector or empty"); - endif - - [stnam,innam,outnam,yd] = sysgetsignals(Asys); - tsam = sysgettsam(Asys); - - ## pack system and then rename signals - retsys = ss2sys(aa,bb,cc,dd,tsam,nn,nz); - retsys = syssetsignals(retsys,"in",innam,1:mm); - retsys = syssetsignals(retsys,"out",outnam,1:pp); - retsys = syssetsignals(retsys,"yd",yd,1:pp); - - ## update added input names - for ii=(mm+1):(mm+length(input_list)) - onum = input_list(ii-mm); - strval = sprintf("%s(dup)",sysgetsignals(retsys,"in",onum,1) ); - retsys = syssetsignals(retsys,"in",strval,ii); - endfor - - ## update added output names/discrete flags - ## give default names to the added outputs - for jj=(pp+1):(pp+length(output_list)) - onum = output_list(jj-pp); - strval = sprintf("%s(dup)",sysgetsignals(retsys,"out",onum,1) ); - retsys = syssetsignals(retsys,"out",strval,jj); - dflg = sysgetsignals(retsys,"yd",onum); - retsys = syssetsignals(retsys,"yd",dflg,jj); - endfor - -endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/sysgetsignals.m --- a/scripts/control/sysgetsignals.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,193 +0,0 @@ -## Copyright (C) 1998 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## -*- texinfo -*- -## @deftypefn {Function File} {[@var{stname}, @var{inname}, @var{outname}, @var{yd}] =} sysgetsignals (@var{sys}) -## @deftypefnx{Function File} {@var{siglist} =} sysgetsignals (@var{sys},@var{sigid}) -## @deftypefnx{Function File} {@var{signame} =} sysgetsignals (@var{sys},@var{sigid},@var{signum}@{, @var{strflg}@}) -## Get signal names from a system -## -## @strong{Inputs} -## @table @var -## @item sys -## system data structure for the state space system -## -## @item sigid -## signal id. String. Must be one of -## @table @code -## @item "in" -## input signals -## @item "out" -## output signals -## @item "st" -## stage signals -## @item "yd" -## value of logical vector @var{yd} -## @end table -## -## @item signum -## Index of signal (or indices of signals if signum is a vector) -## -## @item strflg -## flag to return a string instead of a list; Values: -## @table @code -## @item 0 -## (default) return a list (even if signum is a scalar) -## -## @item 1 -## return a string. Exits with an error if signum is not a scalar. -## @end table -## -## @end table -## -## @strong{Outputs} -## @table @bullet -## @item If @var{sigid} is not specified -## @table @var -## @item stname -## @itemx inname -## @itemx outname -## signal names (lists of strings); names of states, -## inputs, and outputs, respectively -## @item yd -## binary vector; @var{yd}(@var{ii}) is nonzero if output @var{ii} is -## discrete. -## @end table -## -## @item If @var{sigid} is specified but @var{signum} is not specified, then -## @table @code -## @item sigid="in" -## @var{siglist} is set to the list of input names -## -## @item sigid="out" -## @var{siglist} is set to the list of output names -## -## @item sigid="st" -## @var{siglist} is set to the list of state names -## -## stage signals -## @item sigid="yd" -## @var{siglist} is set to logical vector indicating discrete outputs; -## @var{siglist(ii) = 0} indicates that output @var{ii} is continuous -## (unsampled), otherwise it is discrete. -## -## @end table -## -## @item if the first three input arguments are specified, then @var{signame} is -## a list of the specified signal names (@var{sigid} is @code{"in"}, -## @code{"out"}, or @code{"st"}), or else the logical flag -## indicating whether output(s) @var{signum} is(are) discrete (@var{sigval}=1) -## or continuous (@var{sigval}=0). -## @end table -## -## @strong{Examples} (From @code{sysrepdemo}) -## @example -## octave> sys=ss2sys(rand(4),rand(4,2),rand(3,4)); -## octave> [Ast,Ain,Aout,Ayd] = sysgetsignals(sys) i # get all signal names -## Ast = -## ( -## [1] = x_1 -## [2] = x_2 -## [3] = x_3 -## [4] = x_4 -## ) -## Ain = -## ( -## [1] = u_1 -## [2] = u_2 -## ) -## Aout = -## ( -## [1] = y_1 -## [2] = y_2 -## [3] = y_3 -## ) -## Ayd = -## -## 0 0 0 -## octave> Ain = sysgetsignals(sys,"in") # get only input signal names -## Ain = -## ( -## [1] = u_1 -## [2] = u_2 -## ) -## octave> Aout = sysgetsignals(sys,"out",2) # get name of output 2 (in list) -## Aout = -## ( -## [1] = y_2 -## ) -## octave> Aout = sysgetsignals(sys,"out",2,1) # get name of output 2 (as string) -## Aout = y_2 -## @end example -## @end deftypefn - -function [stname, inname, outname, yd] = sysgetsignals (sys, sigid, signum, strflg) - - ## Adapted from ss2sys - - if(nargin < 1 | nargin > 4 | nargout > 4) - usage("[stname{,inname,outname,yd}] = sysgetsignals(sys{,sigid,signum})") - elseif(nargin > 1 & nargout > 1) - usage("sig = sysgetsignals(sys,sigid{,signum,strflg})") - elseif( ! is_struct(sys) ) - error("input argument must be a system data structure"); - endif - if(nargin < 4) strflg = 0; endif - if(nargin == 1) - sys = sysupdate(sys,"ss"); #make sure ss is up to date - stname = sysgetsignals(sys,"st"); - inname = sysgetsignals(sys,"in"); - outname = sysgetsignals(sys,"out"); - yd = sysgetsignals(sys,"yd"); - elseif(!(isstr(sigid) & min(size(sigid)) == 1)) - error(sprintf("sigid(%dx%d) must be a string)",rows(sigid),columns(sigid))); - else - if(strcmp("st",sigid)) stname = sys.stname; - elseif(strcmp("in",sigid)) stname = sys.inname; - elseif(strcmp("out",sigid)) stname = sys.outname; - elseif(strcmp("yd",sigid)) stname = vec(sys.yd)'; - else - error(sprintf("sigid=%s must be \"st\", \"in\", \"out\", or \"yd\"", ... - sigid)); - endif - if(nargin >= 3) - if(signum > length(stname)) - error(sprintf("sysgetsignals(sys,\"%s\",%d):only %d entries.\n", ... - sigid,signum, rows(stname))); - else - if(!is_scalar(strflg)) - error("strflg must be a scalar"); - endif - switch(strflg) - case(0), - stname = stname(signum); - case(1), - if(length(signum) > 1) - error("strflg=1, length(signum) = %d",length(signum)); - endif - stname = nth(stname,signum); - otherwise, - error ("invalid value of strflg = %e", strflg); - endswitch - - endif - endif - endif - -endfunction - diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/sysgettsam.m --- a/scripts/control/sysgettsam.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ -## Copyright (C) 1996, 1998 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## T = sysgettsam(sys) -## return the sampling time of the system - -function T = sysgettsam (sys) - - if(!is_struct(sys)) - usage("T = sysgettsam(sys)"); - endif - - T = sys.tsam; - -endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/sysgettype.m --- a/scripts/control/sysgettype.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,42 +0,0 @@ -## Copyright (C) 1998 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## -*- texinfo -*- -## @deftypefn {Function File} {@var{systype} =} sysgettype (@var{sys}) -## return the initial system type of the system -## -## @strong{Inputs} -## @var{sys}: system data structure -## -## @strong{Outputs} -## @var{systype}: string indicating how the structure was initially -## constructed: -## values: @code{"ss"}, @code{"zp"}, or @code{"tf"} -## -## @strong{Note} FIR initialized systems return @code{systype="tf"}. -## @end deftypefn - -function systype = sysgettype (sys) - - if(!is_struct(sys)) - error("sysgettype: input sys is not a structure"); - endif - - typestr = list("tf","zp","ss"); - systype = nth(typestr,sys.sys(1) + 1); -endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/sysgroup.m --- a/scripts/control/sysgroup.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,150 +0,0 @@ -## Copyright (C) 1996, 1998, 1999 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## -*- texinfo -*- -## @deftypefn {Function File} {@var{sys} =} sysgroup (@var{Asys}, @var{Bsys}) -## Combines two systems into a single system -## -## @strong{Inputs} -## @var{Asys}, @var{Bsys}: system data structures -## -## @strong{Outputs} -## @math{sys = @r{block diag}(Asys,Bsys)} -## @example -## @group -## __________________ -## | ________ | -## u1 ----->|--> | Asys |--->|----> y1 -## | -------- | -## | ________ | -## u2 ----->|--> | Bsys |--->|----> y2 -## | -------- | -## ------------------ -## Ksys -## @end group -## @end example -## The function also rearranges the internal state-space realization of @var{sys} -## so that the -## continuous states come first and the discrete states come last. -## If there are duplicate names, the second name has a unique suffix appended -## on to the end of the name. -## @end deftypefn - -## Author: A. S. Hodel -## Created: August 1995 -## modified by John Ingram July 1996 -## A. S. Hodel: modified for variable number of arguments 1999 - -function sys = sysgroup (...) - - save_emp = empty_list_elements_ok; - empty_list_elements_ok = 1; - - if(nargin < 1) - usage("sys = sysgroup(Asys{,Bsys,...})"); - endif - - ## collect all arguments - arglist = list(); - va_start(); - for kk=1:nargin - arglist(kk) = va_arg(); - if(!is_struct(nth(arglist,kk))) - error("sysgroup: argument %d is not a data structure",kk); - endif - endfor - - if(nargin == 2) - ## the usual case; group the two systems together - Asys = nth(arglist,1); - Bsys = nth(arglist,2); - - ## extract information from Asys, Bsys to consruct sys - Asys = sysupdate(Asys,"ss"); - Bsys = sysupdate(Bsys,"ss"); - [n1,nz1,m1,p1] = sysdimensions(Asys); - [n2,nz2,m2,p2] = sysdimensions(Bsys); - [Aa,Ab,Ac,Ad,Atsam,An,Anz,Ast,Ain,Aout,Ayd] = sys2ss(Asys); - [Ba,Bb,Bc,Bd,Btsam,Bn,Bnz,Bst,Bin,Bout,Byd] = sys2ss(Bsys); - nA = An + Anz; - nB = Bn + Bnz; - - if(p1*m1*p2*m2 == 0) - error("sysgroup: argument lacks inputs and/or outputs"); - - elseif((Atsam + Btsam > 0) & (Atsam * Btsam == 0) ) - warning("sysgroup: creating combination of continuous and discrete systems") - - elseif(Atsam != Btsam) - error("sysgroup: Asys.tsam=%e, Bsys.tsam =%e", Atsam, Btsam); - endif - - A = [Aa,zeros(nA,nB); zeros(nB,nA),Ba]; - B = [Ab,zeros(nA,m2); zeros(nB,m1),Bb]; - C = [Ac,zeros(p1,nB); zeros(p2,nA),Bc]; - D = [Ad,zeros(p1,m2); zeros(p2,m1),Bd]; - tsam = max(Atsam,Btsam); - - ## construct combined signal names; stnames must check for pure gain blocks - if(isempty(Ast)) - stname = Bst; - elseif(isempty(Bst)) - stname = Ast; - else - stname = append(Ast, Bst); - endif - inname = append(Ain, Bin); - outname = append(Aout,Bout); - - ## Sort states into continous first, then discrete - dstates = ones(1,(nA+nB)); - if(An) - dstates(1:(An)) = zeros(1,An); - endif - if(Bn) - dstates((nA+1):(nA+Bn)) = zeros(1,Bn); - endif - [tmp,pv] = sort(dstates); - A = A(pv,pv); - B = B(pv,:); - C = C(:,pv); - stname = stname(pv); - - ## check for duplicate signal names - inname = sysgroupn(inname,"input"); - stname = sysgroupn(stname,"state"); - outname = sysgroupn(outname,"output"); - - ## mark discrete outputs - outlist = find([Ayd, Byd]); - - ## build new system - sys = ss2sys(A,B,C,D,tsam,An+Bn,Anz+Bnz,stname,inname,outname); - - else - ## multiple systems (or a single system); combine together one by one - sys = nth(arglist,1); - for kk=2:length(arglist) - printf("sysgroup: kk=%d\n",kk); - sys = sysgroup(sys,nth(arglist,kk)); - endfor - endif - - empty_list_elements_ok = save_emp; - -endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/sysgroupn.m --- a/scripts/control/sysgroupn.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +0,0 @@ -## Copyright (C) 1996, 1998 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## -*- texinfo -*- -## @deftypefn {Function File} {@var{names} =} sysgroupn (@var{names}) -## names = sysgroupn(names) -## Locate and mark duplicate names -## inputs: -## names: list of signal names -## kind: kind of signal name (used for diagnostic message purposes only) -## outputs: -## returns names with unique suffixes added; diagnostic warning -## message is printed to inform the user of the new signal name -## -## used internally in sysgroup and elsewhere. -## @end deftypefn - -function names = sysgroupn (names, kind) - - ## check for duplicate names - l = length(names); - ii = 1; - while(ii <= l-1) - st1 = nth(names,ii); - jj = ii+1; - while ( jj <= l) - st2 = nth(names,jj); - if(strcmp(st1,st2)) - suffix = ["_",num2str(jj)]; - warning("sysgroup: %s name(%d) = %s name(%d) = %s", ... - kind,ii,kind,jj,st1); - strval = sprintf("%s%s",st2,suffix); - names(jj) = strval; - warning("sysgroup: changed %s name %d to %s",kind,jj,strval); - ## restart the check (just to be sure there's no further duplications) - ii = 0; jj = l; - endif - jj = jj+1; - endwhile - ii = ii+1; - endwhile -endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/sysidx.m --- a/scripts/control/sysidx.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -## Copyright (C) 1996, 1998 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## idxvec = sysidx (sys, sigtype, signamelist) -## return indices of signals with specified signal names -## inputs: -## sys: OCST system data structure -## sigtype: signal type to be selected: "in", "out", "st" -## signamelist: list of desired signal names -## outputs: -## idxvec: vector of signal indices (appropriate for use with sysprune) - -function idxvec = sysidx (sys, sigtype, signamelist) - - if (nargin != 3) - usage ("idxvec = sysidx (sys, sigtype, signamelist)"); - elseif (! is_struct (sys)) - error ("sys must be a system data structure"); - elseif (! isstr (sigtype)) - error ("sigtype must be a string"); - elseif (rows (sigtype) != 1) - [nr, nc] = size (sigtype); - error ("sigtype (%d x %d) must be a single string", nr, nc); - endif - - ## extract correct set of signal names values - [idxvec, msg] = listidx (list ("in", "out", "st", "yd"), sigtype); - if (msg) - error ("invalid sigtype = %s", sigtype); - endif - - syssiglist = sysgetsignals (sys, sigtype); - [idxvec, msg] = listidx (syssiglist, signamelist); - if (length (msg)) - error ("sysidx (sigtype = %s): %s", sigtype, - strrep (msg, "strlist", "signamelist")); - endif - -endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/sysmin.m --- a/scripts/control/sysmin.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,177 +0,0 @@ -## Copyright (C) 1996 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## [retsys,nc,no] = sysmin(sys{,flg}); -## return a minimal (or reduced order) system -## inputs: -## sys: system data structure -## flg: 0 [default] return minimal system; state names lost -## : 1 return system with physical states removed that -## are either uncontrollable or unobservable -## (cannot reduce further without discarding physical -## meaning of states) -## outputs: -## retsys: returned system -## nc: number of controllable states in the returned system -## no: number of observable states in the returned system -## cflg: is_controllable(retsys) -## oflg: is_observable(retsys) - -## Author: A. S. Hodel - -function [retsys, nc, no, cflg, oflg] = sysmin (sys, flg); - - switch(nargin) - case(1), flg = 0; - case(2), jnk = flg; # dummy operation - otherwise, - usage("[retsys,nc,no] = sysmin(sys{,flg})"); - endswitch - dflg = is_digital(sys,2); - [n,nz,m,p] = sysdimensions(sys); - if(n*nz > 0) - # both continuous and discrete states - [aa,bb,cc,dd,tsam,n,nz,stnam,innam,outnam,yd] = sys2ss(sys); - crng = 1:n; - drng = n+(1:nz); - - # get minimal realization of continuous part - Ac = aa(crng,crng); - Acd = aa(crng,drng); - Adc = aa(drng,crng); - Ad = aa(drng,drng); - Bc = bb(crng,:); - Bd = bb(drng,:); - Cc = cc(:,crng); - Cd = cc(:,drng); - - cstnam = stnam(crng); - dstnam = stnam(drng); - cinnam = append(innam,stnam(drng)); - coutnam = append(outnam,stnam(drng)); - csys = ss2sys(Ac,[Bc,Acd],[Cc;Adc]); - csys = syssetsignals(csys,"st",cstnam); - csys = syssetsignals(csys,"in",cinnam); - csys = syssetsignals(csys,"out",coutnam); - - # reduce continuous system, recombine with discrete part - csys = sysmin(csys,flg); - cn = sysdimensions(csys); - - if(cn == 0) - # continuous states are removed; just reduce the discrete part - sys = sysprune(sys,1:p,1:m,drng); - retsys = sysmin(sys,flg); - else - # extract updated parameters from reduced continuous system - [caa,cbb,ccc,cdd,ctsam,cn,cnz,cstnam,cinnam,coutnam] = sys2ss(csys); - crng = 1:cn; - Ac = caa; - Bc = cbb(:,1:m); - Acd = cbb(:,m+(1:nz)); - Cc = ccc(1:p,:); - Adc = ccc(p + (1:nz),:); - - # recombine to reduce discrete part of the system - dinnam = append(innam,cstnam); - doutnam = append(outnam,cstnam); - dsys = ss2sys(Ad,[Bd,Adc],[Cd;Acd],[],tsam); - dsys = syssetsignals(dsys,"st",dstnam); - dsys = syssetsignals(dsys,"in",dinnam); - dsys = syssetsignals(dsys,"out",doutnam); - - # reduce discrete subsystem - dsys = sysmin(dsys); - [n1,nz] = sysdimensions(dsys); - if(nz == 0) - # discrete subsystem is not needed - retsys = sysprune(csys,1:p,1:m); - else - # combine discrete, continuous subsystems - [Ad,dbb,dcc] = sys2ss(dsys); - dstnam = sysgetsignals(dsys,"st"); - Bd = dbb(:,1:m); - Adc = dbb(:,m+(1:cn)); - Cd = dcc(1:p,:); - Acd = dcc(p+(1:cn),:); - stnam = append(cstnam,dstnam); - aa = [Ac, Acd; Adc, Ad]; - bb = [Bc; Bd]; - cc = [Cc, Cd]; - retsys = ss2sys([Ac, Acd; Adc, Ad], [Bc ; Bd], [Cc, Cd], dd, tsam, ... - cn, nz, stnam, innam, outnam, find(yd == 1)); - end - endif - else - Ts = sysgettsam(sys); - switch(flg) - case(0), - ## reduce to a minimal system - [aa,bb,cc,dd] = sys2ss(sys); - [cflg,Uc] = is_controllable(aa,bb); - if(!cflg) - ## reduce to controllable states - if(!isempty(Uc)) - aa = Uc'*aa*Uc; - bb = Uc'*bb; - cc = cc*Uc; - else - aa = bb = cc = []; - endif - endif - if(!isempty(aa)) - [oflg,Uo] = is_observable(aa,cc); - if(!oflg) - if(!isempty(Uo)) - aa = Uo'*aa*Uo; - bb = Uo'*bb; - cc = cc*Uo; - else - aa = bb = cc = []; - endif - endif - endif - switch(dflg) - case(0), - nc = no = nn = columns(aa); - nz = 0; - case(1), - nc = no = nz = columns(aa); - nn = 0; - endswitch - innam = sysgetsignals(sys,"in"); - outnam= sysgetsignals(sys,"out"); - retsys = ss2sys(aa,bb,cc,dd,Ts,nn,nz,[],innam,outnam); - case(1), - ## reduced model with physical states - [cflg,Uc] = is_controllable(sys); xc = find(max(abs(Uc')) != 0); - [oflg,Uo] = is_observable(sys); xo = find(max(abs(Uo')) != 0); - xx = intersection(xc,xo); - if(isempty(xx)) xx = 0; endif # signal no states in reduced model - retsys = sysprune(sys,[],[],xx); - otherwise, - error ("invalid value of flg = %d", flg); - endswitch - if(sysdimensions(retsys,"st") > 0) - [cflg,Uc] = is_controllable(retsys); nc = columns(Uc); - [oflg,Uo] = is_observable(retsys); no = columns(Uo); - else - nc = no = 0; - endif - endif -endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/sysmult.m --- a/scripts/control/sysmult.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,114 +0,0 @@ -## Copyright (C) 1996, 1999 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## -*- texinfo -*- -## @deftypefn {Function File} {@var{sys} =} sysmult (@var{Asys}, @var{Bsys}) -## Compute @math{sys = Asys*Bsys} (series connection): -## @example -## @group -## u ---------- ---------- -## --->| Bsys |---->| Asys |---> -## ---------- ---------- -## @end group -## @end example -## A warning occurs if there is direct feed-through -## from an input of Bsys or a continuous state of Bsys through a discrete -## output of Bsys to a continuous state or output in Asys (system data -## structure does not recognize discrete inputs). -## @end deftypefn - -## Author: John Ingram -## Created: July 1996 -## updated for variable number of arguments by A. S. Hodel July 1999 - -function sys = sysmult (...) - - if(nargin < 1) - usage("sysmult: sys = sysmult(Asys{,Bsys,...})"); - endif - - ## collect all arguments - arglist = list(); - va_start(); - for kk=1:nargin - arglist(kk) = va_arg(); - if(!is_struct(nth(arglist,kk))) - error("sysadd: argument %d is not a data structure",kk); - endif - endfor - - ## check system dimensions - [n,nz,mg,pg,Gyd] = sysdimensions(nth(arglist,1)); - for kk=2:nargin - [n,nz,mh,ph,Hyd] = sysdimensions(nth(arglist,kk)); - if(mh != pg) - error("arg %d has %d outputs; arg %d has vs %d inputs",kk,ph,kk-1,mg); - endif - [n,nz,mg,pg,Gyd] = sysdimensions(nth(arglist,kk)); # for next iteration - endfor - - ## perform the multiply - if(nargin == 2) - Asys = nth(arglist,1); Bsys = nth(arglist,2); - - [An,Anz,Am,Ap] = sysdimensions(Asys); - [Bn,Bnz,Bm,Bp] = sysdimensions(Bsys); - - [Aa,Ab,Ac,Ad,Atsam,An,Anz,Astname,Ainname,Aoutname,Ayd] = sys2ss(Asys); - [Ba,Bb,Bc,Bd,Btsam,Bn,Bnz,Bstname,Binname,Boutname,Byd] = sys2ss(Bsys); - - if(Byd) - ## check direct feed-through of inputs through discrete outputs - alist = find(Byd); - if(An) - bd = Ab(1:An)* Bd(alist,:); - if(norm(bd,1)) - warning("sysmult: inputs -> Bsys discrete outputs -> continous states of Asys"); - endif - endif - ## check direct feed-through of continuous state through discrete outputs - if(Bn) - bc = Ab(1:An)* Bc(alist,1:(Bn)); - if( norm(bc,1) ) - warning("sysmult: Bsys states -> Bsys discrete outputs -> continuous states of Asys"); - endif - endif - endif - - ## change signal names to avoid spurious warnings from sysgroup - Asys = syssetsignals(Asys,"in",sysdefioname(Am,"A_sysmult_tmp_name")); - Bsys = syssetsignals(Bsys,"out",sysdefioname(Bp,"B_sysmult_tmp_name")); - - sys = sysgroup(Asys,Bsys); - - ## connect outputs of B to inputs of A - sys = sysconnect(sys,Ap+(1:Bp),1:Am); - - ## now keep only outputs of A and inputs of B - sys = sysprune(sys,1:Ap,Am+(1:Bm)); - - else - ## multiple systems (or a single system); combine together one by one - sys = nth(arglist,1); - for kk=2:length(arglist) - sys = sysmult(sys,nth(arglist,kk)); - endfor - endif - -endfunction - diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/sysout.m --- a/scripts/control/sysout.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,151 +0,0 @@ -## Copyright (C) 1996 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## -*- texinfo -*- -## @deftypefn {Function File} {} sysout (@var{sys}@{, @var{opt}@}) -## print out a system data structure in desired format -## @table @var -## @item sys -## system data structure -## @item opt -## Display option -## @table @code -## @item [] -## primary system form (default); see @ref{sysgettype}. -## @item "ss" -## state space form -## @item "tf" -## transfer function form -## @item "zp" -## zero-pole form -## @item "all" -## all of the above -## @end table -## @end table -## @end deftypefn - -## Author: A. S. Hodel -## Created: 1995-1996 - -function retsys = sysout (sys, opt) - - if( (nargin < 1) || (nargin > 2) ) - usage("sysout(sys[,opt])"); - endif - - if(isempty(sys)) - retsys = sys; - warning("sysout: empty system") - return; - endif - - if(! is_struct(sys)) - disp("sysout: input must be a system structure") - endif - - ## set up output type array - if( nargin == 1 ) - opt = sysgettype(sys); - else - if( ! (strcmp(opt,"ss") + strcmp(opt,"tf") + ... - strcmp(opt,"zp") + strcmp(opt,"all") ) ) - error("opt must be one of [], \"ss\", \"tf\", \"zp\", or \"all\""); - endif - endif - - ## now check output for each form: - [nn,nz,mm,pp] = sysdimensions(sys); - if( mm > 0) - disp("Input(s)") - disp(outlist(sysgetsignals(sys,"in")," ")); - else - disp("Input(s): none"); - endif - if (pp > 0) - disp("Output(s):") - disp(outlist(sysgetsignals(sys,"out"), ... - " ",sysgetsignals(sys,"yd")) ); - else - disp("Output(s): none"); - endif - if(sysgettsam(sys) > 0) - disp(["Sampling interval: ",num2str(sysgettsam(sys))]); - str = "z"; - else - str = "s"; - endif - - ## transfer function form - if( strcmp(opt,"tf") + strcmp(opt,"all") ) - sys = sysupdate(sys,"tf"); #make sure tf is up to date - disp("transfer function form:") - [num,den] = sys2tf(sys); - tfout(num,den,str); - endif - - if( strcmp(opt,"zp") + strcmp(opt,"all") ) - sys = sysupdate(sys,"zp"); #make sure zp is up to date - disp("zero-pole form:") - [zer,pol,kk] = sys2zp(sys); - zpout(zer, pol, kk,str) - endif - - if( strcmp(opt,"ss") + strcmp(opt,"all") ) - sys = sysupdate(sys,"ss"); - disp("state-space form:"); - disp([num2str(nn)," continuous states, ", num2str(nz)," discrete states"]); - if( nn+nz > 0) - disp("State(s):") - xi = (nn+1):(nn+nz); - xd = zeros(1,nn+nz); - if(!isempty(xi)) - xd(xi) = 1; - endif - disp(outlist(sysgetsignals(sys,"st")," ",xd)); - else - disp("State(s): none"); - endif - - ## display matrix values? - dmat = (max( [ (nn+nz), mm, pp ] ) <= 32); - - printf("A matrix: %d x %d\n",sysdimensions(sys,"st"), - sysdimensions(sys,"st")); - [aa,bb,cc,dd] = sys2ss(sys); - if(dmat) disp(aa); endif - - printf("B matrix: %d x %d\n",sysdimensions(sys,"st"), - sysdimensions(sys,"in")); - if(dmat) disp(bb); endif - - printf("C matrix: %d x %d\n",sysdimensions(sys,"out"), - sysdimensions(sys,"st")); - if(dmat) disp(cc); endif - - printf("D matrix: %d x %d\n",sysdimensions(sys,"out"), - sysdimensions(sys,"in")); - if(dmat) disp(dd); endif - endif - - if(nargout >= 1) - retsys = sys; - endif - - ## restore global variable - -endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/sysprune.m --- a/scripts/control/sysprune.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,157 +0,0 @@ -## Copyright (C) 1996, 1998 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## -*- texinfo -*- -## @deftypefn {Function File} {@var{retsys} =} sysprune (@var{Asys}, @var{out_idx}, @var{in_idx}) -## Extract specified inputs/outputs from a system -## -## @strong{Inputs} -## @table @var -## @item Asys -## system data structure -## @item out_idx -## @itemx in_idx -## list of connections indices; the new -## system has outputs y(out_idx(ii)) and inputs u(in_idx(ii)). -## May select as [] (empty matrix) to specify all outputs/inputs. -## @end table -## -## @strong{Outputs} -## @var{retsys}: resulting system -## @example -## @group -## ____________________ -## u1 ------->| |----> y1 -## (in_idx) | Asys | (out_idx) -## u2 ------->| |----| y2 -## (deleted)-------------------- (deleted) -## @end group -## @end example -## @end deftypefn - -## Author: A. S. Hodel -## Created: August 1995 -## Updated by John Ingram 7-15-96 - -function sys = sysprune (sys, output_idx, input_idx, state_idx) - - if( nargin < 3 | nargin > 4 ) - usage("retsys = sysprune(sys,output_idx,input_idx{,state_idx})"); - elseif(nargin < 4) - state_idx = []; - endif - - ## default: no action - [nn,nz,mm,pp] = sysdimensions(sys); - if(isempty(output_idx)) output_idx = 1:pp; endif - if(isempty(input_idx)) input_idx = 1:mm; endif - if(isempty(state_idx)) state_idx = 1:(nn+nz); endif - - ## check dimensions - if( !(is_vector(output_idx) | isempty(output_idx) ) ) - if(!is_matrix(output_idx)) - error("sysprune: bad argument passed for output_idx"); - else - error("sysprune: output_idx (%d x %d) must be a vector or empty", ... - rows(output_idx),columns(output_idx)); - endif - elseif(is_duplicate_entry(output_idx)) - error("sysprune: duplicate entries found in output_idx"); - endif - - if( !(is_vector(input_idx) | isempty(input_idx) ) ) - if(!is_matrix(input_idx)) - error("sysprune: bad argument passed for input_idx"); - else - error("sysprune: input_idx (%d x %d) must be a vector or empty", ... - rows(input_idx),columns(input_idx)); - endif - elseif(is_duplicate_entry(input_idx)) - error("sysprune: duplicate entries found in input_idx"); - endif - - if( !(is_vector(state_idx) | isempty(state_idx) ) ) - if(!is_matrix(state_idx)) - error("sysprune: bad argument passed for state_idx"); - else - error("sysprune: state_idx (%d x %d) must be a vector or empty", ... - rows(state_idx),columns(state_idx)); - endif - elseif(nn+nz > 0) - if(is_duplicate_entry(state_idx)) - error("sysprune: duplicate entries found in state_idx"); - endif - endif - - lo = length(output_idx); - li = length(input_idx); - lst = length(state_idx); - - if( !is_struct(sys)) - error("Asys must be a system data structure (see ss2sys, tf2sys, or zp2sys)") - elseif(pp < lo) - error([num2str(lo)," output_idx entries, system has only ", ... - num2str(pp)," outputs"]); - elseif(mm < li) - error([num2str(li)," input_idx entries, system has only ", ... - num2str(mm)," inputs"]); - elseif(nn+nz < lst) - error([num2str(lst)," state_idx entries, system has only ", ... - num2str(nn+nz)," states"]); - endif - - [aa,bb,cc,dd,tsam,nn,nz,stnam,innam,outnam,yd] = sys2ss(sys); - - ## check for valid state permutation - if(nn & nz) - c_idx = find(state_idx <= nn); - if(!isempty(c_idx)) max_c = max(c_idx); - else max_c = 0; endif - d_idx = find(state_idx > nn); - if(!isempty(d_idx)) min_d = min(d_idx); - else min_d = nn+nz; endif - if(max_c > min_d) - warning("sysprune: state_idx(%d)=%d (discrete) preceeds", ... - min_d,state_idx(min_d)); - warning(" state_idx(%d)=%d (continuous)",... - max_c,state_idx(max_c)); - warning("sysprune: sys has %d continuous states, %d discrete states", ... - nn,nz); - error("continuous/discrete state partition not preserved ; see ss2sys"); - endif - endif - - idx = input_idx; - odx = output_idx; - if(isempty(state_idx)) - idx = []; - odx = []; - endif - aa = aa(state_idx,state_idx); - bb = bb(state_idx,idx); - cc = cc(odx,state_idx); - dd = dd(output_idx,input_idx); - yd = yd(output_idx); - - innam = innam(input_idx); - outnam = outnam(output_idx); - stnam = stnam(state_idx); - nn1 = length(find(state_idx <= nn)); - nz1 = length(find(state_idx > nn)); - sys = ss2sys(aa,bb,cc,dd,tsam,nn1,nz1,stnam,innam,outnam,find(yd)); -endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/sysreorder.m --- a/scripts/control/sysreorder.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,58 +0,0 @@ -## Copyright (C) 1996 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## -*- texinfo -*- -## @deftypefn {Function File} {@var{pv} =} sysreorder (@var{vlen}, @{var{list}) -## -## @strong{Inputs} -## @var{vlen}=vector length, @var{list}= a subset of @code{[1:vlen]}, -## -## @strong{Outputs} -## @var{pv}: a permutation vector to order elements of @code{[1:vlen]} in -## @code{list} to the end of a vector. -## -## Used internally by @code{sysconnect} to permute vector elements to their -## desired locations. -## @end deftypefn - -## Author: A. S. Hodel -## Created: August 1995 - -function pv = sysreorder (vlen, list) - - ## disp('sysreorder: entry') - - pv = 1:vlen; - ## make it a row vector - list = reshape(list,1,length(list)); - A = pv'*ones(size(list)); - B = ones(size(pv'))*list; - X = (A != B); - if(!is_vector(X)) - y = min(X'); - else - y = X'; - endif - z = find(y == 1); - if(!isempty(z)) - pv = [z, list]; - else - pv = list; - endif - -endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/sysrepdemo.m --- a/scripts/control/sysrepdemo.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,495 +0,0 @@ -## Copyright (C) 1996, 1998 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## -*- texinfo -*- -## @deftypefn {Function File} {} sysrepdemo -## Tutorial for the use of the system data structure functions. -## @end deftypefn - -## Author: A. S. Hodel -## Created: June 1995 -## Revised Aug 1995 for system data structure format - -function sysrepdemo () - - save_val = page_screen_output; - page_screen_output = 1; - - disp("System representation demo:") - num = [5, -1]; - denom = [1, -2, 6]; - a = b = c = []; - syschoice = -1; - ch_init = 2; - ch_extract = ch_init+1; - ch_update = ch_extract+1; - ch_view = ch_update+1; - ch_details = ch_view+1; - ch_quit = ch_details+1; - while(syschoice != ch_quit) - disp(" ") - syschoice = menu("Octave System Representation Menu", ... - "General overview of system representation (DO THIS FIRST)", ... - "Initialize a system (ss2sys, tf2sys, zp2sys)", ... - "Extract data from a system(sys2ss, sys2tf, sys2zp, etc.)", ... - "Update internal representation (sysupdate)", ... - "View the internal contents of a system (sysout)", ... - "Details of internal representation", ... - "Return to main menu"); - if(syschoice == 1) # general overview - disp("The Octave Control Systems Toolbox (OCST) was designed to") - disp("provide a simple user interface to a powerful set of tools.") - disp(" ") - disp(" ----------") - disp(" input(s) ---->| System | ---> output(s) ") - disp(" ----------") - disp(" ") - disp("Like other computer-aided control system design tools, the OCST") - disp("enables users to enter their descriptions of dynamic systems in ") - disp("their preferred form (state space, transfer function, or "); - disp("zero-pole format). "); - disp("The OCST stores system descriptions in a single variable data "); - disp("structure that allows for continuous time, discrete-time, or mixed "); - disp("(sampled-data) systems. "); - disp(" "); - disp("This single variable description of dynamic systems greatly simplifies "); - disp("both the code of the OCST as well as the user interface, since only") - disp("one variable is passed per system, regardless of the internal ") - disp("representation used in the data structure. As a result, the "); - disp("likelihood of user error is greatly reduced when calling OCST") - disp("functions. Further, all OCST functions have been written to") - disp("provide meaningful warning or error message to assist the user") - disp("in correcting their programming errors while using the OCST.") - disp("The details of the internal representation can be seen in "); - disp(["menu option ",num2str(ch_details)]); - disp("The data structure used in the OCST is called a \"system data structure.\""); - disp("A system data structure is contstructed with one of:") - disp(" fir2sys (FIR transfer function to system)") - disp(" ss2sys (state space matrices to system)") - disp(" tf2sys (SISO transfer function to system)") - disp(" zp2sys (SISO zero/pole/leading coefficient to system)") - disp(" ") - disp(["These functions are discussed in in menu option ",num2str(ch_init)]) - disp("The data in a system may be extracted using ") - disp(" sys2fir (FIR transfer function from system") - disp(" sys2ss (state space matrices from system)") - disp(" sys2tf (SISO transfer function from system)") - disp(" sys2zp (SISO zero/pole/leading coefficient from system)") - disp(" ") - disp(["These functions are discussed in menu option ", ... - num2str(ch_extract)]); - disp("Other options discussed under this menu are updating the internal") - disp("representation form of a system data structure with sysupdate and printing") - disp("the description of a dynamic system to the screen with sysout.") - disp(" ") - disp("Once the user is familiar with these commands, the rest of the ") - disp("OCST package will be quite easy to use.") - elseif(syschoice == ch_init) % Initialize - disp("Initialization of a system:"); - disp(" "); - formopt = 0; - while(formopt != 4) - disp("Three data formats may be used to initialize a system:") - formopt = menu("System data structure initialization menu", ... - "State space form (ss2sys)", ... - "Transfer function form (tf2sys)", ... - "zero-pole form (zp2sys)", ... - "Return to System representation menu"); - if(formopt == 1) - disp("State space representation of a system is based on the usual") - disp("multi-variable differential equations") - disp(" ") - disp(" . ") - disp(" x = A x + B u -or - x(k+1) = A x(k) + B u(k) ") - disp(" y = C x + D u y(k) = C x(k) + D u(k) ") - disp(" ") - disp("for matrices A, B, C, D of appropriate dimension.") - disp(" ") - ssopt = 0; - ssquit = 5; - while(ssopt < ssquit) - ssopt = menu("State space initialization examples", ... - "Double integrator example", ... - "Double delay (discrete-time) example", ... - "Summing junction (D-matrix only) example", ... - "ss2sys details (help ss2sys)", ... - "return to system initialization menu", ... - "return to system representation main menu"); - if(ssopt == 1) - disp("Example: construct a system representation of a") - disp("double integrator via state-space form") - cmd = "a = [0, 1; 0, 0];"; - run_cmd - cmd = "b = [0; 1];"; - run_cmd - cmd = "c = [1, 0];"; - run_cmd - cmd = "sys = ss2sys(a,b,c);"; - run_cmd - disp("The state space form of the system is seen via sysout:") - cmd = "sysout(sys)"; - run_cmd - disp("Notice that the Octave controls toolbox automatically") - disp("assigns names to the states, inputs and outputs,") - disp("and that the D matrix was filled in automatically.") - disp("We verify that it's a double integrator via sysout:") - cmd = "sysout(sys,""tf"")"; - run_cmd - prompt - elseif(ssopt == 2) - disp("Example: discrete-time double-delay:") - disp("This example is identical to the double-integrator,") - disp("except that it is a discrete-time system, and so has") - disp("a sampling interval. We arbitrarily select T=1e-3."); - cmd = "a = [0, 1; 0, 0];"; - run_cmd - cmd = "b = [0; 1];"; - run_cmd - cmd = "c = [1, 0];"; - run_cmd - cmd = "sys=ss2sys(a,b,c,[],1e-3);"; - run_cmd - cmd = "sysout(sys)"; - run_cmd - disp("Notice that the D matrix was filled in automatically.") - disp("This is done if D is input as the empty matrix.") - disp(" ") - disp("Notice also that the output y_1 is labelled as a discrete") - disp("output. The OCST data structure keeps track of states") - disp("and output signals that are produced by the discrete-time") - disp("portion of a system. Discrete states and outputs are ") - disp("implemented as shown in the block diagram below:") - disp(" ") - disp(" ") - disp(" _________ ________ x(kT) ________________") - disp("f(t)-->|sampler|-->| delay |----->|zero order hold| -->") - disp(" --------- -------- ----------------") - disp(" ") - disp(" ___________ _______________") - disp("f(t)-->| sampler |-->|zero-order hold| --> y(discrete)") - disp(" ----------- ---------------") - disp(" ") - disp("where f(t) is an input signal to either the output or the") - disp(" discrete state.") - disp(" ") - disp("The OCST does not implement samplers on inputs to continuous") - disp("time states (i.e., there are no samplers implicit in the B") - disp("or D matrices unless there are corresponding discrete") - disp("outputs or states. The OCST provides warning messages when") - disp("if this convention is violated.") - prompt - elseif(ssopt == 3) - disp("A summing junction that computes e(t) = r(t) - y(t) may be"); - disp("constructed as follows:"); - disp("First, we set the matrix D:") - cmd = "D = [1, -1];"; - run_cmd - disp("ss2sys allows the initialization of signal and state names") - disp("(see option 4), so we initialize these as follows:") - cmd = "inname = list(\"r(t)\",\"y(t)\");"; - run_cmd; - cmd = "outname = \"e(t)\";"; - run_cmd - disp("Since the system is continous time and without states,") - disp("the ss2sys inputs tsam, n, and nz are all zero:") - cmd = "sys = ss2sys([],[],[],D,0,0,0,[],inname,outname);"; - run_cmd - disp("The resulting system is:") - cmd = "sysout(sys)"; - run_cmd - disp("A discrete-time summing block can be implemented by setting") - disp("the sampling time positive:") - cmd = "sys = ss2sys([],[],[],D,1e-3,0,0,[],inname,outname);"; - run_cmd - disp("The resulting system is:") - cmd = "sysout(sys)"; - run_cmd - prompt - elseif(ssopt == 4) - help ss2sys - disp(" ") - disp(" ") - disp("Notice that state-space form allows a single system to have") - disp("both continuous and discrete-time states and to have both continuous") - disp("and discrete-time outputs. Since it's fairly easy to make an") - disp("error when mixing systems of this form, the Octave controls") - disp("toolbox attempts to print warning messages whenever something") - disp("questionable occurs.") - elseif(ssopt == 6) - formopt = 4; # return to main menu - endif - endwhile - elseif(formopt == 2) - tfopt = 0; - while(tfopt < 5) - tfopt = menu("Transfer function initialization menu", ... - "Continuous time initialization" , ... - "Discrete time initialization" , ... - "User specified signal names" , ... - "tf2sys details (help tf2sys)", ... - "Return to system initialization menu", ... - "Return to system representation main menu"); - if(tfopt == 1) # continuous time - disp("A transfer function is represented by vectors of the") - disp("coefficients of the numerator and denominator polynomials"); - disp(" ") - disp("For example: the transfer function"); - disp(" "); - num = [5, -1]; - denom = [1, -2, 6]; - tfout(num,denom); - disp(" ") - disp("is generated by the following commands:") - cmd = "num = [5, -1]"; - run_cmd - cmd = "denom = [1, -2, 6]"; - run_cmd - cmd = "sys = tf2sys(num,denom);"; - run_cmd - disp("alternatively, the system can be generated in a single command:"); - cmd = "sys = tf2sys([5, -1], [1, -2, 6]);"; - run_cmd - disp("Notice the output of sys: it is an Octave data structure.") - disp("The details of its member variables are explained under") - disp("System Representation Menu option 5 (the details of system form)") - disp(" "); - disp("The data structure can be observed with the sysout command:") - cmd = "sysout(sys)"; - run_cmd - disp("Notice that Octave assigns names to inputs and outputs.") - disp("The user may manually select input and output names; see option 3"); - prompt - elseif(tfopt == 2) # discrete time - disp("A transfer function is represented by vectors of the") - disp("coefficients of the numerator and denominator polynomials"); - disp("Discrete-time transfer functions require ") - disp("the additional parameter of a sampling period:") - cmd = "sys=tf2sys([5, -1], [1, 2, -6], 1e-3);"; - run_cmd - cmd = "sysout(sys)"; - run_cmd - disp("The OCST recognizes discrete-time transfer functions and") - disp("accordingly prints them with the frequency domain variable z."); - disp("Notice that Octave assigns names to inputs and outputs.") - disp("The user may set input and output names; see option 3"); - elseif(tfopt == 3) # user specified names - disp("The OCST requires all signals to have names. The OCST assigned default"); - disp("names to the signals in the other examples. We may initialize a transfer"); - disp("function with user-specified names as follows: Consider a simple ") - disp("double-integrator model of aircraft roll dynamics with ") - disp("input \"aileron angle\" and output \"theta\". A ") - disp("system for this model is generated by the command") - cmd = "aircraft=tf2sys(1, [1, 0, 0], 0,\"aileron angle\",\"theta\");"; run_cmd - disp("The sampling time parameter 0 indicates that the system") - disp("is continuous time. A positive sampling time indicates a") - disp("discrete-time system (or sampled data system).") - cmd = "sysout(aircraft)"; - run_cmd - disp("Notice that the user-selected signal names are listed.") - disp("These signal names are used in OCST plots and design functions."); - disp("(Run the frequency response demo to see an example of the use of "); - disp("signal names in plots.)") - prompt - elseif(tfopt == 4) # help - help tf2sys - prompt - elseif(tfopt == 6) # return to main menu - formopt = 4; - endif - endwhile - elseif (formopt == 3) - zpopt = 0; - while(zpopt < 5) - zpopt = menu("Zero-pole initialization menu", ... - "Continuous time initialization" , ... - "Discrete time initialization" , ... - "User specified signal names" , ... - "zp2sys details (help zp2sys)", ... - "Return to system initialization menu", ... - "Return to system representation main menu"); - if(zpopt == 1) # continuous time - disp("A zero-pole form representation of a system includes vectors") - disp("of the system poles and zeros and a scalar leading coefficient."); - disp(" ") - disp("For example: the transfer function"); - disp(" "); - k = 5; - num = [5, -1]; - denom = [1, -2, 6]; - zpout(num,denom,k); - disp(" ") - disp("is generated by the following commands:") - cmd = "num = [5, -1]"; - run_cmd - cmd = "denom = [1, -2, 6]"; - run_cmd - cmd = "k = 5"; - run_cmd - cmd = "sys = zp2sys(num,denom,k);"; - run_cmd - disp("alternatively, the system can be generated in a single command:"); - cmd = "sys = zp2sys([5, -1],[1, -2, 6],5);"; - run_cmd - disp("Notice the output of sys: it is an Octave data structure.") - disp("The details of its member variables are explained under") - disp("System Representation Menu option 5 (the details of system form)") - disp(" "); - disp("The data structure can be observed with the sysout command:") - cmd = "sysout(sys)"; - run_cmd - disp("Notice that Octave assigns names to inputs and outputs.") - disp("The user may manually select input and output names; see option 3"); - prompt - elseif(zpopt == 2) # discrete time - disp("A zero-pole form representation of a system includes vectors") - disp("of the system poles and zeros and a scalar leading coefficient."); - disp(" ") - disp("Discrete-time systems require the additional parameter of a sampling period:") - cmd = "sys=zp2sys([5, -1],[1, 2, -6],5,1e-3);"; - run_cmd - cmd = "sysout(sys)"; - run_cmd - disp("The OCST recognizes discrete-time transfer functions and") - disp("accordingly prints them with the frequency domain variable z."); - disp("Notice that Octave assigns names to inputs and outputs.") - disp("The user may set input and output names; see option 3"); - elseif(zpopt == 3) # user specified names - disp("The OCST requires all signals to have names. The OCST assigned default"); - disp("names to the signals in the other examples. We may initialize a transfer"); - disp("function with user-specified names as follows: Consider a simple ") - disp("double-integrator model of aircraft roll dynamics with ") - disp("input \"aileron angle\" and output \"theta\". A ") - disp("system for this model is generated by the command") - cmd = "aircraft=zp2sys([],[0, 0],1,0,\"aileron angle\",\"theta\");"; run_cmd - disp("The sampling time parameter 0 indicates that the system") - disp("is continuous time. A positive sampling time indicates a") - disp("discrete-time system (or sampled data system).") - cmd = "sysout(aircraft)"; - run_cmd - disp("Notice that the user-selected signal names are listed.") - disp("These signal names are used in OCST plots and design functions."); - disp("(Run the frequency response demo to see an example of the use of "); - disp("signal names in plots.)") - prompt - elseif(zpopt == 4) # help - help zp2sys - prompt - elseif(zpopt == 6) # return to main menu - formopt = 4; - endif - endwhile - endif - endwhile - elseif(syschoice == ch_extract) # extract system information - disp("Extract information from a system data structure in a selected format:") - disp("The actions of operations ss2sys, tf2sys, and zp2sys are reversed by") - disp("respective functions sys2ss, sys2tf, and sys2zp. The latter two"); - disp("functions are applicable only to SISO systems.") - formopt = 0; - while(formopt != 8) - formopt = menu("Extract system information", ... - "in state space form (sys2ss)", ... - "in transfer function form (sys2tf)", ... - "in zero pole form (sys2zp)", ... - "signal names (sysgetsignals,syssetsignals)", ... - "sampling time (sysgettsam)", ... - "signal dimensions (sysdimensions)", ... - "primary system type (sysgettype)", ... - "Return to system representation menu"); - if(formopt == 1) - help sys2ss - elseif(formopt == 2) - help sys2tf - elseif(formopt == 3) - help sys2zp - elseif(formopt == 4) - help sysgetsignals - cmd="sys=ss2sys(rand(4),rand(4,2),rand(3,4));"; - run_cmd - printf("Example: All signals names can be extracted by\n"); - cmd = "[Ast,Ain,Aout,Ayd] = sysgetsignals(sys)"; - run_cmd - printf("Example: Input signal names can be extracted as\n"); - cmd = "Ain = sysgetsignals(sys,\"in\")"; - run_cmd - printf("Example: The name of output signal 2 can be extracted as\n"); - cmd = "Aout = sysgetsignals(sys,\"out\",2)"; - run_cmd - printf("\nNotice that Aout is returned as a list; the signal name\n"); - printf("itself is obtained by specifying the input parameter strflg\n"); - cmd = "Aout = sysgetsignals(sys,\"out\",2,1)"; - run_cmd - prompt - cmd = "help syssetsignals"; - run_cmd - printf("Example: set input 2 name to \"motor voltage\"\n"); - cmd = "sys = syssetsignals(sys,\"in\",\"motor voltage\",2); sysout(sys)"; - run_cmd - - printf("Other syssetsignals demos are in the Block diagram demo program bddemo\n"); - elseif(formopt == 5) - help sysgettsam - elseif(formopt == 6) - help sysdimensions - elseif(formopt == 7) - help sysgettype - endif - prompt - endwhile - elseif(syschoice== ch_update) - disp("The OCST system data structure format will store a system in the same format") - disp("as that with which it was initialized. For example, consider the following:") - cmd = "sys=zp2sys([1, 2],[3, 4, 5],6)"; - run_cmd - disp(" ") - disp("Notice the internal variables in the structure include zer, pol, and k,") - disp("the required variables for zero-pole form. We can update the system") - disp("to include state-space form as follows:") - cmd = "sys = sysupdate(sys,\"ss\")"; - run_cmd - disp(" ") - disp("Now the sys data structure includes variables a, b, c, and d, as well") - disp("the default state names stname. sysupdate is usually used internally in") - disp("the OCST, but can be used manually if desired. A full description of") - disp("sysupdate is as follows:") - help sysupdate - prompt - elseif(syschoice == ch_view) - disp("The sysout command can be used to view a system in any desired format.") - disp("For example, consider the system created as follows:") - cmd = "aircraft=zp2sys(1,[0, 0],1,0,\"aileron angle\",\"theta\");"; run_cmd - disp("The system may be viewed in its default format (zero-pole) as follows") - cmd = "sysout(aircraft)"; - run_cmd - disp(" ") - disp("The system may be viewed in state-space or transfer function form as well:") - cmd = "sysout(aircraft,\"ss\")"; - run_cmd - cmd = "sysout(aircraft,\"tf\")"; - run_cmd - disp("A complete description of sysout is below:") - help sysout - prompt - elseif(syschoice == ch_details) - packedform - endif - - endwhile - page_screen_output = save_val; -endfunction - diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/sysscale.m --- a/scripts/control/sysscale.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,139 +0,0 @@ -## Copyright (C) 1996, 1998 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## -*- texinfo -*- -## @deftypefn {Function File} {@var{sys} =} sysscale (@var{sys}, @var{outscale}, @var{inscale}@{, @var{outname}, @var{inname}@}) -## scale inputs/outputs of a system. -## -## @strong{Inputs} -## sys: structured system -## outscale, inscale: constant matrices of appropriate dimension -## -## @strong{Outputs} -## @var{sys}: resulting open loop system: -## @example -## ----------- ------- ----------- -## u --->| inscale |--->| sys |--->| outscale |---> y -## ----------- ------- ----------- -## @end example -## If the input names and output names (each a list of strings) -## are not given and the scaling matrices -## are not square, then default names will be given to the inputs and/or -## outputs. -## -## A warning message is printed if outscale attempts to add continuous -## system outputs to discrete system outputs; otherwise @var{yd} is -## set appropriately in the returned value of @var{sys}. -## @end deftypefn - -## Author: A. S. Hodel -## Created: August 1995 -## modified by John Ingram 7-15-96 - -function sys = sysscale (sys, outscale, inscale, outname, inname) - - if( (nargin < 3) || (nargin > 5) ) - usage("retsys = sysscale(Asys,output_list,input_list{,inname,outname})"); - elseif (!is_struct(sys)) - error("sys must be a structured system"); - endif - - [nn,nz,mm,pp] = sysdimensions(sys); - - ## check for omitted scales - if(isempty(outscale)) outscale = eye(pp); endif - if(isempty(inscale)) inscale = eye(mm); endif - - ## check dimensions of scaling matrices - if(mm!=rows(inscale)) - error("inscale(%dx%d) should have %d rows(# system inputs)", ... - rows(inscale),columns(inscale),mm); - elseif( pp != columns(outscale) ) - error("outscale(%dx%d) should have %d columns(# system outputs)", ... - rows(outscale), columns(outscale),pp); - endif - - sysyd = sysgetsignals(sys,"yd"); - outc = find(sysyd==0); - outd = find(sysyd==1); - - if(length(outc) & length(outd)) - for ii = 1:rows(outscale) - nci = norm(outscale(ii,outc)); - ndi = norm(outscale(ii,outd)); - - if( nci & ndi) - warning("sysscale: outscale(%d,:) sums continuous and discrete outputs; setting output to cont",ii) - sysyd(ii) = 0; - else - sysyd(ii) = (ndi != 0); - endif - endfor - else - sysyd = ones(1,rows(outscale))*( length(outd) > 0); - endif - - ## check for SISO system type - if strcmp(sysgettype(sys),"tf") - [num,den,tsam,innam,outnam] = sys2tf(sys); - num = num*inscale*outscale; - sys = tf2sys(num,den,tsam,innam,outnam,find(sysyd)); - return - elseif strcmp(sysgettype(sys),"zp") - [zer,pol,kk,tsam,innam,outnam] = sys2zp(sys); - kk = kk*inscale*outscale; - sys = zp2sys(zer,pol,k,tsam,innam,outnam,find(sysyd)); - return - endif - - ## it's a state space system... - - [sysa,sysb,sysc,sysd,systsam, ... - sysn,sysnz,sysstname,sysinname,sysoutname,oldyd] = sys2ss(sys); - - sysb = sysb*inscale; - sysc = outscale*sysc; - sysd = outscale*sysd*inscale; - - if( !is_square(outscale) ) - ## strip extra output names (if any) - sysoutname = sysoutname(1:min(rows(outscale),columns(outscale))); - if( nargin < 4) - warning("sysscale: outscale not square, outname not specified"); - warning("sysscale: using default output names"); - outname = sysdefioname(rows(sysc),"y"); - endif - else - outname = sysoutname; - endif - if( !is_square(inscale) ) - ## strip extra output names (if any) - sysinname = sysinname(1:min(rows(inscale),columns(inscale))); - if(nargin < 5) - warning("sysscale: inscale not square, inname not specified"); - warning("sysscale: using default input names"); - inname = sysdefioname(columns(sysb),"u"); - endif - else - inname = sysgetsignals(sys,"in"); - endif - - sys = ss2sys(sysa,sysb,sysc,sysd,systsam,nn,nz,sysstname, ... - inname,outname,find(sysyd==1)); - -endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/syssetsignals.m --- a/scripts/control/syssetsignals.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,227 +0,0 @@ -## Copyright (C) 1996, 1998 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## -*- texinfo -*- -## @deftypefn {Function File} {@var{retsys} =} syssetsignals (@var{sys}, @var{opt}, @var{names}@{, @var{sig_idx}@}) -## change the names of selected inputs, outputs and states. -## @strong{Inputs} -## @table @var -## @item sys -## system data structure -## -## @item opt -## change default name (output) -## -## @table @code -## @item "out" -## change selected output names -## @item "in" -## change selected input names -## @item "st" -## change selected state names -## @item "yd" -## change selected outputs from discrete to continuous or -## from continuous to discrete. -## @end table -## -## @item names -## @table @code -## @item opt = "out", "in", or "st" -## string or string array containing desired signal names or values. -## @item opt = "yd" -## To desired output continuous/discrete flag. -## Set name to 0 for continuous, or 1 for discrete. -## @end table -## @item list -## vector of indices of outputs, yd, inputs, or -## states whose respective names should be changed. -## -## Default: replace entire list of names/entire yd vector. -## @end table -## @strong{Outputs} -## @var{retsys=sys} with appropriate signal names changed -## (or yd values, where appropriate) -## -## @strong{Example} -## @example -## octave:1> sys=ss2sys([1 2; 3 4],[5;6],[7 8]); -## octave:2> sys = syssetsignals(sys,"st",str2mat("Posx","Velx")); -## octave:3> sysout(sys) -## Input(s) -## 1: u_1 -## Output(s): -## 1: y_1 -## state-space form: -## 2 continuous states, 0 discrete states -## State(s): -## 1: Posx -## 2: Velx -## A matrix: 2 x 2 -## 1 2 -## 3 4 -## B matrix: 2 x 1 -## 5 -## 6 -## C matrix: 1 x 2 -## 7 8 -## D matrix: 1 x 1 -## 0 -## @end example -## @end deftypefn - -## Author: John Ingram -## Created: August 1996 - -function retsys = syssetsignals (sys, opt, names, sig_idx) - - if (nargin < 3 | nargin > 4) - usage("retsys=syssetsignals(sys,opt,names{,sig_idx})"); - elseif (!is_struct(sys)) - error("sys must be a system data structure"); - elseif (isempty(opt)) - opt = "out"; - elseif( ! isstr(opt) ) - error("opt must be a string"); - elseif( ! (strcmp(opt,"out") + strcmp(opt,"yd") + ... - strcmp(opt,"in") + strcmp(opt,"st") ) ) - error("opt must be one of [], ""out"", ""yd"", ""in"", or ""st"""); - elseif(nargin == 4) - if(min(size(sig_idx)) > 1) - disp("syssetsignals: sig_idx=") - disp(sig_idx); - error("sig_idx must be a vector") - endif - endif - - sig_vals = sysgetsignals(sys,opt); - - ## make sure it's in state space form if state names are given - if(strcmp(opt,"st")) sys = sysupdate(sys,"ss"); endif - - if(strcmp(opt,"yd") == 0) - ## it's a signal name list we're changing - if(!is_list(names)) - names = list(names); - endif - if(!is_signal_list(names)) - if(isstr(nth(names,1))) - warning("syssetsignals(opt=%s): converting string matrix \"names\" to a list of strings",opt); - tmpstr = nth(names,1); - for ii=1:rows(tmpstr) - names(ii) = deblank(tmpstr(ii,:)); - endfor - else - names - error("parameter \"names\" must be a list of strings"); - endif - endif - nsigs = length(sig_vals); - - if(nargin == 3) - ## replace all signal names - if(length(names) != nsigs) - error("opt=%s, sig_idx omitted: names(len=%d) should have %d entries ", ... - opt,length(names),nsigs); - endif - sig_idx = 1:nsigs; - elseif(length(names) != length(sig_idx)) - ## replace specified signal names - error("opt=%s, sig_idx(len=%d), names(len=%d) mismatch",opt, ... - length(sig_idx), length(names)); - endif - - for ii=1:length(sig_idx) - jj = sig_idx(ii); - if(jj < 1 | jj > nsigs | jj != floor(jj+0.5)) - error("opt=%s, sig_idx(%d)=%d, %e: must be an integer between 1 and %d", ... - opt, ii, jj, jj, nsigs); - endif - sig_vals(jj) = nth(names,ii); - endfor - - else - ## update yd - ## 1st check pathological case: no outputs - nout = sysdimensions(sys,"out"); - if(nout == 0) - if(nargin != 3) - error("opt=%s, %d outputs, sysgetsignals cannot take 4 arguments", ... - yd,nout); - endif - if(!isempty(names)) - error("opt=%s, %d outputs, names is not empty"); - endif - sigvals = []; - else - nsigs = length(sig_vals); - if(!is_vector(names)) - error("syssetsignals: opt=yd, names(%dx%d) must be a vector", ... - rows(names), columns(names)); - endif - if(nargin == 3) - if(length(names) != nsigs) - error("opt=yd, sig_idx omitted: names(%d) should be length(%d)", ... - length(names), nsigs); - endif - sig_idx = 1:nsigs; - elseif(length(names) != length(sig_idx)) - error("opt=yd: length(names)=%d, length(sig_idx)=%d",length(names), ... - length(sig_idx) ); - endif - - badidx = find(names != 0 & names != 1); - if(! isempty(badidx) ) - for ii=1:length(badidx) - warning("syssetsignals: opt=yd: names(%d)=%e, must be 0 or 1", ... - badidx(ii), names(badidx(ii)) ); - endfor - error ("opt=yd: invalid values in names"); - endif - - for ii=1:length(sig_idx) - jj = sig_idx(ii); - if(jj < 1 | jj > nsigs | jj != floor(jj)) - error("sig_idx(%d)=%d, %e: must be an integer between 1 and %d", ... - ii,jj, jj, nsigs); - endif - sig_vals(jj) = names(ii); - endfor - if(any(sig_vals == 1) & sysgettsam(sys) == 0) - warning("Setting system sampling time to 1"); - printf("syssetsignals: original system sampling time=0 but output(s)\n"); - disp(find(sig_vals==1)) - printf("are digital\n"); - sys = syschtsam(sys,1); - endif - - endif - endif - - if(strcmp(opt,"st")) - sys.stname = sig_vals; - elseif(strcmp(opt,"in")) - sys.inname = sig_vals; - elseif(strcmp(opt,"out")) - sys.outname = sig_vals; - elseif(strcmp(opt,"yd")) - sys.yd = sig_vals; - endif - - retsys = sys; - -endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/syssub.m --- a/scripts/control/syssub.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,116 +0,0 @@ -## Copyright (C) 1996, 1999 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## -*- texinfo -*- -## @deftypefn {Function File} {@var{sys} =} syssub (@var{Gsys}, @var{Hsys}) -## returns @math{sys = Gsys - Hsys} -## -## Method: @var{Gsys} and @var{Hsys} are connected in parallel -## The input vector is connected to both systems; the outputs are -## subtracted. Returned system names are those of @var{Gsys}. -## @example -## @group -## +--------+ -## +--->| Gsys |---+ -## | +--------+ | -## | +| -## u --+ (_)--> y -## | -| -## | +--------+ | -## +--->| Hsys |---+ -## +--------+ -## @end group -## @end example -## @end deftypefn - -## Author: John Ingram -## Created: July 1996 -## updated for variable numbers of input arguments by July 1999 A. S. Hodel - -function sys = syssub (...) - - if(nargin < 1) - usage("syssub: sys = syssub(Gsys{,Hsys,...})"); - endif - - ## collect all arguments - arglist = list(); - va_start(); - for kk=1:nargin - arglist(kk) = va_arg(); - if(!is_struct(nth(arglist,kk))) - error("syssub: argument %d is not a data structure",kk); - endif - endfor - - ## check system dimensions - [n,nz,mg,pg,Gyd] = sysdimensions(nth(arglist,1)); - for kk=2:nargin - [n,nz,mh,ph,Hyd] = sysdimensions(nth(arglist,kk)); - if(mg != mh) - error("arg 1 has %d inputs; arg %d has vs %d inputs",mg,kk,mh); - elseif(pg != ph) - error("arg 1 has %d outputs; arg %d has vs %d outputs",pg,kk,ph); - elseif(norm(Gyd - Hyd)) - warning("cannot add a discrete output to a continuous output"); - error("Output type mismatch: arguments 1 and %d\n",kk); - endif - endfor - - ## perform the subtract - if(nargin == 2) - Gsys = nth(arglist,1); Hsys = nth(arglist,2); - if( strcmp(sysgettype(Gsys),"tf") | strcmp(sysgettype(Hsys),"tf") ) - ## see if subtracting transfer functions with identical denominators - [Gnum,Gden,GT,Gin,Gout] = sys2tf(Gsys); - [Hnum,Hden,HT,Hin,Hout] = sys2tf(Hsys); - if(length(Hden) == length(Gden) ) - if( (Hden == Gden) & (HT == GT) ) - sys = tf2sys(Gnum+Hnum,Gden,GT,Gin,Gout); - return - endif - ## if not, we go on and do the usual thing... - endif - endif - - ## make sure in ss form - Gsys = sysupdate(Gsys,"ss"); - Hsys = sysupdate(Hsys,"ss"); - - ## change signal names to avoid warning messages from sysgroup - Gsys = syssetsignals(Gsys,"in",sysdefioname(length(Gin),"Gin_u")); - Gsys = syssetsignals(Gsys,"out",sysdefioname(length(Gout),"Gout_u")); - Hsys = syssetsignals(Hsys,"in",sysdefioname(length(Hin),"Hin_u")); - Hsys = syssetsignals(Hsys,"out",sysdefioname(length(Hout),"Hout_u")); - - sys = sysgroup(Gsys,Hsys); - - eyin = eye(mg); - eyout = eye(pg); - - sys = sysscale (sys, [eyout, -eyout], [eyin; eyin], Gout, Gin); - - else - ## multiple systems (or a single system); combine together one by one - sys = nth(arglist,1); - for kk=2:length(arglist) - sys = syssub(sys,nth(arglist,kk)); - endfor - endif - -endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/system/fir2sys.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/system/fir2sys.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,105 @@ +## Copyright (C) 1996, 1998 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{sys} =} fir2sys (@var{num}@{, @var{tsam}, @var{inname}, @var{outname} @}) +## construct a system data structure from FIR description +## +## @strong{Inputs:} +## @table @var +## @item num +## vector of coefficients @math{[c_0 c_1 ... c_n]} +## of the SISO FIR transfer function +## @ifinfo +## +## C(z) = c0 + c1*z^@{-1@} + c2*z^@{-2@} + ... + znz^@{-n@} +## +## @end ifinfo +## @iftex +## @tex +## $$C(z) = c0 + c1*z^{-1} + c2*z^{-2} + ... + znz^{-n}$$ +## @end tex +## @end iftex +## +## @item tsam +## sampling time (default: 1) +## +## @item inname +## name of input signal; may be a string or a list with a single entry. +## +## @item outname +## name of output signal; may be a string or a list with a single entry. +## @end table +## +## @strong{Outputs} +## @var{sys} (system data structure) +## +## @strong{Example} +## @example +## octave:1> sys = fir2sys([1 -1 2 4],0.342,"A/D input","filter output"); +## octave:2> sysout(sys) +## Input(s) +## 1: A/D input +## +## Output(s): +## 1: filter output (discrete) +## +## Sampling interval: 0.342 +## transfer function form: +## 1*z^3 - 1*z^2 + 2*z^1 + 4 +## ------------------------- +## 1*z^3 + 0*z^2 + 0*z^1 + 0 +## @end example +## @end deftypefn + +## Author: R. Bruce Tenison +## Created: July 29, 1994 +## Name changed to TF2SYS July 1995 +## updated for new system data structure format July 1996 +## adapted from tf2sys july 1996 + +function sys = fir2sys (num, tsam, inname, outname) + + ## Test for the correct number of input arguments + if (nargin < 1 | nargin > 4) + usage ("sys = fir2sys(num [, tsam, inname, outname])"); + endif + + ## let tf2sys do the argument checking + den = [1,zeros(1,length(num)-1)]; + + ## check sampling interval (if any) + if (nargin <= 1) + tsam = 1; # default + elseif (isempty(tsam)) + tsam = 1; + endif + + ## Set name of input + if (nargin < 3) + inname = sysdefioname (1, "u"); + endif + + ## Set name of output + if (nargin < 4) + outname = sysdefioname (1, "y"); + endif + + sys = tf2sys (num, den, tsam, inname, outname); + +endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/system/packedform.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/system/packedform.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,95 @@ +## Copyright (C) 1996, 1998 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +save_var = page_screen_output; +page_screen_output = 1; +disp("Description of system data structure:") +disp("A linear system is stored in a structure, and may be represented in") +disp("ss (state space), tf (transfer function), and/or zp (zero-pole-gain)") +disp("form.") +disp(" ") +disp("variables in all representations:") +disp("inname: list of signal names (strings) containing name(s) of system ") +disp(" inputs; see is_signal_list"); +disp("n: number of continuous states") +disp("nz: number of discrete states") +disp("outname: list of signal names (strings) containing name(s) of system ") +disp(" outputs"); +disp(" ") +disp("variables in all representations:(cont'd)") +disp("sys: system status vector. This vector indicates both what") +disp(" representation was used to initialize the system data structure") +disp(" (called the primary system type) and which other representations") +disp(" are currently up-to-date with the primary system type.") +disp(" sys(0): primary system type") +disp(" =0 for tf form") +disp(" =1 for zp form") +disp(" =2 for ss form") +disp(" sys(1:3): indicate whether tf, zp, or ss, respectively, are") +disp(" \"up to date\" (whether it is safe to use the variables") +disp(" associated with these representations)") +disp(" sys(1): = 1 if tf variables are up to date") +disp(" = 0 else"); +disp(" sys(2): = 1 if zp variables are up to date") +disp(" = 0 else"); +disp(" sys(3): = 1 if ss variables are up to date") +disp(" = 0 else"); +disp("You can update alternative representations internally with the") +disp("sysupdate command:") +disp(" ") +help sysupdate +disp("===============================") +disp("More variables common to all representations in system data structures:"); +disp("tsam: discrete time sampling interval ") +disp(" =0 if system is purely continuous"); +disp(" >0 if system has discrete-time states or outputs"); +disp("yd: vector indicating which outputs are discrete time (i.e.,") +disp(" produced by D/A converters) and which are continuous time.") +disp(" yd(ii) = 0 if output ii is continuous, = 1 if discrete.") +disp(" ") +disp("===============================") +disp("variables in tf representations (SISO only):") +disp("num: vector of numerator coefficients") +disp("den: vector of denominator coefficients") +disp(" ") +disp("===============================") +disp("variables in zp representations (SISO only):") +disp("zer: vector of system zeros") +disp("pol: vector of system poles") +disp("k: system leading coefficient") +disp(" ") +disp("===============================") +disp("variables in ss representations:") +disp("a,b,c,d: usual state-space matrices. If a system has both") +disp(" continuous and discrete states, they are sorted so that") +disp(" continuous states come first, then discrete states") +disp(" ") +disp("WARNING: some functions (e.g., bode) will not accept systems") +disp("with both discrete and continuous states/outputs") +disp("stname: list of signal names (strings) containing name(s) of system ") +disp(" states"); +disp("===============================") +disp("Object oriented programming:") +disp("It is recommended that users do not directly access the internal") +disp("variables themselves, but use the interface functions") +disp(" fir2sys ss2sys tf2sys sys2fir") +disp(" sys2ss sys2tf sys2zp syschtsam") +disp(" sysdimensions sysgetsignals syssetsignals sysgettype") +disp(" zp2sys") +disp("to create/access internal variables. "); +page_screen_output = save_var; diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/system/parallel.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/system/parallel.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,66 @@ +## Copyright (C) 1996 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## function sysp = parallel(Asys,Bsys) +## Forms the parallel connection of two systems. +## +## ____________________ +## | ________ | +## u ----->|----> | Asys |--->|----> y1 +## | | -------- | +## | | ________ | +## |--->|----> | Bsys |--->|----> y2 +## | -------- | +## -------------------- +## Ksys + +## Author: David Clem +## Created: August 15, 1994 +## completely rewritten Oct 1996 a s hodel +## SYS_INTERNAL accesses members of system structure + +function sysp = parallel (Asys, Bsys) + + if(nargin != 2) + usage("sysp = parallel(Asys,Bsys)"); + endif + if(! is_struct(Asys) ) + error("1st input argument is not a system data structure") + elseif (! is_struct(Bsys) ) + error("2nd input argument is not a system data structure") + endif + [Ann,Anz,mA] = sysdimensions(Asys); + [Bnn,Bnz,mB] = sysdimensions(Bsys); + if(mA != mB) + error(["Asys has ",num2str(mA)," inputs, Bsys has ",num2str(mB)," inputs"]); + endif + + ## save signal names + Ain = sysgetsignals(Asys,"in"); + + ## change signal names to avoid warning messages from sysgroup + Asys = syssetsignals(Asys,"in",sysdefioname(length(Ain),"Ain_u")); + Bsys = syssetsignals(Bsys,"in",sysdefioname(length(Ain),"Bin_u")); + + sysp = sysgroup(Asys,Bsys); + sysD = ss2sys([],[],[],[eye(mA);eye(mA)]); + + sysp = sysmult(sysp,sysD); + sysp = syssetsignals(sysp,"in",Ain); + +endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/system/ss2sys.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/system/ss2sys.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,287 @@ +## Copyright (C) 1996, 1998 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{sys} =} ss2sys (@var{a}, @var{b}, @var{c}@{,@var{d}, @var{tsam}, @var{n}, @var{nz}, @var{stname}, @var{inname}, @var{outname}, @var{outlist}@}) +## Create system structure from state-space data. May be continous, +## discrete, or mixed (sampeled-data) +## +## @strong{Inputs} +## @table @var +## @item a +## @itemx b +## @itemx c +## @itemx d +## usual state space matrices. +## +## default: @var{d} = zero matrix +## +## @item tsam +## sampling rate. Default: @math{tsam = 0} (continuous system) +## +## @item n +## @itemx nz +## number of continuous, discrete states in the system +## +## If @var{tsam} is 0, @math{n = @code{rows}(@var{a})}, @math{nz = 0}. +## +## If @var{tsam} is greater than zero, @math{n = 0}, +## @math{nz = @code{rows}(@var{a})} +## +## see below for system partitioning +## +## @item stname +## list of strings of state signal names +## +## default (@var{stname}=[] on input): @code{x_n} for continuous states, +## @code{xd_n} for discrete states +## +## @item inname +## list of strings of input signal names +## +## default (@var{inname} = [] on input): @code{u_n} +## +## @item outname +## list of strings of input signal names +## +## default (@var{outname} = [] on input): @code{y_n} +## +## @item outlist +## +## list of indices of outputs y that are sampled +## +## If @var{tsam} is 0, @math{outlist = []}. +## +## If @var{tsam} is greater than 0, @math{outlist = 1:@code{rows}(@var{c})}. +## @end table +## +## Unlike states, discrete/continous outputs may appear in any order. +## +## @strong{Note} @code{sys2ss} returns a vector @var{yd} where +## @var{yd}(@var{outlist}) = 1; all other entries of @var{yd} are 0. +## +## @strong{Outputs} +## @var{outsys} = system data structure +## +## @strong{System partitioning} +## +## Suppose for simplicity that outlist specified +## that the first several outputs were continuous and the remaining outputs +## were discrete. Then the system is partitioned as +## @example +## @group +## x = [ xc ] (n x 1) +## [ xd ] (nz x 1 discrete states) +## a = [ acc acd ] b = [ bc ] +## [ adc add ] [ bd ] +## c = [ ccc ccd ] d = [ dc ] +## [ cdc cdd ] [ dd ] +## +## (cdc = c(outlist,1:n), etc.) +## @end group +## @end example +## with dynamic equations: +## @ifinfo +## @math{ d/dt xc(t) = acc*xc(t) + acd*xd(k*tsam) + bc*u(t)} +## +## @math{ xd((k+1)*tsam) = adc*xc(k*tsam) + add*xd(k*tsam) + bd*u(k*tsam)} +## +## @math{ yc(t) = ccc*xc(t) + ccd*xd(k*tsam) + dc*u(t)} +## +## @math{ yd(k*tsam) = cdc*xc(k*tsam) + cdd*xd(k*tsam) + dd*u(k*tsam)} +## @end ifinfo +## @iftex +## @tex +## $$\eqalign{ +## {d \over dt} x_c(t) +## & = a_{cc} x_c(t) + a_{cd} x_d(k*t_{sam}) + bc*u(t) \cr +## x_d((k+1)*t_{sam}) +## & = a_{dc} x_c(k t_{sam}) + a_{dd} x_d(k t_{sam}) + b_d u(k t_{sam}) \cr +## y_c(t) +## & = c_{cc} x_c(t) + c_{cd} x_d(k t_{sam}) + d_c u(t) \cr +## y_d(k t_{sam}) +## & = c_{dc} x_c(k t_{sam}) + c_{dd} x_d(k t_{sam}) + d_d u(k t_{sam}) +## }$$ +## @end tex +## @end iftex +## +## @strong{Signal partitions} +## @example +## @group +## | continuous | discrete | +## ---------------------------------------------------- +## states | stname(1:n,:) | stname((n+1):(n+nz),:) | +## ---------------------------------------------------- +## outputs | outname(cout,:) | outname(outlist,:) | +## ---------------------------------------------------- +## @end group +## @end example +## where @math{cout} is the list of in 1:@code{rows}(@var{p}) +## that are not contained in outlist. (Discrete/continuous outputs +## may be entered in any order desired by the user.) +## +## @strong{Example} +## @example +## octave:1> a = [1 2 3; 4 5 6; 7 8 10]; +## octave:2> b = [0 0 ; 0 1 ; 1 0]; +## octave:3> c = eye(3); +## octave:4> sys = ss2sys(a,b,c,[],0,3,0,list("volts","amps","joules")); +## octave:5> sysout(sys); +## Input(s) +## 1: u_1 +## 2: u_2 +## +## Output(s): +## 1: y_1 +## 2: y_2 +## 3: y_3 +## +## state-space form: +## 3 continuous states, 0 discrete states +## State(s): +## 1: volts +## 2: amps +## 3: joules +## +## A matrix: 3 x 3 +## 1 2 3 +## 4 5 6 +## 7 8 10 +## B matrix: 3 x 2 +## 0 0 +## 0 1 +## 1 0 +## C matrix: 3 x 3 +## 1 0 0 +## 0 1 0 +## 0 0 1 +## D matrix: 3 x 3 +## 0 0 +## 0 0 +## 0 0 +## @end example +## Notice that the @var{D} matrix is constructed by default to the +## correct dimensions. Default input and output signals names were assigned +## since none were given. +## @end deftypefn + +## Author: John Ingram +## Created: July 20, 1996 + +function retsys = ss2sys (a, b, c, d, tsam, n, nz, stname, inname, outname, outlist) + + ## Test for correct number of inputs + if ((nargin < 3) | (nargin > 11)) + usage("retsys = ss2sys (a,b,c{,d,tsam,n,nz,stname,inname,outname,outlist})"); + endif + + ## verify A, B, C, D arguments + ## If D is not specified, set it to a zero matrix of appriate dimension. + if (nargin == 3) d = zeros(rows(c) , columns(b)); + elseif (isempty(d)) d = zeros(rows(c) , columns(b)); endif + + ## Check the dimensions + [na,m,p] = abcddim(a,b,c,d); + + ## If dimensions are wrong, exit function + if (m == -1) + error("a(%dx%d), b(%dx%d), c(%dx%d), d(%dx%d); incompatible", ... + rows(a), columns(a), rows(b), columns(b), rows(c), columns(c), ... + rows(d), columns(d)); + endif + + ## check for tsam input + if(nargin < 5) tsam = 0; + elseif( !( is_sample(tsam) | (tsam == 0) ) ) + error("tsam must be a nonnegative real scalar"); + endif + + ## check for continuous states + if( (nargin < 6) & (tsam == 0) ) n = na; + elseif(nargin < 6) n = 0; + elseif((!is_matrix(n)) | isstr(n)) + error("Parameter n is not a numerical value."); + elseif( (!is_scalar(n)) | (n < 0 ) | (n != round(n)) ) + if(is_scalar(n)) error("invalid value of n=%d,%e",n,n); + else error("invalid value of n=(%dx%d)", ... + rows(n), columns(n)); endif + endif + + ## check for num discrete states + if( (nargin < 7) & (tsam == 0)) nz = 0; + elseif(nargin < 7) nz = na - n; + elseif((!is_matrix(nz)) | isstr(nz)) + error("Parameter nz is not a numerical value."); + elseif( (!is_scalar(nz)) | (nz < 0 ) | (nz != round(nz)) ) + if(is_scalar(nz)) + error(["invalid value of nz=",num2str(nz)]); + else + error(["invalid value of nz=(",num2str(rows(nz)),"x", ... + num2str(columns(nz)),")"]); + endif + endif + + ## check for total number of states + if( (n + nz) != na ) + error(["invalid: a is ",num2str(na),"x",num2str(na),", n=", ... + num2str(n),", nz=",num2str(nz)]); + endif + + ## construct system with default names + retsys.a = a; + retsys.b = b; + retsys.c = c; + retsys.d = d; + + retsys.n = n; + retsys.nz = nz; + retsys.tsam = tsam; + retsys.yd = zeros(1,p); # default value entered below + + ## Set the system vector: active = 2(ss), updated = [0 0 1]; + retsys.sys = [2, 0, 0, 1]; + + retsys.stname = sysdefstname(n,nz); + retsys.inname = sysdefioname(m,"u"); + retsys.outname = sysdefioname(p,"y"); + + ## check for state names + if(nargin >= 8) + if(!isempty(stname)) retsys = syssetsignals(retsys,"st",stname); endif + endif + + ## check for input names + if(nargin >= 9) + if(!isempty(inname)) retsys = syssetsignals(retsys,"in",inname); endif + endif + + ## check for output names + if(nargin >= 10) + if(!isempty(outname)) retsys = syssetsignals(retsys,"out",outname); endif + endif + + ## set up yd + if(nargin < 11) + retsys = syssetsignals(retsys,"yd",ones(1,p)*(tsam > 0)); + else + if(!isempty(outlist)) + retsys = syssetsignals(retsys,"yd",ones(size(outlist)),outlist); + endif + endif + +endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/system/ss2tf.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/system/ss2tf.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,80 @@ +## Copyright (C) 1996 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{outputs} =} ss2tf (@var{inputs}) +## @format +## [num,den] = ss2tf(a,b,c,d) +## Conversion from tranfer function to state-space. +## The state space system +## . +## x = Ax + Bu +## y = Cx + Du +## +## is converted to a transfer function +## +## num(s) +## G(s)=------- +## den(s) +## +## used internally in system data structure format manipulations +## @end format +## @end deftypefn + +## Author: R. Bruce Tenison +## Created: June 24, 1994 +## a s hodel: modified to allow for pure gain blocks Aug 1996 + +function [num, den] = ss2tf (a, b, c, d) + + ## Check args + [n,m,p] = abcddim(a,b,c,d); + if (n == -1) + num = []; + den = []; + error("ss2tf: Non compatible matrix arguments"); + elseif ( (m != 1) | (p != 1)) + num = []; + den = []; + error(["ss2tf: not SISO system: m=",num2str(m)," p=",num2str(p)]); + endif + + if(n == 0) + ## gain block only + num = d; + den = 1; + else + ## First, get the denominator coefficients + den = poly(a); + + ## Get the zeros of the system + [zz,g] = tzero(a,b,c,d); + + ## Form the Numerator (and include the gain) + if (!isempty(zz)) + num = g * poly(zz); + else + num = g; + endif + + ## the coefficients must be real + den = real(den); + num = real(num); + endif +endfunction + diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/system/ss2zp.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/system/ss2zp.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,59 @@ +## Copyright (C) 1996 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{outputs} =} ss2zp (@var{inputs}) +## @format +## Converts a state space representation to a set of poles and zeros. +## +## [pol,zer,k] = ss2zp(a,b,c,d) returns the poles and zeros of the state space +## system (a,b,c,d). K is a gain associated with the zeros. +## +## used internally in system data structure format manipulations +## @end format +## @end deftypefn + +## Author: David Clem +## Created: August 15, 1994 +## Hodel: changed order of output arguments to zer, pol, k. July 1996 +## a s hodel: added argument checking, allow for pure gain blocks aug 1996 + +function [zer, pol, k] = ss2zp (a, b, c, d) + + if(nargin != 4) + usage("[zer,pol,k] = ss2zp(a,b,c,d)"); + endif + + [n,m,p] = abcddim(a,b,c,d); + if (n == -1) + error("ss2tf: Non compatible matrix arguments"); + elseif ( (m != 1) | (p != 1)) + error(["ss2tf: not SISO system: m=",num2str(m)," p=",num2str(p)]); + endif + + if(n == 0) + ## gain block only + k = d; + zer = pol = []; + else + ## First, get the denominator coefficients + [zer,k] = tzero(a,b,c,d); + pol = eig(a); + endif +endfunction + diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/system/sys2fir.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/system/sys2fir.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,52 @@ +## Copyright (C) 1996 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## -*- texinfo -*- +## @deftypefn {Function File} {[@var{c}, @var{tsam}, @var{input}, @var{output}] =} sys2fir (@var{sys}) +## +## Extract FIR data from system data structure; see @ref{fir2sys} for +## parameter descriptions. +## @end deftypefn +## @seealso{fir2sys} + +## Author: A. S. Hodel +## Created: July 1996 + +function [c, tsam, inname, outname] = sys2fir (sys) + + ## let sys2tf do most of the work + + [num,den,tsam,inname,outname] = sys2tf(sys); + + alph = den(1); # scale to get monic denominator + den = den/alph; + num = num/alph; + l = length(den); + m = length(num); + if( norm(den(2:l)) ) + sysout(sys,"tf"); + error("denominator has poles away from origin"); + elseif( !is_digital(sys) ) + error("system must be discrete-time to be FIR"); + elseif(m != l) + warning(["sys2fir: deg(num) - deg(den) = ",num2str(m-l), ... + "; coefficients must be shifted"]); + endif + c = num; +endfunction + diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/system/sys2ss.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/system/sys2ss.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,107 @@ +## Copyright (C) 1996, 1998 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## -*- texinfo -*- +## @deftypefn {Function File} {[@var{a}, @var{b}, @var{c}, @var{d}, @var{tsam},@var{n}, @var{nz}, @var{stname}, @var{inname}, @var{outname}, @var{yd}] =} sys2ss (@var{sys}) +## Extract state space representation from system data structure. +## +## @strong{Inputs} +## @var{sys} system data structure (@pxref{sysstruct}) +## +## @strong{Outputs} +## @table @var +## @item a +## @itemx b +## @itemx c +## @itemx d +## state space matrices for sys +## +## @item tsam +## sampling time of sys (0 if continuous) +## +## @item n +## @itemx nz +## number of continuous, discrete states (discrete states come +## last in state vector @var{x}) +## +## @item stname +## @itemx inname +## @itemx outname +## signal names (lists of strings); names of states, +## inputs, and outputs, respectively +## +## @item yd +## binary vector; @var{yd}(@var{ii}) is 1 if output @var{y}(@var{ii})$ +## is discrete (sampled); otherwise @var{yd}(@var{ii}) 0. +## +## @end table +## A warning massage is printed if the system is a mixed +## continuous and discrete system +## +## @strong{Example} +## @example +## octave:1> sys=tf2sys([1 2],[3 4 5]); +## octave:2> [a,b,c,d] = sys2ss(sys) +## a = +## 0.00000 1.00000 +## -1.66667 -1.33333 +## b = +## 0 +## 1 +## c = 0.66667 0.33333 +## d = 0 +## @end example +## @end deftypefn + +## Author: David Clem +## Created: August 19, 1994 +## Updates by John Ingram July 14, 1996 + +function [a, b, c, d, tsam, n, nz, stname, inname, outname, yd] = sys2ss (sys) + + if(nargin != 1) + usage("[a,b,c,d,tsam,n,nz,stname,inname,outname,yd] = sys2ss(sys)") + endif + + if (nargout > 11) + warning(["sys2ss: ",num2str(nargout)," out arguments exceeds max=11"]) + usage("[a,b,c,d,tsam,n,nz,stname,inname,outname,yd] = sys2ss(sys)") + endif + + if( ! is_struct(sys) ) + error("input argument must be a system data structure"); + endif + + sys = sysupdate(sys,"ss"); # make sure state space data is there + [n,nz,m,p] = sysdimensions(sys); + [stname,inname,outname,yd] = sysgetsignals(sys); + tsam = sysgettsam(sys); + + cont = sum(yd == 0) + n; + dig = sum(yd != 0) + nz + tsam; + if(cont*dig) + warning("sys2ss: input system is mixed continuous/discrete"); + endif + + a = sys.a; + b = sys.b; + c = sys.c; + d = sys.d; + +endfunction + diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/system/sys2tf.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/system/sys2tf.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,63 @@ +## Copyright (C) 1996 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## -*- texinfo -*- +## @deftypefn {Function File} {[@var{num}, @var{den}, @var{tsam}, @var{inname}, @var{outname}] =} sys2tf (@var{sys}) +## Extract transfer function data from a system data structure +## +## See @ref{tf2sys} for parameter descriptions. +## +## @strong{Example} +## @example +## octave:1> sys=ss2sys([1 -2; -1.1,-2.1],[0;1],[1 1]); +## octave:2> [num,den] = sys2tf(sys) +## num = 1.0000 -3.0000 +## den = 1.0000 1.1000 -4.3000 +## @end example +## @end deftypefn + +## Author: R. Bruce Tenison +## Created: June 24, 1994 +## modified to make sys2tf by A. S. Hodel Aug 1995 +## modified again for updated system format by John Ingram July 1996 + +function [num, den, tsam, inname, outname] = sys2tf (Asys) + + if(nargin != 1) + usage("[num,den,tsam,inname,outname] = sys2tf(Asys)"); + endif + + if( !is_struct(Asys)) + error("Asys must be a system data structure (see ss2sys, tf2sys, zp2sys)"); + elseif (! is_siso(Asys) ) + [n, nz, m, p] = sysdimensions(Asys); + error(["system is not SISO (",num2str(m)," inputs, ... + ", num2str(p)," outputs"]); + endif + + Asys = sysupdate(Asys,"tf"); # just in case + + num = Asys.num; + den = Asys.den; + + tsam = sysgettsam(Asys); + inname = sysgetsignals(Asys,"in"); + outname = sysgetsignals(Asys,"out"); + +endfunction + diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/system/sys2zp.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/system/sys2zp.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,65 @@ +## Copyright (C) 1996 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## -*- texinfo -*- +##@deftypefn {Function File} {[@var{zer}, @var{pol}, @var{k}, @var{tsam}, @var{inname}, @var{outname}] =} sys2zp (@var{sys}) +## Extract zero/pole/leading coefficient information from a system data +## structure +## +## See @ref{zp2sys} for parameter descriptions. +## +## @strong{Example} +## @example +## octave:1> sys=ss2sys([1 -2; -1.1,-2.1],[0;1],[1 1]); +## octave:2> [zer,pol,k] = sys2zp(sys) +## zer = 3.0000 +## pol = +## -2.6953 +## 1.5953 +## k = 1 +## @end example +## @end deftypefn + +## Author: John Ingram +## Created: July 15, 1996 + +function [zer, pol, k, tsam, inname, outname] = sys2zp (sys) + + if(nargin != 1) + usage("[zer,pol,k,tsam,inname,outname] = sys2zp(sys)"); + elseif( !is_struct(sys)) + error("sysconnect: sys must be in system data structure form") + elseif (! is_siso(sys) ) + [n, nz, m, p] = sysdimensions(sys); + error(["system is not SISO (",num2str(m)," inputs, ... + ", num2str(p)," outputs"]); + endif + + ## update zero-pole form + sys = sysupdate(sys,"zp"); + + zer = sys.zer; + pol = sys.pol; + k = sys.k; + tsam = sysgettsam(sys); + inname = sysgetsignals(sys,"in"); + outname = sysgetsignals(sys,"out"); + +endfunction + + diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/system/sysadd.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/system/sysadd.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,118 @@ +## Copyright (C) 1996, 1999 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{sys} =} sysadd (@var{Gsys}, @var{Hsys}) +## returns @var{sys} = @var{Gsys} + @var{Hsys}. +## @itemize @bullet +## @item Exits with +## an error if @var{Gsys} and @var{Hsys} are not compatibly dimensioned. +## @item Prints a warning message is system states have identical names; +## duplicate names are given a suffix to make them unique. +## @item @var{sys} input/output names are taken from @var{Gsys}. +## @end itemize +## @example +## @group +## ________ +## ----| Gsys |--- +## u | ---------- +| +## ----- (_)----> y +## | ________ +| +## ----| Hsys |--- +## -------- +## @end group +## @end example +## @end deftypefn + +## Author: John Ingram +## Created: July 1996 +## Updated for variable number of arguments July 1999 A. S. Hodel + +function sys = sysadd (...) + + if(nargin < 1) + usage("sysadd: sys = sysysadd(Gsys{,Hsys, ...})"); + endif + + ## collect all arguments + arglist = list(); + va_start(); + for kk=1:nargin + arglist(kk) = va_arg(); + if(!is_struct(nth(arglist,kk))) + error("sysadd: argument %d is not a data structure",kk); + endif + endfor + + ## check system dimensions + [n,nz,mg,pg,Gyd] = sysdimensions(nth(arglist,1)); + for kk=2:nargin + [n,nz,mh,ph,Hyd] = sysdimensions(nth(arglist,kk)); + if(mg != mh) + error("arg 1 has %d inputs; arg %d has vs %d inputs",mg,kk,mh); + elseif(pg != ph) + error("arg 1 has %d outputs; arg %d has vs %d outputs",pg,kk,ph); + elseif(norm(Gyd - Hyd)) + warning("cannot add a discrete output to a continuous output"); + error("Output type mismatch: arguments 1 and %d\n",kk); + endif + endfor + + ## perform the add + if(nargin == 2) + Gsys = nth(arglist,1); Hsys = nth(arglist,2); + if( strcmp(sysgettype(Gsys),"tf") | strcmp(sysgettype(Hsys),"tf") ) + ## see if adding transfer functions with identical denominators + [Gnum,Gden,GT,Gin,Gout] = sys2tf(Gsys); + [Hnum,Hden,HT,Hin,Hout] = sys2tf(Hsys); + if(length(Hden) == length(Gden) ) + if( (Hden == Gden) & (HT == GT) ) + sys = tf2sys(Gnum+Hnum,Gden,GT,Gin,Gout); + return + endif + ## if not, we go on and do the usual thing... + endif + endif + + ## make sure in ss form + Gsys = sysupdate(Gsys,"ss"); + Hsys = sysupdate(Hsys,"ss"); + + ## change signal names to avoid warning messages from sysgroup + Gsys = syssetsignals(Gsys,"in",sysdefioname(length(Gin),"Gin_u")); + Gsys = syssetsignals(Gsys,"out",sysdefioname(length(Gout),"Gout_u")); + Hsys = syssetsignals(Hsys,"in",sysdefioname(length(Hin),"Hin_u")); + Hsys = syssetsignals(Hsys,"out",sysdefioname(length(Hout),"Hout_u")); + + sys = sysgroup(Gsys,Hsys); + + eyin = eye(mg); + eyout = eye(pg); + + sys = sysscale(sys,[eyout, eyout],[eyin;eyin],Gout,Gin); + + else + ## multiple systems (or a single system); combine together one by one + sys = nth(arglist,1); + for kk=2:length(arglist) + sys = sysadd(sys,nth(arglist,kk)); + endfor + endif + +endfunction + diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/system/sysappend.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/system/sysappend.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,190 @@ +## Copyright (C) 1996, 1998 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{retsys} =} sysappend (@var{sys}, @var{b}@{, @var{c}, @var{d}, @var{outname}, @var{inname}, @var{yd}@}) +## appends new inputs and/or outputs to a system +## +## @strong{Inputs} +## @table @var +## @item sys +## system data structure +## +## @item b +## matrix to be appended to sys "B" matrix (empty if none) +## +## @item c +## matrix to be appended to sys "C" matrix (empty if none) +## +## @item d +## revised sys d matrix (can be passed as [] if the revised d is all zeros) +## +## @item outname +## list of names for new outputs +## +## @item inname +## list of names for new inputs +## +## @item yd +## binary vector; @math{yd(ii)=0} indicates a continuous output; +## @math{yd(ii)=1} indicates a discrete output. +## @end table +## +## @strong{Outputs} @var{sys} +## @example +## @group +## sys.b := [sys.b , b] +## sys.c := [sys.c ] +## [ c ] +## sys.d := [sys.d | D12 ] +## [D21 | D22 ] +## @end group +## @end example +## where @var{D12}, @var{D21}, and @var{D22} are the appropriate dimensioned +## blocks of the input parameter @var{d}. +## @itemize @bullet +## @item The leading block @var{D11} of @var{d} is ignored. +## @item If @var{inname} and @var{outname} are not given as arguments, +## the new inputs and outputs are be assigned default names. +## @item @var{yd} is a binary vector of length rows(c) that indicates +## continuous/sampled outputs. Default value for @var{yd} is: +## +## @item @var{sys} = continuous or mixed +## @var{yd} = @code{zeros(1,rows(c))} +## +## @item @var{sys} = discrete +## @var{yd} = @code{ones(1,rows(c))} +## @end itemize +## @end deftypefn + +## Author: John Ingram +## Created: August 1996 + +function retsys = sysappend (sys, b, c, d, outname, inname, yd) + + sav_empty_list_elements_ok = empty_list_elements_ok; + + empty_list_elements_ok = 1; + + ## check input arguments + if ( (nargin < 2) | (nargin > 7) | (!is_struct(sys))) + usage("retsys = sysappend(sys,b,c[,d,outname,inname,yd]) "); + elseif(!is_struct(sys)) + error("sys must be a system data structure"); + endif + + ## default system type must be state space form + [Aa,Ab,Ac,Ad,Ats,Ann,Anz,Ast,Ain,Aout,Ayd] = sys2ss(sys); + [Ann,Anz,Am,Ap] = sysdimensions(sys); + + ## default c + if(nargin < 3) c = []; endif + + ## default d + if(nargin < 4) make_d = 1; + elseif(isempty(d)) make_d = 1; + else make_d = 0; endif + if(make_d) d = zeros(rows(c)+Ap,columns(b) + Am); endif + + ## Append new input(s) if any + Bm = max(columns(d),columns(b)+Am); + if(Bm != Am) + ## construct new signal names + if(nargin >= 6) # new names were passed + if(!isstr(inname)) + error("inname must be a string"); + elseif(rows(inname) != (Bm - Am)) + error(sprintf("%d new inputs requested; inname(%dx%d)", ... + (Bm-Am),rows(inname),columns(inname))); + endif + else + inname = sysdefioname(Bm,"u",(Am+1)); + endif + if(Am) Ain = append(Ain,inname); + else Ain = inname; endif + + ## default b matrix + if(isempty(b)) b = zeros(Ann+Anz,(Bm-Am)); + elseif(rows(b) != Ann+Anz | columns(b) != (Bm-Am)) + error(sprintf("b(%dx%d); should be (%dx%d)", rows(b), columns(b), ... + (Ann+Anz), (Bm-Am))); + endif + + ## append new b matrix + Ab = [Ab,b]; # empty_list_elements_ok=1 makes this ok + endif + + ## Append new output(s) if any + Bp = max(rows(d),rows(c)+Ap); + if(Bp != Ap) + + ## construct new signal names, output classification + if(nargin >= 5) # new names were passed + if(!isstr(outname)) + error("outname must be a string"); + elseif(rows(outname) != (Bp - Ap)) + error(sprintf("%d new outputs requested; outname(%dx%d)", ... + (Bp-Ap),rows(outname),columns(outname))); + endif + else + outname = sysdefioname(Bp,"y",(Ap+1)); + endif + if(Ap) Aout = append(Aout,outname); + else Aout = outname; endif + + ## construct new yd entries + if(nargin == 7) + if(!is_vector(yd)) + error(sprintf("yd(%dx%d) must be a vector",rows(yd),columns(yd))) + elseif(rows(c) != length(yd) & rows(d) != length(yd)) + error(sprintf("length(yd) = %d; c(%dx%d), d(%dx%d); mismatch", ... + length(yd), rows(c), columns(c),rows(d),columns(d))); + endif + else + ## default yd values + yd = ones(1,Bp)*( (Ats > 0) & (Ann == 0) & isempty(find(Ayd == 0)) ) ; + endif + Ayd = [vec(Ayd);vec(yd)]; + + ## default c matrix + if(isempty(c)) c = zeros((Bp-Ap),Ann+Anz); + elseif(columns(c) != Ann+Anz | rows(c) != (Bp-Ap)) + error(sprintf("c(%dx%d); should be (%dx%d)", rows(c), columns(c), ... + (Bp-Ap), (Ann+Anz) )); + endif + + ## append new c matrix + Ac = [Ac;c]; # empty_list_elements_ok=1 makes this ok + endif + + ## check d matrix + if(isempty(d)) d = zeros(Bp,Bm); + elseif(rows(d) != Bp | columns(d) != Bm) + error(sprintf("d(%dx%d) should be (%dx%d)",rows(d), columns(d), Bp, Bp)); + endif + + ## Splice in original D matrix + if(Am & Ap) d(1:Ap, 1:Am) = Ad; endif + Ad = d; + + ## construct return system + retsys = ss2sys(Aa,Ab,Ac,Ad,Ats,Ann,Anz,Ast,Ain,Aout,find(Ayd == 1)); + + empty_list_elements_ok = sav_empty_list_elements_ok; + +endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/system/syschnamesl.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/system/syschnamesl.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,116 @@ +## Copyright (C) 1996 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{old_names} =} syschnamesl (@var{olist}, @var{old_names}, @var{inames}, @var{listname}) +## used internally in syschnames +## item olist: index list +## old_names: original list names +## inames: new names +## listname: name of index list +## +## combines the two string lists old_names and inames +## @end deftypefn + +function old_names = syschnamesl (olist, old_names, inames, listname) + + probstr = []; + if( max(olist) > rows(old_names) ) + probstr = ["index list value(s) exceed(s) number of signals (", ... + num2str(rows(old_names)),")"]; + + elseif( length(olist) > rows(inames) ) + probstr = ["index list dimension exceeds number of replacement names (", ... + num2str(rows(inames)),")"]; + + elseif(isempty(olist)) + probstr = []; # do nothing, no changes + + elseif(min(size(olist)) != 1 ) + probstr = "index list must be either a vector or an empty matrix"; + + elseif(max(olist) > rows(old_names)) + probstr = ["max(",listname,")=",num2str(max(olist))," > ", ... + num2str(rows(old_names)),", too big"]; + + elseif(min(olist) < 1) + probstr = ["min(",listname,")=",num2str(min(olist))," < 1, too small"]; + + else + if( length(olist) == 1) + len_in = columns(inames); + len_out = columns(old_names); + + if (len_in < len_out) + inames(1,(len_in+1):(len_out)) = zeros(1,(len_out - len_in)); + endif + + old_names(olist,1:length(inames)) = inames; + elseif(length(olist) > 1) + for ii=1:length(olist) + mystr = inames(ii,:); + len_my = columns(mystr); + len_out = columns(old_names); + + if (len_my < len_out) + mystr(1,(len_my+1):(len_out)) = " "*ones(1,(len_out - len_my)); + len_my = len_out; + endif + + old_names(olist(ii),1:len_my) = mystr; + endfor + endif + endif + if(!isempty(probstr)) + ## the following lines are NOT debugging code! + disp("Problem in syschnames: old names are") + outlist(old_names," ") + disp("new names are") + outlist(inames," ") + disp("list indices are") + disp(olist) + error(sprintf("syschnames: \"%s\" dim=(%d x %d)--\n\t%s\n", ... + listname, rows(olist), columns(olist),probstr)); + endif + + ## change zeros to blanks + if( find(old_names == 0) ) + ## disp("syschnamesl: old_names contains zeros ") + ## old_names + ## disp("/syschnamesl"); + + [ii,jj] = find(old_names == 0); + for idx=1:length(ii) + old_names(ii(idx),jj(idx)) = " "; + endfor + + ## disp("syschnamesl: old_names fixed zeros ") + ## old_names + ## disp("/syschnamesl"); + endif + + ## just in case it's not a string anymore + if( !isstr(old_names) ) + old_names = setstr(old_names); + endif + + ## disp("syschnamesl: exit, old_names=") + ## old_names + ## disp("/syschnamesl: exiting") + +endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/system/syschtsam.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/system/syschtsam.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,50 @@ +## Copyright (C) 1996 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{retsys} =} syschtsam (@var{sys}, @var{tsam}) +## This function changes the sampling time (tsam) of the system. Exits with +## an error if sys is purely continuous time. +## @end deftypefn + +## Author: John Ingram +## Created: August 1996 + +function retsys = syschtsam (sys, tsam) + + if (nargin != 2) + usage("retsys = syschtsam(sys,tsam)"); + elseif (!is_struct(sys)) + error("sys must be in system data structure form"); + elseif(!is_scalar(tsam)) + disp("syschtsam:") + tsam + error("tsam must be a scalar") + elseif ( ! (is_sample(tsam) | (tsam == 0) ) ) + error("tsam must be real, scalar, and greater than zero"); + elseif (sysgettsam(sys) == 0) + [nc,nz,mm,pp] = sysdimensions(sys); + warning("syschtsam: continuous system (nc=%d, nz=%d, mm=%d, pp=%d)", ... + nc,nz,mm,pp); + warning("syschtsam: The system is continuous, use c2d to make the system discrete"); + endif + + retsys = sys; + retsys.tsam = tsam; + +endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/system/sysconnect.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/system/sysconnect.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,277 @@ +## Copyright (C) 1996, 1998 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{retsys} =} sysconnect (@var{sys}, @var{out_idx},@var{in_idx}@{,@var{order}, @var{tol}@}) +## Close the loop from specified outputs to respective specified inputs +## +## @strong{Inputs} +## @table @var +## @item sys +## system data structure +## @item out_idx +## @itemx in_idx +## list of connections indices; @math{y(out_idx(ii))} +## is connected to @math{u(in_idx(ii))}. +## @item order +## logical flag (default = 0) +## @table @code +## @item 0 +## leave inputs and outputs in their original order +## @item 1 +## permute inputs and outputs to the order shown in the diagram below +## @end table +## @item tol +## tolerance for singularities in algebraic loops default: 200@var{eps} +## @end table +## +## @strong{Outputs} +## @var{sys}: resulting closed loop system. +## +## @strong{Method} +## @code{sysconnect} internally permutes selected inputs, outputs as shown +## below, closes the loop, and then permutes inputs and outputs back to their +## original order +## @example +## @group +## ____________________ +## u_1 ----->| |----> y_1 +## | sys | +## old u_2 | | +## u_2* ---->(+)--->| |----->y_2 +## (in_idx) ^ -------------------| | (out_idx) +## | | +## ------------------------------- +## @end group +## @end example +## The input that has the summing junction added to it has an * added to +## the end of the input name. +## @end deftypefn + +## Author: A. S. Hodel +## Created: August 1995 +## modified by John Ingram July 1996 + +function sys = sysconnect (sys, output_list, input_list, order, tol) + + if( (nargin < 3) | (nargin > 5) ) + usage("retsys = sysconnect(sys,output_list,input_list[,order,tol])"); + endif + + ## check order + if(nargin <= 3) + order = 0; + elseif( (order != 0) & (order != 1) ) + error("sysconnect: order must be either 0 or 1") + endif + + if (nargin <= 4) + tol = 200*eps; + elseif( !is_sample(tol) ) + error("sysconnect: tol must be a positive scalar"); + elseif(tol > 1e2*sqrt(eps)) + warning(["sysconnect: tol set to large value=",num2str(tol), ... + ", eps=",num2str(eps)]) + endif + + ## verify sizes,format of input, output lists + if( min(size(output_list))*min(size(input_list)) != 1) + error("output_list and input_list must be vectors"); + else + lo = length(output_list); + li = length(input_list); + if(lo != li) + error("output_list and input_list must be of the same length") + endif + + if(is_duplicate_entry(output_list) | is_duplicate_entry(input_list) ) + error("duplicate entry in input_list and/or output_list"); + endif + endif + + [nc,nz,mm,pp] = sysdimensions(sys); + nn = nc+nz; + + if( !is_struct(sys)) + error("sys must be in structured system form") + elseif(pp < li) + error(["length(output_list)=",num2str(li),", sys has only ", ... + num2str(pp),"system outputs"]) + elseif(mm < li) + error(["length(input_list)=",num2str(li),", sys has only ", ... + num2str(mm),"system inputs"]) + endif + + ## check that there are enough inputs/outputs in the system for the lists + if(max(input_list) > mm) + error("max(input_list) exceeds the number of inputs"); + elseif(max(output_list) > pp) + error("max(output_list) exceeds the number of outputs"); + endif + + output_list = reshape(output_list,1,length(output_list)); + + ## make sure we're in state space form + sys = sysupdate (sys, "ss"); + + ## permute rows and columns of B,C,D matrices into pseudo-dgkf form... + all_inputs = sysreorder(mm,input_list); + all_outputs = sysreorder(pp,output_list); + + [aa,bb,cc,dd] = sys2ss(sys); + bb = bb(:,all_inputs); + cc = cc(all_outputs,:); + dd = dd(all_outputs,all_inputs); + + yd = sysgetsignals(sys,"yd"); + yd = yd(all_outputs); + + ## m1, p1 = number of inputs, outputs that are not being connected + m1 = mm-li; + p1 = pp-li; + + ## m2, p2: 1st column, row of B, C that is being connected + m2 = m1+1; + p2 = p1+1; + + ## partition system into a DGKF-like form; the loop is closed around + ## B2, C2 + if(m1 > 0) + B1 = bb(:,1:m1); + D21= dd(p2:pp,1:m1); + endif + B2 = bb(:,m2:mm); + if(p1 > 0) + C1 = cc(1:p1,:); + D12= dd(1:p1,m2:mm); + endif + C2 = cc(p2:pp,:); + if(m1*p1 > 0) + D11= dd(1:p1,1:m1); + endif + D22= dd(p2:pp,m2:mm); + + if(norm(D22)) + warning("sysconnect: possible algebraic loop, D22 non-zero"); + D22i = (eye(size(D22))-D22); + C2h = D22i\C2; + if(m1 > 0) + D21h = D22i\D21; + endif + D22h = D22i\D22; + else + C2h = C2; + if(m1 > 0) + D21h = D21; + endif + D22h = D22; + + endif + + ## check cont state -> disc output -> cont state + dyi = find(yd(p2:pp)); + + ## disp("sysconnect: dyi=") + ## dyi + ## nc + ## disp("/sysconnect"); + + if( (nc > 0) & find(dyi > 0) ) + B2con = B2(1:nc,dyi); # connection to cont states + C2hd = C2h(dyi,1:nc); # cont states -> outputs + else + B2con = C2hd = []; + endif + + if(max(size(B2con)) & max(size(C2hd)) ) + if(norm(B2con*C2hd)) + warning("sysconnect: cont-state -> disc output -> cont state derivative"); + warning(" connection made; resulting system may not be meaningful"); + endif + endif + + Ac = aa+B2*C2h; + if(m1 > 0) + B1c = B1 + B2*D21h; + endif + B2c = B2*(eye(size(D22h)) + D22h); + if(p1*m1 > 0) + D11c = D11 + D12*D21h; + endif + if(p1 > 0) + C1c = C1+D12*C2h; + D12c = D12*(eye(size(D22h))+D22h); + endif + + ## construct system data structure + if(m1 > 0) + Bc = [B1c, B2c]; + else + Bc = B2c; + endif + + if(p1 > 0) + Cc = [C1c;C2h]; + else + Cc = C2h; + endif + + if(m1*p1 > 0) + Dc = [D11c,D12c; D21h,D22h]; + elseif(m1 > 0) + Dc = [D21h, D22h]; + elseif(p1 > 0) + Dc = [D12c; D22h]; + else + Dc = D22h; + endif + + ## permute rows and columns of Bc, Cc, Dc back into original order + Im = eye(mm,mm); + Pi = Im(:,all_inputs); + back_inputs = Pi*[1:mm]'; + + Ip = eye(pp,pp); + Po = Ip(:,all_outputs); + back_outputs = Po*[1:pp]'; + + Bc = Bc(:,back_inputs); + Cc = Cc(back_outputs,:); + Dc = Dc(back_outputs,back_inputs); + yd = yd(back_outputs); + + ## rebuild system + Ts = sysgettsam(sys); + [stnam,innam,outnam] = sysgetsignals(sys); + sys = ss2sys(Ac,Bc,Cc,Dc,Ts,nc,nz,stnam,innam,outnam,find(yd)); + + ## update connected input names + for ii = 1:length(input_list) + idx = input_list(ii); + strval = sprintf("%s*",nth(sysgetsignals(sys,"in",idx),1) ); + sys = syssetsignals(sys,"in",strval,idx); + endfor + + ## maintain original system type if it was SISO + if (strcmp (sysgettype (sys), "tf")) + sysupdate (sys, "tf"); + elseif (strcmp (sysgettype (sys),"zp")) + sysupdate (sys, "zp"); + endif + +endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/system/syscont.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/system/syscont.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,88 @@ +## Copyright (C) 1996 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## -*- texinfo -*- +## @deftypefn {Function File} {[@var{csys}, @var{Acd}, @var{Ccd}] =} syscont (@var{sys}) +## Extract the purely continuous subsystem of an input system. +## +## @strong{Inputs} +## @var{sys} is a system data structure +## +## @strong{Outputs} +## @table @var +## @item csys +## is the purely continuous input/output connections of @var{sys} +## @item Acd +## @itemx Ccd +## connections from discrete states to continuous states, +## discrete states to continuous outputs, respectively. +## +## returns @var{csys} empty if no continuous/continous path exists +## @end table +## @end deftypefn + +## Author: John Ingram +## Created: August 1996 + +function [csys, Acd, Ccd] = syscont (sys) + + save_empty = empty_list_elements_ok; + empty_list_elements_ok = 1; + + if (nargin != 1) + usage("[csys,Acd,Ccd,Dcd] = syscont(sys)"); + elseif (!is_struct(sys)) + error("sys must be in system data structure form"); + endif + + sys = sysupdate(sys,"ss"); + [n_tot,st_c,st_d,y_c,y_d] = syscont_disc(sys); # get ranges + + ## assume there's nothing there; build partitions as appropriate + Acc = Acd = Bcc = Ccc = Ccd = Dcc = []; + + if(isempty(st_c) & isempty(y_c)) + error("syscont: expecting continous states and/or continous outputs"); + elseif (isempty(st_c)) + warning("syscont: no continuous states"); + elseif(isempty(y_c)) + warning("syscont: no continuous outputs"); + endif + + [sys_a, sys_b, sys_c, sys_d ] = sys2ss(sys); + [sys_stname, sys_inname, sys_outname] = sysgetsignals(sys); + [sys_n, sys_nz, sys_m, sys_p] = sysdimensions(sys); + if(!isempty(st_c)) + Acc = sys_a(st_c,st_c); + stname = sys_stname(st_c); + Bcc = sys_b(st_c,:); + Ccc = sys_c(y_c,st_c); + Acd = sys_a(st_c,st_d); + else + stname=[]; + endif + outname = sys_outname(y_c); + Dcc = sys_d(y_c,:); + Ccd = sys_c(y_c,st_d); + inname = sys_inname; + + csys = ss2sys(Acc,Bcc,Ccc,Dcc,0,sys_n,0,stname,inname,outname); + + empty_list_elements_ok = save_empty; + +endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/system/syscont_disc.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/system/syscont_disc.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,54 @@ +## Copyright (C) 1996, 1998 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## -*- texinfo -*- +## @deftypefn {Function File} {[@var{n_tot}, @var{st_c}, @var{st_d}, @var{y_c}, @var{y_d}] =} syscont_disc(@var{sys}) +## Used internally in syscont and sysdisc. +## +## @strong{Inputs} +## @var{ sys} is a system data structure. +## +## @strong{Outputs} +## @table @var +## @item n_tot +## total number of states +## @item st_c +## vector of continuous state indices (empty if none) +## @item st_d +## vector of discrete state indices (empty if none) +## @item y_c +## vector of continuous output indices +## @item y_d +## vector of discrete output indices +## @end table +## @end deftypefn + +## Author: A. S. Hodel +## Created: February 1997 + +function [n_tot, st_c, st_d, y_c, y_d] = syscont_disc (sys) + + ## get ranges for discrete/continuous states and outputs + [nn,nz,mm,pp,yd] = sysdimensions(sys); + n_tot = nn + nz; + st_c = 1:(nn); + st_d = nn + (1:nz); + y_c = find(yd == 0); # y_c, y_d will be empty if there are none. + y_d = find(yd == 1); + +endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/system/sysdefioname.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/system/sysdefioname.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,57 @@ +## Copyright (C) 1996, 1998 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{ioname} =} sysdefioname (@var{n},@var{str} @{,@var{m}@}) +## return default input or output names given @var{n}, @var{str}, @var{m}. +## @var{n} is the final value, @var{str} is the string prefix, and @var{m} +## is start value +## +## used internally, minimal argument checking +## +## @strong{Example} @code{ioname = sysdefioname(5,"u",3)} +## returns the list: +## @example +## ioname = +## ( +## [1] = u_3 +## [2] = u_4 +## [3] = u_5 +## ) +## @end example +## @end deftypefn + +function ioname = sysdefioname (n, str, m) + + if (nargin < 2 | nargin > 3) + usage("ioname = sysdefioname(n,str[,m])"); + endif + + if (nargin == 2) m = min(1,n); endif + + ioname = list(); + jj = 1; + if(n > 0 & m > 0 & m <= n) + for ii = m:n + ioname(ii+1-m) = sprintf("%s_%d",str,ii); + endfor + elseif(m > n) + error("str=%s; start value m=%d > final value n=%d",str,m,n); + endif + +endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/system/sysdefstname.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/system/sysdefstname.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,42 @@ +## Copyright (C) 1996 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{stname} =} sysdefstname (@var{n}, @var{nz}) +## return default state names given @var{n}, @var{nz} +## +## used internally, minimal argument checking +## @end deftypefn + +function stname = sysdefstname (n, nz) + + stname = list(); + if(n > 0) + for ii = 1:n + stname(ii) = sprintf("x_%d",ii); + endfor + endif + + ## Set default names for discrete states + if(nz > 0) + for ii = (n+1):(n+nz) + stname(ii) = sprintf("xd_%d",ii); + endfor + endif + +endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/system/sysdimensions.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/system/sysdimensions.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,101 @@ +## Copyright (C) 1996, 1998 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## -*- texinfo -*- +## @deftypefn {Function File} {[@var{n}, @var{nz}, @var{m}, @var{p}, @var{yd}] =} sysdimensions (@var{sys}@{, @var{opt}@}) +## return the number of states, inputs, and/or outputs in the system +## @var{sys}. +## +## @strong{Inputs} +## @table @var +## @item sys +## system data structure +## +## @item opt +## String indicating which dimensions are desired. Values: +## @table @code +## @item "all" +## (default) return all parameters as specified under Outputs below. +## +## @item "cst" +## return @var{n}= number of continuous states +## +## @item "dst" +## return @var{n}= number of discrete states +## +## @item "in" +## return @var{n}= number of inputs +## +## @item "out" +## return @var{n}= number of outputs +## @end table +## @end table +## +## @strong{Outputs} +## @table @var +## @item n +## number of continuous states (or individual requested dimension as specified +## by @var{opt}). +## @item nz +## number of discrete states +## @item m +## number of system inputs +## @item p +## number of system outputs +## @item yd +## binary vector; @var{yd}(@var{ii}) is nonzero if output @var{ii} is +## discrete. +## @math{yd(ii) = 0} if output @var{ii} is continous +## @end table +## @end deftypefn +## @seealso{sysgetsignals and sysgettsam} + +function [n, nz, m, p, yd] = sysdimensions (sys, opt) + + if(nargout > 5 | nargin < 1 | nargin > 2) + usage("[n,nz,m,p[,yd]] = sysdimensions(sys{,opt})"); + elseif(!is_struct(sys)) + usage("[n,nz,m,p] = sysdimensions(sys)"); + elseif(nargin == 1) + opt = "all"; + endif + + n = sys.n; + nz = sys.nz; + m = length(sysgetsignals(sys,"in")); + p = length(sysgetsignals(sys,"out")); + yd = sys.yd; + valid_options = list("all","cst","dst","st","in","out"); + valid_values = list(n,n,nz,n+nz,m,p); + + valid_opt = 0; + for ii=1:length(valid_options) + if(strcmp(nth(valid_options,ii),opt)) + n = nth(valid_values,ii); + valid_opt = 1; + if(ii > 1 & nargout > 1) + warning("opt=%s, %d output arguments requested",opt,nargout); + endif + endif + endfor + + if (! valid_opt) + error ("invalid option passed = %s", opt); + endif + +endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/system/sysdisc.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/system/sysdisc.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,98 @@ +## Copyright (C) 1996 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## -*- texinfo -*- +## @deftypefn {Function File} {[@var{dsys}, @var{Adc}, @var{Cdc}] =} sysdisc (@var{sys}) +## +## @strong{Inputs} +## @var{sys} = system data structure +## +## @strong{Outputs} +## @table @var +## @item dsys +## purely discrete portion of sys (returned empty if there is +## no purely discrete path from inputs to outputs) +## @item Adc +## @itemx Cdc +## connections from continuous states to discrete states and discrete +## outputs, respectively. +## @end table +## @end deftypefn + +function [dsys, Adc, Cdc] = sysdisc (sys) + + save_empty = empty_list_elements_ok; + empty_list_elements_ok = 1; + + if (nargin != 1) + usage("[dsys,Adc,Cdc] = sysdisc(sys)"); + elseif (!is_struct(sys)) + error("sys must be in system data structure form"); + endif + + sys = sysupdate(sys,"ss"); + [n_tot,st_c,st_d,y_c,y_d] = syscont_disc(sys); # get ranges + + ## assume there's nothing there; build partitions as appropriate + Add = Adc = Bdd = Cdd = Cdc = Ddd = []; + + if(isempty(st_d) & isempty(y_d)) + error("sysdisc: expecting discrete states and/or continous outputs"); + elseif (isempty(st_d)) + warning("sysdisc: no discrete states"); + elseif(isempty(y_d)) + warning("sysdisc: no discrete outputs"); + endif + + [aa,bb,cc,dd] = sys2ss(sys); + if(!isempty(st_d) ) + Add = aa( st_d , st_d); + stname = sysgetsignals(sys,"st",st_d); + Bdd = bb( st_d , :); + if(!isempty(st_c)) + Adc = aa( st_d , st_c); + endif + if(!isempty(y_d)) + Cdd = cc(y_d , st_d); + endif + else + stname = []; + endif + if(!isempty(y_d)) + Ddd = dd(y_d , :); + outname = sysgetsignals(sys,"out",y_d); + if(!isempty(st_c)) + Cdc = cc(y_d , st_c); + endif + else + outname=[]; + endif + inname = sysgetsignals(sys,"in"); + outlist = 1:rows(outname); + + if(!isempty(outname)) + tsam = sysgettsam(sys); + [nc,nz] = sysdimensions(sys); + dsys = ss2sys(Add,Bdd,Cdd,Ddd,tsam,0,nz,stname,inname,outname,outlist); + else + dsys=[]; + endif + + empty_list_elements_ok = save_empty; + +endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/system/sysdup.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/system/sysdup.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,120 @@ +## Copyright (C) 1996, 1998 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{retsys} =} sysdup (@var{Asys}, @var{out_idx}, @var{in_idx}) +## Duplicate specified input/output connections of a system +## +## @strong{Inputs} +## @table @var +## @item Asys +## system data structure (@pxref{ss2sys}) +## @item out_idx +## @itemx in_idx +## list of connections indices; +## duplicates are made of @code{y(out_idx(ii))} and @code{u(in_idx(ii))}. +## @end table +## +## @strong{Outputs} +## @var{retsys}: resulting closed loop system: +## duplicated i/o names are appended with a @code{"+"} suffix. +## +## +## @strong{Method} +## @code{sysdup} creates copies of selected inputs and outputs as +## shown below. u1/y1 is the set of original inputs/outputs, and +## u2,y2 is the set of duplicated inputs/outputs in the order specified +## in @var{in_idx}, @var{out_idx}, respectively +## @example +## @group +## ____________________ +## u1 ----->| |----> y1 +## | Asys | +## u2 ------>| |----->y2 +## (in_idx) -------------------| (out_idx) +## @end group +## @end example +## @end deftypefn + +## Author: A. S. Hodel +## Created: August 1995 +## modified by John Ingram July 1996 + +function retsys = sysdup (Asys, output_list, input_list) + + if( nargin != 3) + usage("retsys = sysdup(Asys,output_list,input_list)"); + endif + + if( !is_struct(Asys)) + error("Asys must be a system data structure (see ss2sys, tf2sys, or zp2sys)") + endif + + Asys = sysupdate(Asys,"ss"); + [nn,nz,mm,pp] = sysdimensions(Asys); + [aa,bb,cc,dd] = sys2ss(Asys); + + ## first duplicate inputs + if(is_vector(input_list)) + for ii=1:length(input_list); + bb(:,mm+ii) = bb(:,input_list(ii)); + dd(:,mm+ii) = dd(:,input_list(ii)); + end + elseif(!isempty(input_list)) + error("input_list must be a vector or empty"); + endif + + + ## now duplicate outputs + osize = min(size(output_list)); + if(osize == 1) + for ii=1:length(output_list); + cc(pp+ii,:) = cc(output_list(ii),:); + dd(pp+ii,:) = dd(output_list(ii),:); + end + elseif(osize != 0) + error("output_list must be a vector or empty"); + endif + + [stnam,innam,outnam,yd] = sysgetsignals(Asys); + tsam = sysgettsam(Asys); + + ## pack system and then rename signals + retsys = ss2sys(aa,bb,cc,dd,tsam,nn,nz); + retsys = syssetsignals(retsys,"in",innam,1:mm); + retsys = syssetsignals(retsys,"out",outnam,1:pp); + retsys = syssetsignals(retsys,"yd",yd,1:pp); + + ## update added input names + for ii=(mm+1):(mm+length(input_list)) + onum = input_list(ii-mm); + strval = sprintf("%s(dup)",sysgetsignals(retsys,"in",onum,1) ); + retsys = syssetsignals(retsys,"in",strval,ii); + endfor + + ## update added output names/discrete flags + ## give default names to the added outputs + for jj=(pp+1):(pp+length(output_list)) + onum = output_list(jj-pp); + strval = sprintf("%s(dup)",sysgetsignals(retsys,"out",onum,1) ); + retsys = syssetsignals(retsys,"out",strval,jj); + dflg = sysgetsignals(retsys,"yd",onum); + retsys = syssetsignals(retsys,"yd",dflg,jj); + endfor + +endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/system/sysgetsignals.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/system/sysgetsignals.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,193 @@ +## Copyright (C) 1998 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## -*- texinfo -*- +## @deftypefn {Function File} {[@var{stname}, @var{inname}, @var{outname}, @var{yd}] =} sysgetsignals (@var{sys}) +## @deftypefnx{Function File} {@var{siglist} =} sysgetsignals (@var{sys},@var{sigid}) +## @deftypefnx{Function File} {@var{signame} =} sysgetsignals (@var{sys},@var{sigid},@var{signum}@{, @var{strflg}@}) +## Get signal names from a system +## +## @strong{Inputs} +## @table @var +## @item sys +## system data structure for the state space system +## +## @item sigid +## signal id. String. Must be one of +## @table @code +## @item "in" +## input signals +## @item "out" +## output signals +## @item "st" +## stage signals +## @item "yd" +## value of logical vector @var{yd} +## @end table +## +## @item signum +## Index of signal (or indices of signals if signum is a vector) +## +## @item strflg +## flag to return a string instead of a list; Values: +## @table @code +## @item 0 +## (default) return a list (even if signum is a scalar) +## +## @item 1 +## return a string. Exits with an error if signum is not a scalar. +## @end table +## +## @end table +## +## @strong{Outputs} +## @table @bullet +## @item If @var{sigid} is not specified +## @table @var +## @item stname +## @itemx inname +## @itemx outname +## signal names (lists of strings); names of states, +## inputs, and outputs, respectively +## @item yd +## binary vector; @var{yd}(@var{ii}) is nonzero if output @var{ii} is +## discrete. +## @end table +## +## @item If @var{sigid} is specified but @var{signum} is not specified, then +## @table @code +## @item sigid="in" +## @var{siglist} is set to the list of input names +## +## @item sigid="out" +## @var{siglist} is set to the list of output names +## +## @item sigid="st" +## @var{siglist} is set to the list of state names +## +## stage signals +## @item sigid="yd" +## @var{siglist} is set to logical vector indicating discrete outputs; +## @var{siglist(ii) = 0} indicates that output @var{ii} is continuous +## (unsampled), otherwise it is discrete. +## +## @end table +## +## @item if the first three input arguments are specified, then @var{signame} is +## a list of the specified signal names (@var{sigid} is @code{"in"}, +## @code{"out"}, or @code{"st"}), or else the logical flag +## indicating whether output(s) @var{signum} is(are) discrete (@var{sigval}=1) +## or continuous (@var{sigval}=0). +## @end table +## +## @strong{Examples} (From @code{sysrepdemo}) +## @example +## octave> sys=ss2sys(rand(4),rand(4,2),rand(3,4)); +## octave> [Ast,Ain,Aout,Ayd] = sysgetsignals(sys) i # get all signal names +## Ast = +## ( +## [1] = x_1 +## [2] = x_2 +## [3] = x_3 +## [4] = x_4 +## ) +## Ain = +## ( +## [1] = u_1 +## [2] = u_2 +## ) +## Aout = +## ( +## [1] = y_1 +## [2] = y_2 +## [3] = y_3 +## ) +## Ayd = +## +## 0 0 0 +## octave> Ain = sysgetsignals(sys,"in") # get only input signal names +## Ain = +## ( +## [1] = u_1 +## [2] = u_2 +## ) +## octave> Aout = sysgetsignals(sys,"out",2) # get name of output 2 (in list) +## Aout = +## ( +## [1] = y_2 +## ) +## octave> Aout = sysgetsignals(sys,"out",2,1) # get name of output 2 (as string) +## Aout = y_2 +## @end example +## @end deftypefn + +function [stname, inname, outname, yd] = sysgetsignals (sys, sigid, signum, strflg) + + ## Adapted from ss2sys + + if(nargin < 1 | nargin > 4 | nargout > 4) + usage("[stname{,inname,outname,yd}] = sysgetsignals(sys{,sigid,signum})") + elseif(nargin > 1 & nargout > 1) + usage("sig = sysgetsignals(sys,sigid{,signum,strflg})") + elseif( ! is_struct(sys) ) + error("input argument must be a system data structure"); + endif + if(nargin < 4) strflg = 0; endif + if(nargin == 1) + sys = sysupdate(sys,"ss"); #make sure ss is up to date + stname = sysgetsignals(sys,"st"); + inname = sysgetsignals(sys,"in"); + outname = sysgetsignals(sys,"out"); + yd = sysgetsignals(sys,"yd"); + elseif(!(isstr(sigid) & min(size(sigid)) == 1)) + error(sprintf("sigid(%dx%d) must be a string)",rows(sigid),columns(sigid))); + else + if(strcmp("st",sigid)) stname = sys.stname; + elseif(strcmp("in",sigid)) stname = sys.inname; + elseif(strcmp("out",sigid)) stname = sys.outname; + elseif(strcmp("yd",sigid)) stname = vec(sys.yd)'; + else + error(sprintf("sigid=%s must be \"st\", \"in\", \"out\", or \"yd\"", ... + sigid)); + endif + if(nargin >= 3) + if(signum > length(stname)) + error(sprintf("sysgetsignals(sys,\"%s\",%d):only %d entries.\n", ... + sigid,signum, rows(stname))); + else + if(!is_scalar(strflg)) + error("strflg must be a scalar"); + endif + switch(strflg) + case(0), + stname = stname(signum); + case(1), + if(length(signum) > 1) + error("strflg=1, length(signum) = %d",length(signum)); + endif + stname = nth(stname,signum); + otherwise, + error ("invalid value of strflg = %e", strflg); + endswitch + + endif + endif + endif + +endfunction + diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/system/sysgettsam.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/system/sysgettsam.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,30 @@ +## Copyright (C) 1996, 1998 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## T = sysgettsam(sys) +## return the sampling time of the system + +function T = sysgettsam (sys) + + if(!is_struct(sys)) + usage("T = sysgettsam(sys)"); + endif + + T = sys.tsam; + +endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/system/sysgettype.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/system/sysgettype.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,42 @@ +## Copyright (C) 1998 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{systype} =} sysgettype (@var{sys}) +## return the initial system type of the system +## +## @strong{Inputs} +## @var{sys}: system data structure +## +## @strong{Outputs} +## @var{systype}: string indicating how the structure was initially +## constructed: +## values: @code{"ss"}, @code{"zp"}, or @code{"tf"} +## +## @strong{Note} FIR initialized systems return @code{systype="tf"}. +## @end deftypefn + +function systype = sysgettype (sys) + + if(!is_struct(sys)) + error("sysgettype: input sys is not a structure"); + endif + + typestr = list("tf","zp","ss"); + systype = nth(typestr,sys.sys(1) + 1); +endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/system/sysgroup.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/system/sysgroup.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,150 @@ +## Copyright (C) 1996, 1998, 1999 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{sys} =} sysgroup (@var{Asys}, @var{Bsys}) +## Combines two systems into a single system +## +## @strong{Inputs} +## @var{Asys}, @var{Bsys}: system data structures +## +## @strong{Outputs} +## @math{sys = @r{block diag}(Asys,Bsys)} +## @example +## @group +## __________________ +## | ________ | +## u1 ----->|--> | Asys |--->|----> y1 +## | -------- | +## | ________ | +## u2 ----->|--> | Bsys |--->|----> y2 +## | -------- | +## ------------------ +## Ksys +## @end group +## @end example +## The function also rearranges the internal state-space realization of @var{sys} +## so that the +## continuous states come first and the discrete states come last. +## If there are duplicate names, the second name has a unique suffix appended +## on to the end of the name. +## @end deftypefn + +## Author: A. S. Hodel +## Created: August 1995 +## modified by John Ingram July 1996 +## A. S. Hodel: modified for variable number of arguments 1999 + +function sys = sysgroup (...) + + save_emp = empty_list_elements_ok; + empty_list_elements_ok = 1; + + if(nargin < 1) + usage("sys = sysgroup(Asys{,Bsys,...})"); + endif + + ## collect all arguments + arglist = list(); + va_start(); + for kk=1:nargin + arglist(kk) = va_arg(); + if(!is_struct(nth(arglist,kk))) + error("sysgroup: argument %d is not a data structure",kk); + endif + endfor + + if(nargin == 2) + ## the usual case; group the two systems together + Asys = nth(arglist,1); + Bsys = nth(arglist,2); + + ## extract information from Asys, Bsys to consruct sys + Asys = sysupdate(Asys,"ss"); + Bsys = sysupdate(Bsys,"ss"); + [n1,nz1,m1,p1] = sysdimensions(Asys); + [n2,nz2,m2,p2] = sysdimensions(Bsys); + [Aa,Ab,Ac,Ad,Atsam,An,Anz,Ast,Ain,Aout,Ayd] = sys2ss(Asys); + [Ba,Bb,Bc,Bd,Btsam,Bn,Bnz,Bst,Bin,Bout,Byd] = sys2ss(Bsys); + nA = An + Anz; + nB = Bn + Bnz; + + if(p1*m1*p2*m2 == 0) + error("sysgroup: argument lacks inputs and/or outputs"); + + elseif((Atsam + Btsam > 0) & (Atsam * Btsam == 0) ) + warning("sysgroup: creating combination of continuous and discrete systems") + + elseif(Atsam != Btsam) + error("sysgroup: Asys.tsam=%e, Bsys.tsam =%e", Atsam, Btsam); + endif + + A = [Aa,zeros(nA,nB); zeros(nB,nA),Ba]; + B = [Ab,zeros(nA,m2); zeros(nB,m1),Bb]; + C = [Ac,zeros(p1,nB); zeros(p2,nA),Bc]; + D = [Ad,zeros(p1,m2); zeros(p2,m1),Bd]; + tsam = max(Atsam,Btsam); + + ## construct combined signal names; stnames must check for pure gain blocks + if(isempty(Ast)) + stname = Bst; + elseif(isempty(Bst)) + stname = Ast; + else + stname = append(Ast, Bst); + endif + inname = append(Ain, Bin); + outname = append(Aout,Bout); + + ## Sort states into continous first, then discrete + dstates = ones(1,(nA+nB)); + if(An) + dstates(1:(An)) = zeros(1,An); + endif + if(Bn) + dstates((nA+1):(nA+Bn)) = zeros(1,Bn); + endif + [tmp,pv] = sort(dstates); + A = A(pv,pv); + B = B(pv,:); + C = C(:,pv); + stname = stname(pv); + + ## check for duplicate signal names + inname = sysgroupn(inname,"input"); + stname = sysgroupn(stname,"state"); + outname = sysgroupn(outname,"output"); + + ## mark discrete outputs + outlist = find([Ayd, Byd]); + + ## build new system + sys = ss2sys(A,B,C,D,tsam,An+Bn,Anz+Bnz,stname,inname,outname); + + else + ## multiple systems (or a single system); combine together one by one + sys = nth(arglist,1); + for kk=2:length(arglist) + printf("sysgroup: kk=%d\n",kk); + sys = sysgroup(sys,nth(arglist,kk)); + endfor + endif + + empty_list_elements_ok = save_emp; + +endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/system/sysgroupn.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/system/sysgroupn.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,57 @@ +## Copyright (C) 1996, 1998 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{names} =} sysgroupn (@var{names}) +## names = sysgroupn(names) +## Locate and mark duplicate names +## inputs: +## names: list of signal names +## kind: kind of signal name (used for diagnostic message purposes only) +## outputs: +## returns names with unique suffixes added; diagnostic warning +## message is printed to inform the user of the new signal name +## +## used internally in sysgroup and elsewhere. +## @end deftypefn + +function names = sysgroupn (names, kind) + + ## check for duplicate names + l = length(names); + ii = 1; + while(ii <= l-1) + st1 = nth(names,ii); + jj = ii+1; + while ( jj <= l) + st2 = nth(names,jj); + if(strcmp(st1,st2)) + suffix = ["_",num2str(jj)]; + warning("sysgroup: %s name(%d) = %s name(%d) = %s", ... + kind,ii,kind,jj,st1); + strval = sprintf("%s%s",st2,suffix); + names(jj) = strval; + warning("sysgroup: changed %s name %d to %s",kind,jj,strval); + ## restart the check (just to be sure there's no further duplications) + ii = 0; jj = l; + endif + jj = jj+1; + endwhile + ii = ii+1; + endwhile +endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/system/sysidx.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/system/sysidx.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,54 @@ +## Copyright (C) 1996, 1998 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## idxvec = sysidx (sys, sigtype, signamelist) +## return indices of signals with specified signal names +## inputs: +## sys: OCST system data structure +## sigtype: signal type to be selected: "in", "out", "st" +## signamelist: list of desired signal names +## outputs: +## idxvec: vector of signal indices (appropriate for use with sysprune) + +function idxvec = sysidx (sys, sigtype, signamelist) + + if (nargin != 3) + usage ("idxvec = sysidx (sys, sigtype, signamelist)"); + elseif (! is_struct (sys)) + error ("sys must be a system data structure"); + elseif (! isstr (sigtype)) + error ("sigtype must be a string"); + elseif (rows (sigtype) != 1) + [nr, nc] = size (sigtype); + error ("sigtype (%d x %d) must be a single string", nr, nc); + endif + + ## extract correct set of signal names values + [idxvec, msg] = listidx (list ("in", "out", "st", "yd"), sigtype); + if (msg) + error ("invalid sigtype = %s", sigtype); + endif + + syssiglist = sysgetsignals (sys, sigtype); + [idxvec, msg] = listidx (syssiglist, signamelist); + if (length (msg)) + error ("sysidx (sigtype = %s): %s", sigtype, + strrep (msg, "strlist", "signamelist")); + endif + +endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/system/sysmin.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/system/sysmin.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,177 @@ +## Copyright (C) 1996 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## [retsys,nc,no] = sysmin(sys{,flg}); +## return a minimal (or reduced order) system +## inputs: +## sys: system data structure +## flg: 0 [default] return minimal system; state names lost +## : 1 return system with physical states removed that +## are either uncontrollable or unobservable +## (cannot reduce further without discarding physical +## meaning of states) +## outputs: +## retsys: returned system +## nc: number of controllable states in the returned system +## no: number of observable states in the returned system +## cflg: is_controllable(retsys) +## oflg: is_observable(retsys) + +## Author: A. S. Hodel + +function [retsys, nc, no, cflg, oflg] = sysmin (sys, flg); + + switch(nargin) + case(1), flg = 0; + case(2), jnk = flg; # dummy operation + otherwise, + usage("[retsys,nc,no] = sysmin(sys{,flg})"); + endswitch + dflg = is_digital(sys,2); + [n,nz,m,p] = sysdimensions(sys); + if(n*nz > 0) + # both continuous and discrete states + [aa,bb,cc,dd,tsam,n,nz,stnam,innam,outnam,yd] = sys2ss(sys); + crng = 1:n; + drng = n+(1:nz); + + # get minimal realization of continuous part + Ac = aa(crng,crng); + Acd = aa(crng,drng); + Adc = aa(drng,crng); + Ad = aa(drng,drng); + Bc = bb(crng,:); + Bd = bb(drng,:); + Cc = cc(:,crng); + Cd = cc(:,drng); + + cstnam = stnam(crng); + dstnam = stnam(drng); + cinnam = append(innam,stnam(drng)); + coutnam = append(outnam,stnam(drng)); + csys = ss2sys(Ac,[Bc,Acd],[Cc;Adc]); + csys = syssetsignals(csys,"st",cstnam); + csys = syssetsignals(csys,"in",cinnam); + csys = syssetsignals(csys,"out",coutnam); + + # reduce continuous system, recombine with discrete part + csys = sysmin(csys,flg); + cn = sysdimensions(csys); + + if(cn == 0) + # continuous states are removed; just reduce the discrete part + sys = sysprune(sys,1:p,1:m,drng); + retsys = sysmin(sys,flg); + else + # extract updated parameters from reduced continuous system + [caa,cbb,ccc,cdd,ctsam,cn,cnz,cstnam,cinnam,coutnam] = sys2ss(csys); + crng = 1:cn; + Ac = caa; + Bc = cbb(:,1:m); + Acd = cbb(:,m+(1:nz)); + Cc = ccc(1:p,:); + Adc = ccc(p + (1:nz),:); + + # recombine to reduce discrete part of the system + dinnam = append(innam,cstnam); + doutnam = append(outnam,cstnam); + dsys = ss2sys(Ad,[Bd,Adc],[Cd;Acd],[],tsam); + dsys = syssetsignals(dsys,"st",dstnam); + dsys = syssetsignals(dsys,"in",dinnam); + dsys = syssetsignals(dsys,"out",doutnam); + + # reduce discrete subsystem + dsys = sysmin(dsys); + [n1,nz] = sysdimensions(dsys); + if(nz == 0) + # discrete subsystem is not needed + retsys = sysprune(csys,1:p,1:m); + else + # combine discrete, continuous subsystems + [Ad,dbb,dcc] = sys2ss(dsys); + dstnam = sysgetsignals(dsys,"st"); + Bd = dbb(:,1:m); + Adc = dbb(:,m+(1:cn)); + Cd = dcc(1:p,:); + Acd = dcc(p+(1:cn),:); + stnam = append(cstnam,dstnam); + aa = [Ac, Acd; Adc, Ad]; + bb = [Bc; Bd]; + cc = [Cc, Cd]; + retsys = ss2sys([Ac, Acd; Adc, Ad], [Bc ; Bd], [Cc, Cd], dd, tsam, ... + cn, nz, stnam, innam, outnam, find(yd == 1)); + end + endif + else + Ts = sysgettsam(sys); + switch(flg) + case(0), + ## reduce to a minimal system + [aa,bb,cc,dd] = sys2ss(sys); + [cflg,Uc] = is_controllable(aa,bb); + if(!cflg) + ## reduce to controllable states + if(!isempty(Uc)) + aa = Uc'*aa*Uc; + bb = Uc'*bb; + cc = cc*Uc; + else + aa = bb = cc = []; + endif + endif + if(!isempty(aa)) + [oflg,Uo] = is_observable(aa,cc); + if(!oflg) + if(!isempty(Uo)) + aa = Uo'*aa*Uo; + bb = Uo'*bb; + cc = cc*Uo; + else + aa = bb = cc = []; + endif + endif + endif + switch(dflg) + case(0), + nc = no = nn = columns(aa); + nz = 0; + case(1), + nc = no = nz = columns(aa); + nn = 0; + endswitch + innam = sysgetsignals(sys,"in"); + outnam= sysgetsignals(sys,"out"); + retsys = ss2sys(aa,bb,cc,dd,Ts,nn,nz,[],innam,outnam); + case(1), + ## reduced model with physical states + [cflg,Uc] = is_controllable(sys); xc = find(max(abs(Uc')) != 0); + [oflg,Uo] = is_observable(sys); xo = find(max(abs(Uo')) != 0); + xx = intersection(xc,xo); + if(isempty(xx)) xx = 0; endif # signal no states in reduced model + retsys = sysprune(sys,[],[],xx); + otherwise, + error ("invalid value of flg = %d", flg); + endswitch + if(sysdimensions(retsys,"st") > 0) + [cflg,Uc] = is_controllable(retsys); nc = columns(Uc); + [oflg,Uo] = is_observable(retsys); no = columns(Uo); + else + nc = no = 0; + endif + endif +endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/system/sysmult.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/system/sysmult.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,114 @@ +## Copyright (C) 1996, 1999 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{sys} =} sysmult (@var{Asys}, @var{Bsys}) +## Compute @math{sys = Asys*Bsys} (series connection): +## @example +## @group +## u ---------- ---------- +## --->| Bsys |---->| Asys |---> +## ---------- ---------- +## @end group +## @end example +## A warning occurs if there is direct feed-through +## from an input of Bsys or a continuous state of Bsys through a discrete +## output of Bsys to a continuous state or output in Asys (system data +## structure does not recognize discrete inputs). +## @end deftypefn + +## Author: John Ingram +## Created: July 1996 +## updated for variable number of arguments by A. S. Hodel July 1999 + +function sys = sysmult (...) + + if(nargin < 1) + usage("sysmult: sys = sysmult(Asys{,Bsys,...})"); + endif + + ## collect all arguments + arglist = list(); + va_start(); + for kk=1:nargin + arglist(kk) = va_arg(); + if(!is_struct(nth(arglist,kk))) + error("sysadd: argument %d is not a data structure",kk); + endif + endfor + + ## check system dimensions + [n,nz,mg,pg,Gyd] = sysdimensions(nth(arglist,1)); + for kk=2:nargin + [n,nz,mh,ph,Hyd] = sysdimensions(nth(arglist,kk)); + if(mh != pg) + error("arg %d has %d outputs; arg %d has vs %d inputs",kk,ph,kk-1,mg); + endif + [n,nz,mg,pg,Gyd] = sysdimensions(nth(arglist,kk)); # for next iteration + endfor + + ## perform the multiply + if(nargin == 2) + Asys = nth(arglist,1); Bsys = nth(arglist,2); + + [An,Anz,Am,Ap] = sysdimensions(Asys); + [Bn,Bnz,Bm,Bp] = sysdimensions(Bsys); + + [Aa,Ab,Ac,Ad,Atsam,An,Anz,Astname,Ainname,Aoutname,Ayd] = sys2ss(Asys); + [Ba,Bb,Bc,Bd,Btsam,Bn,Bnz,Bstname,Binname,Boutname,Byd] = sys2ss(Bsys); + + if(Byd) + ## check direct feed-through of inputs through discrete outputs + alist = find(Byd); + if(An) + bd = Ab(1:An)* Bd(alist,:); + if(norm(bd,1)) + warning("sysmult: inputs -> Bsys discrete outputs -> continous states of Asys"); + endif + endif + ## check direct feed-through of continuous state through discrete outputs + if(Bn) + bc = Ab(1:An)* Bc(alist,1:(Bn)); + if( norm(bc,1) ) + warning("sysmult: Bsys states -> Bsys discrete outputs -> continuous states of Asys"); + endif + endif + endif + + ## change signal names to avoid spurious warnings from sysgroup + Asys = syssetsignals(Asys,"in",sysdefioname(Am,"A_sysmult_tmp_name")); + Bsys = syssetsignals(Bsys,"out",sysdefioname(Bp,"B_sysmult_tmp_name")); + + sys = sysgroup(Asys,Bsys); + + ## connect outputs of B to inputs of A + sys = sysconnect(sys,Ap+(1:Bp),1:Am); + + ## now keep only outputs of A and inputs of B + sys = sysprune(sys,1:Ap,Am+(1:Bm)); + + else + ## multiple systems (or a single system); combine together one by one + sys = nth(arglist,1); + for kk=2:length(arglist) + sys = sysmult(sys,nth(arglist,kk)); + endfor + endif + +endfunction + diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/system/sysout.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/system/sysout.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,151 @@ +## Copyright (C) 1996 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## -*- texinfo -*- +## @deftypefn {Function File} {} sysout (@var{sys}@{, @var{opt}@}) +## print out a system data structure in desired format +## @table @var +## @item sys +## system data structure +## @item opt +## Display option +## @table @code +## @item [] +## primary system form (default); see @ref{sysgettype}. +## @item "ss" +## state space form +## @item "tf" +## transfer function form +## @item "zp" +## zero-pole form +## @item "all" +## all of the above +## @end table +## @end table +## @end deftypefn + +## Author: A. S. Hodel +## Created: 1995-1996 + +function retsys = sysout (sys, opt) + + if( (nargin < 1) || (nargin > 2) ) + usage("sysout(sys[,opt])"); + endif + + if(isempty(sys)) + retsys = sys; + warning("sysout: empty system") + return; + endif + + if(! is_struct(sys)) + disp("sysout: input must be a system structure") + endif + + ## set up output type array + if( nargin == 1 ) + opt = sysgettype(sys); + else + if( ! (strcmp(opt,"ss") + strcmp(opt,"tf") + ... + strcmp(opt,"zp") + strcmp(opt,"all") ) ) + error("opt must be one of [], \"ss\", \"tf\", \"zp\", or \"all\""); + endif + endif + + ## now check output for each form: + [nn,nz,mm,pp] = sysdimensions(sys); + if( mm > 0) + disp("Input(s)") + disp(outlist(sysgetsignals(sys,"in")," ")); + else + disp("Input(s): none"); + endif + if (pp > 0) + disp("Output(s):") + disp(outlist(sysgetsignals(sys,"out"), ... + " ",sysgetsignals(sys,"yd")) ); + else + disp("Output(s): none"); + endif + if(sysgettsam(sys) > 0) + disp(["Sampling interval: ",num2str(sysgettsam(sys))]); + str = "z"; + else + str = "s"; + endif + + ## transfer function form + if( strcmp(opt,"tf") + strcmp(opt,"all") ) + sys = sysupdate(sys,"tf"); #make sure tf is up to date + disp("transfer function form:") + [num,den] = sys2tf(sys); + tfout(num,den,str); + endif + + if( strcmp(opt,"zp") + strcmp(opt,"all") ) + sys = sysupdate(sys,"zp"); #make sure zp is up to date + disp("zero-pole form:") + [zer,pol,kk] = sys2zp(sys); + zpout(zer, pol, kk,str) + endif + + if( strcmp(opt,"ss") + strcmp(opt,"all") ) + sys = sysupdate(sys,"ss"); + disp("state-space form:"); + disp([num2str(nn)," continuous states, ", num2str(nz)," discrete states"]); + if( nn+nz > 0) + disp("State(s):") + xi = (nn+1):(nn+nz); + xd = zeros(1,nn+nz); + if(!isempty(xi)) + xd(xi) = 1; + endif + disp(outlist(sysgetsignals(sys,"st")," ",xd)); + else + disp("State(s): none"); + endif + + ## display matrix values? + dmat = (max( [ (nn+nz), mm, pp ] ) <= 32); + + printf("A matrix: %d x %d\n",sysdimensions(sys,"st"), + sysdimensions(sys,"st")); + [aa,bb,cc,dd] = sys2ss(sys); + if(dmat) disp(aa); endif + + printf("B matrix: %d x %d\n",sysdimensions(sys,"st"), + sysdimensions(sys,"in")); + if(dmat) disp(bb); endif + + printf("C matrix: %d x %d\n",sysdimensions(sys,"out"), + sysdimensions(sys,"st")); + if(dmat) disp(cc); endif + + printf("D matrix: %d x %d\n",sysdimensions(sys,"out"), + sysdimensions(sys,"in")); + if(dmat) disp(dd); endif + endif + + if(nargout >= 1) + retsys = sys; + endif + + ## restore global variable + +endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/system/sysprune.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/system/sysprune.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,157 @@ +## Copyright (C) 1996, 1998 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{retsys} =} sysprune (@var{Asys}, @var{out_idx}, @var{in_idx}) +## Extract specified inputs/outputs from a system +## +## @strong{Inputs} +## @table @var +## @item Asys +## system data structure +## @item out_idx +## @itemx in_idx +## list of connections indices; the new +## system has outputs y(out_idx(ii)) and inputs u(in_idx(ii)). +## May select as [] (empty matrix) to specify all outputs/inputs. +## @end table +## +## @strong{Outputs} +## @var{retsys}: resulting system +## @example +## @group +## ____________________ +## u1 ------->| |----> y1 +## (in_idx) | Asys | (out_idx) +## u2 ------->| |----| y2 +## (deleted)-------------------- (deleted) +## @end group +## @end example +## @end deftypefn + +## Author: A. S. Hodel +## Created: August 1995 +## Updated by John Ingram 7-15-96 + +function sys = sysprune (sys, output_idx, input_idx, state_idx) + + if( nargin < 3 | nargin > 4 ) + usage("retsys = sysprune(sys,output_idx,input_idx{,state_idx})"); + elseif(nargin < 4) + state_idx = []; + endif + + ## default: no action + [nn,nz,mm,pp] = sysdimensions(sys); + if(isempty(output_idx)) output_idx = 1:pp; endif + if(isempty(input_idx)) input_idx = 1:mm; endif + if(isempty(state_idx)) state_idx = 1:(nn+nz); endif + + ## check dimensions + if( !(is_vector(output_idx) | isempty(output_idx) ) ) + if(!is_matrix(output_idx)) + error("sysprune: bad argument passed for output_idx"); + else + error("sysprune: output_idx (%d x %d) must be a vector or empty", ... + rows(output_idx),columns(output_idx)); + endif + elseif(is_duplicate_entry(output_idx)) + error("sysprune: duplicate entries found in output_idx"); + endif + + if( !(is_vector(input_idx) | isempty(input_idx) ) ) + if(!is_matrix(input_idx)) + error("sysprune: bad argument passed for input_idx"); + else + error("sysprune: input_idx (%d x %d) must be a vector or empty", ... + rows(input_idx),columns(input_idx)); + endif + elseif(is_duplicate_entry(input_idx)) + error("sysprune: duplicate entries found in input_idx"); + endif + + if( !(is_vector(state_idx) | isempty(state_idx) ) ) + if(!is_matrix(state_idx)) + error("sysprune: bad argument passed for state_idx"); + else + error("sysprune: state_idx (%d x %d) must be a vector or empty", ... + rows(state_idx),columns(state_idx)); + endif + elseif(nn+nz > 0) + if(is_duplicate_entry(state_idx)) + error("sysprune: duplicate entries found in state_idx"); + endif + endif + + lo = length(output_idx); + li = length(input_idx); + lst = length(state_idx); + + if( !is_struct(sys)) + error("Asys must be a system data structure (see ss2sys, tf2sys, or zp2sys)") + elseif(pp < lo) + error([num2str(lo)," output_idx entries, system has only ", ... + num2str(pp)," outputs"]); + elseif(mm < li) + error([num2str(li)," input_idx entries, system has only ", ... + num2str(mm)," inputs"]); + elseif(nn+nz < lst) + error([num2str(lst)," state_idx entries, system has only ", ... + num2str(nn+nz)," states"]); + endif + + [aa,bb,cc,dd,tsam,nn,nz,stnam,innam,outnam,yd] = sys2ss(sys); + + ## check for valid state permutation + if(nn & nz) + c_idx = find(state_idx <= nn); + if(!isempty(c_idx)) max_c = max(c_idx); + else max_c = 0; endif + d_idx = find(state_idx > nn); + if(!isempty(d_idx)) min_d = min(d_idx); + else min_d = nn+nz; endif + if(max_c > min_d) + warning("sysprune: state_idx(%d)=%d (discrete) preceeds", ... + min_d,state_idx(min_d)); + warning(" state_idx(%d)=%d (continuous)",... + max_c,state_idx(max_c)); + warning("sysprune: sys has %d continuous states, %d discrete states", ... + nn,nz); + error("continuous/discrete state partition not preserved ; see ss2sys"); + endif + endif + + idx = input_idx; + odx = output_idx; + if(isempty(state_idx)) + idx = []; + odx = []; + endif + aa = aa(state_idx,state_idx); + bb = bb(state_idx,idx); + cc = cc(odx,state_idx); + dd = dd(output_idx,input_idx); + yd = yd(output_idx); + + innam = innam(input_idx); + outnam = outnam(output_idx); + stnam = stnam(state_idx); + nn1 = length(find(state_idx <= nn)); + nz1 = length(find(state_idx > nn)); + sys = ss2sys(aa,bb,cc,dd,tsam,nn1,nz1,stnam,innam,outnam,find(yd)); +endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/system/sysreorder.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/system/sysreorder.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,58 @@ +## Copyright (C) 1996 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{pv} =} sysreorder (@var{vlen}, @{var{list}) +## +## @strong{Inputs} +## @var{vlen}=vector length, @var{list}= a subset of @code{[1:vlen]}, +## +## @strong{Outputs} +## @var{pv}: a permutation vector to order elements of @code{[1:vlen]} in +## @code{list} to the end of a vector. +## +## Used internally by @code{sysconnect} to permute vector elements to their +## desired locations. +## @end deftypefn + +## Author: A. S. Hodel +## Created: August 1995 + +function pv = sysreorder (vlen, list) + + ## disp('sysreorder: entry') + + pv = 1:vlen; + ## make it a row vector + list = reshape(list,1,length(list)); + A = pv'*ones(size(list)); + B = ones(size(pv'))*list; + X = (A != B); + if(!is_vector(X)) + y = min(X'); + else + y = X'; + endif + z = find(y == 1); + if(!isempty(z)) + pv = [z, list]; + else + pv = list; + endif + +endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/system/sysrepdemo.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/system/sysrepdemo.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,495 @@ +## Copyright (C) 1996, 1998 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## -*- texinfo -*- +## @deftypefn {Function File} {} sysrepdemo +## Tutorial for the use of the system data structure functions. +## @end deftypefn + +## Author: A. S. Hodel +## Created: June 1995 +## Revised Aug 1995 for system data structure format + +function sysrepdemo () + + save_val = page_screen_output; + page_screen_output = 1; + + disp("System representation demo:") + num = [5, -1]; + denom = [1, -2, 6]; + a = b = c = []; + syschoice = -1; + ch_init = 2; + ch_extract = ch_init+1; + ch_update = ch_extract+1; + ch_view = ch_update+1; + ch_details = ch_view+1; + ch_quit = ch_details+1; + while(syschoice != ch_quit) + disp(" ") + syschoice = menu("Octave System Representation Menu", ... + "General overview of system representation (DO THIS FIRST)", ... + "Initialize a system (ss2sys, tf2sys, zp2sys)", ... + "Extract data from a system(sys2ss, sys2tf, sys2zp, etc.)", ... + "Update internal representation (sysupdate)", ... + "View the internal contents of a system (sysout)", ... + "Details of internal representation", ... + "Return to main menu"); + if(syschoice == 1) # general overview + disp("The Octave Control Systems Toolbox (OCST) was designed to") + disp("provide a simple user interface to a powerful set of tools.") + disp(" ") + disp(" ----------") + disp(" input(s) ---->| System | ---> output(s) ") + disp(" ----------") + disp(" ") + disp("Like other computer-aided control system design tools, the OCST") + disp("enables users to enter their descriptions of dynamic systems in ") + disp("their preferred form (state space, transfer function, or "); + disp("zero-pole format). "); + disp("The OCST stores system descriptions in a single variable data "); + disp("structure that allows for continuous time, discrete-time, or mixed "); + disp("(sampled-data) systems. "); + disp(" "); + disp("This single variable description of dynamic systems greatly simplifies "); + disp("both the code of the OCST as well as the user interface, since only") + disp("one variable is passed per system, regardless of the internal ") + disp("representation used in the data structure. As a result, the "); + disp("likelihood of user error is greatly reduced when calling OCST") + disp("functions. Further, all OCST functions have been written to") + disp("provide meaningful warning or error message to assist the user") + disp("in correcting their programming errors while using the OCST.") + disp("The details of the internal representation can be seen in "); + disp(["menu option ",num2str(ch_details)]); + disp("The data structure used in the OCST is called a \"system data structure.\""); + disp("A system data structure is contstructed with one of:") + disp(" fir2sys (FIR transfer function to system)") + disp(" ss2sys (state space matrices to system)") + disp(" tf2sys (SISO transfer function to system)") + disp(" zp2sys (SISO zero/pole/leading coefficient to system)") + disp(" ") + disp(["These functions are discussed in in menu option ",num2str(ch_init)]) + disp("The data in a system may be extracted using ") + disp(" sys2fir (FIR transfer function from system") + disp(" sys2ss (state space matrices from system)") + disp(" sys2tf (SISO transfer function from system)") + disp(" sys2zp (SISO zero/pole/leading coefficient from system)") + disp(" ") + disp(["These functions are discussed in menu option ", ... + num2str(ch_extract)]); + disp("Other options discussed under this menu are updating the internal") + disp("representation form of a system data structure with sysupdate and printing") + disp("the description of a dynamic system to the screen with sysout.") + disp(" ") + disp("Once the user is familiar with these commands, the rest of the ") + disp("OCST package will be quite easy to use.") + elseif(syschoice == ch_init) % Initialize + disp("Initialization of a system:"); + disp(" "); + formopt = 0; + while(formopt != 4) + disp("Three data formats may be used to initialize a system:") + formopt = menu("System data structure initialization menu", ... + "State space form (ss2sys)", ... + "Transfer function form (tf2sys)", ... + "zero-pole form (zp2sys)", ... + "Return to System representation menu"); + if(formopt == 1) + disp("State space representation of a system is based on the usual") + disp("multi-variable differential equations") + disp(" ") + disp(" . ") + disp(" x = A x + B u -or - x(k+1) = A x(k) + B u(k) ") + disp(" y = C x + D u y(k) = C x(k) + D u(k) ") + disp(" ") + disp("for matrices A, B, C, D of appropriate dimension.") + disp(" ") + ssopt = 0; + ssquit = 5; + while(ssopt < ssquit) + ssopt = menu("State space initialization examples", ... + "Double integrator example", ... + "Double delay (discrete-time) example", ... + "Summing junction (D-matrix only) example", ... + "ss2sys details (help ss2sys)", ... + "return to system initialization menu", ... + "return to system representation main menu"); + if(ssopt == 1) + disp("Example: construct a system representation of a") + disp("double integrator via state-space form") + cmd = "a = [0, 1; 0, 0];"; + run_cmd + cmd = "b = [0; 1];"; + run_cmd + cmd = "c = [1, 0];"; + run_cmd + cmd = "sys = ss2sys(a,b,c);"; + run_cmd + disp("The state space form of the system is seen via sysout:") + cmd = "sysout(sys)"; + run_cmd + disp("Notice that the Octave controls toolbox automatically") + disp("assigns names to the states, inputs and outputs,") + disp("and that the D matrix was filled in automatically.") + disp("We verify that it's a double integrator via sysout:") + cmd = "sysout(sys,""tf"")"; + run_cmd + prompt + elseif(ssopt == 2) + disp("Example: discrete-time double-delay:") + disp("This example is identical to the double-integrator,") + disp("except that it is a discrete-time system, and so has") + disp("a sampling interval. We arbitrarily select T=1e-3."); + cmd = "a = [0, 1; 0, 0];"; + run_cmd + cmd = "b = [0; 1];"; + run_cmd + cmd = "c = [1, 0];"; + run_cmd + cmd = "sys=ss2sys(a,b,c,[],1e-3);"; + run_cmd + cmd = "sysout(sys)"; + run_cmd + disp("Notice that the D matrix was filled in automatically.") + disp("This is done if D is input as the empty matrix.") + disp(" ") + disp("Notice also that the output y_1 is labelled as a discrete") + disp("output. The OCST data structure keeps track of states") + disp("and output signals that are produced by the discrete-time") + disp("portion of a system. Discrete states and outputs are ") + disp("implemented as shown in the block diagram below:") + disp(" ") + disp(" ") + disp(" _________ ________ x(kT) ________________") + disp("f(t)-->|sampler|-->| delay |----->|zero order hold| -->") + disp(" --------- -------- ----------------") + disp(" ") + disp(" ___________ _______________") + disp("f(t)-->| sampler |-->|zero-order hold| --> y(discrete)") + disp(" ----------- ---------------") + disp(" ") + disp("where f(t) is an input signal to either the output or the") + disp(" discrete state.") + disp(" ") + disp("The OCST does not implement samplers on inputs to continuous") + disp("time states (i.e., there are no samplers implicit in the B") + disp("or D matrices unless there are corresponding discrete") + disp("outputs or states. The OCST provides warning messages when") + disp("if this convention is violated.") + prompt + elseif(ssopt == 3) + disp("A summing junction that computes e(t) = r(t) - y(t) may be"); + disp("constructed as follows:"); + disp("First, we set the matrix D:") + cmd = "D = [1, -1];"; + run_cmd + disp("ss2sys allows the initialization of signal and state names") + disp("(see option 4), so we initialize these as follows:") + cmd = "inname = list(\"r(t)\",\"y(t)\");"; + run_cmd; + cmd = "outname = \"e(t)\";"; + run_cmd + disp("Since the system is continous time and without states,") + disp("the ss2sys inputs tsam, n, and nz are all zero:") + cmd = "sys = ss2sys([],[],[],D,0,0,0,[],inname,outname);"; + run_cmd + disp("The resulting system is:") + cmd = "sysout(sys)"; + run_cmd + disp("A discrete-time summing block can be implemented by setting") + disp("the sampling time positive:") + cmd = "sys = ss2sys([],[],[],D,1e-3,0,0,[],inname,outname);"; + run_cmd + disp("The resulting system is:") + cmd = "sysout(sys)"; + run_cmd + prompt + elseif(ssopt == 4) + help ss2sys + disp(" ") + disp(" ") + disp("Notice that state-space form allows a single system to have") + disp("both continuous and discrete-time states and to have both continuous") + disp("and discrete-time outputs. Since it's fairly easy to make an") + disp("error when mixing systems of this form, the Octave controls") + disp("toolbox attempts to print warning messages whenever something") + disp("questionable occurs.") + elseif(ssopt == 6) + formopt = 4; # return to main menu + endif + endwhile + elseif(formopt == 2) + tfopt = 0; + while(tfopt < 5) + tfopt = menu("Transfer function initialization menu", ... + "Continuous time initialization" , ... + "Discrete time initialization" , ... + "User specified signal names" , ... + "tf2sys details (help tf2sys)", ... + "Return to system initialization menu", ... + "Return to system representation main menu"); + if(tfopt == 1) # continuous time + disp("A transfer function is represented by vectors of the") + disp("coefficients of the numerator and denominator polynomials"); + disp(" ") + disp("For example: the transfer function"); + disp(" "); + num = [5, -1]; + denom = [1, -2, 6]; + tfout(num,denom); + disp(" ") + disp("is generated by the following commands:") + cmd = "num = [5, -1]"; + run_cmd + cmd = "denom = [1, -2, 6]"; + run_cmd + cmd = "sys = tf2sys(num,denom);"; + run_cmd + disp("alternatively, the system can be generated in a single command:"); + cmd = "sys = tf2sys([5, -1], [1, -2, 6]);"; + run_cmd + disp("Notice the output of sys: it is an Octave data structure.") + disp("The details of its member variables are explained under") + disp("System Representation Menu option 5 (the details of system form)") + disp(" "); + disp("The data structure can be observed with the sysout command:") + cmd = "sysout(sys)"; + run_cmd + disp("Notice that Octave assigns names to inputs and outputs.") + disp("The user may manually select input and output names; see option 3"); + prompt + elseif(tfopt == 2) # discrete time + disp("A transfer function is represented by vectors of the") + disp("coefficients of the numerator and denominator polynomials"); + disp("Discrete-time transfer functions require ") + disp("the additional parameter of a sampling period:") + cmd = "sys=tf2sys([5, -1], [1, 2, -6], 1e-3);"; + run_cmd + cmd = "sysout(sys)"; + run_cmd + disp("The OCST recognizes discrete-time transfer functions and") + disp("accordingly prints them with the frequency domain variable z."); + disp("Notice that Octave assigns names to inputs and outputs.") + disp("The user may set input and output names; see option 3"); + elseif(tfopt == 3) # user specified names + disp("The OCST requires all signals to have names. The OCST assigned default"); + disp("names to the signals in the other examples. We may initialize a transfer"); + disp("function with user-specified names as follows: Consider a simple ") + disp("double-integrator model of aircraft roll dynamics with ") + disp("input \"aileron angle\" and output \"theta\". A ") + disp("system for this model is generated by the command") + cmd = "aircraft=tf2sys(1, [1, 0, 0], 0,\"aileron angle\",\"theta\");"; run_cmd + disp("The sampling time parameter 0 indicates that the system") + disp("is continuous time. A positive sampling time indicates a") + disp("discrete-time system (or sampled data system).") + cmd = "sysout(aircraft)"; + run_cmd + disp("Notice that the user-selected signal names are listed.") + disp("These signal names are used in OCST plots and design functions."); + disp("(Run the frequency response demo to see an example of the use of "); + disp("signal names in plots.)") + prompt + elseif(tfopt == 4) # help + help tf2sys + prompt + elseif(tfopt == 6) # return to main menu + formopt = 4; + endif + endwhile + elseif (formopt == 3) + zpopt = 0; + while(zpopt < 5) + zpopt = menu("Zero-pole initialization menu", ... + "Continuous time initialization" , ... + "Discrete time initialization" , ... + "User specified signal names" , ... + "zp2sys details (help zp2sys)", ... + "Return to system initialization menu", ... + "Return to system representation main menu"); + if(zpopt == 1) # continuous time + disp("A zero-pole form representation of a system includes vectors") + disp("of the system poles and zeros and a scalar leading coefficient."); + disp(" ") + disp("For example: the transfer function"); + disp(" "); + k = 5; + num = [5, -1]; + denom = [1, -2, 6]; + zpout(num,denom,k); + disp(" ") + disp("is generated by the following commands:") + cmd = "num = [5, -1]"; + run_cmd + cmd = "denom = [1, -2, 6]"; + run_cmd + cmd = "k = 5"; + run_cmd + cmd = "sys = zp2sys(num,denom,k);"; + run_cmd + disp("alternatively, the system can be generated in a single command:"); + cmd = "sys = zp2sys([5, -1],[1, -2, 6],5);"; + run_cmd + disp("Notice the output of sys: it is an Octave data structure.") + disp("The details of its member variables are explained under") + disp("System Representation Menu option 5 (the details of system form)") + disp(" "); + disp("The data structure can be observed with the sysout command:") + cmd = "sysout(sys)"; + run_cmd + disp("Notice that Octave assigns names to inputs and outputs.") + disp("The user may manually select input and output names; see option 3"); + prompt + elseif(zpopt == 2) # discrete time + disp("A zero-pole form representation of a system includes vectors") + disp("of the system poles and zeros and a scalar leading coefficient."); + disp(" ") + disp("Discrete-time systems require the additional parameter of a sampling period:") + cmd = "sys=zp2sys([5, -1],[1, 2, -6],5,1e-3);"; + run_cmd + cmd = "sysout(sys)"; + run_cmd + disp("The OCST recognizes discrete-time transfer functions and") + disp("accordingly prints them with the frequency domain variable z."); + disp("Notice that Octave assigns names to inputs and outputs.") + disp("The user may set input and output names; see option 3"); + elseif(zpopt == 3) # user specified names + disp("The OCST requires all signals to have names. The OCST assigned default"); + disp("names to the signals in the other examples. We may initialize a transfer"); + disp("function with user-specified names as follows: Consider a simple ") + disp("double-integrator model of aircraft roll dynamics with ") + disp("input \"aileron angle\" and output \"theta\". A ") + disp("system for this model is generated by the command") + cmd = "aircraft=zp2sys([],[0, 0],1,0,\"aileron angle\",\"theta\");"; run_cmd + disp("The sampling time parameter 0 indicates that the system") + disp("is continuous time. A positive sampling time indicates a") + disp("discrete-time system (or sampled data system).") + cmd = "sysout(aircraft)"; + run_cmd + disp("Notice that the user-selected signal names are listed.") + disp("These signal names are used in OCST plots and design functions."); + disp("(Run the frequency response demo to see an example of the use of "); + disp("signal names in plots.)") + prompt + elseif(zpopt == 4) # help + help zp2sys + prompt + elseif(zpopt == 6) # return to main menu + formopt = 4; + endif + endwhile + endif + endwhile + elseif(syschoice == ch_extract) # extract system information + disp("Extract information from a system data structure in a selected format:") + disp("The actions of operations ss2sys, tf2sys, and zp2sys are reversed by") + disp("respective functions sys2ss, sys2tf, and sys2zp. The latter two"); + disp("functions are applicable only to SISO systems.") + formopt = 0; + while(formopt != 8) + formopt = menu("Extract system information", ... + "in state space form (sys2ss)", ... + "in transfer function form (sys2tf)", ... + "in zero pole form (sys2zp)", ... + "signal names (sysgetsignals,syssetsignals)", ... + "sampling time (sysgettsam)", ... + "signal dimensions (sysdimensions)", ... + "primary system type (sysgettype)", ... + "Return to system representation menu"); + if(formopt == 1) + help sys2ss + elseif(formopt == 2) + help sys2tf + elseif(formopt == 3) + help sys2zp + elseif(formopt == 4) + help sysgetsignals + cmd="sys=ss2sys(rand(4),rand(4,2),rand(3,4));"; + run_cmd + printf("Example: All signals names can be extracted by\n"); + cmd = "[Ast,Ain,Aout,Ayd] = sysgetsignals(sys)"; + run_cmd + printf("Example: Input signal names can be extracted as\n"); + cmd = "Ain = sysgetsignals(sys,\"in\")"; + run_cmd + printf("Example: The name of output signal 2 can be extracted as\n"); + cmd = "Aout = sysgetsignals(sys,\"out\",2)"; + run_cmd + printf("\nNotice that Aout is returned as a list; the signal name\n"); + printf("itself is obtained by specifying the input parameter strflg\n"); + cmd = "Aout = sysgetsignals(sys,\"out\",2,1)"; + run_cmd + prompt + cmd = "help syssetsignals"; + run_cmd + printf("Example: set input 2 name to \"motor voltage\"\n"); + cmd = "sys = syssetsignals(sys,\"in\",\"motor voltage\",2); sysout(sys)"; + run_cmd + + printf("Other syssetsignals demos are in the Block diagram demo program bddemo\n"); + elseif(formopt == 5) + help sysgettsam + elseif(formopt == 6) + help sysdimensions + elseif(formopt == 7) + help sysgettype + endif + prompt + endwhile + elseif(syschoice== ch_update) + disp("The OCST system data structure format will store a system in the same format") + disp("as that with which it was initialized. For example, consider the following:") + cmd = "sys=zp2sys([1, 2],[3, 4, 5],6)"; + run_cmd + disp(" ") + disp("Notice the internal variables in the structure include zer, pol, and k,") + disp("the required variables for zero-pole form. We can update the system") + disp("to include state-space form as follows:") + cmd = "sys = sysupdate(sys,\"ss\")"; + run_cmd + disp(" ") + disp("Now the sys data structure includes variables a, b, c, and d, as well") + disp("the default state names stname. sysupdate is usually used internally in") + disp("the OCST, but can be used manually if desired. A full description of") + disp("sysupdate is as follows:") + help sysupdate + prompt + elseif(syschoice == ch_view) + disp("The sysout command can be used to view a system in any desired format.") + disp("For example, consider the system created as follows:") + cmd = "aircraft=zp2sys(1,[0, 0],1,0,\"aileron angle\",\"theta\");"; run_cmd + disp("The system may be viewed in its default format (zero-pole) as follows") + cmd = "sysout(aircraft)"; + run_cmd + disp(" ") + disp("The system may be viewed in state-space or transfer function form as well:") + cmd = "sysout(aircraft,\"ss\")"; + run_cmd + cmd = "sysout(aircraft,\"tf\")"; + run_cmd + disp("A complete description of sysout is below:") + help sysout + prompt + elseif(syschoice == ch_details) + packedform + endif + + endwhile + page_screen_output = save_val; +endfunction + diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/system/sysscale.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/system/sysscale.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,139 @@ +## Copyright (C) 1996, 1998 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{sys} =} sysscale (@var{sys}, @var{outscale}, @var{inscale}@{, @var{outname}, @var{inname}@}) +## scale inputs/outputs of a system. +## +## @strong{Inputs} +## sys: structured system +## outscale, inscale: constant matrices of appropriate dimension +## +## @strong{Outputs} +## @var{sys}: resulting open loop system: +## @example +## ----------- ------- ----------- +## u --->| inscale |--->| sys |--->| outscale |---> y +## ----------- ------- ----------- +## @end example +## If the input names and output names (each a list of strings) +## are not given and the scaling matrices +## are not square, then default names will be given to the inputs and/or +## outputs. +## +## A warning message is printed if outscale attempts to add continuous +## system outputs to discrete system outputs; otherwise @var{yd} is +## set appropriately in the returned value of @var{sys}. +## @end deftypefn + +## Author: A. S. Hodel +## Created: August 1995 +## modified by John Ingram 7-15-96 + +function sys = sysscale (sys, outscale, inscale, outname, inname) + + if( (nargin < 3) || (nargin > 5) ) + usage("retsys = sysscale(Asys,output_list,input_list{,inname,outname})"); + elseif (!is_struct(sys)) + error("sys must be a structured system"); + endif + + [nn,nz,mm,pp] = sysdimensions(sys); + + ## check for omitted scales + if(isempty(outscale)) outscale = eye(pp); endif + if(isempty(inscale)) inscale = eye(mm); endif + + ## check dimensions of scaling matrices + if(mm!=rows(inscale)) + error("inscale(%dx%d) should have %d rows(# system inputs)", ... + rows(inscale),columns(inscale),mm); + elseif( pp != columns(outscale) ) + error("outscale(%dx%d) should have %d columns(# system outputs)", ... + rows(outscale), columns(outscale),pp); + endif + + sysyd = sysgetsignals(sys,"yd"); + outc = find(sysyd==0); + outd = find(sysyd==1); + + if(length(outc) & length(outd)) + for ii = 1:rows(outscale) + nci = norm(outscale(ii,outc)); + ndi = norm(outscale(ii,outd)); + + if( nci & ndi) + warning("sysscale: outscale(%d,:) sums continuous and discrete outputs; setting output to cont",ii) + sysyd(ii) = 0; + else + sysyd(ii) = (ndi != 0); + endif + endfor + else + sysyd = ones(1,rows(outscale))*( length(outd) > 0); + endif + + ## check for SISO system type + if strcmp(sysgettype(sys),"tf") + [num,den,tsam,innam,outnam] = sys2tf(sys); + num = num*inscale*outscale; + sys = tf2sys(num,den,tsam,innam,outnam,find(sysyd)); + return + elseif strcmp(sysgettype(sys),"zp") + [zer,pol,kk,tsam,innam,outnam] = sys2zp(sys); + kk = kk*inscale*outscale; + sys = zp2sys(zer,pol,k,tsam,innam,outnam,find(sysyd)); + return + endif + + ## it's a state space system... + + [sysa,sysb,sysc,sysd,systsam, ... + sysn,sysnz,sysstname,sysinname,sysoutname,oldyd] = sys2ss(sys); + + sysb = sysb*inscale; + sysc = outscale*sysc; + sysd = outscale*sysd*inscale; + + if( !is_square(outscale) ) + ## strip extra output names (if any) + sysoutname = sysoutname(1:min(rows(outscale),columns(outscale))); + if( nargin < 4) + warning("sysscale: outscale not square, outname not specified"); + warning("sysscale: using default output names"); + outname = sysdefioname(rows(sysc),"y"); + endif + else + outname = sysoutname; + endif + if( !is_square(inscale) ) + ## strip extra output names (if any) + sysinname = sysinname(1:min(rows(inscale),columns(inscale))); + if(nargin < 5) + warning("sysscale: inscale not square, inname not specified"); + warning("sysscale: using default input names"); + inname = sysdefioname(columns(sysb),"u"); + endif + else + inname = sysgetsignals(sys,"in"); + endif + + sys = ss2sys(sysa,sysb,sysc,sysd,systsam,nn,nz,sysstname, ... + inname,outname,find(sysyd==1)); + +endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/system/syssetsignals.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/system/syssetsignals.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,227 @@ +## Copyright (C) 1996, 1998 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{retsys} =} syssetsignals (@var{sys}, @var{opt}, @var{names}@{, @var{sig_idx}@}) +## change the names of selected inputs, outputs and states. +## @strong{Inputs} +## @table @var +## @item sys +## system data structure +## +## @item opt +## change default name (output) +## +## @table @code +## @item "out" +## change selected output names +## @item "in" +## change selected input names +## @item "st" +## change selected state names +## @item "yd" +## change selected outputs from discrete to continuous or +## from continuous to discrete. +## @end table +## +## @item names +## @table @code +## @item opt = "out", "in", or "st" +## string or string array containing desired signal names or values. +## @item opt = "yd" +## To desired output continuous/discrete flag. +## Set name to 0 for continuous, or 1 for discrete. +## @end table +## @item list +## vector of indices of outputs, yd, inputs, or +## states whose respective names should be changed. +## +## Default: replace entire list of names/entire yd vector. +## @end table +## @strong{Outputs} +## @var{retsys=sys} with appropriate signal names changed +## (or yd values, where appropriate) +## +## @strong{Example} +## @example +## octave:1> sys=ss2sys([1 2; 3 4],[5;6],[7 8]); +## octave:2> sys = syssetsignals(sys,"st",str2mat("Posx","Velx")); +## octave:3> sysout(sys) +## Input(s) +## 1: u_1 +## Output(s): +## 1: y_1 +## state-space form: +## 2 continuous states, 0 discrete states +## State(s): +## 1: Posx +## 2: Velx +## A matrix: 2 x 2 +## 1 2 +## 3 4 +## B matrix: 2 x 1 +## 5 +## 6 +## C matrix: 1 x 2 +## 7 8 +## D matrix: 1 x 1 +## 0 +## @end example +## @end deftypefn + +## Author: John Ingram +## Created: August 1996 + +function retsys = syssetsignals (sys, opt, names, sig_idx) + + if (nargin < 3 | nargin > 4) + usage("retsys=syssetsignals(sys,opt,names{,sig_idx})"); + elseif (!is_struct(sys)) + error("sys must be a system data structure"); + elseif (isempty(opt)) + opt = "out"; + elseif( ! isstr(opt) ) + error("opt must be a string"); + elseif( ! (strcmp(opt,"out") + strcmp(opt,"yd") + ... + strcmp(opt,"in") + strcmp(opt,"st") ) ) + error("opt must be one of [], ""out"", ""yd"", ""in"", or ""st"""); + elseif(nargin == 4) + if(min(size(sig_idx)) > 1) + disp("syssetsignals: sig_idx=") + disp(sig_idx); + error("sig_idx must be a vector") + endif + endif + + sig_vals = sysgetsignals(sys,opt); + + ## make sure it's in state space form if state names are given + if(strcmp(opt,"st")) sys = sysupdate(sys,"ss"); endif + + if(strcmp(opt,"yd") == 0) + ## it's a signal name list we're changing + if(!is_list(names)) + names = list(names); + endif + if(!is_signal_list(names)) + if(isstr(nth(names,1))) + warning("syssetsignals(opt=%s): converting string matrix \"names\" to a list of strings",opt); + tmpstr = nth(names,1); + for ii=1:rows(tmpstr) + names(ii) = deblank(tmpstr(ii,:)); + endfor + else + names + error("parameter \"names\" must be a list of strings"); + endif + endif + nsigs = length(sig_vals); + + if(nargin == 3) + ## replace all signal names + if(length(names) != nsigs) + error("opt=%s, sig_idx omitted: names(len=%d) should have %d entries ", ... + opt,length(names),nsigs); + endif + sig_idx = 1:nsigs; + elseif(length(names) != length(sig_idx)) + ## replace specified signal names + error("opt=%s, sig_idx(len=%d), names(len=%d) mismatch",opt, ... + length(sig_idx), length(names)); + endif + + for ii=1:length(sig_idx) + jj = sig_idx(ii); + if(jj < 1 | jj > nsigs | jj != floor(jj+0.5)) + error("opt=%s, sig_idx(%d)=%d, %e: must be an integer between 1 and %d", ... + opt, ii, jj, jj, nsigs); + endif + sig_vals(jj) = nth(names,ii); + endfor + + else + ## update yd + ## 1st check pathological case: no outputs + nout = sysdimensions(sys,"out"); + if(nout == 0) + if(nargin != 3) + error("opt=%s, %d outputs, sysgetsignals cannot take 4 arguments", ... + yd,nout); + endif + if(!isempty(names)) + error("opt=%s, %d outputs, names is not empty"); + endif + sigvals = []; + else + nsigs = length(sig_vals); + if(!is_vector(names)) + error("syssetsignals: opt=yd, names(%dx%d) must be a vector", ... + rows(names), columns(names)); + endif + if(nargin == 3) + if(length(names) != nsigs) + error("opt=yd, sig_idx omitted: names(%d) should be length(%d)", ... + length(names), nsigs); + endif + sig_idx = 1:nsigs; + elseif(length(names) != length(sig_idx)) + error("opt=yd: length(names)=%d, length(sig_idx)=%d",length(names), ... + length(sig_idx) ); + endif + + badidx = find(names != 0 & names != 1); + if(! isempty(badidx) ) + for ii=1:length(badidx) + warning("syssetsignals: opt=yd: names(%d)=%e, must be 0 or 1", ... + badidx(ii), names(badidx(ii)) ); + endfor + error ("opt=yd: invalid values in names"); + endif + + for ii=1:length(sig_idx) + jj = sig_idx(ii); + if(jj < 1 | jj > nsigs | jj != floor(jj)) + error("sig_idx(%d)=%d, %e: must be an integer between 1 and %d", ... + ii,jj, jj, nsigs); + endif + sig_vals(jj) = names(ii); + endfor + if(any(sig_vals == 1) & sysgettsam(sys) == 0) + warning("Setting system sampling time to 1"); + printf("syssetsignals: original system sampling time=0 but output(s)\n"); + disp(find(sig_vals==1)) + printf("are digital\n"); + sys = syschtsam(sys,1); + endif + + endif + endif + + if(strcmp(opt,"st")) + sys.stname = sig_vals; + elseif(strcmp(opt,"in")) + sys.inname = sig_vals; + elseif(strcmp(opt,"out")) + sys.outname = sig_vals; + elseif(strcmp(opt,"yd")) + sys.yd = sig_vals; + endif + + retsys = sys; + +endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/system/syssub.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/system/syssub.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,116 @@ +## Copyright (C) 1996, 1999 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{sys} =} syssub (@var{Gsys}, @var{Hsys}) +## returns @math{sys = Gsys - Hsys} +## +## Method: @var{Gsys} and @var{Hsys} are connected in parallel +## The input vector is connected to both systems; the outputs are +## subtracted. Returned system names are those of @var{Gsys}. +## @example +## @group +## +--------+ +## +--->| Gsys |---+ +## | +--------+ | +## | +| +## u --+ (_)--> y +## | -| +## | +--------+ | +## +--->| Hsys |---+ +## +--------+ +## @end group +## @end example +## @end deftypefn + +## Author: John Ingram +## Created: July 1996 +## updated for variable numbers of input arguments by July 1999 A. S. Hodel + +function sys = syssub (...) + + if(nargin < 1) + usage("syssub: sys = syssub(Gsys{,Hsys,...})"); + endif + + ## collect all arguments + arglist = list(); + va_start(); + for kk=1:nargin + arglist(kk) = va_arg(); + if(!is_struct(nth(arglist,kk))) + error("syssub: argument %d is not a data structure",kk); + endif + endfor + + ## check system dimensions + [n,nz,mg,pg,Gyd] = sysdimensions(nth(arglist,1)); + for kk=2:nargin + [n,nz,mh,ph,Hyd] = sysdimensions(nth(arglist,kk)); + if(mg != mh) + error("arg 1 has %d inputs; arg %d has vs %d inputs",mg,kk,mh); + elseif(pg != ph) + error("arg 1 has %d outputs; arg %d has vs %d outputs",pg,kk,ph); + elseif(norm(Gyd - Hyd)) + warning("cannot add a discrete output to a continuous output"); + error("Output type mismatch: arguments 1 and %d\n",kk); + endif + endfor + + ## perform the subtract + if(nargin == 2) + Gsys = nth(arglist,1); Hsys = nth(arglist,2); + if( strcmp(sysgettype(Gsys),"tf") | strcmp(sysgettype(Hsys),"tf") ) + ## see if subtracting transfer functions with identical denominators + [Gnum,Gden,GT,Gin,Gout] = sys2tf(Gsys); + [Hnum,Hden,HT,Hin,Hout] = sys2tf(Hsys); + if(length(Hden) == length(Gden) ) + if( (Hden == Gden) & (HT == GT) ) + sys = tf2sys(Gnum+Hnum,Gden,GT,Gin,Gout); + return + endif + ## if not, we go on and do the usual thing... + endif + endif + + ## make sure in ss form + Gsys = sysupdate(Gsys,"ss"); + Hsys = sysupdate(Hsys,"ss"); + + ## change signal names to avoid warning messages from sysgroup + Gsys = syssetsignals(Gsys,"in",sysdefioname(length(Gin),"Gin_u")); + Gsys = syssetsignals(Gsys,"out",sysdefioname(length(Gout),"Gout_u")); + Hsys = syssetsignals(Hsys,"in",sysdefioname(length(Hin),"Hin_u")); + Hsys = syssetsignals(Hsys,"out",sysdefioname(length(Hout),"Hout_u")); + + sys = sysgroup(Gsys,Hsys); + + eyin = eye(mg); + eyout = eye(pg); + + sys = sysscale (sys, [eyout, -eyout], [eyin; eyin], Gout, Gin); + + else + ## multiple systems (or a single system); combine together one by one + sys = nth(arglist,1); + for kk=2:length(arglist) + sys = syssub(sys,nth(arglist,kk)); + endfor + endif + +endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/system/sysupdate.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/system/sysupdate.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,123 @@ +## Copyright (C) 1996 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 0211 + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{sys} =} sysupdate (@var{sys}, @var{opt}) +## Update the internal representation of a system. +## +## @strong{Inputs} +## @table @var +## @item sys: +## system data structure +## @item opt +## string: +## @table @code +## @item "tf" +## update transfer function form +## @item "zp" +## update zero-pole form +## @item "ss" +## update state space form +## @item "all" +## all of the above +## @end table +## @end table +## +## @strong{Outputs} +## @var{retsys}: contains union of data in sys and requested data. +## If requested data in sys is already up to date then retsys=sys. +## +## Conversion to @code{tf} or @code{zp} exits with an error if the system is +## mixed continuous/digital. +## @end deftypefn +## @seealso{tf2sys, ss2sys, zp2sys, sysout, sys2ss, sys2tf, and sys2zp} + +## Author: John Ingram +## Created: July 9, 1996 + +function sys = sysupdate (sys, opt) + + ## check for correct number of inputs + if (nargin != 2) + usage("newsys = sysupdate(sys,opt)"); + elseif(! is_struct(sys) ) + error("1st argument must be system data structure") + elseif(! (strcmp(opt,"tf") + strcmp(opt,"zp") + ... + strcmp(opt,"ss") + strcmp(opt,"all")) ) + error("2nd argument must be \"tf\", \"zp\", \"ss\", or \"all\""); + endif + + ## check to make sure not trying to make a SISO system out of a MIMO sys + if ( (strcmp(opt,"tf") + strcmp(opt,"zp") + strcmp(opt,"all")) ... + & strcmp(sysgettype(sys),"ss") & (! is_siso(sys) ) ) + error("MIMO -> SISO update requested"); + endif + + ## update transfer function if desired + if ( (strcmp(opt, "tf") + strcmp(opt,"all"))&& (!sys.sys(2))) + ## check to make sure the system is not discrete and continuous + is_digital(sys); + + ## if original system zero-pole + if strcmp(sysgettype(sys),"zp") + [sys.num,sys.den] = zp2tf(sys.zer,sys.pol,sys.k); + sys.sys(2) = 1; + ## if original system is state-space + elseif(sys.sys(1) == 2) + [sys.num,sys.den] = ss2tf(sys.a,sys.b,sys.c,sys.d); + sys.sys(2) = 1; + endif + endif + + + ## update zero-pole if desired + if ( (strcmp(opt, "zp") + strcmp(opt,"all")) && (! sys.sys(3)) ) + ## check to make sure the system is not discrete and continuous + is_digital(sys); + + ## original system is transfer function + if (sys.sys(1) == 0) + [sys.zer,sys.pol,sys.k] = tf2zp(sys.num,sys.den); + sys.sys(3) = 1; + ## original system is state-space + + elseif(sys.sys(1) == 2) + [sys.zer,sys.pol,sys.k] = ss2zp(sys.a,sys.b,sys.c,sys.d); + sys.sys(3) = 1; + endif + + endif + + ## update state-space if desired + if ( (strcmp(opt, "ss") + strcmp(opt,"all")) && (! sys.sys(4)) ) + ## original system is transfer function + if (sys.sys(1) == 0) + [sys.a,sys.b,sys.c,sys.d] = tf2ss(sys.num,sys.den); + sys.sys(4) = 1; + ## original system is zero-pole + elseif(sys.sys(1) == 1) + [sys.a,sys.b,sys.c,sys.d] = zp2ss(sys.zer,sys.pol,sys.k); + sys.sys(4) = 1; + endif + + ## create new state names + sys.stname = sysdefstname(sys.n, sys.nz); + endif + + +endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/system/tf2ss.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/system/tf2ss.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,98 @@ +## Copyright (C) 1996, 1998 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{outputs} =} tf2ss (@var{inputs}) +## @format +## Conversion from tranfer function to state-space. +## The state space system +## . +## x = Ax + Bu +## y = Cx + Du +## +## is obtained from a transfer function +## +## num(s) +## G(s)=------- +## den(s) +## +## via the function call [a,b,c,d] = tf2ss(num,den). +## The vector 'den' must contain only one row, whereas the vector 'num' +## may contain as many rows as there are outputs of the system 'y'. +## The state space system matrices obtained from this function will be +## in controllable canonical form as described in "Modern Control Theory", +## [Brogan, 1991]. +## +## +## @end format +## @end deftypefn + +## Author: R. Bruce Tenison +## Created: June 22, 1994 +## mod A S Hodel July, Aug 1995 + +function [a, b, c, d] = tf2ss (num, den) + + if(nargin != 2) error("tf2ss: wrong number of input arguments") + elseif(isempty(num)) error("tf2ss: empty numerator"); + elseif(isempty(den)) error("tf2ss: empy denominator"); + elseif(!is_vector(num)) + error(sprintf("num(%dx%d) must be a vector",rows(num),columns(num))); + elseif(!is_vector(den)) + error(sprintf("den(%dx%d) must be a vector",rows(den),columns(den))); + endif + + ## strip leading zeros from num, den + nz = find(num != 0); + if(isempty(nz)) num = 0; + else num = num(nz(1):length(num)); endif + nz = find(den != 0); + if(isempty(nz)) error("denominator is 0."); + else den = den(nz(1):length(den)); endif + + ## force num, den to be row vectors + num = vec(num)'; den = vec(den)'; + nn = length(num); nd = length(den); + if(nn > nd) error(sprintf("deg(num)=%d > deg(den)= %d",nn,nd)); endif + + ## Check sizes + if (nd == 1) a = []; b = []; c = []; d = num(:,1) / den(1); + else + ## Pad num so that length(num) = length(den) + if (nd-nn > 0) num = [zeros(1,nd-nn), num]; endif + + ## Normalize the numerator and denominator vector w.r.t. the leading + ## coefficient + d1 = den(1); num = num / d1; den = den(2:nd)/d1; + sw = nd-1:-1:1; + + ## Form the A matrix + if(nd > 2) a = [zeros(nd-2,1),eye(nd-2,nd-2);-den(sw)]; + else a = -den(sw); endif + + ## Form the B matrix + b = zeros(nd-1,1); b(nd-1,1) = 1; + + ## Form the C matrix + c = num(:,2:nd)-num(:,1)*den; c = c(:,sw); + + ## Form the D matrix + d = num(:,1); + endif + +endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/system/tf2sys.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/system/tf2sys.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,143 @@ +## Copyright (C) 1996, 1998 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{sys} =} tf2sys (@var{num}, @var{den} @{, @var{tsam}, @var{inname}, @var{outname} @}) +## build system data structure from transfer function format data +## +## @strong{Inputs} +## @table @var +## @item num +## @itemx den +## coefficients of numerator/denominator polynomials +## @item tsam +## sampling interval. default: 0 (continuous time) +## @item inname +## @itemx outname +## input/output signal names; may be a string or list with a single string +## entry. +## @end table +## +## @strong{Outputs} +## @var{sys} = system data structure +## +## @strong{Example} +## @example +## octave:1> sys=tf2sys([2 1],[1 2 1],0.1); +## octave:2> sysout(sys) +## Input(s) +## 1: u_1 +## Output(s): +## 1: y_1 (discrete) +## Sampling interval: 0.1 +## transfer function form: +## 2*z^1 + 1 +## ----------------- +## 1*z^2 + 2*z^1 + 1 +## @end example +## @end deftypefn + +## Author: R. Bruce Tenison +## Created: July 29, 1994 +## Name changed to TF2SYS July 1995 +## updated for new system data structure format July 1996 + +function outsys = tf2sys (num, den, tsam, inname, outname) + + ## Test for the correct number of input arguments + if ((nargin < 2) || (nargin > 5)) + usage ("outsys = tf2sys (num, den [, tsam, inname, outname])"); + return + endif + + ## check input format + if( ! ( (is_vector(num) || is_scalar(num)) && ... + (is_vector(den) || is_scalar(den))) ) + error(["num (",num2str(rows(num)),"x",num2str(columns(num)), ... + ") and den (",num2str(rows(den)),"x",num2str(columns(den)), ... + ") must be vectors"]) + endif + + ## strip leading zero coefficients + num = tf2sysl(num); + den = tf2sysl(den); + + if (length(num) > length(den)) + error("# of poles (%d) < # of zeros (%d)",length(den)-1, length(num)-1); + endif + + ## check sampling interval (if any) + if(nargin <= 2) tsam = 0; # default + elseif (isempty(tsam)) tsam = 0; endif + if ( (! (is_scalar(tsam) && (imag(tsam) == 0) )) || (tsam < 0) ) + error("tsam must be a positive real scalar") + endif + + outsys.num = num; + outsys.den = den; + + ## Set the system vector: active = 0(tf), updated = [1 0 0]; + outsys.sys = [0, 1, 0, 0]; + + ## Set defaults + outsys.tsam = tsam; + outsys.n = length(den)-1; + outsys.nz = 0; + outsys.yd = 0; # assume discrete-time + ## check discrete time + if(tsam > 0) + [outsys.n,outsys.nz] = swap(outsys.n, outsys.nz); + outsys.yd = 1; + endif + + outsys.inname = sysdefioname(1,"u"); + outsys.outname = sysdefioname(1,"y"); + outsys.stname = sysdefstname(outsys.n,outsys.nz); + + ## Set name of input + if (nargin > 3) + ## make sure its a list of a single string + if(!isempty(inname)) + if(!is_list(inname)) inname = list(inname); endif + if( !is_signal_list(inname) ) + error("inname must be a string or list of strings"); + endif + if(length(inname) > 1) + warning("tf2sys: %d input names provided; first used",length(inname)); + inname = inname(1); + endif + outsys = syssetsignals(outsys,"in",inname); + endif + endif + + ## Set name of output + if (nargin > 4) + if(!isempty(outname)) + if(!is_list(outname)) outname = list(outname); endif + if(!is_signal_list(outname)) + error("outname must be a string or a list of strings"); + endif + if(length(outname) > 1) + warning("tf2sys: %d output names provided; first used",length(outname)); + outname = outname(1); + endif + outsys = syssetsignals(outsys,"out",outname); + endif + endif + +endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/system/tf2sysl.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/system/tf2sysl.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,35 @@ +## Copyright (C) 1996 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{vec} =} tf2sysl (@var{vec}) +## used internally in @ref{tf2sys}. +## strip leading zero coefficients to get the true polynomial length +## @end deftypefn + +function vec = tf2sysl (vec) + + while( (length(vec) > 1) & (vec(1) == 0) ) + vec = vec(2:length(vec)); + endwhile + + if(vec(1) == 0) + warning("tf2sys: polynomial has no nonzero coefficients!") + endif + +endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/system/tf2zp.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/system/tf2zp.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,42 @@ +## Copyright (C) 1996, 1998 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{outputs} =} tf2zp (@var{inputs}) +## Converts transfer functions to poles / zeros. +## +## [zer,pol,k] = tf2zp(num,den) returns the zeros and poles of the SISO system +## defined by num/den. K is a gain associated with the system zeros. +## @end deftypefn + +## Author: A. S. Hodel + +function [zer, pol, k] = tf2zp (num, den) + + if(nargin == 2) + if(length(den) > 1) pol = roots(den); + else pol=[]; endif + if(length(num) > 1) zer = roots(num); + else zer=[]; endif + else error("Incorrect number of input arguments"); + endif + + [a,b,c,d] = tf2ss(num,den); + [dum,k] = tzero(a,b,c,d); + +endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/system/tfout.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/system/tfout.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,62 @@ +## Copyright (C) 1996 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## -*- texinfo -*- +## @deftypefn {Function File} {} tfout (@var{num}, @var{denom}@{, @var{x}@}) +## Print formatted transfer function @math{n(s)/d(s) } to the screen. +## @var{x} defaults to the string @code{"s"} +## @end deftypefn +## @seealso{polyval, polyvalm, poly, roots, conv, deconv, residue, +## filter, polyderiv, polyinteg, and polyout} + +## Author: A. S. Hodel +## Created: June 1995 + +function tfout (num, denom, x) + + save_empty = empty_list_elements_ok; + empty_list_elements_ok = 1; + + if (nargin < 2 ) | (nargin > 3) | (nargout != 0 ) + usage("tfout(num,denom[,x])"); + endif + + if ( (!is_vector(num)) | (!is_vector(denom)) ) + error("tfout: first two argument must be vectors"); + endif + + if (nargin == 2) + x = "s"; + elseif( ! isstr(x) ) + error("tfout: third argument must be a string"); + endif + + numstring = polyout(num,x); + denomstring = polyout(denom,x); + len = max(length(numstring),length(denomstring)); + if(len > 0) + y = strrep(blanks(len)," ","-"); + disp(numstring) + disp(y) + disp(denomstring) + else + error ("tfout: empty transfer function") + end + + empty_list_elements_ok = save_empty; +endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/system/zp2ss.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/system/zp2ss.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,154 @@ +## Copyright (C) 1996 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## -*- texinfo -*- +## @deftypefn {Function File} {[@var{A}, @var{B}, @var{C}, @var{D}] =} zp2ss (@var{zer}, @var{pol}, @var{k}) +## Conversion from zero / pole to state space. +## @strong{Inputs} +## @table @var +## @item zer +## @itemx pol +## vectors of (possibly) complex poles and zeros of a transfer +## function. Complex values must come in conjugate pairs +## (i.e., x+jy in zer means that x-jy is also in zer) +## @item k +## real scalar (leading coefficient) +## @end table +## @strong{Outputs} +## @var{A}, @var{B}, @var{C}, @var{D} +## The state space system +## @example +## . +## x = Ax + Bu +## y = Cx + Du +## @end example +## is obtained from a vector of zeros and a vector of poles via the +## function call @code{[a,b,c,d] = zp2ss(zer,pol,k)}. +## The vectors @samp{zer} and +## @samp{pol} may either be row or column vectors. Each zero and pole that +## has an imaginary part must have a conjugate in the list. +## The number of zeros must not exceed the number of poles. +## @samp{k} is @code{zp}-form leading coefficient. +## @end deftypefn + +## Author: David Clem +## Created: August 15, 1994 + +function [a, b, c, d] = zp2ss (zer, pol, k) + + sav_val = empty_list_elements_ok; + empty_list_elements_ok = 1; + + if(nargin != 3) + error("Incorrect number of input arguments"); + endif + + if(! (is_vector(zer) | isempty(zer)) ) + error(["zer(",num2str(rows(zer)),",",num2str(columns(zer)), ... + ") should be a vector"]); + elseif(! (is_vector(pol) | isempty(pol) ) ) + error(["pol(",num2str(rows(pol)),",",num2str(columns(pol)), ... + ") should be a vector"]); + elseif(! is_scalar(k)) + error(["k(",num2str(rows(k)),",",num2str(columns(k)), ... + ") should be a scalar"]); + elseif( k != real(k)) + warning("zp2ss: k is complex") + endif + + zpsys = ss2sys([],[],[],k); + + ## Find the number of zeros and the number of poles + nzer=length(zer); + npol =length(pol); + + if(nzer > npol) + error([num2str(nzer)," zeros, exceeds number of poles=",num2str(npol)]); + endif + + ## Sort to place complex conjugate pairs together + zer=sortcom(zer); + pol=sortcom(pol); + + ## construct the system as a series connection of poles and zeros + ## problem: poles and zeros may come in conjugate pairs, and not + ## matched up! + + ## approach: remove poles/zeros from the list as they are included in + ## the ss system + + while(length(pol)) + + ## search for complex poles, zeros + cpol=[]; czer = []; + if(!isempty(pol)) + cpol = find(imag(pol) != 0); + endif + if(!isempty(zer)) + czer = find(imag(zer) != 0); + endif + + if(isempty(cpol) & isempty(czer)) + pcnt = 1; + else + pcnt = 2; + endif + + num=1; # assume no zeros left. + switch(pcnt) + case(1) + ## real pole/zero combination + if(length(zer)) + num = [1, -zer(1)]; + zer = zer(2:length(zer)); + endif + den = [1, -pol(1)]; + pol = pol(2:length(pol)); + case(2) + ## got a complex pole or zero, need two roots (if available) + if(length(zer) > 1) + [num,zer] = zp2ssg2(zer); # get two zeros + elseif(length(zer) == 1) + num = [1, -zer]; # use last zero (better be real!) + zer = []; + endif + [den,pol] = zp2ssg2(pol); # get two poles + otherwise + error(["pcnt = ",num2str(pcnt)]) + endswitch + + ## pack tf into system form and put in series with earlier realization + zpsys1 = tf2sys(num,den,0,"u","yy"); + + ## change names to avoid warning messages from sysgroup + zpsys = syssetsignals(zpsys,"in","u1",1); + zpsys1 = sysupdate(zpsys1,"ss"); + nn = sysdimensions(zpsys); # working with continuous system + zpsys = syssetsignals(zpsys,"st", sysdefioname(nn,"x")); + nn1 = sysdimensions(zpsys1); + zpsys1 = syssetsignals(zpsys1,"st",sysdefioname(nn1,"xx")); + + zpsys = sysmult(zpsys,zpsys1); + + endwhile + + [a,b,c,d] = sys2ss(zpsys); + + empty_list_elements_ok = sav_val; +endfunction + diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/system/zp2ssg2.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/system/zp2ssg2.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,68 @@ +## Copyright (C) 1996, 1998 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## -*- texinfo -*- +## @deftypefn {Function File} {[@var{poly}, @var{rvals}] =} zp2ssg2 (@var{rvals}) +## Used internally in @code{zp2ss} +## Extract 2 values from @var{rvals} (if possible) and construct +## a polynomial with those roots. +## @end deftypefn + +## Author: A. S. Hodel +## Created: August 1996 + +function [poly, rvals] = zp2ssg2 (rvals) + + ## locate imaginary roots (if any) + cidx = find(imag(rvals)); + + if(!isempty(cidx)) + ## select first complex root, omit from cidx + r1i = cidx(1); r1 = rvals(r1i); cidx = complement(r1i,cidx); + + ## locate conjugate root (must be in cidx list, just in case there's + ## roundoff) + err = abs(rvals(cidx) - r1'); + minerr = min(err); + c2i = find(err == minerr); + r2i = cidx(c2i); + r2 = rvals(r2i); + cidx = complement(r2i,cidx); + + ## don't check for divide by zero, since 0 is not complex. + if(abs(r2 - r1')/abs(r1) > 1e-12) + error(sprintf("r1=(%f,%f); r2=(%f,%f), not conjugates.", ... + real(r1),imag(r1),real(r2),imag(r2))); + endif + + ## complex conjugate pair + poly = [1, -2*real(r1), real(r1)^2+imag(r1)^2]; + else + ## select two roots (they're all real) + r1 = rvals(1); + r2 = rvals(2); + poly = [1, -(r1+r2), (r1*r2)]; + r1i = 1; r2i = 2; + endif + + ## remove roots used + idx = complement([r1i, r2i],1:length(rvals)); + rvals = rvals(idx); + +endfunction + diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/system/zp2sys.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/system/zp2sys.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,147 @@ +## Copyright (C) 1996, 1998 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{sys} =} zp2sys (@var{zer},@var{pol},@var{k}@{,@var{tsam},@var{inname},@var{outname}@}) +## Create system data structure from zero-pole data. +## +## @strong{Inputs} +## @table @var +## @item zer +## vector of system zeros +## @item pol +## vector of system poles +## @item k +## scalar leading coefficient +## @item tsam +## sampling period. default: 0 (continuous system) +## @item inname +## @itemx outname +## input/output signal names (lists of strings) +## @end table +## +## @strong{Outputs} +## sys: system data structure +## +## @strong{Example} +## @example +## octave:1> sys=zp2sys([1 -1],[-2 -2 0],1); +## octave:2> sysout(sys) +## Input(s) +## 1: u_1 +## Output(s): +## 1: y_1 +## zero-pole form: +## 1 (s - 1) (s + 1) +## ----------------- +## s (s + 2) (s + 2) +## @end example +## @end deftypefn + +## Modified by John Ingram July 20, 1996 + +function outsys = zp2sys (zer, pol, k, tsam, inname, outname) + + ## Test for the correct number of input arguments + if ((nargin < 3) || (nargin > 6)) + usage("outsys = zp2sys(zer,pol,k[,tsam,inname,outname])"); + endif + + ## check input format + if( ! (is_vector(zer) | isempty(zer) ) ) + error("zer must be a vector or empty"); + endif + if(!isempty(zer)) + zer = reshape(zer,1,length(zer)); # make it a row vector + endif + + if( ! (is_vector(pol) | isempty(pol))) + error("pol must be a vector"); + endif + if(!isempty(pol)) + pol = reshape(pol,1,length(pol)); + endif + + if (! is_scalar(k)) + error("k must be a scalar"); + endif + + ## Test proper numbers of poles and zeros. The number of poles must be + ## greater than or equal to the number of zeros. + if (length(zer) > length(pol)) + error(["number of poles (", num2str(length(pol)), ... + ") < number of zeros (", num2str(length(zer)),")"]); + endif + + ## Set the system transfer function + outsys.zer = zer; + outsys.pol = pol; + outsys.k = k; + + ## Set the system vector: active = 1, updated = [0 1 0]; + outsys.sys = [1, 0, 1, 0]; + + ## Set defaults + outsys.tsam = 0; + outsys.n = length(pol); + outsys.nz = 0; + outsys.yd = 0; # assume (for now) continuous time outputs + + ## Set the type of system + if (nargin > 3) + if( !is_scalar(tsam) ) + error("tsam must be a nonnegative scalar"); + endif + if (tsam < 0) + error("sampling time must be positve") + elseif (tsam > 0) + [outsys.n,outsys.nz] = swap(outsys.n, outsys.nz); + outsys.yd = 1; # discrete-time output + endif + + outsys.tsam = tsam; + endif + + outsys.inname = sysdefioname(1,"u"); + outsys.outname = sysdefioname(1,"y"); + outsys.stname = sysdefstname(outsys.n,outsys.nz); + + ## Set name of input + if (nargin > 4) + ## make sure its a string + if(!isempty(inname)) + if(!is_list(inname)) inname = list(inname); endif + if(!is_signal_list(inname)) + error("inname must be a single signal name"); + endif + outsys.inname = inname(1); + endif + endif + + ## Set name of output + if (nargin > 5) + if(!isempty(outname)) + if(!is_list(outname)) outname = list(outname); endif + if(!is_signal_list(outname)) + error("outname must be a single signal name"); + endif + outsys.outname = outname(1); + endif + endif + +endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/system/zp2tf.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/system/zp2tf.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,75 @@ +## Copyright (C) 1996, 1998 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## -*- texinfo -*- +## @deftypefn {Function File} {[@var{num}, @var{den}] =} zp2tf (@var{zer}, @var{pol}, @var{k}) +## Converts zeros / poles to a transfer function. +## @strong{Inputs} +## @table @var +## @item zer +## @itemx pol +## vectors of (possibly complex) poles and zeros of a transfer +## function. Complex values should appear in conjugate pairs +## @item k +## real scalar (leading coefficient) +## @end table +## @code{[num,den] = zp2tf(zer,pol,k)} forms the transfer function +## @code{num/den} from the vectors of poles and zeros. +## @end deftypefn + +## Author: A. S. Hodel +## (With help from students Ingram, McGowan.) + +function [num, den] = zp2tf (zer, pol, k) + + ## Find out whether data was entered as a row or a column vector and + ## convert to a column vector if necessary. + + [rp,cp] = size(pol); + [rz,cz] = size(zer); + + if(!(is_vector(zer) | isempty(zer)) ) + error(sprintf("zer(%dx%d) must be a vector",rz,cz)); + elseif(!(is_vector(pol) | isempty(pol)) ) + error(sprintf("pol(%dx%d) must be a vector",rp,cp)); + elseif(length(zer) > length(pol)) + error(sprintf("zer(%dx%d) longer than pol(%dx%d)",rz,cz,rp,cp)); + endif + + ## initialize converted polynomials + + num = k; den = 1; + + ## call zp2ssg2 if there are complex conjugate pairs left, otherwise + ## construct real zeros one by one. Repeat for poles. + + while(!isempty(zer)) + if( max(abs(imag(zer))) ) [poly,zer] = zp2ssg2(zer); + else poly = [1, -zer(1)]; + zer = zer(2:length(zer)); endif + num = conv(num,poly); + endwhile + + while(!isempty(pol)) + if( max(abs(imag(pol))) ) [poly,pol] = zp2ssg2(pol); + else poly = [1, -pol(1)]; + pol = pol(2:length(pol)); endif + den = conv(den,poly); + endwhile + +endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/system/zpout.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/system/zpout.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,107 @@ +## Copyright (C) 1996 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 2, 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, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## -*- texinfo -*- +## @deftypefn {Function File} {} zpout (@var{zer}, @var{pol}, @var{k}@{, @var{x}@}) +## print formatted zero-pole form to the screen. +## @var{x} defaults to the string @code{"s"} +## @end deftypefn +## @seealso{polyval, polyvalm, poly, roots, conv, deconv, residue, +## filter, polyderiv, polyinteg, and polyout} + +## Author: A. S. Hodel +## Created: June 1995 + +function zpout (zer, pol, k, x) + + save_empty = empty_list_elements_ok; + empty_list_elements_ok = 1; + + if (nargin < 3 ) | (nargin > 4) | (nargout != 0 ) + usage("zpout(zer,pol,k[,x])"); + endif + + if( !(is_vector(zer) | isempty(zer)) | !(is_vector(pol) | isempty(pol)) ) + error("zer, pol must be vectors or empty"); + endif + + if(!is_scalar(k)) + error("zpout: argument k must be a scalar.") + endif + + if (nargin == 3) + x = "s"; + elseif( ! isstr(x) ) + error("zpout: third argument must be a string"); + endif + + numstring = num2str(k); + + if(length(zer)) + ## find roots at z,s = 0 + nzr = sum(zer == 0); + if(nzr) + if(nzr > 1) + numstring = [numstring,sprintf(" %s^%d",x,nzr)]; + else + numstring = [numstring,sprintf(" %s",x)]; + endif + endif + zer = sortcom(-zer); + for ii=1:length(zer) + if(zer(ii) != 0) + numstring = [numstring,sprintf(" (%s %s)",x,com2str(zer(ii),1) ) ]; + endif + endfor + endif + + if(length(pol)) + ## find roots at z,s = 0 + nzr = sum(pol == 0); + if(nzr) + if(nzr > 1) + denomstring = [sprintf("%s^%d",x,nzr)]; + else + denomstring = [sprintf("%s",x)]; + endif + else + denomstring = " "; + endif + pol = sortcom(-pol); + for ii=1:length(pol) + if(pol(ii) != 0) + denomstring = [denomstring,sprintf(" (%s %s)",x,com2str(pol(ii),1))]; + endif + endfor + endif + + len = max(length(numstring),length(denomstring)); + if(len > 0) + y = strrep(blanks(len)," ","-"); + disp(numstring) + if(length(denomstring)) + disp(y) + disp(denomstring) + endif + else + error ("zpout: empty transfer function") + end + + empty_list_elements_ok = save_empty; + +endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/sysupdate.m --- a/scripts/control/sysupdate.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,123 +0,0 @@ -## Copyright (C) 1996 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 0211 - -## -*- texinfo -*- -## @deftypefn {Function File} {@var{sys} =} sysupdate (@var{sys}, @var{opt}) -## Update the internal representation of a system. -## -## @strong{Inputs} -## @table @var -## @item sys: -## system data structure -## @item opt -## string: -## @table @code -## @item "tf" -## update transfer function form -## @item "zp" -## update zero-pole form -## @item "ss" -## update state space form -## @item "all" -## all of the above -## @end table -## @end table -## -## @strong{Outputs} -## @var{retsys}: contains union of data in sys and requested data. -## If requested data in sys is already up to date then retsys=sys. -## -## Conversion to @code{tf} or @code{zp} exits with an error if the system is -## mixed continuous/digital. -## @end deftypefn -## @seealso{tf2sys, ss2sys, zp2sys, sysout, sys2ss, sys2tf, and sys2zp} - -## Author: John Ingram -## Created: July 9, 1996 - -function sys = sysupdate (sys, opt) - - ## check for correct number of inputs - if (nargin != 2) - usage("newsys = sysupdate(sys,opt)"); - elseif(! is_struct(sys) ) - error("1st argument must be system data structure") - elseif(! (strcmp(opt,"tf") + strcmp(opt,"zp") + ... - strcmp(opt,"ss") + strcmp(opt,"all")) ) - error("2nd argument must be \"tf\", \"zp\", \"ss\", or \"all\""); - endif - - ## check to make sure not trying to make a SISO system out of a MIMO sys - if ( (strcmp(opt,"tf") + strcmp(opt,"zp") + strcmp(opt,"all")) ... - & strcmp(sysgettype(sys),"ss") & (! is_siso(sys) ) ) - error("MIMO -> SISO update requested"); - endif - - ## update transfer function if desired - if ( (strcmp(opt, "tf") + strcmp(opt,"all"))&& (!sys.sys(2))) - ## check to make sure the system is not discrete and continuous - is_digital(sys); - - ## if original system zero-pole - if strcmp(sysgettype(sys),"zp") - [sys.num,sys.den] = zp2tf(sys.zer,sys.pol,sys.k); - sys.sys(2) = 1; - ## if original system is state-space - elseif(sys.sys(1) == 2) - [sys.num,sys.den] = ss2tf(sys.a,sys.b,sys.c,sys.d); - sys.sys(2) = 1; - endif - endif - - - ## update zero-pole if desired - if ( (strcmp(opt, "zp") + strcmp(opt,"all")) && (! sys.sys(3)) ) - ## check to make sure the system is not discrete and continuous - is_digital(sys); - - ## original system is transfer function - if (sys.sys(1) == 0) - [sys.zer,sys.pol,sys.k] = tf2zp(sys.num,sys.den); - sys.sys(3) = 1; - ## original system is state-space - - elseif(sys.sys(1) == 2) - [sys.zer,sys.pol,sys.k] = ss2zp(sys.a,sys.b,sys.c,sys.d); - sys.sys(3) = 1; - endif - - endif - - ## update state-space if desired - if ( (strcmp(opt, "ss") + strcmp(opt,"all")) && (! sys.sys(4)) ) - ## original system is transfer function - if (sys.sys(1) == 0) - [sys.a,sys.b,sys.c,sys.d] = tf2ss(sys.num,sys.den); - sys.sys(4) = 1; - ## original system is zero-pole - elseif(sys.sys(1) == 1) - [sys.a,sys.b,sys.c,sys.d] = zp2ss(sys.zer,sys.pol,sys.k); - sys.sys(4) = 1; - endif - - ## create new state names - sys.stname = sysdefstname(sys.n, sys.nz); - endif - - -endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/tf2ss.m --- a/scripts/control/tf2ss.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,98 +0,0 @@ -## Copyright (C) 1996, 1998 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## -*- texinfo -*- -## @deftypefn {Function File} {@var{outputs} =} tf2ss (@var{inputs}) -## @format -## Conversion from tranfer function to state-space. -## The state space system -## . -## x = Ax + Bu -## y = Cx + Du -## -## is obtained from a transfer function -## -## num(s) -## G(s)=------- -## den(s) -## -## via the function call [a,b,c,d] = tf2ss(num,den). -## The vector 'den' must contain only one row, whereas the vector 'num' -## may contain as many rows as there are outputs of the system 'y'. -## The state space system matrices obtained from this function will be -## in controllable canonical form as described in "Modern Control Theory", -## [Brogan, 1991]. -## -## -## @end format -## @end deftypefn - -## Author: R. Bruce Tenison -## Created: June 22, 1994 -## mod A S Hodel July, Aug 1995 - -function [a, b, c, d] = tf2ss (num, den) - - if(nargin != 2) error("tf2ss: wrong number of input arguments") - elseif(isempty(num)) error("tf2ss: empty numerator"); - elseif(isempty(den)) error("tf2ss: empy denominator"); - elseif(!is_vector(num)) - error(sprintf("num(%dx%d) must be a vector",rows(num),columns(num))); - elseif(!is_vector(den)) - error(sprintf("den(%dx%d) must be a vector",rows(den),columns(den))); - endif - - ## strip leading zeros from num, den - nz = find(num != 0); - if(isempty(nz)) num = 0; - else num = num(nz(1):length(num)); endif - nz = find(den != 0); - if(isempty(nz)) error("denominator is 0."); - else den = den(nz(1):length(den)); endif - - ## force num, den to be row vectors - num = vec(num)'; den = vec(den)'; - nn = length(num); nd = length(den); - if(nn > nd) error(sprintf("deg(num)=%d > deg(den)= %d",nn,nd)); endif - - ## Check sizes - if (nd == 1) a = []; b = []; c = []; d = num(:,1) / den(1); - else - ## Pad num so that length(num) = length(den) - if (nd-nn > 0) num = [zeros(1,nd-nn), num]; endif - - ## Normalize the numerator and denominator vector w.r.t. the leading - ## coefficient - d1 = den(1); num = num / d1; den = den(2:nd)/d1; - sw = nd-1:-1:1; - - ## Form the A matrix - if(nd > 2) a = [zeros(nd-2,1),eye(nd-2,nd-2);-den(sw)]; - else a = -den(sw); endif - - ## Form the B matrix - b = zeros(nd-1,1); b(nd-1,1) = 1; - - ## Form the C matrix - c = num(:,2:nd)-num(:,1)*den; c = c(:,sw); - - ## Form the D matrix - d = num(:,1); - endif - -endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/tf2sys.m --- a/scripts/control/tf2sys.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,143 +0,0 @@ -## Copyright (C) 1996, 1998 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## -*- texinfo -*- -## @deftypefn {Function File} {@var{sys} =} tf2sys (@var{num}, @var{den} @{, @var{tsam}, @var{inname}, @var{outname} @}) -## build system data structure from transfer function format data -## -## @strong{Inputs} -## @table @var -## @item num -## @itemx den -## coefficients of numerator/denominator polynomials -## @item tsam -## sampling interval. default: 0 (continuous time) -## @item inname -## @itemx outname -## input/output signal names; may be a string or list with a single string -## entry. -## @end table -## -## @strong{Outputs} -## @var{sys} = system data structure -## -## @strong{Example} -## @example -## octave:1> sys=tf2sys([2 1],[1 2 1],0.1); -## octave:2> sysout(sys) -## Input(s) -## 1: u_1 -## Output(s): -## 1: y_1 (discrete) -## Sampling interval: 0.1 -## transfer function form: -## 2*z^1 + 1 -## ----------------- -## 1*z^2 + 2*z^1 + 1 -## @end example -## @end deftypefn - -## Author: R. Bruce Tenison -## Created: July 29, 1994 -## Name changed to TF2SYS July 1995 -## updated for new system data structure format July 1996 - -function outsys = tf2sys (num, den, tsam, inname, outname) - - ## Test for the correct number of input arguments - if ((nargin < 2) || (nargin > 5)) - usage ("outsys = tf2sys (num, den [, tsam, inname, outname])"); - return - endif - - ## check input format - if( ! ( (is_vector(num) || is_scalar(num)) && ... - (is_vector(den) || is_scalar(den))) ) - error(["num (",num2str(rows(num)),"x",num2str(columns(num)), ... - ") and den (",num2str(rows(den)),"x",num2str(columns(den)), ... - ") must be vectors"]) - endif - - ## strip leading zero coefficients - num = tf2sysl(num); - den = tf2sysl(den); - - if (length(num) > length(den)) - error("# of poles (%d) < # of zeros (%d)",length(den)-1, length(num)-1); - endif - - ## check sampling interval (if any) - if(nargin <= 2) tsam = 0; # default - elseif (isempty(tsam)) tsam = 0; endif - if ( (! (is_scalar(tsam) && (imag(tsam) == 0) )) || (tsam < 0) ) - error("tsam must be a positive real scalar") - endif - - outsys.num = num; - outsys.den = den; - - ## Set the system vector: active = 0(tf), updated = [1 0 0]; - outsys.sys = [0, 1, 0, 0]; - - ## Set defaults - outsys.tsam = tsam; - outsys.n = length(den)-1; - outsys.nz = 0; - outsys.yd = 0; # assume discrete-time - ## check discrete time - if(tsam > 0) - [outsys.n,outsys.nz] = swap(outsys.n, outsys.nz); - outsys.yd = 1; - endif - - outsys.inname = sysdefioname(1,"u"); - outsys.outname = sysdefioname(1,"y"); - outsys.stname = sysdefstname(outsys.n,outsys.nz); - - ## Set name of input - if (nargin > 3) - ## make sure its a list of a single string - if(!isempty(inname)) - if(!is_list(inname)) inname = list(inname); endif - if( !is_signal_list(inname) ) - error("inname must be a string or list of strings"); - endif - if(length(inname) > 1) - warning("tf2sys: %d input names provided; first used",length(inname)); - inname = inname(1); - endif - outsys = syssetsignals(outsys,"in",inname); - endif - endif - - ## Set name of output - if (nargin > 4) - if(!isempty(outname)) - if(!is_list(outname)) outname = list(outname); endif - if(!is_signal_list(outname)) - error("outname must be a string or a list of strings"); - endif - if(length(outname) > 1) - warning("tf2sys: %d output names provided; first used",length(outname)); - outname = outname(1); - endif - outsys = syssetsignals(outsys,"out",outname); - endif - endif - -endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/tf2sysl.m --- a/scripts/control/tf2sysl.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -## Copyright (C) 1996 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## -*- texinfo -*- -## @deftypefn {Function File} {@var{vec} =} tf2sysl (@var{vec}) -## used internally in @ref{tf2sys}. -## strip leading zero coefficients to get the true polynomial length -## @end deftypefn - -function vec = tf2sysl (vec) - - while( (length(vec) > 1) & (vec(1) == 0) ) - vec = vec(2:length(vec)); - endwhile - - if(vec(1) == 0) - warning("tf2sys: polynomial has no nonzero coefficients!") - endif - -endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/tf2zp.m --- a/scripts/control/tf2zp.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,42 +0,0 @@ -## Copyright (C) 1996, 1998 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## -*- texinfo -*- -## @deftypefn {Function File} {@var{outputs} =} tf2zp (@var{inputs}) -## Converts transfer functions to poles / zeros. -## -## [zer,pol,k] = tf2zp(num,den) returns the zeros and poles of the SISO system -## defined by num/den. K is a gain associated with the system zeros. -## @end deftypefn - -## Author: A. S. Hodel - -function [zer, pol, k] = tf2zp (num, den) - - if(nargin == 2) - if(length(den) > 1) pol = roots(den); - else pol=[]; endif - if(length(num) > 1) zer = roots(num); - else zer=[]; endif - else error("Incorrect number of input arguments"); - endif - - [a,b,c,d] = tf2ss(num,den); - [dum,k] = tzero(a,b,c,d); - -endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/tfout.m --- a/scripts/control/tfout.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,62 +0,0 @@ -## Copyright (C) 1996 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## -*- texinfo -*- -## @deftypefn {Function File} {} tfout (@var{num}, @var{denom}@{, @var{x}@}) -## Print formatted transfer function @math{n(s)/d(s) } to the screen. -## @var{x} defaults to the string @code{"s"} -## @end deftypefn -## @seealso{polyval, polyvalm, poly, roots, conv, deconv, residue, -## filter, polyderiv, polyinteg, and polyout} - -## Author: A. S. Hodel -## Created: June 1995 - -function tfout (num, denom, x) - - save_empty = empty_list_elements_ok; - empty_list_elements_ok = 1; - - if (nargin < 2 ) | (nargin > 3) | (nargout != 0 ) - usage("tfout(num,denom[,x])"); - endif - - if ( (!is_vector(num)) | (!is_vector(denom)) ) - error("tfout: first two argument must be vectors"); - endif - - if (nargin == 2) - x = "s"; - elseif( ! isstr(x) ) - error("tfout: third argument must be a string"); - endif - - numstring = polyout(num,x); - denomstring = polyout(denom,x); - len = max(length(numstring),length(denomstring)); - if(len > 0) - y = strrep(blanks(len)," ","-"); - disp(numstring) - disp(y) - disp(denomstring) - else - error ("tfout: empty transfer function") - end - - empty_list_elements_ok = save_empty; -endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/zp2ss.m --- a/scripts/control/zp2ss.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,154 +0,0 @@ -## Copyright (C) 1996 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## -*- texinfo -*- -## @deftypefn {Function File} {[@var{A}, @var{B}, @var{C}, @var{D}] =} zp2ss (@var{zer}, @var{pol}, @var{k}) -## Conversion from zero / pole to state space. -## @strong{Inputs} -## @table @var -## @item zer -## @itemx pol -## vectors of (possibly) complex poles and zeros of a transfer -## function. Complex values must come in conjugate pairs -## (i.e., x+jy in zer means that x-jy is also in zer) -## @item k -## real scalar (leading coefficient) -## @end table -## @strong{Outputs} -## @var{A}, @var{B}, @var{C}, @var{D} -## The state space system -## @example -## . -## x = Ax + Bu -## y = Cx + Du -## @end example -## is obtained from a vector of zeros and a vector of poles via the -## function call @code{[a,b,c,d] = zp2ss(zer,pol,k)}. -## The vectors @samp{zer} and -## @samp{pol} may either be row or column vectors. Each zero and pole that -## has an imaginary part must have a conjugate in the list. -## The number of zeros must not exceed the number of poles. -## @samp{k} is @code{zp}-form leading coefficient. -## @end deftypefn - -## Author: David Clem -## Created: August 15, 1994 - -function [a, b, c, d] = zp2ss (zer, pol, k) - - sav_val = empty_list_elements_ok; - empty_list_elements_ok = 1; - - if(nargin != 3) - error("Incorrect number of input arguments"); - endif - - if(! (is_vector(zer) | isempty(zer)) ) - error(["zer(",num2str(rows(zer)),",",num2str(columns(zer)), ... - ") should be a vector"]); - elseif(! (is_vector(pol) | isempty(pol) ) ) - error(["pol(",num2str(rows(pol)),",",num2str(columns(pol)), ... - ") should be a vector"]); - elseif(! is_scalar(k)) - error(["k(",num2str(rows(k)),",",num2str(columns(k)), ... - ") should be a scalar"]); - elseif( k != real(k)) - warning("zp2ss: k is complex") - endif - - zpsys = ss2sys([],[],[],k); - - ## Find the number of zeros and the number of poles - nzer=length(zer); - npol =length(pol); - - if(nzer > npol) - error([num2str(nzer)," zeros, exceeds number of poles=",num2str(npol)]); - endif - - ## Sort to place complex conjugate pairs together - zer=sortcom(zer); - pol=sortcom(pol); - - ## construct the system as a series connection of poles and zeros - ## problem: poles and zeros may come in conjugate pairs, and not - ## matched up! - - ## approach: remove poles/zeros from the list as they are included in - ## the ss system - - while(length(pol)) - - ## search for complex poles, zeros - cpol=[]; czer = []; - if(!isempty(pol)) - cpol = find(imag(pol) != 0); - endif - if(!isempty(zer)) - czer = find(imag(zer) != 0); - endif - - if(isempty(cpol) & isempty(czer)) - pcnt = 1; - else - pcnt = 2; - endif - - num=1; # assume no zeros left. - switch(pcnt) - case(1) - ## real pole/zero combination - if(length(zer)) - num = [1, -zer(1)]; - zer = zer(2:length(zer)); - endif - den = [1, -pol(1)]; - pol = pol(2:length(pol)); - case(2) - ## got a complex pole or zero, need two roots (if available) - if(length(zer) > 1) - [num,zer] = zp2ssg2(zer); # get two zeros - elseif(length(zer) == 1) - num = [1, -zer]; # use last zero (better be real!) - zer = []; - endif - [den,pol] = zp2ssg2(pol); # get two poles - otherwise - error(["pcnt = ",num2str(pcnt)]) - endswitch - - ## pack tf into system form and put in series with earlier realization - zpsys1 = tf2sys(num,den,0,"u","yy"); - - ## change names to avoid warning messages from sysgroup - zpsys = syssetsignals(zpsys,"in","u1",1); - zpsys1 = sysupdate(zpsys1,"ss"); - nn = sysdimensions(zpsys); # working with continuous system - zpsys = syssetsignals(zpsys,"st", sysdefioname(nn,"x")); - nn1 = sysdimensions(zpsys1); - zpsys1 = syssetsignals(zpsys1,"st",sysdefioname(nn1,"xx")); - - zpsys = sysmult(zpsys,zpsys1); - - endwhile - - [a,b,c,d] = sys2ss(zpsys); - - empty_list_elements_ok = sav_val; -endfunction - diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/zp2ssg2.m --- a/scripts/control/zp2ssg2.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,68 +0,0 @@ -## Copyright (C) 1996, 1998 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## -*- texinfo -*- -## @deftypefn {Function File} {[@var{poly}, @var{rvals}] =} zp2ssg2 (@var{rvals}) -## Used internally in @code{zp2ss} -## Extract 2 values from @var{rvals} (if possible) and construct -## a polynomial with those roots. -## @end deftypefn - -## Author: A. S. Hodel -## Created: August 1996 - -function [poly, rvals] = zp2ssg2 (rvals) - - ## locate imaginary roots (if any) - cidx = find(imag(rvals)); - - if(!isempty(cidx)) - ## select first complex root, omit from cidx - r1i = cidx(1); r1 = rvals(r1i); cidx = complement(r1i,cidx); - - ## locate conjugate root (must be in cidx list, just in case there's - ## roundoff) - err = abs(rvals(cidx) - r1'); - minerr = min(err); - c2i = find(err == minerr); - r2i = cidx(c2i); - r2 = rvals(r2i); - cidx = complement(r2i,cidx); - - ## don't check for divide by zero, since 0 is not complex. - if(abs(r2 - r1')/abs(r1) > 1e-12) - error(sprintf("r1=(%f,%f); r2=(%f,%f), not conjugates.", ... - real(r1),imag(r1),real(r2),imag(r2))); - endif - - ## complex conjugate pair - poly = [1, -2*real(r1), real(r1)^2+imag(r1)^2]; - else - ## select two roots (they're all real) - r1 = rvals(1); - r2 = rvals(2); - poly = [1, -(r1+r2), (r1*r2)]; - r1i = 1; r2i = 2; - endif - - ## remove roots used - idx = complement([r1i, r2i],1:length(rvals)); - rvals = rvals(idx); - -endfunction - diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/zp2sys.m --- a/scripts/control/zp2sys.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,147 +0,0 @@ -## Copyright (C) 1996, 1998 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## -*- texinfo -*- -## @deftypefn {Function File} {@var{sys} =} zp2sys (@var{zer},@var{pol},@var{k}@{,@var{tsam},@var{inname},@var{outname}@}) -## Create system data structure from zero-pole data. -## -## @strong{Inputs} -## @table @var -## @item zer -## vector of system zeros -## @item pol -## vector of system poles -## @item k -## scalar leading coefficient -## @item tsam -## sampling period. default: 0 (continuous system) -## @item inname -## @itemx outname -## input/output signal names (lists of strings) -## @end table -## -## @strong{Outputs} -## sys: system data structure -## -## @strong{Example} -## @example -## octave:1> sys=zp2sys([1 -1],[-2 -2 0],1); -## octave:2> sysout(sys) -## Input(s) -## 1: u_1 -## Output(s): -## 1: y_1 -## zero-pole form: -## 1 (s - 1) (s + 1) -## ----------------- -## s (s + 2) (s + 2) -## @end example -## @end deftypefn - -## Modified by John Ingram July 20, 1996 - -function outsys = zp2sys (zer, pol, k, tsam, inname, outname) - - ## Test for the correct number of input arguments - if ((nargin < 3) || (nargin > 6)) - usage("outsys = zp2sys(zer,pol,k[,tsam,inname,outname])"); - endif - - ## check input format - if( ! (is_vector(zer) | isempty(zer) ) ) - error("zer must be a vector or empty"); - endif - if(!isempty(zer)) - zer = reshape(zer,1,length(zer)); # make it a row vector - endif - - if( ! (is_vector(pol) | isempty(pol))) - error("pol must be a vector"); - endif - if(!isempty(pol)) - pol = reshape(pol,1,length(pol)); - endif - - if (! is_scalar(k)) - error("k must be a scalar"); - endif - - ## Test proper numbers of poles and zeros. The number of poles must be - ## greater than or equal to the number of zeros. - if (length(zer) > length(pol)) - error(["number of poles (", num2str(length(pol)), ... - ") < number of zeros (", num2str(length(zer)),")"]); - endif - - ## Set the system transfer function - outsys.zer = zer; - outsys.pol = pol; - outsys.k = k; - - ## Set the system vector: active = 1, updated = [0 1 0]; - outsys.sys = [1, 0, 1, 0]; - - ## Set defaults - outsys.tsam = 0; - outsys.n = length(pol); - outsys.nz = 0; - outsys.yd = 0; # assume (for now) continuous time outputs - - ## Set the type of system - if (nargin > 3) - if( !is_scalar(tsam) ) - error("tsam must be a nonnegative scalar"); - endif - if (tsam < 0) - error("sampling time must be positve") - elseif (tsam > 0) - [outsys.n,outsys.nz] = swap(outsys.n, outsys.nz); - outsys.yd = 1; # discrete-time output - endif - - outsys.tsam = tsam; - endif - - outsys.inname = sysdefioname(1,"u"); - outsys.outname = sysdefioname(1,"y"); - outsys.stname = sysdefstname(outsys.n,outsys.nz); - - ## Set name of input - if (nargin > 4) - ## make sure its a string - if(!isempty(inname)) - if(!is_list(inname)) inname = list(inname); endif - if(!is_signal_list(inname)) - error("inname must be a single signal name"); - endif - outsys.inname = inname(1); - endif - endif - - ## Set name of output - if (nargin > 5) - if(!isempty(outname)) - if(!is_list(outname)) outname = list(outname); endif - if(!is_signal_list(outname)) - error("outname must be a single signal name"); - endif - outsys.outname = outname(1); - endif - endif - -endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/zp2tf.m --- a/scripts/control/zp2tf.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,75 +0,0 @@ -## Copyright (C) 1996, 1998 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## -*- texinfo -*- -## @deftypefn {Function File} {[@var{num}, @var{den}] =} zp2tf (@var{zer}, @var{pol}, @var{k}) -## Converts zeros / poles to a transfer function. -## @strong{Inputs} -## @table @var -## @item zer -## @itemx pol -## vectors of (possibly complex) poles and zeros of a transfer -## function. Complex values should appear in conjugate pairs -## @item k -## real scalar (leading coefficient) -## @end table -## @code{[num,den] = zp2tf(zer,pol,k)} forms the transfer function -## @code{num/den} from the vectors of poles and zeros. -## @end deftypefn - -## Author: A. S. Hodel -## (With help from students Ingram, McGowan.) - -function [num, den] = zp2tf (zer, pol, k) - - ## Find out whether data was entered as a row or a column vector and - ## convert to a column vector if necessary. - - [rp,cp] = size(pol); - [rz,cz] = size(zer); - - if(!(is_vector(zer) | isempty(zer)) ) - error(sprintf("zer(%dx%d) must be a vector",rz,cz)); - elseif(!(is_vector(pol) | isempty(pol)) ) - error(sprintf("pol(%dx%d) must be a vector",rp,cp)); - elseif(length(zer) > length(pol)) - error(sprintf("zer(%dx%d) longer than pol(%dx%d)",rz,cz,rp,cp)); - endif - - ## initialize converted polynomials - - num = k; den = 1; - - ## call zp2ssg2 if there are complex conjugate pairs left, otherwise - ## construct real zeros one by one. Repeat for poles. - - while(!isempty(zer)) - if( max(abs(imag(zer))) ) [poly,zer] = zp2ssg2(zer); - else poly = [1, -zer(1)]; - zer = zer(2:length(zer)); endif - num = conv(num,poly); - endwhile - - while(!isempty(pol)) - if( max(abs(imag(pol))) ) [poly,pol] = zp2ssg2(pol); - else poly = [1, -pol(1)]; - pol = pol(2:length(pol)); endif - den = conv(den,poly); - endwhile - -endfunction diff -r b9f5829ec843 -r 65b3519ac3a1 scripts/control/zpout.m --- a/scripts/control/zpout.m Fri Jan 14 03:18:47 2000 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,107 +0,0 @@ -## Copyright (C) 1996 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 2, 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, write to the Free -## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. - -## -*- texinfo -*- -## @deftypefn {Function File} {} zpout (@var{zer}, @var{pol}, @var{k}@{, @var{x}@}) -## print formatted zero-pole form to the screen. -## @var{x} defaults to the string @code{"s"} -## @end deftypefn -## @seealso{polyval, polyvalm, poly, roots, conv, deconv, residue, -## filter, polyderiv, polyinteg, and polyout} - -## Author: A. S. Hodel -## Created: June 1995 - -function zpout (zer, pol, k, x) - - save_empty = empty_list_elements_ok; - empty_list_elements_ok = 1; - - if (nargin < 3 ) | (nargin > 4) | (nargout != 0 ) - usage("zpout(zer,pol,k[,x])"); - endif - - if( !(is_vector(zer) | isempty(zer)) | !(is_vector(pol) | isempty(pol)) ) - error("zer, pol must be vectors or empty"); - endif - - if(!is_scalar(k)) - error("zpout: argument k must be a scalar.") - endif - - if (nargin == 3) - x = "s"; - elseif( ! isstr(x) ) - error("zpout: third argument must be a string"); - endif - - numstring = num2str(k); - - if(length(zer)) - ## find roots at z,s = 0 - nzr = sum(zer == 0); - if(nzr) - if(nzr > 1) - numstring = [numstring,sprintf(" %s^%d",x,nzr)]; - else - numstring = [numstring,sprintf(" %s",x)]; - endif - endif - zer = sortcom(-zer); - for ii=1:length(zer) - if(zer(ii) != 0) - numstring = [numstring,sprintf(" (%s %s)",x,com2str(zer(ii),1) ) ]; - endif - endfor - endif - - if(length(pol)) - ## find roots at z,s = 0 - nzr = sum(pol == 0); - if(nzr) - if(nzr > 1) - denomstring = [sprintf("%s^%d",x,nzr)]; - else - denomstring = [sprintf("%s",x)]; - endif - else - denomstring = " "; - endif - pol = sortcom(-pol); - for ii=1:length(pol) - if(pol(ii) != 0) - denomstring = [denomstring,sprintf(" (%s %s)",x,com2str(pol(ii),1))]; - endif - endfor - endif - - len = max(length(numstring),length(denomstring)); - if(len > 0) - y = strrep(blanks(len)," ","-"); - disp(numstring) - if(length(denomstring)) - disp(y) - disp(denomstring) - endif - else - error ("zpout: empty transfer function") - end - - empty_list_elements_ok = save_empty; - -endfunction