44 #include "input_output/FGXMLElement.h" 50 IDENT(IdSrc,
"$Id: FGSensor.cpp,v 1.28 2015/07/12 19:34:08 bcoconni Exp $");
51 IDENT(IdHdr,ID_SENSOR);
58 FGSensor::FGSensor(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element)
62 bits = quantized = divisions = 0;
63 PreviousInput = PreviousOutput = 0.0;
64 min = max = bias = gain = noise_variance = lag = drift_rate = drift = span = 0.0;
67 fail_low = fail_high = fail_stuck =
false;
69 Element* quantization_element = element->FindElement(
"quantization");
70 if ( quantization_element) {
71 if ( quantization_element->FindElement(
"bits") ) {
72 bits = (int)quantization_element->FindElementValueAsNumber(
"bits");
74 divisions = (1<<bits);
75 if ( quantization_element->FindElement(
"min") ) {
76 min = quantization_element->FindElementValueAsNumber(
"min");
78 if ( quantization_element->FindElement(
"max") ) {
79 max = quantization_element->FindElementValueAsNumber(
"max");
81 quant_property = quantization_element->GetAttributeValue(
"name");
83 granularity = span/divisions;
85 if ( element->FindElement(
"bias") ) {
86 bias = element->FindElementValueAsNumber(
"bias");
88 if ( element->FindElement(
"gain") ) {
89 gain = element->FindElementValueAsNumber(
"gain");
91 if ( element->FindElement(
"drift_rate") ) {
92 drift_rate = element->FindElementValueAsNumber(
"drift_rate");
94 if ( element->FindElement(
"lag") ) {
95 lag = element->FindElementValueAsNumber(
"lag");
96 double denom = 2.00 + dt*lag;
98 cb = (2.00 - dt*lag) / denom;
100 if ( element->FindElement(
"noise") ) {
101 noise_variance = element->FindElementValueAsNumber(
"noise");
102 string variation = element->FindElement(
"noise")->GetAttributeValue(
"variation");
103 if (variation ==
"PERCENT") {
104 NoiseType = ePercent;
105 }
else if (variation ==
"ABSOLUTE") {
106 NoiseType = eAbsolute;
108 NoiseType = ePercent;
109 cerr <<
"Unknown noise type in sensor: " << Name << endl;
110 cerr <<
" defaulting to PERCENT." << endl;
112 string distribution = element->FindElement(
"noise")->GetAttributeValue(
"distribution");
113 if (distribution ==
"UNIFORM") {
114 DistributionType = eUniform;
115 }
else if (distribution ==
"GAUSSIAN") {
116 DistributionType = eGaussian;
118 DistributionType = eUniform;
119 cerr <<
"Unknown random distribution type in sensor: " << Name << endl;
120 cerr <<
" defaulting to UNIFORM." << endl;
124 FGFCSComponent::bind();
132 FGSensor::~FGSensor()
139 void FGSensor::ResetPastStates(
void)
141 FGFCSComponent::ResetPastStates();
143 PreviousOutput = PreviousInput = Output = 0.0;
148 bool FGSensor::Run(
void)
150 Input = InputNodes[0]->getDoubleValue() * InputSigns[0];
152 ProcessSensorSignal();
154 if (IsOutput) SetOutput();
161 void FGSensor::ProcessSensorSignal(
void)
168 Output = PreviousOutput;
170 if (lag != 0.0) Lag();
171 if (noise_variance != 0.0) Noise();
172 if (drift_rate != 0.0) Drift();
173 if (gain != 0.0) Gain();
174 if (bias != 0.0) Bias();
176 if (delay != 0) Delay();
178 if (fail_low) Output = -HUGE_VAL;
179 if (fail_high) Output = HUGE_VAL;
181 if (bits != 0) Quantize();
189 void FGSensor::Noise(
void)
191 double random_value=0.0;
193 if (DistributionType == eUniform) {
194 random_value = 2.0*(((double)rand()/(double)RAND_MAX) - 0.5);
196 random_value = GaussianRandomNumber();
199 switch( NoiseType ) {
201 Output *= (1.0 + noise_variance*random_value);
205 Output += noise_variance*random_value;
212 void FGSensor::Bias(
void)
219 void FGSensor::Gain(
void)
226 void FGSensor::Drift(
void)
228 drift += drift_rate*dt;
234 void FGSensor::Quantize(
void)
236 if (Output < min) Output = min;
237 if (Output > max) Output = max;
238 double portion = Output - min;
239 quantized = (int)(portion/granularity);
240 Output = quantized*granularity + min;
245 void FGSensor::Lag(
void)
248 Output = ca * (Output + PreviousInput) + PreviousOutput * cb;
250 PreviousOutput = Output;
251 PreviousInput = Input;
256 void FGSensor::bind(
void)
259 if (Name.find(
"/") == string::npos) {
262 const string tmp_low = tmp +
"/malfunction/fail_low";
263 const string tmp_high = tmp +
"/malfunction/fail_high";
264 const string tmp_stuck = tmp +
"/malfunction/fail_stuck";
266 PropertyManager->
Tie( tmp_low,
this, &FGSensor::GetFailLow, &FGSensor::SetFailLow);
267 PropertyManager->
Tie( tmp_high,
this, &FGSensor::GetFailHigh, &FGSensor::SetFailHigh);
268 PropertyManager->
Tie( tmp_stuck,
this, &FGSensor::GetFailStuck, &FGSensor::SetFailStuck);
270 if (!quant_property.empty()) {
271 if (quant_property.find(
"/") == string::npos) {
272 string qprop =
"fcs/" + PropertyManager->
mkPropertyName(quant_property,
true);
273 PropertyManager->
Tie(qprop,
this, &FGSensor::GetQuantized);
298 void FGSensor::Debug(
int from)
300 if (debug_lvl <= 0)
return;
304 if (InputSigns.size() > 0) {
305 if (InputSigns[0] < 0)
306 cout <<
" INPUT: -" << InputNodes[0]->GetName() << endl;
308 cout <<
" INPUT: " << InputNodes[0]->GetName() << endl;
311 if (quant_property.empty())
312 cout <<
" Quantized output" << endl;
314 cout <<
" Quantized output (property: " << quant_property <<
")" << endl;
316 cout <<
" Bits: " << bits << endl;
317 cout <<
" Min value: " << min << endl;
318 cout <<
" Max value: " << max << endl;
319 cout <<
" (span: " << span <<
", granularity: " << granularity <<
")" << endl;
321 if (bias != 0.0) cout <<
" Bias: " << bias << endl;
322 if (gain != 0.0) cout <<
" Gain: " << gain << endl;
323 if (drift_rate != 0) cout <<
" Sensor drift rate: " << drift_rate << endl;
324 if (lag != 0) cout <<
" Sensor lag: " << lag << endl;
325 if (noise_variance != 0) {
326 if (NoiseType == eAbsolute) {
327 cout <<
" Noise variance (absolute): " << noise_variance << endl;
328 }
else if (NoiseType == ePercent) {
329 cout <<
" Noise variance (percent): " << noise_variance << endl;
331 cout <<
" Noise variance type is invalid" << endl;
333 if (DistributionType == eUniform) {
334 cout <<
" Random noise is uniformly distributed." << endl;
335 }
else if (DistributionType == eGaussian) {
336 cout <<
" Random noise is gaussian distributed." << endl;
340 for (
unsigned int i=0; i<OutputNodes.size(); i++)
341 cout <<
" OUTPUT: " << OutputNodes[i]->getName() << endl;
345 if (debug_lvl & 2 ) {
346 if (from == 0) cout <<
"Instantiated: FGSensor" << endl;
347 if (from == 1) cout <<
"Destroyed: FGSensor" << endl;
349 if (debug_lvl & 4 ) {
351 if (debug_lvl & 8 ) {
353 if (debug_lvl & 16) {
355 if (debug_lvl & 64) {
357 cout << IdSrc << endl;
358 cout << IdHdr << endl;
std::string mkPropertyName(std::string name, bool lowercase)
Property-ify a name replaces spaces with '-' and, optionally, makes name all lower case...
void Tie(const std::string &name, bool *pointer, bool useDefault=true)
Tie a property to an external bool variable.