From: bcoconni Date: Sat, 15 Nov 2014 10:39:49 +0000 (+0100) Subject: JSBSim sync X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=51e5add743dfb2f36674cec549684b62386d24e8;p=flightgear.git JSBSim sync --- diff --git a/src/FDM/JSBSim/CMakeLists.txt b/src/FDM/JSBSim/CMakeLists.txt index 550d1eca8..aaa91ec29 100644 --- a/src/FDM/JSBSim/CMakeLists.txt +++ b/src/FDM/JSBSim/CMakeLists.txt @@ -25,6 +25,7 @@ set(HEADERS input_output/FGOutputSocket.h input_output/FGOutputTextFile.h input_output/FGOutputType.h + input_output/FGModelLoader.h math/FGParameter.h math/LagrangeMultiplier.h math/FGColumnVector3.h @@ -119,6 +120,7 @@ set(SOURCES input_output/FGOutputSocket.cpp input_output/FGOutputTextFile.cpp input_output/FGOutputType.cpp + input_output/FGModelLoader.cpp math/FGColumnVector3.cpp math/FGCondition.cpp math/FGFunction.cpp diff --git a/src/FDM/JSBSim/FGFDMExec.cpp b/src/FDM/JSBSim/FGFDMExec.cpp index 6d07c01e6..b43cacba1 100644 --- a/src/FDM/JSBSim/FGFDMExec.cpp +++ b/src/FDM/JSBSim/FGFDMExec.cpp @@ -76,7 +76,7 @@ using namespace std; namespace JSBSim { -IDENT(IdSrc,"$Id: FGFDMExec.cpp,v 1.161 2014/05/17 15:35:53 jberndt Exp $"); +IDENT(IdSrc,"$Id: FGFDMExec.cpp,v 1.163 2014/09/04 10:17:20 bcoconni Exp $"); IDENT(IdHdr,ID_FDMEXEC); /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -879,22 +879,13 @@ bool FGFDMExec::LoadModel(const string& model, bool addModelToPath) } } - // Process the output element[s]. This element is OPTIONAL, and there may be more than one. + // Process the output element[s]. This element is OPTIONAL, and there may be + // more than one. element = document->FindElement("output"); while (element) { - string output_file_name = aircraftCfgFileName; - - if (!element->GetAttributeValue("file").empty()) { - output_file_name = RootDir + element->GetAttributeValue("file"); - result = ((FGOutput*)Models[eOutput])->SetDirectivesFile(output_file_name); - } - else - result = ((FGOutput*)Models[eOutput])->Load(element); + if (!static_cast(Models[eOutput])->Load(element)) + return false; - if (!result) { - cerr << endl << "Aircraft output element has problems in file " << output_file_name << endl; - return result; - } element = document->FindNextElement("output"); } @@ -1246,6 +1237,7 @@ void FGFDMExec::DoLinearization(int mode) void FGFDMExec::SRand(int sr) { + gaussian_random_number_phase = 0; srand(sr); } diff --git a/src/FDM/JSBSim/FGJSBBase.cpp b/src/FDM/JSBSim/FGJSBBase.cpp index b509fd1b8..71ce71d6a 100644 --- a/src/FDM/JSBSim/FGJSBBase.cpp +++ b/src/FDM/JSBSim/FGJSBBase.cpp @@ -44,7 +44,7 @@ INCLUDES namespace JSBSim { -IDENT(IdSrc,"$Id: FGJSBBase.cpp,v 1.38 2014/01/13 10:45:59 ehofman Exp $"); +IDENT(IdSrc,"$Id: FGJSBBase.cpp,v 1.39 2014/09/03 17:35:04 bcoconni Exp $"); IDENT(IdHdr,ID_JSBBASE); /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -112,6 +112,8 @@ std::queue FGJSBBase::Messages; FGJSBBase::Message FGJSBBase::localMsg; unsigned int FGJSBBase::messageId = 0; +int FGJSBBase::gaussian_random_number_phase = 0; + short FGJSBBase::debug_lvl = 1; using std::cerr; @@ -257,10 +259,9 @@ string FGJSBBase::CreateIndexedPropertyName(const string& Property, int index) double FGJSBBase::GaussianRandomNumber(void) { static double V1, V2, S; - static int phase = 0; double X; - if (phase == 0) { + if (gaussian_random_number_phase == 0) { V1 = V2 = S = X = 0.0; do { @@ -276,7 +277,7 @@ double FGJSBBase::GaussianRandomNumber(void) } else X = V2 * sqrt(-2 * log(S) / S); - phase = 1 - phase; + gaussian_random_number_phase = 1 - gaussian_random_number_phase; return X; } diff --git a/src/FDM/JSBSim/FGJSBBase.h b/src/FDM/JSBSim/FGJSBBase.h index 3dd78df9d..c0200d484 100644 --- a/src/FDM/JSBSim/FGJSBBase.h +++ b/src/FDM/JSBSim/FGJSBBase.h @@ -57,7 +57,7 @@ using std::max; DEFINITIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -#define ID_JSBBASE "$Id: FGJSBBase.h,v 1.39 2014/01/13 10:45:59 ehofman Exp $" +#define ID_JSBBASE "$Id: FGJSBBase.h,v 1.41 2014/09/03 17:35:04 bcoconni Exp $" /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FORWARD DECLARATIONS @@ -73,7 +73,7 @@ CLASS DOCUMENTATION * This class provides universal constants, utility functions, messaging * functions, and enumerated constants to JSBSim. @author Jon S. Berndt - @version $Id: FGJSBBase.h,v 1.39 2014/01/13 10:45:59 ehofman Exp $ + @version $Id: FGJSBBase.h,v 1.41 2014/09/03 17:35:04 bcoconni Exp $ */ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -329,6 +329,8 @@ public: static double sign(double num) {return num>=0.0?1.0:-1.0;} + static double GaussianRandomNumber(void); + protected: static Message localMsg; @@ -363,7 +365,7 @@ protected: static std::string CreateIndexedPropertyName(const std::string& Property, int index); - static double GaussianRandomNumber(void); + static int gaussian_random_number_phase; public: /// Moments L, M, N diff --git a/src/FDM/JSBSim/input_output/FGModelLoader.cpp b/src/FDM/JSBSim/input_output/FGModelLoader.cpp new file mode 100644 index 000000000..7c84dc7f9 --- /dev/null +++ b/src/FDM/JSBSim/input_output/FGModelLoader.cpp @@ -0,0 +1,110 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Module: FGModelLoader.cpp + Author: Bertrand Coconnier + Date started: 12/14/13 + Purpose: Read and manage XML data for models definition + + ------------- Copyright (C) 2013 Bertrand Coconnier ------------- + + This program is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by the Free Software + Foundation; either version 2 of the License, or (at your option) any later + version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + details. + + You should have received a copy of the GNU Lesser General Public License along with + this program; if not, write to the Free Software Foundation, Inc., 59 Temple + Place - Suite 330, Boston, MA 02111-1307, USA. + + Further information about the GNU Lesser General Public License can also be found on + the world wide web at http://www.gnu.org. + +FUNCTIONAL DESCRIPTION +-------------------------------------------------------------------------------- +This is the place where the XML data is loaded in memory for an access during +the models initialization. + +HISTORY +-------------------------------------------------------------------------------- +12/14/13 BC Created + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include "FGJSBBase.h" +#include "FGModelLoader.h" +#include "FGXMLFileRead.h" +#include "models/FGModel.h" + +using namespace std; + +namespace JSBSim { + +IDENT(IdSrc, "$Id: FGModelLoader.cpp,v 1.1 2014/06/09 11:52:06 bcoconni Exp $"); +IDENT(IdHdr, ID_MODELLOADER); + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS IMPLEMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +Element_ptr FGModelLoader::Open(Element *el) +{ + Element_ptr document = el; + string fname = el->GetAttributeValue("file"); + + if (!fname.empty()) { + FGXMLFileRead XMLFileRead; + string file; + + try { + file = model->FindFullPathName(fname); + } + catch(string& e) { + cerr << endl << el->ReadFrom() + << "Could not open file: " << e << endl; + return NULL; + } + + if (CachedFiles.find(file) != CachedFiles.end()) + document = CachedFiles[file]; + else { + document = XMLFileRead.LoadXMLDocument(file); + if (document == 0L) { + cerr << endl << el->ReadFrom() + << "Could not open file: " << file << endl; + return NULL; + } + CachedFiles[file] = document; + } + + if (document->GetName() != el->GetName()) { + document->SetParent(el); + el->AddChildElement(document); + } + } + + return document; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +string CheckFullPathName(const string& path, const string& fname) +{ + string name = path + "/" + fname; + + if (name.length() <=4 || name.substr(name.length()-4, 4) != ".xml") + name.append(".xml"); + + ifstream file(name.c_str()); + if (!file.is_open()) + return string(); + + return name; +} +} diff --git a/src/FDM/JSBSim/input_output/FGModelLoader.h b/src/FDM/JSBSim/input_output/FGModelLoader.h new file mode 100644 index 000000000..4c2b937c9 --- /dev/null +++ b/src/FDM/JSBSim/input_output/FGModelLoader.h @@ -0,0 +1,81 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Header: FGModelLoader.h + Author: Bertrand Coconnier + Date started: 12/14/13 + + ------------- Copyright (C) 2013 Bertrand Coconnier ------------- + + This program is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by the Free Software + Foundation; either version 2 of the License, or (at your option) any later + version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + details. + + You should have received a copy of the GNU Lesser General Public License along with + this program; if not, write to the Free Software Foundation, Inc., 59 Temple + Place - Suite 330, Boston, MA 02111-1307, USA. + + Further information about the GNU Lesser General Public License can also be found on + the world wide web at http://www.gnu.org. + +HISTORY +-------------------------------------------------------------------------------- +12/14/13 BC Created + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +SENTRY +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#ifndef FGMODELLOADER_H +#define FGMODELLOADER_H + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include + +#include "FGXMLElement.h" + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +DEFINITIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#define ID_MODELLOADER "$Id: FGModelLoader.h,v 1.1 2014/06/09 11:52:06 bcoconni Exp $" + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +FORWARD DECLARATIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +namespace JSBSim { + +class FGModel; + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DOCUMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DECLARATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +class FGModelLoader +{ +public: + FGModelLoader(const FGModel* _model) : model(_model) {} + Element_ptr Open(Element *el); + +private: + const FGModel* model; + std::map CachedFiles; +}; + + std::string CheckFullPathName(const std::string& path, const std::string& fname); +} +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +#endif diff --git a/src/FDM/JSBSim/input_output/FGOutputType.cpp b/src/FDM/JSBSim/input_output/FGOutputType.cpp index 09cbc62b6..362f50b4d 100644 --- a/src/FDM/JSBSim/input_output/FGOutputType.cpp +++ b/src/FDM/JSBSim/input_output/FGOutputType.cpp @@ -46,7 +46,7 @@ INCLUDES namespace JSBSim { -IDENT(IdSrc,"$Id: FGOutputType.cpp,v 1.10 2014/01/13 10:46:00 ehofman Exp $"); +IDENT(IdSrc,"$Id: FGOutputType.cpp,v 1.11 2014/09/12 20:10:04 bcoconni Exp $"); IDENT(IdHdr,ID_OUTPUTTYPE); using namespace std; @@ -100,9 +100,6 @@ void FGOutputType::SetIdx(int idx) bool FGOutputType::Load(Element* element) { - // Perform base class Load. - PreLoad(element, PropertyManager); - if (element->FindElementValue("simulation") == string("ON")) SubSystems += ssSimulation; if (element->FindElementValue("aerosurfaces") == string("ON")) @@ -158,9 +155,6 @@ bool FGOutputType::Load(Element* element) } SetRate(outRate); - // FIXME : PostLoad should be called in the most derived class ? - PostLoad(element, PropertyManager); - return true; } diff --git a/src/FDM/JSBSim/input_output/FGPropertyReader.cpp b/src/FDM/JSBSim/input_output/FGPropertyReader.cpp index b6c001a53..f2956cdba 100644 --- a/src/FDM/JSBSim/input_output/FGPropertyReader.cpp +++ b/src/FDM/JSBSim/input_output/FGPropertyReader.cpp @@ -45,18 +45,20 @@ using namespace std; namespace JSBSim { -IDENT(IdSrc,"$Id: FGPropertyReader.cpp,v 1.3 2014/01/13 10:46:00 ehofman Exp $"); +IDENT(IdSrc,"$Id: FGPropertyReader.cpp,v 1.5 2014/06/14 11:58:31 bcoconni Exp $"); IDENT(IdHdr,ID_PROPERTYREADER); /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS IMPLEMENTATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + bool FGPropertyReader::ResetToIC(void) { - map::iterator it = interface_prop_initial_value.begin(); + map::iterator it = interface_prop_initial_value.begin(); for (;it != interface_prop_initial_value.end(); ++it) { - FGPropertyNode* node = it->first; + SGPropertyNode* node = it->first; if (!node->getAttribute(SGPropertyNode::PRESERVE)) node->setDoubleValue(it->second); } @@ -66,8 +68,7 @@ bool FGPropertyReader::ResetToIC(void) //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void FGPropertyReader::LoadProperties(Element* el, FGPropertyManager* PM, - bool override) +void FGPropertyReader::Load(Element* el, FGPropertyManager* PM, bool override) { // Interface properties are all stored in the interface properties array. string interface_property_string = ""; @@ -83,7 +84,7 @@ void FGPropertyReader::LoadProperties(Element* el, FGPropertyManager* PM, } while (property_element) { - FGPropertyNode* node = 0; + SGPropertyNode* node = 0; double value=0.0; if ( ! property_element->GetAttributeValue("value").empty()) value = property_element->GetAttributeValueAsNumber("value"); @@ -115,12 +116,20 @@ void FGPropertyReader::LoadProperties(Element* el, FGPropertyManager* PM, continue; } } else { - interface_properties.push_back(value); - PM->Tie(interface_property_string, &interface_properties.back()); - if (FGJSBBase::debug_lvl > 0) - cout << " " << interface_property_string << " (initial value: " - << value << ")" << endl << endl; - node = PM->GetNode(interface_property_string); + node = PM->GetNode(interface_property_string, true); + if (node) { + node->setDoubleValue(value); + + if (FGJSBBase::debug_lvl > 0) + cout << " " << interface_property_string << " (initial value: " + << value << ")" << endl << endl; + } + else { + cerr << "Could not create property " << interface_property_string + << endl; + property_element = el->FindNextElement("property"); + continue; + } } interface_prop_initial_value[node] = value; if (property_element->GetAttributeValue("persistent") == string("true")) diff --git a/src/FDM/JSBSim/input_output/FGPropertyReader.h b/src/FDM/JSBSim/input_output/FGPropertyReader.h index c50b363f2..d8539b438 100644 --- a/src/FDM/JSBSim/input_output/FGPropertyReader.h +++ b/src/FDM/JSBSim/input_output/FGPropertyReader.h @@ -38,16 +38,17 @@ SENTRY INCLUDES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -#include +#include #include -#include "simgear/structure/SGSharedPtr.hxx" +#include "simgear/props/props.hxx" +#include "input_output/FGPropertyManager.h" /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% DEFINITIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -#define ID_PROPERTYREADER "$Id: FGPropertyReader.h,v 1.1 2014/01/02 22:37:47 bcoconni Exp $" +#define ID_PROPERTYREADER "$Id: FGPropertyReader.h,v 1.3 2014/06/14 11:58:31 bcoconni Exp $" /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FORWARD DECLARATIONS @@ -56,8 +57,6 @@ FORWARD DECLARATIONS namespace JSBSim { class Element; -class FGPropertyManager; -class FGPropertyNode; /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS DOCUMENTATION @@ -70,12 +69,32 @@ CLASS DECLARATION class FGPropertyReader { public: - void LoadProperties(Element* el, FGPropertyManager* PropertyManager, bool override); + FGPropertyReader() {}; // Needed because the copy constructor is private + void Load(Element* el, FGPropertyManager* PropertyManager, bool override); bool ResetToIC(void); -protected: - std::list interface_properties; - std::map, double> interface_prop_initial_value; + class const_iterator + { + public: + const_iterator(void) {} + const_iterator(const std::map::const_iterator &it) : prop_it(it) {} + const_iterator& operator++() { ++prop_it; return *this; } + bool operator!=(const const_iterator& it) const { return prop_it != it.prop_it; } + FGPropertyNode* operator*() { + SGPropertyNode* node = prop_it->first; + return static_cast(node); + } + + private: + std::map::const_iterator prop_it; + }; + + const_iterator begin(void) const { return const_iterator(interface_prop_initial_value.begin()); } + const_iterator end(void) const { return const_iterator(interface_prop_initial_value.end()); } + bool empty(void) const { return interface_prop_initial_value.empty(); } + +private: + std::map interface_prop_initial_value; }; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/FDM/JSBSim/input_output/FGScript.cpp b/src/FDM/JSBSim/input_output/FGScript.cpp index 5a259ba14..12185869c 100644 --- a/src/FDM/JSBSim/input_output/FGScript.cpp +++ b/src/FDM/JSBSim/input_output/FGScript.cpp @@ -46,16 +46,19 @@ INCLUDES #include #include "FGScript.h" +#include "FGFDMExec.h" #include "input_output/FGXMLElement.h" #include "input_output/FGXMLFileRead.h" -#include "initialization/FGTrim.h" +#include "initialization/FGInitialCondition.h" #include "models/FGInput.h" +#include "math/FGCondition.h" +#include "math/FGFunction.h" using namespace std; namespace JSBSim { -IDENT(IdSrc,"$Id: FGScript.cpp,v 1.57 2014/05/17 15:33:08 jberndt Exp $"); +IDENT(IdSrc,"$Id: FGScript.cpp,v 1.60 2014/06/08 12:50:05 bcoconni Exp $"); IDENT(IdHdr,ID_FGSCRIPT); /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -173,11 +176,11 @@ bool FGScript::LoadScript(string script, double deltaT, const string initfile) return false; } - initialize = element->GetAttributeValue("initialize"); if (initfile.empty()) { - if (initialize.empty()) { - cerr << "Initialization file must be specified in use element." << endl; - return false; + initialize = element->GetAttributeValue("initialize"); + if (initialize.empty()) { + cerr << "Initialization file must be specified in use element." << endl; + return false; } } else { cout << endl << "The initialization file specified in the script file (" << initialize @@ -190,6 +193,12 @@ bool FGScript::LoadScript(string script, double deltaT, const string initfile) return false; } + FGInitialCondition *IC=FDMExec->GetIC(); + if ( ! IC->Load( initialize )) { + cerr << "Initialization unsuccessful" << endl; + exit(-1); + } + // Now, read input spec if given. if (input_element > 0) { FDMExec->GetInput()->Load(input_element); @@ -208,7 +217,7 @@ bool FGScript::LoadScript(string script, double deltaT, const string initfile) // Read local property/value declarations int saved_debug_lvl = debug_lvl; debug_lvl = 0; // Disable messages - LoadProperties(run_element, PropertyManager, true); + LocalProperties.Load(run_element, PropertyManager, true); debug_lvl = saved_debug_lvl; // Read "events" from script @@ -337,12 +346,6 @@ bool FGScript::LoadScript(string script, double deltaT, const string initfile) Debug(4); - FGInitialCondition *IC=FDMExec->GetIC(); - if ( ! IC->Load( initialize )) { - cerr << "Initialization unsuccessful" << endl; - exit(-1); - } - return true; } @@ -350,7 +353,7 @@ bool FGScript::LoadScript(string script, double deltaT, const string initfile) void FGScript::ResetEvents(void) { - //ResetToIC(); + //LocalProperties.ResetToIC(); for (unsigned int i=0; iGetDeltaT()) << " Hz)" << endl; cout << endl; - map::iterator it = interface_prop_initial_value.begin(); - for (; it != interface_prop_initial_value.end(); ++it) { - FGPropertyNode* node = it->first; + FGPropertyReader::const_iterator it; + for (it = LocalProperties.begin(); it != LocalProperties.end(); ++it) { + FGPropertyNode* node = *it; cout << "Local property: " << node->GetName() << " = " << node->getDoubleValue() << endl; } - if (!interface_prop_initial_value.empty()) cout << endl; + if (LocalProperties.empty()) cout << endl; for (unsigned i=0; i #include -#include "FGFDMExec.h" #include "FGJSBBase.h" -#include "math/FGFunction.h" -#include "math/FGCondition.h" #include "FGPropertyReader.h" +#include "input_output/FGPropertyManager.h" /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% DEFINITIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -#define ID_FGSCRIPT "$Id: FGScript.h,v 1.28 2014/01/02 22:37:47 bcoconni Exp $" +#define ID_FGSCRIPT "$Id: FGScript.h,v 1.29 2014/05/29 18:46:44 bcoconni Exp $" /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FORWARD DECLARATIONS @@ -58,6 +56,10 @@ FORWARD DECLARATIONS namespace JSBSim { +class FGFDMExec; +class FGCondition; +class FGFunction; + /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS DOCUMENTATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ @@ -159,14 +161,14 @@ CLASS DOCUMENTATION comes the "run" section, where the conditions are described in "event" clauses.

@author Jon S. Berndt - @version "$Id: FGScript.h,v 1.28 2014/01/02 22:37:47 bcoconni Exp $" + @version "$Id: FGScript.h,v 1.29 2014/05/29 18:46:44 bcoconni Exp $" */ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS DECLARATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -class FGScript : public FGPropertyReader, public FGJSBBase +class FGScript : public FGJSBBase { public: /// Default constructor @@ -258,6 +260,8 @@ private: double EndTime; std::vector Events; + FGPropertyReader LocalProperties; + FGFDMExec* FDMExec; FGPropertyManager* PropertyManager; void Debug(int from); diff --git a/src/FDM/JSBSim/input_output/FGXMLElement.cpp b/src/FDM/JSBSim/input_output/FGXMLElement.cpp index bae0bf1b0..dd9bce1cc 100644 --- a/src/FDM/JSBSim/input_output/FGXMLElement.cpp +++ b/src/FDM/JSBSim/input_output/FGXMLElement.cpp @@ -35,6 +35,7 @@ INCLUDES #include "FGXMLElement.h" #include "string_utilities.h" +#include "FGJSBBase.h" using namespace std; @@ -44,7 +45,7 @@ FORWARD DECLARATIONS namespace JSBSim { -IDENT(IdSrc,"$Id: FGXMLElement.cpp,v 1.48 2014/05/17 15:31:17 jberndt Exp $"); +IDENT(IdSrc,"$Id: FGXMLElement.cpp,v 1.52 2014/06/29 10:13:18 bcoconni Exp $"); IDENT(IdHdr,ID_XMLELEMENT); bool Element::converterIsInitialized = false; @@ -242,9 +243,8 @@ Element::Element(const string& nm) Element::~Element(void) { - for (unsigned int i=0; iSetParent(0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -257,11 +257,13 @@ string Element::GetAttributeValue(const string& attr) //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -bool Element::HasAttribute(const string& attr) +bool Element::SetAttributeValue(const std::string& key, const std::string& value) { - map::iterator found = attributes.find(attr); + bool ret = HasAttribute(key); + if (ret) + attributes[key] = value; - return found != attributes.end(); + return ret; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -588,7 +590,7 @@ double Element::DisperseValue(Element *e, double val, const std::string supplied if (!supplied_units.empty()) disp *= convert[supplied_units][target_units]; string attType = e->GetAttributeValue("type"); if (attType == "gaussian" || attType == "gaussiansigned") { - double grn = GaussianRandomNumber(); + double grn = FGJSBBase::GaussianRandomNumber(); if (attType == "gaussian") { value = val + disp*grn; } else { // Assume gaussiansigned @@ -612,35 +614,6 @@ double Element::DisperseValue(Element *e, double val, const std::string supplied //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -double Element::GaussianRandomNumber(void) -{ - static double V1, V2, S; - static int phase = 0; - double X; - - if (phase == 0) { - V1 = V2 = S = X = 0.0; - - do { - double U1 = (double)rand() / RAND_MAX; - double U2 = (double)rand() / RAND_MAX; - - V1 = 2 * U1 - 1; - V2 = 2 * U2 - 1; - S = V1 * V1 + V2 * V2; - } while(S >= 1 || S == 0); - - X = V1 * sqrt(-2 * log(S) / S); - } else - X = V2 * sqrt(-2 * log(S) / S); - - phase = 1 - phase; - - return X; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - void Element::Print(unsigned int level) { unsigned int i, spaces; @@ -694,4 +667,23 @@ string Element::ReadFrom(void) const return message.str(); } +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void Element::MergeAttributes(Element* el) +{ + map::iterator it; + + for (it=el->attributes.begin(); it != el->attributes.end(); ++it) { + if (attributes.find(it->first) == attributes.end()) + attributes[it->first] = it->second; + else { + if (FGJSBBase::debug_lvl > 0) + cout << el->ReadFrom() << " Attribute '" << it->first << "' is overridden in file " + << GetFileName() << ": line " << GetLineNumber() << endl + << " The value '" << attributes[it->first] << "' will be used instead of '" + << it->second << "'." << endl; + } + } +} + } // end namespace JSBSim diff --git a/src/FDM/JSBSim/input_output/FGXMLElement.h b/src/FDM/JSBSim/input_output/FGXMLElement.h index 9224b1eb8..22c1f39a8 100644 --- a/src/FDM/JSBSim/input_output/FGXMLElement.h +++ b/src/FDM/JSBSim/input_output/FGXMLElement.h @@ -38,14 +38,14 @@ INCLUDES #include #include -#include "FGJSBBase.h" +#include "simgear/structure/SGSharedPtr.hxx" #include "math/FGColumnVector3.h" /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% DEFINITIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -#define ID_XMLELEMENT "$Id: FGXMLElement.h,v 1.20 2014/01/13 10:46:02 ehofman Exp $" +#define ID_XMLELEMENT "$Id: FGXMLElement.h,v 1.24 2014/06/29 10:13:18 bcoconni Exp $" /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FORWARD DECLARATIONS @@ -137,14 +137,17 @@ CLASS DOCUMENTATION - GAL = gallon (U.S. liquid) @author Jon S. Berndt - @version $Id: FGXMLElement.h,v 1.20 2014/01/13 10:46:02 ehofman Exp $ + @version $Id: FGXMLElement.h,v 1.24 2014/06/29 10:13:18 bcoconni Exp $ */ +class Element; +typedef SGSharedPtr Element_ptr; + /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS DECLARATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -class Element { +class Element : public SGReferenced { public: /** Constructor @param nm the name of this element (if given) @@ -156,7 +159,7 @@ public: /** Determines if an element has the supplied attribute. @param key specifies the attribute key to retrieve the value of. @return true or false. */ - bool HasAttribute(const std::string& key); + bool HasAttribute(const std::string& key) {return attributes.find(key) != attributes.end();} /** Retrieves an attribute. @param key specifies the attribute key to retrieve the value of. @@ -164,6 +167,14 @@ public: attribute exists. */ std::string GetAttributeValue(const std::string& key); + /** Modifies an attribute. + @param key specifies the attribute key to modify the value of. + @param value new key value (as a string). + @return false if it did not find any attribute with the requested key, + true otherwise. + */ + bool SetAttributeValue(const std::string& key, const std::string& value); + /** Retrieves an attribute value as a double precision real number. @param key specifies the attribute key to retrieve the value of. @return the key value (as a number), or the HUGE_VAL if no such @@ -359,11 +370,20 @@ public: */ std::string ReadFrom(void) const; + /** Merges the attributes of the current element with another element. The + * attributes from the current element override the element that is passed + * as a parameter. In other words if the two elements have an attribute with + * the same name, the attribute from the current element is kept and the + * corresponding attribute of the other element is ignored. + * @param el element with which the current element will merge its attributes. + */ + void MergeAttributes(Element* el); + private: std::string name; std::map attributes; std::vector data_lines; - std::vector children; + std::vector children; Element *parent; unsigned int element_index; std::string file_name; @@ -371,7 +391,6 @@ private: typedef std::map > tMapConvert; static tMapConvert convert; static bool converterIsInitialized; - double GaussianRandomNumber(void); }; } // namespace JSBSim diff --git a/src/FDM/JSBSim/input_output/FGXMLParse.cpp b/src/FDM/JSBSim/input_output/FGXMLParse.cpp index e6b4c87c0..00b30457f 100644 --- a/src/FDM/JSBSim/input_output/FGXMLParse.cpp +++ b/src/FDM/JSBSim/input_output/FGXMLParse.cpp @@ -29,26 +29,26 @@ INCLUDES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -#include "FGXMLParse.h" -#include "FGXMLElement.h" #include #include #include + +#include "FGJSBBase.h" +#include "FGXMLParse.h" +#include "FGXMLElement.h" #include "input_output/string_utilities.h" using namespace std; namespace JSBSim { -IDENT(IdSrc,"$Id: FGXMLParse.cpp,v 1.14 2014/01/13 10:46:03 ehofman Exp $"); +IDENT(IdSrc,"$Id: FGXMLParse.cpp,v 1.16 2014/06/09 11:52:06 bcoconni Exp $"); IDENT(IdHdr,ID_XMLPARSE); /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS IMPLEMENTATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -#include "FGXMLParse.h" - using namespace std; FGXMLParse::FGXMLParse(void) @@ -59,13 +59,6 @@ FGXMLParse::FGXMLParse(void) //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -FGXMLParse::~FGXMLParse(void) -{ - delete document; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - void FGXMLParse::startXML(void) { } @@ -74,7 +67,6 @@ void FGXMLParse::startXML(void) void FGXMLParse::reset(void) { - delete document; first_element_read = false; current_element = document = 0L; } diff --git a/src/FDM/JSBSim/input_output/FGXMLParse.h b/src/FDM/JSBSim/input_output/FGXMLParse.h index 6367dbb93..68f61b7a0 100644 --- a/src/FDM/JSBSim/input_output/FGXMLParse.h +++ b/src/FDM/JSBSim/input_output/FGXMLParse.h @@ -35,12 +35,13 @@ INCLUDES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #include "simgear/xml/easyxml.hxx" +#include "input_output/FGXMLElement.h" /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% DEFINITIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -#define ID_XMLPARSE "$Id: FGXMLParse.h,v 1.7 2009/10/24 22:59:30 jberndt Exp $" +#define ID_XMLPARSE "$Id: FGXMLParse.h,v 1.9 2014/06/09 11:52:06 bcoconni Exp $" #define VALID_CHARS """`!@#$%^&*()_+`1234567890-={}[];':,.<>/?abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -57,7 +58,7 @@ CLASS DOCUMENTATION /** Encapsulates an XML parser based on the EasyXML parser from the SimGear library. @author Jon S. Berndt - @version $Id: FGXMLParse.h,v 1.7 2009/10/24 22:59:30 jberndt Exp $ + @version $Id: FGXMLParse.h,v 1.9 2014/06/09 11:52:06 bcoconni Exp $ */ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -68,7 +69,6 @@ class FGXMLParse : public XMLVisitor { public: FGXMLParse(void); - virtual ~FGXMLParse(void); Element* GetDocument(void) {return document;} @@ -84,7 +84,7 @@ public: private: bool first_element_read; mutable std::string working_string; - Element *document; + Element_ptr document; Element *current_element; }; diff --git a/src/FDM/JSBSim/math/FGLocation.cpp b/src/FDM/JSBSim/math/FGLocation.cpp index da4183944..2094ecd60 100644 --- a/src/FDM/JSBSim/math/FGLocation.cpp +++ b/src/FDM/JSBSim/math/FGLocation.cpp @@ -47,10 +47,8 @@ INCLUDES namespace JSBSim { -IDENT(IdSrc,"$Id: FGLocation.cpp,v 1.32 2014/01/13 10:46:03 ehofman Exp $"); +IDENT(IdSrc,"$Id: FGLocation.cpp,v 1.33 2014/08/28 11:46:11 bcoconni Exp $"); IDENT(IdHdr,ID_LOCATION); -using std::cerr; -using std::endl; // Set up the default ground callback object. FGGroundCallback_ptr FGLocation::GroundCallback = NULL; @@ -62,13 +60,12 @@ CLASS IMPLEMENTATION FGLocation::FGLocation(void) : mECLoc(1.0, 0.0, 0.0), mCacheValid(false) { - a = b = a2 = b2 = 0.0; - e = e2 = f = 1.0; - eps2 = -1.0; + e2 = c = 0.0; + a = ec = ec2 = 1.0; epa = 0.0; mLon = mLat = mRadius = 0.0; - mGeodLat = GeodeticAltitude = initial_longitude = 0.0; + mGeodLat = GeodeticAltitude = 0.0; mTl2ec.InitMatrix(); mTec2l.InitMatrix(); @@ -83,13 +80,12 @@ FGLocation::FGLocation(void) FGLocation::FGLocation(double lon, double lat, double radius) : mCacheValid(false) { - a = b = a2 = b2 = 0.0; - e = e2 = f = 1.0; - eps2 = -1.0; + e2 = c = 0.0; + a = ec = ec2 = 1.0; epa = 0.0; mLon = mLat = mRadius = 0.0; - mGeodLat = GeodeticAltitude = initial_longitude = 0.0; + mGeodLat = GeodeticAltitude = 0.0; mTl2ec.InitMatrix(); mTec2l.InitMatrix(); @@ -112,13 +108,12 @@ FGLocation::FGLocation(double lon, double lat, double radius) FGLocation::FGLocation(const FGColumnVector3& lv) : mECLoc(lv), mCacheValid(false) { - a = b = a2 = b2 = 0.0; - e = e2 = f = 1.0; - eps2 = -1.0; + e2 = c = 0.0; + a = ec = ec2 = 1.0; epa = 0.0; mLon = mLat = mRadius = 0.0; - mGeodLat = GeodeticAltitude = initial_longitude = 0.0; + mGeodLat = GeodeticAltitude = 0.0; mTl2ec.InitMatrix(); mTec2l.InitMatrix(); @@ -134,13 +129,10 @@ FGLocation::FGLocation(const FGLocation& l) : mECLoc(l.mECLoc), mCacheValid(l.mCacheValid) { a = l.a; - b = l.b; - a2 = l.a2; - b2 = l.b2; e2 = l.e2; - e = l.e; - eps2 = l.eps2; - f = l.f; + c = l.c; + ec = l.ec; + ec2 = l.ec2; epa = l.epa; /*ag @@ -162,7 +154,6 @@ FGLocation::FGLocation(const FGLocation& l) mTi2l = l.mTi2l; mTl2i = l.mTl2i; - initial_longitude = l.initial_longitude; mGeodLat = l.mGeodLat; GeodeticAltitude = l.GeodeticAltitude; } @@ -175,13 +166,10 @@ const FGLocation& FGLocation::operator=(const FGLocation& l) mCacheValid = l.mCacheValid; a = l.a; - b = l.b; - a2 = l.a2; - b2 = l.b2; e2 = l.e2; - e = l.e; - eps2 = l.eps2; - f = l.f; + c = l.c; + ec = l.ec; + ec2 = l.ec2; epa = l.epa; //ag See comment in constructor above @@ -198,7 +186,6 @@ const FGLocation& FGLocation::operator=(const FGLocation& l) mTi2l = l.mTi2l; mTl2i = l.mTl2i; - initial_longitude = l.initial_longitude; mGeodLat = l.mGeodLat; GeodeticAltitude = l.GeodeticAltitude; @@ -221,8 +208,6 @@ void FGLocation::SetLongitude(double longitude) mCacheValid = false; - // Need to figure out how to set the initial_longitude here - mECLoc(eX) = rtmp*cos(longitude); mECLoc(eY) = rtmp*sin(longitude); } @@ -274,7 +259,7 @@ void FGLocation::SetPosition(double lon, double lat, double radius) double cosLat = cos(lat); double sinLon = sin(lon); double cosLon = cos(lon); -// initial_longitude = lon; + mECLoc = FGColumnVector3( radius*cosLat*cosLon, radius*cosLat*sinLon, radius*sinLat ); @@ -286,17 +271,13 @@ void FGLocation::SetPositionGeodetic(double lon, double lat, double height) { mCacheValid = false; - mGeodLat = lat; - mLon = lon; - GeodeticAltitude = height; - -// initial_longitude = mLon; + double slat = sin(lat); + double clat = cos(lat); + double RN = a / sqrt(1.0 - e2*slat*slat); - double RN = a / sqrt(1.0 - e2*sin(mGeodLat)*sin(mGeodLat)); - - mECLoc(eX) = (RN + GeodeticAltitude)*cos(mGeodLat)*cos(mLon); - mECLoc(eY) = (RN + GeodeticAltitude)*cos(mGeodLat)*sin(mLon); - mECLoc(eZ) = ((1 - e2)*RN + GeodeticAltitude)*sin(mGeodLat); + mECLoc(eX) = (RN + height)*clat*cos(lon); + mECLoc(eY) = (RN + height)*clat*sin(lon); + mECLoc(eZ) = ((1 - e2)*RN + height)*slat; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -306,13 +287,10 @@ void FGLocation::SetEllipse(double semimajor, double semiminor) mCacheValid = false; a = semimajor; - b = semiminor; - a2 = a*a; - b2 = b*b; - e2 = 1.0 - b2/a2; - e = sqrt(e2); - eps2 = a2/b2 - 1.0; - f = 1.0 - b/a; + ec = semiminor/a; + ec2 = ec * ec; + e2 = 1.0 - ec2; + c = a * e2; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -387,51 +365,33 @@ void FGLocation::ComputeDerivedUnconditional(void) const mTl2i = mTec2i * mTl2ec; mTi2l = mTl2i.Transposed(); - // Calculate the geodetic latitude base on AIAA Journal of Guidance and Control paper, - // "Improved Method for Calculating Exact Geodetic Latitude and Altitude", and - // "Improved Method for Calculating Exact Geodetic Latitude and Altitude, Revisited", - // author: I. Sofair - - if (a != 0.0 && b != 0.0) { - double c, p, q, s, t, u, v, w, z, p2, u2, r0; - double Ne, P, Q0, Q, signz0, sqrt_q, z_term; - p = fabs(mECLoc(eZ))/eps2; - s = r02/(e2*eps2); - p2 = p*p; - q = p2 - b2 + s; - if (q>0) - { - sqrt_q = sqrt(q); - u = p/sqrt_q; - u2 = p2/q; - v = b2*u2/q; - P = 27.0*v*s/q; - Q0 = sqrt(P+1) + sqrt(P); - Q = pow(Q0, 0.66666666667); - t = (1.0 + Q + 1.0/Q)/6.0; - c = sqrt(u2 - 1 + 2.0*t); - w = (c - u)/2.0; - signz0 = mECLoc(eZ)>=0?1.0:-1.0; - z_term = sqrt(t*t+v)-u*w-0.5*t-0.25; - if (z_term < 0.0) { - z = 0.0; - } else { - z = signz0*sqrt_q*(w+sqrt(z_term)); - } - Ne = a*sqrt(1+eps2*z*z/b2); - double tmp = (eps2+1.0)*(z/Ne); - // Ugly hack to work around the round-off errors when the simulation is - // started at a latitude of 90deg. - if (tmp > 1.0) - tmp = 1.0; - else if (tmp < -1.0) - tmp = -1.0; - // End of ugly hack - mGeodLat = asin(tmp); - r0 = rxy; - GeodeticAltitude = r0*cos(mGeodLat) + mECLoc(eZ)*sin(mGeodLat) - a2/Ne; - } - } + // Calculate the geodetic latitude based on "Transformation from Cartesian + // to geodetic coordinates accelerated by Halley's method", Fukushima T. (2006) + // Journal of Geodesy, Vol. 79, pp. 689-693 + // Unlike I. Sofair's method which uses a closed form solution, Fukushima's + // method is an iterative method whose convergence is so fast that only one + // iteration suffices. In addition, Fukushima's method has a much better + // numerical stability over Sofair's method at the North and South poles and + // it also gives the correct result for a spherical Earth. + + double s0 = fabs(mECLoc(eZ)); + double zc = ec * s0; + double c0 = ec * rxy; + double c02 = c0 * c0; + double s02 = s0 * s0; + double a02 = c02 + s02; + double a0 = sqrt(a02); + double a03 = a02 * a0; + double s1 = zc*a03 + c*s02*s0; + double c1 = rxy*a03 - c*c02*c0; + double cs0c0 = c*c0*s0; + double b0 = 1.5*cs0c0*((rxy*s0-zc*c0)*a0-cs0c0); + s1 = s1*a03-b0*s0; + double cc = ec*(c1*a03-b0*c0); + mGeodLat = sign(mECLoc(eZ))*atan(s1 / cc); + double s12 = s1 * s1; + double cc2 = cc * cc; + GeodeticAltitude = (rxy*cc + s0*s1 - a*sqrt(ec2*s12 + cc2)) / sqrt(s12 + cc2); // Mark the cached values as valid mCacheValid = true; diff --git a/src/FDM/JSBSim/math/FGLocation.h b/src/FDM/JSBSim/math/FGLocation.h index cc8a86b21..38a6c76cb 100644 --- a/src/FDM/JSBSim/math/FGLocation.h +++ b/src/FDM/JSBSim/math/FGLocation.h @@ -42,8 +42,6 @@ SENTRY INCLUDES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -#include - #include "FGJSBBase.h" #include "FGColumnVector3.h" #include "FGMatrix33.h" @@ -53,7 +51,7 @@ INCLUDES DEFINITIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -#define ID_LOCATION "$Id: FGLocation.h,v 1.32 2013/10/19 17:59:51 bcoconni Exp $" +#define ID_LOCATION "$Id: FGLocation.h,v 1.33 2014/08/28 11:46:12 bcoconni Exp $" /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FORWARD DECLARATIONS @@ -152,7 +150,7 @@ CLASS DOCUMENTATION @see W. C. Durham "Aircraft Dynamics & Control", section 2.2 @author Mathias Froehlich - @version $Id: FGLocation.h,v 1.32 2013/10/19 17:59:51 bcoconni Exp $ + @version $Id: FGLocation.h,v 1.33 2014/08/28 11:46:12 bcoconni Exp $ */ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -632,8 +630,6 @@ private: mutable double mGeodLat; mutable double GeodeticAltitude; - double initial_longitude; - /** The cached rotation matrices from and to the associated frames. */ mutable FGMatrix33 mTl2ec; mutable FGMatrix33 mTec2l; @@ -645,14 +641,11 @@ private: double epa; /* Terms for geodetic latitude calculation. Values are from WGS84 model */ - double a; // Earth semimajor axis in feet (6,378,137.0 meters) - double b; // Earth semiminor axis in feet (6,356,752.3142 meters) - double a2; - double b2; - double e; // Earth eccentricity + double a; // Earth semimajor axis in feet double e2; // Earth eccentricity squared - double eps2; // - double f; // Flattening + double c; + double ec; + double ec2; /** A data validity flag. This class implements caching of the derived values like the diff --git a/src/FDM/JSBSim/math/FGModelFunctions.cpp b/src/FDM/JSBSim/math/FGModelFunctions.cpp index 957bf0697..f82ef0cd1 100644 --- a/src/FDM/JSBSim/math/FGModelFunctions.cpp +++ b/src/FDM/JSBSim/math/FGModelFunctions.cpp @@ -40,6 +40,7 @@ INCLUDES #include #include #include + #include "FGModelFunctions.h" #include "FGFunction.h" #include "input_output/FGXMLElement.h" @@ -48,7 +49,7 @@ using namespace std; namespace JSBSim { -IDENT(IdSrc,"$Id: FGModelFunctions.cpp,v 1.12 2014/01/13 10:46:03 ehofman Exp $"); +IDENT(IdSrc,"$Id: FGModelFunctions.cpp,v 1.14 2014/05/30 17:26:42 bcoconni Exp $"); IDENT(IdHdr,ID_MODELFUNCTIONS); /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -67,7 +68,7 @@ FGModelFunctions::~FGModelFunctions() bool FGModelFunctions::InitModel(void) { - ResetToIC(); + LocalProperties.ResetToIC(); return true; } @@ -76,7 +77,7 @@ bool FGModelFunctions::InitModel(void) bool FGModelFunctions::Load(Element* el, FGPropertyManager* PM, string prefix) { - LoadProperties(el, PM, false); + LocalProperties.Load(el, PM, false); PreLoad(el, PM, prefix); return true; // TODO: Need to make this value mean something. @@ -91,18 +92,10 @@ void FGModelFunctions::PreLoad(Element* el, FGPropertyManager* PM, string prefix Element *function = el->FindElement("function"); while (function) { - if (function->GetAttributeValue("type") == "pre") { + string fType = function->GetAttributeValue("type"); + if (fType.empty() || fType == "pre") PreFunctions.push_back(new FGFunction(PM, function, prefix)); - } else if (function->GetAttributeValue("type").empty()) { // Assume pre-function - string funcname = function->GetAttributeValue("name"); - if (funcname.find("IdleThrust") == string::npos && // Do not process functions that are - funcname.find("MilThrust") == string::npos && // already pre-defined turbine engine - funcname.find("AugThrust") == string::npos && // functions. These are loaded within - funcname.find("Injection") == string::npos ) // the Turbine::Load() method. - { - PreFunctions.push_back(new FGFunction(PM, function, prefix)); - } - } + function = el->FindNextElement("function"); } } @@ -152,6 +145,22 @@ void FGModelFunctions::RunPostFunctions(void) //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +FGFunction* FGModelFunctions::GetPreFunction(const std::string& name) +{ + FGFunction* result; + vector::iterator it = PreFunctions.begin(); + + for (; it != PreFunctions.end(); ++it) { + result = *it; + if (result->GetName() == name) + return result; + } + + return 0; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + string FGModelFunctions::GetFunctionStrings(const string& delimeter) const { string FunctionStrings = ""; diff --git a/src/FDM/JSBSim/math/FGModelFunctions.h b/src/FDM/JSBSim/math/FGModelFunctions.h index f67c203fb..7d3d2d664 100644 --- a/src/FDM/JSBSim/math/FGModelFunctions.h +++ b/src/FDM/JSBSim/math/FGModelFunctions.h @@ -45,7 +45,7 @@ INCLUDES DEFINITIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -#define ID_MODELFUNCTIONS "$Id: FGModelFunctions.h,v 1.9 2014/01/02 22:37:48 bcoconni Exp $" +#define ID_MODELFUNCTIONS "$Id: FGModelFunctions.h,v 1.11 2014/05/30 17:26:42 bcoconni Exp $" /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FORWARD DECLARATIONS @@ -78,7 +78,7 @@ CLASS DOCUMENTATION DECLARATION: FGModelFunctions %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -class FGModelFunctions : public FGPropertyReader, public FGJSBBase +class FGModelFunctions : public FGJSBBase { public: virtual ~FGModelFunctions(); @@ -99,9 +99,16 @@ public: functions */ std::string GetFunctionValues(const std::string& delimeter) const; + /** Get one of the "pre" function + @param name the name of the requested function. + @return a pointer to the function (NULL if not found) + */ + FGFunction* GetPreFunction(const std::string& name); + protected: std::vector PreFunctions; std::vector PostFunctions; + FGPropertyReader LocalProperties; virtual bool InitModel(void); }; diff --git a/src/FDM/JSBSim/math/FGRealValue.h b/src/FDM/JSBSim/math/FGRealValue.h index 9564eabf7..9e7eef8b3 100644 --- a/src/FDM/JSBSim/math/FGRealValue.h +++ b/src/FDM/JSBSim/math/FGRealValue.h @@ -35,12 +35,13 @@ INCLUDES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #include "FGParameter.h" +#include "input_output/string_utilities.h" /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% DEFINITIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -#define ID_REALVALUE "$Id: FGRealValue.h,v 1.5 2011/04/05 20:20:21 andgi Exp $" +#define ID_REALVALUE "$Id: FGRealValue.h,v 1.6 2014/08/28 13:44:27 bcoconni Exp $" /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FORWARD DECLARATIONS @@ -68,7 +69,8 @@ public: ~FGRealValue() {}; double GetValue(void) const; - std::string GetName(void) const {return "constant";} + std::string GetName(void) const + { return std::string("constant value ") + to_string(Value); } private: double Value; diff --git a/src/FDM/JSBSim/models/FGAerodynamics.cpp b/src/FDM/JSBSim/models/FGAerodynamics.cpp index a7aedb19e..e870d0f74 100644 --- a/src/FDM/JSBSim/models/FGAerodynamics.cpp +++ b/src/FDM/JSBSim/models/FGAerodynamics.cpp @@ -44,14 +44,13 @@ INCLUDES #include "FGFDMExec.h" #include "FGAerodynamics.h" #include "input_output/FGPropertyManager.h" -#include "input_output/FGXMLFileRead.h" #include "input_output/FGXMLElement.h" using namespace std; namespace JSBSim { -IDENT(IdSrc,"$Id: FGAerodynamics.cpp,v 1.53 2014/05/17 15:30:35 jberndt Exp $"); +IDENT(IdSrc,"$Id: FGAerodynamics.cpp,v 1.55 2014/09/03 17:26:28 bcoconni Exp $"); IDENT(IdHdr,ID_AERODYNAMICS); /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -84,6 +83,7 @@ FGAerodynamics::FGAerodynamics(FGFDMExec* FDMExec) : FGModel(FDMExec) impending_stall = stall_hyst = 0.0; alphaclmin = alphaclmax = 0.0; + alphaclmin0 = alphaclmax0 = 0.0; alphahystmin = alphahystmax = 0.0; clsq = lod = 0.0; alphaw = 0.0; @@ -124,7 +124,8 @@ bool FGAerodynamics::InitModel(void) if (!FGModel::InitModel()) return false; impending_stall = stall_hyst = 0.0; - alphaclmin = alphaclmax = 0.0; + alphaclmin = alphaclmin0; + alphaclmax = alphaclmax0; alphahystmin = alphahystmax = 0.0; clsq = lod = 0.0; alphaw = 0.0; @@ -280,39 +281,29 @@ bool FGAerodynamics::Run(bool Holding) //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -bool FGAerodynamics::Load(Element *element) +bool FGAerodynamics::Load(Element *document) { string parameter, axis, scratch; string scratch_unit=""; - string fname="", file=""; Element *temp_element, *axis_element, *function_element; - string separator = "/"; - FGXMLFileRead XMLFileRead; - Element* document; - - fname = element->GetAttributeValue("file"); - if (!fname.empty()) { - file = FDMExec->GetFullAircraftPath() + separator + fname; - document = XMLFileRead.LoadXMLDocument(file); - if (document == 0L) return false; - } else { - document = element; - } - Name = "Aerodynamics Model: " + document->GetAttributeValue("name"); - FGModel::Load(document); // Perform base class Pre-Load + // Perform base class Pre-Load + if (!FGModel::Load(document)) + return false; - DetermineAxisSystem(document); // Detemine if Lift/Side/Drag, etc. is used. + DetermineAxisSystem(document); // Determine if Lift/Side/Drag, etc. is used. Debug(2); if ((temp_element = document->FindElement("alphalimits"))) { scratch_unit = temp_element->GetAttributeValue("unit"); if (scratch_unit.empty()) scratch_unit = "RAD"; - alphaclmin = temp_element->FindElementValueAsNumberConvertFromTo("min", scratch_unit, "RAD"); - alphaclmax = temp_element->FindElementValueAsNumberConvertFromTo("max", scratch_unit, "RAD"); + alphaclmin0 = temp_element->FindElementValueAsNumberConvertFromTo("min", scratch_unit, "RAD"); + alphaclmax0 = temp_element->FindElementValueAsNumberConvertFromTo("max", scratch_unit, "RAD"); + alphaclmin = alphaclmin0; + alphaclmax = alphaclmax0; } if ((temp_element = document->FindElement("hysteresis_limits"))) { diff --git a/src/FDM/JSBSim/models/FGAerodynamics.h b/src/FDM/JSBSim/models/FGAerodynamics.h index da28d87b9..9b7ec1dad 100644 --- a/src/FDM/JSBSim/models/FGAerodynamics.h +++ b/src/FDM/JSBSim/models/FGAerodynamics.h @@ -51,7 +51,7 @@ INCLUDES DEFINITIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -#define ID_AERODYNAMICS "$Id: FGAerodynamics.h,v 1.29 2013/11/24 11:40:55 bcoconni Exp $" +#define ID_AERODYNAMICS "$Id: FGAerodynamics.h,v 1.30 2014/09/03 17:26:28 bcoconni Exp $" /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FORWARD DECLARATIONS @@ -108,7 +108,7 @@ CLASS DOCUMENTATION Systems may NOT be combined, or a load error will occur. @author Jon S. Berndt, Tony Peden - @version $Revision: 1.29 $ + @version $Revision: 1.30 $ */ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -245,6 +245,7 @@ private: FGColumnVector3 vDXYZcg; FGColumnVector3 vDeltaRP; double alphaclmax, alphaclmin; + double alphaclmax0, alphaclmin0; double alphahystmax, alphahystmin; double impending_stall, stall_hyst; double bi2vel, ci2vel,alphaw; diff --git a/src/FDM/JSBSim/models/FGBuoyantForces.cpp b/src/FDM/JSBSim/models/FGBuoyantForces.cpp index 68c945adc..c1195b7b5 100644 --- a/src/FDM/JSBSim/models/FGBuoyantForces.cpp +++ b/src/FDM/JSBSim/models/FGBuoyantForces.cpp @@ -41,14 +41,13 @@ INCLUDES #include "FGBuoyantForces.h" #include "FGMassBalance.h" #include "input_output/FGPropertyManager.h" -#include "input_output/FGXMLFileRead.h" #include "input_output/FGXMLElement.h" using namespace std; namespace JSBSim { -IDENT(IdSrc,"$Id: FGBuoyantForces.cpp,v 1.26 2014/01/13 10:46:06 ehofman Exp $"); +IDENT(IdSrc,"$Id: FGBuoyantForces.cpp,v 1.27 2014/06/09 11:52:07 bcoconni Exp $"); IDENT(IdHdr,ID_BUOYANTFORCES); /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -117,26 +116,15 @@ bool FGBuoyantForces::Run(bool Holding) //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -bool FGBuoyantForces::Load(Element *element) +bool FGBuoyantForces::Load(Element *document) { - string fname="", file=""; Element *gas_cell_element; Debug(2); - string separator = "/"; - FGXMLFileRead XMLFileRead; - Element* document; - - fname = element->GetAttributeValue("file"); - if (!fname.empty()) { - file = FDMExec->GetFullAircraftPath() + separator + fname; - document = XMLFileRead.LoadXMLDocument(file); - } else { - document = element; - } - - FGModel::Load(element); // Perform base class Load + // Perform base class Pre-Load + if (!FGModel::Load(document)) + return false; gas_cell_element = document->FindElement("gas_cell"); while (gas_cell_element) { diff --git a/src/FDM/JSBSim/models/FGExternalReactions.cpp b/src/FDM/JSBSim/models/FGExternalReactions.cpp index 6e72838b6..b07da0908 100644 --- a/src/FDM/JSBSim/models/FGExternalReactions.cpp +++ b/src/FDM/JSBSim/models/FGExternalReactions.cpp @@ -40,7 +40,6 @@ INCLUDES #include #include "FGExternalReactions.h" -#include "input_output/FGXMLFileRead.h" #include "input_output/FGXMLElement.h" using namespace std; @@ -55,7 +54,7 @@ DEFINITIONS GLOBAL DATA %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -IDENT(IdSrc,"$Id: FGExternalReactions.cpp,v 1.17 2014/01/13 10:46:07 ehofman Exp $"); +IDENT(IdSrc,"$Id: FGExternalReactions.cpp,v 1.18 2014/06/09 11:52:07 bcoconni Exp $"); IDENT(IdHdr,ID_EXTERNALREACTIONS); /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -73,17 +72,9 @@ FGExternalReactions::FGExternalReactions(FGFDMExec* fdmex) : FGModel(fdmex) bool FGExternalReactions::Load(Element* el) { - // check if a file attribute was specified - string fname = el->GetAttributeValue("file"); - FGXMLFileRead XMLFileRead; - - if (!fname.empty()) { - string file = FDMExec->GetFullAircraftPath() + "/" + fname; - el = XMLFileRead.LoadXMLDocument(file); - if (el == 0L) return false; - } - - FGModel::Load(el); // Call the base class Load() function to load interface properties. + // Call the base class Load() function to load interface properties. + if (!FGModel::Load(el)) + return false; Debug(2); diff --git a/src/FDM/JSBSim/models/FGFCS.cpp b/src/FDM/JSBSim/models/FGFCS.cpp index 2c7d3bedb..486f03e87 100644 --- a/src/FDM/JSBSim/models/FGFCS.cpp +++ b/src/FDM/JSBSim/models/FGFCS.cpp @@ -45,8 +45,8 @@ INCLUDES #include "FGFDMExec.h" #include "FGGroundReactions.h" #include "input_output/FGPropertyManager.h" -#include "input_output/FGXMLFileRead.h" #include "input_output/FGXMLElement.h" +#include "input_output/FGModelLoader.h" #include "models/flight_control/FGFilter.h" #include "models/flight_control/FGDeadBand.h" @@ -71,7 +71,7 @@ using namespace std; namespace JSBSim { -IDENT(IdSrc,"$Id: FGFCS.cpp,v 1.88 2014/05/17 15:27:16 jberndt Exp $"); +IDENT(IdSrc,"$Id: FGFCS.cpp,v 1.90 2014/06/09 11:52:07 bcoconni Exp $"); IDENT(IdHdr,ID_FCS); /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -488,40 +488,19 @@ void FGFCS::SetPropFeather(int engineNum, bool setting) //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -bool FGFCS::Load(Element* el, SystemType systype) +bool FGFCS::Load(Element* document, SystemType type) { - string name, file, fname="", interface_property_string, parent_name; + string name, parent_name; Element *component_element; Element *channel_element; - FGXMLFileRead XMLFileRead; - Element* document; -// ToDo: The handling of name and file attributes could be improved, here, -// considering that a name can be in the external file, as well. + systype = type; - name = el->GetAttributeValue("name"); + // Load interface properties from document + if (!FGModel::Load(document)) + return false; - if (name.empty() || !el->GetAttributeValue("file").empty()) { - fname = el->GetAttributeValue("file"); - if (systype == stSystem) { - file = FindSystemFullPathname(fname); - } else { - file = FDMExec->GetFullAircraftPath() + "/" + fname + ".xml"; - } - if (fname.empty()) { - cerr << "FCS, Autopilot, or system does not appear to be defined inline nor in a file" << endl; - return false; - } else { - document = XMLFileRead.LoadXMLDocument(file); - if (!document) { - cerr << "Error loading file " << file << endl; - return false; - } - name = document->GetAttributeValue("name"); - } - } else { - document = el; - } + name = document->GetAttributeValue("name"); Name = "Flight Control Systems Model: " + document->GetAttributeValue("name"); @@ -536,16 +515,6 @@ bool FGFCS::Load(Element* el, SystemType systype) if (document->GetName() == "flight_control") bindModel(); - FGModel::Load(document); // Load interface properties from document - - // After reading interface properties in a file, read properties in the local - // flight_control, autopilot, or system element. This allows general-purpose - // systems to be defined in a file, with overrides or initial loaded constants - // supplied in the relevant element of the aircraft configuration file. - - if (!fname.empty()) - LoadProperties(el, PropertyManager, true); - channel_element = document->FindElement("channel"); while (channel_element) { @@ -648,68 +617,16 @@ double FGFCS::GetBrake(FGLGear::BrakeGroup bg) //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -string FGFCS::FindSystemFullPathname(const string& sysfilename) -{ - string fullpath, localpath; - string system_filename = sysfilename; - string systemPath = FDMExec->GetSystemsPath(); - string aircraftPath = FDMExec->GetFullAircraftPath() + "/"; - ifstream system_file; - - fullpath = systemPath + "/"; - localpath = aircraftPath + "Systems/"; - - if (system_filename.length() <=4 || system_filename.substr(system_filename.length()-4, 4) != ".xml") { - system_filename.append(".xml"); - } - - system_file.open(string(aircraftPath + system_filename).c_str()); - if ( !system_file.is_open()) { - system_file.open(string(localpath + system_filename).c_str()); - if ( !system_file.is_open()) { - system_file.open(string(fullpath + system_filename).c_str()); - if ( !system_file.is_open()) { - cerr << " Could not open system file: " << system_filename << " in path " - << fullpath << " or " << localpath << endl; - return string(""); - } else { - return string(fullpath + system_filename); - } - } else { - return string(localpath + system_filename); - } - } else { - return string(aircraftPath + system_filename); - } - return string(""); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -ifstream* FGFCS::FindSystemFile(const string& sysfilename) +string FGFCS::FindFullPathName(const string& sysfilename) const { - string fullpath, localpath; - string system_filename = sysfilename; - string systemPath = FDMExec->GetSystemsPath(); - string aircraftPath = FDMExec->GetFullAircraftPath(); - ifstream* system_file = new ifstream(); + string name = FGModel::FindFullPathName(sysfilename); - fullpath = systemPath + "/"; - localpath = aircraftPath + "/Systems/"; + if (systype != stSystem || !name.empty()) return name; - if (system_filename.substr(system_filename.length()-4, 4) != ".xml") { - system_filename.append(".xml"); - } + name = CheckFullPathName(FDMExec->GetFullAircraftPath() + "/Systems", sysfilename); + if (!name.empty()) return name; - system_file->open(string(localpath + system_filename).c_str()); - if ( !system_file->is_open()) { - system_file->open(string(fullpath + system_filename).c_str()); - if ( !system_file->is_open()) { - cerr << " Could not open system file: " << system_filename << " in path " - << fullpath << " or " << localpath << endl; - } - } - return system_file; + return CheckFullPathName(FDMExec->GetSystemsPath(), sysfilename); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/FDM/JSBSim/models/FGFCS.h b/src/FDM/JSBSim/models/FGFCS.h index 7a12f8d04..f55fc067e 100644 --- a/src/FDM/JSBSim/models/FGFCS.h +++ b/src/FDM/JSBSim/models/FGFCS.h @@ -50,7 +50,7 @@ INCLUDES DEFINITIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -#define ID_FCS "$Id: FGFCS.h,v 1.45 2013/11/24 11:40:56 bcoconni Exp $" +#define ID_FCS "$Id: FGFCS.h,v 1.46 2014/06/09 11:52:07 bcoconni Exp $" /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FORWARD DECLARATIONS @@ -168,7 +168,7 @@ CLASS DOCUMENTATION @property gear/tailhook-pos-norm @author Jon S. Berndt - @version $Revision: 1.45 $ + @version $Revision: 1.46 $ @see FGActuator @see FGDeadBand @see FGFCSFunction @@ -555,8 +555,7 @@ public: @return true if succesful */ bool Load(Element* el, SystemType systype); - std::ifstream* FindSystemFile(const std::string& system_filename); - std::string FindSystemFullPathname(const std::string& system_filename); + std::string FindFullPathName(const std::string& system_filename) const; void AddThrottle(void); void AddGear(unsigned int NumGear); @@ -588,6 +587,7 @@ private: std::vector BrakePos; // left, center, right - defined by FGLGear:: enum double GearCmd,GearPos; double TailhookPos, WingFoldPos; + SystemType systype; typedef std::vector Channels; Channels SystemChannels; diff --git a/src/FDM/JSBSim/models/FGGasCell.cpp b/src/FDM/JSBSim/models/FGGasCell.cpp index 7a5626650..d4134464f 100644 --- a/src/FDM/JSBSim/models/FGGasCell.cpp +++ b/src/FDM/JSBSim/models/FGGasCell.cpp @@ -50,7 +50,7 @@ using std::max; namespace JSBSim { -IDENT(IdSrc,"$Id: FGGasCell.cpp,v 1.20 2014/01/13 10:46:07 ehofman Exp $"); +IDENT(IdSrc,"$Id: FGGasCell.cpp,v 1.21 2014/06/29 10:18:16 bcoconni Exp $"); IDENT(IdHdr,ID_GASCELL); /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -68,7 +68,7 @@ FGGasCell::FGGasCell(FGFDMExec* exec, Element* el, int num, const struct Inputs& string token; Element* element; - PropertyManager = exec->GetPropertyManager(); + FGPropertyManager* PropertyManager = exec->GetPropertyManager(); MassBalance = exec->GetMassBalance(); gasCellJ = FGMatrix33(); @@ -510,7 +510,7 @@ FGBallonet::FGBallonet(FGFDMExec* exec, Element* el, int num, FGGasCell* parent, string token; Element* element; - PropertyManager = exec->GetPropertyManager(); + FGPropertyManager* PropertyManager = exec->GetPropertyManager(); MassBalance = exec->GetMassBalance(); ballonetJ = FGMatrix33(); diff --git a/src/FDM/JSBSim/models/FGGasCell.h b/src/FDM/JSBSim/models/FGGasCell.h index df8cde022..abffb13fc 100644 --- a/src/FDM/JSBSim/models/FGGasCell.h +++ b/src/FDM/JSBSim/models/FGGasCell.h @@ -50,7 +50,7 @@ INCLUDES DEFINITIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -#define ID_GASCELL "$Id: FGGasCell.h,v 1.13 2013/04/17 20:24:27 andgi Exp $" +#define ID_GASCELL "$Id: FGGasCell.h,v 1.15 2014/06/29 10:18:16 bcoconni Exp $" /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FORWARD DECLARATIONS @@ -261,7 +261,6 @@ private: FGMatrix33 gasCellJ; // [slug foot^2] FGColumnVector3 gasCellM; // [lbs in] - FGPropertyManager* PropertyManager; FGMassBalance* MassBalance; void Debug(int from); @@ -364,7 +363,6 @@ private: double ValveOpen; // 0 <= ValveOpen <= 1 (or higher). FGMatrix33 ballonetJ; // [slug foot^2] - FGPropertyManager* PropertyManager; FGMassBalance* MassBalance; void Debug(int from); diff --git a/src/FDM/JSBSim/models/FGGroundReactions.cpp b/src/FDM/JSBSim/models/FGGroundReactions.cpp index 478703842..8e9bcb5f3 100644 --- a/src/FDM/JSBSim/models/FGGroundReactions.cpp +++ b/src/FDM/JSBSim/models/FGGroundReactions.cpp @@ -42,14 +42,13 @@ INCLUDES #include "FGLGear.h" #include "FGAccelerations.h" #include "input_output/FGPropertyManager.h" -#include "input_output/FGXMLFileRead.h" #include "input_output/FGXMLElement.h" using namespace std; namespace JSBSim { -IDENT(IdSrc,"$Id: FGGroundReactions.cpp,v 1.50 2014/05/17 15:25:20 jberndt Exp $"); +IDENT(IdSrc,"$Id: FGGroundReactions.cpp,v 1.51 2014/06/09 11:52:07 bcoconni Exp $"); IDENT(IdHdr,ID_GROUNDREACTIONS); /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -139,27 +138,18 @@ bool FGGroundReactions::GetWOW(void) const //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -bool FGGroundReactions::Load(Element* elem) +bool FGGroundReactions::Load(Element* document) { int num=0; - string fname="", file=""; - string separator = "/"; - FGXMLFileRead XMLFileRead; - Element* document; - - fname = elem->GetAttributeValue("file"); - if (!fname.empty()) { - file = FDMExec->GetFullAircraftPath() + separator + fname; - document = XMLFileRead.LoadXMLDocument(file); - if (document == 0L) return false; - } else { - document = elem; - } Name = "Ground Reactions Model: " + document->GetAttributeValue("name"); Debug(2); + // Perform base class Pre-Load + if (!FGModel::Load(document)) + return false; + unsigned int numContacts = document->GetNumElements("contact"); lGear.resize(numContacts); Element* contact_element = document->FindElement("contact"); @@ -168,8 +158,6 @@ bool FGGroundReactions::Load(Element* elem) contact_element = document->FindNextElement("contact"); } - FGModel::Load(document); // Perform base class Load - for (unsigned int i=0; ibind(); PostLoad(document, PropertyManager); diff --git a/src/FDM/JSBSim/models/FGLGear.cpp b/src/FDM/JSBSim/models/FGLGear.cpp index 2dbc8b08c..a77d7bfe0 100644 --- a/src/FDM/JSBSim/models/FGLGear.cpp +++ b/src/FDM/JSBSim/models/FGLGear.cpp @@ -44,6 +44,7 @@ INCLUDES #include #include +#include "math/FGFunction.h" #include "FGLGear.h" #include "input_output/FGPropertyManager.h" #include "models/FGGroundReactions.h" @@ -62,7 +63,7 @@ DEFINITIONS GLOBAL DATA %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -IDENT(IdSrc,"$Id: FGLGear.cpp,v 1.116 2014/05/17 15:26:39 jberndt Exp $"); +IDENT(IdSrc,"$Id: FGLGear.cpp,v 1.117 2014/06/08 12:50:05 bcoconni Exp $"); IDENT(IdHdr,ID_LGEAR); // Body To Structural (body frame is rotated 180 deg about Y and lengths are given in diff --git a/src/FDM/JSBSim/models/FGMassBalance.cpp b/src/FDM/JSBSim/models/FGMassBalance.cpp index 64a15b3db..0181c09eb 100644 --- a/src/FDM/JSBSim/models/FGMassBalance.cpp +++ b/src/FDM/JSBSim/models/FGMassBalance.cpp @@ -45,14 +45,13 @@ INCLUDES #include "FGMassBalance.h" #include "FGFDMExec.h" #include "input_output/FGPropertyManager.h" -#include "input_output/FGXMLFileRead.h" #include "input_output/FGXMLElement.h" using namespace std; namespace JSBSim { -IDENT(IdSrc,"$Id: FGMassBalance.cpp,v 1.49 2014/05/17 15:17:13 jberndt Exp $"); +IDENT(IdSrc,"$Id: FGMassBalance.cpp,v 1.50 2014/06/09 11:52:07 bcoconni Exp $"); IDENT(IdHdr,ID_MASSBALANCE); /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -103,27 +102,16 @@ bool FGMassBalance::InitModel(void) //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -bool FGMassBalance::Load(Element* elem) +bool FGMassBalance::Load(Element* document) { string element_name = ""; double bixx, biyy, bizz, bixy, bixz, biyz; - string fname="", file=""; - string separator = "/"; - FGXMLFileRead XMLFileRead; - Element* document; - - fname = elem->GetAttributeValue("file"); - if (!fname.empty()) { - file = FDMExec->GetFullAircraftPath() + separator + fname; - document = XMLFileRead.LoadXMLDocument(file); - if (document == 0L) return false; - } else { - document = elem; - } Name = "Mass Properties Model: " + document->GetAttributeValue("name"); - FGModel::Load(document); // Perform base class Load. + // Perform base class Pre-Load + if (!FGModel::Load(document)) + return false; bixx = biyy = bizz = bixy = bixz = biyz = 0.0; if (document->FindElement("ixx")) diff --git a/src/FDM/JSBSim/models/FGModel.cpp b/src/FDM/JSBSim/models/FGModel.cpp index d3b6c1387..ba05a71e1 100644 --- a/src/FDM/JSBSim/models/FGModel.cpp +++ b/src/FDM/JSBSim/models/FGModel.cpp @@ -38,15 +38,15 @@ HISTORY INCLUDES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -#include #include "FGModel.h" #include "FGFDMExec.h" +#include "input_output/FGModelLoader.h" using namespace std; namespace JSBSim { -IDENT(IdSrc,"$Id: FGModel.cpp,v 1.24 2014/01/13 10:46:07 ehofman Exp $"); +IDENT(IdSrc,"$Id: FGModel.cpp,v 1.25 2014/06/09 11:52:07 bcoconni Exp $"); IDENT(IdHdr,ID_MODEL); /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -101,6 +101,54 @@ bool FGModel::Run(bool Holding) else return true; } +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +string FGModel::FindFullPathName(const string& fname) const +{ + return CheckFullPathName(FDMExec->GetFullAircraftPath(), fname); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +bool FGModel::Load(Element* el) +{ + FGModelLoader ModelLoader(this); + Element* document = ModelLoader.Open(el); + + if (!document) return false; + + if (document->GetName() != el->GetName()) { + cerr << el->ReadFrom() + << " Read model '" << document->GetName() + << "' while expecting model '" << el->GetName() << "'" << endl; + return false; + } + + bool result = FGModelFunctions::Load(document, PropertyManager); + + if (document != el) { + el->MergeAttributes(document); + + // After reading interface properties in a file, read properties in the + // local model element. This allows general-purpose models to be defined in + // a file, with overrides or initial loaded constants supplied in the + // relevant element of the aircraft configuration file. + + LocalProperties.Load(el, PropertyManager, true); + + Element* element = document->FindElement(); + while (element) { + el->AddChildElement(element); + element->SetParent(el); + element = document->FindNextElement(); + } + + document = el; + } + + return result; +} + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // The bitmasked value choices are as follows: // unset: In this case (the default) JSBSim would only print diff --git a/src/FDM/JSBSim/models/FGModel.h b/src/FDM/JSBSim/models/FGModel.h index 7483dface..86b576b46 100644 --- a/src/FDM/JSBSim/models/FGModel.h +++ b/src/FDM/JSBSim/models/FGModel.h @@ -38,17 +38,15 @@ SENTRY INCLUDES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -#include "math/FGFunction.h" -#include "math/FGModelFunctions.h" - #include -#include + +#include "math/FGModelFunctions.h" /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% DEFINITIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -#define ID_MODEL "$Id: FGModel.h,v 1.20 2011/06/21 04:41:54 jberndt Exp $" +#define ID_MODEL "$Id: FGModel.h,v 1.22 2014/06/09 11:52:07 bcoconni Exp $" /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FORWARD DECLARATIONS @@ -100,6 +98,7 @@ public: FGFDMExec* GetExec(void) {return FDMExec;} void SetPropertyManager(FGPropertyManager *fgpm) { PropertyManager=fgpm;} + virtual std::string FindFullPathName(const std::string& filename) const; protected: int exe_ctr; @@ -108,7 +107,7 @@ protected: /** Loads this model. @param el a pointer to the element @return true if model is successfully loaded*/ - virtual bool Load(Element* el) {return FGModelFunctions::Load(el, PropertyManager);} + virtual bool Load(Element* el); virtual void Debug(int from); diff --git a/src/FDM/JSBSim/models/FGOutput.cpp b/src/FDM/JSBSim/models/FGOutput.cpp index 668011d36..46a482d3d 100644 --- a/src/FDM/JSBSim/models/FGOutput.cpp +++ b/src/FDM/JSBSim/models/FGOutput.cpp @@ -46,12 +46,13 @@ INCLUDES #include "input_output/FGOutputFG.h" #include "input_output/FGXMLFileRead.h" #include "input_output/FGXMLElement.h" +#include "input_output/FGModelLoader.h" using namespace std; namespace JSBSim { -IDENT(IdSrc,"$Id: FGOutput.cpp,v 1.77 2014/01/13 10:46:07 ehofman Exp $"); +IDENT(IdSrc,"$Id: FGOutput.cpp,v 1.80 2014/09/12 20:10:05 bcoconni Exp $"); IDENT(IdHdr,ID_OUTPUT); /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -64,7 +65,7 @@ FGOutput::FGOutput(FGFDMExec* fdmex) : FGModel(fdmex) Name = "FGOutput"; - fdmex->GetPropertyManager()->Tie("simulation/force-output", this, (iOPV)0, &FGOutput::ForceOutput, false); + PropertyManager->Tie("simulation/force-output", this, (iOPV)0, &FGOutput::ForceOutput, false); Debug(0); } @@ -255,12 +256,22 @@ bool FGOutput::Load(int subSystems, std::string protocol, std::string type, //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -bool FGOutput::Load(Element* document) +bool FGOutput::Load(Element* el) { - if (!document) return false; + // Unlike the other FGModel classes, properties listed in the section + // are not intended to create new properties. For that reason, FGOutput + // cannot load its XML directives with FGModel::Load(). + // Instead FGModelLoader::Open() and FGModel::PreLoad() must be explicitely + // called. + FGModelLoader ModelLoader(this); + Element* element = ModelLoader.Open(el); + + if (!element) return false; + + FGModel::PreLoad(element, PropertyManager); unsigned int idx = OutputTypes.size(); - string type = document->GetAttributeValue("type"); + string type = element->GetAttributeValue("type"); FGOutputType* Output = 0; if (debug_lvl > 0) cout << endl << " Output data set: " << idx << " " << endl; @@ -284,7 +295,8 @@ bool FGOutput::Load(Element* document) if (!Output) return false; Output->SetIdx(idx); - Output->Load(document); + Output->Load(element); + PostLoad(element, PropertyManager); OutputTypes.push_back(Output); diff --git a/src/FDM/JSBSim/models/FGPropulsion.cpp b/src/FDM/JSBSim/models/FGPropulsion.cpp index 1bcae7205..0857d0fe3 100644 --- a/src/FDM/JSBSim/models/FGPropulsion.cpp +++ b/src/FDM/JSBSim/models/FGPropulsion.cpp @@ -58,16 +58,14 @@ INCLUDES #include "models/propulsion/FGElectric.h" #include "models/propulsion/FGTurboProp.h" #include "models/propulsion/FGTank.h" -#include "input_output/FGPropertyManager.h" -#include "input_output/FGXMLFileRead.h" -#include "input_output/FGXMLElement.h" +#include "input_output/FGModelLoader.h" #include "math/FGColumnVector3.h" using namespace std; namespace JSBSim { -IDENT(IdSrc,"$Id: FGPropulsion.cpp,v 1.78 2014/05/17 15:13:56 jberndt Exp $"); +IDENT(IdSrc,"$Id: FGPropulsion.cpp,v 1.80 2014/06/29 10:18:16 bcoconni Exp $"); IDENT(IdHdr,ID_PROPULSION); extern short debug_lvl; @@ -349,29 +347,18 @@ void FGPropulsion::InitRunning(int n) //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -bool FGPropulsion::Load(Element* elem) +bool FGPropulsion::Load(Element* el) { - string type, engine_filename; - string separator = "/"; - Element *el=0; - FGXMLFileRead XMLFileRead; - FGXMLParse main_file_parser; + FGModelLoader ModelLoader(this); Debug(2); - - string fname="", file=""; - fname = elem->GetAttributeValue("file"); - if (!fname.empty()) { - file = FDMExec->GetFullAircraftPath() + separator + fname; - el = XMLFileRead.LoadXMLDocument(file, main_file_parser); - if (el == 0L) return false; - } else { - el = elem; - } + ReadingEngine = false; Name = "Propulsion Model: " + el->GetAttributeValue("name"); - FGModel::Load(el); // Perform base class Load. + // Perform base class Pre-Load + if (!FGModel::Load(el)) + return false; // Process tank definitions first to establish the number of fuel tanks @@ -387,51 +374,47 @@ bool FGPropulsion::Load(Element* elem) numSelectedFuelTanks = numFuelTanks; numSelectedOxiTanks = numOxiTanks; + ReadingEngine = true; Element* engine_element = el->FindElement("engine"); while (engine_element) { - engine_filename = engine_element->GetAttributeValue("file"); - - if (engine_filename.empty()) { - cerr << "Engine definition did not supply an engine file." << endl; - return false; - } - - engine_filename = FindEngineFullPathname(engine_filename); - if (engine_filename.empty()) { - // error message already printed by FindEngineFullPathname() - return false; - } + if (!ModelLoader.Open(engine_element)) return false; - Element* document = XMLFileRead.LoadXMLDocument(engine_filename); - document->SetParent(engine_element); - - type = document->GetName(); try { - if (type == "piston_engine") { + // Locate the thruster definition + Element* thruster_element = engine_element->FindElement("thruster"); + if (!thruster_element || !ModelLoader.Open(thruster_element)) + throw("No thruster definition supplied with engine definition."); + + if (engine_element->FindElement("piston_engine")) { HavePistonEngine = true; if (!IsBound) bind(); - Engines.push_back(new FGPiston(FDMExec, document, numEngines, in)); - } else if (type == "turbine_engine") { + Element *element = engine_element->FindElement("piston_engine"); + Engines.push_back(new FGPiston(FDMExec, element, numEngines, in)); + } else if (engine_element->FindElement("turbine_engine")) { HaveTurbineEngine = true; if (!IsBound) bind(); - Engines.push_back(new FGTurbine(FDMExec, document, numEngines, in)); - } else if (type == "turboprop_engine") { + Element *element = engine_element->FindElement("turbine_engine"); + Engines.push_back(new FGTurbine(FDMExec, element, numEngines, in)); + } else if (engine_element->FindElement("turboprop_engine")) { HaveTurboPropEngine = true; if (!IsBound) bind(); - Engines.push_back(new FGTurboProp(FDMExec, document, numEngines, in)); - } else if (type == "rocket_engine") { + Element *element = engine_element->FindElement("turboprop_engine"); + Engines.push_back(new FGTurboProp(FDMExec, element, numEngines, in)); + } else if (engine_element->FindElement("rocket_engine")) { HaveRocketEngine = true; if (!IsBound) bind(); - Engines.push_back(new FGRocket(FDMExec, document, numEngines, in)); - } else if (type == "electric_engine") { + Element *element = engine_element->FindElement("rocket_engine"); + Engines.push_back(new FGRocket(FDMExec, element, numEngines, in)); + } else if (engine_element->FindElement("electric_engine")) { HaveElectricEngine = true; if (!IsBound) bind(); - Engines.push_back(new FGElectric(FDMExec, document, numEngines, in)); + Element *element = engine_element->FindElement("electric_engine"); + Engines.push_back(new FGElectric(FDMExec, element, numEngines, in)); } else { - cerr << "Unknown engine type: " << type << endl; - exit(-5); + cerr << engine_element->ReadFrom() << " Unknown engine type" << endl; + return false; } - } catch (std::string str) { + } catch (std::string& str) { cerr << endl << fgred << str << reset << endl; return false; } @@ -439,7 +422,6 @@ bool FGPropulsion::Load(Element* elem) numEngines++; engine_element = el->FindNextElement("engine"); - XMLFileRead.ResetParser(); } CalculateTankInertias(); @@ -455,55 +437,14 @@ bool FGPropulsion::Load(Element* elem) //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -string FGPropulsion::FindEngineFullPathname(const string& engine_filename) +string FGPropulsion::FindFullPathName(const string& filename) const { - string fullpath, localpath; - string enginePath = FDMExec->GetEnginePath(); - string aircraftPath = FDMExec->GetFullAircraftPath(); - ifstream engine_file; - - string separator = "/"; - - fullpath = enginePath + separator; - localpath = aircraftPath + separator + "Engines" + separator; - - engine_file.open(string(localpath + engine_filename + ".xml").c_str()); - if ( !engine_file.is_open()) { - engine_file.open(string(fullpath + engine_filename + ".xml").c_str()); - if ( !engine_file.is_open()) { - cerr << " Could not open engine file: " << engine_filename << " in path " - << fullpath << " or " << localpath << endl; - return string(""); - } else { - return string(fullpath + engine_filename + ".xml"); - } - } - return string(localpath + engine_filename + ".xml"); -} + if (!ReadingEngine) return FGModel::FindFullPathName(filename); -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + string name = CheckFullPathName(FDMExec->GetFullAircraftPath() + "/Engines", filename); + if (!name.empty()) return name; -ifstream* FGPropulsion::FindEngineFile(const string& engine_filename) -{ - string fullpath, localpath; - string enginePath = FDMExec->GetEnginePath(); - string aircraftPath = FDMExec->GetFullAircraftPath(); - ifstream* engine_file = new ifstream(); - - string separator = "/"; - - fullpath = enginePath + separator; - localpath = aircraftPath + separator + "Engines" + separator; - - engine_file->open(string(localpath + engine_filename + ".xml").c_str()); - if ( !engine_file->is_open()) { - engine_file->open(string(fullpath + engine_filename + ".xml").c_str()); - if ( !engine_file->is_open()) { - cerr << " Could not open engine file: " << engine_filename << " in path " - << localpath << " or " << fullpath << endl; - } - } - return engine_file; + return CheckFullPathName(FDMExec->GetEnginePath(), filename); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/FDM/JSBSim/models/FGPropulsion.h b/src/FDM/JSBSim/models/FGPropulsion.h index a04916ada..eb5a087d2 100644 --- a/src/FDM/JSBSim/models/FGPropulsion.h +++ b/src/FDM/JSBSim/models/FGPropulsion.h @@ -49,7 +49,7 @@ INCLUDES DEFINITIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -#define ID_PROPULSION "$Id: FGPropulsion.h,v 1.33 2014/04/13 11:19:15 bcoconni Exp $" +#define ID_PROPULSION "$Id: FGPropulsion.h,v 1.34 2014/06/09 11:52:07 bcoconni Exp $" /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FORWARD DECLARATIONS @@ -91,7 +91,7 @@ CLASS DOCUMENTATION @endcode @author Jon S. Berndt - @version $Id: FGPropulsion.h,v 1.33 2014/04/13 11:19:15 bcoconni Exp $ + @version $Id: FGPropulsion.h,v 1.34 2014/06/09 11:52:07 bcoconni Exp $ @see FGEngine FGTank @@ -182,8 +182,7 @@ public: const FGColumnVector3& GetTanksMoment(void); double GetTanksWeight(void) const; - std::ifstream* FindEngineFile(const std::string& filename); - std::string FindEngineFullPathname(const std::string& engine_filename); + std::string FindFullPathName(const std::string& filename) const; inline int GetActiveEngine(void) const {return ActiveEngine;} inline bool GetFuelFreeze(void) const {return FuelFreeze;} double GetTotalFuelQuantity(void) const {return TotalFuelQuantity;} @@ -225,6 +224,8 @@ private: bool HaveElectricEngine; void ConsumeFuel(FGEngine* engine); + bool ReadingEngine; + void bind(); void Debug(int from); }; diff --git a/src/FDM/JSBSim/models/atmosphere/FGWinds.cpp b/src/FDM/JSBSim/models/atmosphere/FGWinds.cpp index e6fedc103..dd4d1c227 100644 --- a/src/FDM/JSBSim/models/atmosphere/FGWinds.cpp +++ b/src/FDM/JSBSim/models/atmosphere/FGWinds.cpp @@ -51,7 +51,7 @@ using namespace std; namespace JSBSim { -IDENT(IdSrc,"$Id: FGWinds.cpp,v 1.12 2014/02/17 05:02:38 jberndt Exp $"); +IDENT(IdSrc,"$Id: FGWinds.cpp,v 1.14 2014/09/03 17:40:59 bcoconni Exp $"); IDENT(IdHdr,ID_WINDS); /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -87,6 +87,7 @@ FGWinds::FGWinds(FGFDMExec* fdmex) : FGModel(fdmex) vGustNED.InitMatrix(); vTurbulenceNED.InitMatrix(); + vCosineGust.InitMatrix(); // Milspec turbulence model windspeed_at_20ft = 0.; @@ -120,7 +121,18 @@ FGWinds::~FGWinds() bool FGWinds::InitModel(void) { - return FGModel::InitModel(); + if (!FGModel::InitModel()) return false; + + psiw = 0.0; + + vGustNED.InitMatrix(); + vTurbulenceNED.InitMatrix(); + vCosineGust.InitMatrix(); + + oneMinusCosineGust.gustProfile.Running = false; + oneMinusCosineGust.gustProfile.elapsedTime = 0.0; + + return true; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/FDM/JSBSim/models/flight_control/FGActuator.cpp b/src/FDM/JSBSim/models/flight_control/FGActuator.cpp index ed6ee967f..dd492c4af 100644 --- a/src/FDM/JSBSim/models/flight_control/FGActuator.cpp +++ b/src/FDM/JSBSim/models/flight_control/FGActuator.cpp @@ -41,12 +41,13 @@ INCLUDES #include "FGActuator.h" #include "input_output/FGXMLElement.h" +#include "math/FGRealValue.h" using namespace std; namespace JSBSim { -IDENT(IdSrc,"$Id: FGActuator.cpp,v 1.36 2014/08/09 17:40:51 bcoconni Exp $"); +IDENT(IdSrc,"$Id: FGActuator.cpp,v 1.37 2014/08/28 13:44:28 bcoconni Exp $"); IDENT(IdHdr,ID_ACTUATOR); /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -65,9 +66,7 @@ FGActuator::FGActuator(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, eleme PreviousRateLimOutput = 0.0; PreviousLagInput = PreviousLagOutput = 0.0; bias = lag = hysteresis_width = deadband_width = 0.0; - rate_limited = false; - rate_limit = rate_limit_incr = rate_limit_decr = 0.0; // no limit - rate_limit_incr_prop = rate_limit_decr_prop = 0; + rate_limit_incr = rate_limit_decr = 0; // no limit fail_zero = fail_hardover = fail_stuck = false; ca = cb = 0.0; initialized = 0; @@ -85,38 +84,32 @@ FGActuator::FGActuator(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, eleme // a property. Element* ratelim_el = element->FindElement("rate_limit"); while ( ratelim_el ) { - rate_limited = true; - FGPropertyNode* rate_limit_prop=0; - + FGParameter* rate_limit = 0; string rate_limit_str = ratelim_el->GetDataLine(); + trim(rate_limit_str); - if (is_number(rate_limit_str)) { - rate_limit = fabs(atof(rate_limit_str.c_str())); - } else { + if (is_number(rate_limit_str)) + rate_limit = new FGRealValue(fabs(atof(rate_limit_str.c_str()))); + else { if (rate_limit_str[0] == '-') rate_limit_str.erase(0,1); - rate_limit_prop = PropertyManager->GetNode(rate_limit_str, true); - if (rate_limit_prop == 0) + FGPropertyNode* rate_limit_prop = PropertyManager->GetNode(rate_limit_str, true); + if (!rate_limit_prop) { std::cerr << "No such property, " << rate_limit_str << " for rate limiting" << std::endl; + ratelim_el = element->FindNextElement("rate_limit"); + continue; + } + rate_limit = new FGPropertyValue(rate_limit_prop); } if (ratelim_el->HasAttribute("sense")) { string sense = ratelim_el->GetAttributeValue("sense"); - if (sense.substr(0,4) == "incr") { - if (rate_limit_prop != 0) rate_limit_incr_prop = rate_limit_prop; - else rate_limit_incr = rate_limit; - } else if (sense.substr(0,4) == "decr") { - if (rate_limit_prop != 0) rate_limit_decr_prop = rate_limit_prop; - else rate_limit_decr = rate_limit; - } - } else { - if (rate_limit_prop != 0) { - rate_limit_incr_prop = rate_limit_prop; - rate_limit_decr_prop = rate_limit_prop; - } - else { + if (sense.substr(0,4) == "incr") rate_limit_incr = rate_limit; + else if (sense.substr(0,4) == "decr") rate_limit_decr = rate_limit; - } + } else { + rate_limit_incr = rate_limit; + rate_limit_decr = rate_limit; } ratelim_el = element->FindNextElement("rate_limit"); } @@ -141,6 +134,10 @@ FGActuator::FGActuator(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, eleme FGActuator::~FGActuator() { + delete rate_limit_incr; + if (rate_limit_decr != rate_limit_incr) + delete rate_limit_decr; + Debug(1); } @@ -176,8 +173,7 @@ bool FGActuator::Run(void ) Output = PreviousOutput; } else { if (lag != 0.0) Lag(); // models actuator lag - if (rate_limit != 0 || (rate_limit_incr_prop != 0 - || rate_limit_decr_prop != 0)) RateLimit(); // limit the actuator rate + if (rate_limit_incr != 0 || rate_limit_decr != 0) RateLimit(); // limit the actuator rate if (deadband_width != 0.0) Deadband(); if (hysteresis_width != 0.0) Hysteresis(); if (bias != 0.0) Bias(); // models a finite bias @@ -252,12 +248,15 @@ void FGActuator::RateLimit(void) double input = Output; if ( initialized ) { double delta = input - PreviousRateLimOutput; - if (rate_limit_incr_prop != 0) rate_limit_incr = rate_limit_incr_prop->getDoubleValue(); - if (rate_limit_decr_prop != 0) rate_limit_decr = rate_limit_decr_prop->getDoubleValue(); - if (delta > dt * rate_limit_incr) { - Output = PreviousRateLimOutput + rate_limit_incr * dt; - } else if (delta < -dt * rate_limit_decr) { - Output = PreviousRateLimOutput - rate_limit_decr * dt; + if (rate_limit_incr) { + double rate_limit = rate_limit_incr->GetValue(); + if (delta > dt * rate_limit) + Output = PreviousRateLimOutput + rate_limit * dt; + } + if (rate_limit_decr) { + double rate_limit = -rate_limit_decr->GetValue(); + if (delta < dt * rate_limit) + Output = PreviousRateLimOutput + rate_limit * dt; } } PreviousRateLimOutput = Output; @@ -335,17 +334,11 @@ void FGActuator::Debug(int from) cout << " OUTPUT: " << OutputNodes[i]->getName() << endl; } if (bias != 0.0) cout << " Bias: " << bias << endl; - if (rate_limited) { - if (rate_limit_incr_prop != 0) { - cout << " Increasing rate limit: " << rate_limit_incr_prop->GetName() << endl; - } else { - cout << " Increasing rate limit: " << rate_limit_incr << endl; - } - if (rate_limit_decr_prop != 0) { - cout << " Decreasing rate limit: " << rate_limit_decr_prop->GetName() << endl; - } else { - cout << " Decreasing rate limit: " << rate_limit_decr << endl; - } + if (rate_limit_incr != 0) { + cout << " Increasing rate limit: " << rate_limit_incr->GetName() << endl; + } + if (rate_limit_decr != 0) { + cout << " Decreasing rate limit: " << rate_limit_decr->GetName() << endl; } if (lag != 0) cout << " Actuator lag: " << lag << endl; if (hysteresis_width != 0) cout << " Hysteresis width: " << hysteresis_width << endl; diff --git a/src/FDM/JSBSim/models/flight_control/FGActuator.h b/src/FDM/JSBSim/models/flight_control/FGActuator.h index d131d7ab9..9f9df8c49 100644 --- a/src/FDM/JSBSim/models/flight_control/FGActuator.h +++ b/src/FDM/JSBSim/models/flight_control/FGActuator.h @@ -43,7 +43,7 @@ INCLUDES DEFINITIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -#define ID_ACTUATOR "$Id: FGActuator.h,v 1.18 2014/01/02 21:58:42 bcoconni Exp $" +#define ID_ACTUATOR "$Id: FGActuator.h,v 1.19 2014/08/28 13:44:28 bcoconni Exp $" /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FORWARD DECLARATIONS @@ -119,7 +119,7 @@ Example: @endcode @author Jon S. Berndt -@version $Revision: 1.18 $ +@version $Revision: 1.19 $ */ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -156,12 +156,8 @@ public: private: double span; double bias; - bool rate_limited; - double rate_limit; - double rate_limit_incr; - double rate_limit_decr; - FGPropertyNode_ptr rate_limit_incr_prop; - FGPropertyNode_ptr rate_limit_decr_prop; + FGParameter* rate_limit_incr; + FGParameter* rate_limit_decr; double hysteresis_width; double deadband_width; double lag; diff --git a/src/FDM/JSBSim/models/propulsion/FGElectric.cpp b/src/FDM/JSBSim/models/propulsion/FGElectric.cpp index b211981d6..41fba7d7f 100644 --- a/src/FDM/JSBSim/models/propulsion/FGElectric.cpp +++ b/src/FDM/JSBSim/models/propulsion/FGElectric.cpp @@ -50,7 +50,7 @@ using namespace std; namespace JSBSim { -IDENT(IdSrc,"$Id: FGElectric.cpp,v 1.16 2014/01/13 10:46:10 ehofman Exp $"); +IDENT(IdSrc,"$Id: FGElectric.cpp,v 1.18 2014/06/08 12:00:35 bcoconni Exp $"); IDENT(IdHdr,ID_ELECTRIC); /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -58,10 +58,12 @@ CLASS IMPLEMENTATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ FGElectric::FGElectric(FGFDMExec* exec, Element *el, int engine_number, struct FGEngine::Inputs& input) - : FGEngine(exec, el, engine_number, input) + : FGEngine(exec, engine_number, input) { string token; + Load(exec,el); + Type = etElectric; PowerWatts = 745.7; hptowatts = 745.7; diff --git a/src/FDM/JSBSim/models/propulsion/FGEngine.cpp b/src/FDM/JSBSim/models/propulsion/FGEngine.cpp index 75f07bd3e..9f649a419 100644 --- a/src/FDM/JSBSim/models/propulsion/FGEngine.cpp +++ b/src/FDM/JSBSim/models/propulsion/FGEngine.cpp @@ -46,7 +46,6 @@ INCLUDES #include "FGPropeller.h" #include "FGNozzle.h" #include "FGRotor.h" -#include "input_output/FGXMLFileRead.h" #include "input_output/FGXMLElement.h" #include "math/FGColumnVector3.h" @@ -54,19 +53,16 @@ using namespace std; namespace JSBSim { -IDENT(IdSrc,"$Id: FGEngine.cpp,v 1.57 2014/01/13 10:46:10 ehofman Exp $"); +IDENT(IdSrc,"$Id: FGEngine.cpp,v 1.60 2014/06/09 11:52:07 bcoconni Exp $"); IDENT(IdHdr,ID_ENGINE); /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS IMPLEMENTATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -FGEngine::FGEngine(FGFDMExec* exec, Element* engine_element, int engine_number, struct Inputs& input) +FGEngine::FGEngine(FGFDMExec* exec, int engine_number, struct Inputs& input) : in(input), EngineNumber(engine_number) { - Element* local_element; - FGColumnVector3 location, orientation; - Name = ""; Type = etUnknown; X = Y = Z = 0.0; @@ -76,66 +72,6 @@ FGEngine::FGEngine(FGFDMExec* exec, Element* engine_element, int engine_number, MaxThrottle = 1.0; MinThrottle = 0.0; - FDMExec = exec; - - PropertyManager = FDMExec->GetPropertyManager(); - - Name = engine_element->GetAttributeValue("name"); - - Load(engine_element, PropertyManager, to_string((int)EngineNumber)); // Call ModelFunctions loader - -// Find and set engine location - - local_element = engine_element->GetParent()->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. - - local_element = engine_element->GetParent()->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); - - // Load thruster - local_element = engine_element->GetParent()->FindElement("thruster"); - if (local_element) { - try { - if (!LoadThruster(local_element)) exit(-1); - } catch (std::string str) { - throw("Error loading engine " + Name + ". " + str); - } - } else { - cerr << "No thruster definition supplied with engine definition." << endl; - } - - ResetToIC(); // initialize dynamic terms - - // Load feed tank[s] references - local_element = engine_element->GetParent()->FindElement("feed"); - while (local_element) { - int tankID = (int)local_element->GetDataAsNumber(); - SourceTanks.push_back(tankID); - local_element = engine_element->GetParent()->FindNextElement("feed"); - } - - string property_name, base_property_name; - base_property_name = CreateIndexedPropertyName("propulsion/engine", EngineNumber); - - property_name = base_property_name + "/set-running"; - PropertyManager->Tie( property_name.c_str(), this, &FGEngine::GetRunning, &FGEngine::SetRunning ); - property_name = base_property_name + "/thrust-lbs"; - PropertyManager->Tie( property_name.c_str(), Thruster, &FGThruster::GetThrust); - property_name = base_property_name + "/fuel-flow-rate-pps"; - PropertyManager->Tie( property_name.c_str(), this, &FGEngine::GetFuelFlowRate); - property_name = base_property_name + "/fuel-flow-rate-gph"; - PropertyManager->Tie( property_name.c_str(), this, &FGEngine::GetFuelFlowRateGPH); - property_name = base_property_name + "/fuel-used-lbs"; - PropertyManager->Tie( property_name.c_str(), this, &FGEngine::GetFuelUsedLbs); - - PostLoad(engine_element, PropertyManager, to_string((int)EngineNumber)); - Debug(0); } @@ -236,59 +172,100 @@ void FGEngine::LoadThrusterInputs() //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -bool FGEngine::LoadThruster(Element *thruster_element) +void FGEngine::LoadThruster(Element *thruster_element) { - string token, fullpath, localpath; - string thruster_filename, thruster_fullpathname, thrType; - string enginePath = FDMExec->GetEnginePath(); - string aircraftPath = FDMExec->GetFullAircraftPath(); - ifstream thruster_file; - FGColumnVector3 location, orientation; - string separator = "/"; - - fullpath = enginePath + separator; - localpath = aircraftPath + separator + "Engines" + separator; - - thruster_filename = thruster_element->GetAttributeValue("file"); - if ( !thruster_filename.empty()) { - thruster_fullpathname = localpath + thruster_filename + ".xml"; - thruster_file.open(thruster_fullpathname.c_str()); - if ( !thruster_file.is_open()) { - thruster_fullpathname = fullpath + thruster_filename + ".xml"; - thruster_file.open(thruster_fullpathname.c_str()); - if ( !thruster_file.is_open()) { - cerr << "Could not open thruster file: " << thruster_filename << ".xml" << endl; - return false; - } else { - thruster_file.close(); - } - } else { - thruster_file.close(); - } - } else { - cerr << "No thruster filename given." << endl; - return false; - } - - FGXMLFileRead XMLFileRead; - Element *document = XMLFileRead.LoadXMLDocument(thruster_fullpathname); - document->SetParent(thruster_element); - - thrType = document->GetName(); - - if (thrType == "propeller") { + if (thruster_element->FindElement("propeller")) { + Element *document = thruster_element->FindElement("propeller"); Thruster = new FGPropeller(FDMExec, document, EngineNumber); - } else if (thrType == "nozzle") { + } else if (thruster_element->FindElement("nozzle")) { + Element *document = thruster_element->FindElement("nozzle"); Thruster = new FGNozzle(FDMExec, document, EngineNumber); - } else if (thrType == "rotor") { + } else if (thruster_element->FindElement("rotor")) { + Element *document = thruster_element->FindElement("rotor"); Thruster = new FGRotor(FDMExec, document, EngineNumber); - } else if (thrType == "direct") { + } else if (thruster_element->FindElement("direct")) { + Element *document = thruster_element->FindElement("direct"); Thruster = new FGThruster( FDMExec, document, EngineNumber); + } else { + cerr << thruster_element->ReadFrom() << " Unknown thruster type" << endl; + throw("Failed to load the thruster"); } Thruster->SetdeltaT(in.TotalDeltaT); Debug(2); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +bool FGEngine::Load(FGFDMExec *exec, Element *engine_element) +{ + Element* parent_element = engine_element->GetParent(); + Element* local_element; + FGColumnVector3 location, orientation; + + FDMExec = exec; + + PropertyManager = FDMExec->GetPropertyManager(); + + Name = engine_element->GetAttributeValue("name"); + + FGModelFunctions::Load(engine_element, PropertyManager, to_string((int)EngineNumber)); // Call ModelFunctions loader + +// Find and set engine location + + 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. + + 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); + + // Load thruster + local_element = parent_element->FindElement("thruster"); + if (local_element) { + try { + LoadThruster(local_element); + } catch (std::string str) { + throw("Error loading engine " + Name + ". " + str); + } + } else { + cerr << "No thruster definition supplied with engine definition." << endl; + } + + ResetToIC(); // initialize dynamic terms + + // Load feed tank[s] references + local_element = parent_element->FindElement("feed"); + while (local_element) { + int tankID = (int)local_element->GetDataAsNumber(); + SourceTanks.push_back(tankID); + local_element = parent_element->FindNextElement("feed"); + } + + string property_name, base_property_name; + base_property_name = CreateIndexedPropertyName("propulsion/engine", EngineNumber); + + property_name = base_property_name + "/set-running"; + PropertyManager->Tie( property_name.c_str(), this, &FGEngine::GetRunning, &FGEngine::SetRunning ); + property_name = base_property_name + "/thrust-lbs"; + PropertyManager->Tie( property_name.c_str(), Thruster, &FGThruster::GetThrust); + property_name = base_property_name + "/fuel-flow-rate-pps"; + PropertyManager->Tie( property_name.c_str(), this, &FGEngine::GetFuelFlowRate); + property_name = base_property_name + "/fuel-flow-rate-gph"; + PropertyManager->Tie( property_name.c_str(), this, &FGEngine::GetFuelFlowRateGPH); + property_name = base_property_name + "/fuel-used-lbs"; + PropertyManager->Tie( property_name.c_str(), this, &FGEngine::GetFuelUsedLbs); + + PostLoad(engine_element, PropertyManager, to_string((int)EngineNumber)); + + Debug(0); + return true; } diff --git a/src/FDM/JSBSim/models/propulsion/FGEngine.h b/src/FDM/JSBSim/models/propulsion/FGEngine.h index 942a6b4fa..89e81cb39 100644 --- a/src/FDM/JSBSim/models/propulsion/FGEngine.h +++ b/src/FDM/JSBSim/models/propulsion/FGEngine.h @@ -53,7 +53,7 @@ INCLUDES DEFINITIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -#define ID_ENGINE "$Id: FGEngine.h,v 1.39 2013/12/22 17:14:37 bcoconni Exp $" +#define ID_ENGINE "$Id: FGEngine.h,v 1.42 2014/06/09 11:52:07 bcoconni Exp $" /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FORWARD DECLARATIONS @@ -111,7 +111,7 @@ CLASS DOCUMENTATION documentation for engine and thruster classes. @author Jon S. Berndt - @version $Id: FGEngine.h,v 1.39 2013/12/22 17:14:37 bcoconni Exp $ + @version $Id: FGEngine.h,v 1.42 2014/06/09 11:52:07 bcoconni Exp $ */ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -150,7 +150,7 @@ public: double TotalDeltaT; }; - FGEngine(FGFDMExec* exec, Element* el, int engine_number, struct Inputs& input); + FGEngine(FGFDMExec* exec, int engine_number, struct Inputs& input); virtual ~FGEngine(); enum EngineType {etUnknown, etRocket, etPiston, etTurbine, etTurboprop, etElectric}; @@ -207,7 +207,7 @@ public: virtual const FGColumnVector3& GetBodyForces(void); virtual const FGColumnVector3& GetMoments(void); - bool LoadThruster(Element *el); + void LoadThruster(Element *el); FGThruster* GetThruster(void) const {return Thruster;} unsigned int GetSourceTank(unsigned int i) const; @@ -256,6 +256,7 @@ protected: std::vector SourceTanks; + virtual bool Load(FGFDMExec *exec, Element *el); void Debug(int from); }; } diff --git a/src/FDM/JSBSim/models/propulsion/FGPiston.cpp b/src/FDM/JSBSim/models/propulsion/FGPiston.cpp index 48e723728..1b45cdb95 100644 --- a/src/FDM/JSBSim/models/propulsion/FGPiston.cpp +++ b/src/FDM/JSBSim/models/propulsion/FGPiston.cpp @@ -51,7 +51,7 @@ using namespace std; namespace JSBSim { -IDENT(IdSrc,"$Id: FGPiston.cpp,v 1.74 2014/01/13 10:46:10 ehofman Exp $"); +IDENT(IdSrc,"$Id: FGPiston.cpp,v 1.77 2014/06/08 12:00:35 bcoconni Exp $"); IDENT(IdHdr,ID_PISTON); /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -59,7 +59,7 @@ CLASS IMPLEMENTATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ FGPiston::FGPiston(FGFDMExec* exec, Element* el, int engine_number, struct Inputs& input) - : FGEngine(exec, el, engine_number, input), + : FGEngine(exec, engine_number, input), R_air(287.3), // Gas constant for air J/Kg/K rho_fuel(800), // estimate calorific_value_fuel(47.3e6), // J/Kg @@ -67,6 +67,8 @@ FGPiston::FGPiston(FGFDMExec* exec, Element* el, int engine_number, struct Input Cp_fuel(1700), standard_pressure(101320.73) { + Load(exec, el); + Element *table_element; string token; string name=""; @@ -245,6 +247,10 @@ FGPiston::FGPiston(FGFDMExec* exec, Element* el, int engine_number, struct Input cerr << "Unknown table type: " << name << " in piston engine definition." << endl; } } catch (std::string str) { + // Make sure allocated resources are freed before rethrowing. + // (C++ standard guarantees that a null pointer deletion is no-op). + delete Lookup_Combustion_Efficiency; + delete Mixture_Efficiency_Correlation; throw("Error loading piston engine table:" + name + ". " + str); } } diff --git a/src/FDM/JSBSim/models/propulsion/FGRocket.cpp b/src/FDM/JSBSim/models/propulsion/FGRocket.cpp index 230e7483d..220d1bbd4 100644 --- a/src/FDM/JSBSim/models/propulsion/FGRocket.cpp +++ b/src/FDM/JSBSim/models/propulsion/FGRocket.cpp @@ -49,7 +49,7 @@ using namespace std; namespace JSBSim { -IDENT(IdSrc,"$Id: FGRocket.cpp,v 1.35 2014/05/17 15:04:14 jberndt Exp $"); +IDENT(IdSrc,"$Id: FGRocket.cpp,v 1.37 2014/06/08 12:00:35 bcoconni Exp $"); IDENT(IdHdr,ID_ROCKET); /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -57,8 +57,10 @@ CLASS IMPLEMENTATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ FGRocket::FGRocket(FGFDMExec* exec, Element *el, int engine_number, struct Inputs& input) - : FGEngine(exec, el, engine_number, input), isp_function(0L) + : FGEngine(exec, engine_number, input), isp_function(0L) { + Load(exec, el); + Type = etRocket; Element* thrust_table_element = 0; ThrustTable = 0L; diff --git a/src/FDM/JSBSim/models/propulsion/FGTurbine.cpp b/src/FDM/JSBSim/models/propulsion/FGTurbine.cpp index 6ab51091d..5a609f29d 100644 --- a/src/FDM/JSBSim/models/propulsion/FGTurbine.cpp +++ b/src/FDM/JSBSim/models/propulsion/FGTurbine.cpp @@ -42,6 +42,7 @@ INCLUDES #include #include +#include "math/FGFunction.h" #include "FGTurbine.h" #include "FGThruster.h" #include "input_output/FGXMLElement.h" @@ -50,7 +51,7 @@ using namespace std; namespace JSBSim { -IDENT(IdSrc,"$Id: FGTurbine.cpp,v 1.40 2014/01/13 10:46:10 ehofman Exp $"); +IDENT(IdSrc,"$Id: FGTurbine.cpp,v 1.43 2014/06/08 12:50:05 bcoconni Exp $"); IDENT(IdHdr,ID_TURBINE); /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -59,7 +60,7 @@ CLASS IMPLEMENTATION FGTurbine::FGTurbine(FGFDMExec* exec, Element *el, int engine_number, struct Inputs& input) - : FGEngine(exec, el, engine_number, input) + : FGEngine(exec, engine_number, input) { Type = etTurbine; @@ -75,8 +76,6 @@ FGTurbine::FGTurbine(FGFDMExec* exec, Element *el, int engine_number, struct Inp N1_spinup = 1.0; N2_spinup = 3.0; EPR = 1.0; - ResetToIC(); - Load(exec, el); Debug(0); } @@ -85,10 +84,6 @@ FGTurbine::FGTurbine(FGFDMExec* exec, Element *el, int engine_number, struct Inp FGTurbine::~FGTurbine() { - delete IdleThrustLookup; - delete MilThrustLookup; - delete MaxThrustLookup; - delete InjectionLookup; Debug(1); } @@ -416,8 +411,19 @@ double FGTurbine::Seek(double *var, double target, double accel, double decel) { bool FGTurbine::Load(FGFDMExec* exec, Element *el) { - string property_name, property_prefix; - property_prefix = CreateIndexedPropertyName("propulsion/engine", EngineNumber); + Element* function_element = el->FindElement("function"); + + while(function_element) { + string name = function_element->GetAttributeValue("name"); + if (name == "IdleThrust" || name == "MilThrust" || name == "AugThrust" || name == "Injection") + function_element->SetAttributeValue("name", string("propulsion/engine[#]/") + name); + + function_element = el->FindNextElement("function"); + } + + FGEngine::Load(exec, el); + + ResetToIC(); if (el->FindElement("milthrust")) MilThrust = el->FindElementValueAsNumberConvertTo("milthrust","LBS"); @@ -452,24 +458,12 @@ bool FGTurbine::Load(FGFDMExec* exec, Element *el) if (el->FindElement("injection-time")) InjectionTime = el->FindElementValueAsNumber("injection-time"); - Element *function_element; - string name; - FGPropertyManager* PropertyManager = exec->GetPropertyManager(); + string property_prefix = CreateIndexedPropertyName("propulsion/engine", EngineNumber); - while (true) { - function_element = el->FindNextElement("function"); - if (!function_element) break; - name = function_element->GetAttributeValue("name"); - if (name == "IdleThrust") { - IdleThrustLookup = new FGFunction(PropertyManager, function_element, property_prefix); - } else if (name == "MilThrust") { - MilThrustLookup = new FGFunction(PropertyManager, function_element, property_prefix); - } else if (name == "AugThrust") { - MaxThrustLookup = new FGFunction(PropertyManager, function_element, property_prefix); - } else if (name == "Injection") { - InjectionLookup = new FGFunction(PropertyManager, function_element, property_prefix); - } - } + IdleThrustLookup = GetPreFunction(property_prefix+"/IdleThrust"); + MilThrustLookup = GetPreFunction(property_prefix+"/MilThrust"); + MaxThrustLookup = GetPreFunction(property_prefix+"/AugThrust"); + InjectionLookup = GetPreFunction(property_prefix+"/Injection"); // Pre-calculations and initializations diff --git a/src/FDM/JSBSim/models/propulsion/FGTurboProp.cpp b/src/FDM/JSBSim/models/propulsion/FGTurboProp.cpp index f19205545..8216a5ca7 100644 --- a/src/FDM/JSBSim/models/propulsion/FGTurboProp.cpp +++ b/src/FDM/JSBSim/models/propulsion/FGTurboProp.cpp @@ -54,7 +54,7 @@ using namespace std; namespace JSBSim { -IDENT(IdSrc,"$Id: FGTurboProp.cpp,v 1.28 2014/01/13 10:46:10 ehofman Exp $"); +IDENT(IdSrc,"$Id: FGTurboProp.cpp,v 1.30 2014/06/08 12:00:35 bcoconni Exp $"); IDENT(IdHdr,ID_TURBOPROP); /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -62,9 +62,10 @@ CLASS IMPLEMENTATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ FGTurboProp::FGTurboProp(FGFDMExec* exec, Element *el, int engine_number, struct Inputs& input) - : FGEngine(exec, el, engine_number, input), + : FGEngine(exec, engine_number, input), ITT_N1(NULL), EnginePowerRPM_N1(NULL), EnginePowerVC(NULL), CombustionEfficiency_N1(NULL) { + FGEngine::Load(exec, el); SetDefaults(); thrusterType = Thruster->GetType();