Fuel consumption. Simple implementation without support for tank selection
or engine-specific feeds.
This commit is contained in:
parent
bcf9fa3695
commit
388d714fdc
8 changed files with 60 additions and 4 deletions
|
@ -62,7 +62,28 @@ void Airplane::iterate(float dt)
|
||||||
|
|
||||||
_model.iterate();
|
_model.iterate();
|
||||||
|
|
||||||
// FIXME: Consume fuel
|
// Consume fuel. This is a really simple implementation that
|
||||||
|
// assumes all engines draw equally from all tanks in proportion
|
||||||
|
// to the amount of fuel stored there. Needs to be fixed, but
|
||||||
|
// that has to wait for a decision as to what the property
|
||||||
|
// interface will look like.
|
||||||
|
int i, outOfFuel = 0;
|
||||||
|
float fuelFlow = 0, totalFuel = 0.00001; // <-- overflow protection
|
||||||
|
for(i=0; i<_thrusters.size(); i++)
|
||||||
|
fuelFlow += ((ThrustRec*)_thrusters.get(i))->thruster->getFuelFlow();
|
||||||
|
for(i=0; i<_tanks.size(); i++)
|
||||||
|
totalFuel += ((Tank*)_tanks.get(i))->fill;
|
||||||
|
for(i=0; i<_tanks.size(); i++) {
|
||||||
|
Tank* t = (Tank*)_tanks.get(i);
|
||||||
|
t->fill -= dt * fuelFlow * (t->fill/totalFuel);
|
||||||
|
if(t->fill <= 0) {
|
||||||
|
t->fill = 0;
|
||||||
|
outOfFuel = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(outOfFuel)
|
||||||
|
for(int i=0; i<_thrusters.size(); i++)
|
||||||
|
((ThrustRec*)_thrusters.get(i))->thruster->setFuelState(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
ControlMap* Airplane::getControlMap()
|
ControlMap* Airplane::getControlMap()
|
||||||
|
@ -189,6 +210,11 @@ float Airplane::getFuelDensity(int tank)
|
||||||
return ((Tank*)_tanks.get(tank))->density;
|
return ((Tank*)_tanks.get(tank))->density;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float Airplane::getTankCapacity(int tank)
|
||||||
|
{
|
||||||
|
return ((Tank*)_tanks.get(tank))->cap;
|
||||||
|
}
|
||||||
|
|
||||||
void Airplane::setWeight(float weight)
|
void Airplane::setWeight(float weight)
|
||||||
{
|
{
|
||||||
_emptyWeight = weight;
|
_emptyWeight = weight;
|
||||||
|
@ -298,6 +324,7 @@ void Airplane::setFuelFraction(float frac)
|
||||||
int i;
|
int i;
|
||||||
for(i=0; i<_tanks.size(); i++) {
|
for(i=0; i<_tanks.size(); i++) {
|
||||||
Tank* t = (Tank*)_tanks.get(i);
|
Tank* t = (Tank*)_tanks.get(i);
|
||||||
|
t->fill = frac * t->cap;
|
||||||
_model.getBody()->setMass(t->handle, t->cap * frac);
|
_model.getBody()->setMass(t->handle, t->cap * frac);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,6 +57,7 @@ public:
|
||||||
void setFuelFraction(float frac); // 0-1, total amount of fuel
|
void setFuelFraction(float frac); // 0-1, total amount of fuel
|
||||||
float getFuel(int tank); // in kg!
|
float getFuel(int tank); // in kg!
|
||||||
float getFuelDensity(int tank); // kg/m^3
|
float getFuelDensity(int tank); // kg/m^3
|
||||||
|
float getTankCapacity(int tank);
|
||||||
|
|
||||||
void compile(); // generate point masses & such, then solve
|
void compile(); // generate point masses & such, then solve
|
||||||
void initEngines();
|
void initEngines();
|
||||||
|
|
|
@ -148,7 +148,7 @@ void FGFDM::startElement(const char* name, const XMLAttributes &atts)
|
||||||
float n2max = attrf(a, "n2-max", 103);
|
float n2max = attrf(a, "n2-max", 103);
|
||||||
j->setRPMs(n1min, n1max, n2min, n2max);
|
j->setRPMs(n1min, n1max, n2min, n2max);
|
||||||
|
|
||||||
if(a->hasAttribute("tsfc")) j->setTSFC(attrf(a, "tsfc"));
|
j->setTSFC(attrf(a, "tsfc", 0.8));
|
||||||
if(a->hasAttribute("egt")) j->setEGT(attrf(a, "egt"));
|
if(a->hasAttribute("egt")) j->setEGT(attrf(a, "egt"));
|
||||||
if(a->hasAttribute("epr")) j->setEPR(attrf(a, "epr"));
|
if(a->hasAttribute("epr")) j->setEPR(attrf(a, "epr"));
|
||||||
if(a->hasAttribute("exhaust-speed"))
|
if(a->hasAttribute("exhaust-speed"))
|
||||||
|
@ -328,11 +328,22 @@ void FGFDM::setOutputProperties()
|
||||||
p->prop->setFloatValue(val);
|
p->prop->setFloatValue(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
float fuelDensity = 718.95; // default to gasoline: ~6 lb/gal
|
float totalFuel = 0, totalCap = 0;
|
||||||
|
float fuelDensity = 720; // in kg/m^3, default to gasoline: ~6 lb/gal
|
||||||
for(i=0; i<_airplane.numTanks(); i++) {
|
for(i=0; i<_airplane.numTanks(); i++) {
|
||||||
fuelDensity = _airplane.getFuelDensity(i);
|
fuelDensity = _airplane.getFuelDensity(i);
|
||||||
sprintf(buf, "/consumables/fuel/tank[%d]/level-gal_us", i);
|
sprintf(buf, "/consumables/fuel/tank[%d]/level-gal_us", i);
|
||||||
fgSetFloat(buf, CM2GALS*_airplane.getFuel(i)/fuelDensity);
|
fgSetFloat(buf, CM2GALS*_airplane.getFuel(i)/fuelDensity);
|
||||||
|
sprintf(buf, "/consumables/fuel/tank[%d]/level-lbs", i);
|
||||||
|
fgSetFloat(buf, KG2LBS*_airplane.getFuel(i));
|
||||||
|
totalFuel += _airplane.getFuel(i);
|
||||||
|
totalCap += _airplane.getTankCapacity(i);
|
||||||
|
}
|
||||||
|
if(totalCap != 0) {
|
||||||
|
fgSetFloat("/consumables/fuel/total-fuel-lbs", KG2LBS*totalFuel);
|
||||||
|
fgSetFloat("/consumables/fuel/total-fuel-gals",
|
||||||
|
CM2GALS*totalFuel/fuelDensity);
|
||||||
|
fgSetFloat("/consumables/fuel/total-fuel-norm", totalFuel/totalCap);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(i=0; i<_thrusters.size(); i++) {
|
for(i=0; i<_thrusters.size(); i++) {
|
||||||
|
|
|
@ -31,6 +31,7 @@ Jet::Jet()
|
||||||
// And sanify the remaining junk, just in case.
|
// And sanify the remaining junk, just in case.
|
||||||
_running = true;
|
_running = true;
|
||||||
_cranking = false;
|
_cranking = false;
|
||||||
|
_fuel = true;
|
||||||
_epr = 1;
|
_epr = 1;
|
||||||
_fuelFlow = 0;
|
_fuelFlow = 0;
|
||||||
_egt = 273;
|
_egt = 273;
|
||||||
|
@ -148,6 +149,12 @@ void Jet::integrate(float dt)
|
||||||
_pressureCorrect = statP/P0;
|
_pressureCorrect = statP/P0;
|
||||||
_tempCorrect = Math::sqrt(statT/T0);
|
_tempCorrect = Math::sqrt(statT/T0);
|
||||||
|
|
||||||
|
// Handle running out of fuel. This is a hack. What should
|
||||||
|
// really happen is a simulation of ram air torque on the
|
||||||
|
// turbine. This just forces the engine into ground idle.
|
||||||
|
if(_fuel == false)
|
||||||
|
_throttle = 0;
|
||||||
|
|
||||||
// Linearly taper maxThrust to zero at vMax
|
// Linearly taper maxThrust to zero at vMax
|
||||||
float vCorr = 1 - (speed/_vMax);
|
float vCorr = 1 - (speed/_vMax);
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ PistonEngine::PistonEngine(float power, float speed)
|
||||||
_boost = 1;
|
_boost = 1;
|
||||||
_running = false;
|
_running = false;
|
||||||
_cranking = false;
|
_cranking = false;
|
||||||
|
_fuel = true;
|
||||||
|
|
||||||
// Presume a BSFC (in lb/hour per HP) of 0.45. In SI that becomes
|
// Presume a BSFC (in lb/hour per HP) of 0.45. In SI that becomes
|
||||||
// (2.2 lb/kg, 745.7 W/hp, 3600 sec/hour) 7.62e-08 kg/Ws.
|
// (2.2 lb/kg, 745.7 W/hp, 3600 sec/hour) 7.62e-08 kg/Ws.
|
||||||
|
@ -131,6 +132,8 @@ void PistonEngine::calc(float pressure, float temp, float speed)
|
||||||
{
|
{
|
||||||
if(_magnetos == 0 || speed < 200*RPM2RADPS)
|
if(_magnetos == 0 || speed < 200*RPM2RADPS)
|
||||||
_running = false;
|
_running = false;
|
||||||
|
else if(_fuel == false)
|
||||||
|
_running = false;
|
||||||
else
|
else
|
||||||
_running = true;
|
_running = true;
|
||||||
|
|
||||||
|
@ -157,6 +160,7 @@ void PistonEngine::calc(float pressure, float temp, float speed)
|
||||||
// mixture setting. Not all of this will burn with the same
|
// mixture setting. Not all of this will burn with the same
|
||||||
// efficiency.
|
// efficiency.
|
||||||
_fuelFlow = _mixture * speed * _mixCoeff;
|
_fuelFlow = _mixture * speed * _mixCoeff;
|
||||||
|
if(_fuel == false) _fuelFlow = 0;
|
||||||
|
|
||||||
// How much fuel could be burned with ideal (i.e. uncorrected!)
|
// How much fuel could be burned with ideal (i.e. uncorrected!)
|
||||||
// combustion.
|
// combustion.
|
||||||
|
|
|
@ -16,6 +16,7 @@ public:
|
||||||
void setMagnetos(int magnetos);
|
void setMagnetos(int magnetos);
|
||||||
void setMixture(float mixture);
|
void setMixture(float mixture);
|
||||||
void setBoost(float boost); // fraction of turbo-mul used
|
void setBoost(float boost); // fraction of turbo-mul used
|
||||||
|
void setFuelState(bool hasFuel) { _fuel = hasFuel; }
|
||||||
|
|
||||||
// For solver use
|
// For solver use
|
||||||
void setRunning(bool r);
|
void setRunning(bool r);
|
||||||
|
@ -48,6 +49,7 @@ private:
|
||||||
int _magnetos; // 0=off, 1=right, 2=left, 3=both
|
int _magnetos; // 0=off, 1=right, 2=left, 3=both
|
||||||
float _mixture;
|
float _mixture;
|
||||||
float _boost;
|
float _boost;
|
||||||
|
bool _fuel;
|
||||||
|
|
||||||
// Runtime state/output:
|
// Runtime state/output:
|
||||||
bool _running;
|
bool _running;
|
||||||
|
|
|
@ -15,6 +15,7 @@ PropEngine::PropEngine(Propeller* prop, PistonEngine* eng, float moment)
|
||||||
_prop = prop;
|
_prop = prop;
|
||||||
_eng = eng;
|
_eng = eng;
|
||||||
_moment = moment;
|
_moment = moment;
|
||||||
|
_fuel = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
PropEngine::~PropEngine()
|
PropEngine::~PropEngine()
|
||||||
|
@ -140,6 +141,7 @@ void PropEngine::integrate(float dt)
|
||||||
_eng->setStarter(_starter);
|
_eng->setStarter(_starter);
|
||||||
_eng->setMagnetos(_magnetos);
|
_eng->setMagnetos(_magnetos);
|
||||||
_eng->setMixture(_mixture);
|
_eng->setMixture(_mixture);
|
||||||
|
_eng->setFuelState(_fuel);
|
||||||
|
|
||||||
_prop->calc(_rho, speed, _omega, &thrust, &propTorque);
|
_prop->calc(_rho, speed, _omega, &thrust, &propTorque);
|
||||||
_eng->calc(_pressure, _temp, _omega);
|
_eng->calc(_pressure, _temp, _omega);
|
||||||
|
|
|
@ -31,6 +31,7 @@ public:
|
||||||
void setThrottle(float throttle);
|
void setThrottle(float throttle);
|
||||||
void setMixture(float mixture);
|
void setMixture(float mixture);
|
||||||
void setStarter(bool starter);
|
void setStarter(bool starter);
|
||||||
|
void setFuelState(bool hasFuel) { _fuel = hasFuel; }
|
||||||
|
|
||||||
// Dynamic output
|
// Dynamic output
|
||||||
virtual bool isRunning()=0;
|
virtual bool isRunning()=0;
|
||||||
|
@ -38,7 +39,7 @@ public:
|
||||||
virtual void getThrust(float* out)=0;
|
virtual void getThrust(float* out)=0;
|
||||||
virtual void getTorque(float* out)=0;
|
virtual void getTorque(float* out)=0;
|
||||||
virtual void getGyro(float* out)=0;
|
virtual void getGyro(float* out)=0;
|
||||||
virtual float getFuelFlow()=0;
|
virtual float getFuelFlow()=0; // in kg/s
|
||||||
|
|
||||||
// Runtime instructions
|
// Runtime instructions
|
||||||
void setWind(float* wind);
|
void setWind(float* wind);
|
||||||
|
@ -53,6 +54,7 @@ protected:
|
||||||
float _throttle;
|
float _throttle;
|
||||||
float _mixture;
|
float _mixture;
|
||||||
bool _starter; // true=engaged, false=disengaged
|
bool _starter; // true=engaged, false=disengaged
|
||||||
|
bool _fuel; // true=available, false=out
|
||||||
|
|
||||||
float _wind[3];
|
float _wind[3];
|
||||||
float _pressure;
|
float _pressure;
|
||||||
|
|
Loading…
Reference in a new issue