]> git.mxchange.org Git - flightgear.git/blobdiff - src/FDM/YASim/Jet.cpp
YASim now supports the new fuel.nas fuel management system. It
[flightgear.git] / src / FDM / YASim / Jet.cpp
index 001196b53bca8123f14b61d3b57c2217f9fcf745..afbb669cde95956af65c2865aa9757791abaad16 100644 (file)
@@ -5,25 +5,94 @@ namespace yasim {
 
 Jet::Jet()
 {
-    _rho0 = Atmosphere::getStdDensity(0);
-    _thrust = 0;
-    _abThrust = 0;
+    _maxThrust = 0;
+    _abFactor = 1;
     _reheat = 0;
+    _rotControl = 0;
+    _maxRot = 0;
+    _reverseThrust = false;
+
+    // Initialize parameters for an early-ish subsonic turbojet.  More
+    // recent turbofans will typically have a lower vMax, epr0, and
+    // tsfc.
+    _vMax = 800;
+    _epr0 = 3.0;
+    _tsfc = 0.8f;
+    _egt0 = 1050;
+    _n1Min = 55;
+    _n1Max = 102;
+    _n2Min = 73;
+    _n2Max = 103;
+    setSpooling(4); // 4 second spool time? s'bout right.
+
+    // And initialize to an engine that is idling
+    _n1 = _n1Min;
+    _n2 = _n2Min;
+
+    // And sanify the remaining junk, just in case.
+    _running = true;
+    _cranking = false;
+    _fuel = true;
+    _epr = 1;
+    _fuelFlow = 0;
+    _egt = 273;
+    _tempCorrect = 1;
+    _pressureCorrect = 1;
 }
 
 void Jet::stabilize()
 {
-    return; // no-op for now
+    // Just run it for an hour, there's no need to iterate given the
+    // algorithms used.
+    integrate(3600);
+}
+
+void Jet::setMaxThrust(float thrust, float afterburner)
+{
+    _maxThrust = thrust;
+    if(afterburner == 0) _abFactor = 1;
+    else                 _abFactor = afterburner/thrust;
+}
+
+void Jet::setVMax(float spd)
+{
+    _vMax = spd;
+}
+
+void Jet::setTSFC(float tsfc)
+{
+    _tsfc = tsfc;
+}
+
+void Jet::setRPMs(float idleN1, float maxN1, float idleN2, float maxN2)
+{
+    _n1Min = idleN1;
+    _n1Max = maxN1;
+    _n2Min = idleN2;
+    _n2Max = maxN2;
+}
+
+void Jet::setEGT(float takeoffEGT)
+{
+    _egt0 = takeoffEGT;
 }
 
-void Jet::setDryThrust(float thrust)
+void Jet::setEPR(float takeoffEPR)
 {
-    _thrust = thrust;
+    _epr0 = takeoffEPR;
 }
 
-void Jet::setReheatThrust(float thrust)
+void Jet::setSpooling(float time)
 {
-    _abThrust = thrust;
+    // 2.3 = -ln(0.1), i.e. x=2.3 is the 90% point we're defining
+    // The extra fudge factor is there because the N1 speed (which
+    // determines thrust) lags the N2 speed.
+    _decay = 1.5f * 2.3f / time;
+}
+
+void Jet::setVectorAngle(float angle)
+{
+    _maxRot = angle;
 }
 
 void Jet::setReheat(float reheat)
@@ -31,33 +100,137 @@ void Jet::setReheat(float reheat)
     _reheat = Math::clamp(reheat, 0, 1);
 }
 
-void Jet::getThrust(float* out)
+void Jet::setRotation(float rot)
 {
-    float t = _thrust * _throttle;
-    t += (_abThrust - _thrust) * _reheat;
-    t *= _rho / _rho0;
-    Math::mul3(t, _dir, out);
+    if(rot < 0) rot = 0;
+    if(rot > 1) rot = 1;
+    _rotControl = rot;
 }
 
-void Jet::getTorque(float* out)
+float Jet::getN1()
 {
-    out[0] = out[1] = out[2] = 0;
-    return;
+    return _n1 * _tempCorrect;
 }
 
-void Jet::getGyro(float* out)
+float Jet::getN2()
 {
-    out[0] = out[1] = out[2] = 0;
-    return;
+    return _n2 * _tempCorrect;
+}
+
+float Jet::getEPR()
+{
+    return _epr;
+}
+
+float Jet::getEGT()
+{
+    // Exactly zero means "off" -- return the ambient temperature
+    if(_egt == 0) return _temp;
+
+    return _egt * _tempCorrect * _tempCorrect;
 }
 
 float Jet::getFuelFlow()
 {
-    return 0;
+    return _fuelFlow * _pressureCorrect;
 }
 
 void Jet::integrate(float dt)
 {
+    // Sea-level values
+    const static float P0 = Atmosphere::getStdPressure(0);
+    const static float T0 = Atmosphere::getStdTemperature(0);
+    const static float D0 = Atmosphere::getStdDensity(0);
+
+    float speed = -Math::dot3(_wind, _dir);
+
+    float statT, statP, statD;
+    Atmosphere::calcStaticAir(_pressure, _temp, _rho, speed,
+                              &statP, &statT, &statD);
+    _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);
+
+    float maxThrust = _maxThrust * vCorr * (statD/D0);
+    float setThrust = maxThrust * _throttle;
+
+    // Now get a "beta" (i.e. EPR - 1) value.  The output values are
+    // expressed as functions of beta.
+    float ibeta0 = 1/(_epr0 - 1);
+    float betaTarget = (_epr0 - 1) * (setThrust/_maxThrust) * (P0/_pressure)
+       * (_temp/statT);
+    float n2Target = _n2Min + (betaTarget*ibeta0) * (_n2Max - _n2Min);
+
+    // Note that this "first" beta value is used to compute a target
+    // for N2 only Integrate the N2 speed and back-calculate a beta1
+    // target.  The N1 speed will seek to this.
+    _n2 = (_n2 + dt*_decay * n2Target) / (1 + dt*_decay);
+
+    float betaN2 = (_epr0-1) * (_n2 - _n2Min) / (_n2Max - _n2Min);
+    float n1Target = _n1Min + betaN2*ibeta0 * (_n1Max - _n1Min);
+    _n1 = (_n1 + dt*_decay * n1Target) / (1 + dt*_decay);
+
+    // The actual thrust produced is keyed to the N1 speed.  Add the
+    // afterburners in at the end.
+    float betaN1 =  (_epr0-1) * (_n1 - _n1Min) / (_n1Max - _n1Min);
+    _thrust = _maxThrust * betaN1/((_epr0-1)*(P0/_pressure)*(_temp/statT));
+    _thrust *= 1 + _reheat*(_abFactor-1);
+
+    // Finally, calculate the output variables.   Use a 80/20 mix of
+    // the N2/N1 speeds as the key.
+    float beta = 0.8f*betaN2 + 0.2f*betaN1;
+    _epr = beta + 1;
+    float ff0 = _maxThrust*_tsfc*(1/(3600.0f*9.8f)); // takeoff fuel flow, kg/s
+    _fuelFlow = ff0 * beta*ibeta0;
+    _fuelFlow *= 1 + (3.5f * _reheat * _abFactor); // Afterburners take
+                                                 // 3.5 times as much
+                                                 // fuel per thrust unit
+    _egt = T0 + beta*ibeta0 * (_egt0 - T0);
+
+    // Thrust reverse handling:
+    if(_reverseThrust) _thrust *= -_reverseEff;
+}
+
+bool Jet::isRunning()
+{
+    return _running;
+}
+
+bool Jet::isCranking()
+{
+    return _cranking;
+}
+
+void Jet::getThrust(float* out)
+{
+    Math::mul3(_thrust, _dir, out);
+
+    // Rotate about the Y axis for thrust vectoring
+    float angle = _rotControl * _maxRot;
+    float s = Math::sin(angle);
+    float c = Math::cos(angle);
+    float o0 = out[0];
+    out[0] =  c * o0 + s * out[2];
+    out[2] = -s * o0 + c * out[2];
+}
+
+void Jet::getTorque(float* out)
+{
+    out[0] = out[1] = out[2] = 0;
+    return;
+}
+
+void Jet::getGyro(float* out)
+{
+    out[0] = out[1] = out[2] = 0;
     return;
 }