home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 10 / 10.iso / l / l455 / 10.ddi / CONTROL.DI$ / BODE.M < prev    next >
Encoding:
Text File  |  1993-03-11  |  4.8 KB  |  153 lines

  1. function [magout,phase,w] = bode(a,b,c,d,iu,w)
  2. %BODE   Bode frequency response for continuous-time linear systems.
  3. %    BODE(A,B,C,D,IU) produces a Bode plot from the single input IU to
  4. %    all the outputs of the continuous state-space system (A,B,C,D).
  5. %    IU is an index into the inputs of the system and specifies which
  6. %    input to use for the Bode response.  The frequency range and
  7. %    number of points are chosen automatically.
  8. %
  9. %    BODE(NUM,DEN) produces the Bode plot for the polynomial transfer
  10. %    function G(s) = NUM(s)/DEN(s) where NUM and DEN contain the 
  11. %    polynomial coefficients in descending powers of s. 
  12. %
  13. %    BODE(A,B,C,D,IU,W) or BODE(NUM,DEN,W) uses the user-supplied 
  14. %    frequency vector W which must contain the frequencies, in 
  15. %    radians/sec, at which the Bode response is to be evaluated.  See 
  16. %    LOGSPACE to generate logarithmically spaced frequency vectors. 
  17. %    When invoked with left hand arguments,
  18. %        [MAG,PHASE,W] = BODE(A,B,C,D,...)
  19. %        [MAG,PHASE,W] = BODE(NUM,DEN,...) 
  20. %    returns the frequency vector W and matrices MAG and PHASE (in 
  21. %    degrees) with as many columns as outputs and length(W) rows.  No
  22. %    plot is drawn on the screen. 
  23. %
  24. %    See also FBODE, LOGSPACE, SEMILOGX, MARGIN, NICHOLS, and NYQUIST.
  25.  
  26. %     J.N. Little 10-11-85
  27. %    Revised A.C.W.Grace 8-15-89, 2-4-91, 6-21-92
  28. %    Revised Clay M. Thompson 7-9-90
  29. %    Copyright (c) 1986-93 by the MathWorks, Inc.
  30.  
  31. nargs = nargin;
  32. if nargs==0, eval('exresp(''bode'')'), return, end
  33.  
  34. error(nargchk(2,6,nargs));
  35.  
  36. % --- Determine which syntax is being used ---
  37. if (nargs==1),
  38.     error('Wrong number of input arguments.');
  39.  
  40. elseif (nargs==2),    % Transfer function form without frequency vector
  41.     num = a; den = b; 
  42.     w = freqint(num,den,20);
  43.     [ny,nn] = size(num); nu = 1;
  44.  
  45. elseif (nargs==3),    % Transfer function form with frequency vector
  46.     num = a; den = b;
  47.     w = c;
  48.     [ny,nn] = size(num); nu = 1;
  49.  
  50. elseif (nargs==4),    % State space system, w/o iu or frequency vector
  51.     error(abcdchk(a,b,c,d));
  52.     w = freqint(a,b,c,d,30);
  53.     [iu,nargs,mag,phase]=mulresp('bode',a,b,c,d,w,nargout,1);
  54.     if ~iu, if nargout, magout = mag; end, return, end
  55.     [ny,nu] = size(d);
  56.  
  57. elseif (nargs==5),    % State space system, with iu but w/o freq. vector
  58.     error(abcdchk(a,b,c,d));
  59.     w = freqint(a,b,c,d,30);
  60.     [ny,nu] = size(d);
  61.  
  62. else
  63.     error(abcdchk(a,b,c,d));
  64.     [ny,nu] = size(d);
  65.  
  66. end
  67.  
  68. if nu*ny==0, phase=[]; w=[]; if nargout~=0, magout=[]; end, return, end
  69.  
  70. % --- Evaluate the frequency response ---
  71. if (nargs==2)|(nargs==3),
  72.     g = freqresp(num,den,sqrt(-1)*w);
  73. else
  74.     g = freqresp(a,b,c,d,iu,sqrt(-1)*w);
  75. end
  76. mag = abs(g);
  77. phase = (180./pi)*unwrap(atan2(imag(g),real(g)));
  78.  
  79. % Uncomment out the following statement if you don't want the phase to  
  80. % be unwrapped.  Note that phase unwrapping will not always work; it is
  81. % only a "guess" as to whether +-360 should be added to the phase 
  82. % to make it more aesthetically pleasing.  (See UNWRAP.M)
  83.  
  84. %phase = (180./pi)*atan2(imag(g),real(g));
  85.  
  86. %Try to correct phase anomaly for plants with integrators
  87. %by adding multiples of -360 degrees.
  88. if (nargs == 2 | nargs == 3) 
  89.     nd = length(den);
  90.     f = find(fliplr(den) == zeros(1,nd));
  91.     nintgs = sum(f == 1:length(f));    
  92.     if phase(1) > 0 & nintgs > 0
  93.         phase = phase - 360;
  94.     end
  95. else 
  96.     if abs(det(a)) < eps
  97.         if phase(1) > 0 & nintgs > 0
  98.             phase = phase - 360;
  99.         end
  100.     end
  101. end
  102.  
  103. % If no left hand arguments then plot graph.
  104. if nargout==0
  105.     holdon = ishold;
  106.     subplot(211) 
  107.     if holdon
  108.         hold on
  109.     end
  110.     semilogx(w,20*log10(mag),w,zeros(1,length(w)),'w:')
  111.     % If hold is set to on on the current axis then set it on the first axis too.
  112.     % This enables two bode response to be superimposed on each other with
  113.     % the following commands:
  114.     %    bode(num, den); hold on; bode(num2, den2)
  115.     grid on
  116.     xlabel('Frequency (rad/sec)'), ylabel('Gain dB')
  117.  
  118.     subplot(212), 
  119.     semilogx(w,phase)
  120.     xlabel('Frequency (rad/sec)'), ylabel('Phase deg')
  121.  
  122.     % Set tick marks up to be in multiples of 30, 90, 180, 360 ... degrees.
  123.     ytick = get(gca, 'ytick');
  124.     ylim = get(gca, 'ylim');
  125.     yrange = ylim(2) - ylim(1);
  126.     no_of_pts = log(yrange/(length(ytick)*90))/log(2);
  127.     n = round(log(yrange/(length(ytick)*90))/log(2));
  128.  
  129.     set(gca, 'ylimmode', 'manual')
  130.  
  131.     if no_of_pts >= -1.15
  132.         % 45, 90, 180, 360, ...  degree increments  
  133.         ytick = [-90*2^n:-(90*2^n):ylim(1), 0:(90*2^n):ylim(2)];
  134.         ytick = ytick(find(ytick >= ylim(1) & ytick <= ylim(2)));
  135.         set(gca,'ytick',ytick);
  136.     elseif n >= -2 
  137.         % Special case for 30 degree increments rather than 22.5
  138.         ytick = [-30:-30:ylim(1), 0:30:ylim(2)];
  139.         ytick = ytick(find(ytick >= ylim(1) & ytick <= ylim(2)));
  140.         set(gca,'ytick',ytick);
  141.     end
  142.     grid on
  143.     % Reset the graph: subplot(111)
  144.     subplot(111)
  145.     return % Suppress output 
  146. end
  147.  
  148. % Uncomment the following line for decibels, but be warned that the
  149. % MARGIN function will not work with decibel data.
  150. % mag = 20*log10(mag);
  151.  
  152. magout = mag; 
  153.