PageRenderTime 46ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/trunk/octave-forge/extra/control-legacy/inst/nyquist.m

#
MATLAB | 210 lines | 204 code | 6 blank | 0 comment | 18 complexity | ca8c74a6a522b750416b871a328378c3 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, LGPL-2.1, GPL-3.0, LGPL-3.0
  1. ## Copyright (C) 1996, 1998, 2000, 2003, 2004, 2005, 2006, 2007
  2. ## Auburn University. All rights reserved.
  3. ##
  4. ##
  5. ## This program is free software; you can redistribute it and/or modify it
  6. ## under the terms of the GNU General Public License as published by
  7. ## the Free Software Foundation; either version 3 of the License, or (at
  8. ## your option) any later version.
  9. ##
  10. ## This program is distributed in the hope that it will be useful, but
  11. ## WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. ## General Public License for more details.
  14. ##
  15. ## You should have received a copy of the GNU General Public License
  16. ## along with this program; see the file COPYING. If not, see
  17. ## <http://www.gnu.org/licenses/>.
  18. ## -*- texinfo -*-
  19. ## @deftypefn {Function File} {[@var{realp}, @var{imagp}, @var{w}] =} nyquist (@var{sys}, @var{w}, @var{out_idx}, @var{in_idx}, @var{atol})
  20. ## @deftypefnx {Function File} {} nyquist (@var{sys}, @var{w}, @var{out_idx}, @var{in_idx}, @var{atol})
  21. ## Produce Nyquist plots of a system; if no output arguments are given, Nyquist
  22. ## plot is printed to the screen.
  23. ##
  24. ## Compute the frequency response of a system.
  25. ##
  26. ## @strong{Inputs} (pass as empty to get default values)
  27. ## @table @var
  28. ## @item sys
  29. ## system data structure (must be either purely continuous or discrete;
  30. ## see @code{is_digital})
  31. ## @item w
  32. ## frequency values for evaluation.
  33. ## If sys is continuous, then bode evaluates @math{G(@var{jw})};
  34. ## if sys is discrete, then bode evaluates @math{G(exp(@var{jwT}))},
  35. ## where @var{T} is the system sampling time.
  36. ## @item default
  37. ## the default frequency range is selected as follows: (These
  38. ## steps are @strong{not} performed if @var{w} is specified)
  39. ## @enumerate
  40. ## @item via routine @command{__bodquist__}, isolate all poles and zeros away from
  41. ## @var{w}=0 (@var{jw}=0 or @math{exp(@var{jwT})=1}) and select the frequency
  42. ## range based on the breakpoint locations of the frequencies.
  43. ## @item if @var{sys} is discrete time, the frequency range is limited
  44. ## to @var{jwT} in
  45. ## @ifinfo
  46. ## [0,2p*pi]
  47. ## @end ifinfo
  48. ## @iftex
  49. ## @tex
  50. ## $ [ 0,2 p \pi ] $
  51. ## @end tex
  52. ## @end iftex
  53. ## @item A ``smoothing'' routine is used to ensure that the plot phase does
  54. ## not change excessively from point to point and that singular
  55. ## points (e.g., crossovers from +/- 180) are accurately shown.
  56. ## @end enumerate
  57. ## @item atol
  58. ## for interactive nyquist plots: atol is a change-in-slope tolerance
  59. ## for the of asymptotes (default = 0; 1e-2 is a good choice). This allows
  60. ## the user to ``zoom in'' on portions of the Nyquist plot too small to be
  61. ## seen with large asymptotes.
  62. ## @end table
  63. ## @strong{Outputs}
  64. ## @table @var
  65. ## @item realp
  66. ## @itemx imagp
  67. ## the real and imaginary parts of the frequency response
  68. ## @math{G(jw)} or @math{G(exp(jwT))} at the selected frequency values.
  69. ## @item w
  70. ## the vector of frequency values used
  71. ## @end table
  72. ##
  73. ## If no output arguments are given, nyquist plots the results to the screen.
  74. ## If @var{atol} != 0 and asymptotes are detected then the user is asked
  75. ## interactively if they wish to zoom in (remove asymptotes)
  76. ## Descriptive labels are automatically placed.
  77. ##
  78. ## Note: if the requested plot is for an @acronym{MIMO} system, a warning message is
  79. ## presented; the returned information is of the magnitude
  80. ## @iftex
  81. ## @tex
  82. ## $ \Vert G(jw) \Vert $ or $ \Vert G( {\rm exp}(jwT) \Vert $
  83. ## @end tex
  84. ## @end iftex
  85. ## @ifinfo
  86. ## ||G(jw)|| or ||G(exp(jwT))||
  87. ## @end ifinfo
  88. ## only; phase information is not computed.
  89. ## @end deftypefn
  90. ## Author: R. Bruce Tenison <btenison@eng.auburn.edu>
  91. ## Created: July 13, 1994
  92. ## A. S. Hodel July 1995 (adaptive frequency spacing,
  93. ## remove acura parameter, etc.)
  94. ## Revised by John Ingram July 1996 for system format
  95. function [realp, imagp, w] = nyquist (sys, w, outputs, inputs, atol)
  96. ## Both bode and nyquist share the same introduction, so the common
  97. ## parts are in a file called __bodquist__.m. It contains the part that
  98. ## finds the number of arguments, determines whether or not the system
  99. ## is SISO, andd computes the frequency response. Only the way the
  100. ## response is plotted is different between the two functions.
  101. ## check number of input arguments given
  102. if (nargin < 1 || nargin > 5)
  103. print_usage ();
  104. endif
  105. if (nargin < 2)
  106. w = [];
  107. endif
  108. if (nargin < 3)
  109. outputs = [];
  110. endif
  111. if (nargin < 4)
  112. inputs = [];
  113. endif
  114. if (nargin < 5)
  115. atol = 0;
  116. elseif (! (is_sample (atol) || atol == 0))
  117. error ("nyquist: atol must be a nonnegative scalar")
  118. endif
  119. ## signal to __bodquist__ who's calling
  120. [f, w, sys] = __bodquist__ (sys, w, outputs, inputs, "nyquist");
  121. ## Get the real and imaginary part of f.
  122. realp = real (f);
  123. imagp = imag (f);
  124. ## No output arguments, then display plot, otherwise return data.
  125. if (nargout == 0)
  126. dnplot = 0;
  127. while (! dnplot)
  128. plot (realp, imagp, "- ;+w;", realp, -imagp, "-@ ;-w;");
  129. grid ("on");
  130. if (is_digital (sys))
  131. tstr = " G(e^{jw}) ";
  132. else
  133. tstr = " G(jw) ";
  134. endif
  135. xlabel (sprintf ("Re(%s)", tstr));
  136. ylabel (sprintf ("Im(%s)", tstr));
  137. [stn, inn, outn] = sysgetsignals (sys);
  138. if (is_siso (sys))
  139. title (sprintf ("Nyquist plot from %s to %s, w (rad/s) in [%e, %e]",
  140. inn{1}, outn{1}, w(1), w(end)));
  141. endif
  142. axis (__axis2dlim__ ([[realp(:), imagp(:)]; [realp(:), -imagp(:)]]));
  143. ## check for interactive plots
  144. dnplot = 1; # assume done; will change later if atol is satisfied
  145. if (atol > 0 && length (f) > 2)
  146. ## check for asymptotes
  147. fmax = max (abs (f));
  148. fi = find (abs (f) == fmax, 1, "last");
  149. ## compute angles from point to point
  150. df = diff (f);
  151. th = atan2 (real (df), imag (df)) * 180 / pi;
  152. ## get angle at fmax
  153. if (fi == length (f))
  154. fi = fi-1;
  155. endif
  156. thm = th(fi);
  157. ## now locate consecutive angles within atol of thm
  158. ith_same = find (abs (th - thm) < atol);
  159. ichk = union (fi, find (diff (ith_same) == 1));
  160. ## locate max, min consecutive indices in ichk
  161. loval = max (complement (ichk, 1:fi));
  162. if (isempty (loval))
  163. loval = fi;
  164. else
  165. loval = loval + 1;
  166. endif
  167. hival = min (complement (ichk, fi:length(th)));
  168. if (isempty (hival))
  169. hival = fi+1;
  170. endif
  171. keep_idx = complement (loval:hival, 1:length(w));
  172. if (length (keep_idx))
  173. resp = input ("Remove asymptotes and zoom in (y or n): ", 1);
  174. if (resp(1) == "y")
  175. dnplot = 0; # plot again
  176. w = w(keep_idx);
  177. f = f(keep_idx);
  178. realp = real (f);
  179. imagp = imag (f);
  180. endif
  181. endif
  182. endif
  183. endwhile
  184. w = realp = imagp = [];
  185. endif
  186. endfunction