diff --git a/src/FDM/JSBSim/FGFDMExec.cpp b/src/FDM/JSBSim/FGFDMExec.cpp index 48a0fd123..66c96504e 100644 --- a/src/FDM/JSBSim/FGFDMExec.cpp +++ b/src/FDM/JSBSim/FGFDMExec.cpp @@ -144,9 +144,14 @@ FGFDMExec::FGFDMExec(FGPropertyManager* root, unsigned int* fdmctr) // this is to catch errors in binding member functions to the property tree. try { Allocate(); - } catch (const string& msg ) { - cout << "Caught error: " << msg << endl; - exit(1); + } + catch (const string& msg) { + cerr << endl << "Caught error: " << msg << endl; + throw; + } + catch (const BaseException& e) { + cout << endl << "Caught error: " << e.what() << endl; + throw; } trim_status = false; @@ -1093,8 +1098,10 @@ bool FGFDMExec::ReadChild(Element* el) if (location) { child->Loc = location->FindElementTripletConvertTo("IN"); } else { - cerr << endl << highint << fgred << " No location was found for this child object!" << reset << endl; - exit(-1); + const string s(" No location was found for this child object!"); + cerr << el->ReadFrom() << endl << highint << fgred + << s << reset << endl; + throw BaseException(s); } Element* orientation = el->FindElement("orient"); @@ -1165,7 +1172,7 @@ void FGFDMExec::DoTrim(int mode) trim.Report(); if (!success) - throw("Trim Failed"); + throw TrimFailureException("Trim Failed"); trim_completed = 1; } diff --git a/src/FDM/JSBSim/FGFDMExec.h b/src/FDM/JSBSim/FGFDMExec.h index 2d9d934a5..5e91686a8 100644 --- a/src/FDM/JSBSim/FGFDMExec.h +++ b/src/FDM/JSBSim/FGFDMExec.h @@ -72,6 +72,11 @@ class FGPropulsion; class FGMassBalance; class FGTrim; +class TrimFailureException : public BaseException { + public: + TrimFailureException(const std::string& msg) : BaseException(msg) {} +}; + /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS DOCUMENTATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ @@ -194,7 +199,7 @@ class FGFDMExec : public FGJSBBase mated = true; internal = false; } - + void Run(void) {exec->Run();} void AssignState(FGPropagate* source_prop) { exec->GetPropagate()->SetVState(source_prop->GetVState()); @@ -283,44 +288,65 @@ public: @return true if successful*/ bool LoadModel(const std::string& model, bool addModelToPath = true); - /** Loads a script + /** Load a script @param Script The full path name and file name for the script to be loaded. - @param deltaT The simulation integration step size, if given. If no value is supplied - then 0.0 is used and the value is expected to be supplied in - the script file itself. - @param initfile The initialization file that will override the initialization file - specified in the script file. If no file name is given on the command line, - the file specified in the script will be used. If an initialization file - is not given in either place, an error will result. + @param deltaT The simulation integration step size, if given. If no value + is supplied then 0.0 is used and the value is expected to be + supplied in the script file itself. + @param initfile The initialization file that will override the + initialization file specified in the script file. If no + file name is given on the command line, the file specified + in the script will be used. If an initialization file is + not given in either place, an error will result. @return true if successfully loads; false otherwise. */ bool LoadScript(const SGPath& Script, double deltaT=0.0, const SGPath& initfile=SGPath()); - /** Sets the path to the engine config file directories. - @param path path to the directory under which engine config - files are kept, for instance "engine" */ + /** Set the path to the engine config file directories. + Relative paths are taken from the root directory. + @param path path to the directory under which engine config files are + kept, for instance "engine". + @see SetRootDir + @see GetEnginePath */ bool SetEnginePath(const SGPath& path) { EnginePath = GetFullPath(path); return true; } - /** Sets the path to the aircraft config file directories. - @param path path to the aircraft directory. For instance: - "aircraft". Under aircraft, then, would be directories for various - modeled aircraft such as C172/, x15/, etc. */ + /** Set the path to the aircraft config file directories. + Under this path, then, would be directories for various modeled aircraft + such as C172/, x15/, etc. + Relative paths are taken from the root directory. + @param path path to the aircraft directory, for instance "aircraft". + @see SetRootDir + @see GetAircraftPath */ bool SetAircraftPath(const SGPath& path) { AircraftPath = GetFullPath(path); return true; } - - /** Sets the path to the systems config file directories. - @param path path to the directory under which systems config - files are kept, for instance "systems" */ + + /** Set the path to the systems config file directories. + Relative paths are taken from the root directory. + @param path path to the directory under which systems config files are + kept, for instance "systems" + @see SetRootDir + @see GetSystemsPath */ bool SetSystemsPath(const SGPath& path) { SystemsPath = GetFullPath(path); return true; } - + + /** Set the directory where the output files will be written. + Relative paths are taken from the root directory. + @param path path to the directory under which the output files will be + written. + @see SetRootDir + @see GetOutputPath */ + bool SetOutputPath(const SGPath& path) { + OutputPath = GetFullPath(path); + return true; + } + /// @name Top-level executive State and Model retrieval mechanism ///@{ /// Returns the FGAtmosphere pointer. @@ -364,13 +390,15 @@ public: ///@} /// Retrieves the engine path. - const SGPath& GetEnginePath(void) {return EnginePath;} + const SGPath& GetEnginePath(void) { return EnginePath; } /// Retrieves the aircraft path. - const SGPath& GetAircraftPath(void) {return AircraftPath;} + const SGPath& GetAircraftPath(void) { return AircraftPath; } /// Retrieves the systems path. - const SGPath& GetSystemsPath(void) {return SystemsPath;} + const SGPath& GetSystemsPath(void) { return SystemsPath; } /// Retrieves the full aircraft path name. - const SGPath& GetFullAircraftPath(void) {return FullAircraftPath;} + const SGPath& GetFullAircraftPath(void) { return FullAircraftPath; } + /// Retrieves the path to the output files. + const SGPath& GetOutputPath(void) { return OutputPath; } /** Retrieves the value of a property. @param property the name of the property @@ -535,13 +563,23 @@ public: @param delta_t the time step in seconds. */ void Setdt(double delta_t) { dT = delta_t; } - /** Sets the root directory where JSBSim starts looking for its system - directories. - @param rootDir the string containing the root directory. */ + /** Set the root directory that is used to obtain absolute paths from + relative paths. + Aircraft, engine, systems and output paths are not updated by this + method. You must call each methods (SetAircraftPath(), SetEnginePath(), + etc.) individually if you need to update these paths as well. + @param rootDir the path to the root directory. + @see GetRootDir + @see SetAircraftPath + @see SetEnginePath + @see SetSystemsPath + @see SetOutputPath + */ void SetRootDir(const SGPath& rootDir) {RootDir = rootDir;} - /** Retrieves the Root Directory. - @return the string representing the root (base) JSBSim directory. */ + /** Retrieve the Root Directory. + @return the path to the root (base) JSBSim directory. + @see SetRootDir */ const SGPath& GetRootDir(void) const {return RootDir;} /** Increments the simulation time if not in Holding mode. The Frame counter @@ -600,6 +638,7 @@ private: SGPath FullAircraftPath; SGPath EnginePath; SGPath SystemsPath; + SGPath OutputPath; std::string CFGVersion; std::string Release; SGPath RootDir; diff --git a/src/FDM/JSBSim/FGJSBBase.h b/src/FDM/JSBSim/FGJSBBase.h index cc6b6af11..69fbb0014 100644 --- a/src/FDM/JSBSim/FGJSBBase.h +++ b/src/FDM/JSBSim/FGJSBBase.h @@ -42,6 +42,7 @@ INCLUDES #include <queue> #include <string> #include <cmath> +#include <stdexcept> #include "input_output/string_utilities.h" @@ -55,6 +56,11 @@ FORWARD DECLARATIONS namespace JSBSim { +class BaseException : public std::runtime_error { + public: + BaseException(const std::string& msg) : std::runtime_error(msg) {} +}; + /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS DOCUMENTATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ @@ -263,7 +269,7 @@ public: static double PitotTotalPressure(double mach, double p); /** Compute the Mach number from the differential pressure (qc) and the - * static pressure. Based on the formulas in the US Air Force Aircraft + * static pressure. Based on the formulas in the US Air Force Aircraft * Performance Flight Testing Manual (AFFTC-TIH-99-01). * @param qc The differential/impact pressure * @param p Pressure in psf @@ -271,7 +277,7 @@ public: static double MachFromImpactPressure(double qc, double p); /** Calculate the calibrated airspeed from the Mach number. Based on the - * formulas in the US Air Force Aircraft Performance Flight Testing + * formulas in the US Air Force Aircraft Performance Flight Testing * Manual (AFFTC-TIH-99-01). * @param mach The Mach number * @param p Pressure in psf @@ -280,7 +286,7 @@ public: static double VcalibratedFromMach(double mach, double p); /** Calculate the Mach number from the calibrated airspeed.Based on the - * formulas in the US Air Force Aircraft Performance Flight Testing + * formulas in the US Air Force Aircraft Performance Flight Testing * Manual (AFFTC-TIH-99-01). * @param vcas The calibrated airspeed (CAS) in ft/s * @param p Pressure in psf @@ -321,13 +327,13 @@ public: static bool EqualToRoundoff(double a, float b) { return EqualToRoundoff((float)a, b); } - + /** Constrain a value between a minimum and a maximum value. */ static constexpr double Constrain(double min, double value, double max) { return value<min?(min):(value>max?(max):(value)); } - + static constexpr double sign(double num) {return num>=0.0?1.0:-1.0;} static double GaussianRandomNumber(void); diff --git a/src/FDM/JSBSim/initialization/FGInitialCondition.cpp b/src/FDM/JSBSim/initialization/FGInitialCondition.cpp index 774b5596b..3f5935935 100644 --- a/src/FDM/JSBSim/initialization/FGInitialCondition.cpp +++ b/src/FDM/JSBSim/initialization/FGInitialCondition.cpp @@ -808,7 +808,7 @@ void FGInitialCondition::SetAltitudeASLFtIC(double alt) } geodAlt = z/sinGeodLat-N*(1-e2); } - + double longitude = position.GetLongitude(); position.SetPositionGeodetic(longitude, geodLatitude, geodAlt); } @@ -1013,13 +1013,17 @@ bool FGInitialCondition::Load(const SGPath& rstfile, bool useStoredPath) // Make sure that the document is valid if (!document) { - cerr << "File: " << init_file_name << " could not be read." << endl; - exit(-1); + stringstream s; + s << "File: " << init_file_name << " could not be read."; + cerr << s.str() << endl; + throw BaseException(s.str()); } if (document->GetName() != string("initialize")) { - cerr << "File: " << init_file_name << " is not a reset file." << endl; - exit(-1); + stringstream s; + s << "File: " << init_file_name << " is not a reset file."; + cerr << s.str() << endl; + throw BaseException(s.str()); } double version = HUGE_VAL; @@ -1031,8 +1035,9 @@ bool FGInitialCondition::Load(const SGPath& rstfile, bool useStoredPath) if (version == HUGE_VAL) { result = Load_v1(document); // Default to the old version } else if (version >= 3.0) { - cerr << "Only initialization file formats 1 and 2 are currently supported" << endl; - exit (-1); + const string s("Only initialization file formats 1 and 2 are currently supported"); + cerr << document->ReadFrom() << endl << s << endl; + throw BaseException(s); } else if (version >= 2.0) { result = Load_v2(document); } else if (version >= 1.0) { @@ -1182,15 +1187,7 @@ bool FGInitialCondition::Load_v1(Element* document) if (document->FindElement("trim")) SetTrimRequest(document->FindElementValue("trim")); - // Refer to Stevens and Lewis, 1.5-14a, pg. 49. - // This is the rotation rate of the "Local" frame, expressed in the local frame. - const FGMatrix33& Tl2b = orientation.GetT(); - double radInv = 1.0 / position.GetRadius(); - FGColumnVector3 vOmegaLocal = {radInv*vUVW_NED(eEast), - -radInv*vUVW_NED(eNorth), - -radInv*vUVW_NED(eEast)*tan(position.GetLatitude())}; - - vPQR_body = Tl2b * vOmegaLocal; + vPQR_body.InitMatrix(); return result; } @@ -1403,19 +1400,12 @@ bool FGInitialCondition::Load_v2(Element* document) // - Body Element* attrate_el = document->FindElement("attitude_rate"); - const FGMatrix33& Tl2b = orientation.GetT(); - - // Refer to Stevens and Lewis, 1.5-14a, pg. 49. - // This is the rotation rate of the "Local" frame, expressed in the local frame. - double radInv = 1.0 / position.GetRadius(); - FGColumnVector3 vOmegaLocal = { radInv*vUVW_NED(eEast), - -radInv*vUVW_NED(eNorth), - -radInv*vUVW_NED(eEast)*tan(position.GetLatitude())}; if (attrate_el) { string frame = attrate_el->GetAttributeValue("frame"); frame = to_lower(frame); + const FGMatrix33& Tl2b = orientation.GetT(); FGColumnVector3 vAttRate = attrate_el->FindElementTripletConvertTo("RAD/SEC"); if (frame == "eci") { @@ -1424,6 +1414,12 @@ bool FGInitialCondition::Load_v2(Element* document) } else if (frame == "ecef") { vPQR_body = Tl2b * position.GetTec2l() * vAttRate; } else if (frame == "local") { + // Refer to Stevens and Lewis, 1.5-14a, pg. 49. + // This is the rotation rate of the "Local" frame, expressed in the local frame. + double radInv = 1.0 / position.GetRadius(); + FGColumnVector3 vOmegaLocal = {radInv*vUVW_NED(eEast), + -radInv*vUVW_NED(eNorth), + -radInv*vUVW_NED(eEast)*tan(position.GetLatitude())}; vPQR_body = Tl2b * (vAttRate + vOmegaLocal); } else if (frame == "body") { vPQR_body = vAttRate; @@ -1434,11 +1430,11 @@ bool FGInitialCondition::Load_v2(Element* document) result = false; } else if (frame.empty()) { - vPQR_body = Tl2b * vOmegaLocal; + vPQR_body.InitMatrix(); } } else { // Body frame attitude rate assumed 0 relative to local. - vPQR_body = Tl2b * vOmegaLocal; + vPQR_body.InitMatrix(); } return result; diff --git a/src/FDM/JSBSim/initialization/FGInitialCondition.h b/src/FDM/JSBSim/initialization/FGInitialCondition.h index 9190c4651..0a84da1bc 100644 --- a/src/FDM/JSBSim/initialization/FGInitialCondition.h +++ b/src/FDM/JSBSim/initialization/FGInitialCondition.h @@ -519,7 +519,7 @@ public: { const FGMatrix33& Tb2l = orientation.GetTInv(); FGColumnVector3 _vt_NED = Tb2l * Tw2b * FGColumnVector3(vt, 0., 0.); - return _vt_NED(eW); + return -_vt_NED(eW); } /** Gets the initial body velocity diff --git a/src/FDM/JSBSim/input_output/FGOutputFG.cpp b/src/FDM/JSBSim/input_output/FGOutputFG.cpp index f95f980f9..846ea85e3 100644 --- a/src/FDM/JSBSim/input_output/FGOutputFG.cpp +++ b/src/FDM/JSBSim/input_output/FGOutputFG.cpp @@ -214,7 +214,7 @@ void FGOutputFG::SocketDataFill(FGNetFDM* net) net->stall_warning = 0.0; // 0.0 - 1.0 indicating the amount of stall net->slip_deg = (float)(Auxiliary->Getbeta(inDegrees)); // slip ball deflection, deg - net->num_engines = min((unsigned) FGNetFDM::FG_MAX_ENGINES, Propulsion->GetNumEngines()); // Number of valid engines + net->num_engines = min(FGNetFDM::FG_MAX_ENGINES,Propulsion->GetNumEngines()); // Number of valid engines for (i=0; i<net->num_engines; i++) { FGEngine* engine = Propulsion->GetEngine(i); @@ -254,7 +254,7 @@ void FGOutputFG::SocketDataFill(FGNetFDM* net) } } - net->num_tanks = min((unsigned) FGNetFDM::FG_MAX_TANKS, Propulsion->GetNumTanks()); // Max number of fuel tanks + net->num_tanks = min(FGNetFDM::FG_MAX_TANKS, Propulsion->GetNumTanks()); // Max number of fuel tanks for (i=0; i<net->num_tanks; i++) { net->fuel_quantity[i] = (float)(((FGTank *)Propulsion->GetTank(i))->GetContents()); diff --git a/src/FDM/JSBSim/input_output/FGOutputFile.h b/src/FDM/JSBSim/input_output/FGOutputFile.h index 99298bee3..ddfffb1ce 100644 --- a/src/FDM/JSBSim/input_output/FGOutputFile.h +++ b/src/FDM/JSBSim/input_output/FGOutputFile.h @@ -100,7 +100,7 @@ public: the next call to SetStartNewOutput(). @param name new name */ void SetOutputName(const std::string& fname) override { - Name = (FDMExec->GetRootDir()/fname).utf8Str(); + Name = (FDMExec->GetOutputPath()/fname).utf8Str(); runID_postfix = -1; Filename = SGPath(); } diff --git a/src/FDM/JSBSim/input_output/FGOutputSocket.cpp b/src/FDM/JSBSim/input_output/FGOutputSocket.cpp index 6592efd9c..0ad87af0d 100644 --- a/src/FDM/JSBSim/input_output/FGOutputSocket.cpp +++ b/src/FDM/JSBSim/input_output/FGOutputSocket.cpp @@ -121,6 +121,12 @@ bool FGOutputSocket::Load(Element* el) el->GetAttributeValue("protocol") + "/" + el->GetAttributeValue("port")); + // Check if output precision for doubles has been specified, default to 7 if not + if(el->HasAttribute("precision")) + precision = (int)el->GetAttributeValueAsNumber("precision"); + else + precision = 7; + return true; } @@ -130,7 +136,7 @@ bool FGOutputSocket::InitModel(void) { if (FGOutputType::InitModel()) { delete socket; - socket = new FGfdmSocket(SockName, SockPort, SockProtocol); + socket = new FGfdmSocket(SockName, SockPort, SockProtocol, precision); if (socket == 0) return false; if (!socket->GetConnectStatus()) return false; diff --git a/src/FDM/JSBSim/input_output/FGOutputSocket.h b/src/FDM/JSBSim/input_output/FGOutputSocket.h index d65ceec9b..d598ce222 100644 --- a/src/FDM/JSBSim/input_output/FGOutputSocket.h +++ b/src/FDM/JSBSim/input_output/FGOutputSocket.h @@ -108,6 +108,7 @@ protected: unsigned int SockPort; FGfdmSocket::ProtocolType SockProtocol; FGfdmSocket* socket; + int precision; }; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/FDM/JSBSim/input_output/FGPropertyManager.cpp b/src/FDM/JSBSim/input_output/FGPropertyManager.cpp index 9f8fbf806..9ec56b539 100644 --- a/src/FDM/JSBSim/input_output/FGPropertyManager.cpp +++ b/src/FDM/JSBSim/input_output/FGPropertyManager.cpp @@ -28,6 +28,7 @@ INCLUDES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ +#include <assert.h> #include "FGPropertyManager.h" /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -110,13 +111,6 @@ bool FGPropertyNode::HasNode (const string &path) //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -string FGPropertyNode::GetName( void ) const -{ - return getNameString(); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - string FGPropertyNode::GetPrintableName( void ) const { string temp_string(getNameString()); @@ -301,7 +295,7 @@ void FGPropertyNode::SetWritable (const string &name, bool state ) //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void FGPropertyManager::Untie (const string &name) +void FGPropertyManager::Untie(const string &name) { SGPropertyNode* property = root->getNode(name.c_str()); if (!property) { @@ -309,8 +303,18 @@ void FGPropertyManager::Untie (const string &name) return; } - vector <SGPropertyNode_ptr>::iterator it; - for (it = tied_properties.begin(); it != tied_properties.end(); ++it) { + Untie(property); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGPropertyManager::Untie(SGPropertyNode *property) +{ + const string& name = property->getNameString(); + + assert(property->isTied()); + + for (auto it = tied_properties.begin(); it != tied_properties.end(); ++it) { if (*it == property) { property->untie(); tied_properties.erase(it); diff --git a/src/FDM/JSBSim/input_output/FGPropertyManager.h b/src/FDM/JSBSim/input_output/FGPropertyManager.h index 4015f9118..dfdf2fa02 100644 --- a/src/FDM/JSBSim/input_output/FGPropertyManager.h +++ b/src/FDM/JSBSim/input_output/FGPropertyManager.h @@ -97,7 +97,7 @@ class FGPropertyNode : public SGPropertyNode /** * Get the name of a node */ - std::string GetName( void ) const; + const std::string& GetName( void ) const { return getNameString(); } /** * Get the name of a node without underscores, etc. @@ -413,9 +413,21 @@ class FGPropertyManager * * Classes should use this function to release control of any * properties they are managing. + * + * @param name The property name to untie (full path). */ void Untie (const std::string &name); + /** + * Untie a property from an external data source. + * + * Classes should use this function to release control of any + * properties they are managing. + * + * @param property A pointer to the property to untie. + */ + void Untie (SGPropertyNode* property); + /** * Unbind all properties bound by this manager to an external data source. * diff --git a/src/FDM/JSBSim/input_output/FGScript.cpp b/src/FDM/JSBSim/input_output/FGScript.cpp index 4db9865fd..fd5d309a7 100644 --- a/src/FDM/JSBSim/input_output/FGScript.cpp +++ b/src/FDM/JSBSim/input_output/FGScript.cpp @@ -150,7 +150,7 @@ bool FGScript::LoadScript(const SGPath& script, double default_dT, // Make sure that the desired time is reached and executed. EndTime += 0.99*FDMExec->GetDeltaT(); - + // read aircraft and initialization files element = document->FindElement("use"); @@ -193,7 +193,7 @@ bool FGScript::LoadScript(const SGPath& script, double default_dT, while (element) { if (!FDMExec->GetInput()->Load(element)) return false; - + element = document->FindNextElement("input"); } @@ -206,7 +206,7 @@ bool FGScript::LoadScript(const SGPath& script, double default_dT, while (element) { if (!FDMExec->GetOutput()->Load(element, scriptDir)) return false; - + element = document->FindNextElement("output"); } @@ -295,7 +295,7 @@ bool FGScript::LoadScript(const SGPath& script, double default_dT, } else newEvent->NotifyProperties.push_back(new FGPropertyValue(notifyPropertyName, PropertyManager)); - + string caption_attribute = notify_property_element->GetAttributeValue("caption"); if (caption_attribute.empty()) { newEvent->DisplayString.push_back(notifyPropertyName); @@ -496,7 +496,7 @@ bool FGScript::RunScript(void) } else { cout << endl << underon << highint << thisEvent.Name << normint << underoff - << " (Event " << event_ctr << ")" + << " (Event " << event_ctr << ")" << " executed at time: " << highint << currentTime << normint << endl; } @@ -573,7 +573,7 @@ void FGScript::Debug(int from) << " = " << node->getDoubleValue() << endl; } - + if (LocalProperties.empty()) cout << endl; for (unsigned i=0; i<Events.size(); i++) { @@ -597,38 +597,38 @@ void FGScript::Debug(int from) for (unsigned j=0; j<Events[i].SetValue.size(); j++) { if (Events[i].SetValue[j] == 0.0 && Events[i].Functions[j] != 0L) { if (Events[i].SetParam[j] == 0) { - if (Events[i].SetParamName[j].size() == 0) { - cerr << fgred << highint << endl - << " An attempt has been made to access a non-existent property" << endl - << " in this event. Please check the property names used, spelling, etc." - << reset << endl; - exit(-1); + if (Events[i].SetParamName[j].empty()) { + stringstream s; + s << " An attempt has been made to access a non-existent property" << endl + << " in this event. Please check the property names used, spelling, etc."; + cerr << fgred << highint << endl << s.str() << reset << endl; + throw BaseException(s.str()); } else { cout << endl << " set " << Events[i].SetParamName[j] << " to function value (Late Bound)"; - } + } } else { - cout << endl << " set " - << Events[i].SetParam[j]->GetRelativeName("/fdm/jsbsim/") - << " to function value"; + cout << endl << " set " + << Events[i].SetParam[j]->GetRelativeName("/fdm/jsbsim/") + << " to function value"; } } else { if (Events[i].SetParam[j] == 0) { - if (Events[i].SetParamName[j].size() == 0) { - cerr << fgred << highint << endl - << " An attempt has been made to access a non-existent property" << endl - << " in this event. Please check the property names used, spelling, etc." - << reset << endl; - exit(-1); + if (Events[i].SetParamName[j].empty()) { + stringstream s; + s << " An attempt has been made to access a non-existent property" << endl + << " in this event. Please check the property names used, spelling, etc."; + cerr << fgred << highint << endl << s.str() << reset << endl; + throw BaseException(s.str()); } else { cout << endl << " set " << Events[i].SetParamName[j] << " to function value (Late Bound)"; - } + } } else { - cout << endl << " set " - << Events[i].SetParam[j]->GetRelativeName("/fdm/jsbsim/") - << " to " << Events[i].SetValue[j]; - } + cout << endl << " set " + << Events[i].SetParam[j]->GetRelativeName("/fdm/jsbsim/") + << " to " << Events[i].SetValue[j]; + } } switch (Events[i].Type[j]) { diff --git a/src/FDM/JSBSim/input_output/FGfdmSocket.cpp b/src/FDM/JSBSim/input_output/FGfdmSocket.cpp index 5fddce2b3..e6ebc91e1 100644 --- a/src/FDM/JSBSim/input_output/FGfdmSocket.cpp +++ b/src/FDM/JSBSim/input_output/FGfdmSocket.cpp @@ -81,12 +81,13 @@ static bool LoadWinSockDLL(int debug_lvl) } #endif -FGfdmSocket::FGfdmSocket(const string& address, int port, int protocol) +FGfdmSocket::FGfdmSocket(const string& address, int port, int protocol, int precision) { sckt = sckt_in = 0; Protocol = (ProtocolType)protocol; connected = false; struct addrinfo *addr = nullptr; + this->precision = precision; #if defined(_MSC_VER) || defined(__MINGW32__) if (!LoadWinSockDLL(debug_lvl)) return; @@ -150,12 +151,13 @@ FGfdmSocket::FGfdmSocket(const string& address, int port, int protocol) //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // assumes TCP or UDP socket on localhost, for inbound datagrams -FGfdmSocket::FGfdmSocket(int port, int protocol) +FGfdmSocket::FGfdmSocket(int port, int protocol, int precision) { sckt = -1; connected = false; Protocol = (ProtocolType)protocol; string ProtocolName; + this->precision = precision; #if defined(_MSC_VER) || defined(__MINGW32__) if (!LoadWinSockDLL(debug_lvl)) return; @@ -338,7 +340,7 @@ void FGfdmSocket::Append(const char* item) void FGfdmSocket::Append(double item) { if (buffer.tellp() > 0) buffer << ','; - buffer << std::setw(12) << std::setprecision(7) << item; + buffer << std::setw(12) << std::setprecision(precision) << item; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/FDM/JSBSim/input_output/FGfdmSocket.h b/src/FDM/JSBSim/input_output/FGfdmSocket.h index 4075040c1..7327088df 100644 --- a/src/FDM/JSBSim/input_output/FGfdmSocket.h +++ b/src/FDM/JSBSim/input_output/FGfdmSocket.h @@ -70,10 +70,8 @@ CLASS DECLARATION class FGfdmSocket : public FGJSBBase { public: - FGfdmSocket(const std::string& address, int port) - : FGfdmSocket(address, port, ptTCP) {} - FGfdmSocket(const std::string&, int, int); - FGfdmSocket(int, int); + FGfdmSocket(const std::string& address, int port, int protocol, int precision = 7); + FGfdmSocket(int port, int protocol, int precision = 7); ~FGfdmSocket(); void Send(void); void Send(const char *data, int length); @@ -104,6 +102,7 @@ private: struct sockaddr_in scktName; struct hostent *host; std::ostringstream buffer; + int precision; bool connected; void Debug(int from); }; diff --git a/src/FDM/JSBSim/math/FGCondition.cpp b/src/FDM/JSBSim/math/FGCondition.cpp index 14f94fb24..c77341a94 100644 --- a/src/FDM/JSBSim/math/FGCondition.cpp +++ b/src/FDM/JSBSim/math/FGCondition.cpp @@ -124,7 +124,7 @@ FGCondition::FGCondition(const string& test, FGPropertyManager* PropertyManager, Comparison = mComparison[conditional]; if (Comparison == ecUndef) { - std::invalid_argument("JSBSim FGCondition: Comparison operator: \""+conditional + throw std::invalid_argument("JSBSim FGCondition: Comparison operator: \""+conditional +"\" does not exist. Please check the conditional."); } } diff --git a/src/FDM/JSBSim/math/FGFunction.cpp b/src/FDM/JSBSim/math/FGFunction.cpp index 22959aa76..c4cc3efa5 100644 --- a/src/FDM/JSBSim/math/FGFunction.cpp +++ b/src/FDM/JSBSim/math/FGFunction.cpp @@ -890,10 +890,8 @@ void FGFunction::Load(Element* el, FGPropertyValue* var, FGFDMExec* fdmex, FGFunction::~FGFunction() { - if (pNode && pNode->isTied()) { - string pName = pNode->GetFullyQualifiedName(); - PropertyManager->Untie(pName); - } + if (pNode && pNode->isTied()) + PropertyManager->Untie(pNode); Debug(1); } diff --git a/src/FDM/JSBSim/math/FGMatrix33.cpp b/src/FDM/JSBSim/math/FGMatrix33.cpp index f187d89d1..bcf5105f1 100644 --- a/src/FDM/JSBSim/math/FGMatrix33.cpp +++ b/src/FDM/JSBSim/math/FGMatrix33.cpp @@ -425,19 +425,16 @@ FGMatrix33 FGMatrix33::operator/(const double scalar) const { FGMatrix33 Quot; - if ( scalar != 0 ) { - double tmp = 1.0/scalar; - Quot.data[0] = data[0] * tmp; - Quot.data[3] = data[3] * tmp; - Quot.data[6] = data[6] * tmp; - Quot.data[1] = data[1] * tmp; - Quot.data[4] = data[4] * tmp; - Quot.data[7] = data[7] * tmp; - Quot.data[2] = data[2] * tmp; - Quot.data[5] = data[5] * tmp; - Quot.data[8] = data[8] * tmp; - } else - throw MatrixException{"Attempt to divide by zero in method FGMatrix33::operator/(const double scalar)"}; + double tmp = 1.0/scalar; + Quot.data[0] = data[0] * tmp; + Quot.data[3] = data[3] * tmp; + Quot.data[6] = data[6] * tmp; + Quot.data[1] = data[1] * tmp; + Quot.data[4] = data[4] * tmp; + Quot.data[7] = data[7] * tmp; + Quot.data[2] = data[2] * tmp; + Quot.data[5] = data[5] * tmp; + Quot.data[8] = data[8] * tmp; return Quot; } @@ -446,19 +443,16 @@ FGMatrix33 FGMatrix33::operator/(const double scalar) const FGMatrix33& FGMatrix33::operator/=(const double scalar) { - if ( scalar != 0 ) { - double tmp = 1.0/scalar; - data[0] *= tmp; - data[3] *= tmp; - data[6] *= tmp; - data[1] *= tmp; - data[4] *= tmp; - data[7] *= tmp; - data[2] *= tmp; - data[5] *= tmp; - data[8] *= tmp; - } else - throw MatrixException{"Attempt to divide by zero in method FGMatrix33::operator/=(const double scalar)"}; + double tmp = 1.0/scalar; + data[0] *= tmp; + data[3] *= tmp; + data[6] *= tmp; + data[1] *= tmp; + data[4] *= tmp; + data[7] *= tmp; + data[2] *= tmp; + data[5] *= tmp; + data[8] *= tmp; return *this; } diff --git a/src/FDM/JSBSim/math/FGMatrix33.h b/src/FDM/JSBSim/math/FGMatrix33.h index 0ca03e1bc..8e7791644 100644 --- a/src/FDM/JSBSim/math/FGMatrix33.h +++ b/src/FDM/JSBSim/math/FGMatrix33.h @@ -42,8 +42,8 @@ INCLUDES #include <string> #include <iosfwd> -#include <stdexcept> +#include "FGJSBBase.h" #include "FGColumnVector3.h" /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -54,23 +54,6 @@ namespace JSBSim { class FGQuaternion; -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -CLASS DOCUMENTATION -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -/** Exception convenience class. - */ - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -DECLARATION: MatrixException -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -class MatrixException : public std::runtime_error -{ -public: - MatrixException(const std::string& msg) : std::runtime_error{msg} { } -}; - /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS DOCUMENTATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ diff --git a/src/FDM/JSBSim/math/FGTable.cpp b/src/FDM/JSBSim/math/FGTable.cpp index 0f3ab6226..ff88b1281 100644 --- a/src/FDM/JSBSim/math/FGTable.cpp +++ b/src/FDM/JSBSim/math/FGTable.cpp @@ -158,7 +158,7 @@ FGTable::FGTable(FGPropertyManager* propMan, Element* el, std::cerr << el->ReadFrom() <<" An unknown table type attribute is listed: " << call_type << endl; - throw TableException("Unknown table type."); + throw BaseException("Unknown table type."); } // Determine and store the lookup properties for this table unless this table @@ -199,7 +199,7 @@ FGTable::FGTable(FGPropertyManager* propMan, Element* el, } else if (lookup_axis == string("table")) { lookupProperty[eTable] = node; } else if (!lookup_axis.empty()) { - throw TableException("Lookup table axis specification not understood: " + lookup_axis); + throw BaseException("Lookup table axis specification not understood: " + lookup_axis); } else { // assumed single dimension table; row lookup lookupProperty[eRow] = node; } @@ -232,7 +232,7 @@ FGTable::FGTable(FGPropertyManager* propMan, Element* el, std::cerr << el->ReadFrom() << "No independentVars found, and table is not marked as internal," << " nor is it a 3D table." << endl; - throw TableException("No independent variable found for table."); + throw BaseException("No independent variable found for table."); } } // end lookup property code @@ -245,8 +245,16 @@ FGTable::FGTable(FGPropertyManager* propMan, Element* el, } for (i=0; i<tableData->GetNumDataLines(); i++) { - buf << tableData->GetDataLine(i) << string(" "); + string line = tableData->GetDataLine(i); + if (line.find_first_not_of("0123456789.-+eE \t\n") != string::npos) { + cerr << " In file " << tableData->GetFileName() << endl + << " Illegal character found in line " + << tableData->GetLineNumber() + i + 1 << ": " << endl << line << endl; + throw BaseException("Illegal character"); + } + buf << line << " "; } + switch (dimension) { case 1: nRows = tableData->GetNumDataLines(); @@ -267,12 +275,12 @@ FGTable::FGTable(FGPropertyManager* propMan, Element* el, if (nCols < 2) { std::cerr << tableData->ReadFrom() << "Not enough columns in table data" << endl; - throw TableException("Not enough columns in table data."); + throw BaseException("Not enough columns in table data."); } } else { std::cerr << tableData->ReadFrom() << "Not enough rows in table data" << endl; - throw TableException("Not enough rows in the table data."); + throw BaseException("Not enough rows in the table data."); } Type = tt2D; @@ -330,7 +338,7 @@ FGTable::FGTable(FGPropertyManager* propMan, Element* el, if (nameel != 0) std::cerr << " of table in " << nameel->GetAttributeValue("name"); std::cerr << ":" << reset << endl << " " << Data[b][1] << "<=" << Data[b-1][1] << endl; - throw TableException("Breakpoint lookup is not monotonically increasing"); + throw BaseException("Breakpoint lookup is not monotonically increasing"); } } } @@ -346,7 +354,7 @@ FGTable::FGTable(FGPropertyManager* propMan, Element* el, if (nameel != 0) std::cerr << " of table in " << nameel->GetAttributeValue("name"); std::cerr << ":" << reset << endl << " " << Data[0][c] << "<=" << Data[0][c-1] << endl; - throw TableException("FGTable: column lookup is not monotonically increasing"); + throw BaseException("FGTable: column lookup is not monotonically increasing"); } } } @@ -362,7 +370,7 @@ FGTable::FGTable(FGPropertyManager* propMan, Element* el, if (nameel != 0) std::cerr << " of table in " << nameel->GetAttributeValue("name"); std::cerr << ":" << reset << endl << " " << Data[r][0] << "<=" << Data[r-1][0] << endl; - throw TableException("FGTable: row lookup is not monotonically increasing"); + throw BaseException("FGTable: row lookup is not monotonically increasing"); } } } @@ -393,10 +401,10 @@ FGTable::~FGTable() // Untie the bound property so that it makes no further reference to this // instance of FGTable after the destruction is completed. if (!Name.empty() && !internal) { - string tmp = mkPropertyName(nullptr, ""); + string tmp = PropertyManager->mkPropertyName(Name, false); FGPropertyNode* node = PropertyManager->GetNode(tmp); - if (node->isTied()) - PropertyManager->Untie(tmp); + if (node && node->isTied()) + PropertyManager->Untie(node); } if (nTables > 0) { @@ -653,33 +661,26 @@ void FGTable::Print(void) //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -string FGTable::mkPropertyName(Element* el, const std::string& Prefix) -{ - if (!Prefix.empty()) { - if (is_number(Prefix)) { - if (Name.find("#") != string::npos) { // if "#" is found - Name = replace(Name, "#", Prefix); - } else { - cerr << el->ReadFrom() - << "Malformed table name with number: " << Prefix - << " and property name: " << Name - << " but no \"#\" sign for substitution." << endl; - } - } else { - Name = Prefix + "/" + Name; - } - } - - return PropertyManager->mkPropertyName(Name, false); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - void FGTable::bind(Element* el, const string& Prefix) { typedef double (FGTable::*PMF)(void) const; + if ( !Name.empty() && !internal) { - string tmp = mkPropertyName(el, Prefix); + if (!Prefix.empty()) { + if (is_number(Prefix)) { + if (Name.find("#") != string::npos) { // if "#" is found + Name = replace(Name, "#", Prefix); + } else { + cerr << el->ReadFrom() + << "Malformed table name with number: " << Prefix + << " and property name: " << Name + << " but no \"#\" sign for substitution." << endl; + } + } else { + Name = Prefix + "/" + Name; + } + } + string tmp = PropertyManager->mkPropertyName(Name, false); if (PropertyManager->HasNode(tmp)) { FGPropertyNode* _property = PropertyManager->GetNode(tmp); @@ -689,7 +690,8 @@ void FGTable::bind(Element* el, const string& Prefix) throw("Failed to bind the property to an existing already tied node."); } } - PropertyManager->Tie( tmp, this, (PMF)&FGTable::GetValue); + + PropertyManager->Tie(tmp, this, (PMF)&FGTable::GetValue); } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/FDM/JSBSim/math/FGTable.h b/src/FDM/JSBSim/math/FGTable.h index d9cea9198..dceaf629a 100644 --- a/src/FDM/JSBSim/math/FGTable.h +++ b/src/FDM/JSBSim/math/FGTable.h @@ -226,19 +226,6 @@ combustion_efficiency = Lookup_Combustion_Efficiency->GetValue(equivalence_ratio @author Jon S. Berndt */ -/** Exception convenience class. - */ - -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -DECLARATION: TableException -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ - -class TableException : public std::runtime_error -{ -public: - TableException(const std::string& msg) : std::runtime_error{msg} { } -}; - /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS DECLARATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ @@ -317,8 +304,6 @@ private: FGPropertyManager* const PropertyManager; std::string Name; void bind(Element* el, const std::string& Prefix); - - std::string mkPropertyName(Element* el, const std::string& Prefix); void Debug(int from); }; } diff --git a/src/FDM/JSBSim/models/FGAerodynamics.cpp b/src/FDM/JSBSim/models/FGAerodynamics.cpp index 2cb7cda7b..2de19dd5f 100644 --- a/src/FDM/JSBSim/models/FGAerodynamics.cpp +++ b/src/FDM/JSBSim/models/FGAerodynamics.cpp @@ -229,9 +229,13 @@ bool FGAerodynamics::Run(bool Holding) vForcesAtCG = Ts2b*vFnativeAtCG; break; default: - cerr << endl << " A proper axis type has NOT been selected. Check " - << "your aerodynamics definition." << endl; - exit(-1); + { + stringstream s; + s << " A proper axis type has NOT been selected. Check " + << "your aerodynamics definition."; + cerr << endl << s.str() << endl; + throw BaseException(s.str()); + } } // Calculate aerodynamic reference point shift, if any. The shift takes place // in the structual axis. That is, if the shift is positive, it is towards the @@ -257,7 +261,7 @@ bool FGAerodynamics::Run(bool Holding) vMomentsMRC(axis_ctr+1) += (*f)->GetValue(); } } - + // Transform moments to bodyXYZ if the moments are specified in stability or // wind axes vMomentsMRCBodyXYZ.InitMatrix(); @@ -272,13 +276,17 @@ bool FGAerodynamics::Run(bool Holding) vMomentsMRCBodyXYZ = in.Tw2b*vMomentsMRC; break; default: - cerr << endl << " A proper axis type has NOT been selected. Check " - << "your aerodynamics definition." << endl; - exit(-1); + { + stringstream s; + s << " A proper axis type has NOT been selected. Check " + << "your aerodynamics definition."; + cerr << endl << s.str() << endl; + throw BaseException(s.str()); + } } vMoments = vMomentsMRCBodyXYZ + vDXYZcg*vForces; // M = r X F - + // Now add the "at CG" values to base forces - after the moments have been // transferred. vForces += vForcesAtCG; @@ -310,7 +318,7 @@ bool FGAerodynamics::Run(bool Holding) //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGColumnVector3 FGAerodynamics::GetForcesInStabilityAxes(void) const -{ +{ FGColumnVector3 vFs = Tb2s*vForces; // Need sign flips since drag is positive and lift is positive in stability axes vFs(eDrag) *= -1; vFs(eLift) *= -1; @@ -403,15 +411,15 @@ bool FGAerodynamics::Load(Element *document) //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // // This private class function checks to verify consistency in the choice of -// aerodynamic axes used in the config file. One set of LIFT|DRAG|SIDE, or +// aerodynamic axes used in the config file. One set of LIFT|DRAG|SIDE, or // X|Y|Z, or AXIAL|NORMAL|SIDE must be chosen; mixed system axes are not allowed. -// Note that if the "SIDE" axis specifier is entered first in a config file, +// Note that if the "SIDE" axis specifier is entered first in a config file, // a warning message will be given IF the AXIAL|NORMAL specifiers are also given. // This is OK, and the warning is due to the SIDE specifier used for both // the Lift/Drag and Axial/Normal axis systems. -// Alternatively the axis name 'X|Y|Z or ROLL|PITCH|YAW' can be specified in +// Alternatively the axis name 'X|Y|Z or ROLL|PITCH|YAW' can be specified in // conjunction with a frame 'BODY|STABILITY|WIND', for example: -// <axis name="X" frame="STABILITY"/> +// <axis name="X" frame="STABILITY"/> void FGAerodynamics::DetermineAxisSystem(Element* document) { @@ -447,10 +455,12 @@ void FGAerodynamics::DetermineAxisSystem(Element* document) << " aircraft config file. (NORMAL AXIAL)" << endl; } } else { // error - cerr << endl << axis_element->ReadFrom() - << endl << " An unknown axis type, " << axis << " has been specified" - << " in the aircraft configuration file." << endl; - exit(-1); + stringstream s; + s << axis_element->ReadFrom() + << endl << " An unknown axis type, " << axis << " has been specified" + << " in the aircraft configuration file."; + cerr << endl << s.str() << endl; + throw BaseException(s.str()); } axis_element = document->FindNextElement("axis"); } @@ -495,8 +505,10 @@ void FGAerodynamics::ProcessAxesNameAndFrame(eAxisType& axisType, const string& << " aircraft config file." << validNames << " - WIND" << endl; } else { - cerr << endl << " Unknown axis frame type of - " << frame << endl; - exit(-1); + stringstream s; + s << " Unknown axis frame type of - " << frame; + cerr << endl << s.str() << endl; + throw BaseException(s.str()); } } @@ -596,7 +608,7 @@ void FGAerodynamics::bind(void) //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // -// Build transformation matrices for transforming from stability axes to +// Build transformation matrices for transforming from stability axes to // body axes and to wind axes. Where "a" is alpha and "B" is beta: // // The transform from body to stability axes is: diff --git a/src/FDM/JSBSim/models/FGGasCell.cpp b/src/FDM/JSBSim/models/FGGasCell.cpp index 3aecd5c05..9e201415e 100644 --- a/src/FDM/JSBSim/models/FGGasCell.cpp +++ b/src/FDM/JSBSim/models/FGGasCell.cpp @@ -86,8 +86,9 @@ FGGasCell::FGGasCell(FGFDMExec* exec, Element* el, unsigned int num, if (element) { vXYZ = element->FindElementTripletConvertTo("IN"); } else { - cerr << "Fatal Error: No location found for this gas cell." << endl; - exit(-1); + const string s("Fatal Error: No location found for this gas cell."); + cerr << el->ReadFrom() << endl << s << endl; + throw BaseException(s); } if ((el->FindElement("x_radius") || el->FindElement("x_width")) && (el->FindElement("y_radius") || el->FindElement("y_width")) && @@ -126,7 +127,7 @@ FGGasCell::FGGasCell(FGFDMExec* exec, Element* el, unsigned int num, MaxVolume = M_PI * Yradius * Zradius * Xwidth; } else { cerr << "Warning: Unsupported gas cell shape." << endl; - MaxVolume = + MaxVolume = (4.0 * M_PI * Xradius * Yradius * Zradius / 3.0 + M_PI * Yradius * Zradius * Xwidth + M_PI * Xradius * Zradius * Ywidth + @@ -137,8 +138,9 @@ FGGasCell::FGGasCell(FGFDMExec* exec, Element* el, unsigned int num, Xwidth * Ywidth * Zwidth); } } else { - cerr << "Fatal Error: Gas cell shape must be given." << endl; - exit(-1); + const string s("Fatal Error: Gas cell shape must be given."); + cerr << el->ReadFrom() << endl << s << endl; + throw BaseException(s); } if (el->FindElement("max_overpressure")) { MaxOverpressure = el->FindElementValueAsNumberConvertTo("max_overpressure", @@ -146,12 +148,12 @@ FGGasCell::FGGasCell(FGFDMExec* exec, Element* el, unsigned int num, } if (el->FindElement("fullness")) { const double Fullness = el->FindElementValueAsNumber("fullness"); - if (0 <= Fullness) { - Volume = Fullness * MaxVolume; + if (0 <= Fullness) { + Volume = Fullness * MaxVolume; } else { cerr << "Warning: Invalid initial gas cell fullness value." << endl; } - } + } if (el->FindElement("valve_coefficient")) { ValveCoefficient = el->FindElementValueAsNumberConvertTo("valve_coefficient", @@ -171,7 +173,7 @@ FGGasCell::FGGasCell(FGFDMExec* exec, Element* el, unsigned int num, if (Volume != 0.0) { // Calculate initial gas content. Contents = Pressure * Volume / (R * Temperature); - + // Clip to max allowed value. const double IdealPressure = Contents * R * Temperature / MaxVolume; if (IdealPressure > Pressure + MaxOverpressure) { @@ -263,7 +265,7 @@ void FGGasCell::Calculate(double dt) const size_t no_ballonets = Ballonet.size(); //-- Read ballonet state -- - // NOTE: This model might need a more proper integration technique. + // NOTE: This model might need a more proper integration technique. double BallonetsVolume = 0.0; double BallonetsHeatFlow = 0.0; for (i = 0; i < no_ballonets; i++) { @@ -282,7 +284,7 @@ void FGGasCell::Calculate(double dt) dU += HeatTransferCoeff[i]->GetValue(); } // Don't include dt when accounting for adiabatic expansion/contraction. - // The rate of adiabatic cooling looks about right: ~5.4 Rankine/1000ft. + // The rate of adiabatic cooling looks about right: ~5.4 Rankine/1000ft. if (Contents > 0) { Temperature += (dU * dt - Pressure * dVolumeIdeal - BallonetsHeatFlow) / @@ -354,7 +356,7 @@ void FGGasCell::Calculate(double dt) //-- Current buoyancy -- // The buoyancy is computed using the atmospheres local density. Buoyancy = Volume * AirDensity * g; - + // Note: This is gross buoyancy. The weight of the gas itself and // any ballonets is not deducted here as the effects of the gas mass // is handled by FGMassBalance. @@ -372,7 +374,7 @@ void FGGasCell::Calculate(double dt) // Ellipsoid volume. Ixx = (1.0 / 5.0) * mass * (Yradius*Yradius + Zradius*Zradius); Iyy = (1.0 / 5.0) * mass * (Xradius*Xradius + Zradius*Zradius); - Izz = (1.0 / 5.0) * mass * (Xradius*Xradius + Yradius*Yradius); + Izz = (1.0 / 5.0) * mass * (Xradius*Xradius + Yradius*Yradius); } else if ((Xradius == 0.0) && (Yradius != 0.0) && (Zradius != 0.0) && (Xwidth != 0.0) && (Ywidth == 0.0) && (Zwidth == 0.0)) { // Cylindrical volume (might not be valid with an elliptical cross-section). @@ -407,7 +409,7 @@ void FGGasCell::Calculate(double dt) // Add the mass, moment and inertia of any ballonets. for (i = 0; i < no_ballonets; i++) { Mass += Ballonet[i]->GetMass(); - + // Add ballonet moments due to mass (in the structural frame). gasCellM(eX) += Ballonet[i]->GetXYZ(eX) * Ballonet[i]->GetMass()*slugtolb; @@ -415,7 +417,7 @@ void FGGasCell::Calculate(double dt) Ballonet[i]->GetXYZ(eY) * Ballonet[i]->GetMass()*slugtolb; gasCellM(eZ) += Ballonet[i]->GetXYZ(eZ) * Ballonet[i]->GetMass()*slugtolb; - + gasCellJ += Ballonet[i]->GetInertia(); } } @@ -451,9 +453,9 @@ void FGGasCell::Debug(int from) cout << " Cell location (X, Y, Z) (in.): " << vXYZ(eX) << ", " << vXYZ(eY) << ", " << vXYZ(eZ) << endl; cout << " Maximum volume: " << MaxVolume << " ft3" << endl; - cout << " Relief valve release pressure: " << MaxOverpressure << + cout << " Relief valve release pressure: " << MaxOverpressure << " lbs/ft2" << endl; - cout << " Manual valve coefficient: " << ValveCoefficient << + cout << " Manual valve coefficient: " << ValveCoefficient << " ft4*sec/slug" << endl; cout << " Initial temperature: " << Temperature << " Rankine" << endl; @@ -471,7 +473,7 @@ void FGGasCell::Debug(int from) } if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects } - if (debug_lvl & 8 ) { // Runtime state variables + if (debug_lvl & 8 ) { // Runtime state variables cout << " " << type << " cell holds " << Contents << " mol " << endl; cout << " Temperature: " << Temperature << " Rankine" << endl; cout << " Pressure: " << Pressure << " lbs/ft2" << endl; @@ -517,8 +519,9 @@ FGBallonet::FGBallonet(FGFDMExec* exec, Element* el, unsigned int num, if (element) { vXYZ = element->FindElementTripletConvertTo("IN"); } else { - cerr << "Fatal Error: No location found for this ballonet." << endl; - exit(-1); + const string s("Fatal Error: No location found for this ballonet."); + cerr << el->ReadFrom() << endl << s << endl; + throw BaseException(s); } if ((el->FindElement("x_radius") || el->FindElement("x_width")) && (el->FindElement("y_radius") || el->FindElement("y_width")) && @@ -557,7 +560,7 @@ FGBallonet::FGBallonet(FGFDMExec* exec, Element* el, unsigned int num, MaxVolume = M_PI * Yradius * Zradius * Xwidth; } else { cerr << "Warning: Unsupported ballonet shape." << endl; - MaxVolume = + MaxVolume = (4.0 * M_PI * Xradius * Yradius * Zradius / 3.0 + M_PI * Yradius * Zradius * Xwidth + M_PI * Xradius * Zradius * Ywidth + @@ -568,8 +571,9 @@ FGBallonet::FGBallonet(FGFDMExec* exec, Element* el, unsigned int num, Xwidth * Ywidth * Zwidth); } } else { - cerr << "Fatal Error: Ballonet shape must be given." << endl; - exit(-1); + const string s("Fatal Error: Ballonet shape must be given."); + cerr << el->ReadFrom() << endl << s << endl; + throw BaseException(s); } if (el->FindElement("max_overpressure")) { MaxOverpressure = el->FindElementValueAsNumberConvertTo("max_overpressure", @@ -577,12 +581,12 @@ FGBallonet::FGBallonet(FGFDMExec* exec, Element* el, unsigned int num, } if (el->FindElement("fullness")) { const double Fullness = el->FindElementValueAsNumber("fullness"); - if (0 <= Fullness) { - Volume = Fullness * MaxVolume; + if (0 <= Fullness) { + Volume = Fullness * MaxVolume; } else { cerr << "Warning: Invalid initial ballonet fullness value." << endl; } - } + } if (el->FindElement("valve_coefficient")) { ValveCoefficient = el->FindElementValueAsNumberConvertTo("valve_coefficient", @@ -600,7 +604,7 @@ FGBallonet::FGBallonet(FGFDMExec* exec, Element* el, unsigned int num, if (Volume != 0.0) { // Calculate initial air content. Contents = Pressure * Volume / (R * Temperature); - + // Clip to max allowed value. const double IdealPressure = Contents * R * Temperature / MaxVolume; if (IdealPressure > Pressure + MaxOverpressure) { @@ -746,7 +750,7 @@ void FGBallonet::Calculate(double dt) // Ellipsoid volume. Ixx = (1.0 / 5.0) * mass * (Yradius*Yradius + Zradius*Zradius); Iyy = (1.0 / 5.0) * mass * (Xradius*Xradius + Zradius*Zradius); - Izz = (1.0 / 5.0) * mass * (Xradius*Xradius + Yradius*Yradius); + Izz = (1.0 / 5.0) * mass * (Xradius*Xradius + Yradius*Yradius); } else if ((Xradius == 0.0) && (Yradius != 0.0) && (Zradius != 0.0) && (Xwidth != 0.0) && (Ywidth == 0.0) && (Zwidth == 0.0)) { // Cylindrical volume (might not be valid with an elliptical cross-section). @@ -798,9 +802,9 @@ void FGBallonet::Debug(int from) cout << " Location (X, Y, Z) (in.): " << vXYZ(eX) << ", " << vXYZ(eY) << ", " << vXYZ(eZ) << endl; cout << " Maximum volume: " << MaxVolume << " ft3" << endl; - cout << " Relief valve release pressure: " << MaxOverpressure << + cout << " Relief valve release pressure: " << MaxOverpressure << " lbs/ft2" << endl; - cout << " Relief valve coefficient: " << ValveCoefficient << + cout << " Relief valve coefficient: " << ValveCoefficient << " ft4*sec/slug" << endl; cout << " Initial temperature: " << Temperature << " Rankine" << endl; @@ -818,7 +822,7 @@ void FGBallonet::Debug(int from) } if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects } - if (debug_lvl & 8 ) { // Runtime state variables + if (debug_lvl & 8 ) { // Runtime state variables cout << " Ballonet holds " << Contents << " mol air" << endl; cout << " Temperature: " << Temperature << " Rankine" << endl; diff --git a/src/FDM/JSBSim/models/FGInput.cpp b/src/FDM/JSBSim/models/FGInput.cpp index da5b8cd9a..1fe66c76e 100644 --- a/src/FDM/JSBSim/models/FGInput.cpp +++ b/src/FDM/JSBSim/models/FGInput.cpp @@ -43,7 +43,7 @@ INCLUDES #include "input_output/FGUDPInputSocket.h" #include "input_output/FGXMLFileRead.h" #include "input_output/FGModelLoader.h" - + using namespace std; namespace JSBSim { @@ -84,7 +84,7 @@ bool FGInput::Load(Element* el) Element* element = ModelLoader.Open(el); if (!element) return false; - + FGModel::PreLoad(element, FDMExec); size_t idx = InputTypes.size(); @@ -152,6 +152,11 @@ bool FGInput::SetDirectivesFile(const SGPath& fname) { FGXMLFileRead XMLFile; Element* document = XMLFile.LoadXMLDocument(fname); + if (!document) { + stringstream s; + s << "Could not read directive file: " << fname; + throw BaseException(s.str()); + } bool result = Load(document); if (!result) diff --git a/src/FDM/JSBSim/models/FGLGear.cpp b/src/FDM/JSBSim/models/FGLGear.cpp index 4d8d0f0ed..049b246a6 100644 --- a/src/FDM/JSBSim/models/FGLGear.cpp +++ b/src/FDM/JSBSim/models/FGLGear.cpp @@ -180,7 +180,12 @@ FGLGear::FGLGear(Element* el, FGFDMExec* fdmex, int number, const struct Inputs& Element* element = el->FindElement("location"); if (element) vXYZn = element->FindElementTripletConvertTo("IN"); - else {cerr << "No location given for contact " << name << endl; exit(-1);} + else { + stringstream s; + s << "No location given for contact " << name; + cerr << endl << s.str() << endl; + throw BaseException(s.str()); + } SetTransformType(FGForce::tCustom); element = el->FindElement("orientation"); diff --git a/src/FDM/JSBSim/models/FGMassBalance.cpp b/src/FDM/JSBSim/models/FGMassBalance.cpp index bf58c3d27..b65a8e85b 100644 --- a/src/FDM/JSBSim/models/FGMassBalance.cpp +++ b/src/FDM/JSBSim/models/FGMassBalance.cpp @@ -117,7 +117,7 @@ static FGMatrix33 ReadInertiaMatrix(Element* document) // Transform the inertia products from the structural frame to the body frame // and create the inertia matrix. - if (document->GetAttributeValue("negated_crossproduct_inertia") == string("false")) + if (document->GetAttributeValue("negated_crossproduct_inertia") == string("false")) return FGMatrix33( bixx, bixy, -bixz, bixy, biyy, biyz, -bixz, biyz, bizz ); @@ -268,9 +268,11 @@ void FGMassBalance::AddPointMass(Element* el) Element* loc_element = el->FindElement("location"); string pointmass_name = el->GetAttributeValue("name"); if (!loc_element) { - cerr << el->ReadFrom() << "Pointmass " << pointmass_name - << " has no location." << endl; - exit(-1); + stringstream s; + s << el->ReadFrom() << "Pointmass " << pointmass_name + << " has no location."; + cerr << endl << s.str() << endl; + throw BaseException(s.str()); } double w = el->FindElementValueAsNumberConvertTo("weight", "LBS"); @@ -449,11 +451,11 @@ void FGMassBalance::PointMass::bind(FGPropertyManager* PropertyManager, void FGMassBalance::GetMassPropertiesReport(int i) { - cout << endl << fgblue << highint + cout << endl << fgblue << highint << " Mass Properties Report (English units: lbf, in, slug-ft^2)" << reset << endl; cout << " " << underon << " Weight CG-X CG-Y" - << " CG-Z Ixx Iyy Izz" + << " CG-Z Ixx Iyy Izz" << " Ixy Ixz Iyz" << underoff << endl; cout.precision(1); cout << highint << setw(34) << left << " Base Vehicle " << normint @@ -469,13 +471,13 @@ void FGMassBalance::GetMassPropertiesReport(int i) << right << setw(10) << pmweight << setw(8) << pm->GetLocation()(eX) << setw(8) << pm->GetLocation()(eY) << setw(8) << pm->GetLocation()(eZ) << setw(12) << pm->GetPointMassMoI(1,1) << setw(12) << pm->GetPointMassMoI(2,2) << setw(12) << pm->GetPointMassMoI(3,3) - << setw(12) << pm->GetPointMassMoI(1,2) << setw(12) << pm->GetPointMassMoI(1,3) << setw(12) << pm->GetPointMassMoI(2,3) << endl; + << setw(12) << pm->GetPointMassMoI(1,2) << setw(12) << pm->GetPointMassMoI(1,3) << setw(12) << pm->GetPointMassMoI(2,3) << endl; } cout << FDMExec->GetPropulsionTankReport(); cout << " " << underon << setw(136) << " " << underoff << endl; - cout << highint << left << setw(30) << " Total: " << right << setw(14) << Weight + cout << highint << left << setw(30) << " Total: " << right << setw(14) << Weight << setw(8) << vXYZcg(eX) << setw(8) << vXYZcg(eY) << setw(8) << vXYZcg(eZ) diff --git a/src/FDM/JSBSim/models/FGOutput.cpp b/src/FDM/JSBSim/models/FGOutput.cpp index 23147f31a..f98abb5a6 100644 --- a/src/FDM/JSBSim/models/FGOutput.cpp +++ b/src/FDM/JSBSim/models/FGOutput.cpp @@ -173,8 +173,13 @@ bool FGOutput::SetDirectivesFile(const SGPath& fname) { FGXMLFileRead XMLFile; Element* document = XMLFile.LoadXMLDocument(fname); - bool result = Load(document); + if (!document) { + stringstream s; + s << "Could not read directive file: " << fname; + throw BaseException(s.str()); + } + bool result = Load(document); if (!result) cerr << endl << "Aircraft output element has problems in file " << fname << endl; diff --git a/src/FDM/JSBSim/models/FGPropagate.cpp b/src/FDM/JSBSim/models/FGPropagate.cpp index 3b55ea515..5dc0f127b 100644 --- a/src/FDM/JSBSim/models/FGPropagate.cpp +++ b/src/FDM/JSBSim/models/FGPropagate.cpp @@ -688,7 +688,7 @@ void FGPropagate::WriteStateFile(int num) if (num == 0) return; - SGPath path = FDMExec->GetFullAircraftPath(); + SGPath path = FDMExec->GetOutputPath(); if (path.isNull()) path = SGPath("initfile."); else path.append("initfile."); @@ -968,16 +968,22 @@ void FGPropagate::Debug(int from) if (debug_lvl & 16) { // Sanity checking if (from == 2) { // State sanity checking if (fabs(VState.vPQR.Magnitude()) > 1000.0) { - cerr << endl << "Vehicle rotation rate is excessive (>1000 rad/sec): " << VState.vPQR.Magnitude() << endl; - exit(-1); + stringstream s; + s << "Vehicle rotation rate is excessive (>1000 rad/sec): " << VState.vPQR.Magnitude(); + cerr << endl << s.str() << endl; + throw BaseException(s.str()); } if (fabs(VState.vUVW.Magnitude()) > 1.0e10) { - cerr << endl << "Vehicle velocity is excessive (>1e10 ft/sec): " << VState.vUVW.Magnitude() << endl; - exit(-1); + stringstream s; + s << "Vehicle velocity is excessive (>1e10 ft/sec): " << VState.vUVW.Magnitude(); + cerr << endl << s.str() << endl; + throw BaseException(s.str()); } if (fabs(GetDistanceAGL()) > 1e10) { - cerr << endl << "Vehicle altitude is excessive (>1e10 ft): " << GetDistanceAGL() << endl; - exit(-1); + stringstream s; + s << "Vehicle altitude is excessive (>1e10 ft): " << GetDistanceAGL(); + cerr << endl << s.str() << endl; + throw BaseException(s.str()); } } } diff --git a/src/FDM/JSBSim/models/flight_control/FGKinemat.cpp b/src/FDM/JSBSim/models/flight_control/FGKinemat.cpp index 67634d704..039860f65 100644 --- a/src/FDM/JSBSim/models/flight_control/FGKinemat.cpp +++ b/src/FDM/JSBSim/models/flight_control/FGKinemat.cpp @@ -52,34 +52,29 @@ CLASS IMPLEMENTATION FGKinemat::FGKinemat(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element) { - Element *traverse_element, *setting_element; - double tmpDetent; - double tmpTime; - CheckInputNodes(1, 1, element); - Detents.clear(); - TransitionTimes.clear(); - Output = 0; DoScale = true; if (element->FindElement("noscale")) DoScale = false; - traverse_element = element->FindElement("traverse"); - setting_element = traverse_element->FindElement("setting"); + Element* traverse_element = element->FindElement("traverse"); + Element* setting_element = traverse_element->FindElement("setting"); while (setting_element) { - tmpDetent = setting_element->FindElementValueAsNumber("position"); - tmpTime = setting_element->FindElementValueAsNumber("time"); + double tmpDetent = setting_element->FindElementValueAsNumber("position"); + double tmpTime = setting_element->FindElementValueAsNumber("time"); Detents.push_back(tmpDetent); TransitionTimes.push_back(tmpTime); setting_element = traverse_element->FindNextElement("setting"); } if (Detents.size() <= 1) { - cerr << "Kinematic component " << Name - << " must have more than 1 setting element" << endl; - exit(-1); + stringstream s; + s << "Kinematic component " << Name + << " must have more than 1 setting element"; + cerr << element->ReadFrom() << endl << s.str() << endl; + throw BaseException(s.str()); } bind(element); diff --git a/src/FDM/JSBSim/models/flight_control/FGWaypoint.cpp b/src/FDM/JSBSim/models/flight_control/FGWaypoint.cpp index 9981918f2..c813c0a4e 100644 --- a/src/FDM/JSBSim/models/flight_control/FGWaypoint.cpp +++ b/src/FDM/JSBSim/models/flight_control/FGWaypoint.cpp @@ -182,7 +182,24 @@ bool FGWaypoint::Run(void ) double target_longitude_rad = target_longitude->GetValue() * target_longitude_unit; source.SetPosition(source_longitude_rad, source_latitude_rad, radius); + if (fabs(target_latitude_rad) > M_PI/2.0) { + cerr << endl; + cerr << "Target latitude in waypoint \"" << Name << "\" must be less than or equal to 90 degrees." << endl; + cerr << "(is longitude being mistakenly supplied?)" << endl; + cerr << endl; + throw("Waypoint target latitude exceeded 90 degrees."); + } + + if (fabs(source_latitude_rad) > M_PI/2.0) { + cerr << endl; + cerr << "Source latitude in waypoint \"" << Name << "\" must be less than or equal to 90 degrees." << endl; + cerr << "(is longitude being mistakenly supplied?)" << endl; + cerr << endl; + throw("Source latitude exceeded 90 degrees."); + } + if (WaypointType == eHeading) { // Calculate Heading + double heading_to_waypoint_rad = source.GetHeadingTo(target_longitude_rad, target_latitude_rad); @@ -190,11 +207,12 @@ bool FGWaypoint::Run(void ) else Output = heading_to_waypoint_rad; } else { // Calculate Distance + double wp_distance = source.GetDistanceTo(target_longitude_rad, target_latitude_rad); - if (eUnit == eMeters) Output = FeetToMeters(wp_distance); else Output = wp_distance; + } Clip(); diff --git a/src/FDM/JSBSim/models/propulsion/FGEngine.cpp b/src/FDM/JSBSim/models/propulsion/FGEngine.cpp index 0432b85fc..0241c2837 100644 --- a/src/FDM/JSBSim/models/propulsion/FGEngine.cpp +++ b/src/FDM/JSBSim/models/propulsion/FGEngine.cpp @@ -56,8 +56,6 @@ FGEngine::FGEngine(int engine_number, struct Inputs& input) : in(input), EngineNumber(engine_number) { Type = etUnknown; - X = Y = Z = 0.0; - EnginePitch = EngineYaw = 0.0; SLFuelFlowMax = 0.0; FuelExpended = 0.0; MaxThrottle = 1.0; @@ -113,18 +111,6 @@ unsigned int FGEngine::GetSourceTank(unsigned int i) const //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void FGEngine::SetPlacement(const FGColumnVector3& location, - const FGColumnVector3& orientation) -{ - X = location(eX); - Y = location(eY); - Z = location(eZ); - EnginePitch = orientation(ePitch); - EngineYaw = orientation (eYaw); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - double FGEngine::GetThrust(void) const { return Thruster->GetThrust(); @@ -200,19 +186,17 @@ bool FGEngine::Load(FGFDMExec *exec, Element *engine_element) // Call ModelFunctions loader FGModelFunctions::Load(engine_element, exec, to_string((int)EngineNumber)); -// Find and set engine location - + // If engine location and/or orientation is supplied issue a warning since they + // are ignored. What counts is the location and orientation of the thruster. local_element = parent_element->FindElement("location"); - if (local_element) location = local_element->FindElementTripletConvertTo("IN"); -// else cerr << "No engine location found for this engine." << endl; -// Jon: The engine location is not important - the nozzle location is. + if (local_element) + cerr << local_element->ReadFrom() + << "Engine location ignored, only thruster location is used." << endl; local_element = parent_element->FindElement("orient"); - if (local_element) orientation = local_element->FindElementTripletConvertTo("RAD"); -// else cerr << "No engine orientation found for this engine." << endl; -// Jon: The engine orientation has a default and is not normally used. - - SetPlacement(location, orientation); + if (local_element) + cerr << local_element->ReadFrom() + << "Engine orientation ignored, only thruster orientation is used." << endl; // Load thruster local_element = parent_element->FindElement("thruster"); diff --git a/src/FDM/JSBSim/models/propulsion/FGEngine.h b/src/FDM/JSBSim/models/propulsion/FGEngine.h index 26a011eb5..5edc751ce 100644 --- a/src/FDM/JSBSim/models/propulsion/FGEngine.h +++ b/src/FDM/JSBSim/models/propulsion/FGEngine.h @@ -71,17 +71,6 @@ CLASS DOCUMENTATION <h3>Configuration File Format:</h3> @code <engine file="{string}"> - <location unit="{IN | M}"> - <x> {number} </x> - <y> {number} </y> - <z> {number} </z> - </location> - <!-- optional orientation definition --> - <orient unit="{RAD | DEG}"> - <roll> {number} </roll> - <pitch> {number} </pitch> - <yaw> {number} </yaw> - </orient> <feed> {integer} </feed> ... optional more feed tank index numbers ... <thruster file="{string}"> @@ -183,9 +172,6 @@ public: virtual double GetThrust(void) const; - /// Sets engine placement information - virtual void SetPlacement(const FGColumnVector3& location, const FGColumnVector3& orientation); - /** The fuel need is calculated based on power levels and flow rate for that power level. It is also turned from a rate into an actual amount (pounds) by multiplying it by the delta T and the rate. @@ -216,9 +202,6 @@ protected: std::string Name; const int EngineNumber; EngineType Type; - double X, Y, Z; - double EnginePitch; - double EngineYaw; double SLFuelFlowMax; double MaxThrottle; double MinThrottle; diff --git a/src/FDM/JSBSim/models/propulsion/FGForce.cpp b/src/FDM/JSBSim/models/propulsion/FGForce.cpp index 9dba77b32..30350350b 100644 --- a/src/FDM/JSBSim/models/propulsion/FGForce.cpp +++ b/src/FDM/JSBSim/models/propulsion/FGForce.cpp @@ -106,8 +106,11 @@ const FGMatrix33& FGForce::Transform(void) const case tNone: return mT; default: - cout << "Unrecognized tranform requested from FGForce::Transform()" << endl; - exit(1); + { + const string s("Unrecognized tranform requested from FGForce::Transform()"); + cout << s << endl; + throw BaseException(s); + } } } diff --git a/src/FDM/JSBSim/models/propulsion/FGNozzle.cpp b/src/FDM/JSBSim/models/propulsion/FGNozzle.cpp index 11c546bd9..976533960 100644 --- a/src/FDM/JSBSim/models/propulsion/FGNozzle.cpp +++ b/src/FDM/JSBSim/models/propulsion/FGNozzle.cpp @@ -57,13 +57,14 @@ FGNozzle::FGNozzle(FGFDMExec* FDMExec, Element* nozzle_element, int num) if (nozzle_element->FindElement("area")) Area = nozzle_element->FindElementValueAsNumberConvertTo("area", "FT2"); else { - cerr << "Fatal Error: Nozzle exit area must be given in nozzle config file." << endl; - exit(-1); + const string s("Fatal Error: Nozzle exit area must be given in nozzle config file."); + cerr << s << endl; + throw BaseException(s); } Thrust = 0; Type = ttNozzle; - + Debug(0); } diff --git a/src/FDM/JSBSim/models/propulsion/FGTank.cpp b/src/FDM/JSBSim/models/propulsion/FGTank.cpp index 957e49226..30d09eaed 100644 --- a/src/FDM/JSBSim/models/propulsion/FGTank.cpp +++ b/src/FDM/JSBSim/models/propulsion/FGTank.cpp @@ -193,10 +193,9 @@ FGTank::FGTank(FGFDMExec* exec, Element* el, int tank_number) switch (grainType) { case gtCYLINDRICAL: if (Radius <= InnerRadius) { - cerr << element_Grain->ReadFrom() - << "The bore diameter should be smaller than the total grain diameter!" - << endl; - exit(-1); + const string s("The bore diameter should be smaller than the total grain diameter!"); + cerr << element_Grain->ReadFrom() << endl << s << endl; + throw BaseException(s); } Volume = M_PI * Length * (Radius*Radius - InnerRadius*InnerRadius); // cubic inches break; @@ -207,10 +206,11 @@ FGTank::FGTank(FGFDMExec* exec, Element* el, int tank_number) Volume = 1; // Volume is irrelevant for the FUNCTION type, but it can't be zero! break; case gtUNKNOWN: - cerr << el->ReadFrom() - << "Unknown grain type found in this rocket engine definition." - << endl; - exit(-1); + { + const string s("Unknown grain type found in this rocket engine definition."); + cerr << el->ReadFrom() << endl << s << endl; + throw BaseException(s); + } } Density = (Capacity*lbtoslug)/Volume; // slugs/in^3 } @@ -221,7 +221,7 @@ FGTank::FGTank(FGFDMExec* exec, Element* el, int tank_number) Area = 40.0 * pow(Capacity/1975, 0.666666667); // A named fuel type will override a previous density value - if (!strFuelName.empty()) Density = ProcessFuelName(strFuelName); + if (!strFuelName.empty()) Density = ProcessFuelName(strFuelName); bind(PropertyManager); @@ -375,8 +375,9 @@ void FGTank::CalculateInertias(void) } else if (Contents <= 0.0) { Volume = 0; } else { - cerr << endl << " Solid propellant grain density is zero!" << endl << endl; - exit(-1); + const string s(" Solid propellant grain density is zero!"); + cerr << endl << s << endl; + throw BaseException(s); } switch (grainType) { @@ -399,9 +400,11 @@ void FGTank::CalculateInertias(void) Izz = function_izz->GetValue()*izz_unit; break; default: - cerr << "Unknown grain type found." << endl; - exit(-1); - break; + { + const string s("Unknown grain type found."); + cerr << s << endl; + throw BaseException(s); + } } } else { // assume liquid propellant: shrinking snowball @@ -415,7 +418,7 @@ void FGTank::CalculateInertias(void) double FGTank::ProcessFuelName(const std::string& name) { - if (name == "AVGAS") return 6.02; + if (name == "AVGAS") return 6.02; else if (name == "JET-A") return 6.74; else if (name == "JET-A1") return 6.74; else if (name == "JET-B") return 6.48; @@ -442,7 +445,7 @@ double FGTank::ProcessFuelName(const std::string& name) else if (name == "AVCAT") return 6.81; else { cerr << "Unknown fuel type specified: "<< name << endl; - } + } return 6.6; }