]> git.mxchange.org Git - flightgear.git/blobdiff - src/FDM/JSBSim/models/propulsion/FGRocket.cpp
Andreas Gaeb: fix #222 (JSBSIm reset problems)
[flightgear.git] / src / FDM / JSBSim / models / propulsion / FGRocket.cpp
index eab01be1529c2d30939481ee56b17e200cd525c4..3fef49616352fd5bf7b8dd73c62030074b2cd498 100644 (file)
@@ -41,7 +41,6 @@ INCLUDES
 #include <iostream>
 #include <sstream>
 #include "FGRocket.h"
-#include "FGState.h"
 #include "models/FGPropulsion.h"
 #include "FGThruster.h"
 #include "FGTank.h"
@@ -50,7 +49,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGRocket.cpp,v 1.22 2010/12/30 13:35:09 jberndt Exp $";
 static const char *IdHdr = ID_ROCKET;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -60,17 +59,21 @@ CLASS IMPLEMENTATION
 FGRocket::FGRocket(FGFDMExec* exec, Element *el, int engine_number)
   : FGEngine(exec, el, engine_number)
 {
+  Type = etRocket;
   Element* thrust_table_element = 0;
   ThrustTable = 0L;
   BurnTime = 0.0;
   previousFuelNeedPerTank = 0.0;
   previousOxiNeedPerTank = 0.0;
   PropellantFlowRate = 0.0;
-  FuelFlowRate = 0.0;
-  OxidizerFlowRate = 0.0;
-  SLOxiFlowMax = 0.0;
+  FuelFlowRate = FuelExpended = 0.0;
+  OxidizerFlowRate = OxidizerExpended = 0.0;
+  SLOxiFlowMax = SLFuelFlowMax = 0.0;
   BuildupTime = 0.0;
   It = 0.0;
+  ThrustVariation = 0.0;
+  TotalIspVariation = 0.0;
+  Flameout = false;
 
   // Defaults
    MinThrottle = 0.0;
@@ -89,18 +92,24 @@ FGRocket::FGRocket(FGFDMExec* exec, Element *el, int engine_number)
   if (el->FindElement("sloxiflowmax"))
     SLOxiFlowMax = el->FindElementValueAsNumberConvertTo("sloxiflowmax", "LBS/SEC");
 
+  // If there is a thrust table element, this is a solid propellant engine.
   thrust_table_element = el->FindElement("thrust_table");
   if (thrust_table_element) {
     ThrustTable = new FGTable(PropertyManager, thrust_table_element);
+    Element* variation_element = el->FindElement("variation");
+    if (variation_element) {
+      if (variation_element->FindElement("thrust")) {
+        ThrustVariation = variation_element->FindElementValueAsNumber("thrust");
+      }
+      if (variation_element->FindElement("total_isp")) {
+        TotalIspVariation = variation_element->FindElementValueAsNumber("total_isp");
+      }
+    }
   }
 
   bindmodel();
 
   Debug(0);
-
-  Type = etRocket;
-  Flameout = false;
-
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -113,10 +122,13 @@ FGRocket::~FGRocket(void)
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-double FGRocket::Calculate(void)
+void FGRocket::Calculate(void)
 {
-  double dT = State->Getdt()*Propulsion->GetRate();
-  double thrust;
+  if (FDMExec->IntegrationSuspended()) return;
+
+  double dT = FDMExec->GetDeltaT()*Propulsion->GetRate();
+
+  RunPreFunctions();
 
   if (!Flameout && !Starved) ConsumeFuel();
 
@@ -138,12 +150,14 @@ double FGRocket::Calculate(void)
         }
       }
 
-      VacThrust = ThrustTable->GetValue(TotalEngineFuelBurned);
+      VacThrust = ThrustTable->GetValue(TotalEngineFuelBurned)
+                * (ThrustVariation + 1)
+                * (TotalIspVariation + 1);
       if (BurnTime <= BuildupTime && BuildupTime > 0.0) {
         VacThrust *= sin((BurnTime/BuildupTime)*M_PI/2.0);
         // VacThrust *= (1-cos((BurnTime/BuildupTime)*M_PI))/2.0; // 1 - cos approach
       }
-      BurnTime += State->Getdt(); // Increment burn time
+      BurnTime += FDMExec->GetDeltaT(); // Increment burn time
     } else {
       VacThrust = 0.0;
     }
@@ -171,10 +185,9 @@ double FGRocket::Calculate(void)
 
   } // End thrust calculations
 
-  thrust = Thruster->Calculate(VacThrust);
-  It += thrust * dT;
+  It += Thruster->Calculate(VacThrust) * dT;
 
-  return thrust;
+  RunPostFunctions();
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -196,14 +209,16 @@ void FGRocket::ConsumeFuel(void)
   // a solid rocket is being modeled.
 
   for (i=0; i<SourceTanks.size(); i++) {
-    Tank = Propulsion->GetTank(SourceTanks[i]);
+    Tank = Propulsion->GetTank(i);
     switch(Tank->GetType()) {
       case FGTank::ttFUEL:
-        if (Tank->GetContents() > 0.0 && Tank->GetSelected()) ++TanksWithFuel;
+        if (Tank->GetContents() > 0.0 && Tank->GetSelected() && SourceTanks[i] > 0) ++TanksWithFuel;
         break;
       case FGTank::ttOXIDIZER:
-        haveOxTanks = true;
-        if (Tank->GetContents() > 0.0 && Tank->GetSelected()) ++TanksWithOxidizer;
+        if (Tank->GetSelected() && SourceTanks[i] > 0) {
+          haveOxTanks = true;
+          if (Tank->GetContents() > 0.0) ++TanksWithOxidizer;
+        }
         break;
     }
   }
@@ -218,12 +233,15 @@ void FGRocket::ConsumeFuel(void)
   // Expend fuel from the engine's tanks if the tank is selected as a source
   // for this engine.
 
-  double fuelNeedPerTank = CalcFuelNeed()/TanksWithFuel;
-  double oxiNeedPerTank = CalcOxidizerNeed()/TanksWithOxidizer;
+  double fuelNeedPerTank = 0;
+  double oxiNeedPerTank = 0;
+
+  if (TanksWithFuel > 0) fuelNeedPerTank = CalcFuelNeed()/TanksWithFuel;
+  if (TanksWithOxidizer > 0) oxiNeedPerTank = CalcOxidizerNeed()/TanksWithOxidizer;
 
   for (i=0; i<SourceTanks.size(); i++) {
-    Tank = Propulsion->GetTank(SourceTanks[i]);
-    if ( ! Tank->GetSelected()) continue; // If this tank is not selected as a source, skip it.
+    Tank = Propulsion->GetTank(i);
+    if ( ! Tank->GetSelected() || SourceTanks[i] == 0) continue; // If this tank is not selected as a source, skip it.
     switch(Tank->GetType()) {
       case FGTank::ttFUEL:
         Fshortage += Tank->Drain(2.0*fuelNeedPerTank - previousFuelNeedPerTank);
@@ -241,13 +259,19 @@ void FGRocket::ConsumeFuel(void)
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+// 
+// The FuelFlowRate can be affected by the TotalIspVariation value (settable
+// in a config file or via properties). The TotalIspVariation parameter affects
+// thrust, but the thrust determines fuel flow rate, so it must be adjusted
+// for Total Isp Variation.
 
 double FGRocket::CalcFuelNeed(void)
 {
-  double dT = State->Getdt()*Propulsion->GetRate();
+  double dT = FDMExec->GetDeltaT()*Propulsion->GetRate();
 
   if (ThrustTable != 0L) {          // Thrust table given - infers solid fuel
     FuelFlowRate = VacThrust/Isp;   // This calculates wdot (weight flow rate in lbs/sec)
+    FuelFlowRate /= (1 + TotalIspVariation);
   } else {
     FuelFlowRate = SLFuelFlowMax*PctPower;
   }
@@ -260,7 +284,7 @@ double FGRocket::CalcFuelNeed(void)
 
 double FGRocket::CalcOxidizerNeed(void)
 {
-  double dT = State->Getdt()*Propulsion->GetRate();
+  double dT = FDMExec->GetDeltaT()*Propulsion->GetRate();
   OxidizerFlowRate = SLOxiFlowMax*PctPower;
   OxidizerExpended = OxidizerFlowRate*dT;
   return OxidizerExpended;
@@ -290,7 +314,7 @@ string FGRocket::GetEngineValues(const string& delimiter)
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-// This funciton should tie properties to rocket engine specific properties
+// This function should tie properties to rocket engine specific properties
 // that are not bound in the base class (FGEngine) code.
 //
 void FGRocket::bindmodel()
@@ -300,10 +324,20 @@ void FGRocket::bindmodel()
 
   property_name = base_property_name + "/total-impulse";
   PropertyManager->Tie( property_name.c_str(), this, &FGRocket::GetTotalImpulse);
-  property_name = base_property_name + "/oxi-flow-rate-pps";
-  PropertyManager->Tie( property_name.c_str(), this, &FGRocket::GetOxiFlowRate);
   property_name = base_property_name + "/vacuum-thrust_lbs";
   PropertyManager->Tie( property_name.c_str(), this, &FGRocket::GetVacThrust);
+
+  if (ThrustTable) { // Solid rocket motor
+    property_name = base_property_name + "/thrust-variation_pct";
+    PropertyManager->Tie( property_name.c_str(), this, &FGRocket::GetThrustVariation,
+                                                       &FGRocket::SetThrustVariation);
+    property_name = base_property_name + "/total-isp-variation_pct";
+    PropertyManager->Tie( property_name.c_str(), this, &FGRocket::GetTotalIspVariation,
+                                                       &FGRocket::SetTotalIspVariation);
+  } else { // Liquid rocket motor
+    property_name = base_property_name + "/oxi-flow-rate-pps";
+    PropertyManager->Tie( property_name.c_str(), this, &FGRocket::GetOxiFlowRate);
+  }
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -337,7 +371,8 @@ void FGRocket::Debug(int from)
       cout << "      Minimum Throttle = " << MinThrottle << endl;
       cout << "      Fuel Flow (max) = " << SLFuelFlowMax << endl;
       cout << "      Oxidizer Flow (max) = " << SLOxiFlowMax << endl;
-      cout << "      Mixture ratio = " << SLOxiFlowMax/SLFuelFlowMax << endl;
+      if (SLFuelFlowMax > 0)
+        cout << "      Mixture ratio = " << SLOxiFlowMax/SLFuelFlowMax << endl;
     }
   }
   if (debug_lvl & 2 ) { // Instantiation/Destruction notification