41 #include "input_output/FGXMLElement.h"
52 FGSensor::FGSensor(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element)
56 bits = quantized = divisions = 0;
57 PreviousInput = PreviousOutput = 0.0;
58 min = max = bias = gain = noise_variance = lag = drift_rate = drift = span = 0.0;
61 fail_low = fail_high = fail_stuck =
false;
63 Element* quantization_element = element->FindElement(
"quantization");
64 if ( quantization_element) {
65 if ( quantization_element->FindElement(
"bits") ) {
66 bits = (int)quantization_element->FindElementValueAsNumber(
"bits");
68 divisions = (1<<bits);
69 if ( quantization_element->FindElement(
"min") ) {
70 min = quantization_element->FindElementValueAsNumber(
"min");
72 if ( quantization_element->FindElement(
"max") ) {
73 max = quantization_element->FindElementValueAsNumber(
"max");
75 quant_property = quantization_element->GetAttributeValue(
"name");
77 granularity = span/divisions;
79 if ( element->FindElement(
"bias") ) {
80 bias = element->FindElementValueAsNumber(
"bias");
82 if ( element->FindElement(
"gain") ) {
83 gain = element->FindElementValueAsNumber(
"gain");
85 if ( element->FindElement(
"drift_rate") ) {
86 drift_rate = element->FindElementValueAsNumber(
"drift_rate");
88 if ( element->FindElement(
"lag") ) {
89 lag = element->FindElementValueAsNumber(
"lag");
90 double denom = 2.00 + dt*lag;
92 cb = (2.00 - dt*lag) / denom;
94 if ( element->FindElement(
"noise") ) {
95 noise_variance = element->FindElementValueAsNumber(
"noise");
96 string variation = element->FindElement(
"noise")->GetAttributeValue(
"variation");
97 if (variation ==
"PERCENT") {
99 }
else if (variation ==
"ABSOLUTE") {
100 NoiseType = eAbsolute;
102 NoiseType = ePercent;
103 cerr <<
"Unknown noise type in sensor: " << Name << endl;
104 cerr <<
" defaulting to PERCENT." << endl;
106 string distribution = element->FindElement(
"noise")->GetAttributeValue(
"distribution");
107 if (distribution ==
"UNIFORM") {
108 DistributionType = eUniform;
109 }
else if (distribution ==
"GAUSSIAN") {
110 DistributionType = eGaussian;
112 DistributionType = eUniform;
113 cerr <<
"Unknown random distribution type in sensor: " << Name << endl;
114 cerr <<
" defaulting to UNIFORM." << endl;
125 FGSensor::~FGSensor()
132 void FGSensor::ResetPastStates(
void)
134 FGFCSComponent::ResetPastStates();
141 bool FGSensor::Run(
void)
143 Input = InputNodes[0]->getDoubleValue();
145 ProcessSensorSignal();
154 void FGSensor::ProcessSensorSignal(
void)
161 if (lag != 0.0) Lag();
162 if (noise_variance != 0.0) Noise();
163 if (drift_rate != 0.0) Drift();
164 if (gain != 0.0) Gain();
165 if (bias != 0.0) Bias();
167 if (delay != 0) Delay();
169 if (fail_low) Output = -HUGE_VAL;
170 if (fail_high) Output = HUGE_VAL;
172 if (bits != 0) Quantize();
180 void FGSensor::Noise(
void)
182 double random_value=0.0;
184 if (DistributionType == eUniform) {
185 random_value = 2.0*(((double)rand()/(double)RAND_MAX) - 0.5);
187 random_value = GaussianRandomNumber();
190 switch( NoiseType ) {
192 Output *= (1.0 + noise_variance*random_value);
196 Output += noise_variance*random_value;
203 void FGSensor::Bias(
void)
210 void FGSensor::Gain(
void)
217 void FGSensor::Drift(
void)
219 drift += drift_rate*dt;
225 void FGSensor::Quantize(
void)
227 if (Output < min) Output = min;
228 if (Output > max) Output = max;
229 double portion = Output - min;
230 quantized = (int)(portion/granularity);
231 Output = quantized*granularity + min;
236 void FGSensor::Lag(
void)
242 PreviousInput = Input;
247 void FGSensor::bind(Element* el)
251 FGFCSComponent::bind(el);
253 if (Name.find(
"/") == string::npos) {
256 const string tmp_low = tmp +
"/malfunction/fail_low";
257 const string tmp_high = tmp +
"/malfunction/fail_high";
258 const string tmp_stuck = tmp +
"/malfunction/fail_stuck";
260 PropertyManager->
Tie( tmp_low,
this, &FGSensor::GetFailLow, &FGSensor::SetFailLow);
261 PropertyManager->
Tie( tmp_high,
this, &FGSensor::GetFailHigh, &FGSensor::SetFailHigh);
262 PropertyManager->
Tie( tmp_stuck,
this, &FGSensor::GetFailStuck, &FGSensor::SetFailStuck);
264 if (!quant_property.empty()) {
265 if (quant_property.find(
"/") == string::npos) {
266 string qprop =
"fcs/" + PropertyManager->
mkPropertyName(quant_property,
true);
267 FGPropertyNode* node = PropertyManager->GetNode(qprop,
true);
268 if (node->isTied()) {
269 cerr << el->ReadFrom()
270 <<
"Property " << tmp <<
" has already been successfully bound (late)." << endl;
271 throw(
"Failed to bind the property to an existing already tied node.");
274 PropertyManager->
Tie(qprop,
this, &FGSensor::GetQuantized);
299 void FGSensor::Debug(
int from)
301 if (debug_lvl <= 0)
return;
305 if (!InputNodes.empty())
306 cout <<
" INPUT: " << InputNodes[0]->GetNameWithSign() << endl;
308 if (quant_property.empty())
309 cout <<
" Quantized output" << endl;
311 cout <<
" Quantized output (property: " << quant_property <<
")" << endl;
313 cout <<
" Bits: " << bits << endl;
314 cout <<
" Min value: " << min << endl;
315 cout <<
" Max value: " << max << endl;
316 cout <<
" (span: " << span <<
", granularity: " << granularity <<
")" << endl;
318 if (bias != 0.0) cout <<
" Bias: " << bias << endl;
319 if (gain != 0.0) cout <<
" Gain: " << gain << endl;
320 if (drift_rate != 0) cout <<
" Sensor drift rate: " << drift_rate << endl;
321 if (lag != 0) cout <<
" Sensor lag: " << lag << endl;
322 if (noise_variance != 0) {
323 if (NoiseType == eAbsolute) {
324 cout <<
" Noise variance (absolute): " << noise_variance << endl;
325 }
else if (NoiseType == ePercent) {
326 cout <<
" Noise variance (percent): " << noise_variance << endl;
328 cout <<
" Noise variance type is invalid" << endl;
330 if (DistributionType == eUniform) {
331 cout <<
" Random noise is uniformly distributed." << endl;
332 }
else if (DistributionType == eGaussian) {
333 cout <<
" Random noise is gaussian distributed." << endl;
336 for (
auto node: OutputNodes)
337 cout <<
" OUTPUT: " << node->getNameString() << endl;
340 if (debug_lvl & 2 ) {
341 if (from == 0) cout <<
"Instantiated: FGSensor" << endl;
342 if (from == 1) cout <<
"Destroyed: FGSensor" << endl;
344 if (debug_lvl & 4 ) {
346 if (debug_lvl & 8 ) {
348 if (debug_lvl & 16) {
350 if (debug_lvl & 64) {