From: Bertrand Coconnier Date: Sun, 10 Jul 2016 12:45:09 +0000 (+0200) Subject: JSBSim sync. X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=7718810f7071132ad1029b45425575a1ea62e04f;p=flightgear.git JSBSim sync. * Fixed the initial conditions settings (geodetic altitude is now correctly computed). * FGLGear reports the time at which it detected a violent ground hit (aka crash) * Doc update of the kinematic component * TurboProp code cleanup with the removal of lots of obsolete/no-op members. --- diff --git a/src/FDM/JSBSim/JSBSim.cxx b/src/FDM/JSBSim/JSBSim.cxx index d825a4262..89b96e48c 100644 --- a/src/FDM/JSBSim/JSBSim.cxx +++ b/src/FDM/JSBSim/JSBSim.cxx @@ -653,7 +653,7 @@ bool FGJSBsim::copy_to_JSBsim() FGTurboProp* eng = (FGTurboProp*)Propulsion->GetEngine(i); eng->SetReverse( globals->get_controls()->get_reverser(i) ); eng->SetCutoff( globals->get_controls()->get_cutoff(i) ); - eng->SetIgnition( globals->get_controls()->get_ignition(i) ); + // eng->SetIgnition( globals->get_controls()->get_ignition(i) ); eng->SetGeneratorPower( globals->get_controls()->get_generator_breaker(i) ); eng->SetCondition( globals->get_controls()->get_condition(i) ); @@ -881,9 +881,9 @@ bool FGJSBsim::copy_from_JSBsim() node->setDoubleValue("n1", eng->GetN1()); //node->setDoubleValue("n2", eng->GetN2()); node->setDoubleValue("itt_degf", 32 + eng->GetITT()*9/5); - node->setBoolValue("ignition", eng->GetIgnition() != 0); - node->setDoubleValue("nozzle-pos-norm", eng->GetNozzle()); - node->setDoubleValue("inlet-pos-norm", eng->GetInlet()); + // node->setBoolValue("ignition", eng->GetIgnition() != 0); + // node->setDoubleValue("nozzle-pos-norm", eng->GetNozzle()); + // node->setDoubleValue("inlet-pos-norm", eng->GetInlet()); node->setDoubleValue("oil-pressure-psi", eng->getOilPressure_psi()); node->setBoolValue("reversed", eng->GetReversed()); node->setBoolValue("cutoff", eng->GetCutoff()); diff --git a/src/FDM/JSBSim/initialization/FGInitialCondition.cpp b/src/FDM/JSBSim/initialization/FGInitialCondition.cpp index 8b9b2c0fe..c5eea1a2f 100644 --- a/src/FDM/JSBSim/initialization/FGInitialCondition.cpp +++ b/src/FDM/JSBSim/initialization/FGInitialCondition.cpp @@ -58,7 +58,7 @@ using namespace std; namespace JSBSim { -IDENT(IdSrc,"$Id: FGInitialCondition.cpp,v 1.107 2016/01/24 18:18:38 bcoconni Exp $"); +IDENT(IdSrc,"$Id: FGInitialCondition.cpp,v 1.111 2016/07/03 17:20:55 bcoconni Exp $"); IDENT(IdHdr,ID_INITIALCONDITION); //****************************************************************************** @@ -104,6 +104,8 @@ void FGInitialCondition::ResetIC(double u0, double v0, double w0, position.SetLongitude(lonRad0); position.SetLatitude(latRad0); position.SetAltitudeAGL(altAGLFt0); + lastLatitudeSet = setgeoc; + lastAltitudeSet = setagl; orientation = FGQuaternion(phi0, theta0, psi0); const FGMatrix33& Tb2l = orientation.GetTInv(); @@ -125,8 +127,12 @@ void FGInitialCondition::ResetIC(double u0, double v0, double w0, void FGInitialCondition::InitializeIC(void) { alpha=beta=0; + a = fdmex->GetInertial()->GetSemimajor(); + double b = fdmex->GetInertial()->GetSemiminor(); + double ec = b/a; + e2 = 1.0 - ec*ec; - position.SetEllipse(fdmex->GetInertial()->GetSemimajor(), fdmex->GetInertial()->GetSemiminor()); + position.SetEllipse(a, b); position.SetPositionGeodetic(0.0, 0.0, 0.0); position.SetEarthPositionAngle(fdmex->GetPropagate()->GetEarthPositionAngle()); @@ -143,6 +149,7 @@ void FGInitialCondition::InitializeIC(void) lastSpeedSet = setvt; lastAltitudeSet = setasl; + lastLatitudeSet = setgeoc; enginesRunning = 0; needTrim = 0; } @@ -696,18 +703,26 @@ void FGInitialCondition::SetAltitudeASLFtIC(double alt) double mach0 = vt / soundSpeed; double vc0 = VcalibratedFromMach(mach0, pressure, pressureSL, rhoSL); double ve0 = vt * sqrt(rho/rhoSL); + double PitotAngle = Aircraft->GetPitotAngle(); + double geodLatitude = position.GetGeodLatitudeRad(); altitudeASL=alt; position.SetAltitudeASL(alt); + if (lastLatitudeSet == setgeod) { + double h = ComputeGeodAltitude(geodLatitude); + position.SetPositionGeodetic(position.GetLongitude(), geodLatitude, h); + } + soundSpeed = Atmosphere->GetSoundSpeed(altitudeASL); rho = Atmosphere->GetDensity(altitudeASL); pressure = Atmosphere->GetPressure(altitudeASL); switch(lastSpeedSet) { case setvc: - mach0 = MachFromVcalibrated(vc0, pressure, pressureSL, rhoSL); - SetVtrueFpsIC(mach0 * soundSpeed); + mach0 = MachFromVcalibrated(vc0 * cos(alpha+PitotAngle) * cos(beta), + pressure, pressureSL, rhoSL); + SetVtrueFpsIC(mach0 * soundSpeed / (cos(alpha+PitotAngle) * cos(beta))); break; case setmach: SetVtrueFpsIC(mach0 * soundSpeed); @@ -728,6 +743,8 @@ void FGInitialCondition::SetLatitudeRadIC(double lat) { double altitude; + lastLatitudeSet = setgeoc; + switch(lastAltitudeSet) { case setagl: altitude = GetAltitudeAGLFtIC(); @@ -735,9 +752,8 @@ void FGInitialCondition::SetLatitudeRadIC(double lat) SetAltitudeAGLFtIC(altitude); break; default: - altitude = position.GetAltitudeASL(); position.SetLatitude(lat); - position.SetAltitudeASL(altitude); + break; } } @@ -904,32 +920,40 @@ bool FGInitialCondition::Load(string rstfile, bool useStoredPath) } //****************************************************************************** - -bool FGInitialCondition::Load_v1(Element* document) +// Given an altitude above the sea level (or a position radius which is the +// same) and a geodetic latitude, compute the geodetic altitude. It is assumed +// that the terrain is a sphere and that the elevation is uniform all over the +// Earth. Would that assumption fail, the computation below would need to be +// adapted since the position radius would depend on the terrain elevation which +// depends itself on the latitude. +// +// This is an acceptable trade off because this routine is only used by +// standalone JSBSim which uses FGDefaultGroundCallback which assumes that the +// Earth is a sphere. + +double FGInitialCondition::ComputeGeodAltitude(double geodLatitude) { - bool result = true; - - if (document->FindElement("longitude")) - SetLongitudeRadIC(document->FindElementValueAsNumberConvertTo("longitude", "RAD")); - if (document->FindElement("elevation")) - SetTerrainElevationFtIC(document->FindElementValueAsNumberConvertTo("elevation", "FT")); + double R = position.GetRadius(); + double slat = sin(geodLatitude); + double RN = a / sqrt(1.0 - e2*slat*slat); + double p1 = e2*RN*slat*slat; + double p2 = e2*e2*RN*RN*slat*slat-R*R; + return p1 + sqrt(p1*p1-p2) - RN; +} - if (document->FindElement("altitude")) // This is feet above ground level - SetAltitudeAGLFtIC(document->FindElementValueAsNumberConvertTo("altitude", "FT")); - else if (document->FindElement("altitudeAGL")) // This is feet above ground level - SetAltitudeAGLFtIC(document->FindElementValueAsNumberConvertTo("altitudeAGL", "FT")); - else if (document->FindElement("altitudeMSL")) // This is feet above sea level - SetAltitudeASLFtIC(document->FindElementValueAsNumberConvertTo("altitudeMSL", "FT")); +//****************************************************************************** - double altitude = GetAltitudeASLFtIC(); - double longitude = GetLongitudeRadIC(); +bool FGInitialCondition::LoadLatitude(Element* position_el) +{ + Element* latitude_el = position_el->FindElement("latitude"); - Element* latitude_el = document->FindElement("latitude"); if (latitude_el) { - double latitude = document->FindElementValueAsNumberConvertTo("latitude", "RAD"); + double latitude = position_el->FindElementValueAsNumberConvertTo("latitude", "RAD"); + if (fabs(latitude) > 0.5*M_PI) { string unit_type = latitude_el->GetAttributeValue("unit"); if (unit_type.empty()) unit_type="RAD"; + cerr << latitude_el->ReadFrom() << "The latitude value " << latitude_el->GetDataAsNumber() << " " << unit_type << " is outside the range ["; @@ -937,16 +961,46 @@ bool FGInitialCondition::Load_v1(Element* document) cerr << "-90 DEG ; +90 DEG]" << endl; else cerr << "-PI/2 RAD; +PI/2 RAD]" << endl; - result = false; + + return false; } string lat_type = latitude_el->GetAttributeValue("type"); - if (lat_type == "geod" || lat_type == "geodetic") - position.SetPositionGeodetic(longitude, latitude, altitude); // Longitude and altitude will be set later on - else + + if (lat_type == "geod" || lat_type == "geodetic") { + double h = ComputeGeodAltitude(latitude); + position.SetPositionGeodetic(position.GetLongitude(), latitude, h); + lastLatitudeSet = setgeod; + } + else { position.SetLatitude(latitude); + lastLatitudeSet = setgeoc; + } } + return true; +} + +//****************************************************************************** + +bool FGInitialCondition::Load_v1(Element* document) +{ + bool result = true; + + if (document->FindElement("longitude")) + SetLongitudeRadIC(document->FindElementValueAsNumberConvertTo("longitude", "RAD")); + if (document->FindElement("elevation")) + SetTerrainElevationFtIC(document->FindElementValueAsNumberConvertTo("elevation", "FT")); + + if (document->FindElement("altitude")) // This is feet above ground level + SetAltitudeAGLFtIC(document->FindElementValueAsNumberConvertTo("altitude", "FT")); + else if (document->FindElement("altitudeAGL")) // This is feet above ground level + SetAltitudeAGLFtIC(document->FindElementValueAsNumberConvertTo("altitudeAGL", "FT")); + else if (document->FindElement("altitudeMSL")) // This is feet above sea level + SetAltitudeASLFtIC(document->FindElementValueAsNumberConvertTo("altitudeMSL", "FT")); + + result = LoadLatitude(document); + FGColumnVector3 vOrient = orientation.GetEuler(); if (document->FindElement("phi")) @@ -995,9 +1049,7 @@ bool FGInitialCondition::Load_v1(Element* document) if (document->FindElement("xwind")) SetCrossWindKtsIC(document->FindElementValueAsNumberConvertTo("xwind", "KTS")); if (document->FindElement("targetNlf")) - { SetTargetNlfIC(document->FindElementValueAsNumber("targetNlf")); - } if (document->FindElement("trim")) needTrim = document->FindElementValueAsNumber("trim"); @@ -1006,9 +1058,9 @@ bool FGInitialCondition::Load_v1(Element* document) const FGMatrix33& Tl2b = orientation.GetT(); double radInv = 1.0 / position.GetRadius(); FGColumnVector3 vOmegaLocal = FGColumnVector3( - radInv*vUVW_NED(eEast), - -radInv*vUVW_NED(eNorth), - -radInv*vUVW_NED(eEast)*position.GetTanLatitude() ); + radInv*vUVW_NED(eEast), + -radInv*vUVW_NED(eNorth), + -radInv*vUVW_NED(eEast)*position.GetTanLatitude() ); vPQR_body = Tl2b * vOmegaLocal; @@ -1035,6 +1087,9 @@ bool FGInitialCondition::Load_v2(Element* document) } FGColumnVector3 vOmegaEarth = fdmex->GetInertial()->GetOmegaPlanet(); + if (document->FindElement("elevation")) + fdmex->GetGroundCallback()->SetTerrainGeoCentRadius(document->FindElementValueAsNumberConvertTo("elevation", "FT")+position.GetSeaLevelRadius()); + // Initialize vehicle position // // Allowable frames: @@ -1049,7 +1104,6 @@ bool FGInitialCondition::Load_v2(Element* document) position = position.GetTi2ec() * position_el->FindElementTripletConvertTo("FT"); } else if (frame == "ecef") { if (!position_el->FindElement("x") && !position_el->FindElement("y") && !position_el->FindElement("z")) { - Element* latitude_el = position_el->FindElement("latitude"); if (position_el->FindElement("longitude")) position.SetLongitude(position_el->FindElementValueAsNumberConvertTo("longitude", "RAD")); @@ -1064,17 +1118,7 @@ bool FGInitialCondition::Load_v2(Element* document) result = false; } - double altitude = position.GetAltitudeASL(); - double longitude = position.GetLongitude(); - - if (latitude_el) { - string lat_type = latitude_el->GetAttributeValue("type"); - double latitude = position_el->FindElementValueAsNumberConvertTo("latitude", "RAD"); - if (lat_type == "geod" || lat_type == "geodetic") - position.SetPositionGeodetic(longitude, latitude, altitude); - else - position.SetLatitude(latitude); - } + result = LoadLatitude(position_el); } else { position = position_el->FindElementTripletConvertTo("FT"); @@ -1088,9 +1132,6 @@ bool FGInitialCondition::Load_v2(Element* document) result = false; } - if (document->FindElement("elevation")) - fdmex->GetGroundCallback()->SetTerrainGeoCentRadius(document->FindElementValueAsNumberConvertTo("elevation", "FT")+position.GetSeaLevelRadius()); - // End of position initialization // Initialize vehicle orientation diff --git a/src/FDM/JSBSim/initialization/FGInitialCondition.h b/src/FDM/JSBSim/initialization/FGInitialCondition.h index 488d37add..c5428b7ad 100644 --- a/src/FDM/JSBSim/initialization/FGInitialCondition.h +++ b/src/FDM/JSBSim/initialization/FGInitialCondition.h @@ -54,7 +54,7 @@ INCLUDES DEFINITIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -#define ID_INITIALCONDITION "$Id: FGInitialCondition.h,v 1.44 2016/01/10 16:35:28 bcoconni Exp $" +#define ID_INITIALCONDITION "$Id: FGInitialCondition.h,v 1.46 2016/07/03 17:20:55 bcoconni Exp $" /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FORWARD DECLARATIONS @@ -71,7 +71,8 @@ class FGPropertyManager; class Element; typedef enum { setvt, setvc, setve, setmach, setuvw, setned, setvg } speedset; -typedef enum { setasl, setagl} altitudeset; +typedef enum { setasl, setagl } altitudeset; +typedef enum { setgeoc, setgeod } latitudeset; /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS DOCUMENTATION @@ -219,7 +220,7 @@ CLASS DOCUMENTATION @property ic/r-rad_sec (read/write) Yaw rate initial condition in radians/second @author Tony Peden - @version "$Id: FGInitialCondition.h,v 1.44 2016/01/10 16:35:28 bcoconni Exp $" + @version "$Id: FGInitialCondition.h,v 1.46 2016/07/03 17:20:55 bcoconni Exp $" */ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -677,9 +678,11 @@ private: FGMatrix33 Tw2b, Tb2w; double alpha, beta; + double a, e2; speedset lastSpeedSet; altitudeset lastAltitudeSet; + latitudeset lastLatitudeSet; unsigned int enginesRunning; int needTrim; @@ -699,6 +702,8 @@ private: double GetBodyVelFpsIC(int idx) const; void calcAeroAngles(const FGColumnVector3& _vt_BODY); void calcThetaBeta(double alfa, const FGColumnVector3& _vt_NED); + double ComputeGeodAltitude(double geodLatitude); + bool LoadLatitude(Element* position_el); void Debug(int from); }; } diff --git a/src/FDM/JSBSim/models/FGLGear.cpp b/src/FDM/JSBSim/models/FGLGear.cpp index 3d552dddf..00ddba4fe 100644 --- a/src/FDM/JSBSim/models/FGLGear.cpp +++ b/src/FDM/JSBSim/models/FGLGear.cpp @@ -61,7 +61,7 @@ DEFINITIONS GLOBAL DATA %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -IDENT(IdSrc,"$Id: FGLGear.cpp,v 1.123 2016/05/16 18:19:57 bcoconni Exp $"); +IDENT(IdSrc,"$Id: FGLGear.cpp,v 1.124 2016/06/25 17:48:02 bcoconni Exp $"); IDENT(IdHdr,ID_LGEAR); // Body To Structural (body frame is rotated 180 deg about Y and lengths are given in @@ -555,7 +555,9 @@ void FGLGear::CrashDetect(void) GetMoments().Magnitude() > 5000000000.0 || SinkRate > 1.4666*30 ) && !fdmex->IntegrationSuspended()) { - PutMessage("Crash Detected: Simulation FREEZE."); + ostringstream buf; + buf << "*CRASH DETECTED* " << fdmex->GetSimTime() << " seconds: " << name; + PutMessage(buf.str()); // fdmex->SuspendIntegration(); } } diff --git a/src/FDM/JSBSim/models/flight_control/FGKinemat.h b/src/FDM/JSBSim/models/flight_control/FGKinemat.h index ff06bfbe9..70d8e6d77 100644 --- a/src/FDM/JSBSim/models/flight_control/FGKinemat.h +++ b/src/FDM/JSBSim/models/flight_control/FGKinemat.h @@ -44,7 +44,7 @@ INCLUDES DEFINITIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -#define ID_FLAPS "$Id: FGKinemat.h,v 1.12 2016/06/12 14:47:46 bcoconni Exp $" +#define ID_FLAPS "$Id: FGKinemat.h,v 1.13 2016/07/09 11:35:39 bcoconni Exp $" /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FORWARD DECLARATIONS @@ -56,14 +56,16 @@ namespace JSBSim { CLASS DOCUMENTATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -/** Encapsulates a kinematic (mechanical) component for the flight control system. -This component models the action of a moving effector, such as an aerosurface or -other mechanized entity such as a landing gear strut for the purpose of effecting -vehicle control or configuration. The form of the component specification is: +/** Encapsulates a kinematic (mechanical) component for the flight control +system. This component models the action of a moving effector, such as an +aerosurface or other mechanized entity such as a landing gear strut for the +purpose of effecting vehicle control or configuration. The form of the component +specification is: @code [-]property + [] number @@ -102,6 +104,13 @@ takes to get to that position from an adjacent setting. For example: In this case, it takes 5 seconds to get to a 1 setting. As this is a software mechanization of a servo-actuator, there should be an output specified. + +Positions must be given in ascending order. + +By default, the input is assumed to be in the range [-1;1] and is scaled to the +value specified in the last tag. This behavior can be modified by +adding a tag to the component definition: in that case, the input +value is directly used to determine the current position of the component. */ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/FDM/JSBSim/models/propulsion/FGTurboProp.cpp b/src/FDM/JSBSim/models/propulsion/FGTurboProp.cpp old mode 100644 new mode 100755 index e3533049c..7f5b5eee8 --- a/src/FDM/JSBSim/models/propulsion/FGTurboProp.cpp +++ b/src/FDM/JSBSim/models/propulsion/FGTurboProp.cpp @@ -55,7 +55,7 @@ using namespace std; namespace JSBSim { -IDENT(IdSrc,"$Id: FGTurboProp.cpp,v 1.32 2015/09/27 09:54:21 bcoconni Exp $"); +IDENT(IdSrc,"$Id: FGTurboProp.cpp,v 1.35 2016/07/10 12:39:28 bcoconni Exp $"); IDENT(IdHdr,ID_TURBOPROP); /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -64,11 +64,10 @@ CLASS IMPLEMENTATION FGTurboProp::FGTurboProp(FGFDMExec* exec, Element *el, int engine_number, struct Inputs& input) : FGEngine(engine_number, input), - ITT_N1(NULL), EnginePowerRPM_N1(NULL), EnginePowerVC(NULL), EnginePowerVCFN(NULL), CombustionEfficiency_N1(NULL), - FDMExec(exec) + ITT_N1(NULL), EnginePowerRPM_N1(NULL), EnginePowerVC(NULL), + CombustionEfficiency_N1(NULL) { SetDefaults(); - Load(exec, el); Debug(0); } @@ -79,7 +78,8 @@ FGTurboProp::~FGTurboProp() { delete ITT_N1; delete EnginePowerRPM_N1; - delete EnginePowerVC; + if (dynamic_cast(EnginePowerVC)) + delete EnginePowerVC; delete CombustionEfficiency_N1; Debug(1); } @@ -106,7 +106,7 @@ bool FGTurboProp::Load(FGFDMExec* exec, Element *el) string property_prefix = CreateIndexedPropertyName("propulsion/engine", EngineNumber); - EnginePowerVCFN = GetPreFunction(property_prefix+"/EnginePowerVC"); + EnginePowerVC = GetPreFunction(property_prefix+"/EnginePowerVC"); // ToDo: Need to make sure units are properly accounted for below. @@ -115,12 +115,8 @@ bool FGTurboProp::Load(FGFDMExec* exec, Element *el) MilThrust = el->FindElementValueAsNumberConvertTo("milthrust","LBS"); if (el->FindElement("idlen1")) IdleN1 = el->FindElementValueAsNumber("idlen1"); - if (el->FindElement("idlen2")) - 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); @@ -146,17 +142,16 @@ bool FGTurboProp::Load(FGFDMExec* exec, Element *el) if (el->FindElement("itt_delay")) ITT_Delay = el->FindElementValueAsNumber("itt_delay"); - Element *table_element; - string name; + Element *table_element = el->FindElement("table"); FGPropertyManager* PropertyManager = exec->GetPropertyManager(); - while (true) { - table_element = el->FindNextElement("table"); - if (!table_element) break; - name = table_element->GetAttributeValue("name"); - if (!EnginePowerVCFN && name == "EnginePowerVC") { + while (table_element) { + string name = table_element->GetAttributeValue("name"); + if (!EnginePowerVC && name == "EnginePowerVC") { EnginePowerVC = new FGTable(PropertyManager, table_element); - std::cerr << "Note: Using the EnginePowerVC without enclosed tag is deprecated" << std::endl; + cerr << table_element->ReadFrom() + <<"Note: Using the EnginePowerVC without enclosed tag is deprecated" + << endl; } else if (name == "EnginePowerRPM_N1") { EnginePowerRPM_N1 = new FGTable(PropertyManager, table_element); } else if (name == "ITT_N1") { @@ -167,13 +162,13 @@ bool FGTurboProp::Load(FGFDMExec* exec, Element *el) cerr << el->ReadFrom() << "Unknown table type: " << name << " in turboprop definition." << endl; } + table_element = el->FindNextElement("table"); } // Pre-calculations and initializations delay=1; N1_factor = MaxN1 - IdleN1; - N2_factor = MaxN2 - IdleN2; OilTemp_degK = in.TAT_c + 273.0; // default table based on '9.333 - (N1)/12.0' approximation @@ -188,7 +183,7 @@ bool FGTurboProp::Load(FGFDMExec* exec, Element *el) *CombustionEfficiency_N1 << 110.0 << 6.0; } - bindmodel(exec->GetPropertyManager()); + bindmodel(PropertyManager); return true; } @@ -200,8 +195,6 @@ void FGTurboProp::Calculate(void) { RunPreFunctions(); - TAT = in.TAT_c; - ThrottlePos = in.ThrottlePos[EngineNumber]; /* The thruster controls the engine RPM because it encapsulates the gear ratio and other transmission variables */ @@ -230,16 +223,15 @@ void FGTurboProp::Calculate(void) if ((phase == tpTrim) && (in.TotalDeltaT > 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; + Eng_ITT_degC = in.TAT_c; + Eng_Temperature = in.TAT_c; + OilTemp_degK = in.TAT_c+273.15; } } @@ -312,9 +304,9 @@ double FGTurboProp::Off(void) //allow the air turn with generator 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); + OilTemp_degK = ExpSeek(&OilTemp_degK,273.15 + in.TAT_c, 400 , 400); - Eng_Temperature = ExpSeek(&Eng_Temperature,TAT,300,400); + Eng_Temperature = ExpSeek(&Eng_Temperature,in.TAT_c,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); @@ -338,7 +330,7 @@ double FGTurboProp::Run(void) N1 = ExpSeek(&N1, IdleN1 + ThrottlePos * N1_factor, Idle_Max_Delay, Idle_Max_Delay * 2.4); EngPower_HP = EnginePowerRPM_N1->GetValue(RPM,N1); - EngPower_HP *= EnginePowerVCFN ? EnginePowerVCFN->GetValue() : EnginePowerVC->GetValue(); + EngPower_HP *= EnginePowerVC->GetValue(); if (EngPower_HP > MaxPower) EngPower_HP = MaxPower; CombustionEfficiency = CombustionEfficiency_N1->GetValue(N1); @@ -377,17 +369,16 @@ double FGTurboProp::SpinUp(void) N1 = ExpSeek(&N1, StarterN1, Idle_Max_Delay * 6, Idle_Max_Delay * 2.4); - Eng_Temperature = ExpSeek(&Eng_Temperature,TAT,300,400); + Eng_Temperature = ExpSeek(&Eng_Temperature,in.TAT_c,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); - OilTemp_degK = ExpSeek(&OilTemp_degK,273.15 + TAT, 400 , 400); + OilTemp_degK = ExpSeek(&OilTemp_degK,273.15 + in.TAT_c, 400 , 400); 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(RPM,N1); - EngPower_HP *= EnginePowerVCFN ? EnginePowerVCFN->GetValue() : EnginePowerVC->GetValue(); + EngPower_HP *= EnginePowerVC->GetValue(); if (EngPower_HP > MaxPower) EngPower_HP = MaxPower; if (StartTime>=0) StartTime+=in.TotalDeltaT; @@ -406,12 +397,12 @@ double FGTurboProp::Start(void) double EngPower_HP = 0.0; EngStarting = false; - if ((N1 > 15.0) && !Starved) { // minimum 15% N2 needed for start + if ((N1 > 15.0) && !Starved) { // minimum 15% N1 needed for start double old_N1 = N1; Cranking = true; // provided for sound effects signal if (N1 < IdleN1) { EngPower_HP = EnginePowerRPM_N1->GetValue(RPM,N1); - EngPower_HP *= EnginePowerVCFN ? EnginePowerVCFN->GetValue() : EnginePowerVC->GetValue(); + 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); CombustionEfficiency = CombustionEfficiency_N1->GetValue(N1); @@ -430,7 +421,7 @@ double FGTurboProp::Start(void) Cranking = false; FuelFlow_pph = 0; } - } else { // no start if N2 < 15% or Starved + } else { // no start if N1 < 15% or Starved phase = tpOff; Starter = false; } @@ -483,23 +474,15 @@ double FGTurboProp::ExpSeek(double *var, double target, double accel_tau, double void FGTurboProp::SetDefaults(void) { // Name = "Not defined"; - N1 = N2 = 0.0; + N1 = 0.0; HP = 0.0; Type = etTurboprop; MilThrust = 10000.0; IdleN1 = 30.0; - IdleN2 = 60.0; MaxN1 = 100.0; - MaxN2 = 100.0; - InletPosition = 1.0; - NozzlePosition = 1.0; Reversed = false; Cutoff = true; phase = tpOff; - Stalled = false; - Seized = false; - Overtemp = false; - Fire = false; Eng_ITT_degC = 0.0; GeneratorPower=true; @@ -523,7 +506,6 @@ string FGTurboProp::GetEngineLabels(const string& delimiter) std::ostringstream buf; buf << Name << "_N1[" << EngineNumber << "]" << delimiter - << Name << "_N2[" << EngineNumber << "]" << delimiter << Name << "_PwrAvail[" << EngineNumber << "]" << delimiter << Thruster->GetThrusterLabels(EngineNumber, delimiter); @@ -537,7 +519,6 @@ string FGTurboProp::GetEngineValues(const string& delimiter) std::ostringstream buf; buf << N1 << delimiter - << N2 << delimiter << HP << delimiter << Thruster->GetThrusterValues(EngineNumber,delimiter); @@ -548,12 +529,12 @@ string FGTurboProp::GetEngineValues(const string& delimiter) int FGTurboProp::InitRunning(void) { - FDMExec->SuspendIntegration(); + double dt = in.TotalDeltaT; + in.TotalDeltaT = 0.0; Cutoff=false; Running=true; - N2=16.0; Calculate(); - FDMExec->ResumeIntegration(); + in.TotalDeltaT = dt; return phase==tpRun; } @@ -565,8 +546,6 @@ void FGTurboProp::bindmodel(FGPropertyManager* PropertyManager) 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"; diff --git a/src/FDM/JSBSim/models/propulsion/FGTurboProp.h b/src/FDM/JSBSim/models/propulsion/FGTurboProp.h old mode 100644 new mode 100755 index 74df2d922..cc3e00829 --- a/src/FDM/JSBSim/models/propulsion/FGTurboProp.h +++ b/src/FDM/JSBSim/models/propulsion/FGTurboProp.h @@ -46,7 +46,7 @@ INCLUDES #include "FGEngine.h" #include "math/FGTable.h" -#define ID_TURBOPROP "$Id: FGTurboProp.h,v 1.21 2015/09/27 09:54:21 bcoconni Exp $" +#define ID_TURBOPROP "$Id: FGTurboProp.h,v 1.24 2016/07/10 12:39:28 bcoconni Exp $" /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FORWARD DECLARATIONS @@ -102,13 +102,13 @@ public: /// Destructor ~FGTurboProp(); - enum phaseType { tpOff, tpRun, tpSpinUp, tpStart, tpStall, tpSeize, tpTrim }; + enum phaseType { tpOff, tpRun, tpSpinUp, tpStart, tpTrim }; void Calculate(void); double CalcFuelNeed(void); double GetPowerAvailable(void) const { return (HP * hptoftlbssec); } - double GetRPM(void) const { return (RPM); } + double GetRPM(void) const { return RPM; } double GetIeluThrottle(void) const { return (ThrottlePos); } bool GetIeluIntervent(void) const { return Ielu_intervent; } @@ -117,16 +117,10 @@ public: phaseType GetPhase(void) const { return phase; } - bool GetOvertemp(void) const {return Overtemp; } - bool GetFire(void) const { return Fire; } bool GetReversed(void) const { return Reversed; } bool GetCutoff(void) const { return Cutoff; } - int GetIgnition(void) const {return Ignition;} - double GetInlet(void) const { return InletPosition; } - double GetNozzle(void) const { return NozzlePosition; } double GetN1(void) const {return N1;} - double GetN2(void) const {return N2;} double GetEPR(void) const {return EPR;} double GetITT(void) const {return Eng_ITT_degC;} double GetEngStarting(void) const { return EngStarting; } @@ -137,7 +131,6 @@ public: inline bool GetGeneratorPower(void) const { return GeneratorPower; } inline int GetCondition(void) const { return Condition; } - void SetIgnition(int ignition) {Ignition = ignition;} void SetPhase( phaseType p ) { phase = p; } void SetEPR(double epr) {EPR = epr;} void SetReverse(bool reversed) { Reversed = reversed; } @@ -154,29 +147,17 @@ private: phaseType phase; ///< Operating mode, or "phase" double MilThrust; ///< Maximum Unaugmented Thrust, static @ S.L. (lbf) double IdleN1; ///< Idle N1 - double IdleN2; ///< Idle N2 double N1; ///< N1 - double N2; ///< N2 double MaxN1; ///< N1 at 100% throttle - double MaxN2; ///< N2 at 100% throttle double delay; ///< Inverse spool-up time from idle to 100% (seconds) double N1_factor; ///< factor to tie N1 and throttle - double N2_factor; ///< factor to tie N2 and throttle double ThrottlePos; ///< FCS-supplied throttle position, modified locally - double TAT; ///< total air temperature (deg C) - bool Stalled; ///< true if engine is compressor-stalled - bool Seized; ///< true if inner spool is seized - bool Overtemp; ///< true if EGT exceeds limits - bool Fire; ///< true if engine fire detected bool Reversed; bool Cutoff; - int Ignition; double EPR; double OilPressure_psi; double OilTemp_degK; - double InletPosition; - double NozzlePosition; double Ielu_max_torque; // max propeller torque (before ielu intervent) bool Ielu_intervent; @@ -190,8 +171,6 @@ private: double StarterN1; // rotates of generator maked by starter [%] double MaxStartingTime; // maximal time for start [s] (-1 means not used) double RPM; // shaft RPM - //double Velocity; - //double rho; double PSFC; // Power specific fuel comsumption [lb/(HP*hr)] at best efficiency double CombustionEfficiency; @@ -220,10 +199,8 @@ private: FGTable* ITT_N1; // ITT temperature depending on throttle command FGTable* EnginePowerRPM_N1; - FGTable* EnginePowerVC; - FGFunction* EnginePowerVCFN; + FGParameter* EnginePowerVC; FGTable* CombustionEfficiency_N1; - FGFDMExec* FDMExec; }; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%