]> git.mxchange.org Git - flightgear.git/blobdiff - src/FDM/JSBSim/models/FGPropulsion.cpp
sync with JSB JSBSim CVS
[flightgear.git] / src / FDM / JSBSim / models / FGPropulsion.cpp
index 21f469c1fc29c330c425afbd30ec3e40ea13eef1..a721bf7659d6593652983cc6db47fae8d4c000b5 100644 (file)
@@ -44,10 +44,14 @@ HISTORY
 INCLUDES
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
+#include <iostream>
+#include <sstream>
+#include <cstdlib>
+#include <iomanip>
+
+#include "FGFDMExec.h"
 #include "FGPropulsion.h"
-#include "models/FGFCS.h"
 #include "models/FGMassBalance.h"
-#include "models/propulsion/FGThruster.h"
 #include "models/propulsion/FGRocket.h"
 #include "models/propulsion/FGTurbine.h"
 #include "models/propulsion/FGPiston.h"
@@ -57,15 +61,12 @@ INCLUDES
 #include "input_output/FGPropertyManager.h"
 #include "input_output/FGXMLParse.h"
 #include "math/FGColumnVector3.h"
-#include <iostream>
-#include <sstream>
-#include <cstdlib>
 
 using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGPropulsion.cpp,v 1.41 2010/10/15 11:32:41 jberndt Exp $";
+static const char *IdSrc = "$Id: FGPropulsion.cpp,v 1.61 2012/04/14 18:10:44 bcoconni Exp $";
 static const char *IdHdr = ID_PROPULSION;
 
 extern short debug_lvl;
@@ -87,7 +88,7 @@ FGPropulsion::FGPropulsion(FGFDMExec* exec) : FGModel(exec)
   tankJ.InitMatrix();
   refuel = dump = false;
   DumpRate = 0.0;
-  fuel_freeze = false;
+  FuelFreeze = false;
   TotalFuelQuantity = 0.0;
   IsBound =
   HavePistonEngine =
@@ -115,7 +116,7 @@ FGPropulsion::~FGPropulsion()
 
 bool FGPropulsion::InitModel(void)
 {
-  if (!FGModel::InitModel()) return false;
+  bool result = true;
 
   for (unsigned int i=0; i<numTanks; i++) Tanks[i]->ResetToIC();
 
@@ -123,58 +124,173 @@ bool FGPropulsion::InitModel(void)
     switch (Engines[i]->GetType()) {
       case FGEngine::etPiston:
         ((FGPiston*)Engines[i])->ResetToIC();
-        if (HasInitializedEngines && (InitializedEngines & i)) InitRunning(i);
+        try {
+          if (HasInitializedEngines && (InitializedEngines & i)) InitRunning(i);
+        } catch (string str) {
+          cerr << str << endl;
+          result = false;
+        }
         break;
       case FGEngine::etTurbine:
         ((FGTurbine*)Engines[i])->ResetToIC();
-        if (HasInitializedEngines && (InitializedEngines & i)) InitRunning(i);
+        try {
+          if (HasInitializedEngines && (InitializedEngines & i)) InitRunning(i);
+        } catch (string str) {
+          cerr << str << endl;
+          result = false;
+        }
         break;
       default:
         break;
     }
   }
 
-  return true;
+  return result;
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-bool FGPropulsion::Run(void)
+bool FGPropulsion::Run(bool Holding)
 {
   unsigned int i;
 
-  if (FGModel::Run()) return true;
-  if (FDMExec->Holding()) return false;
+  if (FGModel::Run(Holding)) return true;
+  if (Holding) return false;
 
   RunPreFunctions();
 
-  double dt = FDMExec->GetDeltaT();
-
   vForces.InitMatrix();
   vMoments.InitMatrix();
 
   for (i=0; i<numEngines; i++) {
     Engines[i]->Calculate();
+    ConsumeFuel(Engines[i]);
     vForces  += Engines[i]->GetBodyForces();  // sum body frame forces
     vMoments += Engines[i]->GetMoments();     // sum body frame moments
   }
 
   TotalFuelQuantity = 0.0;
   for (i=0; i<numTanks; i++) {
-    Tanks[i]->Calculate( dt * rate );
+    Tanks[i]->Calculate( in.TotalDeltaT, in.TAT_c);
     if (Tanks[i]->GetType() == FGTank::ttFUEL) {
       TotalFuelQuantity += Tanks[i]->GetContents();
     }
   }
 
-  if (refuel) DoRefuel( dt * rate );
-  if (dump) DumpFuel( dt * rate );
+  if (refuel) DoRefuel( in.TotalDeltaT );
+  if (dump) DumpFuel( in.TotalDeltaT );
 
   RunPostFunctions();
 
   return false;
 }
 
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+//
+// The engine can tell us how much fuel it needs, but it is up to the propulsion
+// subsystem manager class FGPropulsion to manage fuel flow amongst tanks. Engines
+// May burn fuel from more than one tank at a time, and may burn from one tank
+// before another - that is, may burn from one tank until the tank is depleted,
+// then burn from the next highest priority tank. This can be accompished
+// by defining a fuel management system, but this way of specifying priorities
+// is more automatic from a user perspective.
+
+void FGPropulsion::ConsumeFuel(FGEngine* engine)
+{
+  if (FuelFreeze) return;
+  if (FDMExec->GetTrimStatus()) return;
+
+  unsigned int TanksWithFuel=0, CurrentFuelTankPriority=1;
+  unsigned int TanksWithOxidizer=0, CurrentOxidizerTankPriority=1;
+  vector <int> FeedListFuel, FeedListOxi;
+  bool Starved = true; // Initially set Starved to true. Set to false in code below.
+  bool hasOxTanks = false;
+
+  // For this engine,
+  // 1) Count how many fuel tanks with the current priority level have fuel
+  // 2) If there none, then try next lower priority (higher number) - that is,
+  //    increment CurrentPriority.
+  // 3) Build the feed list.
+  // 4) Do the same for oxidizer tanks, if needed.
+
+  // Process fuel tanks, if any
+  while ((TanksWithFuel == 0) && (CurrentFuelTankPriority <= numTanks)) {
+    for (unsigned int i=0; i<engine->GetNumSourceTanks(); i++) {
+      unsigned int TankId = engine->GetSourceTank(i);
+      FGTank* Tank = Tanks[TankId];
+      unsigned int TankPriority = Tank->GetPriority();
+      if (TankPriority != 0) {
+        switch(Tank->GetType()) {
+        case FGTank::ttFUEL:
+          if ((Tank->GetContents() > 0.0) && Tank->GetSelected() && (TankPriority == CurrentFuelTankPriority)) {
+            TanksWithFuel++;
+            Starved = false;
+            FeedListFuel.push_back(TankId);
+          } 
+          break;
+        case FGTank::ttOXIDIZER:
+          // Skip this here (done below)
+          break;
+        }
+      }
+    }
+    if (TanksWithFuel == 0) CurrentFuelTankPriority++; // No tanks at this priority, try next priority
+  }
+
+  bool FuelStarved = Starved;
+  Starved = true;
+
+  // Process Oxidizer tanks, if any
+  if (engine->GetType() == FGEngine::etRocket) {
+    while ((TanksWithOxidizer == 0) && (CurrentOxidizerTankPriority <= numTanks)) {
+      for (unsigned int i=0; i<engine->GetNumSourceTanks(); i++) {
+        unsigned int TankId = engine->GetSourceTank(i);
+        FGTank* Tank = Tanks[TankId];
+        unsigned int TankPriority = Tank->GetPriority();
+        if (TankPriority != 0) {
+          switch(Tank->GetType()) {
+          case FGTank::ttFUEL:
+            // Skip this here (done above)
+            break;
+          case FGTank::ttOXIDIZER:
+            hasOxTanks = true;
+            if (Tank->GetContents() > 0.0 && Tank->GetSelected() && TankPriority == CurrentOxidizerTankPriority) {
+              TanksWithOxidizer++;
+              if (TanksWithFuel > 0) Starved = false;
+              FeedListOxi.push_back(TankId);
+            }
+            break;
+          }
+        }
+      }
+      if (TanksWithOxidizer == 0) CurrentOxidizerTankPriority++; // No tanks at this priority, try next priority
+    }
+  }
+
+  bool OxiStarved = Starved;
+
+  engine->SetStarved(FuelStarved || (hasOxTanks && OxiStarved)); // Tanks can be refilled, so be sure to reset engine Starved flag here.
+
+  // No fuel or fuel/oxidizer found at any priority!
+//  if (Starved) return;
+  if (FuelStarved || (hasOxTanks && OxiStarved)) return;
+
+  double FuelToBurn = engine->CalcFuelNeed();            // How much fuel does this engine need?
+  double FuelNeededPerTank = FuelToBurn / TanksWithFuel; // Determine fuel needed per tank.  
+  for (unsigned int i=0; i<FeedListFuel.size(); i++) {
+    Tanks[FeedListFuel[i]]->Drain(FuelNeededPerTank); 
+  }
+
+  if (engine->GetType() == FGEngine::etRocket) {
+    double OxidizerToBurn = engine->CalcOxidizerNeed();                // How much fuel does this engine need?
+    double OxidizerNeededPerTank = OxidizerToBurn / TanksWithOxidizer; // Determine fuel needed per tank.  
+    for (unsigned int i=0; i<FeedListOxi.size(); i++) {
+      Tanks[FeedListOxi[i]]->Drain(OxidizerNeededPerTank); 
+    }
+  }
+
+}
+
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 bool FGPropulsion::GetSteadyState(void)
@@ -182,40 +298,38 @@ bool FGPropulsion::GetSteadyState(void)
   double currentThrust = 0, lastThrust = -1;
   int steady_count = 0, j = 0;
   bool steady = false;
+  bool TrimMode = FDMExec->GetTrimStatus();
 
   vForces.InitMatrix();
   vMoments.InitMatrix();
 
-  if (!FGModel::Run()) {
+  if (!FGModel::Run(false)) {
+    FDMExec->SetTrimStatus(true);
+
     for (unsigned int i=0; i<numEngines; i++) {
-//      cout << "  Finding steady state for engine " << i << endl;
-      Engines[i]->SetTrimMode(true);
       steady=false;
       steady_count=0;
       j=0;
       while (!steady && j < 6000) {
         Engines[i]->Calculate();
         lastThrust = currentThrust;
-        currentThrust = Engines[i]->GetThruster()->GetThrust();
+        currentThrust = Engines[i]->GetThrust();
         if (fabs(lastThrust-currentThrust) < 0.0001) {
           steady_count++;
           if (steady_count > 120) {
             steady=true;
-//            cout << "    Steady state found at thrust: " << currentThrust << " lbs." << endl;
           }
         } else {
           steady_count=0;
         }
         j++;
       }
-//      if (j >= 6000) {
-//        cout << "    Could not find a steady state for this engine." << endl;
-//      }
       vForces  += Engines[i]->GetBodyForces();  // sum body frame forces
       vMoments += Engines[i]->GetMoments();     // sum body frame moments
-      Engines[i]->SetTrimMode(false);
     }
 
+    FDMExec->SetTrimStatus(TrimMode);
+
     return false;
   } else {
     return true;
@@ -226,14 +340,15 @@ bool FGPropulsion::GetSteadyState(void)
 
 void FGPropulsion::InitRunning(int n)
 {
-  if (n > 0) { // A specific engine is supposed to be initialized
+  if (n >= 0) { // A specific engine is supposed to be initialized
 
     if (n >= (int)GetNumEngines() ) {
-      cerr << "Tried to initialize a non-existent engine!" << endl;
-      throw;
+      throw(string("Tried to initialize a non-existent engine!"));
     }
-    FCS->SetThrottleCmd(n,1);
-    FCS->SetMixtureCmd(n,1);
+
+    in.ThrottleCmd[n] = in.ThrottlePos[n] = 1; // Set the throttle command and position
+    in.MixtureCmd[n] = in.MixturePos[n] = 1;   // Set the mixture command and position
+
     GetEngine(n)->InitRunning();
     GetSteadyState();
 
@@ -243,16 +358,14 @@ void FGPropulsion::InitRunning(int n)
   } else if (n < 0) { // -1 refers to "All Engines"
 
     for (unsigned int i=0; i<GetNumEngines(); i++) {
-      FCS->SetThrottleCmd(i,1);
-      FCS->SetMixtureCmd(i,1);
+      in.ThrottleCmd[i] = in.ThrottlePos[i] = 1; // Set the throttle command and position
+      in.MixtureCmd[i] = in.MixturePos[i] = 1;   // Set the mixture command and position
       GetEngine(i)->InitRunning();
     }
+
     GetSteadyState();
     InitializedEngines = -1;
     HasInitializedEngines = true;
-
-  } else if (n == 0) { // No engines are to be initialized
-    // Do nothing
   }
 }
 
@@ -261,7 +374,6 @@ void FGPropulsion::InitRunning(int n)
 bool FGPropulsion::Load(Element* el)
 {
   string type, engine_filename;
-  bool ThrottleAdded = false;
 
   Debug(2);
 
@@ -291,6 +403,11 @@ bool FGPropulsion::Load(Element* el)
     }
 
     engine_filename = FindEngineFullPathname(engine_filename);
+    if (engine_filename.empty()) {
+      // error message already printed by FindEngineFullPathname()
+      return false;
+    }
+
     document = LoadXMLDocument(engine_filename);
     document->SetParent(engine_element);
 
@@ -299,23 +416,23 @@ bool FGPropulsion::Load(Element* el)
       if (type == "piston_engine") {
         HavePistonEngine = true;
         if (!IsBound) bind();
-        Engines.push_back(new FGPiston(FDMExec, document, numEngines));
+        Engines.push_back(new FGPiston(FDMExec, document, numEngines, in));
       } else if (type == "turbine_engine") {
         HaveTurbineEngine = true;
         if (!IsBound) bind();
-        Engines.push_back(new FGTurbine(FDMExec, document, numEngines));
+        Engines.push_back(new FGTurbine(FDMExec, document, numEngines, in));
       } else if (type == "turboprop_engine") {
         HaveTurboPropEngine = true;
         if (!IsBound) bind();
-        Engines.push_back(new FGTurboProp(FDMExec, document, numEngines));
+        Engines.push_back(new FGTurboProp(FDMExec, document, numEngines, in));
       } else if (type == "rocket_engine") {
         HaveRocketEngine = true;
         if (!IsBound) bind();
-        Engines.push_back(new FGRocket(FDMExec, document, numEngines));
+        Engines.push_back(new FGRocket(FDMExec, document, numEngines, in));
       } else if (type == "electric_engine") {
         HaveElectricEngine = true;
         if (!IsBound) bind();
-        Engines.push_back(new FGElectric(FDMExec, document, numEngines));
+        Engines.push_back(new FGElectric(FDMExec, document, numEngines, in));
       } else {
         cerr << "Unknown engine type: " << type << endl;
         exit(-5);
@@ -325,9 +442,6 @@ bool FGPropulsion::Load(Element* el)
       return false;
     }
 
-    FCS->AddThrottle();
-    ThrottleAdded = true;
-
     numEngines++;
 
     engine_element = el->FindNextElement("engine");
@@ -335,7 +449,6 @@ bool FGPropulsion::Load(Element* el)
   }
 
   CalculateTankInertias();
-  if (!ThrottleAdded) FCS->AddThrottle(); // need to have at least one throttle
 
   // Process fuel dump rate
   if (el->FindElement("dump-rate"))
@@ -360,18 +473,18 @@ string FGPropulsion::FindEngineFullPathname(const string& engine_filename)
   fullpath = enginePath + separator;
   localpath = aircraftPath + separator + "Engines" + separator;
 
-  engine_file.open(string(fullpath + engine_filename + ".xml").c_str());
+  engine_file.open(string(localpath + engine_filename + ".xml").c_str());
   if ( !engine_file.is_open()) {
-    engine_file.open(string(localpath + engine_filename + ".xml").c_str());
+    engine_file.open(string(fullpath + engine_filename + ".xml").c_str());
       if ( !engine_file.is_open()) {
         cerr << " Could not open engine file: " << engine_filename << " in path "
              << fullpath << " or " << localpath << endl;
         return string("");
       } else {
-        return string(localpath + engine_filename + ".xml");
+        return string(fullpath + engine_filename + ".xml");
       }
   }
-  return string(fullpath + engine_filename + ".xml");
+  return string(localpath + engine_filename + ".xml");
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -388,12 +501,12 @@ ifstream* FGPropulsion::FindEngineFile(const string& engine_filename)
   fullpath = enginePath + separator;
   localpath = aircraftPath + separator + "Engines" + separator;
 
-  engine_file->open(string(fullpath + engine_filename + ".xml").c_str());
+  engine_file->open(string(localpath + engine_filename + ".xml").c_str());
   if ( !engine_file->is_open()) {
-    engine_file->open(string(localpath + engine_filename + ".xml").c_str());
+    engine_file->open(string(fullpath + engine_filename + ".xml").c_str());
       if ( !engine_file->is_open()) {
         cerr << " Could not open engine file: " << engine_filename << " in path "
-             << fullpath << " or " << localpath << endl;
+             << localpath << " or " << fullpath << endl;
       }
   }
   return engine_file;
@@ -401,7 +514,7 @@ ifstream* FGPropulsion::FindEngineFile(const string& engine_filename)
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-string FGPropulsion::GetPropulsionStrings(const string& delimiter)
+string FGPropulsion::GetPropulsionStrings(const string& delimiter) const
 {
   unsigned int i;
 
@@ -420,12 +533,15 @@ string FGPropulsion::GetPropulsionStrings(const string& delimiter)
     else if (Tanks[i]->GetType() == FGTank::ttOXIDIZER) buf << delimiter << "Oxidizer Tank " << i;
   }
 
+  PropulsionStrings += buf.str();
+  buf.str("");
+
   return PropulsionStrings;
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-string FGPropulsion::GetPropulsionValues(const string& delimiter)
+string FGPropulsion::GetPropulsionValues(const string& delimiter) const
 {
   unsigned int i;
 
@@ -444,25 +560,54 @@ string FGPropulsion::GetPropulsionValues(const string& delimiter)
     buf << Tanks[i]->GetContents();
   }
 
+  PropulsionValues += buf.str();
+  buf.str("");
+
   return PropulsionValues;
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-FGColumnVector3& FGPropulsion::GetTanksMoment(void)
+string FGPropulsion::GetPropulsionTankReport()
+{
+  string out="";
+  stringstream outstream;
+  for (unsigned int i=0; i<numTanks; i++)
+  {
+    FGTank* tank = Tanks[i];
+    string tankname="";
+    if (tank->GetType() == FGTank::ttFUEL && tank->GetGrainType() != FGTank::gtUNKNOWN) {
+      tankname = "Solid Fuel";
+    } else if (tank->GetType() == FGTank::ttFUEL) {
+      tankname = "Fuel";
+    } else if (tank->GetType() == FGTank::ttOXIDIZER) {
+      tankname = "Oxidizer";
+    } else {
+      tankname = "(Unknown tank type)";
+    }
+    outstream << highint << left << setw(4) << i << setw(30) << tankname << normint
+      << right << setw(10) << tank->GetContents() << setw(8) << tank->GetXYZ(eX)
+         << setw(8) << tank->GetXYZ(eY) << setw(8) << tank->GetXYZ(eZ)
+         << setw(12) << "*" << setw(12) << "*"
+         << setw(12) << "*" << endl;
+  }
+  return outstream.str();
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+const FGColumnVector3& FGPropulsion::GetTanksMoment(void)
 {
   vXYZtank_arm.InitMatrix();
   for (unsigned int i=0; i<Tanks.size(); i++) {
-    vXYZtank_arm(eX) += Tanks[i]->GetXYZ(eX) * Tanks[i]->GetContents();
-    vXYZtank_arm(eY) += Tanks[i]->GetXYZ(eY) * Tanks[i]->GetContents();
-    vXYZtank_arm(eZ) += Tanks[i]->GetXYZ(eZ) * Tanks[i]->GetContents();
+    vXYZtank_arm += Tanks[i]->GetXYZ() * Tanks[i]->GetContents();
   }
   return vXYZtank_arm;
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-double FGPropulsion::GetTanksWeight(void)
+double FGPropulsion::GetTanksWeight(void) const
 {
   double Tw = 0.0;
 
@@ -473,8 +618,9 @@ double FGPropulsion::GetTanksWeight(void)
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-FGMatrix33& FGPropulsion::CalculateTankInertias(void)
+const FGMatrix33& FGPropulsion::CalculateTankInertias(void)
 {
+  const FGMatrix33 Ts2b(-inchtoft, 0., 0., 0., inchtoft, 0., 0., 0., -inchtoft);
   unsigned int size;
 
   size = Tanks.size();
@@ -483,8 +629,10 @@ FGMatrix33& FGPropulsion::CalculateTankInertias(void)
   tankJ = FGMatrix33();
 
   for (unsigned int i=0; i<size; i++) {
-    tankJ += MassBalance->GetPointmassInertia( lbtoslug * Tanks[i]->GetContents(),
-                                               Tanks[i]->GetXYZ() );
+    FGColumnVector3 vTankBodyVec = Ts2b * (in.vXYZcg - Tanks[i]->GetXYZ());
+
+    tankJ += FDMExec->GetMassBalance()->GetPointmassInertia( lbtoslug * Tanks[i]->GetContents(),
+                                                             vTankBodyVec);
     tankJ(1,1) += Tanks[i]->GetIxx();
     tankJ(2,2) += Tanks[i]->GetIyy();
     tankJ(3,3) += Tanks[i]->GetIzz();
@@ -623,7 +771,7 @@ void FGPropulsion::DumpFuel(double time_slice)
 
 void FGPropulsion::SetFuelFreeze(bool f)
 {
-  fuel_freeze = f;
+  FuelFreeze = f;
   for (unsigned int i=0; i<numEngines; i++) {
     Engines[i]->SetFuelFreeze(f);
   }
@@ -637,15 +785,15 @@ void FGPropulsion::bind(void)
   typedef int (FGPropulsion::*iPMF)(void) const;
 
   IsBound = true;
-  PropertyManager->Tie("propulsion/set-running", this, (iPMF)0, &FGPropulsion::InitRunning, true);
+  PropertyManager->Tie("propulsion/set-running", this, (iPMF)0, &FGPropulsion::InitRunning, false);
   if (HaveTurbineEngine) {
-    PropertyManager->Tie("propulsion/starter_cmd", this, (iPMF)0, &FGPropulsion::SetStarter,  true);
-    PropertyManager->Tie("propulsion/cutoff_cmd", this,  (iPMF)0, &FGPropulsion::SetCutoff,   true);
+    PropertyManager->Tie("propulsion/starter_cmd", this, (iPMF)0, &FGPropulsion::SetStarter,  false);
+    PropertyManager->Tie("propulsion/cutoff_cmd", this,  (iPMF)0, &FGPropulsion::SetCutoff,   false);
   }
 
   if (HavePistonEngine) {
-    PropertyManager->Tie("propulsion/starter_cmd", this, (iPMF)0, &FGPropulsion::SetStarter,  true);
-    PropertyManager->Tie("propulsion/magneto_cmd", this, (iPMF)0, &FGPropulsion::SetMagnetos, true);
+    PropertyManager->Tie("propulsion/starter_cmd", this, (iPMF)0, &FGPropulsion::SetStarter,  false);
+    PropertyManager->Tie("propulsion/magneto_cmd", this, (iPMF)0, &FGPropulsion::SetMagnetos, false);
   }
 
   PropertyManager->Tie("propulsion/active_engine", this, (iPMF)&FGPropulsion::GetActiveEngine,