Mercurial > hg > octave-nkf
diff scripts/control/base/stepimp.m @ 3431:99ab64f4a09d
[project @ 2000-01-14 03:53:03 by jwe]
author | jwe |
---|---|
date | Fri, 14 Jan 2000 04:12:41 +0000 |
parents | |
children |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/scripts/control/base/stepimp.m @@ -0,0 +1,279 @@ +## 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{y}, @var{t}] = } stepimp (@var{sitype}, @var{sys} [, @var{inp}, @var{tstop}, @var{n}]) +## Impulse or step response for a linear system. +## The system can be discrete or multivariable (or both). +## This m-file contains the "common code" of step and impulse. +## +## Produces a plot or the response data for system sys. +## +## Limited argument checking; "do not attempt to do this at home". +## Used internally in @code{impulse}, @code{step}. Use @code{step} +## or @code{impulse} instead. +## @end deftypefn +## @seealso{step and impulse} + +## Author: Kai P. Mueller <mueller@ifr.ing.tu-bs.de> +## Created: October 2, 1997 +## based on lsim.m of Scottedward Hodel + +function [y, t] = stepimp (sitype, sys, inp, tstop, n) + + if (sitype == 1) IMPULSE = 0; + elseif (sitype == 2) IMPULSE = 1; + else error("stepimp: invalid sitype argument.") + endif + sys = sysupdate(sys,"ss"); + + USE_DEF = 0; # default tstop and n if we have to give up + N_MIN = 50; # minimum number of points + N_MAX = 2000; # maximum number of points + T_DEF = 10.0; # default simulation time + + ## collect useful information about the system + [ncstates,ndstates,NIN,NOUT] = sysdimensions(sys); + TSAMPLE = sysgettsam(sys); + + if (nargin < 3) inp = 1; + elseif (inp < 1 | inp > NIN) error("Argument inp out of range") + endif + + DIGITAL = is_digital(sys); + if (DIGITAL) + NSTATES = ndstates; + if (TSAMPLE < eps) + error("stepimp: sampling time of discrete system too small.") + endif + else NSTATES = ncstates; endif + if (NSTATES < 1) + error("step: pure gain block (n_states < 1), step response is trivial"); + endif + if (nargin < 5) + ## we have to compute the time when the system reaches steady state + ## and the step size + ev = eig(sys2ss(sys)); + if (DIGITAL) + ## perform bilinear transformation on poles in z + for i = 1:NSTATES + pole = ev(i); + if (abs(pole + 1) < 1.0e-10) + ev(i) = 0; + else + ev(i) = 2 / TSAMPLE * (pole - 1) / (pole + 1); + endif + endfor + endif + ## remove poles near zero from eigenvalue array ev + nk = NSTATES; + for i = 1:NSTATES + if (abs(ev(i)) < 1.0e-10) + ev(i) = 0; + nk = nk - 1; + endif + endfor + if (nk == 0) + USE_DEF = 1; + ## printf("##STEPIMP-DEBUG: using defaults.\n"); + else + ev = ev(find(ev)); + x = max(abs(ev)); + t_step = 0.2 * pi / x; + x = min(abs(real(ev))); + t_sim = 5.0 / x; + ## round up + yy = 10^(ceil(log10(t_sim)) - 1); + t_sim = yy * ceil(t_sim / yy); + ## printf("##STEPIMP-DEBUG: nk=%d t_step=%f t_sim=%f\n", + ## nk, t_step, t_sim); + endif + endif + + if (DIGITAL) + ## ---- sampled system + if (nargin == 5) + n = round(n); + if (n < 2) + error("stepimp: n must not be less than 2.") + endif + else + if (nargin == 4) + ## n is unknown + elseif (nargin >= 1) + ## tstop and n are unknown + if (USE_DEF) + tstop = (N_MIN - 1) * TSAMPLE; + else + tstop = t_sim; + endif + endif + n = floor(tstop / TSAMPLE) + 1; + if (n < 2) n = 2; endif + if (n > N_MAX) + n = N_MAX; + printf("Hint: number of samples limited to %d by default.\n", \ + N_MAX); + printf(" ==> increase \"n\" parameter for longer simulations.\n"); + endif + endif + tstop = (n - 1) * TSAMPLE; + t_step = TSAMPLE; + else + ## ---- continuous system + if (nargin == 5) + n = round(n); + if (n < 2) + error("step: n must not be less than 2.") + endif + t_step = tstop / (n - 1); + else + if (nargin == 4) + ## only n in unknown + if (USE_DEF) + n = N_MIN; + t_step = tstop / (n - 1); + else + n = floor(tstop / t_step) + 1; + endif + else + ## tstop and n are unknown + if (USE_DEF) + tstop = T_DEF; + n = N_MIN; + t_step = tstop / (n - 1); + else + tstop = t_sim; + n = floor(tstop / t_step) + 1; + endif + endif + if (n < N_MIN) + n = N_MIN; + t_step = tstop / (n - 1); + endif + if (n > N_MAX) + tstop = (n - 1) * t_step; + t_step = tstop / (N_MAX - 1); + n = N_MAX; + endif + endif + tstop = (n - 1) * t_step; + [jnk,B] = sys2ss(sys); + B = B(:,inp); + sys = c2d(sys, t_step); + endif + ## printf("##STEPIMP-DEBUG: t_step=%f n=%d tstop=%f\n", t_step, n, tstop); + + F = sys.a; + G = sys.b(:,inp); + C = sys.c; + D = sys.d(:,inp); + y = zeros(NOUT, n); + t = linspace(0, tstop, n); + + if (IMPULSE) + if (!DIGITAL && (D'*D > 0)) + error("impulse: D matrix is nonzero, impulse response infinite.") + endif + if (DIGITAL) + y(:,1) = D / t_step; + x = G / t_step; + else + x = B; + y(:,1) = C * x; + x = F * x; + endif + for i = 2:n + y(:,i) = C * x; + x = F * x; + endfor + else + x = zeros(NSTATES, 1); + for i = 1:n + y(:,i) = C * x + D; + x = F * x + G; + endfor + endif + + if(nargout == 0) + ## Plot the information + oneplot(); + gset nogrid + gset nologscale + gset autoscale + gset nokey + clearplot(); + if (gnuplot_has_multiplot) + if (IMPULSE) + gm = zeros(NOUT, 1); + tt = "impulse"; + else + ssys = ss2sys(F, G, C, D, t_step); + gm = dcgain(ssys); + tt = "step"; + endif + ncols = floor(sqrt(NOUT)); + nrows = ceil(NOUT / ncols); + for i = 1:NOUT + subplot(nrows, ncols, i); + title(sprintf("%s: | %s -> %s", tt,sysgetsignals(sys,"in",inp,1), ... + sysgetsignals(sys,"out",i,1))); + if (DIGITAL) + [ts, ys] = stairs(t, y(i,:)); + ts = ts(1:2*n-2)'; ys = ys(1:2*n-2)'; + if (length(gm) > 0) + yy = [ys; gm(i)*ones(size(ts))]; + else + yy = ys; + endif + grid("on"); + xlabel("time [s]"); + ylabel("y(t)"); + plot(ts, yy); + else + if (length(gm) > 0) + yy = [y(i,:); gm(i)*ones(size(t))]; + else + yy = y(i,:); + endif + grid("on"); + xlabel("time [s]"); + ylabel("y(t)"); + plot(t, yy); + endif + endfor + ## leave gnuplot in multiplot mode is bad style + oneplot(); + else + ## plot everything in one diagram + title([tt, " response | ", sysgetsignals(sys,"in",inp,1), ... + " -> all outputs"]); + if (DIGITAL) + stairs(t, y(i,:)); + else + grid("on"); + xlabel("time [s]"); + ylabel("y(t)"); + plot(t, y(i,:)); + endif + endif + y=[]; + t=[]; + endif + ## printf("##STEPIMP-DEBUG: gratulations, successfull completion.\n"); +endfunction