📄 fbode.m
字号:
function [magout,phase,w] = fbode(a,b,c,d,iu,w)
%FBODE Bode frequency response for continuous-time linear systems.
% FBODE(A,B,C,D,IU) produces a Bode plot from the single input IU to
% all the outputs of the continuous state-space system (A,B,C,D).
% IU is an index into the inputs of the system and specifies which
% input to use for the Bode response. The frequency range and
% number of points are chosen automatically. FBODE is a faster, but
% less accurate, version of BODE.
%
% FBODE(NUM,DEN) produces the Bode plot for the polynomial transfer
% function G(s) = NUM(s)/DEN(s) where NUM and DEN contain the
% polynomial coefficients in descending powers of s.
%
% FBODE(A,B,C,D,IU,W) or FBODE(NUM,DEN,W) uses the user-supplied
% frequency vector W which must contain the frequencies, in
% radians/sec, at which the Bode response is to be evaluated. See
% LOGSPACE to generate log. spaced frequency vectors. When invoked
% with left hand arguments,
% [MAG,PHASE,W] = FBODE(A,B,C,D,...)
% [MAG,PHASE,W] = FBODE(NUM,DEN,...)
% returns the frequency vector W and matrices MAG and PHASE (in
% degrees) with as many columns as outputs and length(W) rows. No
% plot is drawn on the screen.
% See also: LOGSPACE,SEMILOGX,MARGIN and BODE.
% J.N. Little 12-5-88
% Revised CMT 8-2-90, ACWG 6-21-92
% Copyright (c) 1986-93 by the MathWorks, Inc.
nargs = nargin;
if nargs==0, eval('exresp(''fbode'')'), return, end
error(nargchk(2,6,nargs));
% --- Determine which syntax is being used ---
if (nargs==1),
error('Wrong number of input arguments.');
elseif (nargs==2), % Transfer function form without frequency vector
num = a; den = b;
w = freqint(num,den,20);
[ny,nn] = size(num); nu = 1;
elseif (nargs==3), % Transfer function form with frequency vector
num = a; den = b;
w = c;
[ny,nn] = size(num); nu = 1;
elseif (nargs==4), % State space system, w/o iu or frequency vector
error(abcdchk(a,b,c,d));
w = freqint(a,b,c,d,30);
[iu,nargs,mag,phase]=mulresp('bode',a,b,c,d,w,nargout,1);
if ~iu, if nargout, magout = mag; end, return, end
[ny,nu] = size(d);
elseif (nargs==5), % State space system, with iu but w/o freq. vector
error(abcdchk(a,b,c,d));
w = freqint(a,b,c,d,30);
[ny,nu] = size(d);
else % State space system, with iu and freq. vector
error(abcdchk(a,b,c,d));
[ny,nu] = size(d);
end
if nu*ny==0, phase=[]; w=[]; if nargout~=0, magout=[]; end, return, end
% --- Evaluate the frequency response ---
if (nargs == 2)|(nargs == 3)
% It is in transfer function form. Do directly, using Horner's method
% of polynomial evaluation at the frequency points, for each row in
% the numerator. Then divide by the denominator.
[ma,na] = size(num);
s = sqrt(-1)*w(:);
for i=1:ma
g(:,i) = polyval(num(i,:),s);
end
g = polyval(den,s)*ones(1,ma).\g;
else
[no,nu] = size(d);
[ns,na] = size(a);
nw = max(size(w));
[p,a] = eig(a); % Reduce A to diagonal form
if rcond(p)<sqrt(eps),
disp('Warning: Diagonalization matrix singular. Use BODE instead.')
end
% Apply similarity transformations to B and C
if ns>0,
b = p \ b(:,iu);
c = c * p;
d = d(:,iu);
s = (w*sqrt(-1)).';
s = s(ones(ns,1),:);
a2 = diag(a)*ones(1,nw);
b = b*ones(1,nw);
g = (c*((1 ./(s-a2)).*b) + diag(d)*ones(no,nw)).';
else
d = d(:,iu);
g = (diag(d)*ones(no,nw)).';
end
end
mag = abs(g);
phase = (180./pi)*unwrap(atan2(imag(g),real(g)));
% Uncomment out the following statement if you don't want the phase to
% be unwrapped. Note that phase unwrapping will not always work; it is
% only a "guess" as to whether +-360 should be added to the phase
% to make it more aesthetically pleasing. (See UNWRAP.M)
%phase = (180./pi)*atan2(imag(g),real(g));
%Try to correct phase anomaly for plants with integrators
%by adding multiples of -360 degrees.
if (nargs == 2 | nargs == 3)
nd = length(den);
f = find(fliplr(den) == zeros(1,nd));
nintgs = sum(f == 1:length(f));
if phase(1) > 0 & nintgs > 0
phase = phase - 360;
end
else
if abs(det(a)) < eps
if phase(1) > 0 & nintgs > 0
phase = phase - 360;
end
end
end
% If no left hand arguments then plot graph.
if nargout==0
holdon = ishold;
subplot(211)
if holdon
hold on
end
semilogx(w,20*log10(mag),w,zeros(1,length(w)),'w:')
% If hold is set to on on the current axis then set it on the first axis too.
% This enables two bode response to be superimposed on each other with
% the following commands:
% bode(num, den); hold on; bode(num2, den2)
grid
xlabel('Frequency (rad/sec)'), ylabel('Gain dB')
subplot(212),
semilogx(w,phase)
xlabel('Frequency (rad/sec)'), ylabel('Phase deg')
% Set tick marks up to be in multiples of 30, 90, 180, 360 ... degrees.
ytick = get(gca, 'ytick');
ylim = get(gca, 'ylim');
yrange = ylim(2) - ylim(1);
n = round(log(yrange/(length(ytick)*90))/log(2));
set(gca, 'ylimmode', 'manual')
if n >=0
ytick = [-90*2^n:-(90*2^n):ylim(1), 0:(90*2^n):ylim(2)];
set(gca,'ytick',ytick);
elseif n >= -2
ytick = [-30:-30:ylim(1), 0:30:ylim(2)];
set(gca,'ytick',ytick);
end
grid
% Reset the graph: subplot(111)
subplot(111)
return % Suppress output
end
% Uncomment the following line for decibels, but be warned that the
% MARGIN function will not work with decibel data.
% mag = 20*log10(mag);
magout = mag;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -