| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Observers can be defined as software sensors. An Observer has Sensors and other Observers for inputs, maintains its state, and produces one or more estimated variables.
| 7.1 Observer Code Structure | ||
| 7.2 Observer Example |
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The Observer code is structured in four steps, two of which are initialization steps and two of which are run during each control loop. These steps are:
The Setup step is where the Observer is described: the needed inputs are declared, and the produced estimated variables, parameters, and state variables are defined.
In that step, you will:
The Init step is where initial values are set.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Note that other examples can be found in the ‘observers’ directory of your Odin install.
//===================================================================
//
// Copyright INRIA Sophia Antipolis 2008, all rights reserved
//
// Project : Odin
//
// Description: Biomass observer
//
// Author: Romain Primet <romain.primet@sophia.inria.fr>
//
//===================================================================
function hrs = secToDays(tSec)
hrs = tSec/(24.*60.*60.);
endfunction
/// Computes the system state's derivative ///
function ydot = obs(t,y)
,
qIn = Inputs("SensorB-qIn")("value");
sIn = Inputs("SensorB-sIn")("value");
vLiq = Parameters("vLiq")("value");
k1 = Parameters("k1")("value");
d = qIn/vLiq;
ydot = -d*y + (k1)*d*sIn;
,
endfunction
function y = doContinuousIntegration(Inputs, Parameters, StateVars),
StateVarValue = [StateVars("z")("value")];
y = ode(StateVarValue,tLast,tCurr/(24.*60.*60.),obs);
endfunction
function sv = doDiscreteIntegration(Inputs, Parameters, StateVars),
//fill in this function
sv = 0.
endfunction
//// Control loop entry points ////
select ObsJob,
case 'Setup' then
exec('./observers/factories.sci');
ObsName = 'obs';
ObsDescription = 'Asymptotic observer for biomass estimation';
continuousScheme = %t; //set to %f if integration step is to be discrete
//EDIT
InputsRequiredUid = ['SensorA-s'; 'SensorB-qIn'; 'SensorB-sIn'];
//DO NOT EDIT
Inputs = tlist([["Inputs"] ; InputsRequiredUid]);
//Note that parameters are constant
//EDIT
ParametersUid = ['vLiq'; 'muMax'; 'ksm'; 'lambda'; 'k1'; 'k6' ];
//DO NOT EDIT
Parameters = tlist([["Parameters"] ; ParametersUid]);
//State variables (or estimated variables)
//EDIT
StateVarsUid = ['z' ];
//DO NOT EDIT
StateVars = tlist([["StateVars"] ; StateVarsUid]);
//Estimated variables
//EDIT
EstimatedVarsUid = ['obs-xc'];
//DO NOT EDIT
EstimatedVars = tlist([["EstimatedVars"] ; EstimatedVarsUid]);
//EDIT
//Initialize individual inputs
IName = "SensorA-s";
Inputs(IName) = makeSensor();
Inputs(IName)("deviceUid") = 'SensorA-s';
Inputs(IName)("value") = 0.;
Inputs(IName)("timestamp") = 0.;
IName = "SensorB-qIn";
Inputs(IName) = makeSensor();
Inputs(IName)("deviceUid") = 'SensorB-qIn';
Inputs(IName)("value") = 0.;
Inputs(IName)("timestamp") = 0.;
IName = "SensorB-sIn";
Inputs(IName) = makeSensor();
Inputs(IName)("deviceUid") = 'SensorB-sIn';
Inputs(IName)("value") = 0.;
Inputs(IName)("timestamp") = 0.;
//Initialize individual parameters
PName = "vLiq";
Parameters(PName) = makeParameter();
Parameters(PName)("label") = 'vLiq';
Parameters(PName)("uid") = 'vLiq';
Parameters(PName)("description") = 'Bioreactor volume';
Parameters(PName)("value") = 900.;
Parameters(PName)("unit") = 'L';
PName = "k1";
Parameters(PName) = makeParameter();
Parameters(PName)("label") = 'k1';
Parameters(PName)("uid") = 'k1';
Parameters(PName)("description") = 'k1';
Parameters(PName)("value") = 1.;
Parameters(PName)("unit") = 'mmol/g';
SVName = "z";
StateVars(SVName) = makeStateVar();
StateVars(SVName)("label") = 'z';
StateVars(SVName)("uid") = 'z';
StateVars(SVName)("description") = 'z';
StateVars(SVName)("value") = 0.;
StateVars(SVName)("unit") = 'Day^{-1}';
//Attributes should exactly mirror input attributes.
EVName = "obs-xc";
EstimatedVars(EVName) = makeEstimatedVar();
EstimatedVars(EVName)("physicalDeviceLabel") = 'Biomass concentration observer';
EstimatedVars(EVName)("physicalDeviceUid") = 'obs';
EstimatedVars(EVName)("deviceUid") = 'obs-xc';
EstimatedVars(EVName)("dataLabel") = 'xc';
EstimatedVars(EVName)("dataDescription") = 'Biomass concentration (estimated)';
EstimatedVars(EVName)("unit") = 'g/L';
EstimatedVars(EVName)("domain") = [-1000; 1000];
EstimatedVars(EVName)("validityPeriod") = -1.;
EstimatedVars(EVName)("value") = 0.;
EstimatedVars(EVName)("timestamp") = 0.;
,
case 'Init' then
tLast = tCurr/(24*60*60);
//EDIT initial values
StateVars("z")("value") = 5.0;
,
//DO NOT EDIT this step, instead edit either doContinuousIntegration
//or doDiscreteIntegration
case 'Integration' then
if continuousScheme then,
y = doContinuousIntegration();
StateVars("z")("value") = y(1);
else,
doDiscreteIntegration();
end
,
//Computation of estimated variables
case 'EstimatedVarsComputation' then
z = StateVars("z")("value");
k1 = Parameters("k1")("value");
s = Inputs("SensorA-s")("value");
xc = max(0,(z - k1*s));
printf("z=%f, k1=%f, s=%f, xc=%f, sIn=%f, qIn=%f\n", z, k1, s, xc, Inputs("SensorB-sIn")("value"), Inputs("SensorB-qIn")("value"));
EstimatedVars("obs-xc")("value") = xc;
tLast = tCurr/(24*60*60);
,
//Otherwise
else
disp('Observer job flag unknown');
//make observer fail if the flag is unknown
//(better fail explicitly than silently)
pause;
end;
| [ << ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This document was generated by Fabien Dilet on July, 22 2010 using texi2html 1.78.