home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / octa21eb.zip / octave / SCRIPTS.ZIP / scripts.fat / control / rlocus.m < prev    next >
Text File  |  1999-04-29  |  7KB  |  199 lines

  1. # Copyright (C) 1996 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 [rldata,k_break,rlpol,gvec,real_ax_pts] = rlocus(sys,increment,min_k,max_k)
  18.   # [rldata,k_break,rlpol,gvec,real_ax_pts] = rlocus(sys,increment,min_k,max_k)
  19.   # Displays root locus plot of the specified SISO system.
  20.   # 
  21.   #       -----   ---     -------- 
  22.   #   --->| + |---|k|---->| SISO |----------->
  23.   #       -----   ---     --------        | 
  24.   #       - ^                             | 
  25.   #         |_____________________________|  
  26.   #
  27.   #inputs: sys = system data structure
  28.   #        min_k, max_k,increment: minimum, maximum values of k and
  29.   #               the increment used in computing gain values
  30.   # outputs: plots the root locus to the screen.  
  31.   #   rldata: Data points plotted column 1: real values, column 2: imaginary
  32.   #           values)
  33.   #   k_break: gains for real axis break points.
  34.   #   rlpol: complex vector: column ii of pol is the set of poles
  35.   #        corresponding to to gain gvec(ii)
  36.   #   gvec: gains used to compute root locus
  37.   #   real_ax_pts: breakpoints of the real axis locus.
  38.   
  39.   # Convert the input to a transfer function if necessary
  40.   # Written by Clem and Tenison
  41.   # Updated by Kristi McGowan July 1996 for intelligent gain selection
  42.   # Updated by John Ingram July 1996 for systems
  43.   
  44.   if (nargin < 1) | (nargin > 4)
  45.     usage("rlocus(sys[,inc,mink,maxk])");
  46.   endif
  47.   
  48.   [num,den] = sys2tf(sys);        # extract numerator/denom polyomials
  49.   lnum = length(num);      lden = length(den);
  50.   if(lden < 2)
  51.     error(sprintf("length of derivative=%d, doesn't make sense",lden));
  52.   elseif(lnum == 1)
  53.     num = [0, num];     # so that derivative is shortened by one
  54.   endif
  55.  
  56.   # root locus plot axis limits
  57.   
  58.   # compute real axis locus breakpoints
  59.   # compute the derivative of the numerator and the denominator 
  60.   dern=polyderv(num);        derd=polyderv(den);
  61.   
  62.   # compute real axis breakpoints
  63.   real_ax_pol = conv(den,dern) - conv(num,derd);
  64.   real_ax_pts = roots(real_ax_pol);
  65.   if(isempty(real_ax_pts))
  66.     k_break = [];
  67.     maxk = 0;
  68.   else
  69.     # compute gains that achieve the breakpoints
  70.     c1 = polyval(num,real_ax_pts);
  71.     c2 = polyval(den,real_ax_pts);
  72.     k_break = -real(c2 ./ c1);
  73.     maxk = max(max(k_break,0));
  74.   endif
  75.  
  76.   # compute gain ranges based on computed K values
  77.   if(maxk == 0)     maxk = 1; 
  78.   else              maxk = 1.1*maxk;        endif
  79.   mink = 0;
  80.   ngain = 20;
  81.  
  82.   # check for input arguments:
  83.   if (nargin > 2)       mink = min_k;          endif
  84.   if (nargin > 3)       maxk = max_k;          endif
  85.   if (nargin > 1)
  86.     if(increment <= 0)  error("increment must be positive");
  87.     else
  88.       ngain = (maxk-mink)/increment;
  89.     endif
  90.   endif
  91.  
  92.   # vector of gains
  93.   ngain = max(3,ngain);
  94.   gvec = linspace(mink,maxk,ngain);
  95.   
  96.   # Find the open loop zeros and the initial poles
  97.   rlzer = roots(num);
  98.  
  99.   # update num to be the same length as den
  100.   lnum = length(num);  if(lnum < lden) num = [zeros(1,lden - lnum),num];  endif
  101.  
  102.   # compute preliminary pole sets
  103.   nroots = lden-1;
  104.   for ii=1:ngain
  105.    gain = gvec(ii);
  106.    rlpol(1:nroots,ii)  = vec(sortcom(roots(den + gain*num)));
  107.   endfor
  108.  
  109.   # compute axis limits (isolate asymptotes)
  110.   olpol = roots(den);
  111.   real_axdat = union(real(rlzer), real(union(olpol,real_ax_pts)) );
  112.   rmin = min(real_axdat);      rmax = max(real_axdat);
  113.  
  114.   rlpolv = [vec(rlpol); vec(real_axdat)];
  115.   idx = find(real(rlpolv) >= rmin & real(rlpolv) <= rmax);
  116.   axlim = ax2dlim([real(rlpolv(idx)),imag(rlpolv(idx))]);
  117.   xmin = axlim(1);
  118.   xmax = axlim(2);
  119.   
  120.   # set smoothing tolerance per axis limits
  121.   smtol = 0.01*max(abs(axlim));
  122.   
  123.   # smooth poles if necessary, up to maximum of 1000 gain points
  124.   # only smooth points within the axis limit window
  125.   # smoothing done if max_k not specified as a command argument
  126.   done=(nargin == 4);    # perform a smoothness check
  127.   while((!done) & ngain < 1000)
  128.     done = 1 ;      # assume done
  129.     dp = abs(diff(rlpol'))';
  130.     maxd = max(dp);
  131.     # search for poles in the real axis limits whose neighbors are distant
  132.     idx = find(maxd > smtol);
  133.     for ii=1:length(idx)
  134.       i1 = idx(ii);      g1 = gvec(i1);       p1 = rlpol(:,i1);
  135.       i2 = idx(ii)+1;    g2 = gvec(i2);       p2 = rlpol(:,i2);
  136.     
  137.       # isolate poles in p1, p2 that are inside the real axis limits
  138.       bidx = find( (real(p1) >= xmin & real(p1) <= xmax)  ...
  139.           | (real(p2) >= xmin & real(p2) <= xmax) );
  140.       if(!isempty(bidx))
  141.         p1 = p1(bidx);
  142.         p2 = p2(bidx);
  143.         if( max(abs(p2-p1)) > smtol) 
  144.           newg = linspace(g1,g2,5);
  145.           newg = newg(2:4);
  146.           if(isempty(newg))
  147.             printf("rlocus: empty newg")
  148.             g1
  149.             g2
  150.             i1
  151.             i2
  152.             idx_i1 = idx(ii)
  153.             gvec_i1 = gvec(i1:i2)
  154.             delta_vec_i1 = diff(gvec(i1:i2))
  155.             prompt
  156.           endif
  157.           gvec =  [gvec,newg];
  158.           done = 0;             # need to process new gains
  159.         endif
  160.       endif
  161.     endfor
  162.     
  163.     # process new gain values
  164.     ngain1 = length(gvec);
  165.     for ii=(ngain+1):ngain1
  166.       gain = gvec(ii);
  167.       rlpol(1:nroots,ii)  = vec(sortcom(roots(den + gain*num)));
  168.     endfor
  169.  
  170.     [gvec,idx] = sort(gvec);
  171.     rlpol = rlpol(:,idx);
  172.     ngain = length(gvec);
  173.   endwhile
  174.    
  175.   # Plot the data
  176.   if(nargout  == 0)
  177.     rlpolv = vec(rlpol);
  178.     idx = find(real(rlpolv) >= xmin & real(rlpolv) <= xmax);
  179.     axdata = [real(rlpolv(idx)),imag(rlpolv(idx))];
  180.     axlim = ax2dlim(axdata);
  181.     axlim(1:2) = [xmin, xmax];
  182.     gset nologscale xy;
  183.     grid("on");
  184.     rldata = [real(rlpolv), imag(rlpolv) ];
  185.     axis(axlim);
  186.     [stn,inname,outname] = sysgetsg(sys);
  187.     xlabel(sprintf("Root locus from %s to %s, gain=[%f,%f]: Real axis", ...
  188.     nth(inname,1),nth(outname,1),gvec(1),gvec(ngain)));
  189.     ylabel("Imag. axis");
  190.     
  191.     plot(real(rlpolv),imag(rlpolv),".1;locus points;", ...
  192.     real(olpol),imag(olpol),"x2;open loop poles;", ...
  193.     real(rlzer),imag(rlzer),"o3;zeros;");
  194.     rldata = [];
  195.   endif
  196. endfunction
  197.