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();
|
||||
|
||||
// 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()
|
||||
|
@ -189,6 +210,11 @@ float Airplane::getFuelDensity(int tank)
|
|||
return ((Tank*)_tanks.get(tank))->density;
|
||||
}
|
||||
|
||||
float Airplane::getTankCapacity(int tank)
|
||||
{
|
||||
return ((Tank*)_tanks.get(tank))->cap;
|
||||
}
|
||||
|
||||
void Airplane::setWeight(float weight)
|
||||
{
|
||||
_emptyWeight = weight;
|
||||
|
@ -298,6 +324,7 @@ void Airplane::setFuelFraction(float frac)
|
|||
int i;
|
||||
for(i=0; i<_tanks.size(); i++) {
|
||||
Tank* t = (Tank*)_tanks.get(i);
|
||||
t->fill = frac * t->cap;
|
||||
_model.getBody()->setMass(t->handle, t->cap * frac);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,6 +57,7 @@ public:
|
|||
void setFuelFraction(float frac); // 0-1, total amount of fuel
|
||||
float getFuel(int tank); // in kg!
|
||||
float getFuelDensity(int tank); // kg/m^3
|
||||
float getTankCapacity(int tank);
|
||||
|
||||
void compile(); // generate point masses & such, then solve
|
||||
void initEngines();
|
||||
|
|
|
@ -148,7 +148,7 @@ void FGFDM::startElement(const char* name, const XMLAttributes &atts)
|
|||
float n2max = attrf(a, "n2-max", 103);
|
||||
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("epr")) j->setEPR(attrf(a, "epr"));
|
||||
if(a->hasAttribute("exhaust-speed"))
|
||||
|
@ -328,11 +328,22 @@ void FGFDM::setOutputProperties()
|
|||
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++) {
|
||||
fuelDensity = _airplane.getFuelDensity(i);
|
||||
sprintf(buf, "/consumables/fuel/tank[%d]/level-gal_us", i);
|
||||
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++) {
|
||||
|
|
|
@ -31,6 +31,7 @@ Jet::Jet()
|
|||
// And sanify the remaining junk, just in case.
|
||||
_running = true;
|
||||
_cranking = false;
|
||||
_fuel = true;
|
||||
_epr = 1;
|
||||
_fuelFlow = 0;
|
||||
_egt = 273;
|
||||
|
@ -148,6 +149,12 @@ void Jet::integrate(float dt)
|
|||
_pressureCorrect = statP/P0;
|
||||
_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
|
||||
float vCorr = 1 - (speed/_vMax);
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ PistonEngine::PistonEngine(float power, float speed)
|
|||
_boost = 1;
|
||||
_running = false;
|
||||
_cranking = false;
|
||||
_fuel = true;
|
||||
|
||||
// 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.
|
||||
|
@ -131,6 +132,8 @@ void PistonEngine::calc(float pressure, float temp, float speed)
|
|||
{
|
||||
if(_magnetos == 0 || speed < 200*RPM2RADPS)
|
||||
_running = false;
|
||||
else if(_fuel == false)
|
||||
_running = false;
|
||||
else
|
||||
_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
|
||||
// efficiency.
|
||||
_fuelFlow = _mixture * speed * _mixCoeff;
|
||||
if(_fuel == false) _fuelFlow = 0;
|
||||
|
||||
// How much fuel could be burned with ideal (i.e. uncorrected!)
|
||||
// combustion.
|
||||
|
|
|
@ -16,6 +16,7 @@ public:
|
|||
void setMagnetos(int magnetos);
|
||||
void setMixture(float mixture);
|
||||
void setBoost(float boost); // fraction of turbo-mul used
|
||||
void setFuelState(bool hasFuel) { _fuel = hasFuel; }
|
||||
|
||||
// For solver use
|
||||
void setRunning(bool r);
|
||||
|
@ -48,6 +49,7 @@ private:
|
|||
int _magnetos; // 0=off, 1=right, 2=left, 3=both
|
||||
float _mixture;
|
||||
float _boost;
|
||||
bool _fuel;
|
||||
|
||||
// Runtime state/output:
|
||||
bool _running;
|
||||
|
|
|
@ -15,6 +15,7 @@ PropEngine::PropEngine(Propeller* prop, PistonEngine* eng, float moment)
|
|||
_prop = prop;
|
||||
_eng = eng;
|
||||
_moment = moment;
|
||||
_fuel = true;
|
||||
}
|
||||
|
||||
PropEngine::~PropEngine()
|
||||
|
@ -140,6 +141,7 @@ void PropEngine::integrate(float dt)
|
|||
_eng->setStarter(_starter);
|
||||
_eng->setMagnetos(_magnetos);
|
||||
_eng->setMixture(_mixture);
|
||||
_eng->setFuelState(_fuel);
|
||||
|
||||
_prop->calc(_rho, speed, _omega, &thrust, &propTorque);
|
||||
_eng->calc(_pressure, _temp, _omega);
|
||||
|
|
|
@ -31,6 +31,7 @@ public:
|
|||
void setThrottle(float throttle);
|
||||
void setMixture(float mixture);
|
||||
void setStarter(bool starter);
|
||||
void setFuelState(bool hasFuel) { _fuel = hasFuel; }
|
||||
|
||||
// Dynamic output
|
||||
virtual bool isRunning()=0;
|
||||
|
@ -38,7 +39,7 @@ public:
|
|||
virtual void getThrust(float* out)=0;
|
||||
virtual void getTorque(float* out)=0;
|
||||
virtual void getGyro(float* out)=0;
|
||||
virtual float getFuelFlow()=0;
|
||||
virtual float getFuelFlow()=0; // in kg/s
|
||||
|
||||
// Runtime instructions
|
||||
void setWind(float* wind);
|
||||
|
@ -53,6 +54,7 @@ protected:
|
|||
float _throttle;
|
||||
float _mixture;
|
||||
bool _starter; // true=engaged, false=disengaged
|
||||
bool _fuel; // true=available, false=out
|
||||
|
||||
float _wind[3];
|
||||
float _pressure;
|
||||
|
|
Loading…
Reference in a new issue