40#include "FGActuator.h"
41#include "input_output/FGXMLElement.h"
42#include "math/FGParameterValue.h"
43#include "models/FGFCS.h"
44#include "input_output/FGLog.h"
60 PreviousHystOutput = 0.0;
61 PreviousRateLimOutput = 0.0;
62 PreviousLagInput = PreviousLagOutput = 0.0;
63 bias = hysteresis_width = deadband_width = 0.0;
65 rate_limit_incr = rate_limit_decr = 0;
66 fail_zero = fail_hardover = fail_stuck =
false;
71 CheckInputNodes(1, 1, element);
83 auto PropertyManager = fcs->GetPropertyManager();
85 while ( ratelim_el ) {
88 PropertyManager, ratelim_el);
92 if (sense.substr(0,4) ==
"incr")
93 rate_limit_incr = rate_limit;
94 else if (sense.substr(0,4) ==
"decr")
95 rate_limit_decr = rate_limit;
97 rate_limit_incr = rate_limit;
98 rate_limit_decr = rate_limit;
112 InitializeLagCoefficients();
115 bind(element, PropertyManager.get());
124 delete rate_limit_incr;
125 if (rate_limit_decr != rate_limit_incr)
126 delete rate_limit_decr;
135void FGActuator::ResetPastStates(
void)
137 FGFCSComponent::ResetPastStates();
139 PreviousOutput = PreviousHystOutput = PreviousRateLimOutput
140 = PreviousLagInput = PreviousLagOutput = Output = 0.0;
147 Input = InputNodes[0]->getDoubleValue();
149 if( fcs->GetTrimStatus() ) initialized = 0;
151 if (fail_zero) Input = 0;
152 if (fail_hardover) Input = Input < 0.0 ? ClipMin->GetValue() : ClipMax->GetValue();
162 Output = PreviousOutput;
165 if (rate_limit_incr != 0 || rate_limit_decr != 0) RateLimit();
166 if (deadband_width != 0.0) Deadband();
167 if (hysteresis_width != 0.0) Hysteresis();
168 if (bias != 0.0) Bias();
169 if (delay != 0) Delay();
172 PreviousOutput = Output;
179 double clipmax = ClipMax->GetValue();
182 if (Output >= clipmax && clipmax != 0)
185 double clipmin = ClipMin->GetValue();
186 if (Output <= clipmin && clipmin != 0)
198void FGActuator::Bias(
void)
205void FGActuator::Lag(
void)
209 double input = Output;
213 if (lagVal != lag->GetValue())
214 InitializeLagCoefficients();
215 Output = ca * (input + PreviousLagInput) + PreviousLagOutput * cb;
218 PreviousLagInput = input;
219 PreviousLagOutput = Output;
224void FGActuator::Hysteresis(
void)
229 double input = Output;
232 if (input > PreviousHystOutput)
233 Output = max(PreviousHystOutput, input-0.5*hysteresis_width);
234 else if (input < PreviousHystOutput)
235 Output = min(PreviousHystOutput, input+0.5*hysteresis_width);
238 PreviousHystOutput = Output;
243void FGActuator::RateLimit(
void)
248 double input = Output;
250 double delta = input - PreviousRateLimOutput;
251 if (rate_limit_incr) {
252 double rate_limit = rate_limit_incr->GetValue();
253 if (delta > dt * rate_limit)
254 Output = PreviousRateLimOutput + rate_limit * dt;
256 if (rate_limit_decr) {
257 double rate_limit = -rate_limit_decr->GetValue();
258 if (delta < dt * rate_limit)
259 Output = PreviousRateLimOutput + rate_limit * dt;
262 PreviousRateLimOutput = Output;
267void FGActuator::Deadband(
void)
272 double input = Output;
274 if (input < -deadband_width/2.0) {
275 Output = (input + deadband_width/2.0);
276 }
else if (input > deadband_width/2.0) {
277 Output = (input - deadband_width/2.0);
285void FGActuator::bind(Element* el, FGPropertyManager* PropertyManager)
289 FGFCSComponent::bind(el, PropertyManager);
291 if (Name.find(
"/") == string::npos) {
292 tmp =
"fcs/" + PropertyManager->mkPropertyName(Name,
true);
294 const string tmp_zero = tmp +
"/malfunction/fail_zero";
295 const string tmp_hardover = tmp +
"/malfunction/fail_hardover";
296 const string tmp_stuck = tmp +
"/malfunction/fail_stuck";
297 const string tmp_sat = tmp +
"/saturated";
300 PropertyManager->Tie( tmp_hardover,
this, &FGActuator::GetFailHardover, &FGActuator::SetFailHardover);
301 PropertyManager->Tie( tmp_stuck,
this, &FGActuator::GetFailStuck, &FGActuator::SetFailStuck);
302 PropertyManager->Tie( tmp_sat,
this, &FGActuator::IsSaturated);
307void FGActuator::InitializeLagCoefficients()
309 lagVal = lag->GetValue();
310 double denom = 2.00 + dt * lagVal;
311 ca = dt * lagVal / denom;
312 cb = (2.00 - dt * lagVal) / denom;
334void FGActuator::Debug(
int from)
336 if (debug_lvl <= 0)
return;
340 FGLogging log(LogLevel::DEBUG);
341 log <<
" INPUT: " << InputNodes[0]->GetNameWithSign() << fixed
342 << setprecision(4) <<
"\n";
344 if (!OutputNodes.empty()) {
345 for (
auto node: OutputNodes)
346 log <<
" OUTPUT: " << node->getNameString() <<
"\n";
348 if (bias != 0.0) log <<
" Bias: " << bias <<
"\n";
349 if (rate_limit_incr != 0) {
350 log <<
" Increasing rate limit: " << rate_limit_incr->GetName() <<
"\n";
352 if (rate_limit_decr != 0) {
353 log <<
" Decreasing rate limit: " << rate_limit_decr->GetName() <<
"\n";
355 if (lag != 0) log <<
" Actuator lag: " << lag->GetName() <<
"\n";
356 if (hysteresis_width != 0) log <<
" Hysteresis width: " << hysteresis_width <<
"\n";
357 if (deadband_width != 0) log <<
" Deadband width: " << deadband_width <<
"\n";
360 if (debug_lvl & 2 ) {
361 FGLogging log(LogLevel::DEBUG);
362 if (from == 0) log <<
"Instantiated: FGActuator\n";
363 if (from == 1) log <<
"Destroyed: FGActuator\n";
365 if (debug_lvl & 4 ) {
367 if (debug_lvl & 8 ) {
369 if (debug_lvl & 16) {
371 if (debug_lvl & 64) {
Element * FindElement(const std::string &el="")
Searches for a specified element.
std::string GetAttributeValue(const std::string &key)
Retrieves an attribute.
std::string GetDataLine(unsigned int i=0)
Gets a line of data belonging to an element.
Element * FindNextElement(const std::string &el="")
Searches for the next element as specified.
bool HasAttribute(const std::string &key)
Determines if an element has the supplied attribute.
double FindElementValueAsNumber(const std::string &el="")
Searches for the named element and returns the data belonging to it as a number.
FGActuator(FGFCS *fcs, Element *element)
Constructor.
void SetFailZero(bool set)
This function fails the actuator to zero.
bool Run(void) override
This function processes the input.
Base class for JSBSim Flight Control System Components.
Encapsulates the Flight Control System (FCS) functionality.
Represents a either a real value or a property value.
Represents various types of parameters.
Main namespace for the JSBSim Flight Dynamics Model.