1
## Copyright (C) 1996, 1998, 2000, 2002, 2003, 2004, 2005, 2006, 2007
2
## Auburn University. All rights reserved.
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.
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.
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/>.
19
## Undocumented internal function.
22
## @deftypefn {Function File} {[@var{f}, @var{w}, @var{rsys}] =} __bodquist__ (@var{sys}, @var{w}, @var{out_idx}, @var{in_idx})
23
## Used internally by @command{bode}, @command{nyquist}; compute system frequency response.
28
## input system structure
30
## range of frequencies; empty if user wants default
33
## names or indices of output/input signal names; empty if user wants all
35
## name of routine that called __bodquist__ ("bode", "nyquist", or "nichols")
40
## list of frequencies
42
## frequency response of sys; @math{f(ii) = f(omega(ii))}
44
## system with selected inputs and outputs
47
## @code{bode}, @code{nichols}, and @code{nyquist} share the same
48
## introduction, so the common parts are
49
## in __bodquist__. It contains the part that finds the number of arguments,
50
## determines whether or not the system is @acronym{SISO}, and computes the frequency
51
## response. Only the way the response is plotted is different between the
55
function [f, w, rsys] = __bodquist__ (sys, w, outputs, inputs, rname)
57
## check number of input arguments given
62
## check each argument to see if it's in the correct form
64
error ("sys must be a system data structure");
67
## let __freqresp__ determine w if it's not already given
70
## get initial dimensions (revised below if sysprune is called)
71
[nn, nz, mm, pp] = sysdimensions (sys);
73
## check for an output vector and to see whether it`s correct
74
if (! isempty (outputs))
76
inputs = 1:mm; # use all inputs
77
warning ("%s: outputs specified but not inputs", rname);
78
elseif (is_signal_list (inputs) || ischar (inputs))
79
inputs = sysidx (sys, "in", inputs);
81
if (is_signal_list (outputs) || ischar (outputs))
82
outputs = sysidx (sys, "out", outputs);
84
sys = sysprune (sys, outputs, inputs);
85
[nn, nz, mm, pp] = sysdimensions (sys);
88
## for speed in computation, convert local copy of
89
## SISO state space systems to zero-pole form
90
if (is_siso (sys) && strcmp (sysgettype (sys), "ss"))
91
[zer, pol, k, tsam, inname, outname] = sys2zp (sys);
92
sys = zp (zer, pol, k, tsam, inname, outname);
95
## get system frequency response
96
[f, w] = __freqresp__ (sys, USEW, w);
98
phase = arg(f)*180.0/pi;
102
pcnt = 5; # max number of refinement steps
103
dphase = 5; # desired max change in phase
104
dmag = 0.2; # desired max change in magnitude
106
pd = abs (diff (phase)); # phase variation
107
pdbig = find (pd > dphase);
109
## relative variation
114
fm = max (abs ([f(1:lp1); f(2:lp)]));
115
fdbig = find (fd > fm/10);
117
bigpts = union (fdbig, pdbig);
119
if (isempty (bigpts))
124
crossover_points = find (phase(1:lp1).*phase(2:lp) < 0);
125
pd(crossover_points) = abs (359.99+dphase - pd(crossover_points));
126
np_pts = max (3, ceil(pd/dphase)+2); # phase points
127
nm_pts = max (3, ceil(log(fd./fm)/log(dmag))+2); # magnitude points
128
npts = min (5, max(np_pts, nm_pts));
130
w1 = log10 (w(1:lp1));
131
w2 = log10 (w(2:lp));
134
wtmp = logspace (w1(ii), w2(ii), npts(ii));
135
wseg(ii,1:(npts(ii)-2)) = wtmp(2:(npts(ii)-1));
138
wnew = vec(wseg)'; # make a row vector
139
wnew = wnew(find (wnew != 0));
141
wnew = create_set (wnew);
142
if (isempty (wnew)) # all small crossovers
145
## get new freq resp points, combine with old, and sort.
146
[fnew, wnew] = __freqresp__ (sys, 1, wnew);
151
phase = arg(f)*180.0/pi;
157
## ensure unique frequency values
162
w_dup = find (w_diff == 0);
163
w_idx = complement (w_dup, 1:length(w));
167
## set rsys to pruned system