GetTank(SourceTanks[i]);
if (Tank->GetType() == FGTank::ttFUEL){
if (Tank->GetContents() > 0.0) ++TanksWithFuel;
- } else if (Tank->GetType() == FGTank::ttOXIDIZER) {
- haveOxTanks = true;
- if (Tank->GetContents() > 0.0) ++TanksWithOxidizer;
+ } else {
+ cerr << "No oxidizer tanks should be used for this engine type." << endl;
}
}
- if (TanksWithFuel==0 || (haveOxTanks && TanksWithOxidizer==0)) {
+ if (TanksWithFuel==0) {
Starved = true;
return;
}
@@ -184,12 +186,12 @@ void FGEngine::ConsumeFuel(void)
Tank = Propulsion->GetTank(SourceTanks[i]);
if (Tank->GetType() == FGTank::ttFUEL) {
Fshortage += Tank->Drain(CalcFuelNeed()/TanksWithFuel);
- } else if (Tank->GetType() == FGTank::ttOXIDIZER) {
- Oshortage += Tank->Drain(CalcOxidizerNeed()/TanksWithOxidizer);
+ } else {
+ cerr << "No oxidizer tanks should be used for this engine type." << endl;
}
}
- if (Fshortage < 0.00 || Oshortage < 0.00) Starved = true;
+ if (Fshortage < 0.00) Starved = true;
else Starved = false;
}
@@ -197,16 +199,10 @@ void FGEngine::ConsumeFuel(void)
double FGEngine::CalcFuelNeed(void)
{
- FuelNeed = SLFuelFlowMax*PctPower*State->Getdt()*Propulsion->GetRate();
- return FuelNeed;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-double FGEngine::CalcOxidizerNeed(void)
-{
- OxidizerNeed = SLOxiFlowMax*PctPower*State->Getdt()*Propulsion->GetRate();
- return OxidizerNeed;
+ double dT = State->Getdt()*Propulsion->GetRate();
+ FuelFlowRate = SLFuelFlowMax*PctPower;
+ FuelExpended = FuelFlowRate*dT;
+ return FuelExpended;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/src/FDM/JSBSim/models/propulsion/FGEngine.h b/src/FDM/JSBSim/models/propulsion/FGEngine.h
index 225c39a0f..dd8b1302b 100644
--- a/src/FDM/JSBSim/models/propulsion/FGEngine.h
+++ b/src/FDM/JSBSim/models/propulsion/FGEngine.h
@@ -149,7 +149,8 @@ public:
virtual double getFuelFlow_gph () const {return FuelFlow_gph;}
virtual double getFuelFlow_pph () const {return FuelFlow_pph;}
- virtual double GetThrust(void) { return Thrust; }
+ virtual double GetFuelFlowRate(void) const {return FuelFlowRate;}
+ virtual double GetThrust(void) const { return Thrust; }
virtual bool GetStarved(void) { return Starved; }
virtual bool GetRunning(void) const { return Running; }
virtual bool GetCranking(void) { return Cranking; }
@@ -173,25 +174,6 @@ public:
@return Thrust in pounds */
virtual double Calculate(void) {return 0.0;}
- /** Reduces the fuel in the active tanks by the amount required.
- This function should be called from within the
- derived class' Calculate() function before any other calculations are
- done. This base class method removes fuel from the fuel tanks as
- appropriate, and sets the starved flag if necessary. */
- virtual void ConsumeFuel(void);
-
- /** The fuel need is calculated based on power levels and flow rate for that
- power level. It is also turned from a rate into an actual amount (pounds)
- by multiplying it by the delta T and the rate.
- @return Total fuel requirement for this engine in pounds. */
- virtual double CalcFuelNeed(void);
-
- /** The oxidizer need is calculated based on power levels and flow rate for that
- power level. It is also turned from a rate into an actual amount (pounds)
- by multiplying it by the delta T and the rate.
- @return Total oxidizer requirement for this engine in pounds. */
- virtual double CalcOxidizerNeed(void);
-
/// Sets engine placement information
virtual void SetPlacement(FGColumnVector3& location, FGColumnVector3& orientation);
@@ -210,6 +192,19 @@ public:
virtual string GetEngineValues(string delimeter) = 0;
protected:
+ /** Reduces the fuel in the active tanks by the amount required.
+ This function should be called from within the
+ derived class' Calculate() function before any other calculations are
+ done. This base class method removes fuel from the fuel tanks as
+ appropriate, and sets the starved flag if necessary. */
+ virtual void ConsumeFuel(void);
+
+ /** The fuel need is calculated based on power levels and flow rate for that
+ power level. It is also turned from a rate into an actual amount (pounds)
+ by multiplying it by the delta T and the rate.
+ @return Total fuel requirement for this engine in pounds. */
+ virtual double CalcFuelNeed(void);
+
FGPropertyManager* PropertyManager;
string Name;
const int EngineNumber;
@@ -218,15 +213,14 @@ protected:
double EnginePitch;
double EngineYaw;
double SLFuelFlowMax;
- double SLOxiFlowMax;
double MaxThrottle;
double MinThrottle;
double Thrust;
double Throttle;
double Mixture;
- double FuelNeed;
- double OxidizerNeed;
+ double FuelExpended;
+ double FuelFlowRate;
double PctPower;
bool Starter;
bool Starved;
diff --git a/src/FDM/JSBSim/models/propulsion/FGNozzle.cpp b/src/FDM/JSBSim/models/propulsion/FGNozzle.cpp
index 476f4a988..dc397cd7f 100644
--- a/src/FDM/JSBSim/models/propulsion/FGNozzle.cpp
+++ b/src/FDM/JSBSim/models/propulsion/FGNozzle.cpp
@@ -53,6 +53,12 @@ CLASS IMPLEMENTATION
FGNozzle::FGNozzle(FGFDMExec* FDMExec, Element* nozzle_element, int num)
: FGThruster(FDMExec, nozzle_element, num)
{
+ if (nozzle_element->FindElement("area"))
+ Area = nozzle_element->FindElementValueAsNumberConvertTo("area", "FT2");
+ else {
+ cerr << "Fatal Error: Nozzle exit area must be given in nozzle config file." << endl;
+ exit(-1);
+ }
if (nozzle_element->FindElement("pe"))
PE = nozzle_element->FindElementValueAsNumberConvertTo("pe", "PSF");
@@ -60,29 +66,9 @@ FGNozzle::FGNozzle(FGFDMExec* FDMExec, Element* nozzle_element, int num)
cerr << "Fatal Error: Nozzle exit pressure must be given in nozzle config file." << endl;
exit(-1);
}
- if (nozzle_element->FindElement("expr"))
- ExpR = nozzle_element->FindElementValueAsNumber("expr");
- else {
- cerr << "Fatal Error: Nozzle expansion ratio must be given in nozzle config file." << endl;
- exit(-1);
- }
- if (nozzle_element->FindElement("nzl_eff"))
- nzlEff = nozzle_element->FindElementValueAsNumber("nzl_eff");
- else {
- cerr << "Fatal Error: Nozzle efficiency must be given in nozzle config file." << endl;
- exit(-1);
- }
- if (nozzle_element->FindElement("diam"))
- Diameter = nozzle_element->FindElementValueAsNumberConvertTo("diam", "FT");
- else {
- cerr << "Fatal Error: Nozzle diameter must be given in nozzle config file." << endl;
- exit(-1);
- }
Thrust = 0;
Type = ttNozzle;
- Area2 = (Diameter*Diameter/4.0)*M_PI;
- AreaT = Area2/ExpR;
Debug(0);
}
@@ -96,30 +82,18 @@ FGNozzle::~FGNozzle()
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-double FGNozzle::Calculate(double CfPc)
+double FGNozzle::Calculate(double vacThrust)
{
double pAtm = fdmex->GetAtmosphere()->GetPressure();
- if (CfPc > 0)
- Thrust = max((double)0.0, (CfPc * AreaT + (PE - pAtm)*Area2) * nzlEff);
- else
- Thrust = 0.0;
+ Thrust = max((double)0.0, vacThrust - pAtm*Area);
vFn(1) = Thrust * cos(ReverserAngle);
- ThrustCoeff = max((double)0.0, CfPc / ((pAtm - PE) * Area2));
-
return Thrust;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-double FGNozzle::GetPowerRequired(void)
-{
- return PE;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
string FGNozzle::GetThrusterLabels(int id, string delimeter)
{
std::ostringstream buf;
@@ -166,10 +140,7 @@ void FGNozzle::Debug(int from)
if (debug_lvl & 1) { // Standard console startup message output
if (from == 0) { // Constructor
cout << " Nozzle Name: " << Name << endl;
- cout << " Nozzle Exit Pressure = " << PE << endl;
- cout << " Nozzle Expansion Ratio = " << ExpR << endl;
- cout << " Nozzle Efficiency = " << nzlEff << endl;
- cout << " Nozzle Diameter = " << Diameter << endl;
+ cout << " Nozzle Exit Area = " << Area << endl;
}
}
if (debug_lvl & 2 ) { // Instantiation/Destruction notification
diff --git a/src/FDM/JSBSim/models/propulsion/FGNozzle.h b/src/FDM/JSBSim/models/propulsion/FGNozzle.h
index dfa3ffd7d..c9549126b 100644
--- a/src/FDM/JSBSim/models/propulsion/FGNozzle.h
+++ b/src/FDM/JSBSim/models/propulsion/FGNozzle.h
@@ -63,18 +63,14 @@ CLASS DOCUMENTATION
@code
{number}
- {number}
- {number}
- {number}
+ {number}
@endcode
Configuration parameters are:
- pe - Nozzle exit pressure.
- expr - Nozzle expansion ratio, Ae/At, sqft. dimensionless ratio.
- nzl_eff - Nozzle efficiency, 0.0 - 1.0.
- diam - Nozzle diameter.
+ pe - Nozzle design exit pressure.
+ area - Nozzle area at the exit plane.
All parameters MUST be specified.
@@ -94,18 +90,13 @@ public:
/// Destructor
~FGNozzle();
- double Calculate(double CfPc);
- double GetPowerRequired(void);
+ double Calculate(double vacThrust);
string GetThrusterLabels(int id, string delimeter);
string GetThrusterValues(int id, string delimeter);
private:
double PE;
- double ExpR;
- double nzlEff;
- double Diameter;
- double AreaT;
- double Area2;
+ double Area;
void Debug(int from);
};
}
diff --git a/src/FDM/JSBSim/models/propulsion/FGPiston.cpp b/src/FDM/JSBSim/models/propulsion/FGPiston.cpp
index 7f981ce33..e23d981a8 100644
--- a/src/FDM/JSBSim/models/propulsion/FGPiston.cpp
+++ b/src/FDM/JSBSim/models/propulsion/FGPiston.cpp
@@ -82,6 +82,9 @@ FGPiston::FGPiston(FGFDMExec* exec, Element* el, int engine_number)
MaxManifoldPressure_inHg = 28.5;
BSFC = -1;
+ // Initialisation
+ volumetric_efficiency = 0.8; // Actually f(speed, load) but this will get us running
+
// These are internal program variables
crank_counter = 0;
@@ -113,8 +116,6 @@ FGPiston::FGPiston(FGFDMExec* exec, Element* el, int engine_number)
BoostSwitchAltitude[i] = 0.0;
BoostSwitchPressure[i] = 0.0;
}
- // Initialisation
- volumetric_efficiency = 0.8; // Actually f(speed, load) but this will get us running
// First column is thi, second is neta (combustion efficiency)
Lookup_Combustion_Efficiency = new FGTable(12);
@@ -202,7 +203,9 @@ Manifold_Pressure_Lookup = new
if (el->FindElement("minthrottle"))
MinThrottle = el->FindElementValueAsNumber("minthrottle");
if (el->FindElement("bsfc"))
- BSFC = el->FindElementValueAsNumber("bsfc");
+ BSFC = el->FindElementValueAsNumberConvertTo("bsfc", "LBS/HP*HR");
+ if (el->FindElement("volumetric-efficiency"))
+ volumetric_efficiency = el->FindElementValueAsNumber("volumetric-efficiency");
if (el->FindElement("numboostspeeds")) { // Turbo- and super-charging parameters
BoostSpeeds = (int)el->FindElementValueAsNumber("numboostspeeds");
if (el->FindElement("boostoverride"))
@@ -236,16 +239,16 @@ Manifold_Pressure_Lookup = new
}
// Create a BSFC to match the engine if not provided
- // The 0.8 in the equation below is volumetric efficiency
if (BSFC < 0) {
- BSFC = ( Displacement * MaxRPM * 0.8 ) / (9411 * MaxHP);
+ BSFC = ( Displacement * MaxRPM * volumetric_efficiency ) / (9411 * MaxHP);
}
char property_name[80];
- snprintf(property_name, 80, "propulsion/engine[%d]/power_hp", EngineNumber);
+ snprintf(property_name, 80, "propulsion/engine[%d]/power-hp", EngineNumber);
PropertyManager->Tie(property_name, &HP);
- snprintf(property_name, 80, "propulsion/engine[%d]/bsfc", EngineNumber);
+ snprintf(property_name, 80, "propulsion/engine[%d]/bsfc-lbs_hphr", EngineNumber);
PropertyManager->Tie(property_name, &BSFC);
-
+ snprintf(property_name, 80, "propulsion/engine[%d]/volumetric-efficiency", EngineNumber);
+ PropertyManager->Tie(property_name, &volumetric_efficiency);
minMAP = MinManifoldPressure_inHg * inhgtopa; // inHg to Pa
maxMAP = MaxManifoldPressure_inHg * inhgtopa;
StarterHP = sqrt(MaxHP) * 0.4;
@@ -315,7 +318,7 @@ FGPiston::~FGPiston()
void FGPiston::ResetToIC(void)
{
FGEngine::ResetToIC();
-
+
ManifoldPressure_inHg = Atmosphere->GetPressure() * psftoinhg; // psf to in Hg
MAP = Atmosphere->GetPressure() * psftopa;
double airTemperature_degK = RankineToKelvin(Atmosphere->GetTemperature());
@@ -325,6 +328,7 @@ void FGPiston::ResetToIC(void)
EGT_degC = ExhaustGasTemp_degK - 273;
Thruster->SetRPM(0.0);
RPM = 0.0;
+ OilPressure_psi = 0.0;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -385,7 +389,11 @@ if(HP<0.1250)
double FGPiston::CalcFuelNeed(void)
{
- return FuelFlow_gph / 3600 * 6 * State->Getdt() * Propulsion->GetRate();
+ double dT = State->Getdt() * Propulsion->GetRate();
+ FuelFlow_pph = FuelFlow_gph * 6.0; // Assumes 6 lbs / gallon
+ FuelFlowRate = FuelFlow_pph / 3600.0;
+ FuelExpended = FuelFlowRate * dT;
+ return FuelExpended;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -541,7 +549,9 @@ void FGPiston::doMAP(void)
}
}
// Boost the manifold pressure.
- MAP += MAP * BoostMul[BoostSpeed] * suction_loss * RPM/RatedRPM[BoostSpeed];
+ double boost_factor = BoostMul[BoostSpeed] * suction_loss * RPM/RatedRPM[BoostSpeed];
+ if (boost_factor < 1.0) boost_factor = 1.0; // boost will never reduce the MAP
+ MAP *= boost_factor;
// Now clip the manifold pressure to BCV or Wastegate setting.
if(bTakeoffPos) {
if(MAP > TakeoffMAP[BoostSpeed]) {
@@ -574,8 +584,7 @@ void FGPiston::doMAP(void)
void FGPiston::doAirFlow(void)
{
-
-rho_air = p_amb / (R_air * T_amb);
+ rho_air = p_amb / (R_air * T_amb);
double displacement_SI = Displacement * in3tom3;
double swept_volume = (displacement_SI * (RPM/60)) / 2;
double v_dot_air = swept_volume * volumetric_efficiency * suction_loss;
@@ -596,9 +605,10 @@ rho_air = p_amb / (R_air * T_amb);
void FGPiston::doFuelFlow(void)
{
double thi_sea_level = 1.3 * Mixture; // Allows an AFR of infinity:1 to 11.3075:1
- equivalence_ratio = thi_sea_level; // * p_amb_sea_level / p_amb;
- double AFR = 10+(12*(1-Mixture));// mixture 10:1 to 22:1
- m_dot_fuel = m_dot_air / AFR;
+ equivalence_ratio = thi_sea_level * 101325.0 / p_amb;
+// double AFR = 10+(12*(1-Mixture));// mixture 10:1 to 22:1
+// m_dot_fuel = m_dot_air / AFR;
+ m_dot_fuel = (m_dot_air * equivalence_ratio) / 14.7;
FuelFlow_gph = m_dot_fuel
* 3600 // seconds to hours
* 2.2046 // kg to lb
@@ -703,7 +713,7 @@ void FGPiston::doEGT(void)
* Calculate the cylinder head temperature.
*
* Inputs: T_amb, IAS, rho_air, m_dot_fuel, calorific_value_fuel,
- * combustion_efficiency, RPM
+ * combustion_efficiency, RPM, MaxRPM
*
* Outputs: CylinderHeadTemp_degK
*/
@@ -712,7 +722,7 @@ void FGPiston::doCHT(void)
{
double h1 = -95.0;
double h2 = -3.95;
- double h3 = -0.05;
+ double h3 = -140.0; // -0.05 * 2800 (default maxrpm)
double arbitary_area = 1.0;
double CpCylinderHead = 800.0;
@@ -725,7 +735,7 @@ void FGPiston::doCHT(void)
double dqdt_from_combustion =
m_dot_fuel * calorific_value_fuel * combustion_efficiency * 0.33;
double dqdt_forced = (h2 * m_dot_cooling_air * temperature_difference) +
- (h3 * RPM * temperature_difference);
+ (h3 * RPM * temperature_difference / MaxRPM);
double dqdt_free = h1 * temperature_difference;
double dqdt_cylinder_head = dqdt_from_combustion + dqdt_forced + dqdt_free;
@@ -739,7 +749,7 @@ void FGPiston::doCHT(void)
/**
* Calculate the oil temperature.
*
- * Inputs: Percentage_Power, running flag.
+ * Inputs: CylinderHeadTemp_degK, T_amb, OilPressure_psi.
*
* Outputs: OilTemp_degK
*/
@@ -749,15 +759,18 @@ void FGPiston::doOilTemperature(void)
double idle_percentage_power = 0.023; // approximately
double target_oil_temp; // Steady state oil temp at the current engine conditions
double time_constant; // The time constant for the differential equation
+ double efficiency = 0.667; // The aproximate oil cooling system efficiency // FIXME: may vary by engine
- if (Running) {
- target_oil_temp = 363;
- time_constant = 500; // Time constant for engine-on idling.
- if (Percentage_Power > idle_percentage_power) {
- time_constant /= ((Percentage_Power / idle_percentage_power) / 10.0); // adjust for power
- }
+// Target oil temp is interpolated between ambient temperature and Cylinder Head Tempurature
+// target_oil_temp = ( T_amb * efficiency ) + (CylinderHeadTemp_degK *(1-efficiency)) ;
+ target_oil_temp = CylinderHeadTemp_degK + efficiency * (T_amb - CylinderHeadTemp_degK) ;
+
+ if (OilPressure_psi > 5.0 ) {
+ time_constant = 5000 / OilPressure_psi; // Guess at a time constant for circulated oil.
+ // The higher the pressure the faster it reaches
+ // target temperature. Oil pressure should be about
+ // 60 PSI yielding a TC of about 80.
} else {
- target_oil_temp = RankineToKelvin(Atmosphere->GetTemperature());
time_constant = 1000; // Time constant for engine-off; reflects the fact
// that oil is no longer getting circulated
}
@@ -771,7 +784,7 @@ void FGPiston::doOilTemperature(void)
/**
* Calculate the oil pressure.
*
- * Inputs: RPM
+ * Inputs: RPM, MaxRPM, OilTemp_degK
*
* Outputs: OilPressure_psi
*/
diff --git a/src/FDM/JSBSim/models/propulsion/FGPiston.h b/src/FDM/JSBSim/models/propulsion/FGPiston.h
index 14d86e3b0..d4fa080f3 100644
--- a/src/FDM/JSBSim/models/propulsion/FGPiston.h
+++ b/src/FDM/JSBSim/models/propulsion/FGPiston.h
@@ -27,7 +27,7 @@ HISTORY
--------------------------------------------------------------------------------
09/12/2000 JSB Created
10/01/2001 DPM Modified to use equations from Dave Luff's piston model.
-
+11/01/2008 RKJ Modified piston engine model for more general use.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
SENTRY
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
@@ -66,15 +66,19 @@ CLASS DOCUMENTATION
@code
- {number}
- {number}
+ {number}
+ {number}
{number}
+ {number}
{number}
{number}
{number}
+ {number}
{number}
{number}
{number}
+ {number}
+ {number}
{0 | 1}
{number}
{number}
@@ -164,6 +168,7 @@ CLASS DOCUMENTATION
@author Jon S. Berndt (Engine framework code and framework-related mods)
@author Dave Luff (engine operational code)
@author David Megginson (initial porting and additional code)
+ @author Ron Jensen (additional engine code)
@version $Id$
*/
@@ -279,7 +284,7 @@ private:
double minMAP; // Pa
double maxMAP; // Pa
double MAP; // Pa
- double BSFC; // unitless
+ double BSFC; // brake specific fuel consumption [lbs/horsepower*hour
//
// Inputs (in addition to those in FGEngine).
diff --git a/src/FDM/JSBSim/models/propulsion/FGRocket.cpp b/src/FDM/JSBSim/models/propulsion/FGRocket.cpp
index ada946f9d..66390010c 100644
--- a/src/FDM/JSBSim/models/propulsion/FGRocket.cpp
+++ b/src/FDM/JSBSim/models/propulsion/FGRocket.cpp
@@ -57,18 +57,20 @@ FGRocket::FGRocket(FGFDMExec* exec, Element *el, int engine_number)
Element* thrust_table_element = 0;
ThrustTable = 0L;
BurnTime = 0.0;
+ previousFuelNeedPerTank = 0.0;
+ previousOxiNeedPerTank = 0.0;
+ PropellantFlowRate = 0.0;
+ FuelFlowRate = 0.0;
+ OxidizerFlowRate = 0.0;
+ SLOxiFlowMax = 0.0;
+ It = 0.0;
// Defaults
- Variance = 0.0;
MinThrottle = 0.0;
MaxThrottle = 1.0;
- if (el->FindElement("shr"))
- SHR = el->FindElementValueAsNumber("shr");
- if (el->FindElement("max_pc"))
- maxPC = el->FindElementValueAsNumberConvertTo("max_pc", "PSF");
- if (el->FindElement("prop_eff"))
- propEff = el->FindElementValueAsNumber("prop_eff");
+ if (el->FindElement("isp"))
+ Isp = el->FindElementValueAsNumber("isp");
if (el->FindElement("maxthrottle"))
MaxThrottle = el->FindElementValueAsNumber("maxthrottle");
if (el->FindElement("minthrottle"))
@@ -77,21 +79,19 @@ FGRocket::FGRocket(FGFDMExec* exec, Element *el, int engine_number)
SLFuelFlowMax = el->FindElementValueAsNumberConvertTo("slfuelflowmax", "LBS/SEC");
if (el->FindElement("sloxiflowmax"))
SLOxiFlowMax = el->FindElementValueAsNumberConvertTo("sloxiflowmax", "LBS/SEC");
- if (el->FindElement("variance"))
- Variance = el->FindElementValueAsNumber("variance");
thrust_table_element = el->FindElement("thrust_table");
if (thrust_table_element) {
ThrustTable = new FGTable(PropertyManager, thrust_table_element);
}
+ bindmodel();
+
Debug(0);
Type = etRocket;
Flameout = false;
- PC = 0.0;
- kFactor = (2.0*SHR*SHR/(SHR-1.0))*pow(2.0/(SHR+1), (SHR+1)/(SHR-1));
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -105,41 +105,143 @@ FGRocket::~FGRocket(void)
double FGRocket::Calculate(void)
{
- double Cf=0;
+ double dT = State->Getdt()*Propulsion->GetRate();
if (!Flameout && !Starved) ConsumeFuel();
+ PropellantFlowRate = (FuelExpended + OxidizerExpended)/dT;
Throttle = FCS->GetThrottlePos(EngineNumber);
- // If there is a thrust table, it is a function of elapsed burn time. The engine
- // is started when the throttle is advanced to 1.0. After that, it burns
- // without regard to throttle setting. The table returns a value between zero
- // and one, representing the percentage of maximum vacuum thrust being applied.
+ // If there is a thrust table, it is a function of propellant remaining. The
+ // engine is started when the throttle is advanced to 1.0. After that, it
+ // burns without regard to throttle setting. The table returns a value between
+ // zero and one, representing the percentage of maximum vacuum thrust being
+ // applied.
- if (ThrustTable != 0L) {
- if (Throttle == 1 || BurnTime > 0.0) {
+ if (ThrustTable != 0L) { // Thrust table given -> Solid fuel used
+
+ if ((Throttle == 1 || BurnTime > 0.0 ) && !Starved) {
BurnTime += State->Getdt();
+ double TotalEngineFuelAvailable=0.0;
+ for (int i=0; i<(int)SourceTanks.size(); i++)
+ TotalEngineFuelAvailable += Propulsion->GetTank(SourceTanks[i])->GetContents();
+
+ VacThrust = ThrustTable->GetValue(TotalEngineFuelAvailable);
+ } else {
+ VacThrust = 0.0;
+ }
+
+ } else { // liquid fueled rocket assumed
+
+ if (Throttle < MinThrottle || Starved) { // Combustion not supported
+
+ PctPower = Thrust = 0.0; // desired thrust
+ Flameout = true;
+ VacThrust = 0.0;
+
+ } else { // Calculate thrust
+
+ PctPower = Throttle / MaxThrottle; // Min and MaxThrottle range from 0.0 to 1.0, normally.
+ Flameout = false;
+ VacThrust = Isp * PropellantFlowRate;
+
+ }
+
+ } // End thrust calculations
+
+ Thrust = Thruster->Calculate(VacThrust);
+ It += Thrust * dT;
+
+ return Thrust;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+// This overrides the base class ConsumeFuel() function, for special rocket
+// engine processing.
+
+void FGRocket::ConsumeFuel(void)
+{
+ unsigned int i;
+ FGTank* Tank;
+ bool haveOxTanks = false;
+ double Fshortage=0, Oshortage=0, TanksWithFuel=0, TanksWithOxidizer=0;
+
+ if (FuelFreeze) return;
+ if (TrimMode) return;
+
+ // Count how many assigned tanks have fuel for this engine at this time.
+ // If there is/are fuel tanks but no oxidizer tanks, this indicates
+ // a solid rocket is being modeled.
+
+ for (i=0; iGetTank(SourceTanks[i]);
+ switch(Tank->GetType()) {
+ case FGTank::ttFUEL:
+ if (Tank->GetContents() > 0.0 && Tank->GetSelected()) ++TanksWithFuel;
+ break;
+ case FGTank::ttOXIDIZER:
+ haveOxTanks = true;
+ if (Tank->GetContents() > 0.0 && Tank->GetSelected()) ++TanksWithOxidizer;
+ break;
}
- Throttle = ThrustTable->GetValue(BurnTime);
}
- if (Throttle < MinThrottle || Starved) {
- PctPower = Thrust = 0.0; // desired thrust
- Flameout = true;
- PC = 0.0;
+ // If this engine has burned out, it is starved.
+
+ if (TanksWithFuel==0 || (haveOxTanks && TanksWithOxidizer==0)) {
+ Starved = true;
+ return;
+ }
+
+ // Expend fuel from the engine's tanks if the tank is selected as a source
+ // for this engine.
+
+ double fuelNeedPerTank = CalcFuelNeed()/TanksWithFuel;
+ double oxiNeedPerTank = CalcOxidizerNeed()/TanksWithOxidizer;
+
+ for (i=0; iGetTank(SourceTanks[i]);
+ if ( ! Tank->GetSelected()) continue; // If this tank is not selected as a source, skip it.
+ switch(Tank->GetType()) {
+ case FGTank::ttFUEL:
+ Fshortage += Tank->Drain(2.0*fuelNeedPerTank - previousFuelNeedPerTank);
+ previousFuelNeedPerTank = fuelNeedPerTank;
+ break;
+ case FGTank::ttOXIDIZER:
+ Oshortage += Tank->Drain(2.0*oxiNeedPerTank - previousOxiNeedPerTank);
+ previousOxiNeedPerTank = oxiNeedPerTank;
+ break;
+ }
+ }
+
+ if (Fshortage < 0.00 || (haveOxTanks && Oshortage < 0.00)) Starved = true;
+ else Starved = false;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGRocket::CalcFuelNeed(void)
+{
+ double dT = State->Getdt()*Propulsion->GetRate();
+
+ if (ThrustTable != 0L) { // Thrust table given - infers solid fuel
+ FuelFlowRate = VacThrust/Isp; // This calculates wdot (weight flow rate in lbs/sec)
} else {
- PctPower = Throttle / MaxThrottle;
- //todo: remove Variance?
- PC = maxPC*PctPower * (1.0 + Variance * ((double)rand()/(double)RAND_MAX - 0.5));
- // The Cf (below) is CF from Eqn. 3-30, "Rocket Propulsion Elements", Fifth Edition,
- // George P. Sutton. Note that the thruster function GetPowerRequired() might
- // be better called GetResistance() or something; this function returns the
- // nozzle exit pressure.
- Cf = sqrt(kFactor*(1 - pow(Thruster->GetPowerRequired()/(PC), (SHR-1)/SHR)));
- Flameout = false;
+ FuelFlowRate = SLFuelFlowMax*PctPower;
}
- return Thruster->Calculate(Cf*maxPC*PctPower*propEff);
+ FuelExpended = FuelFlowRate*dT; // For this time step ...
+ return FuelExpended;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGRocket::CalcOxidizerNeed(void)
+{
+ double dT = State->Getdt()*Propulsion->GetRate();
+ OxidizerFlowRate = SLOxiFlowMax*PctPower;
+ OxidizerExpended = OxidizerFlowRate*dT;
+ return OxidizerExpended;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -148,7 +250,7 @@ string FGRocket::GetEngineLabels(string delimeter)
{
std::ostringstream buf;
- buf << Name << " Chamber Pressure (engine " << EngineNumber << " in psf)" << delimeter
+ buf << Name << " Total Impulse (engine " << EngineNumber << " in psf)" << delimeter
<< Thruster->GetThrusterLabels(EngineNumber, delimeter);
return buf.str();
@@ -160,11 +262,27 @@ string FGRocket::GetEngineValues(string delimeter)
{
std::ostringstream buf;
- buf << PC << delimeter << Thruster->GetThrusterValues(EngineNumber, delimeter);
+ buf << It << delimeter << Thruster->GetThrusterValues(EngineNumber, delimeter);
return buf.str();
}
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+// This funciton should tie properties to rocket engine specific properties
+// that are not bound in the base class (FGEngine) code.
+//
+void FGRocket::bindmodel()
+{
+ char property_name[80];
+
+ snprintf(property_name, 80, "propulsion/engine[%u]/total-impulse", EngineNumber);
+ PropertyManager->Tie( property_name, this, &FGRocket::GetTotalImpulse);
+ snprintf(property_name, 80, "propulsion/engine[%u]/oxi-flow-rate-pps", EngineNumber);
+ PropertyManager->Tie( property_name, this, &FGRocket::GetOxiFlowRate);
+ snprintf(property_name, 80, "propulsion/engine[%u]/vacuum-thrust_lbs", EngineNumber);
+ PropertyManager->Tie( property_name, this, &FGRocket::GetVacThrust);
+}
+
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// The bitmasked value choices are as follows:
// unset: In this case (the default) JSBSim would only print
@@ -191,14 +309,12 @@ void FGRocket::Debug(int from)
if (debug_lvl & 1) { // Standard console startup message output
if (from == 0) { // Constructor
cout << " Engine Name: " << Name << endl;
- cout << " Specific Heat Ratio = " << SHR << endl;
- cout << " Maximum Chamber Pressure = " << maxPC << endl;
- cout << " Propulsive Efficiency = " << propEff << endl;
- cout << " MaxThrottle = " << MaxThrottle << endl;
- cout << " MinThrottle = " << MinThrottle << endl;
- cout << " FuelFlowMax = " << SLFuelFlowMax << endl;
- cout << " OxiFlowMax = " << SLOxiFlowMax << endl;
- cout << " Variance = " << Variance << endl;
+ cout << " Vacuum Isp = " << Isp << endl;
+ cout << " Maximum Throttle = " << MaxThrottle << endl;
+ cout << " Minimum Throttle = " << MinThrottle << endl;
+ cout << " Fuel Flow (max) = " << SLFuelFlowMax << endl;
+ cout << " Oxidizer Flow (max) = " << SLOxiFlowMax << endl;
+ cout << " Mixture ratio = " << SLOxiFlowMax/SLFuelFlowMax << endl;
}
}
if (debug_lvl & 2 ) { // Instantiation/Destruction notification
diff --git a/src/FDM/JSBSim/models/propulsion/FGRocket.h b/src/FDM/JSBSim/models/propulsion/FGRocket.h
index 3e4479406..afefb5884 100644
--- a/src/FDM/JSBSim/models/propulsion/FGRocket.h
+++ b/src/FDM/JSBSim/models/propulsion/FGRocket.h
@@ -61,10 +61,7 @@ CLASS DOCUMENTATION
/** Models a generic rocket engine.
The rocket engine is modeled given the following parameters:
- - Chamber pressure (in psf)
- - Specific heat ratio (usually about 1.2 for hydrocarbon fuel and LOX)
- - Propulsive efficiency (in percent, from 0 to 1.0)
- - Variance (in percent, from 0 to 1.0, nominally 0.05)
+ - Specific Impulse (in sec)
Additionally, the following control inputs, operating characteristics, and
location are required, as with all other engine types:
@@ -78,12 +75,8 @@ CLASS DOCUMENTATION
Pitch and Yaw
The nozzle exit pressure (p2) is returned via a
- call to FGNozzle::GetPowerRequired(). This exit pressure is used,
- along with chamber pressure and specific heat ratio, to get the
- thrust coefficient for the throttle setting. This thrust
- coefficient is multiplied by the chamber pressure and then passed
- to the nozzle Calculate() routine, where the thrust force is
- determined.
+ call to FGNozzle::GetPowerRequired(). This exit pressure is used
+ to get the at-altitude thrust level.
One can model the thrust of a solid rocket by providing a normalized thrust table
as a function of time. For instance, the space shuttle solid rocket booster
@@ -150,30 +143,62 @@ public:
/** Destructor */
~FGRocket(void);
- /** Determines the thrust coefficient.
- @return thrust coefficient times chamber pressure */
+ /** Determines the thrust.
+ @return thrust */
double Calculate(void);
- /** Gets the chamber pressure.
- @return chamber pressure in psf. */
- double GetChamberPressure(void) {return PC;}
+ /** Gets the total impulse of the rocket.
+ @return The cumulative total impulse of the rocket up to this time.*/
+ double GetTotalImpulse(void) const {return It;}
/** Gets the flame-out status.
The engine will "flame out" if the throttle is set below the minimum
- sustainable setting.
+ sustainable-thrust setting.
@return true if engine has flamed out. */
bool GetFlameout(void) {return Flameout;}
+
+ double GetOxiFlowRate(void) const {return OxidizerFlowRate;}
+
string GetEngineLabels(string delimeter);
string GetEngineValues(string delimeter);
private:
- double SHR;
- double maxPC;
- double propEff;
- double kFactor;
- double Variance;
- double PC;
+ /** Reduces the fuel in the active tanks by the amount required.
+ This function should be called from within the
+ derived class' Calculate() function before any other calculations are
+ done. This base class method removes fuel from the fuel tanks as
+ appropriate, and sets the starved flag if necessary. */
+ void ConsumeFuel(void);
+
+ /** The fuel need is calculated based on power levels and flow rate for that
+ power level. It is also turned from a rate into an actual amount (pounds)
+ by multiplying it by the delta T and the rate.
+ @return Total fuel requirement for this engine in pounds. */
+ double CalcFuelNeed(void);
+
+ /** The oxidizer need is calculated based on power levels and flow rate for that
+ power level. It is also turned from a rate into an actual amount (pounds)
+ by multiplying it by the delta T and the rate.
+ @return Total oxidizer requirement for this engine in pounds. */
+ double CalcOxidizerNeed(void);
+
+ /** Returns the vacuum thrust.
+ @return The vacuum thrust in lbs. */
+ double GetVacThrust(void) const {return VacThrust;}
+
+ void bindmodel(void);
+
+ double Isp; // Vacuum Isp
+ double It;
+ double MxR; // Mixture Ratio
double BurnTime;
+ double VacThrust;
+ double previousFuelNeedPerTank;
+ double previousOxiNeedPerTank;
+ double OxidizerExpended;
+ double SLOxiFlowMax;
+ double OxidizerFlowRate;
+ double PropellantFlowRate;
bool Flameout;
FGTable* ThrustTable;
diff --git a/src/FDM/JSBSim/models/propulsion/FGTank.cpp b/src/FDM/JSBSim/models/propulsion/FGTank.cpp
index 9827c5606..5f99f402e 100644
--- a/src/FDM/JSBSim/models/propulsion/FGTank.cpp
+++ b/src/FDM/JSBSim/models/propulsion/FGTank.cpp
@@ -56,10 +56,11 @@ FGTank::FGTank(FGFDMExec* exec, Element* el, int tank_number)
{
string token;
Element* element;
+ Element* element_Grain;
Area = 1.0;
Temperature = -9999.0;
Auxiliary = exec->GetAuxiliary();
- Radius = Capacity = Contents = Standpipe = 0.0;
+ Radius = Capacity = Contents = Standpipe = Length = InnerRadius = 0.0;
PropertyManager = exec->GetPropertyManager();
vXYZ.InitMatrix();
vXYZ_drain.InitMatrix();
@@ -100,6 +101,44 @@ FGTank::FGTank(FGFDMExec* exec, Element* el, int tank_number)
PctFull = 0;
}
+ // Check whether this is a solid propellant "tank". Initialize it if true.
+
+ grainType = gtUNKNOWN; // This is the default
+
+ element_Grain = el->FindElement("grain_config");
+ if (element_Grain) {
+
+ strGType = element_Grain->GetAttributeValue("type");
+ if (strGType == "CYLINDRICAL") grainType = gtCYLINDRICAL;
+ else if (strGType == "ENDBURNING") grainType = gtENDBURNING;
+ else cerr << "Unknown propellant grain type specified" << endl;
+
+ if (element_Grain->FindElement("length"))
+ Length = element_Grain->FindElementValueAsNumberConvertTo("length", "IN");
+ if (element_Grain->FindElement("bore_diameter"))
+ InnerRadius = element_Grain->FindElementValueAsNumberConvertTo("bore_diameter", "IN")/2.0;
+
+ // Initialize solid propellant values for debug and runtime use.
+
+ switch (grainType) {
+ case gtCYLINDRICAL:
+ if (Radius <= InnerRadius) {
+ cerr << "The bore diameter should be smaller than the total grain diameter!" << endl;
+ exit(-1);
+ }
+ Volume = M_PI * Length * (Radius*Radius - InnerRadius*InnerRadius); // cubic inches
+ break;
+ case gtENDBURNING:
+ Volume = M_PI * Length * Radius * Radius; // cubic inches
+ break;
+ case gtUNKNOWN:
+ cerr << "Unknown grain type found in this rocket engine definition." << endl;
+ exit(-1);
+ }
+ Density = (Contents*lbtoslug)/Volume; // slugs/in^3
+
+ }
+
char property_name[80];
snprintf(property_name, 80, "propulsion/tank[%d]/contents-lbs", TankNumber);
PropertyManager->Tie( property_name, (FGTank*)this, &FGTank::GetContents,
@@ -160,6 +199,9 @@ double FGTank::Drain(double used)
PctFull = 0.0;
Selected = false;
}
+
+ if (grainType != gtUNKNOWN) CalculateInertias();
+
return remaining;
}
@@ -210,6 +252,35 @@ double FGTank::Calculate(double dt)
return Temperature += (dTemp + dTemp); // For now, assume upper/lower the same
}
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+// This function calculates the moments of inertia for a solid propellant
+// grain - either an end burning cylindrical grain or a bored cylindrical
+// grain.
+
+void FGTank::CalculateInertias(void)
+{
+ double Mass = Contents*lbtoslug;
+ double RadSumSqr;
+ double Rad2 = Radius*Radius;
+ Volume = (Contents*lbtoslug)/Density; // in^3
+
+ switch (grainType) {
+ case gtCYLINDRICAL:
+ InnerRadius = sqrt(Rad2 - Volume/(M_PI * Length));
+ RadSumSqr = (Rad2 + InnerRadius*InnerRadius)/144.0;
+ Ixx = 0.5*Mass*RadSumSqr;
+ Iyy = Mass*(3.0*RadSumSqr + Length*Length/144.0)/12.0;
+ break;
+ case gtENDBURNING:
+ Length = Volume/(M_PI*Rad2);
+ Ixx = 0.5*Mass*Rad2/144.0;
+ Iyy = Mass*(3.0*Rad2 + Length*Length)/(144.0*12.0);
+ break;
+ }
+ Izz = Iyy;
+
+}
+
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// The bitmasked value choices are as follows:
// unset: In this case (the default) JSBSim would only print
diff --git a/src/FDM/JSBSim/models/propulsion/FGTank.h b/src/FDM/JSBSim/models/propulsion/FGTank.h
index f9bb0332f..950c0c12a 100644
--- a/src/FDM/JSBSim/models/propulsion/FGTank.h
+++ b/src/FDM/JSBSim/models/propulsion/FGTank.h
@@ -109,6 +109,9 @@ CLASS DOCUMENTATION
@code
+
+ {number}
+
{number}
{number}
@@ -119,7 +122,7 @@ CLASS DOCUMENTATION
{number}
{number}
- {number}
+ {number}
{number}
{number}
{number}
@@ -131,6 +134,8 @@ CLASS DOCUMENTATION
- \b type - One of FUEL or OXIDIZER. This is required.
- \b radius - Equivalent radius of tank for modeling slosh, defaults to inches.
+- \b grain_config type - One of CYLINDRICAL or ENDBURNING.
+- \b length - length of tank for modeling solid fuel propellant grain, defaults to inches.
- \b capacity - Capacity, defaults to pounds.
- \b contents - Initial contents, defaults to pounds.
- \b temperature - Initial temperature, defaults to degrees Fahrenheit.
@@ -236,6 +241,10 @@ public:
is given, otherwise 32 degrees F is returned. */
double GetTemperature(void) {return CelsiusToFahrenheit(Temperature);}
+ double GetIxx(void) {return Ixx;}
+ double GetIyy(void) {return Iyy;}
+ double GetIzz(void) {return Izz;}
+
double GetStandpipe(void) {return Standpipe;}
const FGColumnVector3 GetXYZ(void);
@@ -247,15 +256,25 @@ public:
void SetStandpipe(double amount) { Standpipe = amount; }
enum TankType {ttUNKNOWN, ttFUEL, ttOXIDIZER};
+ enum GrainType {gtUNKNOWN, gtCYLINDRICAL, gtENDBURNING};
private:
TankType Type;
+ GrainType grainType;
int TankNumber;
string type;
+ string strGType;
FGColumnVector3 vXYZ;
FGColumnVector3 vXYZ_drain;
double Capacity;
double Radius;
+ double InnerRadius;
+ double Length;
+ double Volume;
+ double Density;
+ double Ixx;
+ double Iyy;
+ double Izz;
double PctFull;
double Contents, InitialContents;
double Area;
@@ -264,6 +283,7 @@ private:
bool Selected;
FGAuxiliary* Auxiliary;
FGPropertyManager* PropertyManager;
+ void CalculateInertias(void);
void Debug(int from);
};
}
diff --git a/src/FDM/JSBSim/models/propulsion/FGTurbine.cpp b/src/FDM/JSBSim/models/propulsion/FGTurbine.cpp
index be8dc8a19..022d39235 100644
--- a/src/FDM/JSBSim/models/propulsion/FGTurbine.cpp
+++ b/src/FDM/JSBSim/models/propulsion/FGTurbine.cpp
@@ -361,7 +361,10 @@ double FGTurbine::Trim()
double FGTurbine::CalcFuelNeed(void)
{
- return FuelFlow_pph /3600 * State->Getdt() * Propulsion->GetRate();
+ double dT = State->Getdt() * Propulsion->GetRate();
+ FuelFlowRate = FuelFlow_pph / 3600.0; // Calculates flow in lbs/sec from lbs/hr
+ FuelExpended = FuelFlowRate * dT; // Calculates fuel expended in this time step
+ return FuelExpended;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -493,8 +496,6 @@ void FGTurbine::bindmodel()
PropertyManager->Tie( property_name, &N1);
snprintf(property_name, 80, "propulsion/engine[%u]/n2", EngineNumber);
PropertyManager->Tie( property_name, &N2);
- snprintf(property_name, 80, "propulsion/engine[%u]/thrust", EngineNumber);
- PropertyManager->Tie( property_name, this, &FGTurbine::GetThrust);
snprintf(property_name, 80, "propulsion/engine[%u]/injection_cmd", EngineNumber);
PropertyManager->Tie( property_name, (FGTurbine*)this,
&FGTurbine::GetInjection, &FGTurbine::SetInjection);
diff --git a/src/FDM/JSBSim/models/propulsion/FGTurbine.h b/src/FDM/JSBSim/models/propulsion/FGTurbine.h
index 752c622c3..52193db99 100644
--- a/src/FDM/JSBSim/models/propulsion/FGTurbine.h
+++ b/src/FDM/JSBSim/models/propulsion/FGTurbine.h
@@ -169,7 +169,7 @@ public:
double Calculate(void);
double CalcFuelNeed(void);
double GetPowerAvailable(void);
- double GetThrust(void) const {return Thrust;}
+// double GetThrust(void) const {return Thrust;}
/** A lag filter.
Used to control the rate at which values are allowed to change.
@param var a pointer to a variable of type double
diff --git a/src/FDM/JSBSim/models/propulsion/FGTurboProp.cpp b/src/FDM/JSBSim/models/propulsion/FGTurboProp.cpp
index d7be93c91..be304747f 100755
--- a/src/FDM/JSBSim/models/propulsion/FGTurboProp.cpp
+++ b/src/FDM/JSBSim/models/propulsion/FGTurboProp.cpp
@@ -398,7 +398,10 @@ double FGTurboProp::Start(void)
double FGTurboProp::CalcFuelNeed(void)
{
- return FuelFlow_pph /3600 * State->Getdt() * Propulsion->GetRate();
+ double dT = State->Getdt() * Propulsion->GetRate();
+ FuelFlowRate = FuelFlow_pph / 3600.0;
+ FuelExpended = FuelFlowRate * dT;
+ return FuelExpended;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%