From 4aff7b279db80407d82d0a5556738cf111501457 Mon Sep 17 00:00:00 2001 From: ehofman Date: Mon, 1 Jun 2009 08:52:34 +0000 Subject: [PATCH] Upgrade to JSBSim 1.0-prerelease --- src/FDM/JSBSim/FGFDMExec.cpp | 132 ++++++++++-------- src/FDM/JSBSim/FGFDMExec.h | 61 ++++---- src/FDM/JSBSim/FGJSBBase.h | 14 +- src/FDM/JSBSim/JSBSim.cxx | 28 ++-- .../initialization/FGInitialCondition.cpp | 49 ++++--- .../initialization/FGInitialCondition.h | 26 ++-- src/FDM/JSBSim/input_output/FGScript.cpp | 20 ++- src/FDM/JSBSim/models/FGAerodynamics.cpp | 1 + src/FDM/JSBSim/models/FGAtmosphere.cpp | 2 +- src/FDM/JSBSim/models/FGAuxiliary.h | 14 ++ src/FDM/JSBSim/models/FGInertial.cpp | 1 + src/FDM/JSBSim/models/FGLGear.cpp | 11 +- src/FDM/JSBSim/models/FGMassBalance.cpp | 14 +- src/FDM/JSBSim/models/FGOutput.cpp | 14 +- src/FDM/JSBSim/models/FGPropagate.cpp | 59 ++++---- src/FDM/JSBSim/models/FGPropagate.h | 36 +++-- src/FDM/JSBSim/models/atmosphere/FGMSIS.cpp | 2 +- .../models/flight_control/FGActuator.cpp | 2 +- .../JSBSim/models/flight_control/FGSensor.cpp | 51 ++++++- .../JSBSim/models/flight_control/FGSensor.h | 11 +- src/FDM/JSBSim/models/propulsion/FGPiston.cpp | 8 +- .../JSBSim/models/propulsion/FGTurbine.cpp | 20 ++- src/FDM/JSBSim/models/propulsion/FGTurbine.h | 1 + 23 files changed, 354 insertions(+), 223 deletions(-) diff --git a/src/FDM/JSBSim/FGFDMExec.cpp b/src/FDM/JSBSim/FGFDMExec.cpp index 72f37d4e5..a6b5a7367 100644 --- a/src/FDM/JSBSim/FGFDMExec.cpp +++ b/src/FDM/JSBSim/FGFDMExec.cpp @@ -90,7 +90,6 @@ void checkTied ( FGPropertyManager *node ) for (int i=0; igetChild(i)->nChildren() ) { -// cout << "Untieing " << node->getChild(i)->getName() << " property branch." << endl; checkTied( (FGPropertyManager*)node->getChild(i) ); } else if ( node->getChild(i)->isTied() ) { name = ((FGPropertyManager*)node->getChild(i))->GetFullyQualifiedName(); @@ -128,19 +127,12 @@ FGFDMExec::FGFDMExec(FGPropertyManager* root) : Root(root) Script = 0; modelLoaded = false; - IsSlave = false; + IsChild = false; holding = false; Terminate = false; - // Multiple FDM's are stopped for now. We need to ensure that - // the "user" instance always gets the zeroeth instance number, - // because there may be instruments or scripts tied to properties - // in the jsbsim[0] node. - // ToDo: it could be that when JSBSim is reset and a new FDM is wanted, that - // process might try setting FDMctr = 0. Then the line below would not need - // to be commented out. - IdFDM = FDMctr; - //FDMctr++; + IdFDM = FDMctr; // The main (parent) JSBSim instance is always the "zeroth" + FDMctr++; // instance. "child" instances are loaded last. try { char* num = getenv("JSBSIM_DEBUG"); @@ -189,10 +181,10 @@ FGFDMExec::~FGFDMExec() cout << "Caught error: " << msg << endl; } - for (unsigned int i=1; iexec; - SlaveFDMList.clear(); + for (unsigned int i=1; iexec; + ChildFDMList.clear(); - //ToDo remove property catalog. + PropertyCatalog.clear(); Debug(1); } @@ -355,9 +347,9 @@ bool FGFDMExec::Run(void) Debug(2); - for (unsigned int i=1; iexec->State->Initialize(); // Transfer state to the slave FDM -// SlaveFDMList[i]->exec->Run(); + for (unsigned int i=1; iAssignState(Propagate); // Transfer state to the child FDM + ChildFDMList[i]->Run(); } // returns true if success @@ -453,8 +445,8 @@ vector FGFDMExec::EnumerateFDMs(void) FDMList.push_back(Aircraft->GetAircraftName()); - for (unsigned int i=1; iexec->GetAircraft()->GetAircraftName()); + for (unsigned int i=1; iexec->GetAircraft()->GetAircraftName()); } return FDMList; @@ -511,10 +503,16 @@ bool FGFDMExec::LoadModel(string model, bool addModelToPath) Allocate(); } + int saved_debug_lvl = debug_lvl; + document = LoadXMLDocument(aircraftCfgFileName); // "document" is a class member if (document) { + if (IsChild) debug_lvl = 0; + ReadPrologue(document); + if (IsChild) debug_lvl = saved_debug_lvl; + // Process the fileheader element in the aircraft config file. This element is OPTIONAL. element = document->FindElement("fileheader"); if (element) { @@ -525,6 +523,8 @@ bool FGFDMExec::LoadModel(string model, bool addModelToPath) } } + if (IsChild) debug_lvl = 0; + // Process the metrics element. This element is REQUIRED. element = document->FindElement("metrics"); if (element) { @@ -662,18 +662,27 @@ bool FGFDMExec::LoadModel(string model, bool addModelToPath) element = document->FindNextElement("output"); } - // Lastly, process the slave element. This element is OPTIONAL - and NOT YET SUPPORTED. - element = document->FindElement("slave"); + // Lastly, process the child element. This element is OPTIONAL - and NOT YET SUPPORTED. + element = document->FindElement("child"); if (element) { - result = ReadSlave(element); + result = ReadChild(element); if (!result) { - cerr << endl << "Aircraft slave element has problems in file " << aircraftCfgFileName << endl; + cerr << endl << "Aircraft child element has problems in file " << aircraftCfgFileName << endl; return result; } } modelLoaded = true; + if (debug_lvl > 0) { + cout << endl << fgblue << highint + << "End of vehicle configuration loading." << endl + << "-------------------------------------------------------------------------------" + << reset << endl; + } + + if (IsChild) debug_lvl = saved_debug_lvl; + } else { cerr << fgred << " JSBSim failed to open the configuration file: " << aircraftCfgFileName @@ -745,16 +754,20 @@ bool FGFDMExec::ReadFileHeader(Element* el) { bool result = true; // true for success - if (debug_lvl & ~1) return result; + if (debug_lvl == 0) return result; + if (IsChild) { + cout << endl <FindElement("description")) + cout << " Description: " << el->FindElement("description")->GetDataLine() << endl; if (el->FindElement("author")) cout << " Model Author: " << el->FindElement("author")->GetDataLine() << endl; if (el->FindElement("filecreationdate")) cout << " Creation Date: " << el->FindElement("filecreationdate")->GetDataLine() << endl; if (el->FindElement("version")) cout << " Version: " << el->FindElement("version")->GetDataLine() << endl; - if (el->FindElement("description")) - cout << " Description: " << el->FindElement("description")->GetDataLine() << endl; return result; } @@ -821,54 +834,51 @@ bool FGFDMExec::ReadPrologue(Element* el) // el for ReadPrologue is the document //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -bool FGFDMExec::ReadSlave(Element* el) +bool FGFDMExec::ReadChild(Element* el) { - // Add a new slaveData object to the slave FDM list - // Populate that slaveData element with a new FDMExec object - // Set the IsSlave flag for that FDMExec object + // Add a new childData object to the child FDM list + // Populate that childData element with a new FDMExec object + // Set the IsChild flag for that FDMExec object // Get the aircraft name - // set debug level to print out no additional data for slave objects + // set debug level to print out no additional data for child objects // Load the model given the aircraft name // reset debug level to prior setting - int saved_debug_lvl = debug_lvl; string token; - SlaveFDMList.push_back(new slaveData); - SlaveFDMList.back()->exec = new FGFDMExec(); - SlaveFDMList.back()->exec->SetSlave(true); -/* - string AircraftName = AC_cfg->GetValue("file"); + struct childData* child = new childData; - debug_lvl = 0; // turn off debug output for slave vehicle + child->exec = new FGFDMExec(); + child->exec->SetChild(true); - SlaveFDMList.back()->exec->SetAircraftPath( AircraftPath ); - SlaveFDMList.back()->exec->SetEnginePath( EnginePath ); - SlaveFDMList.back()->exec->SetSystemsPath( SystemsPath ); - SlaveFDMList.back()->exec->LoadModel(AircraftName); - debug_lvl = saved_debug_lvl; // turn debug output back on for master vehicle + string childAircraft = el->GetAttributeValue("name"); + string sMated = el->GetAttributeValue("mated"); + if (sMated == "false") child->mated = false; // child objects are mated by default. + string sInternal = el->GetAttributeValue("internal"); + if (sInternal == "true") child->internal = true; // child objects are external by default. - AC_cfg->GetNextConfigLine(); - while ((token = AC_cfg->GetValue()) != string("/SLAVE")) { - *AC_cfg >> token; - if (token == "xloc") { *AC_cfg >> SlaveFDMList.back()->x; } - else if (token == "yloc") { *AC_cfg >> SlaveFDMList.back()->y; } - else if (token == "zloc") { *AC_cfg >> SlaveFDMList.back()->z; } - else if (token == "pitch") { *AC_cfg >> SlaveFDMList.back()->pitch;} - else if (token == "yaw") { *AC_cfg >> SlaveFDMList.back()->yaw; } - else if (token == "roll") { *AC_cfg >> SlaveFDMList.back()->roll; } - else cerr << "Unknown identifier: " << token << " in slave vehicle definition" << endl; + child->exec->SetAircraftPath( AircraftPath ); + child->exec->SetEnginePath( EnginePath ); + child->exec->SetSystemsPath( SystemsPath ); + child->exec->LoadModel(childAircraft); + + Element* location = el->FindElement("location"); + if (location) { + child->Loc = location->FindElementTripletConvertTo("IN"); + } else { + cerr << endl << highint << fgred << " No location was found for this child object!" << reset << endl; + exit(-1); } -*/ - if (debug_lvl > 0) { - cout << " X = " << SlaveFDMList.back()->x << endl; - cout << " Y = " << SlaveFDMList.back()->y << endl; - cout << " Z = " << SlaveFDMList.back()->z << endl; - cout << " Pitch = " << SlaveFDMList.back()->pitch << endl; - cout << " Yaw = " << SlaveFDMList.back()->yaw << endl; - cout << " Roll = " << SlaveFDMList.back()->roll << endl; + + Element* orientation = el->FindElement("orient"); + if (orientation) { + child->Orient = orientation->FindElementTripletConvertTo("RAD"); + } else if (debug_lvl > 0) { + cerr << endl << highint << " No orientation was found for this child object! Assuming 0,0,0." << reset << endl; } + ChildFDMList.push_back(child); + return true; } diff --git a/src/FDM/JSBSim/FGFDMExec.h b/src/FDM/JSBSim/FGFDMExec.h index 9ab3e33b2..904e8e43a 100644 --- a/src/FDM/JSBSim/FGFDMExec.h +++ b/src/FDM/JSBSim/FGFDMExec.h @@ -51,6 +51,7 @@ INCLUDES #include #include #include +#include #include #include @@ -177,6 +178,32 @@ CLASS DECLARATION class FGFDMExec : public FGJSBBase, public FGXMLFileRead { + struct childData { + FGFDMExec* exec; + string info; + FGColumnVector3 Loc; + FGColumnVector3 Orient; + bool mated; + bool internal; + + childData(void) { + info = ""; + Loc = FGColumnVector3(0,0,0); + Orient = FGColumnVector3(0,0,0); + mated = true; + internal = false; + } + + void Run(void) {exec->Run();} + void AssignState(FGPropagate* source_prop) { + exec->GetPropagate()->SetVState(source_prop->GetVState()); + } + + ~childData(void) { + delete exec; + } + }; + public: /// Default constructor @@ -335,8 +362,12 @@ public: FGPropertyManager* GetPropertyManager(void); /// Returns a vector of strings representing the names of all loaded models (future) vector EnumerateFDMs(void); - /// Marks this instance of the Exec object as a "slave" object. - void SetSlave(bool s) {IsSlave = s;} + /// Gets the number of child FDMs. + int GetFDMCount(void) {return ChildFDMList.size();} + /// Gets a particular child FDM. + childData* GetChildFDM(int i) {return ChildFDMList[i];} + /// Marks this instance of the Exec object as a "child" object. + void SetChild(bool ch) {IsChild = ch;} /** Sets the output (logging) mechanism for this run. Calling this function passes the name of an output directives file to @@ -443,7 +474,7 @@ private: bool holding; bool Constructing; bool modelLoaded; - bool IsSlave; + bool IsChild; string modelName; string AircraftPath; string FullAircraftPath; @@ -455,26 +486,6 @@ private: bool trim_status; int ta_mode; - - struct slaveData { - FGFDMExec* exec; - string info; - double x, y, z; - double roll, pitch, yaw; - bool mated; - - slaveData(void) { - info = ""; - x = y = z = 0.0; - roll = pitch = yaw = 0.0; - mated = true; - } - - ~slaveData(void) { - delete exec; - } - }; - static FGPropertyManager *master; FGModel* FirstModel; @@ -502,10 +513,10 @@ private: vector PropertyCatalog; vector Outputs; - vector SlaveFDMList; + vector ChildFDMList; bool ReadFileHeader(Element*); - bool ReadSlave(Element*); + bool ReadChild(Element*); bool ReadPrologue(Element*); void ResetToInitialConditions(int mode); bool Allocate(void); diff --git a/src/FDM/JSBSim/FGJSBBase.h b/src/FDM/JSBSim/FGJSBBase.h index 93e9d431d..8ec700a15 100644 --- a/src/FDM/JSBSim/FGJSBBase.h +++ b/src/FDM/JSBSim/FGJSBBase.h @@ -156,7 +156,7 @@ public: /** Places a Message structure on the Message queue. @param msg pointer to a Message structure @return pointer to a Message structure */ -void PutMessage(const Message& msg); + void PutMessage(const Message& msg); /** Creates a message with the given text and places it on the queue. @param text message text @return pointer to a Message structure */ @@ -165,17 +165,17 @@ void PutMessage(const Message& msg); @param text message text @param bVal boolean value associated with the message @return pointer to a Message structure */ -void PutMessage(const string& text, bool bVal); + void PutMessage(const string& text, bool bVal); /** Creates a message with the given text and integer value and places it on the queue. @param text message text @param iVal integer value associated with the message @return pointer to a Message structure */ -void PutMessage(const string& text, int iVal); + void PutMessage(const string& text, int iVal); /** Creates a message with the given text and double value and places it on the queue. @param text message text @param dVal double value associated with the message @return pointer to a Message structure */ -void PutMessage(const string& text, double dVal); + void PutMessage(const string& text, double dVal); /** Reads the message on the queue (but does not delete it). @return 1 if some messages */ int SomeMessages(void); @@ -295,6 +295,8 @@ void PutMessage(const string& text, double dVal); static double Constrain(double min, double value, double max) { return valuemax?(max):(value)); } + + static double sign(double num) {return num>=0.0?1.0:-1.0;} protected: static Message localMsg; @@ -341,6 +343,8 @@ protected: static int phase = 0; double X; + V1 = V2 = S = X = 0.0; + if (phase == 0) { do { double U1 = (double)rand() / RAND_MAX; @@ -351,7 +355,7 @@ protected: S = V1 * V1 + V2 * V2; } while(S >= 1 || S == 0); - X = V1 * sqrt(-2 * log(S) / S); + X = V1 * sqrt(-2 * log(S) / S); } else X = V2 * sqrt(-2 * log(S) / S); diff --git a/src/FDM/JSBSim/JSBSim.cxx b/src/FDM/JSBSim/JSBSim.cxx index 5a1be0a29..b36c19657 100644 --- a/src/FDM/JSBSim/JSBSim.cxx +++ b/src/FDM/JSBSim/JSBSim.cxx @@ -85,7 +85,7 @@ public: FGFSGroundCallback(FGJSBsim* ifc) : mInterface(ifc) {} virtual ~FGFSGroundCallback() {} - /** Get the altitude above sea level depenent on the location. */ + /** Get the altitude above sea level dependent on the location. */ virtual double GetAltitude(const FGLocation& l) const { double pt[3] = { SG_FEET_TO_METER*l(eX), SG_FEET_TO_METER*l(eY), @@ -145,13 +145,6 @@ FGJSBsim::FGJSBsim( double dt ) fdmex = new FGFDMExec( (FGPropertyManager*)globals->get_props() ); - // begin ugly hack - // Untie the write-state-file property to avoid creating an initfile.xml - // file on each FlightGear reset. - fgGetNode("/fdm/jsbsim/simulation/write-state-file")->untie(); - fgGetNode("/fdm/jsbsim/simulation")->removeChild("write-state-file", false); - // end ugly hack - // Register ground callback. fdmex->SetGroundCallback( new FGFSGroundCallback(this) ); @@ -391,7 +384,7 @@ void FGJSBsim::init() SG_LOG( SG_FLIGHT, SG_INFO, " Longitude: " << Propagate->GetLocation().GetLongitudeDeg() << " deg" ); SG_LOG( SG_FLIGHT, SG_INFO, " Altitude: " - << Propagate->Geth() << " feet" ); + << Propagate->GetAltitudeASL() << " feet" ); SG_LOG( SG_FLIGHT, SG_INFO, " loaded initial conditions" ); SG_LOG( SG_FLIGHT, SG_INFO, " set dt" ); @@ -438,7 +431,7 @@ void FGJSBsim::update( double dt ) double alt, slr, lat, lon; FGColumnVector3 cart = Auxiliary->GetLocationVRP(); if ( needTrim && startup_trim->getBoolValue() ) { - alt = fgic->GetAltitudeFtIC(); + alt = fgic->GetAltitudeASLFtIC(); slr = fgic->GetSeaLevelRadiusFtIC(); lat = fgic->GetLatitudeDegIC() * SGD_DEGREES_TO_RADIANS; lon = fgic->GetLongitudeDegIC() * SGD_DEGREES_TO_RADIANS; @@ -452,7 +445,7 @@ void FGJSBsim::update( double dt ) SG_LOG(SG_FLIGHT, SG_WARN, "FGInterface is being called without scenery below the aircraft!"); - alt = fgic->GetAltitudeFtIC(); + alt = fgic->GetAltitudeASLFtIC(); SG_LOG(SG_FLIGHT, SG_WARN, "altitude = " << alt); slr = fgic->GetSeaLevelRadiusFtIC(); @@ -479,10 +472,10 @@ void FGJSBsim::update( double dt ) + contact[2]*contact[2]) - fgic->GetSeaLevelRadiusFtIC(); SG_LOG(SG_FLIGHT, SG_INFO, - "Ready to trim, terrain altitude is: " + "Ready to trim, terrain elevation is: " << terrain_alt * SG_METER_TO_FEET ); - fgic->SetTerrainAltitudeFtIC( terrain_alt ); + fgic->SetTerrainElevationFtIC( terrain_alt ); do_trim(); } else { fdmex->RunIC(); //apply any changes made through the set_ functions @@ -638,7 +631,7 @@ bool FGJSBsim::copy_to_JSBsim() } Propulsion->SetFuelFreeze((fgGetNode("/sim/freeze/fuel",true))->getBoolValue()); - fdmex->SetSlave(slaved->getBoolValue()); + fdmex->SetChild(slaved->getBoolValue()); return true; } @@ -963,6 +956,7 @@ void FGJSBsim::set_Longitude(double lon) needTrim=true; } +// Sets the altitude above sea level. void FGJSBsim::set_Altitude(double alt) { static SGConstPropertyNode_ptr latitude = fgGetNode("/position/latitude-deg"); @@ -981,9 +975,9 @@ void FGJSBsim::set_Altitude(double alt) _set_Sea_level_radius( sea_level_radius_meters * SG_METER_TO_FEET ); fgic->SetSeaLevelRadiusFtIC( sea_level_radius_meters * SG_METER_TO_FEET ); SG_LOG(SG_FLIGHT, SG_INFO, - "Terrain altitude: " << cur_fdm_state->get_Runway_altitude() * SG_METER_TO_FEET ); + "Terrain elevation: " << cur_fdm_state->get_Runway_altitude() * SG_METER_TO_FEET ); fgic->SetLatitudeRadIC( lat_geoc ); - fgic->SetAltitudeFtIC(alt); + fgic->SetAltitudeASLFtIC(alt); needTrim=true; } @@ -1169,7 +1163,7 @@ void FGJSBsim::update_ic(void) if ( !needTrim ) { fgic->SetLatitudeRadIC(get_Lat_geocentric() ); fgic->SetLongitudeRadIC( get_Longitude() ); - fgic->SetAltitudeFtIC( get_Altitude() ); + fgic->SetAltitudeASLFtIC( get_Altitude() ); fgic->SetVcalibratedKtsIC( get_V_calibrated_kts() ); fgic->SetThetaRadIC( get_Theta() ); fgic->SetPhiRadIC( get_Phi() ); diff --git a/src/FDM/JSBSim/initialization/FGInitialCondition.cpp b/src/FDM/JSBSim/initialization/FGInitialCondition.cpp index 4df38860a..de904e0e1 100644 --- a/src/FDM/JSBSim/initialization/FGInitialCondition.cpp +++ b/src/FDM/JSBSim/initialization/FGInitialCondition.cpp @@ -66,7 +66,7 @@ FGInitialCondition::FGInitialCondition(FGFDMExec *FDMExec) : fdmex(FDMExec) InitializeIC(); if(FDMExec != NULL ) { - fdmex->GetPropagate()->Seth(altitude); + fdmex->GetPropagate()->SetAltitudeASL(altitudeASL); fdmex->GetAtmosphere()->Run(); PropertyManager=fdmex->GetPropertyManager(); Constructing = true; @@ -120,7 +120,7 @@ void FGInitialCondition::ResetIC(double u0, double v0, double w0, FGColumnVector3 _vUVW_BODY(u,v,w); FGColumnVector3 _vUVW_NED = _Tb2l * _vUVW_BODY; FGColumnVector3 _vWIND_NED(wnorth,weast,wdown); - FGColumnVector3 _vUVWAero = _Tl2b * ( _vUVW_NED + _vWIND_NED ); +// FGColumnVector3 _vUVWAero = _Tl2b * ( _vUVW_NED + _vWIND_NED ); uw=_vWIND_NED(1); vw=_vWIND_NED(2); ww=_vWIND_NED(3); @@ -134,7 +134,7 @@ void FGInitialCondition::InitializeIC(void) mach=0; alpha=beta=gamma=0; theta=phi=psi=0; - altitude=hdot=0; + altitudeASL=hdot=0; latitude=longitude=0; u=v=w=0; p=q=r=0; @@ -146,7 +146,7 @@ void FGInitialCondition::InitializeIC(void) lastSpeedSet=setvt; lastWindSet=setwned; radius_to_vehicle = sea_level_radius = fdmex->GetInertial()->GetRefRadius(); - terrain_altitude = 0; + terrain_elevation = 0; targetNlfIC = 1.0; @@ -181,7 +181,7 @@ void FGInitialCondition::WriteStateFile(int num) outfile << " " << Propagate->GetEuler(ePsi) << " " << endl; outfile << " " << Propagate->GetLongitudeDeg() << " " << endl; outfile << " " << Propagate->GetLatitudeDeg() << " " << endl; - outfile << " " << Propagate->Geth() << " " << endl; + outfile << " " << Propagate->GetAltitudeASL() << " " << endl; outfile << "" << endl; outfile.close(); } else { @@ -538,9 +538,10 @@ void FGInitialCondition::calcWindUVW(void) { //****************************************************************************** -void FGInitialCondition::SetAltitudeFtIC(double tt) { - altitude=tt; - fdmex->GetPropagate()->Seth(altitude); +void FGInitialCondition::SetAltitudeASLFtIC(double tt) +{ + altitudeASL=tt; + fdmex->GetPropagate()->SetAltitudeASL(altitudeASL); fdmex->GetAtmosphere()->Run(); //lets try to make sure the user gets what they intended @@ -567,25 +568,29 @@ void FGInitialCondition::SetAltitudeFtIC(double tt) { //****************************************************************************** -void FGInitialCondition::SetAltitudeAGLFtIC(double tt) { - SetAltitudeFtIC(terrain_altitude + tt); +void FGInitialCondition::SetAltitudeAGLFtIC(double tt) +{ + SetAltitudeASLFtIC(terrain_elevation + tt); } //****************************************************************************** -void FGInitialCondition::SetSeaLevelRadiusFtIC(double tt) { +void FGInitialCondition::SetSeaLevelRadiusFtIC(double tt) +{ sea_level_radius = tt; } //****************************************************************************** -void FGInitialCondition::SetTerrainAltitudeFtIC(double tt) { - terrain_altitude=tt; +void FGInitialCondition::SetTerrainElevationFtIC(double tt) +{ + terrain_elevation=tt; } //****************************************************************************** -void FGInitialCondition::calcUVWfromNED(void) { +void FGInitialCondition::calcUVWfromNED(void) +{ u=vnorth*ctheta*cpsi + veast*ctheta*spsi - vdown*stheta; @@ -858,8 +863,10 @@ bool FGInitialCondition::Load(string rstfile, bool useStoredPath) SetLatitudeDegIC(document->FindElementValueAsNumberConvertTo("latitude", "DEG")); if (document->FindElement("longitude")) SetLongitudeDegIC(document->FindElementValueAsNumberConvertTo("longitude", "DEG")); - if (document->FindElement("altitude")) - SetAltitudeFtIC(document->FindElementValueAsNumberConvertTo("altitude", "FT")); + if (document->FindElement("elevation")) + SetTerrainElevationFtIC(document->FindElementValueAsNumberConvertTo("elevation", "FT")); + if (document->FindElement("altitude")) // This is feet above ground level + SetAltitudeAGLFtIC(document->FindElementValueAsNumberConvertTo("altitude", "FT")); if (document->FindElement("ubody")) SetUBodyFpsIC(document->FindElementValueAsNumberConvertTo("ubody", "FT/SEC")); if (document->FindElement("vbody")) @@ -979,8 +986,8 @@ void FGInitialCondition::bind(void){ &FGInitialCondition::SetLongitudeDegIC, true); PropertyManager->Tie("ic/h-sl-ft", this, - &FGInitialCondition::GetAltitudeFtIC, - &FGInitialCondition::SetAltitudeFtIC, + &FGInitialCondition::GetAltitudeASLFtIC, + &FGInitialCondition::SetAltitudeASLFtIC, true); PropertyManager->Tie("ic/h-agl-ft", this, &FGInitialCondition::GetAltitudeAGLFtIC, @@ -990,9 +997,9 @@ void FGInitialCondition::bind(void){ &FGInitialCondition::GetSeaLevelRadiusFtIC, &FGInitialCondition::SetSeaLevelRadiusFtIC, true); - PropertyManager->Tie("ic/terrain-altitude-ft", this, - &FGInitialCondition::GetTerrainAltitudeFtIC, - &FGInitialCondition::SetTerrainAltitudeFtIC, + PropertyManager->Tie("ic/terrain-elevation-ft", this, + &FGInitialCondition::GetTerrainElevationFtIC, + &FGInitialCondition::SetTerrainElevationFtIC, true); PropertyManager->Tie("ic/vg-fps", this, &FGInitialCondition::GetVgroundFpsIC, diff --git a/src/FDM/JSBSim/initialization/FGInitialCondition.h b/src/FDM/JSBSim/initialization/FGInitialCondition.h index c70cfc9ab..330552e7f 100644 --- a/src/FDM/JSBSim/initialization/FGInitialCondition.h +++ b/src/FDM/JSBSim/initialization/FGInitialCondition.h @@ -85,7 +85,7 @@ CLASS DOCUMENTATION @code FGInitialCondition fgic=new FGInitialCondition(FDMExec); fgic->SetVcalibratedKtsIC() - fgic->SetAltitudeFtIC(); + fgic->SetAltitudeAGLFtIC(); // directly into Run FDMExec->GetState()->Initialize(fgic) @@ -140,7 +140,7 @@ CLASS DOCUMENTATION - beta (angle, degrees) - gamma (angle, degrees) - roc (vertical velocity, ft/sec) - - altitude (altitude, ft) + - altitude (altitude AGL, ft) - winddir (wind from-angle, degrees) - vwind (magnitude wind speed, ft/sec) - hwind (headwind speed, knots) @@ -168,7 +168,7 @@ CLASS DOCUMENTATION @property ic/h-sl-ft (read/write) Height above sea level initial condition in feet @property ic/h-agl-ft (read/write) Height above ground level initial condition in feet @property ic/sea-level-radius-ft (read/write) Radius of planet at sea level in feet - @property ic/terrain-altitude-ft (read/write) Terrain elevation above sea level in feet + @property ic/terrain-elevation-ft (read/write) Terrain elevation above sea level in feet @property ic/vg-fps (read/write) Ground speed initial condition in feet/second @property ic/vt-fps (read/write) True airspeed initial condition in feet/second @property ic/vw-bx-fps (read/write) Wind velocity initial condition in Body X frame in feet/second @@ -269,9 +269,9 @@ public: @param gamma Flight path angle in degrees */ inline void SetFlightPathAngleDegIC(double gamma) { SetFlightPathAngleRadIC(gamma*degtorad); } - /** Sets the altitude initial condition in feet. - @param alt Altitude in feet */ - void SetAltitudeFtIC(double alt); + /** Sets the altitude above sea level initial condition in feet. + @param altitudeASL Altitude above sea level in feet */ + void SetAltitudeASLFtIC(double altitudeASL); /** Sets the initial Altitude above ground level. @param agl Altitude above ground level in feet */ @@ -283,7 +283,7 @@ public: /** Sets the initial terrain elevation. @param elev Initial terrain elevation in feet */ - void SetTerrainAltitudeFtIC(double elev); + void SetTerrainElevationFtIC(double elev); /** Sets the initial latitude. @param lat Initial latitude in degrees */ @@ -349,13 +349,13 @@ public: @return Initial longitude in degrees */ inline double GetLongitudeDegIC(void) const { return longitude*radtodeg; } - /** Gets the initial altitude. + /** Gets the initial altitude above sea level. @return Initial altitude in feet. */ - inline double GetAltitudeFtIC(void) const { return altitude; } + inline double GetAltitudeASLFtIC(void) const { return altitudeASL; } /** Gets the initial altitude above ground level. @return Initial altitude AGL in feet */ - inline double GetAltitudeAGLFtIC(void) const { return altitude - terrain_altitude; } + inline double GetAltitudeAGLFtIC(void) const { return altitudeASL - terrain_elevation; } /** Gets the initial sea level radius. @return Initial sea level radius */ @@ -363,7 +363,7 @@ public: /** Gets the initial terrain elevation. @return Initial terrain elevation in feet */ - inline double GetTerrainAltitudeFtIC(void) const { return terrain_altitude; } + inline double GetTerrainElevationFtIC(void) const { return terrain_elevation; } /** Sets the initial ground speed. @param vg Initial ground speed in feet/second */ @@ -616,7 +616,7 @@ public: private: double vt,vc,ve,vg; double mach; - double altitude,hdot; + double altitudeASL,hdot; double latitude,longitude; double u,v,w; double p,q,r; @@ -625,7 +625,7 @@ private: double wnorth,weast,wdown; double whead, wcross, wdir, wmag; double sea_level_radius; - double terrain_altitude; + double terrain_elevation; double radius_to_vehicle; double targetNlfIC; diff --git a/src/FDM/JSBSim/input_output/FGScript.cpp b/src/FDM/JSBSim/input_output/FGScript.cpp index 9ea8a9186..dc033e26f 100755 --- a/src/FDM/JSBSim/input_output/FGScript.cpp +++ b/src/FDM/JSBSim/input_output/FGScript.cpp @@ -181,14 +181,20 @@ bool FGScript::LoadScript( string script ) while (property_element) { double value=0.0; + string title=""; + + title = property_element->GetDataLine(); if ( ! property_element->GetAttributeValue("value").empty()) value = property_element->GetAttributeValueAsNumber("value"); LocalProps *localProp = new LocalProps(value); - localProp->title = property_element->GetDataLine(); + localProp->title = title; local_properties.push_back(localProp); - - PropertyManager->Tie(localProp->title, (local_properties.back())->value); + if (PropertyManager->HasNode(title)) { + PropertyManager->GetNode(title)->setDoubleValue(value); + } else { + PropertyManager->Tie(localProp->title, localProp->value); + } property_element = run_element->FindNextElement("property"); } @@ -447,6 +453,14 @@ void FGScript::Debug(int from) << " seconds with dt = " << State->Getdt() << endl; cout << endl; + for (unsigned int i=0; ititle + << " = " << PropertyManager->GetNode(local_properties[i]->title)->getDoubleValue() + << endl; + } + + if (local_properties.size() > 0) cout << endl; + for (unsigned i=0; i #include "FGAerodynamics.h" #include "FGPropagate.h" #include "FGAircraft.h" diff --git a/src/FDM/JSBSim/models/FGAtmosphere.cpp b/src/FDM/JSBSim/models/FGAtmosphere.cpp index 8c47b0226..a1bdb89b6 100644 --- a/src/FDM/JSBSim/models/FGAtmosphere.cpp +++ b/src/FDM/JSBSim/models/FGAtmosphere.cpp @@ -136,7 +136,7 @@ bool FGAtmosphere::Run(void) if (FDMExec->Holding()) return false; T_dev = 0.0; - h = Propagate->Geth(); + h = Propagate->GetAltitudeASL(); if (!useExternal) { Calculate(h); diff --git a/src/FDM/JSBSim/models/FGAuxiliary.h b/src/FDM/JSBSim/models/FGAuxiliary.h index 8d47ce8cc..c7e066bf4 100644 --- a/src/FDM/JSBSim/models/FGAuxiliary.h +++ b/src/FDM/JSBSim/models/FGAuxiliary.h @@ -40,6 +40,7 @@ INCLUDES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #include "FGModel.h" +#include #include #include #include "FGPropagate.h" @@ -185,10 +186,23 @@ public: double GetqbarUW (void) const { return qbarUW; } double GetqbarUV (void) const { return qbarUV; } double GetReynoldsNumber(void) const { return Re; } + + /** Gets the magnitude of total vehicle velocity including wind effects in feet per second. */ double GetVt (void) const { return Vt; } + + /** Gets the ground speed in feet per second. + The magnitude is the square root of the sum of the squares (RSS) of the + vehicle north and east velocity components. + @return The magnitude of the vehicle velocity in the horizontal plane. */ double GetVground (void) const { return Vground; } + + /** Gets the Mach number. */ double GetMach (void) const { return Mach; } + + /** The mach number calculated using the vehicle X axis velocity. */ double GetMachU (void) const { return MachU; } + + /** The vertical acceleration in g's of the aircraft center of gravity. */ double GetNz (void) const { return Nz; } double GetHOverBCG(void) const { return hoverbcg; } diff --git a/src/FDM/JSBSim/models/FGInertial.cpp b/src/FDM/JSBSim/models/FGInertial.cpp index 39aa91ddc..9f6373399 100644 --- a/src/FDM/JSBSim/models/FGInertial.cpp +++ b/src/FDM/JSBSim/models/FGInertial.cpp @@ -36,6 +36,7 @@ INCLUDES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #include "FGInertial.h" +#include #include "FGPropagate.h" #include "FGState.h" #include "FGMassBalance.h" diff --git a/src/FDM/JSBSim/models/FGLGear.cpp b/src/FDM/JSBSim/models/FGLGear.cpp index f740cf643..3031af700 100644 --- a/src/FDM/JSBSim/models/FGLGear.cpp +++ b/src/FDM/JSBSim/models/FGLGear.cpp @@ -663,7 +663,8 @@ void FGLGear::Report(ReportType repType) switch(repType) { case erLand: - cout << endl << "Touchdown report for " << name << endl; + cout << endl << "Touchdown report for " << name << " (WOW at time: " + << Exec->GetState()->Getsim_time() << " seconds)" << endl; cout << " Sink rate at contact: " << SinkRate << " fps, " << SinkRate*0.3048 << " mps" << endl; cout << " Contact ground speed: " << GroundSpeed*.5925 << " knots, " @@ -677,11 +678,17 @@ void FGLGear::Report(ReportType repType) LandingReported = true; break; case erTakeoff: - cout << endl << "Takeoff report for " << name << endl; + cout << endl << "Takeoff report for " << name << " (Liftoff at time: " + << Exec->GetState()->Getsim_time() << " seconds)" << endl; cout << " Distance traveled: " << TakeoffDistanceTraveled << " ft, " << TakeoffDistanceTraveled*0.3048 << " meters" << endl; cout << " Distance traveled (over 50'): " << TakeoffDistanceTraveled50ft << " ft, " << TakeoffDistanceTraveled50ft*0.3048 << " meters" << endl; + cout << " [Altitude (ASL): " << Exec->GetPropagate()->GetAltitudeASL() << " ft. / " + << Exec->GetPropagate()->GetAltitudeASLmeters() << " m | Temperature: " + << Exec->GetAtmosphere()->GetTemperature() - 459.67 << " F / " + << RankineToCelsius(Exec->GetAtmosphere()->GetTemperature()) << " C]" << endl; + cout << " [Velocity (KCAS): " << Exec->GetAuxiliary()->GetVcalibratedKTS() << "]" << endl; TakeoffReported = true; break; } diff --git a/src/FDM/JSBSim/models/FGMassBalance.cpp b/src/FDM/JSBSim/models/FGMassBalance.cpp index ecdd86a52..967f0ff44 100644 --- a/src/FDM/JSBSim/models/FGMassBalance.cpp +++ b/src/FDM/JSBSim/models/FGMassBalance.cpp @@ -130,8 +130,13 @@ bool FGMassBalance::Load(Element* el) element = el->FindNextElement("pointmass"); } + double ChildFDMWeight = 0.0; + for (int fdm=0; fdmGetFDMCount(); fdm++) { + if (FDMExec->GetChildFDM(fdm)->mated) ChildFDMWeight += FDMExec->GetChildFDM(fdm)->exec->GetMassBalance()->GetWeight(); + } + Weight = EmptyWeight + Propulsion->GetTanksWeight() + GetTotalPointMassWeight() - + BuoyantForces->GetGasMass()*slugtolb; + + BuoyantForces->GetGasMass()*slugtolb + ChildFDMWeight; Mass = lbtoslug*Weight; @@ -149,8 +154,13 @@ bool FGMassBalance::Run(void) if (FGModel::Run()) return true; if (FDMExec->Holding()) return false; + double ChildFDMWeight = 0.0; + for (int fdm=0; fdmGetFDMCount(); fdm++) { + if (FDMExec->GetChildFDM(fdm)->mated) ChildFDMWeight += FDMExec->GetChildFDM(fdm)->exec->GetMassBalance()->GetWeight(); + } + Weight = EmptyWeight + Propulsion->GetTanksWeight() + GetTotalPointMassWeight() - + BuoyantForces->GetGasMass()*slugtolb; + + BuoyantForces->GetGasMass()*slugtolb + ChildFDMWeight; Mass = lbtoslug*Weight; diff --git a/src/FDM/JSBSim/models/FGOutput.cpp b/src/FDM/JSBSim/models/FGOutput.cpp index b76f5d9a2..f8ef6a0b3 100644 --- a/src/FDM/JSBSim/models/FGOutput.cpp +++ b/src/FDM/JSBSim/models/FGOutput.cpp @@ -323,7 +323,8 @@ void FGOutput::DelimitedOutput(string fname) } if (SubSystems & ssPropagate) { outstream << delimeter; - outstream << "Altitude (ft)" + delimeter; + outstream << "Altitude ASL (ft)" + delimeter; + outstream << "Altitude AGL (ft)" + delimeter; outstream << "Phi (deg)" + delimeter + "Theta (deg)" + delimeter + "Psi (deg)" + delimeter; outstream << "Alpha (deg)" + delimeter; outstream << "Beta (deg)" + delimeter; @@ -332,7 +333,7 @@ void FGOutput::DelimitedOutput(string fname) outstream << "ECEF X (ft)" + delimeter + "ECEF Y (ft)" + delimeter + "ECEF Z (ft)" + delimeter; outstream << "EPA (deg)" + delimeter; outstream << "Distance AGL (ft)" + delimeter; - outstream << "Runway Radius (ft)"; + outstream << "Terrain Radius (ft)"; } if (SubSystems & ssCoefficients) { scratch = Aerodynamics->GetCoefficientStrings(delimeter); @@ -432,7 +433,8 @@ void FGOutput::DelimitedOutput(string fname) if (SubSystems & ssPropagate) { outstream.precision(14); outstream << delimeter; - outstream << Propagate->Geth() << delimeter; + outstream << Propagate->GetAltitudeASL() << delimeter; + outstream << Propagate->GetDistanceAGL() << delimeter; outstream << (radtodeg*Propagate->GetEuler()).Dump(delimeter) << delimeter; outstream << Auxiliary->Getalpha(inDegrees) << delimeter; outstream << Auxiliary->Getbeta(inDegrees) << delimeter; @@ -443,7 +445,7 @@ void FGOutput::DelimitedOutput(string fname) outstream.precision(14); outstream << Inertial->GetEarthPositionAngleDeg() << delimeter; outstream << Propagate->GetDistanceAGL() << delimeter; - outstream << Propagate->GetRunwayRadius(); + outstream << Propagate->GetLocalTerrainRadius(); outstream.precision(10); } if (SubSystems & ssCoefficients) { @@ -483,7 +485,7 @@ void FGOutput::SocketDataFill(FGNetFDM* net) // Positions net->longitude = Propagate->GetLocation().GetLongitude(); // geodetic (radians) net->latitude = Propagate->GetLocation().GetLatitude(); // geodetic (radians) - net->altitude = Propagate->Geth()*0.3048; // altitude, above sea level (meters) + net->altitude = Propagate->GetAltitudeASL()*0.3048; // altitude, above sea level (meters) net->agl = (float)(Propagate->GetDistanceAGL()*0.3048); // altitude, above ground level (meters) net->phi = (float)(Propagate->GetEuler(ePhi)); // roll (radians) @@ -881,7 +883,7 @@ void FGOutput::SocketOutput(void) socket->Append(MassBalance->GetXYZcg()(eZ)); } if (SubSystems & ssPropagate) { - socket->Append(Propagate->Geth()); + socket->Append(Propagate->GetAltitudeASL()); socket->Append(radtodeg*Propagate->GetEuler(ePhi)); socket->Append(radtodeg*Propagate->GetEuler(eTht)); socket->Append(radtodeg*Propagate->GetEuler(ePsi)); diff --git a/src/FDM/JSBSim/models/FGPropagate.cpp b/src/FDM/JSBSim/models/FGPropagate.cpp index 8a41ec21e..0b7d7f78a 100644 --- a/src/FDM/JSBSim/models/FGPropagate.cpp +++ b/src/FDM/JSBSim/models/FGPropagate.cpp @@ -118,10 +118,10 @@ bool FGPropagate::InitModel(void) { if (!FGModel::InitModel()) return false; - SeaLevelRadius = Inertial->GetRefRadius(); // For initialization ONLY - RunwayRadius = SeaLevelRadius; + // For initialization ONLY: + SeaLevelRadius = LocalTerrainRadius = Inertial->GetRefRadius(); - VState.vLocation.SetRadius( SeaLevelRadius + 4.0 ); // Todo Add terrain elevation? + VState.vLocation.SetRadius( LocalTerrainRadius + 4.0 ); VState.vLocation.SetEllipse(Inertial->GetSemimajor(), Inertial->GetSemiminor()); vOmega = FGColumnVector3( 0.0, 0.0, Inertial->omega() ); // Earth rotation vector @@ -155,13 +155,13 @@ bool FGPropagate::InitModel(void) void FGPropagate::SetInitialState(const FGInitialCondition *FGIC) { - SeaLevelRadius = FGIC->GetSeaLevelRadiusFtIC(); - RunwayRadius = SeaLevelRadius; + SetSeaLevelRadius(FGIC->GetSeaLevelRadiusFtIC()); + SetTerrainElevation(FGIC->GetTerrainElevationFtIC()); // Set the position lat/lon/radius VState.vLocation.SetPosition( FGIC->GetLongitudeRadIC(), FGIC->GetLatitudeRadIC(), - FGIC->GetAltitudeFtIC() + FGIC->GetSeaLevelRadiusFtIC() ); + FGIC->GetAltitudeASLFtIC() + FGIC->GetSeaLevelRadiusFtIC() ); VehicleRadius = GetRadius(); radInv = 1.0/VehicleRadius; @@ -187,8 +187,8 @@ void FGPropagate::SetInitialState(const FGInitialCondition *FGIC) // Finally, make sure that the quaternion stays normalized. VState.vQtrn.Normalize(); - // Recompute the RunwayRadius level. - RecomputeRunwayRadius(); + // Recompute the LocalTerrainRadius. + RecomputeLocalTerrainRadius(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -216,7 +216,7 @@ bool FGPropagate::Run(void) if (FGModel::Run()) return true; // Fast return if we have nothing to do ... if (FDMExec->Holding()) return false; - RecomputeRunwayRadius(); + RecomputeLocalTerrainRadius(); // Calculate current aircraft radius from center of planet @@ -424,27 +424,28 @@ void FGPropagate::CalculateLocationdot(void) //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void FGPropagate::RecomputeRunwayRadius(void) +void FGPropagate::RecomputeLocalTerrainRadius(void) { - // Get the runway radius. + double t = State->Getsim_time(); + + // Get the LocalTerrain radius. FGLocation contactloc; FGColumnVector3 dv; - FGGroundCallback* gcb = FDMExec->GetGroundCallback(); - double t = State->Getsim_time(); - gcb->GetAGLevel(t, VState.vLocation, contactloc, dv, dv); - RunwayRadius = contactloc.GetRadius(); + FDMExec->GetGroundCallback()->GetAGLevel(t, VState.vLocation, contactloc, dv, dv); + LocalTerrainRadius = contactloc.GetRadius(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void FGPropagate::SetTerrainElevationASL(double tt) +void FGPropagate::SetTerrainElevation(double terrainElev) { - FDMExec->GetGroundCallback()->SetTerrainGeoCentRadius(tt+SeaLevelRadius); + LocalTerrainRadius = terrainElev + SeaLevelRadius; + FDMExec->GetGroundCallback()->SetTerrainGeoCentRadius(LocalTerrainRadius); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -double FGPropagate::GetTerrainElevationASL(void) const +double FGPropagate::GetTerrainElevation(void) const { return FDMExec->GetGroundCallback()->GetTerrainGeoCentRadius()-SeaLevelRadius; } @@ -465,30 +466,30 @@ const FGMatrix33& FGPropagate::GetTec2i(void) //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void FGPropagate::Seth(double tt) +void FGPropagate::SetAltitudeASL(double altASL) { - VState.vLocation.SetRadius( tt + SeaLevelRadius ); + VState.vLocation.SetRadius( altASL + SeaLevelRadius ); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -double FGPropagate::GetRunwayRadius(void) const +double FGPropagate::GetLocalTerrainRadius(void) const { - return RunwayRadius; + return LocalTerrainRadius; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double FGPropagate::GetDistanceAGL(void) const { - return VState.vLocation.GetRadius() - RunwayRadius; + return VState.vLocation.GetRadius() - LocalTerrainRadius; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void FGPropagate::SetDistanceAGL(double tt) { - VState.vLocation.SetRadius( tt + RunwayRadius ); + VState.vLocation.SetRadius( tt + LocalTerrainRadius ); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -525,8 +526,8 @@ void FGPropagate::bind(void) PropertyManager->Tie("accelerations/vdot-ft_sec2", this, eV, (PMF)&FGPropagate::GetUVWdot); PropertyManager->Tie("accelerations/wdot-ft_sec2", this, eW, (PMF)&FGPropagate::GetUVWdot); - PropertyManager->Tie("position/h-sl-ft", this, &FGPropagate::Geth, &FGPropagate::Seth, true); - PropertyManager->Tie("position/h-sl-meters", this, &FGPropagate::Gethmeters, &FGPropagate::Sethmeters, true); + PropertyManager->Tie("position/h-sl-ft", this, &FGPropagate::GetAltitudeASL, &FGPropagate::SetAltitudeASL, true); + PropertyManager->Tie("position/h-sl-meters", this, &FGPropagate::GetAltitudeASLmeters, &FGPropagate::SetAltitudeASLmeters, true); PropertyManager->Tie("position/lat-gc-rad", this, &FGPropagate::GetLatitude, &FGPropagate::SetLatitude); PropertyManager->Tie("position/long-gc-rad", this, &FGPropagate::GetLongitude, &FGPropagate::SetLongitude); PropertyManager->Tie("position/lat-gc-deg", this, &FGPropagate::GetLatitudeDeg, &FGPropagate::SetLatitudeDeg); @@ -537,10 +538,10 @@ void FGPropagate::bind(void) PropertyManager->Tie("position/h-agl-ft", this, &FGPropagate::GetDistanceAGL, &FGPropagate::SetDistanceAGL); PropertyManager->Tie("position/radius-to-vehicle-ft", this, &FGPropagate::GetRadius); PropertyManager->Tie("position/terrain-elevation-asl-ft", this, - &FGPropagate::GetTerrainElevationASL, - &FGPropagate::SetTerrainElevationASL, false); + &FGPropagate::GetTerrainElevation, + &FGPropagate::SetTerrainElevation, false); - PropertyManager->Tie("metrics/runway-radius", this, &FGPropagate::GetRunwayRadius); + PropertyManager->Tie("metrics/terrain-radius", this, &FGPropagate::GetLocalTerrainRadius); PropertyManager->Tie("attitude/phi-rad", this, (int)ePhi, (PMF)&FGPropagate::GetEuler); PropertyManager->Tie("attitude/theta-rad", this, (int)eTht, (PMF)&FGPropagate::GetEuler); diff --git a/src/FDM/JSBSim/models/FGPropagate.h b/src/FDM/JSBSim/models/FGPropagate.h index adf136e79..63c2b42c3 100644 --- a/src/FDM/JSBSim/models/FGPropagate.h +++ b/src/FDM/JSBSim/models/FGPropagate.h @@ -286,21 +286,19 @@ public: */ double GetInertialVelocityMagnitude(void) const { return vInertialVelocity.Magnitude(); } - /** Returns the current altitude. - Returns the current altitude. Specifically, this function returns the - difference between the distance to the center of the Earth, and sea level. + /** Returns the current altitude above sea level. + This function returns the altitude above sea level. units ft @return The current altitude above sea level in feet. */ - double Geth(void) const { return VState.vLocation.GetRadius() - SeaLevelRadius; } + double GetAltitudeASL(void) const { return VState.vLocation.GetRadius() - SeaLevelRadius; } - /** Returns the current altitude. - Returns the curren altitude. Specifically, this function returns the - difference between the distance to the center of the Earth, and sea level. + /** Returns the current altitude above sea level. + This function returns the altitude above sea level. units meters @return The current altitude above sea level in meters. */ - double Gethmeters(void) const { return Geth()*fttom;} + double GetAltitudeASLmeters(void) const { return GetAltitudeASL()*fttom;} /** Retrieves a body frame angular velocity component relative to the ECEF frame. Retrieves a body frame angular velocity component. The angular velocity @@ -385,16 +383,16 @@ public: */ double Gethdot(void) const { return -vVel(eDown); } - /** Returns the "constant" RunwayRadius. - The RunwayRadius parameter is set by the calling application or set to - sea level if JSBSim is running in standalone mode. + /** Returns the "constant" LocalTerrainRadius. + The LocalTerrainRadius parameter is set by the calling application or set to + sea level + terrain elevation if JSBSim is running in standalone mode. units feet - @return distance of the runway from the center of the earth. + @return distance of the local terrain from the center of the earth. */ - double GetRunwayRadius(void) const; + double GetLocalTerrainRadius(void) const; double GetSeaLevelRadius(void) const { return SeaLevelRadius; } - double GetTerrainElevationASL(void) const; + double GetTerrainElevation(void) const; double GetDistanceAGL(void) const; double GetRadius(void) const { if (VState.vLocation.GetRadius() == 0) return 1.0; @@ -481,13 +479,13 @@ public: void SetLatitudeDeg(double lat) {SetLatitude(lat*degtorad);} void SetRadius(double r) { VState.vLocation.SetRadius(r); } void SetLocation(const FGLocation& l) { VState.vLocation = l; } - void Seth(double tt); - void Sethmeters(double tt) {Seth(tt/fttom);} + void SetAltitudeASL(double altASL); + void SetAltitudeASLmeters(double altASL) {SetAltitudeASL(altASL/fttom);} void SetSeaLevelRadius(double tt) { SeaLevelRadius = tt; } - void SetTerrainElevationASL(double tt); + void SetTerrainElevation(double tt); void SetDistanceAGL(double tt); void SetInitialState(const FGInitialCondition *); - void RecomputeRunwayRadius(void); + void RecomputeLocalTerrainRadius(void); void CalculatePQRdot(void); void CalculateQuatdot(void); @@ -521,7 +519,7 @@ private: FGMatrix33 Ti2b; // ECI to body frame rotation matrix FGMatrix33 Tb2i; // body to ECI frame rotation matrix - double RunwayRadius, SeaLevelRadius, VehicleRadius; + double LocalTerrainRadius, SeaLevelRadius, VehicleRadius; double radInv; int integrator_rotational_rate; int integrator_translational_rate; diff --git a/src/FDM/JSBSim/models/atmosphere/FGMSIS.cpp b/src/FDM/JSBSim/models/atmosphere/FGMSIS.cpp index e3197404d..590e3f6d3 100755 --- a/src/FDM/JSBSim/models/atmosphere/FGMSIS.cpp +++ b/src/FDM/JSBSim/models/atmosphere/FGMSIS.cpp @@ -168,7 +168,7 @@ bool MSIS::Run(void) // get at-altitude values Calculate(Auxiliary->GetDayOfYear(), Auxiliary->GetSecondsInDay(), - Propagate->Geth(), + Propagate->GetAltitudeASL(), Propagate->GetLocation().GetLatitudeDeg(), Propagate->GetLocation().GetLongitudeDeg()); intTemperature = output.t[1] * 1.8; diff --git a/src/FDM/JSBSim/models/flight_control/FGActuator.cpp b/src/FDM/JSBSim/models/flight_control/FGActuator.cpp index 9370c5f84..3b36b3a92 100755 --- a/src/FDM/JSBSim/models/flight_control/FGActuator.cpp +++ b/src/FDM/JSBSim/models/flight_control/FGActuator.cpp @@ -106,7 +106,7 @@ bool FGActuator::Run(void ) Input = InputNodes[0]->getDoubleValue() * InputSigns[0]; if (fail_zero) Input = 0; - if (fail_hardover) Input = clipmax*fabs(Input)/Input; + if (fail_hardover) Input = clipmax*sign(Input); Output = Input; // Perfect actuator. At this point, if no failures are present // and no subsequent lag, limiting, etc. is done, the output diff --git a/src/FDM/JSBSim/models/flight_control/FGSensor.cpp b/src/FDM/JSBSim/models/flight_control/FGSensor.cpp index 5e4ede578..824f0ea5c 100755 --- a/src/FDM/JSBSim/models/flight_control/FGSensor.cpp +++ b/src/FDM/JSBSim/models/flight_control/FGSensor.cpp @@ -56,7 +56,7 @@ FGSensor::FGSensor(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element) // inputs are read from the base class constructor - bits = quantized = divisions = 0; + bits = quantized = divisions = index = delay = 0; PreviousInput = PreviousOutput = 0.0; min = max = bias = noise_variance = lag = drift_rate = drift = span = 0.0; granularity = 0.0; @@ -103,6 +103,21 @@ FGSensor::FGSensor(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element) cerr << "Unknown noise type in sensor: " << Name << endl; cerr << " defaulting to PERCENT." << endl; } + string distribution = element->FindElement("noise")->GetAttributeValue("distribution"); + if (distribution == "UNIFORM") { + DistributionType = eUniform; + } else if (distribution == "GAUSSIAN") { + DistributionType = eGaussian; + } else { + DistributionType = eUniform; + cerr << "Unknown random distribution type in sensor: " << Name << endl; + cerr << " defaulting to UNIFORM." << endl; + } + } + if ( element->FindElement("delay") ) { + delay = (unsigned int)element->FindElementValueAsNumber("delay"); + output_array.resize(delay); + for (unsigned int i=0; igetName() << endl; } - if (IsOutput) cout << " OUTPUT: " << OutputNode->getName() << endl; + if (delay > 0) cout <<" Frame delay: " << delay + << " frames (" << delay*dt << " sec)" << endl; if (bits != 0) { if (quant_property.empty()) cout << " Quantized output" << endl; @@ -281,7 +314,13 @@ void FGSensor::Debug(int from) } else { cout << " Noise variance type is invalid" << endl; } + if (DistributionType == eUniform) { + cout << " Random noise is uniformly distributed." << endl; + } else if (DistributionType == eGaussian) { + cout << " Random noise is gaussian distributed." << endl; + } } + if (IsOutput) cout << " OUTPUT: " << OutputNode->getName() << endl; } } if (debug_lvl & 2 ) { // Instantiation/Destruction notification diff --git a/src/FDM/JSBSim/models/flight_control/FGSensor.h b/src/FDM/JSBSim/models/flight_control/FGSensor.h index 87fd3d518..efbc5b7c5 100755 --- a/src/FDM/JSBSim/models/flight_control/FGSensor.h +++ b/src/FDM/JSBSim/models/flight_control/FGSensor.h @@ -39,6 +39,7 @@ INCLUDES #include "FGFCSComponent.h" #include +#include /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% DEFINITIONS @@ -52,6 +53,7 @@ FORWARD DECLARATIONS namespace JSBSim { +using std::vector; class FGFCS; /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -74,6 +76,7 @@ Syntax: number number + number < /delay> @endcode @@ -101,7 +104,8 @@ percentage variance. That is, if the number given is 0.05, the the variance is understood to be +/-0.05 percent maximum variance. So, the actual value for the sensor will be *anywhere* from 0.95 to 1.05 of the actual "perfect" value at any time - even varying all the way from 0.95 to 1.05 in adjacent frames - whatever the delta -time. +time. The delay element can specify a frame delay. The integer number provided is +the number of frames to delay the output signal. @author Jon S. Berndt @version $Revision$ @@ -130,6 +134,7 @@ public: protected: enum eNoiseType {ePercent=0, eAbsolute} NoiseType; + enum eDistributionType {eUniform=0, eGaussian} DistributionType; double dt; double min, max; double span; @@ -147,16 +152,20 @@ protected: int bits; int quantized; int divisions; + int delay; + int index; bool fail_low; bool fail_high; bool fail_stuck; string quant_property; + vector output_array; void Noise(void); void Bias(void); void Drift(void); void Quantize(void); void Lag(void); + void Delay(void); void bind(void); diff --git a/src/FDM/JSBSim/models/propulsion/FGPiston.cpp b/src/FDM/JSBSim/models/propulsion/FGPiston.cpp index fbb9f2d02..cd24bfbab 100644 --- a/src/FDM/JSBSim/models/propulsion/FGPiston.cpp +++ b/src/FDM/JSBSim/models/propulsion/FGPiston.cpp @@ -548,7 +548,7 @@ void FGPiston::doMAP(void) } } // Boost the manifold pressure. - double boost_factor = BoostMul[BoostSpeed] * map_coefficient * RPM/RatedRPM[BoostSpeed]; + double boost_factor = BoostMul[BoostSpeed] * RPM/RatedRPM[BoostSpeed]; if (boost_factor < 1.0) boost_factor = 1.0; // boost will never reduce the MAP MAP = TMAP * boost_factor; // Now clip the manifold pressure to BCV or Wastegate setting. @@ -713,7 +713,7 @@ void FGPiston::doEGT(void) * Calculate the cylinder head temperature. * * Inputs: T_amb, IAS, rho_air, m_dot_fuel, calorific_value_fuel, - * combustion_efficiency, RPM, MaxRPM + * combustion_efficiency, RPM, MaxRPM, Displacement * * Outputs: CylinderHeadTemp_degK */ @@ -813,7 +813,7 @@ string FGPiston::GetEngineLabels(string delimeter) buf << Name << " Power Available (engine " << EngineNumber << " in HP)" << delimeter << Name << " HP (engine " << EngineNumber << ")" << delimeter << Name << " equivalent ratio (engine " << EngineNumber << ")" << delimeter - << Name << " MAP (engine " << EngineNumber << ")" << delimeter + << Name << " MAP (engine " << EngineNumber << " in inHg)" << delimeter << Thruster->GetThrusterLabels(EngineNumber, delimeter); return buf.str(); @@ -826,7 +826,7 @@ string FGPiston::GetEngineValues(string delimeter) std::ostringstream buf; buf << PowerAvailable << delimeter << HP << delimeter - << equivalence_ratio << delimeter << MAP << delimeter + << equivalence_ratio << delimeter << ManifoldPressure_inHg << delimeter << Thruster->GetThrusterValues(EngineNumber, delimeter); return buf.str(); diff --git a/src/FDM/JSBSim/models/propulsion/FGTurbine.cpp b/src/FDM/JSBSim/models/propulsion/FGTurbine.cpp index d751654a0..6c4a7818c 100644 --- a/src/FDM/JSBSim/models/propulsion/FGTurbine.cpp +++ b/src/FDM/JSBSim/models/propulsion/FGTurbine.cpp @@ -92,6 +92,7 @@ FGTurbine::~FGTurbine() void FGTurbine::ResetToIC(void) { N1 = N2 = 0.0; + N2norm = 0.0; correctedTSFC = TSFC; ThrottlePos = AugmentCmd = 0.0; InletPosition = NozzlePosition = 1.0; @@ -186,7 +187,9 @@ double FGTurbine::Off(void) double FGTurbine::Run() { double idlethrust, milthrust, thrust; - double N2norm; // 0.0 = idle N2, 1.0 = maximum N2 + double spoolup; // acceleration in pct/sec + double sigma = Atmosphere->GetDensityRatio(); + double T = Atmosphere->GetTemperature(); idlethrust = MilThrust * IdleThrustLookup->GetValue(); milthrust = (MilThrust - idlethrust) * MilThrustLookup->GetValue(); @@ -194,8 +197,13 @@ double FGTurbine::Run() Running = true; Starter = false; - N2 = Seek(&N2, IdleN2 + ThrottlePos * N2_factor, delay, delay * 3.0); - N1 = Seek(&N1, IdleN1 + ThrottlePos * N1_factor, delay, delay * 2.4); + // adjust acceleration for N2 and atmospheric density + double n = N2norm + 0.1; + if (n > 1) n = 1; + spoolup = delay / (1 + 3 * (1-n)*(1-n)*(1-n) + (1 - sigma)); + + N2 = Seek(&N2, IdleN2 + ThrottlePos * N2_factor, spoolup, spoolup * 3.0); + N1 = Seek(&N1, IdleN1 + ThrottlePos * N1_factor, spoolup, spoolup * 2.4); N2norm = (N2 - IdleN2) / N2_factor; thrust = idlethrust + (milthrust * N2norm * N2norm); EGT_degC = TAT + 363.1 + ThrottlePos * 357.1; @@ -203,7 +211,7 @@ double FGTurbine::Run() OilTemp_degK = Seek(&OilTemp_degK, 366.0, 1.2, 0.1); if (!Augmentation) { - correctedTSFC = TSFC * (0.84 + (1-N2norm)*(1-N2norm)); + correctedTSFC = TSFC * sqrt(T/389.7) * (0.84 + (1-N2norm)*(1-N2norm)); FuelFlow_pph = Seek(&FuelFlow_pph, thrust * correctedTSFC, 1000.0, 100000); if (FuelFlow_pph < IdleFF) FuelFlow_pph = IdleFF; NozzlePosition = Seek(&NozzlePosition, 1.0 - N2norm, 0.8, 0.8); @@ -329,7 +337,7 @@ double FGTurbine::Seize(void) double FGTurbine::Trim() { - double idlethrust, milthrust, thrust, tdiff, N2norm; + double idlethrust, milthrust, thrust, tdiff; idlethrust = MilThrust * IdleThrustLookup->GetValue(); milthrust = (MilThrust - idlethrust) * MilThrustLookup->GetValue(); N2 = IdleN2 + ThrottlePos * N2_factor; @@ -457,7 +465,7 @@ bool FGTurbine::Load(FGFDMExec* exec, Element *el) // Pre-calculations and initializations - delay = 60.0 / (BypassRatio + 3.0); + delay = 90.0 / (BypassRatio + 3.0); N1_factor = MaxN1 - IdleN1; N2_factor = MaxN2 - IdleN2; OilTemp_degK = (Auxiliary->GetTotalTemperature() - 491.69) * 0.5555556 + 273.0; diff --git a/src/FDM/JSBSim/models/propulsion/FGTurbine.h b/src/FDM/JSBSim/models/propulsion/FGTurbine.h index 4c63dc602..552c258b1 100644 --- a/src/FDM/JSBSim/models/propulsion/FGTurbine.h +++ b/src/FDM/JSBSim/models/propulsion/FGTurbine.h @@ -224,6 +224,7 @@ private: double IdleN2; ///< Idle N2 double N1; ///< N1 double N2; ///< N2 + double N2norm; ///< N2 normalized (0=idle, 1=max) double MaxN1; ///< N1 at 100% throttle double MaxN2; ///< N2 at 100% throttle double IdleFF; ///< Idle Fuel Flow (lbm/hr)