]> Creatis software - CreaPhase.git/blobdiff - octave_packages/control-2.3.52/__time_response__.m
Add a useful package (from Source forge) for octave
[CreaPhase.git] / octave_packages / control-2.3.52 / __time_response__.m
diff --git a/octave_packages/control-2.3.52/__time_response__.m b/octave_packages/control-2.3.52/__time_response__.m
new file mode 100644 (file)
index 0000000..81ca3d1
--- /dev/null
@@ -0,0 +1,304 @@
+## Copyright (C) 2009, 2010   Lukas F. Reichlin
+##
+## This file is part of LTI Syncope.
+##
+## LTI Syncope is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## LTI Syncope 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 LTI Syncope.  If not, see <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## Common code for the time response functions step, impulse and initial.
+
+## Author: Lukas Reichlin <lukas.reichlin@gmail.com>
+## Created: October 2009
+## Version: 0.2
+
+function [y, t, x_arr] = __time_response__ (sys, resptype, plotflag, tfinal, dt, x0, sysname)
+
+  if (! isa (sys, "ss"))
+    sys = ss (sys);                                    # sys must be proper
+  endif
+
+  if (is_real_vector (tfinal) && length (tfinal) > 1)  # time vector t passed
+    dt = tfinal(2) - tfinal(1);                        # assume that t is regularly spaced
+    tfinal = tfinal(end);
+  endif
+
+  [A, B, C, D, tsam] = ssdata (sys);
+
+  discrete = ! isct (sys);                             # static gains are treated as analog systems
+  tsam = abs (tsam);                                   # use 1 second if tsam is unspecified (-1)
+
+  if (discrete)
+    if (! isempty (dt))
+      warning ("time_response: argument dt has no effect on sampling time of discrete system");
+    endif
+
+    dt = tsam;
+  endif
+
+  [tfinal, dt] = __sim_horizon__ (A, discrete, tfinal, dt);
+
+  if (! discrete)
+    sys = c2d (sys, dt, "zoh");
+  endif
+
+  [F, G] = ssdata (sys);                               # matrices C and D don't change
+
+  n = rows (F);                                        # number of states
+  m = columns (G);                                     # number of inputs
+  p = rows (C);                                        # number of outputs
+
+  ## time vector
+  t = reshape (0 : dt : tfinal, [], 1);
+  l_t = length (t);
+
+  switch (resptype)
+    case "initial"
+      str = ["Response of ", sysname, " to Initial Conditions"];
+      yfinal = zeros (p, 1);
+
+      ## preallocate memory
+      y = zeros (l_t, p);
+      x_arr = zeros (l_t, n);
+
+      ## initial conditions
+      x = reshape (x0, [], 1);                         # make sure that x is a column vector
+
+      if (n != length (x0) || ! is_real_vector (x0))
+        error ("initial: x0 must be a real vector with %d elements", n);
+      endif
+
+      ## simulation
+      for k = 1 : l_t
+        y(k, :) = C * x;
+        x_arr(k, :) = x;
+        x = F * x;
+      endfor
+
+    case "step"
+      str = ["Step Response of ", sysname];
+      yfinal = dcgain (sys);
+
+      ## preallocate memory
+      y = zeros (l_t, p, m);
+      x_arr = zeros (l_t, n, m);
+
+      for j = 1 : m                                    # for every input channel
+        ## initial conditions
+        x = zeros (n, 1);
+        u = zeros (m, 1);
+        u(j) = 1;
+
+        ## simulation
+        for k = 1 : l_t
+          y(k, :, j) = C * x + D * u;
+          x_arr(k, :, j) = x;
+          x = F * x + G * u;
+        endfor
+      endfor
+
+    case "impulse"
+      str = ["Impulse Response of ", sysname];
+      yfinal = zeros (p, m);
+
+      ## preallocate memory
+      y = zeros (l_t, p, m);
+      x_arr = zeros (l_t, n, m);
+
+      for j = 1 : m                                    # for every input channel
+        ## initial conditions
+        u = zeros (m, 1);
+        u(j) = 1;
+
+        if (discrete)
+          x = zeros (n, 1);                            # zero by definition 
+          y(1, :, j) = D * u / dt;
+          x_arr(1, :, j) = x;
+          x = G * u / dt;
+        else
+          x = B * u;                                   # B, not G!
+          y(1, :, j) = C * x;
+          x_arr(1, :, j) = x;
+          x = F * x;
+        endif
+
+        ## simulation
+        for k = 2 : l_t
+          y (k, :, j) = C * x;
+          x_arr(k, :, j) = x;
+          x = F * x;
+        endfor
+      endfor
+
+      if (discrete)
+        y *= dt;
+        x_arr *= dt;
+      endif
+
+    otherwise
+      error ("time_response: invalid response type");
+
+  endswitch
+
+  
+  if (plotflag)                                        # display plot
+
+    ## TODO: Set correct titles, especially for multi-input systems
+
+    stable = isstable (sys);
+    outname = get (sys, "outname");
+    outname = __labels__ (outname, "y_");
+
+    if (strcmp (resptype, "initial"))
+      cols = 1;
+    else
+      cols = m;
+    endif
+
+    if (discrete)                                      # discrete system
+      for k = 1 : p
+        for j = 1 : cols
+
+          subplot (p, cols, (k-1)*cols+j);
+
+          if (stable)
+            stairs (t, [y(:, k, j), yfinal(k, j) * ones(l_t, 1)]);
+          else
+            stairs (t, y(:, k, j));
+          endif
+
+          grid ("on");
+
+          if (k == 1 && j == 1)
+            title (str);
+          endif
+
+          if (j == 1)
+            ylabel (sprintf ("Amplitude %s", outname{k}));
+          endif
+
+        endfor
+      endfor
+
+      xlabel ("Time [s]");
+
+    else                                               # continuous system
+      for k = 1 : p
+        for j = 1 : cols
+
+          subplot (p, cols, (k-1)*cols+j);
+
+          if (stable)
+            plot (t, [y(:, k, j), yfinal(k, j) * ones(l_t, 1)]);
+          else
+            plot (t, y(:, k, j));
+          endif
+
+          grid ("on");
+
+          if (k == 1 && j == 1)
+            title (str);
+          endif
+
+          if (j == 1)
+            ylabel (sprintf ("Amplitude %s", outname{k}));
+          endif
+
+        endfor
+      endfor
+
+      xlabel ("Time [s]");
+
+    endif 
+  endif
+
+endfunction
+
+
+function [tfinal, dt] = __sim_horizon__ (A, discrete, tfinal, Ts)
+
+  ## code based on __stepimp__.m of Kai P. Mueller and A. Scottedward Hodel
+
+  TOL = 1.0e-10;                                       # values below TOL are assumed to be zero
+  N_MIN = 50;                                          # min number of points
+  N_MAX = 2000;                                        # max number of points
+  N_DEF = 1000;                                        # default number of points
+  T_DEF = 10;                                          # default simulation time
+
+  n = rows (A);
+  eigw = eig (A);
+
+  if (discrete)
+    ## perform bilinear transformation on poles in z
+    for k = 1 : n
+      pol = eigw(k);
+      if (abs (pol + 1) < TOL)
+        eigw(k) = 0;
+      else
+        eigw(k) = 2 / Ts * (pol - 1) / (pol + 1);
+      endif
+    endfor
+  endif
+
+  ## remove poles near zero from eigenvalue array eigw
+  nk = n;
+  for k = 1 : n
+    if (abs (real (eigw(k))) < TOL)
+      eigw(k) = 0;
+      nk -= 1;
+    endif
+  endfor
+
+  if (nk == 0)
+    if (isempty (tfinal))
+      tfinal = T_DEF;
+    endif
+
+    if (! discrete)
+      dt = tfinal / N_DEF;
+    endif
+  else
+    eigw = eigw(find (eigw));
+    eigw_max = max (abs (eigw));
+
+    if (! discrete)
+      dt = 0.2 * pi / eigw_max;
+    endif
+
+    if (isempty (tfinal))
+      eigw_min = min (abs (real (eigw)));
+      tfinal = 5.0 / eigw_min;
+
+      ## round up
+      yy = 10^(ceil (log10 (tfinal)) - 1);
+      tfinal = yy * ceil (tfinal / yy);
+    endif
+
+    if (! discrete)
+      N = tfinal / dt;
+
+      if (N < N_MIN)
+        dt = tfinal / N_MIN;
+      endif
+
+      if (N > N_MAX)
+        dt = tfinal / N_MAX;
+      endif
+    endif
+  endif
+
+  if (! isempty (Ts))                                  # catch case cont. system with dt specified
+    dt = Ts;
+  endif
+
+endfunction