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:
parent
94e1cdc551
commit
04eb045931
8 changed files with 133 additions and 48 deletions
src/FDM/JSBSim
input_output
math
models
|
@ -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).
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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")) {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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"))
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Add table
Reference in a new issue