]> git.mxchange.org Git - flightgear.git/blobdiff - src/FDM/YASim/PropEngine.cpp
Add support for a turbo prop condition lever.
[flightgear.git] / src / FDM / YASim / PropEngine.cpp
index 73cca9a10f3c18ac6893eb2400b60b84113fe5fa..74c29f317bda064cfc4eba408e8117abea680d02 100644 (file)
@@ -1,20 +1,22 @@
 #include "Math.hpp"
 #include "Propeller.hpp"
-#include "PistonEngine.hpp"
+#include "Engine.hpp"
 #include "PropEngine.hpp"
 namespace yasim {
 
-PropEngine::PropEngine(Propeller* prop, PistonEngine* eng, float moment)
+PropEngine::PropEngine(Propeller* prop, Engine* eng, float moment)
 {
     // Start off at 500rpm, because the start code doesn't exist yet
-    _omega = 52.3;
+    _omega = 52.3f;
     _dir[0] = 1; _dir[1] = 0; _dir[2] = 0;
 
     _variable = false;
+    _gearRatio = 1;
 
     _prop = prop;
     _eng = eng;
     _moment = moment;
+    _fuel = true;
 }
 
 PropEngine::~PropEngine()
@@ -23,11 +25,28 @@ PropEngine::~PropEngine()
     delete _eng;
 }
 
+void PropEngine::setMagnetos(int pos)
+{
+    _magnetos = pos;
+}
+
 void PropEngine::setAdvance(float advance)
 {
     _advance = Math::clamp(advance, 0, 1);
 }
 
+void PropEngine::setPropPitch(float proppitch)
+{
+    // update Propeller property
+    _prop->setPropPitch(proppitch);
+}
+
+void PropEngine::setPropFeather(int state)
+{
+    // toggle prop feathering on/off
+    _prop->setPropFeather(state);
+}
+
 void PropEngine::setVariableProp(float min, float max)
 {
     _variable = true;
@@ -35,24 +54,42 @@ void PropEngine::setVariableProp(float min, float max)
     _maxOmega = max;
 }
 
+bool PropEngine::isRunning()
+{
+    return _eng->isRunning();
+}
+
+bool PropEngine::isCranking()
+{
+    return _eng->isCranking();
+}
+
 float PropEngine::getOmega()
 {
     return _omega;
 }
 
+void PropEngine::setOmega (float omega)
+{
+    _omega = omega;
+}
+
 void PropEngine::getThrust(float* out)
 {
-    for(int i=0; i<3; i++) out[i] = _thrust[i];    
+    int i;
+    for(i=0; i<3; i++) out[i] = _thrust[i];    
 }
 
 void PropEngine::getTorque(float* out)
 {
-    for(int i=0; i<3; i++) out[i] = _torque[i];
+    int i;
+    for(i=0; i<3; i++) out[i] = _torque[i];
 }
 
 void PropEngine::getGyro(float* out)
 {
-    for(int i=0; i<3; i++) out[i] = _gyro[i];
+    int i;
+    for(i=0; i<3; i++) out[i] = _gyro[i];
 }
 
 float PropEngine::getFuelFlow()
@@ -66,6 +103,12 @@ void PropEngine::stabilize()
     _eng->setThrottle(_throttle);
     _eng->setMixture(_mixture);
 
+    _eng->setStarter(false);
+    _eng->setMagnetos(3);
+
+    bool running_state = _eng->isRunning();
+    _eng->setRunning(true);
+
     if(_variable) {
        _omega = _minOmega + _advance * (_maxOmega - _minOmega);
        _prop->modPitch(1e6); // Start at maximum pitch and move down
@@ -76,26 +119,44 @@ void PropEngine::stabilize()
     bool goingUp = false;
     float step = 10;
     while(true) {
-       float etau, ptau, dummy;
-       _prop->calc(_rho, speed, _omega, &dummy, &ptau);
-       _eng->calc(_P, _T, _omega, &etau, &dummy);
+       float ptau, thrust;
+       _prop->calc(_rho, speed, _omega * _gearRatio, &thrust, &ptau);
+       _eng->calc(_pressure, _temp, _omega);
+        _eng->stabilize();
+
+        // Compute torque as seen by the engine's end of the
+        // gearbox.
+        ptau *= _gearRatio;
+        float etau = _eng->getTorque();
        float tdiff = etau - ptau;
+        
+        Math::mul3(thrust, _dir, _thrust);
 
-       if(Math::abs(tdiff/_moment) < 0.1)
+       if(Math::abs(tdiff/(_moment * _gearRatio)) < 0.1)
            break;
 
        if(tdiff > 0) {
-           if(!goingUp) step *= 0.5;
+           if(!goingUp) step *= 0.5f;
            goingUp = true;
            if(!_variable)  _omega += step;
-           else            _prop->modPitch(1+(step*0.005));
+           else            _prop->modPitch(1+(step*0.005f));
        } else {
-           if(goingUp) step *= 0.5;
+           if(goingUp) step *= 0.5f;
            goingUp = false;
            if(!_variable)  _omega -= step;
-           else            _prop->modPitch(1-(step*0.005));
+           else            _prop->modPitch(1-(step*0.005f));
        }
     }
+
+    // ...and back off
+    _eng->setRunning(running_state);
+}
+
+void PropEngine::init()
+{
+    _omega = 0.01f;
+    _eng->setStarter(false);
+    _eng->setMagnetos(0);
 }
 
 void PropEngine::integrate(float dt)
@@ -105,29 +166,34 @@ void PropEngine::integrate(float dt)
     float propTorque, engTorque, thrust;
 
     _eng->setThrottle(_throttle);
+    _eng->setStarter(_starter);
+    _eng->setMagnetos(_magnetos);
     _eng->setMixture(_mixture);
+    _eng->setFuelState(_fuel);
     
-    _prop->calc(_rho, speed, _omega,
-               &thrust, &propTorque);
-    _eng->calc(_P, _T, _omega, &engTorque, &_fuelFlow);
+    _prop->calc(_rho, speed, _omega * _gearRatio, &thrust, &propTorque);
+    _eng->calc(_pressure, _temp, _omega);
+    _eng->integrate(dt);
+    engTorque = _eng->getTorque();
+    _fuelFlow = _eng->getFuelFlow();
 
     // Turn the thrust into a vector and save it
     Math::mul3(thrust, _dir, _thrust);
 
+    // We do our "RPM" computations on the engine's side of the
+    // world, so modify the moment value accordingly.
+    float momt = _moment * _gearRatio;
+
     // Euler-integrate the RPM.  This doesn't need the full-on
     // Runge-Kutta stuff.
-    float rotacc = (engTorque-propTorque)/Math::abs(_moment);
+    float rotacc = (engTorque-propTorque)/Math::abs(momt);
     _omega += dt * rotacc;
-
-    // Clamp to a 500 rpm idle.  This should probably be settable, and
-    // needs to go away when the startup code gets written.
-    if(_omega < 52.3) _omega = 52.3;
-
-    // FIXME: Integrate the propeller governor here, when that gets
-    // implemented...
+    if (_omega < 0)
+        _omega = 0 - _omega;    // don't allow negative RPM
+                                // FIXME: introduce proper windmilling
 
     // Store the total angular momentum into _gyro
-    Math::mul3(_omega*_moment, _dir, _gyro);
+    Math::mul3(_omega*momt, _dir, _gyro);
 
     // Accumulate the engine torque, it acts on the body as a whole.
     // (Note: engine torque, not propeller torque.  They can be
@@ -137,15 +203,25 @@ void PropEngine::integrate(float dt)
     float tau = _moment < 0 ? engTorque : -engTorque;
     Math::mul3(tau, _dir, _torque);
 
-    // Play with the variable propeller, but only if the propeller is
-    // vaguely stable alread (accelerating less than 100 rpm/s)
-    if(_variable && Math::abs(rotacc) < 20) {
-       float target = _minOmega + _advance*(_maxOmega-_minOmega);
-       float mod = 1.04;
-       if(target > _omega) mod = 1/mod;
-       float diff = Math::abs(target - _omega);
-       if(diff < 1) mod = 1 + (mod-1)*diff;
-       if(thrust < 0) mod = 1;
+    // Iterate the propeller governor, if we have one.  Since engine
+    // torque is basically constant with RPM, we want to make the
+    // propeller torque at the target RPM equal to the engine by
+    // varying the pitch.  Assume the the torque goes as the square of
+    // the RPM (roughly correct) and compute a "target" torque for the
+    // _current_ RPM.  Seek to that.  This is sort of a continuous
+    // Newton-Raphson, basically.
+    if(_variable) {
+       float targetOmega = _minOmega + _advance*(_maxOmega-_minOmega);
+       float ratio2 = (_omega*_omega)/(targetOmega*targetOmega);
+       float targetTorque = engTorque * ratio2;
+
+       float mod = propTorque < targetTorque ? 1.04f : (1.0f/1.04f);
+
+       // Convert to an acceleration here, so that big propellers
+       // don't seek faster than small ones.
+       float diff = Math::abs((propTorque - targetTorque) / momt);
+       if(diff < 10) mod = 1 + (mod-1)*(0.1f*diff);
+
        _prop->modPitch(mod);
     }
 }