home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / octa21eb.zip / octave / SCRIPTS.ZIP / scripts / control / bodquist.m < prev    next >
Text File  |  1999-03-05  |  4KB  |  128 lines

  1. # Copyright (C) 1996,1998 A. Scottedward Hodel 
  2. #
  3. # This file is part of Octave. 
  4. #
  5. # Octave is free software; you can redistribute it and/or modify it 
  6. # under the terms of the GNU General Public License as published by the 
  7. # Free Software Foundation; either version 2, or (at your option) any 
  8. # later version. 
  9. # Octave is distributed in the hope that it will be useful, but WITHOUT 
  10. # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
  11. # FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License 
  12. # for more details.
  13. # You should have received a copy of the GNU General Public License 
  14. # along with Octave; see the file COPYING.  If not, write to the Free 
  15. # Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
  16.  
  17. function [f,w] = bodquist(sys,w,outputs,inputs,rname)
  18. # [f,w] = bodquist(sys,w,outputs,inputs)
  19. # used by bode, nyquist
  20. # inputs:
  21. #   sys: input system structure
  22. #   w: range of frequencies; empty if user wants default
  23. #   outputs:list of outputs; empty if user wants all
  24. #   inputs: list of inputs; empty if user wants all
  25. #   rname: name of routine that called bodquist ("bode" or "nyquist")
  26. # outputs:
  27. #   w: list of frequencies 
  28. #   f: frequency response of sys; f(ii) = f(omega(ii))
  29. #
  30. # Both bode and nyquist share the same introduction, so the common parts are 
  31. # in this file bodquist.m.  It contains the part that finds the 
  32. # number of arguments, determines whether or not the system is SISO, and 
  33. # computes the frequency response.  Only the way the response is plotted is
  34. # different between the two functions.
  35.  
  36.   # check number of input arguments given
  37.   if (nargin != 5)
  38.     usage("[f,w] = bodquist(sys,w,outputs,inputs,rname)");
  39.   endif
  40.  
  41.   # check each argument to see if it's in the correct form
  42.   if (!is_struct(sys))
  43.     error("sys must be a system data structure");
  44.   endif
  45.     
  46.   # let freqresp determine w if it's not already given
  47.   USEW = freqchkw(w);
  48.  
  49.   # get initial dimensions (revised below if sysprune is called)
  50.   [nn,nz,mm,pp ] = sysdimensions(sys);
  51.  
  52.   # check for an output vector and to see whether it`s correct
  53.   if (!isempty(outputs))
  54.     if (isempty(inputs))
  55.       inputs = 1:mm;            # use all inputs
  56.       warning([rname,": outputs specified but not inputs"]);
  57.     endif
  58.     sys = sysprune(sys,outputs,inputs);
  59.     [nn,nz,mm,pp ] = sysdimensions(sys);
  60.   endif
  61.  
  62.   # for speed in computation, convert local copy of 
  63.   # SISO state space systems to zero-pole  form
  64.   if( is_siso(sys) & strcmp( sysgettype(sys), "ss") )
  65.     [zer,pol,k,tsam,inname,outname] = sys2zp(sys);
  66.     sys = zp2sys(zer,pol,k,tsam,inname,outname);
  67.   endif
  68.  
  69.   # get system frequency response
  70.   [f,w] = freqresp(sys,USEW,w);   
  71.  
  72.   phase = arg(f)*180.0/pi;
  73.  
  74.   if(!USEW)
  75.     # smooth plots
  76.     pcnt = 5;        # max number of refinement steps
  77.     dphase = 5;        # desired max change in phase
  78.     dmag = 0.2;        # desired max change in magnitude
  79.     while(pcnt)
  80.       pd = abs(diff(phase));            # phase variation
  81.       pdbig = vec(find(pd > dphase));
  82.  
  83.       lp = length(f);  lp1 = lp-1;        # relative variation
  84.       fd = abs(diff(f));
  85.       fm = max(abs([f(1:lp1); f(2:lp)]));
  86.       fdbig = vec(find(fd > fm/10));
  87.  
  88.       bigpts = union(fdbig, pdbig);
  89.  
  90.       if(isempty(bigpts) )
  91.         pcnt = 0;
  92.       else
  93.         pcnt = pcnt - 1;
  94.         wnew = [];
  95.         crossover_points = find ( phase(1:lp1).*phase(2:lp) < 0);
  96.         pd(crossover_points) = abs(359.99+dphase - pd(crossover_points));
  97.         np_pts = ceil(pd/dphase)+2;        # phase points
  98.         nm_pts = ceil(log(fd./fm)/log(dmag))+2;     # magnitude points
  99.         npts = min(5,max(np_pts, nm_pts));
  100.         w1 = log10(w(1:lp1));
  101.         w2 = log10(w(2:lp));
  102.         for ii=bigpts
  103.           if(npts(ii))
  104.             wseg(ii,1:npts(ii)) = logspace(w1(ii),w2(ii),npts(ii));
  105.           endif
  106.         endfor
  107.         wnew = reshape(wseg,1,rows(wseg)*columns(wseg)); # make a row vector
  108.         wnew = wnew(find(wnew != 0));
  109.         wnew = sort(wnew);
  110.         wnew = create_set(wnew);
  111.         if(isempty(wnew))   # all small crossovers
  112.           pcnt = 0;
  113.         else
  114.           [fnew,wnew] = freqresp(sys,1,wnew);    # get new freq resp points
  115.           w = [w,wnew];            # combine with old freq resp
  116.           f = [f,fnew];
  117.           [w,idx] = sort(w);        # sort into order
  118.           f = f(idx);
  119.           phase = arg(f)*180.0/pi;
  120.         endif
  121.       endif
  122.     endwhile
  123.   endif
  124.     
  125. endfunction
  126.