Mercurial > hg > octave-nkf
diff scripts/control/freqresp.m @ 3213:ba1c7cdc6090
[project @ 1998-11-06 16:15:36 by jwe]
author | jwe |
---|---|
date | Fri, 06 Nov 1998 16:16:31 +0000 |
parents | |
children | dbcc24961c44 |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/scripts/control/freqresp.m @@ -0,0 +1,118 @@ +# Copyright (C) 1996,1998 A. Scottedward Hodel +# +# 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, 675 Mass Ave, Cambridge, MA 02139, USA. + +function [ff,w] = freqresp(sys,USEW,w); + # function [ff,w] = freqresp(sys,USEW{,w}); + # Frequency response function - used internally by bode, nyquist. + # minimal argument checking; "do not attempt to do this at home" + # USEW returned by freqchkw + # w: optional, must be present if USEW is given + # + # returns: ff = vector of finite G(j*w) entries (or || G(j*w) || for MIMO) + # w = vector of frequencies used + # ff and w are both returned as row vectors + + # Written by: R. Bruce Tenison July 11, 1994 + # $Revision: 1.6 $ + # SYS_INTERNAL accesses members of system data structure + + save_val = empty_list_elements_ok; + empty_list_elements_ok = 1; + + # Check Args + if( (nargin < 2) || (nargin > 4) ) + usage ("[ff,w] = freqresp(sys,USEW{,w})"); + elseif( USEW & (nargin < 3) ) + error("USEW=1 but w was not passed."); + elseif( USEW & isempty(w)) + warning("USEW=1 but w is empty; setting USEW=0"); + USEW=0; + endif + + DIGITAL = is_digital(sys); + + # compute default w if needed + if(!USEW) + if(is_siso(sys)) + sys = sysupdate(sys,"zp"); + [zer,pol] = sys2zp(sys); + else + zer = tzero(sys); + pol = eig(sys2ss(sys)); + endif + + # get default frequency range + [wmin,wmax] = bode_bounds(zer,pol,DIGITAL,sysgettsam(sys)); + w = logspace(wmin,wmax,50); + else + w = reshape(w,1,length(w)); # make sure it's a row vector + endif + + # now get complex values of s or z + if(DIGITAL) + jw = exp(i*w*sysgettsam(sys)); + else + jw = i*w; + endif + + [nn,nz,mm,pp] = sysdimensions(sys); + + # now compute the frequency response - divide by zero yields a warning + if (strcmp(sysgettype(sys),"zp")) + # zero-pole form (preferred) + [zer,pol,sysk] = sys2zp(sys); + ff = ones(size(jw)); + l1 = min(length(zer)*(1-isempty(zer)),length(pol)*(1-isempty(pol))); + for ii=1:l1 + ff = ff .* (jw - zer(ii)) ./ (jw - pol(ii)); + endfor + + # require proper transfer function, so now just get poles. + for ii=(l1+1):length(pol) + ff = ff ./ (jw - pol(ii)); + endfor + ff = ff*sysk; + + elseif (strcmp(sysgettype(sys),"tf")) + # transfer function form + [num,den] = sys2tf(sys); + ff = polyval(num,jw)./polyval(den,jw); + elseif (mm==pp) + # The system is square; do state-space form bode plot + [sysa,sysb,sysc,sysd,tsam,sysn,sysnz] = sys2ss(sys); + n = sysn + sysnz; + for ii=1:length(jw); + ff(ii) = det(sysc*((jw(ii).*eye(n)-sysa)\sysb)+sysd); + endfor; + else + # Must be state space... bode + [sysa,sysb,sysc,sysd,tsam,sysn,sysnz] = sys2ss(sys); + n = sysn + sysnz; + for ii=1:length(jw); + ff(ii) = norm(sysc*((jw(ii)*eye(n)-sysa)\sysb)+sysd); + endfor + + endif + + w = reshape(w,1,length(w)); + ff = reshape(ff,1,length(ff)); + + # restore global variable + empty_list_elements_ok = save_val; +endfunction +