Difference between revisions of "Using tfest to find a system model"

From Course Wiki
Jump to: navigation, search
 
(8 intermediate revisions by 2 users not shown)
Line 1: Line 1:
 
[[Category:Electronics]]
 
[[Category:Electronics]]
 
{{Template:20.309}}
 
{{Template:20.309}}
 +
The function <tt> FitTransferFunction</tt> below uses <tt>tfest</tt> to fit a linear model to frequency response data.
  
Here is some example code that demonstrates how to use <tt>tfest</tt> to fit a linear model to frequency response data.
+
The arguments NumeratorForm and DenominatorForm are vectors of ones and zeros. The model is a transfer function whose numerator and denominator are polynomials in <math>s</math>. (Recall that <math>s=j\omega</math>.)
 +
Each element of the vectors corresponds to a single term of the numerator or denominator, in order of decreasing powers of <math>s</math>.  
  
The arguments numeratorForm and denominatorForm are vectors of ones and zeros. Each element corresponds to one term of the numerator or denominator of the transfer function, in order of decreasing powers of <math>s</math>. For example, if you want the function to fit a transfer function of the form <math>\frac{K_1 s}{K_2 s + K_3}</math> (a high-pass filter), you would use <tt>numeratorForm = [ 1 0 ]</tt> and<tt> denominatorForm  = [ 1 1 ]</tt>. Using these parameters, prevent <tt>tfest</tt> will fit a first-order polynomial for the numerator and denominator with no constant term in the numerator. If you wanted to fit a transfer function of the form <math>\frac{K_1 s^2}{K_2 s^3 + K_3 s^2 + K_4 s + K_5}</math>, you would use <tt>numeratorForm = [ 1 0 0 ]</tt> and<tt> denominatorForm  = [ 1 1 1 1]</tt>
+
For example, if you want the function to fit a transfer function of the form <math>\frac{K_1 s}{K_2 s + K_3}</math> (a high-pass filter), you would use <tt>numeratorForm = [ 1 0 ]</tt> and<tt> denominatorForm  = [ 1 1 ]</tt>. These parameters, <tt>tfest</tt> will fit a first-order polynomial for the numerator and denominator with no constant term in the numerator.  
 
+
% specify the form of the model to fit. they are in decreasing powers
+
 
+
decreasing powers of s -- numerator for HPF has no constant term, so set it to zero (otherwise tfest will fit a constant value)
+
  
 +
If you wanted to fit a transfer function of the form <math>\frac{K_1 s^2}{K_2 s^3 + K_3 s^2 + K_4 s + K_5}</math>, you would use <tt>numeratorForm = [ 1 0 0 ]</tt> and<tt> denominatorForm  = [ 1 1 1 1]</tt>
  
 
<pre>
 
<pre>
%Generate some synthetic frequency response measurement data
+
function EstimatedTransferFunction = FitTransferFunction( ...
s = tf( [ 1 0 ], 1 );
+
          MagnitudeRatio, PhaseDifferenceDegrees, FrequencyHertz, NumeratorForm, DenominatorForm )
highPass = s / ( s + 1 )
+
 
+
[ magnitude, phase, frequency ] = bode( highPass );
+
 
+
% add some random noise
+
noiseStandardDeviation = 0.05;
+
magnitude = magnitude + noiseStandardDeviation * randn( size( magnitude ) );
+
phase = phase + noiseStandardDeviation * randn( size( phase ) );
+
 
+
numeratorForm = [ 1 0 ]; % decreasing powers of s -- numerator for HPF has no constant term, so set it to zero (otherwise tfest will fit a constant value)
+
denominatorForm = [ 1 0 ]; % decreasing powers of s -- numerator for HPF has no constant term, so set it to zero (otherwise tfest will fit a constant value)
+
 
+
estimatedTransferFunction = FitTransferFunction( magnitude, phase, frequency, numeratorForm, denominatorForm )
+
 
+
function EstimatedTransferFunction = FitTransferFunction( MagnitudeRatio, PhaseDifferenceDegrees, FrequencyHertz, NumeratorForm, DenominatorForm )
+
 
     % convert magnitude and phase to single complex vector
 
     % convert magnitude and phase to single complex vector
 
     complexResponseData = MagnitudeRatio .* exp( 1i .* PhaseDifferenceDegrees .* pi ./ 180 );
 
     complexResponseData = MagnitudeRatio .* exp( 1i .* PhaseDifferenceDegrees .* pi ./ 180 );
Line 36: Line 20:
 
     initalModel = idtf( NumeratorForm, DenominatorForm );
 
     initalModel = idtf( NumeratorForm, DenominatorForm );
 
     zeroCoefficients = find( NumeratorForm == 0 );
 
     zeroCoefficients = find( NumeratorForm == 0 );
     for ii = 1:numel( zeroCoefficients )
+
     for ii = zeroCoefficients
 
         initalModel.Structure.Numerator.Free(ii) = false;
 
         initalModel.Structure.Numerator.Free(ii) = false;
 
     end
 
     end
 
     zeroCoefficients = find( DenominatorForm == 0 );
 
     zeroCoefficients = find( DenominatorForm == 0 );
     for ii = 1:numel( zeroCoefficients )
+
     for ii = zeroCoefficients
 
         initalModel.Structure.Denominator.Free(ii) = false;
 
         initalModel.Structure.Denominator.Free(ii) = false;
 
     end
 
     end
Line 47: Line 31:
 
     EstimatedTransferFunction = tfest( frequencyResponseData, initalModel );
 
     EstimatedTransferFunction = tfest( frequencyResponseData, initalModel );
 
end
 
end
 +
</pre>
 +
 +
Here is some sample code you can use to test and understand <tt> FitTransferFunction</tt>.
 +
 +
<pre>
 +
%Generate some synthetic frequency response measurement data
 +
s = tf( [ 1 0 ], 1 );
 +
highPass = s / ( s + 1 )
 +
 +
[ magnitude, phase, omega ] = bode( highPass );
 +
frequency = omega / ( 2 * pi );
 +
 +
% add some random noise
 +
noiseStandardDeviation = 0.05;
 +
magnitude = magnitude + noiseStandardDeviation * randn( size( magnitude ) );
 +
phase = phase + noiseStandardDeviation * randn( size( phase ) );
 +
 +
numeratorForm = [ 1 0 ]; % decreasing powers of s -- first order with no constant term
 +
denominatorForm = [ 1 1 ]; % decreasing powers of s -- first order with constant term
 +
 +
estimatedTransferFunction = FitTransferFunction( ...
 +
          magnitude, phase, frequency, numeratorForm, denominatorForm )
 
</pre>
 
</pre>
  
  
{{Template:20.309}}
+
{{Template:20.309 bottom}}

Latest revision as of 22:03, 9 April 2019

20.309: Biological Instrumentation and Measurement

ImageBar 774.jpg

The function FitTransferFunction below uses tfest to fit a linear model to frequency response data.

The arguments NumeratorForm and DenominatorForm are vectors of ones and zeros. The model is a transfer function whose numerator and denominator are polynomials in $ s $. (Recall that $ s=j\omega $.) Each element of the vectors corresponds to a single term of the numerator or denominator, in order of decreasing powers of $ s $.

For example, if you want the function to fit a transfer function of the form $ \frac{K_1 s}{K_2 s + K_3} $ (a high-pass filter), you would use numeratorForm = [ 1 0 ] and denominatorForm = [ 1 1 ]. These parameters, tfest will fit a first-order polynomial for the numerator and denominator with no constant term in the numerator.

If you wanted to fit a transfer function of the form $ \frac{K_1 s^2}{K_2 s^3 + K_3 s^2 + K_4 s + K_5} $, you would use numeratorForm = [ 1 0 0 ] and denominatorForm = [ 1 1 1 1]

function EstimatedTransferFunction = FitTransferFunction( ...
          MagnitudeRatio, PhaseDifferenceDegrees, FrequencyHertz, NumeratorForm, DenominatorForm )
    % convert magnitude and phase to single complex vector
    complexResponseData = MagnitudeRatio .* exp( 1i .* PhaseDifferenceDegrees .* pi ./ 180 );

    % create optional initial model for tfest so that known zero
    % coefficients can be constrained
    initalModel = idtf( NumeratorForm, DenominatorForm );
    zeroCoefficients = find( NumeratorForm == 0 );
    for ii = zeroCoefficients
        initalModel.Structure.Numerator.Free(ii) = false;
    end
    zeroCoefficients = find( DenominatorForm == 0 );
    for ii = zeroCoefficients
        initalModel.Structure.Denominator.Free(ii) = false;
    end

    frequencyResponseData = frd( complexResponseData, FrequencyHertz, 'FrequencyUnit', 'Hz');
    EstimatedTransferFunction = tfest( frequencyResponseData, initalModel );
end

Here is some sample code you can use to test and understand FitTransferFunction.

%Generate some synthetic frequency response measurement data
s = tf( [ 1 0 ], 1 );
highPass = s / ( s + 1 )

[ magnitude, phase, omega ] = bode( highPass );
frequency = omega / ( 2 * pi );

% add some random noise
noiseStandardDeviation = 0.05;
magnitude = magnitude + noiseStandardDeviation * randn( size( magnitude ) );
phase = phase + noiseStandardDeviation * randn( size( phase ) );

numeratorForm = [ 1 0 ]; % decreasing powers of s -- first order with no constant term
denominatorForm = [ 1 1 ]; % decreasing powers of s -- first order with constant term

estimatedTransferFunction = FitTransferFunction( ...
          magnitude, phase, frequency, numeratorForm, denominatorForm )