case BOOST:
((PistonEngine*)((Thruster*)obj)->getEngine())->setBoost(lval);
break;
+ case WASTEGATE:
+ ((PistonEngine*)((Thruster*)obj)->getEngine())->setWastegate(lval);
+ break;
}
}
}
INCIDENCE, FLAP0, FLAP1, SLAT, SPOILER, VECTOR,
BOOST, CASTERING, PROPPITCH, PROPFEATHER,
COLLECTIVE, CYCLICAIL, CYCLICELE, ROTORENGINEON,
- REVERSE_THRUST };
+ REVERSE_THRUST, WASTEGATE };
enum { OPT_SPLIT = 0x01,
OPT_INVERT = 0x02,
eng->setTurboParams(mul, mp);
}
+ if(a->hasAttribute("supercharger"))
+ eng->setSupercharger(attrb(a, "supercharger"));
+
((PropEngine*)_currObj)->setEngine(eng);
}
_turbo = 1;
_maxMP = 1e6; // No waste gate on non-turbo engines.
+ _wastegate = 1;
+ _charge = 1;
+ _chargeTarget = 1;
// Guess at reasonable values for these guys. Displacements run
// at about 2 cubic inches per horsepower or so, at least for
void PistonEngine::stabilize()
{
_oilTemp = _oilTempTarget;
+ _charge = _chargeTarget;
}
void PistonEngine::integrate(float dt)
{
_oilTemp += (_dOilTempdt * dt);
+
+ // See comments in Jet.cpp for how this decay constant works
+ float decay = 1.5f * 2.3f / _turboLag;
+ _charge = (_charge + dt*decay * _chargeTarget) / (1 + dt*decay);
}
void PistonEngine::calc(float pressure, float temp, float speed)
float B = 0.55620178;
float C = 1.246708471;
float rpm_factor = A * Math::pow(B, rpm_norm) * Math::pow(rpm_norm, C);
+ _chargeTarget = 1 + (_boost * (_turbo-1) * rpm_factor);
+
+ if(_hasSuper) {
+ // Superchargers have no lag
+ _charge = _chargeTarget;
+ } else if(!_running) {
+ // Turbochargers only work when the engine is actually
+ // running. The 25% number is a guesstimate from Vivian.
+ _chargeTarget = 1 + (_chargeTarget - 1) * 0.25;
+ }
// We need to adjust the minimum manifold pressure to get a
// reasonable idle speed (a "closed" throttle doesn't suck a total
// vacuum in real manifolds). This is a hack.
float _minMP = (-0.008 * _turbo ) + 0.1;
+ _mp = pressure * _charge;
+
// Scale to throttle setting, clamp to wastegate
- if(_running) {
- _mp = pressure * (1 + (_boost * (_turbo-1) * rpm_factor));
+ if(_running)
_mp *= _minMP + (1 -_minMP) * _throttle;
- }
if(_mp > _maxMP) _mp = _maxMP;
// The "boost" is the delta above ambient
void setTurboParams(float mul, float maxMP);
void setDisplacement(float d);
void setCompression(float c);
+ void setWastegate(float norm) { _wastegate = norm; }
+ void setSupercharger(float hasSuper) { _hasSuper = hasSuper; }
+ void setTurboLag(float lag) { _turboLag = lag; }
bool isCranking();
float getMP();
float _f0; // "ideal" fuel flow at P0/omega0
float _mixCoeff; // fuel flow per omega at full mixture
float _turbo; // (or super-)charger pressure multiplier
- float _maxMP; // wastegate setting
+ bool _hasSuper; // true indicates gear-driven (not turbo)
+ float _turboLag; // turbo lag time in seconds
+ float _charge; // current {turbo|super}charge multiplier
+ float _chargeTarget; // eventual charge value
+ float _maxMP; // static maximum pressure
+ float _wastegate; // wastegate setting, [0:1]
float _displacement; // piston stroke volume
float _compression; // compression ratio (>1)
_eng->calc(_pressure, _temp, _omega);
_eng->stabilize();
+ // Do it again -- the turbo sets the target MP in the first
+ // run, stabilize sets the current to the target, then we need
+ // to run again to get the correct output torque. Clumsy, but
+ // it works without side effects (other than solver
+ // performance). In the future, the Engine objects should
+ // store state to allow them to do the work themselves.
+ _eng->calc(_pressure, _temp, _omega);
+
// Compute torque as seen by the engine's end of the gearbox.
// The propeller will be moving more slowly (for gear ratios
// less than one), so it's torque will be higher than the