or engine-specific feeds.
_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()
return ((Tank*)_tanks.get(tank))->density;
}
+float Airplane::getTankCapacity(int tank)
+{
+ return ((Tank*)_tanks.get(tank))->cap;
+}
+
void Airplane::setWeight(float weight)
{
_emptyWeight = weight;
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);
}
}
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();
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"))
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++) {
// And sanify the remaining junk, just in case.
_running = true;
_cranking = false;
+ _fuel = true;
_epr = 1;
_fuelFlow = 0;
_egt = 273;
_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);
_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.
{
if(_magnetos == 0 || speed < 200*RPM2RADPS)
_running = false;
+ else if(_fuel == false)
+ _running = false;
else
_running = true;
// 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.
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);
int _magnetos; // 0=off, 1=right, 2=left, 3=both
float _mixture;
float _boost;
+ bool _fuel;
// Runtime state/output:
bool _running;
_prop = prop;
_eng = eng;
_moment = moment;
+ _fuel = true;
}
PropEngine::~PropEngine()
_eng->setStarter(_starter);
_eng->setMagnetos(_magnetos);
_eng->setMixture(_mixture);
+ _eng->setFuelState(_fuel);
_prop->calc(_rho, speed, _omega, &thrust, &propTorque);
_eng->calc(_pressure, _temp, _omega);
void setThrottle(float throttle);
void setMixture(float mixture);
void setStarter(bool starter);
+ void setFuelState(bool hasFuel) { _fuel = hasFuel; }
// Dynamic output
virtual bool isRunning()=0;
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);
float _throttle;
float _mixture;
bool _starter; // true=engaged, false=disengaged
+ bool _fuel; // true=available, false=out
float _wind[3];
float _pressure;