]> git.mxchange.org Git - flightgear.git/commitdiff
latest changes for JSBSim (1.0 prerelease)
authorehofman <ehofman>
Sat, 13 Jun 2009 07:55:25 +0000 (07:55 +0000)
committerTim Moore <timoore@redhat.com>
Mon, 15 Jun 2009 08:29:44 +0000 (10:29 +0200)
31 files changed:
src/FDM/JSBSim/FGJSBBase.cpp
src/FDM/JSBSim/FGJSBBase.h
src/FDM/JSBSim/initialization/FGTrim.cpp
src/FDM/JSBSim/input_output/FGXMLParse.cpp
src/FDM/JSBSim/input_output/FGfdmSocket.cpp
src/FDM/JSBSim/input_output/string_utilities.h [new file with mode: 0644]
src/FDM/JSBSim/math/FGCondition.cpp
src/FDM/JSBSim/math/FGLocation.cpp
src/FDM/JSBSim/math/FGLocation.h
src/FDM/JSBSim/models/FGAerodynamics.cpp
src/FDM/JSBSim/models/FGAircraft.cpp
src/FDM/JSBSim/models/FGBuoyantForces.cpp
src/FDM/JSBSim/models/FGBuoyantForces.h
src/FDM/JSBSim/models/FGExternalReactions.cpp
src/FDM/JSBSim/models/FGExternalReactions.h
src/FDM/JSBSim/models/FGFCS.cpp
src/FDM/JSBSim/models/FGFCS.h
src/FDM/JSBSim/models/FGGroundReactions.cpp
src/FDM/JSBSim/models/FGInput.cpp
src/FDM/JSBSim/models/FGMassBalance.cpp
src/FDM/JSBSim/models/FGModel.cpp
src/FDM/JSBSim/models/FGModel.h
src/FDM/JSBSim/models/FGPropulsion.cpp
src/FDM/JSBSim/models/flight_control/FGDeadBand.cpp
src/FDM/JSBSim/models/flight_control/FGDeadBand.h
src/FDM/JSBSim/models/flight_control/FGFCSComponent.cpp
src/FDM/JSBSim/models/flight_control/FGFilter.cpp
src/FDM/JSBSim/models/flight_control/FGGain.cpp
src/FDM/JSBSim/models/flight_control/FGPID.cpp
src/FDM/JSBSim/models/flight_control/FGSensor.h
src/FDM/JSBSim/models/flight_control/FGSwitch.cpp

index b5e854d8f47c48daa55b1f4e12ad475aa4c26547..228fa8639237769cb0f677c5511a7caf004fa563 100644 (file)
@@ -35,6 +35,8 @@ HISTORY
 INCLUDES
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
+#define BASE
+
 #include "FGJSBBase.h"
 
 namespace JSBSim {
index 8ec700a1515ca0297ff311dd1b2c93628a18b887..7e56d5f5f5079d1574d12b24c9c96004a78ea9ba 100644 (file)
@@ -45,6 +45,8 @@ INCLUDES
 #include <cmath>
 #include <cstdlib>
 
+#include "input_output/string_utilities.h"
+
 using std::fabs;
 using std::string;
 
index 39e934f5bc3d84a9d0b212b22bec3e611db7fe79..ed69050cdea5f0ab9915238f1e297f7ad421263d 100644 (file)
@@ -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;
       }
index 5a57040a42d018caf6e2f5416965e8bae9d0f0af..b8923225fcf33d55a55e21c12d7fa2f2e24bbaf3 100755 (executable)
@@ -31,6 +31,7 @@ INCLUDES
 
 #include "FGXMLParse.h"
 #include <cstdlib>
+#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 <string> work_strings = split(working_string, '\n');
+    for (int i=0; i<work_strings.size(); i++) current_element->AddData(work_strings[i]);
   }
 
   current_element = current_element->GetParent();
index 1c390696f153e89d1743898dc70fb7e1decdd9e2..7fa7ae59fbc7678d646c93adf943030f68bd4de5 100644 (file)
@@ -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 (file)
index 0000000..38ab806
--- /dev/null
@@ -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 <vector>
+#include <ctype.h>
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+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 <string> 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<str.size(); i++) str[i] = toupper(str[i]);
+    return str;
+  }
+
+  string& to_lower(string& str)
+  {
+    for (int i=0; i<str.size(); i++) str[i] = tolower(str[i]);
+    return str;
+  }
+
+  bool is_number(string& str)
+  {
+    return (str.find_first_not_of("+-.0123456789Ee") == string::npos);
+  }
+
+  vector <string> split(string str, char d)
+  {
+    vector <string> 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
index 02bcdf7753189903f7dcca66f4b41638a1aa7344..cfc4bae91d9b653916a13ee57c3ce9ed57d3e61f 100644 (file)
@@ -35,6 +35,7 @@ INCLUDES
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
 #include "FGCondition.h"
+#include <vector>
 
 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 <string> 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);
index 4eea80ad2668d06bdb05be46d737711dcb938c5b..8aee82863f48846518c10616c40c55b0673a6795 100644 (file)
@@ -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;
index ddfbc5071a2a6c2b117e01fb93c7df321a582141..2ad5b87bfcc24ac614c7b4ca47f38dd41dfeafd8 100644 (file)
@@ -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 */
index 1280e0e8b8c13262d355e546b562ee8dc526f4b8..2721fbf09ec4e7a9e71d2415607142c590b36e1e 100644 (file)
@@ -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);
index 463e902a2512ecdf8dae4b322e4b3a7dea23d2e1..0d8c3ed7910228f40fc254b7f9fa2b593de6d85f 100644 (file)
@@ -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"))
index 341f16bd8c27e8abc2eebd204af09001de19b174..4803195edb1b0b2aa0e0864ccb466fe2298b6df8 100644 (file)
@@ -72,10 +72,6 @@ FGBuoyantForces::~FGBuoyantForces()
   for (unsigned int i=0; i<Cells.size(); i++) delete Cells[i];
   Cells.clear();
 
-  for (unsigned int i=0; i<interface_properties.size(); i++)
-    delete interface_properties[i];
-  interface_properties.clear();
-
   Debug(1);
 }
 
@@ -127,28 +123,7 @@ bool FGBuoyantForces::Load(Element *element)
     document = element;
   }
 
-  Element *property_element = document->FindElement("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) {
index b1a7ee2917b07297665cb9cf557e871415a60a6d..7ef94b088187b423d8bdfe8438cdb631d194be7d 100644 (file)
@@ -169,8 +169,6 @@ private:
   FGColumnVector3 vGasCellXYZ;
   FGColumnVector3 vXYZgasCell_arm;
 
-  vector <double*> interface_properties;
-
   bool NoneDefined;
 
   void bind(void);
index 0add9cf3962c0127e2a00cf8e9d048651aca16f2..6bff2bb46184e6fd05d5e6f9c1c3ef8f182221a1 100755 (executable)
@@ -66,26 +66,9 @@ FGExternalReactions::FGExternalReactions(FGFDMExec* fdmex) : FGModel(fdmex)
 
 bool FGExternalReactions::Load(Element* el)
 {
-  Debug(2);
+  FGModel::Load(el); // Call the base class Load() function to load interface properties.
 
-  // 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");
-  }
+  Debug(2);
 
   // Parse force elements
 
@@ -107,8 +90,7 @@ FGExternalReactions::~FGExternalReactions()
 {
   for (unsigned int i=0; i<Forces.size(); i++) delete Forces[i];
   Forces.clear();
-  for (unsigned int i=0; i<interface_properties.size(); i++) delete interface_properties[i];
-  interface_properties.clear();
+
   Debug(1);
 }
 
index f32cab28f46eb4f8d80335d4e66cf77ee8f65adb..60cca4440ba53c4123ead7c7669c64947cce3c6b 100755 (executable)
@@ -158,7 +158,6 @@ private:
   unsigned int numForces;
   FGColumnVector3 vTotalForces;
   FGColumnVector3 vTotalMoments;
-  vector <double*> interface_properties;
 
   bool NoneDefined;
 
index 3c5b28ca520d4385a5efcdd7dadbc9fe60e210d8..22ca19d77ee9892333698f3638762840e41cc615 100644 (file)
@@ -101,8 +101,6 @@ FGFCS::~FGFCS()
 
   unsigned int i;
 
-  for (i=0;i<sensors.size();i++) delete sensors[i];
-  sensors.clear();
   for (i=0;i<APComponents.size();i++) delete APComponents[i];
   APComponents.clear();
   for (i=0;i<FCSComponents.size();i++) delete FCSComponents[i];
@@ -110,8 +108,6 @@ FGFCS::~FGFCS()
   for (i=0;i<Systems.size();i++) delete Systems[i];
   Systems.clear();
 
-  for (unsigned int i=0; i<interface_properties.size(); i++) delete interface_properties[i];
-  interface_properties.clear();
 
   Debug(1);
 }
@@ -208,10 +204,6 @@ bool FGFCS::Run(void)
     SteerPosDeg[i] = gear->GetDefaultSteerAngle( GetDsCmd() );
   }
 
-  // Cycle through the sensor, systems, autopilot, and flight control components
-  // Execute Sensors
-  for (i=0; i<sensors.size(); i++) sensors[i]->Run();
-
   // Execute Systems in order
   for (i=0; i<Systems.size(); i++) Systems[i]->Run();
 
@@ -527,7 +519,7 @@ bool FGFCS::Load(Element* el, SystemType systype)
 {
   string name, file, fname="", interface_property_string, parent_name;
   vector <FGFCSComponent*> *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) {
   
index 8aa9ca9ffc750ce63083663079a29b293bf9d84b..b026e4b1a1ec99ce707ba857f5aabf6c660b607d 100644 (file)
@@ -568,8 +568,6 @@ private:
   FCSCompVec Systems;
   FCSCompVec FCSComponents;
   FCSCompVec APComponents;
-  FCSCompVec sensors;
-  vector <double*> interface_properties;
   void bind(void);
   void bindModel(void);
   void bindThrottle(unsigned int);
index 4638c1f3982ee12a0f4ffb10ccd5c70c2cc29600..1068d81e5838ce39e33c20d5c76fe8ce30b4a0cd 100644 (file)
@@ -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; i<lGear.size();i++) lGear[i]->bind();
 
index 9c5c2259b9c743d4ec53b25bf01b5563a52d944f..d7e2a2a517a0e1d175a52932115da2f6365d20e2 100755 (executable)
@@ -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 <string> 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"
index 967f0ff44d388838438b907878edda97f8906e63..eae63733523674de850efd750ec44bc1c52cde52 100644 (file)
@@ -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");
index 651f301eac300cd725f193a8ad5decede9f97602..6ddf5ed3799a4c709851b43871d7ea3539e8b769 100644 (file)
@@ -99,6 +99,9 @@ FGModel::FGModel(FGFDMExec* fdmex)
 
 FGModel::~FGModel()
 {
+  for (unsigned int i=0; i<interface_properties.size(); i++) delete interface_properties[i];
+  interface_properties.clear();
+
   if (debug_lvl & 2) cout << "Destroyed:    FGModel" << endl;
 }
 
@@ -137,6 +140,35 @@ bool FGModel::InitModel(void)
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
+bool FGModel::Load(Element* el)
+{
+  // Interface properties are all stored in the interface properties array.
+
+  string interface_property_string = "";
+
+  Element *property_element = el->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));
+      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;
index a28c7789711ed9ea6fe534ced950553b9156261e..cef01d5e39c279530acedacb0c095e3dd99edd29 100644 (file)
@@ -44,6 +44,7 @@ INCLUDES
 
 #include <iostream>
 #include <string>
+#include <vector>
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 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 <double*> interface_properties;
 };
 }
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index 859254a83cd4b97b25ff8525253f35e2f7ebcccd..04ff6b40c7412c5c3d2cd614d5c58c2289fcbb43 100644 (file)
@@ -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");
index 6f458d16187cff5a991f01cbd3075ce4fe406cc5..745f8ad281d5804fa14fa14ae82b0c2009ea7c35 100644 (file)
@@ -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;
     }
index 8f8b595b57a5983a517c36f2fd5bba4b028964ed..d07b88cc4fbaacb33ac0afef4808f8e220eb7015 100644 (file)
@@ -97,6 +97,8 @@ public:
 private:
   double width;
   double gain;
+  FGPropertyManager* WidthPropertyNode;
+  double WidthPropertySign;
 
   void Debug(int from);
 };
index 7d48293579a74fa9089a6baff291e17b495f82b5..7af390ef5549fd92759286deb823b3737f2173db 100644 (file)
@@ -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);
index d6b263a2dfa6f30c4bf6a203ef38261baf99f731..99793923871efc2c86870efa0de2613352a62f14 100644 (file)
@@ -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);
index df0a0bf264c9c24acb67b9d3a88fc1f0aca8af1c..f8f73daf38d0bc5171ee75140e14555514ac7b2d 100644 (file)
@@ -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;
index 27be32c3271acd41e0028ae436e542e57cfbfdb2..b8cced69717551163fea61ab389349732f896771 100755 (executable)
@@ -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);
index efbc5b7c5d079912ca7fb51fdafe0876a3054419..63c217e2054b1dbc8b3cdd3ce7e572ba8b08491f 100755 (executable)
@@ -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;}
index eee81becf83eaea5f90eeb58b1643a88978290cd..63d9e9bbcd54ed1a07a8ecbfbbcf5c95823f0181 100644 (file)
@@ -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; i<test_element->GetNumDataLines(); 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.