Mercurial > hg > octave-lyh
view scripts/control/base/nyquist.m @ 7583:1d7c23e288d7
__go_draw_axes__: use strcmpi for text properties; use get for hidden properties
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Tue, 11 Mar 2008 23:12:17 -0400 |
parents | 4a375de63f66 |
children |
line wrap: on
line source
## Copyright (C) 1996, 1998, 2000, 2003, 2004, 2005, 2006, 2007 ## Auburn University. All rights reserved. ## ## This file is part of Octave. ## ## Octave is free software; you can redistribute it and/or modify it ## under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or (at ## your option) any later version. ## ## Octave is distributed in the hope that it will be useful, but ## WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with Octave; see the file COPYING. If not, see ## <http://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{realp}, @var{imagp}, @var{w}] =} nyquist (@var{sys}, @var{w}, @var{out_idx}, @var{in_idx}, @var{atol}) ## @deftypefnx {Function File} {} nyquist (@var{sys}, @var{w}, @var{out_idx}, @var{in_idx}, @var{atol}) ## Produce Nyquist plots of a system; if no output arguments are given, Nyquist ## plot is printed to the screen. ## ## Compute the frequency response of a system. ## ## @strong{Inputs} (pass as empty to get default values) ## @table @var ## @item sys ## system data structure (must be either purely continuous or discrete; ## see @code{is_digital}) ## @item w ## frequency values for evaluation. ## If sys is continuous, then bode evaluates @math{G(@var{jw})}; ## if sys is discrete, then bode evaluates @math{G(exp(@var{jwT}))}, ## where @var{T} is the system sampling time. ## @item default ## the default frequency range is selected as follows: (These ## steps are @strong{not} performed if @var{w} is specified) ## @enumerate ## @item via routine @command{__bodquist__}, isolate all poles and zeros away from ## @var{w}=0 (@var{jw}=0 or @math{exp(@var{jwT})=1}) and select the frequency ## range based on the breakpoint locations of the frequencies. ## @item if @var{sys} is discrete time, the frequency range is limited ## to @var{jwT} in ## @ifinfo ## [0,2p*pi] ## @end ifinfo ## @iftex ## @tex ## $ [ 0,2 p \pi ] $ ## @end tex ## @end iftex ## @item A ``smoothing'' routine is used to ensure that the plot phase does ## not change excessively from point to point and that singular ## points (e.g., crossovers from +/- 180) are accurately shown. ## @end enumerate ## @item atol ## for interactive nyquist plots: atol is a change-in-slope tolerance ## for the of asymptotes (default = 0; 1e-2 is a good choice). This allows ## the user to ``zoom in'' on portions of the Nyquist plot too small to be ## seen with large asymptotes. ## @end table ## @strong{Outputs} ## @table @var ## @item realp ## @itemx imagp ## the real and imaginary parts of the frequency response ## @math{G(jw)} or @math{G(exp(jwT))} at the selected frequency values. ## @item w ## the vector of frequency values used ## @end table ## ## If no output arguments are given, nyquist plots the results to the screen. ## If @var{atol} != 0 and asymptotes are detected then the user is asked ## interactively if they wish to zoom in (remove asymptotes) ## Descriptive labels are automatically placed. ## ## Note: if the requested plot is for an @acronym{MIMO} system, a warning message is ## presented; the returned information is of the magnitude ## @iftex ## @tex ## $ \Vert G(jw) \Vert $ or $ \Vert G( {\rm exp}(jwT) \Vert $ ## @end tex ## @end iftex ## @ifinfo ## ||G(jw)|| or ||G(exp(jwT))|| ## @end ifinfo ## only; phase information is not computed. ## @end deftypefn ## Author: R. Bruce Tenison <btenison@eng.auburn.edu> ## Created: July 13, 1994 ## A. S. Hodel July 1995 (adaptive frequency spacing, ## remove acura parameter, etc.) ## Revised by John Ingram July 1996 for system format function [realp, imagp, w] = nyquist (sys, w, outputs, inputs, atol) ## Both bode and nyquist share the same introduction, so the common ## parts are in a file called __bodquist__.m. It contains the part that ## finds the number of arguments, determines whether or not the system ## is SISO, andd computes the frequency response. Only the way the ## response is plotted is different between the two functions. ## check number of input arguments given if (nargin < 1 || nargin > 5) print_usage (); endif if (nargin < 2) w = []; endif if (nargin < 3) outputs = []; endif if (nargin < 4) inputs = []; endif if (nargin < 5) atol = 0; elseif (! (is_sample (atol) || atol == 0)) error ("nyquist: atol must be a nonnegative scalar") endif ## signal to __bodquist__ who's calling [f, w, sys] = __bodquist__ (sys, w, outputs, inputs, "nyquist"); ## Get the real and imaginary part of f. realp = real (f); imagp = imag (f); ## No output arguments, then display plot, otherwise return data. if (nargout == 0) dnplot = 0; while (! dnplot) plot (realp, imagp, "- ;+w;", realp, -imagp, "-@ ;-w;"); grid ("on"); if (is_digital (sys)) tstr = " G(e^{jw}) "; else tstr = " G(jw) "; endif xlabel (sprintf ("Re(%s)", tstr)); ylabel (sprintf ("Im(%s)", tstr)); [stn, inn, outn] = sysgetsignals (sys); if (is_siso (sys)) title (sprintf ("Nyquist plot from %s to %s, w (rad/s) in [%e, %e]", inn{1}, outn{1}, w(1), w(end))); endif axis (axis2dlim ([[realp(:), imagp(:)]; [realp(:), -imagp(:)]])); ## check for interactive plots dnplot = 1; # assume done; will change later if atol is satisfied if (atol > 0 && length (f) > 2) ## check for asymptotes fmax = max (abs (f)); fi = find (abs (f) == fmax, 1, "last"); ## compute angles from point to point df = diff (f); th = atan2 (real (df), imag (df)) * 180 / pi; ## get angle at fmax if (fi == length (f)) fi = fi-1; endif thm = th(fi); ## now locate consecutive angles within atol of thm ith_same = find (abs (th - thm) < atol); ichk = union (fi, find (diff (ith_same) == 1)); ## locate max, min consecutive indices in ichk loval = max (complement (ichk, 1:fi)); if (isempty (loval)) loval = fi; else loval = loval + 1; endif hival = min (complement (ichk, fi:length(th))); if (isempty (hival)) hival = fi+1; endif keep_idx = complement (loval:hival, 1:length(w)); if (length (keep_idx)) resp = input ("Remove asymptotes and zoom in (y or n): ", 1); if (resp(1) == "y") dnplot = 0; # plot again w = w(keep_idx); f = f(keep_idx); realp = real (f); imagp = imag (f); endif endif endif endwhile w = realp = imagp = []; endif endfunction