]> git.mxchange.org Git - flightgear.git/blobdiff - src/FDM/JSBSim/models/propulsion/FGTurboProp.cpp
Merge branch 'next' into durk-atc
[flightgear.git] / src / FDM / JSBSim / models / propulsion / FGTurboProp.cpp
index 6191e21492f80d535287117469c1ba8d020c3aab..acc35cca2a324de58d57bba690837be9398fee0c 100755 (executable)
@@ -34,6 +34,7 @@ based on parameters given in the engine config file for this class
 HISTORY
 --------------------------------------------------------------------------------
 05/14/2004  Created
+02/08/2011  T. Kreitler, added rotor support
 
 //JVK (mark)
 
@@ -41,15 +42,19 @@ HISTORY
 INCLUDES
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#include <vector>
+#include <iostream>
 #include <sstream>
 #include "FGTurboProp.h"
-
 #include "FGPropeller.h"
+#include "FGRotor.h"
+#include "models/FGPropulsion.h"
+#include "models/FGAuxiliary.h"
+
+using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGTurboProp.cpp,v 1.19 2011/03/10 01:35:25 dpculp Exp $";
 static const char *IdHdr = ID_TURBOPROP;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -57,11 +62,14 @@ CLASS IMPLEMENTATION
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
 FGTurboProp::FGTurboProp(FGFDMExec* exec, Element *el, int engine_number)
-  : FGEngine(exec, el, engine_number)
+  : FGEngine(exec, el, engine_number),
+    ITT_N1(NULL), EnginePowerRPM_N1(NULL), EnginePowerVC(NULL)
 {
   SetDefaults();
+  thrusterType = Thruster->GetType();
 
   Load(exec, el);
+  bindmodel();
   Debug(0);
 }
 
@@ -69,6 +77,9 @@ FGTurboProp::FGTurboProp(FGFDMExec* exec, Element *el, int engine_number)
 
 FGTurboProp::~FGTurboProp()
 {
+  delete ITT_N1;
+  delete EnginePowerRPM_N1;
+  delete EnginePowerVC;
   Debug(1);
 }
 
@@ -76,9 +87,6 @@ FGTurboProp::~FGTurboProp()
 
 bool FGTurboProp::Load(FGFDMExec* exec, Element *el)
 {
-  char property_prefix[80];
-  snprintf(property_prefix, 80, "propulsion/engine[%u]/", EngineNumber);
-
   IdleFF=-1;
   MaxStartingTime = 999999; //very big timeout -> infinite
   Ielu_max_torque=-1;
@@ -90,13 +98,14 @@ bool FGTurboProp::Load(FGFDMExec* exec, Element *el)
   if (el->FindElement("idlen1"))
     IdleN1 = el->FindElementValueAsNumber("idlen1");
   if (el->FindElement("idlen2"))
-    IdleN2 = el->FindElementValueAsNumber("idlen1");
+    IdleN2 = el->FindElementValueAsNumber("idlen2");
   if (el->FindElement("maxn1"))
     MaxN1 = el->FindElementValueAsNumber("maxn1");
   if (el->FindElement("maxn2"))
     MaxN2 = el->FindElementValueAsNumber("maxn2");
   if (el->FindElement("betarangeend"))
     BetaRangeThrottleEnd = el->FindElementValueAsNumber("betarangeend")/100.0;
+  BetaRangeThrottleEnd = Constrain(0.0, BetaRangeThrottleEnd, 0.99999);
   if (el->FindElement("reversemaxpower"))
     ReverseMaxPower = el->FindElementValueAsNumber("reversemaxpower")/100.0;
 
@@ -142,10 +151,10 @@ bool FGTurboProp::Load(FGFDMExec* exec, Element *el)
   delay=1;
   N1_factor = MaxN1 - IdleN1;
   N2_factor = MaxN2 - IdleN2;
-  OilTemp_degK = (Auxiliary->GetTotalTemperature() - 491.69) * 0.5555556 + 273.0;
+  OilTemp_degK = Auxiliary->GetTAT_C() + 273.0;
   if (IdleFF==-1) IdleFF = pow(MilThrust, 0.2) * 107.0;  // just an estimate
 
-  cout << "ENG POWER:" << EnginePowerRPM_N1->GetValue(1200,90) << "\n";
+  // cout << "ENG POWER:" << EnginePowerRPM_N1->GetValue(1200,90) << endl;
 
   return true;
 }
@@ -154,31 +163,33 @@ bool FGTurboProp::Load(FGFDMExec* exec, Element *el)
 // The main purpose of Calculate() is to determine what phase the engine should
 // be in, then call the corresponding function.
 
-double FGTurboProp::Calculate(void)
+void FGTurboProp::Calculate(void)
 {
-  TAT = (Auxiliary->GetTotalTemperature() - 491.69) * 0.5555556;
-  dt = State->Getdt() * Propulsion->GetRate();
+  RunPreFunctions();
 
-  ThrottleCmd = FCS->GetThrottleCmd(EngineNumber);
+  TAT = Auxiliary->GetTAT_C();
+  dt = FDMExec->GetDeltaT() * Propulsion->GetRate();
 
-  Prop_RPM = Thruster->GetRPM() * Thruster->GetGearRatio();
-  if (Thruster->GetType() == FGThruster::ttPropeller) {
+  Throttle = FCS->GetThrottlePos(EngineNumber);
+
+  RPM = Thruster->GetRPM() * Thruster->GetGearRatio();
+  if (thrusterType == FGThruster::ttPropeller) {
     ((FGPropeller*)Thruster)->SetAdvance(FCS->GetPropAdvance(EngineNumber));
     ((FGPropeller*)Thruster)->SetFeather(FCS->GetPropFeather(EngineNumber));
     ((FGPropeller*)Thruster)->SetReverse(Reversed);
     if (Reversed) {
-      ((FGPropeller*)Thruster)->SetReverseCoef(ThrottleCmd);
+      ((FGPropeller*)Thruster)->SetReverseCoef(Throttle);
     } else {
       ((FGPropeller*)Thruster)->SetReverseCoef(0.0);
     }
-  }
 
-  if (Reversed) {
-    if (ThrottleCmd < BetaRangeThrottleEnd) {
-        ThrottleCmd = 0.0;  // idle when in Beta-range
-    } else {
-      // when reversed:
-      ThrottleCmd = (ThrottleCmd-BetaRangeThrottleEnd)/(1-BetaRangeThrottleEnd) * ReverseMaxPower;
+    if (Reversed) {
+      if (Throttle < BetaRangeThrottleEnd) {
+          Throttle = 0.0;  // idle when in Beta-range
+      } else {
+        // when reversed:
+        Throttle = (Throttle-BetaRangeThrottleEnd)/(1-BetaRangeThrottleEnd) * ReverseMaxPower;
+      }
     }
   }
 
@@ -217,34 +228,43 @@ double FGTurboProp::Calculate(void)
     StartTime=-1;
   }
 
-  if (Condition < 1) {
-    if (Ielu_max_torque > 0
-      && -Ielu_max_torque > ((FGPropeller*)(Thruster))->GetTorque()
-      && ThrottleCmd >= OldThrottle ) {
-      ThrottleCmd = OldThrottle - 0.1 * dt; //IELU down
-      Ielu_intervent = true;
-    } else if (Ielu_max_torque > 0 && Ielu_intervent && ThrottleCmd >= OldThrottle) {
-      ThrottleCmd = OldThrottle;
-      ThrottleCmd = OldThrottle + 0.05 * dt; //IELU up
-      Ielu_intervent = true;
+  // limiter intervention wanted?
+  if (Ielu_max_torque > 0.0) {
+    double torque = 0.0;
+    
+    if (thrusterType == FGThruster::ttPropeller) {
+      torque = ((FGPropeller*)(Thruster))->GetTorque();
+    } else if (thrusterType == FGThruster::ttRotor) {
+      torque = ((FGRotor*)(Thruster))->GetTorque();
+    }
+
+    if (Condition < 1) {
+      if ( abs(torque) > Ielu_max_torque && Throttle >= OldThrottle ) {
+        Throttle = OldThrottle - 0.1 * dt; //IELU down
+        Ielu_intervent = true;
+      } else if ( Ielu_intervent && Throttle >= OldThrottle) {
+        Throttle = OldThrottle + 0.05 * dt; //IELU up
+        Ielu_intervent = true;
+      } else {
+        Ielu_intervent = false;
+      }
     } else {
       Ielu_intervent = false;
     }
-  } else {
-    Ielu_intervent = false;
+    OldThrottle = Throttle;
   }
-  OldThrottle = ThrottleCmd;
 
   switch (phase) {
-    case tpOff:    Eng_HP = Off(); break;
-    case tpRun:    Eng_HP = Run(); break;
-    case tpSpinUp: Eng_HP = SpinUp(); break;
-    case tpStart:  Eng_HP = Start(); break;
-    default: Eng_HP = 0;
+    case tpOff:    HP = Off(); break;
+    case tpRun:    HP = Run(); break;
+    case tpSpinUp: HP = SpinUp(); break;
+    case tpStart:  HP = Start(); break;
+    default: HP = 0;
   }
+  Thruster->Calculate(HP * hptoftlbssec);
 
-  //printf ("EngHP: %lf / Requi: %lf\n",Eng_HP,Prop_Required_Power);
-  return Thruster->Calculate((Eng_HP * hptoftlbssec)-Thruster->GetPowerRequired());
+  RunPostFunctions();
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -270,7 +290,7 @@ double FGTurboProp::Off(void)
   ConsumeFuel(); // for possible setting Starved = false when fuel tank
                  // is refilled (fuel crossfeed etc.)
 
-  if (Prop_RPM>5) return -0.012; // friction in engine when propeller spining (estimate)
+  if (RPM>5) return -0.012; // friction in engine when propeller spining (estimate)
   return 0.0;
 }
 
@@ -283,9 +303,9 @@ double FGTurboProp::Run(void)
 
 //---
   double old_N1 = N1;
-  N1 = ExpSeek(&N1, IdleN1 + ThrottleCmd * N1_factor, Idle_Max_Delay, Idle_Max_Delay * 2.4);
+  N1 = ExpSeek(&N1, IdleN1 + Throttle * N1_factor, Idle_Max_Delay, Idle_Max_Delay * 2.4);
 
-  EngPower_HP = EnginePowerRPM_N1->GetValue(Prop_RPM,N1);
+  EngPower_HP = EnginePowerRPM_N1->GetValue(RPM,N1);
   EngPower_HP *= EnginePowerVC->GetValue();
   if (EngPower_HP > MaxPower) EngPower_HP = MaxPower;
 
@@ -336,7 +356,7 @@ double FGTurboProp::SpinUp(void)
   OilPressure_psi = (N1/100.0*0.25+(0.1-(OilTemp_degK-273.15)*0.1/80.0)*N1/100.0) / 7692.0e-6; //from MPa to psi
   NozzlePosition = 1.0;
 
-  EngPower_HP = EnginePowerRPM_N1->GetValue(Prop_RPM,N1);
+  EngPower_HP = EnginePowerRPM_N1->GetValue(RPM,N1);
   EngPower_HP *= EnginePowerVC->GetValue();
   if (EngPower_HP > MaxPower) EngPower_HP = MaxPower;
 
@@ -356,13 +376,15 @@ double FGTurboProp::SpinUp(void)
 
 double FGTurboProp::Start(void)
 {
-  double EngPower_HP,eff_coef;
+  double EngPower_HP = 0.0;
+  double eff_coef;
+
   EngStarting = false;
   if ((N1 > 15.0) && !Starved) {       // minimum 15% N2 needed for start
     double old_N1 = N1;
     Cranking = true;                   // provided for sound effects signal
     if (N1 < IdleN1) {
-      EngPower_HP = EnginePowerRPM_N1->GetValue(Prop_RPM,N1);
+      EngPower_HP = EnginePowerRPM_N1->GetValue(RPM,N1);
       EngPower_HP *= EnginePowerVC->GetValue();
       if (EngPower_HP > MaxPower) EngPower_HP = MaxPower;
       N1 = ExpSeek(&N1, IdleN1*1.1, Idle_Max_Delay*4, Idle_Max_Delay * 2.4);
@@ -381,7 +403,6 @@ double FGTurboProp::Start(void)
       Starter = false;
       Cranking = false;
       FuelFlow_pph = 0;
-      EngPower_HP=0.0;
     }
   } else {                 // no start if N2 < 15% or Starved
     phase = tpOff;
@@ -398,7 +419,10 @@ double FGTurboProp::Start(void)
 
 double FGTurboProp::CalcFuelNeed(void)
 {
-  return FuelFlow_pph /3600 * State->Getdt() * Propulsion->GetRate();
+  double dT = FDMExec->GetDeltaT() * Propulsion->GetRate();
+  FuelFlowRate = FuelFlow_pph / 3600.0;
+  FuelExpended = FuelFlowRate * dT;
+  return FuelExpended;
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -434,15 +458,16 @@ double FGTurboProp::ExpSeek(double *var, double target, double accel_tau, double
 
 void FGTurboProp::SetDefaults(void)
 {
-  Name = "Not defined";
+//  Name = "Not defined";
   N1 = N2 = 0.0;
+  HP = 0.0;
   Type = etTurboprop;
   MilThrust = 10000.0;
   IdleN1 = 30.0;
   IdleN2 = 60.0;
   MaxN1 = 100.0;
   MaxN2 = 100.0;
-  ThrottleCmd = 0.0;
+  Throttle = 0.0;
   InletPosition = 1.0;
   NozzlePosition = 1.0;
   Reversed = false;
@@ -459,68 +484,77 @@ void FGTurboProp::SetDefaults(void)
   Ielu_intervent=false;
 
   Idle_Max_Delay = 1.0;
+
+  Throttle = OldThrottle = 0.0;
+  ITT_Delay = 0.05;
+  ReverseMaxPower = 0.0;
+  BetaRangeThrottleEnd = 0.0;
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 
-string FGTurboProp::GetEngineLabels(string delimeter)
+string FGTurboProp::GetEngineLabels(const string& delimiter)
 {
   std::ostringstream buf;
 
-  buf << Name << "_N1[" << EngineNumber << "]" << delimeter
-      << Name << "_N2[" << EngineNumber << "]" << delimeter
-      << Name << "__PwrAvailJVK[" << EngineNumber << "]" << delimeter
-      << Thruster->GetThrusterLabels(EngineNumber, delimeter);
+  buf << Name << "_N1[" << EngineNumber << "]" << delimiter
+      << Name << "_N2[" << EngineNumber << "]" << delimiter
+      << Name << "_PwrAvail[" << EngineNumber << "]" << delimiter
+      << Thruster->GetThrusterLabels(EngineNumber, delimiter);
 
   return buf.str();
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-string FGTurboProp::GetEngineValues(string delimeter)
+string FGTurboProp::GetEngineValues(const string& delimiter)
 {
   std::ostringstream buf;
 
-  buf << N1 << delimeter
-      << N2 << delimeter
-      << Thruster->GetThrusterValues(EngineNumber,delimeter);
+  buf << N1 << delimiter
+      << N2 << delimiter
+      << HP << delimiter
+      << Thruster->GetThrusterValues(EngineNumber,delimiter);
 
   return buf.str();
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-void FGTurboProp::bindmodel()
+int FGTurboProp::InitRunning(void)
 {
-  char property_name[80];
-
-// ToDo: Do a proper Tie here, this should be read only.
-
-  snprintf(property_name, 80, "propulsion/engine[%u]/n1", EngineNumber);
-  PropertyManager->Tie( property_name, &N1);
-  snprintf(property_name, 80, "propulsion/engine[%u]/n2", EngineNumber);
-  PropertyManager->Tie( property_name, &N2);
-  snprintf(property_name, 80, "propulsion/engine[%u]/reverser", EngineNumber);
-  PropertyManager->Tie( property_name, &Reversed);
-
+  FDMExec->SuspendIntegration();
+  Cutoff=false;
+  Running=true;  
+  N2=16.0;
+  Calculate();
+  FDMExec->ResumeIntegration();
+  return phase==tpRun;
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-void FGTurboProp::unbind()
+void FGTurboProp::bindmodel()
 {
-  char property_name[80];
-
-  snprintf(property_name, 80, "propulsion/engine[%u]/n1", EngineNumber);
-  PropertyManager->Untie(property_name);
-  snprintf(property_name, 80, "propulsion/engine[%u]/n2", EngineNumber);
-  PropertyManager->Untie(property_name);
-  snprintf(property_name, 80, "propulsion/engine[%u]/reverser", EngineNumber);
-  PropertyManager->Untie(property_name);
+  string property_name, base_property_name;
+  base_property_name = CreateIndexedPropertyName("propulsion/engine", EngineNumber);
+  property_name = base_property_name + "/n1";
+  PropertyManager->Tie( property_name.c_str(), &N1);
+  // property_name = base_property_name + "/n2";
+  // PropertyManager->Tie( property_name.c_str(), &N2);
+  property_name = base_property_name + "/reverser";
+  PropertyManager->Tie( property_name.c_str(), &Reversed);
+  property_name = base_property_name + "/power-hp";
+  PropertyManager->Tie( property_name.c_str(), &HP);
+  property_name = base_property_name + "/itt-c";
+  PropertyManager->Tie( property_name.c_str(), &Eng_ITT_degC);
+  property_name = base_property_name + "/engtemp-c";
+  PropertyManager->Tie( property_name.c_str(), &Eng_Temperature);
+  property_name = base_property_name + "/ielu_intervent";
+  PropertyManager->Tie( property_name.c_str(), &Ielu_intervent);
 }
 
-
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 //    The bitmasked value choices are as follows:
 //    unset: In this case (the default) JSBSim would only print