40 #include "FGActuator.h"
41 #include "input_output/FGXMLElement.h"
42 #include "math/FGParameterValue.h"
43 #include "models/FGFCS.h"
59 PreviousHystOutput = 0.0;
60 PreviousRateLimOutput = 0.0;
61 PreviousLagInput = PreviousLagOutput = 0.0;
62 bias = hysteresis_width = deadband_width = 0.0;
64 rate_limit_incr = rate_limit_decr = 0;
65 fail_zero = fail_hardover = fail_stuck =
false;
70 CheckInputNodes(1, 1, element);
83 while ( ratelim_el ) {
90 if (sense.substr(0,4) ==
"incr")
91 rate_limit_incr = rate_limit;
92 else if (sense.substr(0,4) ==
"decr")
93 rate_limit_decr = rate_limit;
95 rate_limit_incr = rate_limit;
96 rate_limit_decr = rate_limit;
110 InitializeLagCoefficients();
122 delete rate_limit_incr;
123 if (rate_limit_decr != rate_limit_incr)
124 delete rate_limit_decr;
133 void FGActuator::ResetPastStates(
void)
135 FGFCSComponent::ResetPastStates();
137 PreviousOutput = PreviousHystOutput = PreviousRateLimOutput
138 = PreviousLagInput = PreviousLagOutput = Output = 0.0;
145 Input = InputNodes[0]->getDoubleValue();
147 if( fcs->GetTrimStatus() ) initialized = 0;
149 if (fail_zero) Input = 0;
150 if (fail_hardover) Input = Input < 0.0 ? ClipMin->GetValue() : ClipMax->GetValue();
160 Output = PreviousOutput;
163 if (rate_limit_incr != 0 || rate_limit_decr != 0) RateLimit();
164 if (deadband_width != 0.0) Deadband();
165 if (hysteresis_width != 0.0) Hysteresis();
166 if (bias != 0.0) Bias();
167 if (delay != 0) Delay();
170 PreviousOutput = Output;
177 double clipmax = ClipMax->GetValue();
180 if (Output >= clipmax && clipmax != 0)
183 double clipmin = ClipMin->GetValue();
184 if (Output <= clipmin && clipmin != 0)
196 void FGActuator::Bias(
void)
203 void FGActuator::Lag(
void)
207 double input = Output;
211 if (lagVal != lag->GetValue())
212 InitializeLagCoefficients();
213 Output = ca * (input + PreviousLagInput) + PreviousLagOutput * cb;
216 PreviousLagInput = input;
217 PreviousLagOutput = Output;
222 void FGActuator::Hysteresis(
void)
227 double input = Output;
230 if (input > PreviousHystOutput)
231 Output = max(PreviousHystOutput, input-0.5*hysteresis_width);
232 else if (input < PreviousHystOutput)
233 Output = min(PreviousHystOutput, input+0.5*hysteresis_width);
236 PreviousHystOutput = Output;
241 void FGActuator::RateLimit(
void)
246 double input = Output;
248 double delta = input - PreviousRateLimOutput;
249 if (rate_limit_incr) {
250 double rate_limit = rate_limit_incr->GetValue();
251 if (delta > dt * rate_limit)
252 Output = PreviousRateLimOutput + rate_limit * dt;
254 if (rate_limit_decr) {
255 double rate_limit = -rate_limit_decr->GetValue();
256 if (delta < dt * rate_limit)
257 Output = PreviousRateLimOutput + rate_limit * dt;
260 PreviousRateLimOutput = Output;
265 void FGActuator::Deadband(
void)
270 double input = Output;
272 if (input < -deadband_width/2.0) {
273 Output = (input + deadband_width/2.0);
274 }
else if (input > deadband_width/2.0) {
275 Output = (input - deadband_width/2.0);
283 void FGActuator::bind(Element* el)
287 FGFCSComponent::bind(el);
289 if (Name.find(
"/") == string::npos) {
292 const string tmp_zero = tmp +
"/malfunction/fail_zero";
293 const string tmp_hardover = tmp +
"/malfunction/fail_hardover";
294 const string tmp_stuck = tmp +
"/malfunction/fail_stuck";
295 const string tmp_sat = tmp +
"/saturated";
298 PropertyManager->
Tie( tmp_hardover,
this, &FGActuator::GetFailHardover, &FGActuator::SetFailHardover);
299 PropertyManager->
Tie( tmp_stuck,
this, &FGActuator::GetFailStuck, &FGActuator::SetFailStuck);
300 PropertyManager->
Tie( tmp_sat,
this, &FGActuator::IsSaturated);
305 void FGActuator::InitializeLagCoefficients()
307 lagVal = lag->GetValue();
308 double denom = 2.00 + dt * lagVal;
309 ca = dt * lagVal / denom;
310 cb = (2.00 - dt * lagVal) / denom;
332 void FGActuator::Debug(
int from)
334 if (debug_lvl <= 0)
return;
338 cout <<
" INPUT: " << InputNodes[0]->GetNameWithSign() << endl;
340 if (!OutputNodes.empty()) {
341 for (
auto node: OutputNodes)
342 cout <<
" OUTPUT: " << node->GetName() << endl;
344 if (bias != 0.0) cout <<
" Bias: " << bias << endl;
345 if (rate_limit_incr != 0) {
346 cout <<
" Increasing rate limit: " << rate_limit_incr->GetName() << endl;
348 if (rate_limit_decr != 0) {
349 cout <<
" Decreasing rate limit: " << rate_limit_decr->GetName() << endl;
351 if (lag != 0) cout <<
" Actuator lag: " << lag << endl;
352 if (hysteresis_width != 0) cout <<
" Hysteresis width: " << hysteresis_width << endl;
353 if (deadband_width != 0) cout <<
" Deadband width: " << deadband_width << endl;
356 if (debug_lvl & 2 ) {
357 if (from == 0) cout <<
"Instantiated: FGActuator" << endl;
358 if (from == 1) cout <<
"Destroyed: FGActuator" << endl;
360 if (debug_lvl & 4 ) {
362 if (debug_lvl & 8 ) {
364 if (debug_lvl & 16) {
366 if (debug_lvl & 64) {