]> git.mxchange.org Git - flightgear.git/blobdiff - src/FDM/JSBSim/models/propulsion/FGTurboProp.cpp
Better fix for a compilation problem with MSVC 2012
[flightgear.git] / src / FDM / JSBSim / models / propulsion / FGTurboProp.cpp
old mode 100755 (executable)
new mode 100644 (file)
index e6bd2dc..c0bb279
@@ -9,20 +9,20 @@
  ------------- Copyright (C) 2004  (javky@email.cz) ---------
 
  This program is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free Software
+ the terms of the GNU Lesser General Public License as published by the Free Software
  Foundation; either version 2 of the License, or (at your option) any later
  version.
 
  This program is distributed in the hope that it will be useful, but WITHOUT
  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
  details.
 
- You should have received a copy of the GNU General Public License along with
+ You should have received a copy of the GNU Lesser General Public License along with
  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
  Place - Suite 330, Boston, MA  02111-1307, USA.
 
- Further information about the GNU General Public License can also be found on
+ Further information about the GNU Lesser General Public License can also be found on
  the world wide web at http://www.gnu.org.
 
 FUNCTIONAL DESCRIPTION
@@ -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,27 +42,33 @@ HISTORY
 INCLUDES
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#include <vector>
+#include <iostream>
 #include <sstream>
-#include "FGTurboProp.h"
 
+#include "FGTurboProp.h"
 #include "FGPropeller.h"
+#include "FGRotor.h"
+
+using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGTurboProp.cpp,v 1.24 2011/09/25 23:56:11 jentron Exp $";
 static const char *IdHdr = ID_TURBOPROP;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 CLASS IMPLEMENTATION
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-FGTurboProp::FGTurboProp(FGFDMExec* exec, Element *el, int engine_number)
-  : FGEngine(exec, el, engine_number)
+FGTurboProp::FGTurboProp(FGFDMExec* exec, Element *el, int engine_number, struct Inputs& input)
+  : FGEngine(exec, el, engine_number, input),
+    ITT_N1(NULL), EnginePowerRPM_N1(NULL), EnginePowerVC(NULL)
 {
   SetDefaults();
+  thrusterType = Thruster->GetType();
 
   Load(exec, el);
+  bindmodel();
   Debug(0);
 }
 
@@ -69,6 +76,9 @@ FGTurboProp::FGTurboProp(FGFDMExec* exec, Element *el, int engine_number)
 
 FGTurboProp::~FGTurboProp()
 {
+  delete ITT_N1;
+  delete EnginePowerRPM_N1;
+  delete EnginePowerVC;
   Debug(1);
 }
 
@@ -76,9 +86,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 +97,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 +150,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 = in.TAT_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,36 +162,38 @@ 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();
+
+  TAT = in.TAT_c;
 
-  ThrottleCmd = FCS->GetThrottleCmd(EngineNumber);
+  ThrottlePos = in.ThrottlePos[EngineNumber];
 
-  Prop_RPM = Thruster->GetRPM() * Thruster->GetGearRatio();
-  if (Thruster->GetType() == FGThruster::ttPropeller) {
-    ((FGPropeller*)Thruster)->SetAdvance(FCS->GetPropAdvance(EngineNumber));
-    ((FGPropeller*)Thruster)->SetFeather(FCS->GetPropFeather(EngineNumber));
+/* The thruster controls the engine RPM because it encapsulates the gear ratio and other transmission variables */
+  RPM = Thruster->GetEngineRPM();
+  if (thrusterType == FGThruster::ttPropeller) {
+    ((FGPropeller*)Thruster)->SetAdvance(in.PropAdvance[EngineNumber]);
+    ((FGPropeller*)Thruster)->SetFeather(in.PropFeather[EngineNumber]);
     ((FGPropeller*)Thruster)->SetReverse(Reversed);
     if (Reversed) {
-      ((FGPropeller*)Thruster)->SetReverseCoef(ThrottleCmd);
+      ((FGPropeller*)Thruster)->SetReverseCoef(ThrottlePos);
     } 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 (ThrottlePos < BetaRangeThrottleEnd) {
+          ThrottlePos = 0.0;  // idle when in Beta-range
+      } else {
+        // when reversed:
+        ThrottlePos = (ThrottlePos-BetaRangeThrottleEnd)/(1-BetaRangeThrottleEnd) * ReverseMaxPower;
+      }
     }
   }
 
   // When trimming is finished check if user wants engine OFF or RUNNING
-  if ((phase == tpTrim) && (dt > 0)) {
+  if ((phase == tpTrim) && (in.TotalDeltaT > 0)) {
     if (Running && !Starved) {
       phase = tpRun;
       N2 = IdleN2;
@@ -210,54 +220,63 @@ double FGTurboProp::Calculate(void)
     StartTime = -1;
   }
   if (Cutoff && (phase != tpSpinUp)) phase = tpOff;
-  if (dt == 0) phase = tpTrim;
+  if (in.TotalDeltaT == 0) phase = tpTrim;
   if (Starved) phase = tpOff;
   if (Condition >= 10) {
     phase = tpOff;
     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 && ThrottlePos >= OldThrottle ) {
+        ThrottlePos = OldThrottle - 0.1 * in.TotalDeltaT; //IELU down
+        Ielu_intervent = true;
+      } else if ( Ielu_intervent && ThrottlePos >= OldThrottle) {
+        ThrottlePos = OldThrottle + 0.05 * in.TotalDeltaT; //IELU up
+        Ielu_intervent = true;
+      } else {
+        Ielu_intervent = false;
+      }
     } else {
       Ielu_intervent = false;
     }
-  } else {
-    Ielu_intervent = false;
+    OldThrottle = ThrottlePos;
   }
-  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;
   }
+  LoadThrusterInputs();
+  Thruster->Calculate(HP * hptoftlbssec);
 
-  //printf ("EngHP: %lf / Requi: %lf\n",Eng_HP,Prop_Required_Power);
-  return Thruster->Calculate((Eng_HP * hptoftlbssec)-Thruster->GetPowerRequired());
+  RunPostFunctions();
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 double FGTurboProp::Off(void)
 {
-  double qbar = Auxiliary->Getqbar();
   Running = false; EngStarting = false;
 
   FuelFlow_pph = Seek(&FuelFlow_pph, 0, 800.0, 800.0);
 
   //allow the air turn with generator
-  N1 = ExpSeek(&N1, qbar/15.0, Idle_Max_Delay*2.5, Idle_Max_Delay * 5);
+  N1 = ExpSeek(&N1, in.qbar/15.0, Idle_Max_Delay*2.5, Idle_Max_Delay * 5);
 
   OilTemp_degK = ExpSeek(&OilTemp_degK,273.15 + TAT, 400 , 400);
 
@@ -267,10 +286,7 @@ double FGTurboProp::Off(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
 
-  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;
 }
 
@@ -278,14 +294,14 @@ double FGTurboProp::Off(void)
 
 double FGTurboProp::Run(void)
 {
-  double idlethrust, milthrust, thrust, EngPower_HP, eff_coef;
+  double thrust = 0.0, EngPower_HP, eff_coef;
   Running = true; Starter = false; EngStarting = false;
 
 //---
   double old_N1 = N1;
-  N1 = ExpSeek(&N1, IdleN1 + ThrottleCmd * N1_factor, Idle_Max_Delay, Idle_Max_Delay * 2.4);
+  N1 = ExpSeek(&N1, IdleN1 + ThrottlePos * 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;
 
@@ -302,8 +318,6 @@ double FGTurboProp::Run(void)
 
   OilTemp_degK = Seek(&OilTemp_degK, 353.15, 0.4-N1*0.001, 0.04);
 
-  ConsumeFuel();
-
   if (Cutoff) phase = tpOff;
   if (Starved) phase = tpOff;
 
@@ -336,19 +350,16 @@ 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;
 
-  if (StartTime>=0) StartTime+=dt;
+  if (StartTime>=0) StartTime+=in.TotalDeltaT;
   if (StartTime > MaxStartingTime && MaxStartingTime > 0) { //start failed due timeout
     phase = tpOff;
     StartTime = -1;
   }
 
-  ConsumeFuel(); // for possible setting Starved = false when fuel tank
-                 // is refilled (fuel crossfeed etc.)
-
   return EngPower_HP;
 }
 
@@ -356,13 +367,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,15 +394,12 @@ 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;
     Starter = false;
   }
 
-  ConsumeFuel();
-
   return EngPower_HP;
 }
 
@@ -398,7 +408,10 @@ double FGTurboProp::Start(void)
 
 double FGTurboProp::CalcFuelNeed(void)
 {
-  return FuelFlow_pph /3600 * State->Getdt() * Propulsion->GetRate();
+  FuelFlowRate = FuelFlow_pph / 3600.0;
+  FuelExpended = FuelFlowRate * in.TotalDeltaT;
+  if (!Starved) FuelUsedLbs += FuelExpended;
+  return FuelExpended;
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -407,10 +420,10 @@ double FGTurboProp::Seek(double *var, double target, double accel, double decel)
 {
   double v = *var;
   if (v > target) {
-    v -= dt * decel;
+    v -= in.TotalDeltaT * decel;
     if (v < target) v = target;
   } else if (v < target) {
-    v += dt * accel;
+    v += in.TotalDeltaT * accel;
     if (v > target) v = target;
   }
   return v;
@@ -423,9 +436,9 @@ double FGTurboProp::ExpSeek(double *var, double target, double accel_tau, double
 // exponential delay instead of the linear delay used in Seek
   double v = *var;
   if (v > target) {
-    v = (v - target) * exp ( -dt / decel_tau) + target;
+    v = (v - target) * exp ( -in.TotalDeltaT / decel_tau) + target;
   } else if (v < target) {
-    v = (target - v) * (1 - exp ( -dt / accel_tau)) + v;
+    v = (target - v) * (1 - exp ( -in.TotalDeltaT / accel_tau)) + v;
   }
   return v;
 }
@@ -434,15 +447,15 @@ 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;
   InletPosition = 1.0;
   NozzlePosition = 1.0;
   Reversed = false;
@@ -459,68 +472,77 @@ void FGTurboProp::SetDefaults(void)
   Ielu_intervent=false;
 
   Idle_Max_Delay = 1.0;
+
+  ThrottlePos = 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