1
0
Fork 0

New features for JSBSim (not to be included in release 2018.3)

The following new features have been added to JSBSim:
* Added the ability to set up the starter and acceleration times of a turbine (parameters <n1spinup>, <n2spinup>, <n1startrate>, <n2startrate>).
* The <integrator> filter can now be reset to 0.0 by setting its <trigger> property to a negative value.
* The integration scheme of the <integrator> filter can now be chosen among "rect" (Euler), "trap" (Trapezoidal), "ab2" 2nd order Adams-BashForth and "ab3" 3rd order Adams-Bashforth
* The following functions can now be used in <function>: floor, ceil and fmod. Their functionalities are the same than the corresponding C/C++ functions.
This commit is contained in:
Bertrand Coconnier 2018-10-28 16:16:20 +01:00
parent 94e1cdc551
commit 04eb045931
8 changed files with 133 additions and 48 deletions

View file

@ -177,6 +177,7 @@ public:
/** Retrieves the element name. /** Retrieves the element name.
@return the element name, or the empty string if no name has been set.*/ @return the element name, or the empty string if no name has been set.*/
const std::string& GetName(void) const {return name;} const std::string& GetName(void) const {return name;}
void ChangeName(const std::string& _name) { name = _name; }
/** Gets a line of data belonging to an element. /** Gets a line of data belonging to an element.
@param i the index of the data line to return (0 by default). @param i the index of the data line to return (0 by default).

View file

@ -107,6 +107,9 @@ const std::string FGFunction::not_string = "not";
const std::string FGFunction::ifthen_string = "ifthen"; const std::string FGFunction::ifthen_string = "ifthen";
const std::string FGFunction::switch_string = "switch"; const std::string FGFunction::switch_string = "switch";
const std::string FGFunction::interpolate1d_string = "interpolate1d"; const std::string FGFunction::interpolate1d_string = "interpolate1d";
const std::string FGFunction::floor_string = "floor";
const std::string FGFunction::ceil_string = "ceil";
const std::string FGFunction::fmod_string = "fmod";
FGFunction::FGFunction(FGPropertyManager* PropertyManager, Element* el, FGFunction::FGFunction(FGPropertyManager* PropertyManager, Element* el,
const string& prefix, FGPropertyValue* var) const string& prefix, FGPropertyValue* var)
@ -228,6 +231,12 @@ void FGFunction::Load(FGPropertyManager* PropertyManager, Element* el,
Type = eSwitch; Type = eSwitch;
} else if (operation == interpolate1d_string) { } else if (operation == interpolate1d_string) {
Type = eInterpolate1D; Type = eInterpolate1D;
} else if (operation == floor_string) {
Type = eFloor;
} else if (operation == ceil_string) {
Type = eCeil;
} else if (operation == fmod_string) {
Type = eFmod;
} else if (operation != description_string) { } else if (operation != description_string) {
cerr << "Bad operation " << operation << " detected in configuration file" << endl; cerr << "Bad operation " << operation << " detected in configuration file" << endl;
} }
@ -324,7 +333,10 @@ void FGFunction::Load(FGPropertyManager* PropertyManager, Element* el,
operation == not_string || operation == not_string ||
operation == ifthen_string || operation == ifthen_string ||
operation == switch_string || operation == switch_string ||
operation == interpolate1d_string) operation == interpolate1d_string ||
operation == floor_string ||
operation == ceil_string ||
operation == fmod_string)
{ {
Parameters.push_back(new FGFunction(PropertyManager, element, Prefix, var)); Parameters.push_back(new FGFunction(PropertyManager, element, Prefix, var));
} else if (operation != description_string) { } else if (operation != description_string) {
@ -767,6 +779,18 @@ double FGFunction::GetValue(void) const
else // else //
{temp = 1;} {temp = 1;}
break; break;
case eFloor:
temp = floor(temp);
break;
case eCeil:
temp = ceil(temp);
break;
case eFmod:
if (Parameters[1]->GetValue() != 0.0)
temp = fmod(temp, Parameters[1]->GetValue());
else
temp = HUGE_VAL;
break;
default: default:
cerr << "Unknown function operation type" << endl; cerr << "Unknown function operation type" << endl;
break; break;

View file

@ -84,6 +84,9 @@ A function definition consists of an operation, a value, a table, or a property
- avg (takes n args) - avg (takes n args)
- fraction - fraction
- mod - mod
- floor (takes 1 arg)
- ceil (takes 1 arg)
- fmod (takes 2 args)
- lt (less than, takes 2 args) - lt (less than, takes 2 args)
- le (less equal, takes 2 args) - le (less equal, takes 2 args)
- gt (greater than, takes 2 args) - gt (greater than, takes 2 args)
@ -466,13 +469,36 @@ of the three words refers to one or more instances of a property, value, or tabl
quotient of 3 and leaves a remainder of 0. quotient of 3 and leaves a remainder of 0.
@code @code
<mod> <mod>
{property, value, table, or other function element} {property, value, table, or other function element} {property, value, table, or other function element}
{property, value, table, or other function element}
</mod> </mod>
Example: 5 mod 2, evaluates to 1 Example: 5 mod 2, evaluates to 1
<mod> <v> 5 </v> <v> 2 </v> </mod> <mod> <v> 5 </v> <v> 2 </v> </mod>
@endcode @endcode
- @b floor returns the largest integral value that is not greater than X.
@code
<floor>
{property, value, table, or other function element}
</floor>
@endcode
Examples: floor(2.3) evaluates to 2.0 while floor(-2.3) evaluates to -3.0
- @b ceil returns the smallest integral value that is not less than X.
@code
<ceil>
{property, value, table, or other function element}
</ceil>
@endcode
Examples: ceil(2.3) evaluates to 3.0 while ceil(-2.3) evaluates to -2.0
- @b fmod returns the floating-point remainder of X/Y (rounded towards zero)
@code
<fmod>
{property, value, table, or other function element}
{property, value, table, or other function element}
</fmod>
@endcode
Example: fmod(18.5, 4.2) evaluates to 1.7
- @b lt returns a 1 if the value of the first immediate child element is less - @b lt returns a 1 if the value of the first immediate child element is less
than the value of the second immediate child element, returns 0 than the value of the second immediate child element, returns 0
otherwise otherwise
@ -799,6 +825,9 @@ private:
static const std::string ifthen_string; static const std::string ifthen_string;
static const std::string switch_string; static const std::string switch_string;
static const std::string interpolate1d_string; static const std::string interpolate1d_string;
static const std::string floor_string;
static const std::string ceil_string;
static const std::string fmod_string;
enum functionType {eTopLevel=0, eProduct, eDifference, eSum, eQuotient, ePow, eSqrt, eToRadians, enum functionType {eTopLevel=0, eProduct, eDifference, eSum, eQuotient, ePow, eSqrt, eToRadians,
eToDegrees, eExp, eAbs, eSign, eSin, eCos, eTan, eASin, eACos, eATan, eATan2, eToDegrees, eExp, eAbs, eSign, eSin, eCos, eTan, eASin, eACos, eATan, eATan2,
@ -806,7 +835,7 @@ private:
eLog2, eLn, eLog10, eLT, eLE, eGE, eGT, eEQ, eNE, eAND, eOR, eNOT, eLog2, eLn, eLog10, eLT, eLE, eGE, eGT, eEQ, eNE, eAND, eOR, eNOT,
eIfThen, eSwitch, eInterpolate1D, eRotation_alpha_local, eIfThen, eSwitch, eInterpolate1D, eRotation_alpha_local,
eRotation_beta_local, eRotation_gamma_local, eRotation_bf_to_wf, eRotation_beta_local, eRotation_gamma_local, eRotation_bf_to_wf,
eRotation_wf_to_bf} Type; eRotation_wf_to_bf, eFloor, eCeil, eFmod} Type;
std::string Prefix; std::string Prefix;
bool cached; bool cached;
double cachedValue; double cachedValue;

View file

@ -534,8 +534,7 @@ bool FGFCS::Load(Element* document)
if ((component_element->GetName() == string("lag_filter")) || if ((component_element->GetName() == string("lag_filter")) ||
(component_element->GetName() == string("lead_lag_filter")) || (component_element->GetName() == string("lead_lag_filter")) ||
(component_element->GetName() == string("washout_filter")) || (component_element->GetName() == string("washout_filter")) ||
(component_element->GetName() == string("second_order_filter")) || (component_element->GetName() == string("second_order_filter")) )
(component_element->GetName() == string("integrator")) )
{ {
newChannel->Add(new FGFilter(this, component_element)); newChannel->Add(new FGFilter(this, component_element));
} else if ((component_element->GetName() == string("pure_gain")) || } else if ((component_element->GetName() == string("pure_gain")) ||
@ -555,6 +554,18 @@ bool FGFCS::Load(Element* document)
newChannel->Add(new FGFCSFunction(this, component_element)); newChannel->Add(new FGFCSFunction(this, component_element));
} else if (component_element->GetName() == string("pid")) { } else if (component_element->GetName() == string("pid")) {
newChannel->Add(new FGPID(this, component_element)); newChannel->Add(new FGPID(this, component_element));
} else if (component_element->GetName() == string("integrator")) {
// <integrator> is equivalent to <pid type="trap">
Element* c1_el = component_element->FindElement("c1");
if (!c1_el) {
cerr << component_element->ReadFrom();
throw("INTEGRATOR component " + component_element->GetAttributeValue("name")
+ " does not provide the parameter <c1>");
}
c1_el->ChangeName("ki");
if (!c1_el->HasAttribute("type"))
c1_el->AddAttribute("type", "trap");
newChannel->Add(new FGPID(this, component_element));
} else if (component_element->GetName() == string("actuator")) { } else if (component_element->GetName() == string("actuator")) {
newChannel->Add(new FGActuator(this, component_element)); newChannel->Add(new FGActuator(this, component_element));
} else if (component_element->GetName() == string("sensor")) { } else if (component_element->GetName() == string("sensor")) {

View file

@ -68,7 +68,6 @@ FGFilter::FGFilter(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element)
else if (Type == "LEAD_LAG_FILTER") FilterType = eLeadLag ; else if (Type == "LEAD_LAG_FILTER") FilterType = eLeadLag ;
else if (Type == "SECOND_ORDER_FILTER") FilterType = eOrder2 ; else if (Type == "SECOND_ORDER_FILTER") FilterType = eOrder2 ;
else if (Type == "WASHOUT_FILTER") FilterType = eWashout ; else if (Type == "WASHOUT_FILTER") FilterType = eWashout ;
else if (Type == "INTEGRATOR") FilterType = eIntegrator ;
else FilterType = eUnknown ; else FilterType = eUnknown ;
if (element->FindElement("trigger")) { if (element->FindElement("trigger")) {
@ -170,10 +169,6 @@ void FGFilter::CalculateDynamicFilters(void)
ca = 2.00 / denom; ca = 2.00 / denom;
cb = (2.00 - dt*C[1]) / denom; cb = (2.00 - dt*C[1]) / denom;
break; break;
case eIntegrator:
if (PropertyNode[1] != 0L) C[1] = PropertyNode[1]->getDoubleValue()*PropertySign[1];
ca = dt*C[1] / 2.00;
break;
case eUnknown: case eUnknown:
cerr << "Unknown filter type" << endl; cerr << "Unknown filter type" << endl;
break; break;
@ -210,15 +205,6 @@ bool FGFilter::Run(void)
case eWashout: case eWashout:
Output = Input * ca - PreviousInput1 * ca + PreviousOutput1 * cb; Output = Input * ca - PreviousInput1 * ca + PreviousOutput1 * cb;
break; break;
case eIntegrator:
if (Trigger != 0) {
double test = Trigger->getDoubleValue();
if (fabs(test) > 0.000001) {
Input = PreviousInput1 = PreviousInput2 = 0.0;
}
}
Output = Input * ca + PreviousInput1 * ca + PreviousOutput1;
break;
case eUnknown: case eUnknown:
break; break;
} }
@ -321,12 +307,6 @@ void FGFilter::Debug(int from)
if (PropertyNode[1] == 0L) cout << " C[1]: " << C[1] << endl; if (PropertyNode[1] == 0L) cout << " C[1]: " << C[1] << endl;
else cout << " C[1] is the value of property: " << sgn << PropertyNode[1]->GetName() << endl; else cout << " C[1] is the value of property: " << sgn << PropertyNode[1]->GetName() << endl;
break; break;
case eIntegrator:
if (PropertySign[1] < 0.0) sgn="-";
else sgn = "";
if (PropertyNode[1] == 0L) cout << " C[1]: " << C[1] << endl;
else cout << " C[1] is the value of property: " << sgn << PropertyNode[1]->GetName() << endl;
break;
case eUnknown: case eUnknown:
break; break;
} }

View file

@ -199,15 +199,15 @@ For an integrator of the form:
The corresponding filter definition is: The corresponding filter definition is:
@code @code
<integrator name="name"> <integrator name="{string}">
<input> property </input> <input> {property} </input>
<c1> value|property </c1> <c1 type="rect|trap|ab2|ab3"> {[-]property | number} </c1>
[<trigger> property </trigger>] [<trigger> {property} </trigger>]
[<clipto> [<clipto>
<min> {[-]property name | value} </min> <min> {[-]property | number} </min>
<max> {[-]property name | value} </max> <max> {[-]property | number} </max>
</clipto>] </clipto>]
[<output> property </output>] [<output> {property} </output>]
</integrator> </integrator>
@endcode @endcode
@ -217,12 +217,32 @@ property value is:
- not 0: (or simply greater than zero), all current and previous inputs will - not 0: (or simply greater than zero), all current and previous inputs will
be set to 0.0 be set to 0.0
By default, the integration scheme is the trapezoidal scheme.
An integrator is equivalent to a PID with the following parameters:
@code
<pid name="{string}">
<input> {[-]property} </input>
<kp> 0.0 </kp>
<ki type="rect|trap|ab2|ab3"> {number|[-]property} </ki>
<kd> 0.0 </kd>
<trigger> {property} </trigger>
[<clipto>
<min> {[-]property | value} </min>
<max> {[-]property | value} </max>
</clipto>]
[<output> {property} </output>]
</pid>
@endcode
As a consequence, JSBSim internally uses PID controllers to simulate INTEGRATOR
filters.
In all the filter specifications above, an \<output> element is also seen. This In all the filter specifications above, an \<output> element is also seen. This
is so that the last component in a "string" can copy its value to the appropriate is so that the last component in a "string" can copy its value to the
output, such as the elevator, or speedbrake, etc. appropriate output, such as the elevator, or speedbrake, etc.
@author Jon S. Berndt @author Jon S. Berndt
@version $Revision: 1.14 $
*/ */
@ -243,7 +263,7 @@ public:
bool Initialize; bool Initialize;
void ResetPastStates(void); void ResetPastStates(void);
enum {eLag, eLeadLag, eOrder2, eWashout, eIntegrator, eUnknown} FilterType; enum {eLag, eLeadLag, eOrder2, eWashout, eUnknown} FilterType;
private: private:
double ca; double ca;

View file

@ -70,7 +70,7 @@ FGTurbine::FGTurbine(FGFDMExec* exec, Element *el, int engine_number, struct Inp
Augmented = AugMethod = Injected = 0; Augmented = AugMethod = Injected = 0;
BypassRatio = BleedDemand = 0.0; BypassRatio = BleedDemand = 0.0;
IdleThrustLookup = MilThrustLookup = MaxThrustLookup = InjectionLookup = 0; IdleThrustLookup = MilThrustLookup = MaxThrustLookup = InjectionLookup = 0;
N1_spinup = 1.0; N2_spinup = 3.0; N1_spinup = 1.0; N2_spinup = 3.0; IgnitionN1 = 5.21; IgnitionN2 = 25.18; N1_start_rate = 1.4; N2_start_rate = 2.0;
InjectionTime = 30.0; InjectionTime = 30.0;
InjectionTimer = InjWaterNorm = 0.0; InjectionTimer = InjWaterNorm = 0.0;
EPR = 1.0; EPR = 1.0;
@ -281,8 +281,8 @@ double FGTurbine::SpinUp(void)
{ {
Running = false; Running = false;
FuelFlow_pph = 0.0; FuelFlow_pph = 0.0;
N2 = Seek(&N2, 25.18, N2_spinup, N2/2.0); N2 = Seek(&N2, IgnitionN2, N2_spinup, N2/2.0);
N1 = Seek(&N1, 5.21, N1_spinup, N1/2.0); N1 = Seek(&N1, IgnitionN1, N1_spinup, N1/2.0);
EGT_degC = Seek(&EGT_degC, in.TAT_c, 11.7, 7.3); EGT_degC = Seek(&EGT_degC, in.TAT_c, 11.7, 7.3);
OilPressure_psi = N2 * 0.62; OilPressure_psi = N2 * 0.62;
OilTemp_degK = Seek(&OilTemp_degK, in.TAT_c + 273.0, 0.2, 0.2); OilTemp_degK = Seek(&OilTemp_degK, in.TAT_c + 273.0, 0.2, 0.2);
@ -299,8 +299,8 @@ double FGTurbine::Start(void)
if ((N2 > 15.0) && !Starved) { // minimum 15% N2 needed for start if ((N2 > 15.0) && !Starved) { // minimum 15% N2 needed for start
Cranking = true; // provided for sound effects signal Cranking = true; // provided for sound effects signal
if (N2 < IdleN2) { if (N2 < IdleN2) {
N2 = Seek(&N2, IdleN2, 2.0, N2/2.0); N2 = Seek(&N2, IdleN2, N2_start_rate, N2/2.0);
N1 = Seek(&N1, IdleN1, 1.4, N1/2.0); N1 = Seek(&N1, IdleN1, N1_start_rate, N1/2.0);
EGT_degC = Seek(&EGT_degC, in.TAT_c + 363.1, 21.3, 7.3); EGT_degC = Seek(&EGT_degC, in.TAT_c + 363.1, 21.3, 7.3);
FuelFlow_pph = IdleFF * N2 / IdleN2; FuelFlow_pph = IdleFF * N2 / IdleN2;
OilPressure_psi = N2 * 0.62; OilPressure_psi = N2 * 0.62;
@ -448,6 +448,10 @@ bool FGTurbine::Load(FGFDMExec* exec, Element *el)
TSFC = el->FindElementValueAsNumber("tsfc"); TSFC = el->FindElementValueAsNumber("tsfc");
if (el->FindElement("atsfc")) if (el->FindElement("atsfc"))
ATSFC = el->FindElementValueAsNumber("atsfc"); ATSFC = el->FindElementValueAsNumber("atsfc");
if (el->FindElement("ignitionn1"))
IgnitionN1 = el->FindElementValueAsNumber("ignitionn1");
if (el->FindElement("ignitionn2"))
IgnitionN1 = el->FindElementValueAsNumber("ignitionn2");
if (el->FindElement("idlen1")) if (el->FindElement("idlen1"))
IdleN1 = el->FindElementValueAsNumber("idlen1"); IdleN1 = el->FindElementValueAsNumber("idlen1");
if (el->FindElement("idlen2")) if (el->FindElement("idlen2"))
@ -460,6 +464,10 @@ bool FGTurbine::Load(FGFDMExec* exec, Element *el)
N1_spinup = el->FindElementValueAsNumber("n1spinup"); N1_spinup = el->FindElementValueAsNumber("n1spinup");
if (el->FindElement("n2spinup")) if (el->FindElement("n2spinup"))
N2_spinup = el->FindElementValueAsNumber("n2spinup"); N2_spinup = el->FindElementValueAsNumber("n2spinup");
if (el->FindElement("n1startrate"))
N1_start_rate = el->FindElementValueAsNumber("n1startrate");
if (el->FindElement("n2startrate"))
N2_start_rate = el->FindElementValueAsNumber("n2startrate");
if (el->FindElement("augmented")) if (el->FindElement("augmented"))
Augmented = (int)el->FindElementValueAsNumber("augmented"); Augmented = (int)el->FindElementValueAsNumber("augmented");
if (el->FindElement("augmethod")) if (el->FindElement("augmethod"))

View file

@ -66,8 +66,8 @@ CLASS DOCUMENTATION
<P> <P>
- STARTING (on ground): - STARTING (on ground):
-# Set the control FGEngine::Starter to true. The engine will spin up to -# Set the control FGEngine::Starter to true. The engine will spin up to
a maximum of about %25 N2 (%5.2 N1). This simulates the action of a a maximum of about %25 N2 (%5.2 N1). This value may be changed using the <startnX> parameter.
pneumatic starter. This simulates the action of a pneumatic starter.
-# After reaching %15 N2 set the control FGEngine::Cutoff to false. If fuel -# After reaching %15 N2 set the control FGEngine::Cutoff to false. If fuel
is available the engine will now accelerate to idle. The starter will is available the engine will now accelerate to idle. The starter will
automatically be set to false after the start cycle. automatically be set to false after the start cycle.
@ -78,7 +78,7 @@ CLASS DOCUMENTATION
-# Place the control FGEngine::Cutoff to false. -# Place the control FGEngine::Cutoff to false.
<P> <P>
Ignition is assumed to be on anytime the Cutoff control is set to false, Ignition is assumed to be on anytime the Cutoff control is set to false,
therefore a seperate ignition system is not modeled. therefore a separate ignition system is not modeled.
<h3>Configuration File Format:</h3> <h3>Configuration File Format:</h3>
@code @code
@ -89,10 +89,14 @@ CLASS DOCUMENTATION
<bleed> {number} </bleed> <bleed> {number} </bleed>
<tsfc> {number} </tsfc> <tsfc> {number} </tsfc>
<atsfc> {number} </atsfc> <atsfc> {number} </atsfc>
<ignitionn1> {number} </ignitionn1>
<ignitionn2> {number} </ignitionn2>
<idlen1> {number} </idlen1> <idlen1> {number} </idlen1>
<idlen2> {number} </idlen2> <idlen2> {number} </idlen2>
<n1spinup> {number} </n1spinup> <n1spinup> {number} </n1spinup>
<n2spinup> {number} </n2spinup> <n2spinup> {number} </n2spinup>
<n1startrate> {number} </n1startrate>
<n2startrate> {number} </n2startrate>
<maxn1> {number} </maxn1> <maxn1> {number} </maxn1>
<maxn2> {number} </maxn2> <maxn2> {number} </maxn2>
<augmented> {0 | 1} </augmented> <augmented> {0 | 1} </augmented>
@ -111,10 +115,14 @@ CLASS DOCUMENTATION
bleed - Thrust reduction factor due to losses (0.0 to 1.0). bleed - Thrust reduction factor due to losses (0.0 to 1.0).
tsfc - Thrust-specific fuel consumption at cruise, lbm/hr/lbf tsfc - Thrust-specific fuel consumption at cruise, lbm/hr/lbf
atsfc - Afterburning TSFC, lbm/hr/lbf atsfc - Afterburning TSFC, lbm/hr/lbf
ignitionn1 - Fan rotor rpm (% of max) while starting
ignitionn2 - Core rotor rpm (% of max) while starting
idlen1 - Fan rotor rpm (% of max) at idle idlen1 - Fan rotor rpm (% of max) at idle
idlen2 - Core rotor rpm (% of max) at idle idlen2 - Core rotor rpm (% of max) at idle
n1spinup - Fan rotor rpm starter acceleration (default 1.0) n1spinup - Fan rotor rpm starter acceleration to ignitionn1 value (default 1.0)
n2spinup - Core rotor rpm starter acceleration (default 3.0) n2spinup - Core rotor rpm starter acceleration to ignitionn2 value (default 3.0)
n1startrate - Fan rotor rpm time taken to accelerate from ignitionn1 to idlen1 value (default 1.4)
n2startrate - Core rotor rpm time taken to accelerate to ignitionn2 idlen2 value (default 2.0)
maxn1 - Fan rotor rpm (% of max) at full throttle maxn1 - Fan rotor rpm (% of max) at full throttle
maxn2 - Core rotor rpm (% of max) at full throttle maxn2 - Core rotor rpm (% of max) at full throttle
augmented augmented
@ -238,6 +246,8 @@ private:
double ATSFC; ///< Augmented TSFC (lbm/hr/lbf) double ATSFC; ///< Augmented TSFC (lbm/hr/lbf)
double IdleN1; ///< Idle N1 double IdleN1; ///< Idle N1
double IdleN2; ///< Idle N2 double IdleN2; ///< Idle N2
double IgnitionN1; ///< Ignition N1
double IgnitionN2; ///< Ignition N2
double N1; ///< N1 double N1; ///< N1
double N2; ///< N2 double N2; ///< N2
double N2norm; ///< N2 normalized (0=idle, 1=max) double N2norm; ///< N2 normalized (0=idle, 1=max)
@ -248,8 +258,10 @@ private:
double N2_factor; ///< factor to tie N2 and throttle double N2_factor; ///< factor to tie N2 and throttle
double ThrottlePos; ///< FCS-supplied throttle position - modified for local use! double ThrottlePos; ///< FCS-supplied throttle position - modified for local use!
double AugmentCmd; ///< modulated afterburner command (0.0 to 1.0) double AugmentCmd; ///< modulated afterburner command (0.0 to 1.0)
double N1_spinup; ///< N1 spin up rate from starter (per second) double N1_spinup; ///< N1 spin up rate from pneumatic starter (per second)
double N2_spinup; ///< N2 spin up rate from starter (per second) double N2_spinup; ///< N2 spin up rate from pneumatic starter (per second)
double N1_start_rate; ///< N1 spin up rate from ignition (per second)
double N2_start_rate; ///< N2 spin up rate from ignition (per second)
bool Stalled; ///< true if engine is compressor-stalled bool Stalled; ///< true if engine is compressor-stalled
bool Seized; ///< true if inner spool is seized bool Seized; ///< true if inner spool is seized
bool Overtemp; ///< true if EGT exceeds limits bool Overtemp; ///< true if EGT exceeds limits