41 #include "models/FGFCS.h"
42 #include "input_output/FGXMLElement.h"
53 FGSensor::FGSensor(FGFCS* fcs, Element* element)
54 : FGFCSComponent(fcs, element), generator(fcs->GetExec()->GetRandomGenerator())
58 bits = quantized = divisions = 0;
59 PreviousInput = PreviousOutput = 0.0;
60 min = max = bias = gain = noise_variance = lag = drift_rate = drift = span = 0.0;
63 fail_low = fail_high = fail_stuck =
false;
65 Element* quantization_element = element->FindElement(
"quantization");
66 if ( quantization_element) {
67 if ( quantization_element->FindElement(
"bits") ) {
68 bits = (int)quantization_element->FindElementValueAsNumber(
"bits");
70 divisions = (1<<bits);
71 if ( quantization_element->FindElement(
"min") ) {
72 min = quantization_element->FindElementValueAsNumber(
"min");
74 if ( quantization_element->FindElement(
"max") ) {
75 max = quantization_element->FindElementValueAsNumber(
"max");
77 quant_property = quantization_element->GetAttributeValue(
"name");
79 granularity = span/divisions;
81 if ( element->FindElement(
"bias") ) {
82 bias = element->FindElementValueAsNumber(
"bias");
84 if ( element->FindElement(
"gain") ) {
85 gain = element->FindElementValueAsNumber(
"gain");
87 if ( element->FindElement(
"drift_rate") ) {
88 drift_rate = element->FindElementValueAsNumber(
"drift_rate");
90 if ( element->FindElement(
"lag") ) {
91 lag = element->FindElementValueAsNumber(
"lag");
92 double denom = 2.00 + dt*lag;
94 cb = (2.00 - dt*lag) / denom;
96 if ( element->FindElement(
"noise") ) {
97 noise_variance = element->FindElementValueAsNumber(
"noise");
98 string variation = element->FindElement(
"noise")->GetAttributeValue(
"variation");
99 if (variation ==
"PERCENT") {
100 NoiseType = ePercent;
101 }
else if (variation ==
"ABSOLUTE") {
102 NoiseType = eAbsolute;
104 NoiseType = ePercent;
105 cerr <<
"Unknown noise type in sensor: " << Name << endl;
106 cerr <<
" defaulting to PERCENT." << endl;
108 string distribution = element->FindElement(
"noise")->GetAttributeValue(
"distribution");
109 if (distribution ==
"UNIFORM") {
110 DistributionType = eUniform;
111 }
else if (distribution ==
"GAUSSIAN") {
112 DistributionType = eGaussian;
114 DistributionType = eUniform;
115 cerr <<
"Unknown random distribution type in sensor: " << Name << endl;
116 cerr <<
" defaulting to UNIFORM." << endl;
120 bind(element, fcs->GetPropertyManager().get());
127 FGSensor::~FGSensor()
134 void FGSensor::ResetPastStates(
void)
136 FGFCSComponent::ResetPastStates();
138 PreviousOutput = PreviousInput = Output = 0.0;
143 bool FGSensor::Run(
void)
145 Input = InputNodes[0]->getDoubleValue();
147 ProcessSensorSignal();
156 void FGSensor::ProcessSensorSignal(
void)
163 if (lag != 0.0) Lag();
164 if (noise_variance != 0.0) Noise();
165 if (drift_rate != 0.0) Drift();
166 if (gain != 0.0) Gain();
167 if (bias != 0.0) Bias();
169 if (delay != 0) Delay();
171 if (fail_low) Output = -HUGE_VAL;
172 if (fail_high) Output = HUGE_VAL;
174 if (bits != 0) Quantize();
182 void FGSensor::Noise(
void)
184 double random_value=0.0;
186 if (DistributionType == eUniform)
187 random_value = generator->GetUniformRandomNumber();
189 random_value = generator->GetNormalRandomNumber();
191 switch( NoiseType ) {
193 Output *= (1.0 + noise_variance*random_value);
197 Output += noise_variance*random_value;
204 void FGSensor::Bias(
void)
211 void FGSensor::Gain(
void)
218 void FGSensor::Drift(
void)
220 drift += drift_rate*dt;
226 void FGSensor::Quantize(
void)
228 if (Output < min) Output = min;
229 if (Output > max) Output = max;
230 double portion = Output - min;
231 quantized = (int)(portion/granularity);
232 Output = quantized*granularity + min;
237 void FGSensor::Lag(
void)
240 Output = ca * (Output + PreviousInput) + PreviousOutput * cb;
242 PreviousOutput = Output;
243 PreviousInput = Input;
248 void FGSensor::bind(Element* el, FGPropertyManager* PropertyManager)
252 FGFCSComponent::bind(el, PropertyManager);
254 if (Name.find(
"/") == string::npos) {
255 tmp =
"fcs/" + PropertyManager->mkPropertyName(Name,
true);
257 const string tmp_low = tmp +
"/malfunction/fail_low";
258 const string tmp_high = tmp +
"/malfunction/fail_high";
259 const string tmp_stuck = tmp +
"/malfunction/fail_stuck";
261 PropertyManager->Tie( tmp_low,
this, &FGSensor::GetFailLow, &FGSensor::SetFailLow);
262 PropertyManager->Tie( tmp_high,
this, &FGSensor::GetFailHigh, &FGSensor::SetFailHigh);
263 PropertyManager->Tie( tmp_stuck,
this, &FGSensor::GetFailStuck, &FGSensor::SetFailStuck);
265 if (!quant_property.empty()) {
266 if (quant_property.find(
"/") == string::npos) {
267 string qprop =
"fcs/" + PropertyManager->mkPropertyName(quant_property,
true);
268 FGPropertyNode* node = PropertyManager->GetNode(qprop,
true);
269 if (node->isTied()) {
270 cerr << el->ReadFrom()
271 <<
"Property " << tmp <<
" has already been successfully bound (late)." << endl;
272 throw(
"Failed to bind the property to an existing already tied node.");
275 PropertyManager->Tie(qprop,
this, &FGSensor::GetQuantized);
300 void FGSensor::Debug(
int from)
302 if (debug_lvl <= 0)
return;
306 if (!InputNodes.empty())
307 cout <<
" INPUT: " << InputNodes[0]->GetNameWithSign() << endl;
309 if (quant_property.empty())
310 cout <<
" Quantized output" << endl;
312 cout <<
" Quantized output (property: " << quant_property <<
")" << endl;
314 cout <<
" Bits: " << bits << endl;
315 cout <<
" Min value: " << min << endl;
316 cout <<
" Max value: " << max << endl;
317 cout <<
" (span: " << span <<
", granularity: " << granularity <<
")" << endl;
319 if (bias != 0.0) cout <<
" Bias: " << bias << endl;
320 if (gain != 0.0) cout <<
" Gain: " << gain << endl;
321 if (drift_rate != 0) cout <<
" Sensor drift rate: " << drift_rate << endl;
322 if (lag != 0) cout <<
" Sensor lag: " << lag << endl;
323 if (noise_variance != 0) {
324 if (NoiseType == eAbsolute) {
325 cout <<
" Noise variance (absolute): " << noise_variance << endl;
326 }
else if (NoiseType == ePercent) {
327 cout <<
" Noise variance (percent): " << noise_variance << endl;
329 cout <<
" Noise variance type is invalid" << endl;
331 if (DistributionType == eUniform) {
332 cout <<
" Random noise is uniformly distributed." << endl;
333 }
else if (DistributionType == eGaussian) {
334 cout <<
" Random noise is gaussian distributed." << endl;
337 for (
auto node: OutputNodes)
338 cout <<
" OUTPUT: " << node->getNameString() << endl;
341 if (debug_lvl & 2 ) {
342 if (from == 0) cout <<
"Instantiated: FGSensor" << endl;
343 if (from == 1) cout <<
"Destroyed: FGSensor" << endl;
345 if (debug_lvl & 4 ) {
347 if (debug_lvl & 8 ) {
349 if (debug_lvl & 16) {
351 if (debug_lvl & 64) {