1
0
Fork 0

[JSBSim] Actuator <lag> elements can now be specified by either a value or a property.

Thanks to Sean McLeod for the patch.
This commit is contained in:
Bertrand Coconnier 2020-05-27 15:48:41 +02:00
parent cd2011b61e
commit 9ed2406878
2 changed files with 39 additions and 26 deletions

View file

@ -39,7 +39,7 @@ INCLUDES
#include "FGActuator.h" #include "FGActuator.h"
#include "input_output/FGXMLElement.h" #include "input_output/FGXMLElement.h"
#include "math/FGRealValue.h" #include "math/FGParameterValue.h"
#include "models/FGFCS.h" #include "models/FGFCS.h"
using namespace std; using namespace std;
@ -59,7 +59,8 @@ FGActuator::FGActuator(FGFCS* fcs, Element* element)
PreviousHystOutput = 0.0; PreviousHystOutput = 0.0;
PreviousRateLimOutput = 0.0; PreviousRateLimOutput = 0.0;
PreviousLagInput = PreviousLagOutput = 0.0; PreviousLagInput = PreviousLagOutput = 0.0;
bias = lag = hysteresis_width = deadband_width = 0.0; bias = hysteresis_width = deadband_width = 0.0;
lag = nullptr;
rate_limit_incr = rate_limit_decr = 0; // no limit rate_limit_incr = rate_limit_decr = 0; // no limit
fail_zero = fail_hardover = fail_stuck = false; fail_zero = fail_hardover = fail_stuck = false;
ca = cb = 0.0; ca = cb = 0.0;
@ -78,22 +79,9 @@ FGActuator::FGActuator(FGFCS* fcs, Element* element)
// a property. // a property.
Element* ratelim_el = element->FindElement("rate_limit"); Element* ratelim_el = element->FindElement("rate_limit");
while ( ratelim_el ) { while ( ratelim_el ) {
FGParameter* rate_limit = 0;
string rate_limit_str = ratelim_el->GetDataLine(); string rate_limit_str = ratelim_el->GetDataLine();
FGParameter* rate_limit = new FGParameterValue(rate_limit_str,
trim(rate_limit_str); PropertyManager);
if (is_number(rate_limit_str))
rate_limit = new FGRealValue(fabs(atof(rate_limit_str.c_str())));
else {
if (rate_limit_str[0] == '-') rate_limit_str.erase(0,1);
FGPropertyNode* rate_limit_prop = PropertyManager->GetNode(rate_limit_str, true);
if (!rate_limit_prop) {
std::cerr << "No such property, " << rate_limit_str << " for rate limiting" << std::endl;
ratelim_el = element->FindNextElement("rate_limit");
continue;
}
rate_limit = new FGPropertyValue(rate_limit_prop);
}
if (ratelim_el->HasAttribute("sense")) { if (ratelim_el->HasAttribute("sense")) {
string sense = ratelim_el->GetAttributeValue("sense"); string sense = ratelim_el->GetAttributeValue("sense");
@ -111,11 +99,13 @@ FGActuator::FGActuator(FGFCS* fcs, Element* element)
if ( element->FindElement("bias") ) { if ( element->FindElement("bias") ) {
bias = element->FindElementValueAsNumber("bias"); bias = element->FindElementValueAsNumber("bias");
} }
if ( element->FindElement("lag") ) {
lag = element->FindElementValueAsNumber("lag"); // Lag if specified can be numeric or a property
double denom = 2.00 + dt*lag; Element* lag_el = element->FindElement("lag");
ca = dt*lag / denom; if ( lag_el ) {
cb = (2.00 - dt*lag) / denom; string lag_str = lag_el->GetDataLine();
lag = new FGParameterValue(lag_str, PropertyManager);
InitializeLagCoefficients();
} }
bind(element); bind(element);
@ -131,6 +121,8 @@ FGActuator::~FGActuator()
if (rate_limit_decr != rate_limit_incr) if (rate_limit_decr != rate_limit_incr)
delete rate_limit_decr; delete rate_limit_decr;
delete lag;
Debug(1); Debug(1);
} }
@ -165,7 +157,7 @@ bool FGActuator::Run(void )
if (fail_stuck) { if (fail_stuck) {
Output = PreviousOutput; Output = PreviousOutput;
} else { } else {
if (lag != 0.0) Lag(); // models actuator lag if (lag) Lag(); // models actuator lag
if (rate_limit_incr != 0 || rate_limit_decr != 0) RateLimit(); // limit the actuator rate if (rate_limit_incr != 0 || rate_limit_decr != 0) RateLimit(); // limit the actuator rate
if (deadband_width != 0.0) Deadband(); if (deadband_width != 0.0) Deadband();
if (hysteresis_width != 0.0) Hysteresis(); if (hysteresis_width != 0.0) Hysteresis();
@ -212,8 +204,12 @@ void FGActuator::Lag(void)
// for this Lag filter // for this Lag filter
double input = Output; double input = Output;
if ( initialized ) if (initialized) {
// Check if lag value has changed via dynamic property
if (lagVal != lag->GetValue())
InitializeLagCoefficients();
Output = ca * (input + PreviousLagInput) + PreviousLagOutput * cb; Output = ca * (input + PreviousLagInput) + PreviousLagOutput * cb;
}
PreviousLagInput = input; PreviousLagInput = input;
PreviousLagOutput = Output; PreviousLagOutput = Output;
@ -302,6 +298,16 @@ void FGActuator::bind(Element* el)
PropertyManager->Tie( tmp_sat, this, &FGActuator::IsSaturated); PropertyManager->Tie( tmp_sat, this, &FGActuator::IsSaturated);
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGActuator::InitializeLagCoefficients()
{
lagVal = lag->GetValue();
double denom = 2.00 + dt * lagVal;
ca = dt * lagVal / denom;
cb = (2.00 - dt * lagVal) / denom;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// The bitmasked value choices are as follows: // The bitmasked value choices are as follows:
// unset: In this case (the default) JSBSim would only print // unset: In this case (the default) JSBSim would only print

View file

@ -74,13 +74,17 @@ CLASS DOCUMENTATION
<rate_limit> element is supplied with a "sense" attribute of either <rate_limit> element is supplied with a "sense" attribute of either
"incr[easing]" or "decr[easing]" then the actuator is limited to the "incr[easing]" or "decr[easing]" then the actuator is limited to the
provided numeric or property value) exactly as provided. provided numeric or property value) exactly as provided.
Lag filter's numerical integration assumes that the lag parameter is
constant. So a continuously varying parameter via a property will introduce
a non negligible error that will accumulate as the simulation progresses.
Syntax: Syntax:
@code @code
<actuator name="name"> <actuator name="name">
<input> {[-]property} </input> <input> {[-]property} </input>
<lag> number </lag> <lag> {property name | value} </lag>
[<rate_limit> {property name | value} </rate_limit>] [<rate_limit> {property name | value} </rate_limit>]
[<rate_limit sense="incr"> {property name | value} </rate_limit> [<rate_limit sense="incr"> {property name | value} </rate_limit>
<rate_limit sense="decr"> {property name | value} </rate_limit>] <rate_limit sense="decr"> {property name | value} </rate_limit>]
@ -154,7 +158,8 @@ private:
FGParameter* rate_limit_decr; FGParameter* rate_limit_decr;
double hysteresis_width; double hysteresis_width;
double deadband_width; double deadband_width;
double lag; FGParameter* lag;
double lagVal;
double ca; // lag filter coefficient "a" double ca; // lag filter coefficient "a"
double cb; // lag filter coefficient "b" double cb; // lag filter coefficient "b"
double PreviousOutput; double PreviousOutput;
@ -176,6 +181,8 @@ private:
void bind(Element* el) override; void bind(Element* el) override;
void InitializeLagCoefficients();
void Debug(int from) override; void Debug(int from) override;
}; };
} }