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

From Course Wiki
Jump to: navigation, search
 
(9 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>.
  
<pre>
+
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.
%Generate some synthetic frequency response measurement data
+
s = tf( [ 1 0 ], 1 );
+
highPass = s / ( s + 1 )
+
  
[ magnitude, phase, frequency ] = bode( highPass );
+
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>
  
% add some random noise
+
<pre>
noiseStandardDeviation = 0.05;
+
function EstimatedTransferFunction = FitTransferFunction( ...
magnitude = magnitude + noiseStandardDeviation * randn( size( magnitude ) );
+
          MagnitudeRatio, PhaseDifferenceDegrees, FrequencyHertz, NumeratorForm, DenominatorForm )
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 29: 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 40: 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 )