📄 fgturboprop.cpp
字号:
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Module: FGTurboProp.cpp Author: Jiri "Javky" Javurek based on SimTurbine and Turbine engine from David Culp Date started: 05/14/2004 Purpose: This module models a turbo propeller engine. ------------- 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 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 Lesser General Public License for more details. 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 Lesser General Public License can also be found on the world wide web at http://www.gnu.org.FUNCTIONAL DESCRIPTION--------------------------------------------------------------------------------This class descends from the FGEngine class and models a Turbo propeller enginebased on parameters given in the engine config file for this classHISTORY--------------------------------------------------------------------------------05/14/2004 Created//JVK (mark)%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%INCLUDES%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/#include <vector>#include <sstream>#include "FGTurboProp.h"#include "FGPropeller.h"namespace JSBSim {static const char *IdSrc = "$Id$";static const char *IdHdr = ID_TURBOPROP;/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%CLASS IMPLEMENTATION%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/FGTurboProp::FGTurboProp(FGFDMExec* exec, Element *el, int engine_number) : FGEngine(exec, el, engine_number){ SetDefaults(); Load(exec, el); Debug(0);}//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%FGTurboProp::~FGTurboProp(){ Debug(1);}//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%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;// ToDo: Need to make sure units are properly accounted for below. if (el->FindElement("milthrust")) MilThrust = el->FindElementValueAsNumberConvertTo("milthrust","LBS"); if (el->FindElement("idlen1")) IdleN1 = el->FindElementValueAsNumber("idlen1"); if (el->FindElement("idlen2")) IdleN2 = el->FindElementValueAsNumber("idlen1"); 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; if (el->FindElement("reversemaxpower")) ReverseMaxPower = el->FindElementValueAsNumber("reversemaxpower")/100.0; if (el->FindElement("maxpower")) MaxPower = el->FindElementValueAsNumber("maxpower"); if (el->FindElement("idlefuelflow")) IdleFF = el->FindElementValueAsNumber("idlefuelflow"); if (el->FindElement("psfc")) PSFC = el->FindElementValueAsNumber("psfc"); if (el->FindElement("n1idle_max_delay")) Idle_Max_Delay = el->FindElementValueAsNumber("n1idle_max_delay"); if (el->FindElement("maxstartingtime")) MaxStartingTime = el->FindElementValueAsNumber("maxstartingtime"); if (el->FindElement("startern1")) StarterN1 = el->FindElementValueAsNumber("startern1"); if (el->FindElement("ielumaxtorque")) Ielu_max_torque = el->FindElementValueAsNumber("ielumaxtorque"); if (el->FindElement("itt_delay")) ITT_Delay = el->FindElementValueAsNumber("itt_delay"); Element *table_element; string name; FGPropertyManager* PropertyManager = exec->GetPropertyManager(); while (true) { table_element = el->FindNextElement("table"); if (!table_element) break; name = table_element->GetAttributeValue("name"); if (name == "EnginePowerVC") { EnginePowerVC = new FGTable(PropertyManager, table_element); } else if (name == "EnginePowerRPM_N1") { EnginePowerRPM_N1 = new FGTable(PropertyManager, table_element); } else if (name == "ITT_N1") { ITT_N1 = new FGTable(PropertyManager, table_element); } else { cerr << "Unknown table type: " << name << " in turbine definition." << endl; } } // Pre-calculations and initializations delay=1; N1_factor = MaxN1 - IdleN1; N2_factor = MaxN2 - IdleN2; OilTemp_degK = (Auxiliary->GetTotalTemperature() - 491.69) * 0.5555556 + 273.0; if (IdleFF==-1) IdleFF = pow(MilThrust, 0.2) * 107.0; // just an estimate cout << "ENG POWER:" << EnginePowerRPM_N1->GetValue(1200,90) << "\n"; return true;}//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%// The main purpose of Calculate() is to determine what phase the engine should// be in, then call the corresponding function.double FGTurboProp::Calculate(void){ TAT = (Auxiliary->GetTotalTemperature() - 491.69) * 0.5555556; dt = State->Getdt() * Propulsion->GetRate(); ThrottleCmd = FCS->GetThrottleCmd(EngineNumber); Prop_RPM = Thruster->GetRPM() * Thruster->GetGearRatio(); if (Thruster->GetType() == FGThruster::ttPropeller) { ((FGPropeller*)Thruster)->SetAdvance(FCS->GetPropAdvance(EngineNumber)); ((FGPropeller*)Thruster)->SetFeather(FCS->GetPropFeather(EngineNumber)); ((FGPropeller*)Thruster)->SetReverse(Reversed); if (Reversed) { ((FGPropeller*)Thruster)->SetReverseCoef(ThrottleCmd); } 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; } } // When trimming is finished check if user wants engine OFF or RUNNING if ((phase == tpTrim) && (dt > 0)) { if (Running && !Starved) { phase = tpRun; N2 = IdleN2; N1 = IdleN1; OilTemp_degK = 366.0; Cutoff = false; } else { phase = tpOff; Cutoff = true; Eng_ITT_degC = TAT; Eng_Temperature = TAT; OilTemp_degK = TAT+273.15; } } if (!Running && Starter) { if (phase == tpOff) { phase = tpSpinUp; if (StartTime < 0) StartTime=0; } } if (!Running && !Cutoff && (N1 > 15.0)) { phase = tpStart; StartTime = -1; } if (Cutoff && (phase != tpSpinUp)) phase = tpOff; if (dt == 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; } else { Ielu_intervent = false; } } else { Ielu_intervent = false; } 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; } //printf ("EngHP: %lf / Requi: %lf\n",Eng_HP,Prop_Required_Power); return Thruster->Calculate((Eng_HP * hptoftlbssec)-Thruster->GetPowerRequired());}//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%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); OilTemp_degK = ExpSeek(&OilTemp_degK,273.15 + TAT, 400 , 400); Eng_Temperature = ExpSeek(&Eng_Temperature,TAT,300,400); double ITT_goal = ITT_N1->GetValue(N1,0.1) + ((N1>20) ? 0.0 : (20-N1)/20.0 * Eng_Temperature); Eng_ITT_degC = ExpSeek(&Eng_ITT_degC,ITT_goal,ITT_Delay,ITT_Delay*1.2); 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) return 0.0;}//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%double FGTurboProp::Run(void){ 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); EngPower_HP = EnginePowerRPM_N1->GetValue(Prop_RPM,N1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -