From cb435814c1293b5ada428612a3e6bb8f2180f21b Mon Sep 17 00:00:00 2001 From: ehofman Date: Sat, 13 Jun 2009 07:55:25 +0000 Subject: [PATCH] latest changes for JSBSim (1.0 prerelease) --- src/FDM/JSBSim/FGJSBBase.cpp | 2 + src/FDM/JSBSim/FGJSBBase.h | 2 + src/FDM/JSBSim/initialization/FGTrim.cpp | 2 +- src/FDM/JSBSim/input_output/FGXMLParse.cpp | 24 +-- src/FDM/JSBSim/input_output/FGfdmSocket.cpp | 4 +- .../JSBSim/input_output/string_utilities.h | 144 ++++++++++++++++++ src/FDM/JSBSim/math/FGCondition.cpp | 27 ++-- src/FDM/JSBSim/math/FGLocation.cpp | 20 +++ src/FDM/JSBSim/math/FGLocation.h | 6 + src/FDM/JSBSim/models/FGAerodynamics.cpp | 2 + src/FDM/JSBSim/models/FGAircraft.cpp | 2 + src/FDM/JSBSim/models/FGBuoyantForces.cpp | 27 +--- src/FDM/JSBSim/models/FGBuoyantForces.h | 2 - src/FDM/JSBSim/models/FGExternalReactions.cpp | 24 +-- src/FDM/JSBSim/models/FGExternalReactions.h | 1 - src/FDM/JSBSim/models/FGFCS.cpp | 50 +----- src/FDM/JSBSim/models/FGFCS.h | 2 - src/FDM/JSBSim/models/FGGroundReactions.cpp | 2 + src/FDM/JSBSim/models/FGInput.cpp | 56 +++---- src/FDM/JSBSim/models/FGMassBalance.cpp | 2 + src/FDM/JSBSim/models/FGModel.cpp | 32 ++++ src/FDM/JSBSim/models/FGModel.h | 7 +- src/FDM/JSBSim/models/FGPropulsion.cpp | 2 + .../models/flight_control/FGDeadBand.cpp | 27 +++- .../JSBSim/models/flight_control/FGDeadBand.h | 2 + .../models/flight_control/FGFCSComponent.cpp | 4 +- .../JSBSim/models/flight_control/FGFilter.cpp | 2 +- .../JSBSim/models/flight_control/FGGain.cpp | 8 +- .../JSBSim/models/flight_control/FGPID.cpp | 6 +- .../JSBSim/models/flight_control/FGSensor.h | 2 +- .../JSBSim/models/flight_control/FGSwitch.cpp | 15 +- 31 files changed, 332 insertions(+), 176 deletions(-) create mode 100644 src/FDM/JSBSim/input_output/string_utilities.h diff --git a/src/FDM/JSBSim/FGJSBBase.cpp b/src/FDM/JSBSim/FGJSBBase.cpp index b5e854d8f..228fa8639 100644 --- a/src/FDM/JSBSim/FGJSBBase.cpp +++ b/src/FDM/JSBSim/FGJSBBase.cpp @@ -35,6 +35,8 @@ HISTORY INCLUDES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ +#define BASE + #include "FGJSBBase.h" namespace JSBSim { diff --git a/src/FDM/JSBSim/FGJSBBase.h b/src/FDM/JSBSim/FGJSBBase.h index 8ec700a15..7e56d5f5f 100644 --- a/src/FDM/JSBSim/FGJSBBase.h +++ b/src/FDM/JSBSim/FGJSBBase.h @@ -45,6 +45,8 @@ INCLUDES #include #include +#include "input_output/string_utilities.h" + using std::fabs; using std::string; diff --git a/src/FDM/JSBSim/initialization/FGTrim.cpp b/src/FDM/JSBSim/initialization/FGTrim.cpp index 39e934f5b..ed69050cd 100644 --- a/src/FDM/JSBSim/initialization/FGTrim.cpp +++ b/src/FDM/JSBSim/initialization/FGTrim.cpp @@ -184,7 +184,7 @@ bool FGTrim::RemoveState( State state ) { ta=*iAxes; if( ta->GetStateType() == state ) { delete ta; - TrimAxes.erase(iAxes); + iAxes = TrimAxes.erase(iAxes); result=true; continue; } diff --git a/src/FDM/JSBSim/input_output/FGXMLParse.cpp b/src/FDM/JSBSim/input_output/FGXMLParse.cpp index 5a57040a4..b8923225f 100755 --- a/src/FDM/JSBSim/input_output/FGXMLParse.cpp +++ b/src/FDM/JSBSim/input_output/FGXMLParse.cpp @@ -31,6 +31,7 @@ INCLUDES #include "FGXMLParse.h" #include +#include "input_output/string_utilities.h" namespace JSBSim { @@ -114,26 +115,9 @@ void FGXMLParse::startElement (const char * name, const XMLAttributes &atts) void FGXMLParse::endElement (const char * name) { - string local_work_string; - - while (!working_string.empty()) { - // clear leading newlines and spaces - string::size_type pos = working_string.find_first_not_of( " \n"); - if (pos > 0) - working_string.erase(0, pos); - - // remove spaces (only) from end of string - pos = working_string.find_last_not_of( " "); - if (pos != string::npos) - working_string.erase( ++pos); - - if (!working_string.empty()) { - pos = working_string.find("\n"); - if (pos != string::npos) local_work_string = working_string.substr(0,pos); - else local_work_string = working_string; - current_element->AddData(local_work_string); - working_string.erase(0, pos); - } + if (!working_string.empty()) { + vector work_strings = split(working_string, '\n'); + for (int i=0; iAddData(work_strings[i]); } current_element = current_element->GetParent(); diff --git a/src/FDM/JSBSim/input_output/FGfdmSocket.cpp b/src/FDM/JSBSim/input_output/FGfdmSocket.cpp index 1c390696f..7fa7ae59f 100644 --- a/src/FDM/JSBSim/input_output/FGfdmSocket.cpp +++ b/src/FDM/JSBSim/input_output/FGfdmSocket.cpp @@ -63,7 +63,7 @@ FGfdmSocket::FGfdmSocket(string address, int port, int protocol) else cout << "Winsock DLL not initialized ..." << endl; #endif - if (address.find_first_not_of("0123456789.",0) != address.npos) { + if (!is_number(address)) { if ((host = gethostbyname(address.c_str())) == NULL) { cout << "Could not get host net address by name..." << endl; } @@ -121,7 +121,7 @@ FGfdmSocket::FGfdmSocket(string address, int port) cout << "Host name... " << address << ", Port... " << port << "." << endl; cout << "Host name... (char) " << address.c_str() << "." << endl; - if (address.find_first_not_of("0123456789.",0) != address.npos) { + if (!is_number(address)) { if ((host = gethostbyname(address.c_str())) == NULL) { cout << "Could not get host net address by name..." << endl; } diff --git a/src/FDM/JSBSim/input_output/string_utilities.h b/src/FDM/JSBSim/input_output/string_utilities.h new file mode 100644 index 000000000..38ab80628 --- /dev/null +++ b/src/FDM/JSBSim/input_output/string_utilities.h @@ -0,0 +1,144 @@ +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + Header: string_utilities.h + Author: Jon S. Berndt + Date started: 06/01/09 + + ------------- Copyright (C) 2009 Jon S. Berndt (jsb@hal-pc.org) ------------- + + 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 +-------------------------------------------------------------------------------- +06/01/09 JSB Created + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +SENTRY +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#ifndef STRINGUTILS_H +#define STRINGUTILS_H + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +INCLUDES +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#include +#include + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +DEFINITIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#define ID_STRINGUTILS "$Id$" + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +FORWARD DECLARATIONS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +using namespace std; + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DOCUMENTATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +CLASS DECLARATION +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#if !defined(BASE) + extern string& trim_left(string& str); + extern string& trim_right(string& str); + extern string& trim(string& str); + extern string& to_upper(string& str); + extern string& to_lower(string& str); + extern bool is_number(string& str); + vector split(string str, char d); +#else + + string& trim_left(string& str) + { + while ( !isgraph(str[0]) ) { + str = str.erase(0,1); + if (str.size() == 0) break; + } + return str; + } + + string& trim_right(string& str) + { + while (!isgraph(str[str.size()-1])) { + str = str.erase(str.size()-1,1); + if (str.size() == 0) break; + } + return str; + } + + string& trim(string& str) + { + if (str.size() == 0) return str; + string temp_str = trim_right(str); + return str = trim_left(temp_str); + } + + string& to_upper(string& str) + { + for (int i=0; i split(string str, char d) + { + vector str_array; + int index=0; + string temp = ""; + + trim(str); + index = str.find(d); + while (index != string::npos) { + temp = str.substr(0,index); + trim(temp); + if (temp.size() > 0) str_array.push_back(temp); + str = str.erase(0,index+1); + index = str.find(d); + } + if (str.size() > 0) { + temp = trim(str); + if (temp.size() > 0) str_array.push_back(temp); + } + + return str_array; + } + +#endif + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +#endif diff --git a/src/FDM/JSBSim/math/FGCondition.cpp b/src/FDM/JSBSim/math/FGCondition.cpp index 02bcdf775..cfc4bae91 100644 --- a/src/FDM/JSBSim/math/FGCondition.cpp +++ b/src/FDM/JSBSim/math/FGCondition.cpp @@ -35,6 +35,7 @@ INCLUDES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #include "FGCondition.h" +#include namespace JSBSim { @@ -87,13 +88,14 @@ FGCondition::FGCondition(Element* element, FGPropertyManager* PropertyManager) : } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -//This constructor is called when there are no nested test groups inside the +// This constructor is called when there are no nested test groups inside the // condition FGCondition::FGCondition(string test, FGPropertyManager* PropertyManager) : PropertyManager(PropertyManager), isGroup(false) { string property1, property2, compare_string; + vector test_strings; InitializeConditionals(); @@ -103,20 +105,21 @@ FGCondition::FGCondition(string test, FGPropertyManager* PropertyManager) : Logic = elUndef; conditions.clear(); - unsigned int start = 0, end = 0; - start = test.find_first_not_of(" "); - end = test.find_first_of(" ", start+1); - property1 = test.substr(start,end-start); - start = test.find_first_not_of(" ",end); - end = test.find_first_of(" ",start+1); - conditional = test.substr(start,end-start); - start = test.find_first_not_of(" ",end); - end = test.find_first_of(" ",start+1); - property2 = test.substr(start,end-start); + test_strings = split(test, ' '); + if (test_strings.size() == 3) { + property1 = test_strings[0]; + conditional = test_strings[1]; + property2 = test_strings[2]; + } else { + cerr << endl << " Conditional test is invalid: \"" << test + << "\" has " << test_strings.size() << " elements in the " + << "test condition." << endl; + exit(-1); + } TestParam1 = PropertyManager->GetNode(property1, true); Comparison = mComparison[conditional]; - if (property2.find_first_not_of("-.0123456789eE") == string::npos) { + if (is_number(property2)) { TestValue = atof(property2.c_str()); } else { TestParam2 = PropertyManager->GetNode(property2, true); diff --git a/src/FDM/JSBSim/math/FGLocation.cpp b/src/FDM/JSBSim/math/FGLocation.cpp index 4eea80ad2..8aee82863 100644 --- a/src/FDM/JSBSim/math/FGLocation.cpp +++ b/src/FDM/JSBSim/math/FGLocation.cpp @@ -168,6 +168,26 @@ void FGLocation::SetPosition(double lon, double lat, double radius) //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +void FGLocation::SetPositionGeodetic(double lon, double lat, double height) +{ + mCacheValid = false; + + mGeodLat = lat; + mLon = lon; + GeodeticAltitude = height; + + initial_longitude = mLon; + + 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); + +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + void FGLocation::SetEllipse(double semimajor, double semiminor) { mCacheValid = false; diff --git a/src/FDM/JSBSim/math/FGLocation.h b/src/FDM/JSBSim/math/FGLocation.h index ddfbc5071..2ad5b87bf 100644 --- a/src/FDM/JSBSim/math/FGLocation.h +++ b/src/FDM/JSBSim/math/FGLocation.h @@ -233,6 +233,12 @@ public: @param radius distance from center of earth to vehicle in feet*/ void SetPosition(double lon, double lat, double radius); + /** Sets the longitude, latitude and the distance above the reference ellipsoid. + @param lon longitude in radians + @param lat GEODETIC latitude in radians + @param height distance above the reference ellipsoid to vehicle in feet*/ + void SetPositionGeodetic(double lon, double lat, double height); + /** Sets the semimajor and semiminor axis lengths for this planet. The eccentricity and flattening are calculated from the semimajor and semiminor axis lengths */ diff --git a/src/FDM/JSBSim/models/FGAerodynamics.cpp b/src/FDM/JSBSim/models/FGAerodynamics.cpp index 1280e0e8b..2721fbf09 100644 --- a/src/FDM/JSBSim/models/FGAerodynamics.cpp +++ b/src/FDM/JSBSim/models/FGAerodynamics.cpp @@ -318,6 +318,8 @@ bool FGAerodynamics::Load(Element *element) document = element; } + FGModel::Load(element); // Perform base class Load + DetermineAxisSystem(); // Detemine if Lift/Side/Drag, etc. is used. Debug(2); diff --git a/src/FDM/JSBSim/models/FGAircraft.cpp b/src/FDM/JSBSim/models/FGAircraft.cpp index 463e902a2..0d8c3ed79 100644 --- a/src/FDM/JSBSim/models/FGAircraft.cpp +++ b/src/FDM/JSBSim/models/FGAircraft.cpp @@ -152,6 +152,8 @@ bool FGAircraft::Load(Element* el) string element_name; Element* element; + FGModel::Load(el); + if (el->FindElement("wingarea")) WingArea = el->FindElementValueAsNumberConvertTo("wingarea", "FT2"); if (el->FindElement("wingspan")) diff --git a/src/FDM/JSBSim/models/FGBuoyantForces.cpp b/src/FDM/JSBSim/models/FGBuoyantForces.cpp index 341f16bd8..4803195ed 100644 --- a/src/FDM/JSBSim/models/FGBuoyantForces.cpp +++ b/src/FDM/JSBSim/models/FGBuoyantForces.cpp @@ -72,10 +72,6 @@ FGBuoyantForces::~FGBuoyantForces() for (unsigned int i=0; iFindElement("property"); - if (property_element) - cout << endl << " Declared properties" << endl << endl; - while (property_element) { - string interface_property_string = property_element->GetDataLine(); - - if (PropertyManager->HasNode(interface_property_string)) { - cout << " Property " << interface_property_string << - " is already defined." << endl; - } else { - double value=0.0; - if ( ! property_element->GetAttributeValue("value").empty()) - value = property_element->GetAttributeValueAsNumber("value"); - interface_properties.push_back(new double(value)); - interface_property_string = property_element->GetDataLine(); - PropertyManager->Tie(interface_property_string, - interface_properties.back()); - cout << " " << interface_property_string << - " (initial value: " << value << ")" << endl; - } - property_element = document->FindNextElement("property"); - } + FGModel::Load(element); // Perform base class Load gas_cell_element = document->FindElement("gas_cell"); while (gas_cell_element) { diff --git a/src/FDM/JSBSim/models/FGBuoyantForces.h b/src/FDM/JSBSim/models/FGBuoyantForces.h index b1a7ee291..7ef94b088 100644 --- a/src/FDM/JSBSim/models/FGBuoyantForces.h +++ b/src/FDM/JSBSim/models/FGBuoyantForces.h @@ -169,8 +169,6 @@ private: FGColumnVector3 vGasCellXYZ; FGColumnVector3 vXYZgasCell_arm; - vector interface_properties; - bool NoneDefined; void bind(void); diff --git a/src/FDM/JSBSim/models/FGExternalReactions.cpp b/src/FDM/JSBSim/models/FGExternalReactions.cpp index 0add9cf39..6bff2bb46 100755 --- a/src/FDM/JSBSim/models/FGExternalReactions.cpp +++ b/src/FDM/JSBSim/models/FGExternalReactions.cpp @@ -66,27 +66,10 @@ FGExternalReactions::FGExternalReactions(FGFDMExec* fdmex) : FGModel(fdmex) bool FGExternalReactions::Load(Element* el) { + FGModel::Load(el); // Call the base class Load() function to load interface properties. + Debug(2); - // Interface properties are all stored in the interface properties array. - // ToDo: Interface properties should not be created if they already exist. - // A check should be done prior to creation. This ought to make it easier - // to work with FlightGear, where some properties used in definitions may - // already have been created, but would not be seen when JSBSim is run - // in standalone mode. - - Element* property_element; - property_element = el->FindElement("property"); - while (property_element) { - double value=0.0; - if ( ! property_element->GetAttributeValue("value").empty()) - value = property_element->GetAttributeValueAsNumber("value"); - interface_properties.push_back(new double(value)); - string interface_property_string = property_element->GetDataLine(); - PropertyManager->Tie(interface_property_string, interface_properties.back()); - property_element = el->FindNextElement("property"); - } - // Parse force elements int index=0; @@ -107,8 +90,7 @@ FGExternalReactions::~FGExternalReactions() { for (unsigned int i=0; i interface_properties; bool NoneDefined; diff --git a/src/FDM/JSBSim/models/FGFCS.cpp b/src/FDM/JSBSim/models/FGFCS.cpp index 3c5b28ca5..22ca19d77 100644 --- a/src/FDM/JSBSim/models/FGFCS.cpp +++ b/src/FDM/JSBSim/models/FGFCS.cpp @@ -101,8 +101,6 @@ FGFCS::~FGFCS() unsigned int i; - for (i=0;iGetDefaultSteerAngle( GetDsCmd() ); } - // Cycle through the sensor, systems, autopilot, and flight control components - // Execute Sensors - for (i=0; iRun(); - // Execute Systems in order for (i=0; iRun(); @@ -527,7 +519,7 @@ bool FGFCS::Load(Element* el, SystemType systype) { string name, file, fname="", interface_property_string, parent_name; vector *Components; - Element *component_element, *property_element, *sensor_element; + Element *component_element, *sensor_element; Element *channel_element; Components=0; @@ -575,33 +567,15 @@ bool FGFCS::Load(Element* el, SystemType systype) if (document->GetName() == "flight_control") bindModel(); - // Interface properties from any autopilot, flight control, or other system are - // all stored in the interface properties array. - - property_element = document->FindElement("property"); - if (property_element && debug_lvl > 0) cout << endl << " Declared properties" << endl << endl; - while (property_element) { - interface_property_string = property_element->GetDataLine(); - if (PropertyManager->HasNode(interface_property_string)) { - cerr << " Property " << interface_property_string << " is already defined." << endl; - } else { - double value=0.0; - if ( ! property_element->GetAttributeValue("value").empty()) - value = property_element->GetAttributeValueAsNumber("value"); - interface_properties.push_back(new double(value)); - interface_property_string = property_element->GetDataLine(); - PropertyManager->Tie(interface_property_string, interface_properties.back()); - if (debug_lvl > 0) - cout << " " << interface_property_string << " (initial value: " << value << ")" << endl; - } - property_element = document->FindNextElement("property"); - } + 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. + Element* property_element = 0; + if (!fname.empty()) { property_element = el->FindElement("property"); if (property_element && debug_lvl > 0) cout << endl << " Overriding properties" << endl << endl; @@ -628,22 +602,6 @@ bool FGFCS::Load(Element* el, SystemType systype) } } - // Any sensor elements that are outside of a channel (in either the autopilot - // or the flight_control, or even any possible "system") are placed into the global - // "sensors" array, and are executed prior to any autopilot, flight control, or - // system. - - sensor_element = document->FindElement("sensor"); - while (sensor_element) { - try { - sensors.push_back(new FGSensor(this, sensor_element)); - } catch (string s) { - cerr << highint << fgred << endl << " " << s << endl; - return false; - } - sensor_element = document->FindNextElement("sensor"); - } - channel_element = document->FindElement("channel"); while (channel_element) { diff --git a/src/FDM/JSBSim/models/FGFCS.h b/src/FDM/JSBSim/models/FGFCS.h index 8aa9ca9ff..b026e4b1a 100644 --- a/src/FDM/JSBSim/models/FGFCS.h +++ b/src/FDM/JSBSim/models/FGFCS.h @@ -568,8 +568,6 @@ private: FCSCompVec Systems; FCSCompVec FCSComponents; FCSCompVec APComponents; - FCSCompVec sensors; - vector interface_properties; void bind(void); void bindModel(void); void bindThrottle(unsigned int); diff --git a/src/FDM/JSBSim/models/FGGroundReactions.cpp b/src/FDM/JSBSim/models/FGGroundReactions.cpp index 4638c1f39..1068d81e5 100644 --- a/src/FDM/JSBSim/models/FGGroundReactions.cpp +++ b/src/FDM/JSBSim/models/FGGroundReactions.cpp @@ -130,6 +130,8 @@ bool FGGroundReactions::Load(Element* el) FCS->AddGear(); // make the FCS aware of the landing gear contact_element = el->FindNextElement("contact"); } + + FGModel::Load(el); // Perform base class Load for (unsigned int i=0; ibind(); diff --git a/src/FDM/JSBSim/models/FGInput.cpp b/src/FDM/JSBSim/models/FGInput.cpp index 9c5c2259b..d7e2a2a51 100755 --- a/src/FDM/JSBSim/models/FGInput.cpp +++ b/src/FDM/JSBSim/models/FGInput.cpp @@ -114,67 +114,71 @@ bool FGInput::Run(void) if (line.size() == 0) break; // now parse individual line - token_start = line.find_first_not_of(" ", 0); - token_end = line.find_first_of(" ", token_start); - token = line.substr(token_start, token_end - token_start); + vector tokens = split(line,' '); + + string command="", argument="", str_value=""; + if (tokens.size() > 0) { + command = to_lower(tokens[0]); + if (tokens.size() > 1) { + argument = trim(tokens[1]); + if (tokens.size() > 2) { + str_value = trim(tokens[2]); + } + } + } - if (token == "set" || token == "SET" ) { // SET PROPERTY + if (command == "set") { // SET PROPERTY - token_start = line.find_first_not_of(" ", token_end); - token_end = line.find_first_of(" ", token_start); - token = line.substr(token_start, token_end-token_start); - node = PropertyManager->GetNode(token); - if (node == 0) socket->Reply("Unknown property\n"); + node = PropertyManager->GetNode(argument); + if (node == 0) + socket->Reply("Unknown property\n"); else { - token_start = line.find_first_not_of(" ", token_end); - token_end = line.find_first_of(" ", token_start); - token = line.substr(token_start, token_end-token_start); - value = atof(token.c_str()); + value = atof(str_value.c_str()); node->setDoubleValue(value); } + socket->Reply(""); - } else if (token == "get" || token == "GET") { // GET PROPERTY + } else if (command == "get") { // GET PROPERTY - token_start = line.find_first_not_of(" ", token_end); - if (token_start == string::npos) { + if (argument.size() == 0) { socket->Reply("No property argument supplied.\n"); break; - } else { - token = line.substr(token_start, line.size()-token_start); } try { - node = PropertyManager->GetNode(token); + node = PropertyManager->GetNode(argument); } catch(...) { socket->Reply("Badly formed property query\n"); break; } if (node == 0) { if (FDMExec->Holding()) { // if holding can query property list - string query = FDMExec->QueryPropertyCatalog(token); + string query = FDMExec->QueryPropertyCatalog(argument); socket->Reply(query); } else { socket->Reply("Must be in HOLD to search properties\n"); } } else if (node > 0) { - sprintf(buf, "%s = %12.6f\n", token.c_str(), node->getDoubleValue()); + sprintf(buf, "%s = %12.6f\n", argument.c_str(), node->getDoubleValue()); socket->Reply(buf); } - } else if (token == "hold" || token == "HOLD") { // PAUSE + } else if (command == "hold") { // PAUSE FDMExec->Hold(); + socket->Reply(""); - } else if (token == "resume" || token == "RESUME") { // RESUME + } else if (command == "resume") { // RESUME FDMExec->Resume(); + socket->Reply(""); - } else if (token == "quit" || token == "QUIT") { // QUIT + } else if (command == "quit") { // QUIT // close the socket connection socket->Reply(""); socket->Close(); - } else if (token == "info" || token == "INFO") { // INFO + } else if (command == "info") { // INFO // get info about the sim run and/or aircraft, etc. sprintf(buf, "%8.3f\0", State->Getsim_time()); @@ -184,7 +188,7 @@ bool FGInput::Run(void) info_string += "Simulation time: " + string(buf) + "\n"; socket->Reply(info_string); - } else if (token == "help" || token == "HELP") { // HELP + } else if (command == "help") { // HELP socket->Reply( " JSBSim Server commands:\n\n" diff --git a/src/FDM/JSBSim/models/FGMassBalance.cpp b/src/FDM/JSBSim/models/FGMassBalance.cpp index 967f0ff44..eae637335 100644 --- a/src/FDM/JSBSim/models/FGMassBalance.cpp +++ b/src/FDM/JSBSim/models/FGMassBalance.cpp @@ -96,6 +96,8 @@ bool FGMassBalance::Load(Element* el) string element_name = ""; double bixx, biyy, bizz, bixy, bixz, biyz; + FGModel::Load(el); // Perform base class Load. + bixx = biyy = bizz = bixy = bixz = biyz = 0.0; if (el->FindElement("ixx")) bixx = el->FindElementValueAsNumberConvertTo("ixx", "SLUG*FT2"); diff --git a/src/FDM/JSBSim/models/FGModel.cpp b/src/FDM/JSBSim/models/FGModel.cpp index 651f301ea..6ddf5ed37 100644 --- a/src/FDM/JSBSim/models/FGModel.cpp +++ b/src/FDM/JSBSim/models/FGModel.cpp @@ -99,6 +99,9 @@ FGModel::FGModel(FGFDMExec* fdmex) FGModel::~FGModel() { + for (unsigned int i=0; iFindElement("property"); + if (property_element && debug_lvl > 0) cout << endl << " Declared properties" << endl << endl; + while (property_element) { + interface_property_string = property_element->GetDataLine(); + if (PropertyManager->HasNode(interface_property_string)) { + cerr << " Property " << interface_property_string << " is already defined." << endl; + } else { + double value=0.0; + if ( ! property_element->GetAttributeValue("value").empty()) + value = property_element->GetAttributeValueAsNumber("value"); + interface_properties.push_back(new double(value)); + PropertyManager->Tie(interface_property_string, interface_properties.back()); + if (debug_lvl > 0) + cout << " " << interface_property_string << " (initial value: " << value << ")" << endl; + } + property_element = el->FindNextElement("property"); + } + + return true; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + bool FGModel::Run() { if (debug_lvl & 4) cout << "Entering Run() for model " << Name << endl; diff --git a/src/FDM/JSBSim/models/FGModel.h b/src/FDM/JSBSim/models/FGModel.h index a28c77897..cef01d5e3 100644 --- a/src/FDM/JSBSim/models/FGModel.h +++ b/src/FDM/JSBSim/models/FGModel.h @@ -44,6 +44,7 @@ INCLUDES #include #include +#include /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% DEFINITIONS @@ -93,12 +94,12 @@ public: /// Constructor FGModel(FGFDMExec*); /// Destructor - virtual ~FGModel(); + ~FGModel(); /** Loads this model. @param el a pointer to the element @return true if model is successfully loaded*/ - virtual bool Load(Element* el) {return true;} + virtual bool Load(Element* el); FGModel* NextModel; string Name; @@ -135,6 +136,8 @@ protected: FGPropagate* Propagate; FGAuxiliary* Auxiliary; FGPropertyManager* PropertyManager; + + vector interface_properties; }; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/FDM/JSBSim/models/FGPropulsion.cpp b/src/FDM/JSBSim/models/FGPropulsion.cpp index 859254a83..04ff6b40c 100644 --- a/src/FDM/JSBSim/models/FGPropulsion.cpp +++ b/src/FDM/JSBSim/models/FGPropulsion.cpp @@ -253,6 +253,8 @@ bool FGPropulsion::Load(Element* el) Debug(2); + FGModel::Load(el); // Perform base class Load. + Element* engine_element = el->FindElement("engine"); while (engine_element) { engine_filename = engine_element->GetAttributeValue("file"); diff --git a/src/FDM/JSBSim/models/flight_control/FGDeadBand.cpp b/src/FDM/JSBSim/models/flight_control/FGDeadBand.cpp index 6f458d161..745f8ad28 100644 --- a/src/FDM/JSBSim/models/flight_control/FGDeadBand.cpp +++ b/src/FDM/JSBSim/models/flight_control/FGDeadBand.cpp @@ -52,11 +52,24 @@ CLASS IMPLEMENTATION FGDeadBand::FGDeadBand(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element) { + string width_string; + + WidthPropertyNode = 0; + WidthPropertySign = 1.0; gain = 1.0; width = 0.0; - if (element->FindElement("width")) { - width = element->FindElementValueAsNumber("width"); + if ( element->FindElement("width") ) { + width_string = element->FindElementValue("width"); + if (!is_number(width_string)) { // property + if (width_string[0] == '-') { + WidthPropertySign = -1.0; + width_string.erase(0,1); + } + WidthPropertyNode = PropertyManager->GetNode(width_string); + } else { + width = element->FindElementValueAsNumber("width"); + } } if (element->FindElement("gain")) { @@ -80,6 +93,10 @@ bool FGDeadBand::Run(void ) { Input = InputNodes[0]->getDoubleValue() * InputSigns[0]; + if (WidthPropertyNode != 0) { + width = WidthPropertyNode->getDoubleValue() * WidthPropertySign; + } + if (Input < -width/2.0) { Output = (Input + width/2.0)*gain; } else if (Input > width/2.0) { @@ -121,7 +138,11 @@ void FGDeadBand::Debug(int from) if (debug_lvl & 1) { // Standard console startup message output if (from == 0) { // Constructor cout << " INPUT: " << InputNodes[0]->getName() << endl; - cout << " DEADBAND WIDTH: " << width << endl; + if (WidthPropertyNode != 0) { + cout << " DEADBAND WIDTH: " << WidthPropertyNode->GetName() << endl; + } else { + cout << " DEADBAND WIDTH: " << width << endl; + } cout << " GAIN: " << gain << endl; if (IsOutput) cout << " OUTPUT: " << OutputNode->getName() << endl; } diff --git a/src/FDM/JSBSim/models/flight_control/FGDeadBand.h b/src/FDM/JSBSim/models/flight_control/FGDeadBand.h index 8f8b595b5..d07b88cc4 100644 --- a/src/FDM/JSBSim/models/flight_control/FGDeadBand.h +++ b/src/FDM/JSBSim/models/flight_control/FGDeadBand.h @@ -97,6 +97,8 @@ public: private: double width; double gain; + FGPropertyManager* WidthPropertyNode; + double WidthPropertySign; void Debug(int from); }; diff --git a/src/FDM/JSBSim/models/flight_control/FGFCSComponent.cpp b/src/FDM/JSBSim/models/flight_control/FGFCSComponent.cpp index 7d4829357..7af390ef5 100644 --- a/src/FDM/JSBSim/models/flight_control/FGFCSComponent.cpp +++ b/src/FDM/JSBSim/models/flight_control/FGFCSComponent.cpp @@ -133,7 +133,7 @@ FGFCSComponent::FGFCSComponent(FGFCS* _fcs, Element* element) : fcs(_fcs) clip_el = element->FindElement("clipto"); if (clip_el) { clip_string = clip_el->FindElementValue("min"); - if (clip_string.find_first_not_of("+-.0123456789") != string::npos) { // it's a property + if (!is_number(clip_string)) { // it's a property if (clip_string[0] == '-') { clipMinSign = -1.0; clip_string.erase(0,1); @@ -143,7 +143,7 @@ FGFCSComponent::FGFCSComponent(FGFCS* _fcs, Element* element) : fcs(_fcs) clipmin = clip_el->FindElementValueAsNumber("min"); } clip_string = clip_el->FindElementValue("max"); - if (clip_string.find_first_not_of("+-.0123456789") != string::npos) { // it's a property + if (!is_number(clip_string)) { // it's a property if (clip_string[0] == '-') { clipMaxSign = -1.0; clip_string.erase(0,1); diff --git a/src/FDM/JSBSim/models/flight_control/FGFilter.cpp b/src/FDM/JSBSim/models/flight_control/FGFilter.cpp index d6b263a2d..997939238 100644 --- a/src/FDM/JSBSim/models/flight_control/FGFilter.cpp +++ b/src/FDM/JSBSim/models/flight_control/FGFilter.cpp @@ -105,7 +105,7 @@ void FGFilter::ReadFilterCoefficients(Element* element, int index) if ( element->FindElement(coefficient) ) { property_string = element->FindElementValue(coefficient); - if (property_string.find_first_not_of("+-.0123456789Ee") != string::npos) { // property + if (!is_number(property_string)) { // property if (property_string[0] == '-') { PropertySign[index] = -1.0; property_string.erase(0,1); diff --git a/src/FDM/JSBSim/models/flight_control/FGGain.cpp b/src/FDM/JSBSim/models/flight_control/FGGain.cpp index df0a0bf26..f8f73daf3 100644 --- a/src/FDM/JSBSim/models/flight_control/FGGain.cpp +++ b/src/FDM/JSBSim/models/flight_control/FGGain.cpp @@ -70,7 +70,7 @@ FGGain::FGGain(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element) if ( element->FindElement("gain") ) { gain_string = element->FindElementValue("gain"); - if (gain_string.find_first_not_of("+-.0123456789Ee") != string::npos) { // property + if (!is_number(gain_string)) { // property if (gain_string[0] == '-') { GainPropertySign = -1.0; gain_string.erase(0,1); @@ -207,7 +207,11 @@ void FGGain::Debug(int from) else cout << " INPUT: " << InputNodes[0]->getName() << endl; - cout << " GAIN: " << Gain << endl; + if (GainPropertyNode != 0) { + cout << " GAIN: " << GainPropertyNode->GetName() << endl; + } else { + cout << " GAIN: " << Gain << endl; + } if (IsOutput) cout << " OUTPUT: " << OutputNode->getName() << endl; if (Type == "AEROSURFACE_SCALE") { cout << " In/Out Mapping:" << endl; diff --git a/src/FDM/JSBSim/models/flight_control/FGPID.cpp b/src/FDM/JSBSim/models/flight_control/FGPID.cpp index 27be32c32..b8cced697 100755 --- a/src/FDM/JSBSim/models/flight_control/FGPID.cpp +++ b/src/FDM/JSBSim/models/flight_control/FGPID.cpp @@ -64,7 +64,7 @@ FGPID::FGPID(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element) if ( element->FindElement("kp") ) { kp_string = element->FindElementValue("kp"); - if (kp_string.find_first_not_of("+-.0123456789Ee") != string::npos) { // property + if (!is_number(kp_string)) { // property if (kp_string[0] == '-') { KpPropertySign = -1.0; kp_string.erase(0,1); @@ -77,7 +77,7 @@ FGPID::FGPID(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element) if ( element->FindElement("ki") ) { ki_string = element->FindElementValue("ki"); - if (ki_string.find_first_not_of("+-.0123456789Ee") != string::npos) { // property + if (!is_number(ki_string)) { // property if (ki_string[0] == '-') { KiPropertySign = -1.0; ki_string.erase(0,1); @@ -90,7 +90,7 @@ FGPID::FGPID(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element) if ( element->FindElement("kd") ) { kd_string = element->FindElementValue("kd"); - if (kd_string.find_first_not_of("+-.0123456789Ee") != string::npos) { // property + if (!is_number(kd_string)) { // property if (kd_string[0] == '-') { KdPropertySign = -1.0; kd_string.erase(0,1); diff --git a/src/FDM/JSBSim/models/flight_control/FGSensor.h b/src/FDM/JSBSim/models/flight_control/FGSensor.h index efbc5b7c5..63c217e20 100755 --- a/src/FDM/JSBSim/models/flight_control/FGSensor.h +++ b/src/FDM/JSBSim/models/flight_control/FGSensor.h @@ -119,7 +119,7 @@ class FGSensor : public FGFCSComponent { public: FGSensor(FGFCS* fcs, Element* element); - ~FGSensor(); + virtual ~FGSensor(); void SetFailLow(double val) {if (val > 0.0) fail_low = true; else fail_low = false;} void SetFailHigh(double val) {if (val > 0.0) fail_high = true; else fail_high = false;} diff --git a/src/FDM/JSBSim/models/flight_control/FGSwitch.cpp b/src/FDM/JSBSim/models/flight_control/FGSwitch.cpp index eee81becf..63d9e9bbc 100644 --- a/src/FDM/JSBSim/models/flight_control/FGSwitch.cpp +++ b/src/FDM/JSBSim/models/flight_control/FGSwitch.cpp @@ -97,7 +97,17 @@ FGSwitch::FGSwitch(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element) cerr << "Unrecognized LOGIC token " << logic << " in switch component: " << Name << endl; } for (unsigned int i=0; iGetNumDataLines(); i++) { - current_test->conditions.push_back(new FGCondition(test_element->GetDataLine(i), PropertyManager)); + string input_data = test_element->GetDataLine(i); + while (input_data[0] <= 32) { + input_data = input_data.erase(0,1); + if (input_data.size() <= 1) break; + } + if (input_data.size() <= 1) { + // Make sure there are no bad data lines that consist solely of whitespace + cerr << fgred << " Bad data line in switch component: " << Name << reset << endl; + continue; + } + current_test->conditions.push_back(new FGCondition(input_data, PropertyManager)); } condition_element = test_element->GetElement(); // retrieve condition groups @@ -115,8 +125,7 @@ FGSwitch::FGSwitch(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element) if (value.empty()) { cerr << "No VALUE supplied for switch component: " << Name << endl; } else { - if (value.find_first_not_of("-.0123456789eE") == string::npos) { - // if true (and execution falls into this block), "value" is a number. + if (is_number(value)) { current_test->OutputVal = atof(value.c_str()); } else { // "value" must be a property if execution passes to here.