]> git.mxchange.org Git - flightgear.git/blobdiff - src/FDM/JSBSim/models/propulsion/FGRocket.cpp
Merge branch 'next' into durk-atc
[flightgear.git] / src / FDM / JSBSim / models / propulsion / FGRocket.cpp
index 7a72c9fe9fd01e45ff62e218c5cc8d9e75c08394..f8fb091cb6344653e5fb35cef2e903bad1cdef54 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.23 2011/01/24 13:01:56 jberndt Exp $";
 static const char *IdHdr = ID_ROCKET;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -60,16 +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;
@@ -77,6 +81,8 @@ FGRocket::FGRocket(FGFDMExec* exec, Element *el, int engine_number)
 
   if (el->FindElement("isp"))
     Isp = el->FindElementValueAsNumber("isp");
+  if (el->FindElement("builduptime"))
+    BuildupTime = el->FindElementValueAsNumber("builduptime");
   if (el->FindElement("maxthrottle"))
     MaxThrottle = el->FindElementValueAsNumber("maxthrottle");
   if (el->FindElement("minthrottle"))
@@ -86,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;
-
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -110,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();
 
@@ -127,7 +142,6 @@ double FGRocket::Calculate(void)
   if (ThrustTable != 0L) { // Thrust table given -> Solid fuel used
 
     if ((Throttle == 1 || BurnTime > 0.0 ) && !Starved) {
-      BurnTime += State->Getdt();
       double TotalEngineFuelBurned=0.0;
       for (int i=0; i<(int)SourceTanks.size(); i++) {
         FGTank* tank = Propulsion->GetTank(i);
@@ -136,7 +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 += FDMExec->GetDeltaT(); // Increment burn time
     } else {
       VacThrust = 0.0;
     }
@@ -164,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();
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -182,21 +202,23 @@ void FGRocket::ConsumeFuel(void)
   double Fshortage=0, Oshortage=0, TanksWithFuel=0, TanksWithOxidizer=0;
 
   if (FuelFreeze) return;
-  if (TrimMode) return;
+  if (FDMExec->GetTrimStatus()) return;
 
   // Count how many assigned tanks have fuel for this engine at this time.
   // If there is/are fuel tanks but no oxidizer tanks, this indicates
   // 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;
     }
   }
@@ -211,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);
@@ -234,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;
   }
@@ -253,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;
@@ -283,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()
@@ -293,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);
+  }
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -330,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