1
0
Fork 0

David Culp:

Here's a new FGSimTurbine module.  Changes are:

1.  Adds starting and stopping functionality
2.  Calculate() now calls other functions, based on the engine's state, which gives more readable code.

Until now turbine engines were always running as long as fuel was available. With this new module the engine defaults to OFF.  To start with the engine running, the variable FGEngine::Running must be set to true at sim startup. In FlightGear this is done with --prop:/engines/engine[n]/running=true.

To start the engine (on the ground), first set the starter to ON, i.e. FGEngine::Starter is set to true.  In FlightGear this is done by toggling /controls/engines/engine[n]/starter to TRUE.  Note that the current FlightGear key binding will not work, as it causes the starter to quit when the key is released.  A new key binding is needed, without the mod-up.

When N2 reaches 15% or greater, place the fuel cutoff control to FALSE.  This is FGEngine::Cutoff.  In FlightGear this is done with /controls/engines/engine[n]/cutoff set to FALSE.  The engine will then accelerate to idle.  Upon reaching idle, the starter is automatically turned off, and the engine is running.  There is presently no FlightGear key binding for the fuel cutoff switch.

To shut off the engine, place the fuel cutoff control to TRUE.

If you shut down the engine in flight it will windmill.  To airstart you will need at least 15% N2, just as with a ground start.  When you have enough N2, place the cutoff control to FALSE and the engine will restart. Note that if you can't get enough N2 by speeding up, you can get it by using the starter.

The reverser still works, and is controlled in FlightGear with /controls/engines/engine[n]/reverser.  With the reverser control on (TRUE), the engine will produce negative thrust in proportion to throttle position, i.e. to get more reverse thrust, increase throttle.
This commit is contained in:
ehofman 2003-09-23 09:24:36 +00:00
parent 2764b9181b
commit 4a5dbf1106
3 changed files with 223 additions and 68 deletions

View file

@ -130,7 +130,7 @@ void FGEngine::ConsumeFuel(void)
if (TrimMode) return;
Fshortage = Oshortage = 0.0;
for (unsigned int i=0; i<SourceTanks.size(); i++) {
Tank = Propulsion->GetTank(i);
Tank = Propulsion->GetTank(SourceTanks[i]);
if (Tank->GetType() == FGTank::ttFUEL) {
Fshortage += Tank->Reduce(CalcFuelNeed()/Propulsion->GetnumSelectedFuelTanks());
} else {

View file

@ -5,7 +5,7 @@
Date started: 03/11/2003
Purpose: This module models a turbine engine.
------------- Copyright (C) 2003 David Culp (davidculp2@attbi.com) -----------
------------- Copyright (C) 2003 David Culp (davidculp2@comcast.net) ---------
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@ -33,6 +33,7 @@ on parameters given in the engine config file for this class
HISTORY
--------------------------------------------------------------------------------
03/11/2003 DPC Created
09/08/2003 DPC Changed Calculate() and added engine phases
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
INCLUDES
@ -67,89 +68,200 @@ FGSimTurbine::~FGSimTurbine()
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// The main purpose of Calculate() is to determine what phase the engine should
// be in, then call the corresponding function.
double FGSimTurbine::Calculate(double dummy)
{
double idlethrust, milthrust, thrust;
double TAT = (Auxiliary->GetTotalTemperature() - 491.69) * 0.5555556;
TAT = (Auxiliary->GetTotalTemperature() - 491.69) * 0.5555556;
dt = State->Getdt() * Propulsion->GetRate();
ThrottleCmd = FCS->GetThrottleCmd(EngineNumber);
// calculate virtual throttle position (actual +/- lag) based on
// FCS Throttle value (except when trimming)
if (dt > 0.0) {
Running = !Starved;
ThrottleCmd = FCS->GetThrottleCmd(EngineNumber);
if ( ThrottleCmd > throttle ) {
throttle += (dt * delay);
if (throttle > ThrottleCmd ) throttle = ThrottleCmd;
// When trimming is finished check if user wants engine OFF or RUNNING
if ((phase == tpTrim) && (dt > 0)) {
if (Running && !Starved) {
phase = tpRun;
N2 = IdleN2;
N1 = IdleN1;
OilTemp_degK = TAT + 10;
Cutoff = false;
}
else {
throttle -= (dt * delay * 3.0);
if (throttle < ThrottleCmd ) throttle = ThrottleCmd;
phase = tpOff;
Cutoff = true;
EGT_degC = TAT;
}
}
else {
Starved = false;
throttle = ThrottleCmd = FCS->GetThrottleCmd(EngineNumber);
}
idlethrust = MaxMilThrust * ThrustTables[0]->TotalValue();
milthrust = MaxMilThrust * ThrustTables[1]->TotalValue();
if (!Running && Cutoff && Starter) {
if (phase == tpOff) phase = tpSpinUp;
}
if (!Running && !Cutoff && (N2 > 15.0)) phase = tpStart;
if (Cutoff && (phase != tpSpinUp)) phase = tpOff;
if (dt == 0) phase = tpTrim;
if (Starved) phase = tpOff;
if (Stalled) phase = tpStall;
if (Seized) phase = tpSeize;
switch (phase) {
case tpOff: Thrust = Off(); break;
case tpRun: Thrust = Run(); break;
case tpSpinUp: Thrust = SpinUp(); break;
case tpStart: Thrust = Start(); break;
case tpStall: Thrust = Stall(); break;
case tpSeize: Thrust = Seize(); break;
case tpTrim: Thrust = Trim(); break;
default: Thrust = Off();
}
if (Running) {
thrust = milthrust * throttle * throttle;
if (thrust < idlethrust) thrust = idlethrust;
return Thrust;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double FGSimTurbine::Off(void)
{
double qbar = Translation->Getqbar();
Running = false;
FuelFlow_pph = 0.0;
N1 = Seek(&N1, qbar/10.0, N1/2.0, N1/2.0);
N2 = Seek(&N2, qbar/15.0, N2/2.0, N2/2.0);
EGT_degC = Seek(&EGT_degC, TAT, 11.7, 7.3);
OilTemp_degK = Seek(&OilTemp_degK, TAT + 273.0, 0.2, 0.2);
OilPressure_psi = N2 * 0.62;
EPR = 1.0;
return 0.0;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double FGSimTurbine::Run(void)
{
double idlethrust, milthrust, thrust;
double N2norm; // 0.0 = idle N2, 1.0 = maximum N2
idlethrust = MaxMilThrust * ThrustTables[0]->TotalValue();
milthrust = (MaxMilThrust - idlethrust) * ThrustTables[1]->TotalValue();
Running = true;
Starter = false;
N2 = Seek(&N2, IdleN2 + ThrottleCmd * N2_factor, delay, delay * 3.0);
N1 = Seek(&N1, IdleN1 + ThrottleCmd * N1_factor, delay, delay * 2.4);
N2norm = (N2 - IdleN2) / N2_factor;
thrust = idlethrust + (milthrust * N2norm * N2norm);
FuelFlow_pph = thrust * TSFC;
thrust = thrust * (1.0 - BleedDemand);
IdleFF = pow(MaxMilThrust, 0.2) * 107.0;
if (FuelFlow_pph < IdleFF) FuelFlow_pph = IdleFF;
N1 = IdleN1 + throttle * N1_factor;
N2 = IdleN2 + throttle * N2_factor;
EGT_degC = TAT + 363.1 + ThrottleCmd * 357.1;
OilPressure_psi = N2 * 0.62;
OilTemp_degK += dt * 1.2;
if (OilTemp_degK > 366.0) OilTemp_degK = 366.0;
OilTemp_degK = Seek(&OilTemp_degK, 366.0, 1.2, 0);
EPR = 1.0 + thrust/MaxMilThrust;
NozzlePosition = 1.0 - throttle;
NozzlePosition = Seek(&NozzlePosition, 1.0 - N2norm, 0.8, 0.8);
if (Reversed) thrust = thrust * -0.2;
}
else {
thrust = 0.0;
FuelFlow_pph = 0.000001;
N1 -= (dt * 3.0);
if (N1 < (Translation->Getqbar()/10.0)) N1 = Translation->Getqbar()/10.0;
N2 -= (dt * 3.5);
if (N2 < (Translation->Getqbar()/15.0)) N2 = Translation->Getqbar()/15.0;
EGT_degC -= (dt * 11.7);
if (EGT_degC < TAT) EGT_degC = TAT;
OilPressure_psi = N2 * 0.62;
OilTemp_degK -= (dt * 0.2);
if (OilTemp_degK < (TAT + 273.0)) OilTemp_degK = (TAT + 273.0);
EPR = 1.0;
}
if (AugMethod == 1) {
if (throttle > 0.99) {Augmentation = true;}
else {Augmentation = false;}
}
if (AugMethod == 1) {
if ((ThrottleCmd > 0.99) && (N2 > 97.0)) {Augmentation = true;}
else {Augmentation = false;}
}
if ((Augmented == 1) && Augmentation) {
thrust = thrust * ThrustTables[2]->TotalValue();
FuelFlow_pph = thrust * ATSFC;
NozzlePosition = 1.0;
}
if ((Augmented == 1) && Augmentation) {
thrust = thrust * ThrustTables[2]->TotalValue();
FuelFlow_pph = thrust * ATSFC;
NozzlePosition = Seek(&NozzlePosition, 1.0, 0.8, 0);
}
if ((Injected == 1) && Injection)
thrust = thrust * ThrustTables[3]->TotalValue();
ConsumeFuel();
return Thrust = thrust;
if ((Injected == 1) && Injection)
thrust = thrust * ThrustTables[3]->TotalValue();
ConsumeFuel();
if (Cutoff) phase = tpOff;
if (Starved) phase = tpOff;
return thrust;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double FGSimTurbine::SpinUp(void)
{
Running = false;
FuelFlow_pph = 0.0;
N2 = Seek(&N2, 25.18, 3.0, N2/2.0);
N1 = Seek(&N1, 5.21, 1.0, N1/2.0);
EGT_degC = TAT;
OilPressure_psi = N2 * 0.62;
OilTemp_degK = TAT + 273.0;
EPR = 1.0;
NozzlePosition = 1.0;
return 0.0;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double FGSimTurbine::Start(void)
{
if ((N2 > 15.0) && !Starved) { // minimum 15% N2 needed for start
Cranking = true;
if (N2 < IdleN2) {
N2 = Seek(&N2, IdleN2, 2.0, N2/2.0);
N1 = Seek(&N1, IdleN1, 1.4, N1/2.0);
EGT_degC = Seek(&EGT_degC, TAT + 363.1, 21.3, 7.3);
FuelFlow_pph = Seek(&FuelFlow_pph, IdleFF, 103.7, 103.7);
OilPressure_psi = N2 * 0.62;
}
else {
phase = tpRun;
Running = true;
Starter = false;
Cranking = false;
}
}
else { // no start if N2 < 15%
phase = tpOff;
Starter = false;
}
return 0.0;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double FGSimTurbine::Stall(void)
{
double qbar = Translation->Getqbar();
EGT_degC = TAT + 903.14;
FuelFlow_pph = IdleFF;
N1 = Seek(&N1, qbar/10.0, 0, N1/10.0);
N2 = Seek(&N2, qbar/15.0, 0, N2/10.0);
if (ThrottleCmd == 0) phase = tpRun; // clear the stall with throttle
return 0.0;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double FGSimTurbine::Seize(void)
{
double qbar = Translation->Getqbar();
N2 = 0.0;
N1 = Seek(&N1, qbar/20.0, 0, N1/15.0);
FuelFlow_pph = IdleFF;
OilPressure_psi = 0.0;
OilTemp_degK = Seek(&OilTemp_degK, TAT + 273.0, 0, 0.2);
Running = false;
return 0.0;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double FGSimTurbine::Trim(void)
{
double idlethrust, milthrust, thrust;
idlethrust = MaxMilThrust * ThrustTables[0]->TotalValue();
milthrust = (MaxMilThrust - idlethrust) * ThrustTables[1]->TotalValue();
thrust = idlethrust + (milthrust * ThrottleCmd * ThrottleCmd);
return thrust;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double FGSimTurbine::CalcFuelNeed(void)
{
return FuelFlow_pph /3600 * State->Getdt() * Propulsion->GetRate();
@ -158,10 +270,24 @@ double FGSimTurbine::CalcFuelNeed(void)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double FGSimTurbine::GetPowerAvailable(void) {
if( throttle <= 0.77 )
return 64.94*throttle;
if( ThrottleCmd <= 0.77 )
return 64.94*ThrottleCmd;
else
return 217.38*throttle - 117.38;
return 217.38*ThrottleCmd - 117.38;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double FGSimTurbine::Seek(double *var, double target, double accel, double decel) {
double v = *var;
if (v > target) {
v -= dt * decel;
if (v < target) v = target;
} else if (v < target) {
v += dt * accel;
if (v > target) v = target;
}
return v;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -181,12 +307,17 @@ void FGSimTurbine::SetDefaults(void)
AugMethod = 0;
Injected = 0;
BleedDemand = 0.0;
throttle = 0.0;
ThrottleCmd = 0.0;
InletPosition = 1.0;
NozzlePosition = 1.0;
Augmentation = false;
Injection = false;
Reversed = false;
phase = tpOff;
Stalled = false;
Seized = false;
Overtemp = false;
Fire = false;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -217,12 +348,11 @@ bool FGSimTurbine::Load(FGConfigFile *Eng_cfg)
}
// pre-calculations and initializations
delay= 1.0 / (BypassRatio + 3.0);
delay= 60.0 / (BypassRatio + 3.0);
N1_factor = MaxN1 - IdleN1;
N2_factor = MaxN2 - IdleN2;
OilTemp_degK = (Auxiliary->GetTotalTemperature() - 491.69) * 0.5555556 + 273.0;
IdleFF = pow(MaxMilThrust, 0.2) * 107.0; // just an estimate
AddFeedTank(EngineNumber); // engine[n] feeds from tank[n]
return true;
}

View file

@ -4,7 +4,7 @@
Author: David Culp
Date started: 03/11/2003
------------- Copyright (C) 2003 David Culp (davidculp2@attbi.com)------------
------------- Copyright (C) 2003 David Culp (davidculp2@comcast.net)----------
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@ -26,6 +26,7 @@
HISTORY
--------------------------------------------------------------------------------
03/11/2003 DPC Created
09/22/2003 DPC Added starting, stopping
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
COMMENTS, REFERENCES, and NOTES
@ -61,15 +62,25 @@ public:
FGSimTurbine(FGFDMExec* exec, FGConfigFile* Eng_cfg);
~FGSimTurbine();
enum phaseType { tpOff, tpRun, tpSpinUp, tpStart, tpStall, tpSeize, tpTrim };
double Calculate(double);
double CalcFuelNeed(void);
double GetPowerAvailable(void);
double Seek(double* var, double target, double accel, double decel);
virtual phaseType GetPhase(void) { return phase; }
virtual void SetPhase( phaseType p ) { phase = p; }
virtual bool GetOvertemp(void) { return Overtemp; }
virtual bool GetFire(void) { return Fire; }
private:
typedef vector<FGCoefficient*> CoeffArray;
CoeffArray ThrustTables;
phaseType phase; // Operating mode, or "phase"
double MaxMilThrust; // Maximum Rated Thrust, static @ S.L. (lbf)
double BypassRatio; // Bypass Ratio
double TSFC; // Thrust Specific Fuel Consumption (lbm/hr/lbf)
@ -85,11 +96,25 @@ private:
double N2_factor; // factor to tie N2 and throttle
double ThrottleCmd; // FCS-supplied throttle position
double throttle; // virtual throttle position
double TAT; // total air temperature (deg C)
bool Stalled; // true if engine is compressor-stalled
bool Seized; // true if inner spool is seized
bool Overtemp; // true if EGT exceeds limits
bool Fire; // true if engine fire detected
bool start_running; // true if user wants engine running at start
int Augmented; // = 1 if augmentation installed
int Injected; // = 1 if water injection installed
int AugMethod; // = 0 if using property /engine[n]/augmentation
// = 1 if using last 1% of throttle movement
double Off(void);
double Run(void);
double SpinUp(void);
double Start(void);
double Stall(void);
double Seize(void);
double Trim(void);
void SetDefaults(void);
bool Load(FGConfigFile *ENG_cfg);
void Debug(int from);