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 "input_output/FGXMLElement.h"
#include "math/FGRealValue.h"
#include "math/FGParameterValue.h"
#include "models/FGFCS.h"
using namespace std;
@ -59,7 +59,8 @@ FGActuator::FGActuator(FGFCS* fcs, Element* element)
PreviousHystOutput = 0.0;
PreviousRateLimOutput = 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
fail_zero = fail_hardover = fail_stuck = false;
ca = cb = 0.0;
@ -78,22 +79,9 @@ FGActuator::FGActuator(FGFCS* fcs, Element* element)
// a property.
Element* ratelim_el = element->FindElement("rate_limit");
while ( ratelim_el ) {
FGParameter* rate_limit = 0;
string rate_limit_str = ratelim_el->GetDataLine();
trim(rate_limit_str);
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);
}
FGParameter* rate_limit = new FGParameterValue(rate_limit_str,
PropertyManager);
if (ratelim_el->HasAttribute("sense")) {
string sense = ratelim_el->GetAttributeValue("sense");
@ -111,11 +99,13 @@ FGActuator::FGActuator(FGFCS* fcs, Element* element)
if ( element->FindElement("bias") ) {
bias = element->FindElementValueAsNumber("bias");
}
if ( element->FindElement("lag") ) {
lag = element->FindElementValueAsNumber("lag");
double denom = 2.00 + dt*lag;
ca = dt*lag / denom;
cb = (2.00 - dt*lag) / denom;
// Lag if specified can be numeric or a property
Element* lag_el = element->FindElement("lag");
if ( lag_el ) {
string lag_str = lag_el->GetDataLine();
lag = new FGParameterValue(lag_str, PropertyManager);
InitializeLagCoefficients();
}
bind(element);
@ -131,6 +121,8 @@ FGActuator::~FGActuator()
if (rate_limit_decr != rate_limit_incr)
delete rate_limit_decr;
delete lag;
Debug(1);
}
@ -165,7 +157,7 @@ bool FGActuator::Run(void )
if (fail_stuck) {
Output = PreviousOutput;
} 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 (deadband_width != 0.0) Deadband();
if (hysteresis_width != 0.0) Hysteresis();
@ -212,8 +204,12 @@ void FGActuator::Lag(void)
// for this Lag filter
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;
}
PreviousLagInput = input;
PreviousLagOutput = Output;
@ -302,6 +298,16 @@ void FGActuator::bind(Element* el)
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:
// 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
"incr[easing]" or "decr[easing]" then the actuator is limited to the
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:
@code
<actuator name="name">
<input> {[-]property} </input>
<lag> number </lag>
<lag> {property name | value} </lag>
[<rate_limit> {property name | value} </rate_limit>]
[<rate_limit sense="incr"> {property name | value} </rate_limit>
<rate_limit sense="decr"> {property name | value} </rate_limit>]
@ -154,7 +158,8 @@ private:
FGParameter* rate_limit_decr;
double hysteresis_width;
double deadband_width;
double lag;
FGParameter* lag;
double lagVal;
double ca; // lag filter coefficient "a"
double cb; // lag filter coefficient "b"
double PreviousOutput;
@ -176,6 +181,8 @@ private:
void bind(Element* el) override;
void InitializeLagCoefficients();
void Debug(int from) override;
};
}