]> git.mxchange.org Git - flightgear.git/commitdiff
Synchronized with JSBSim/CVS.
authorAnders Gidenstam <anders@gidenstam.org>
Tue, 11 Jun 2013 20:06:35 +0000 (22:06 +0200)
committerAnders Gidenstam <anders@gidenstam.org>
Tue, 11 Jun 2013 20:14:51 +0000 (22:14 +0200)
58 files changed:
src/FDM/JSBSim/CMakeLists.txt
src/FDM/JSBSim/FGFDMExec.cpp
src/FDM/JSBSim/FGFDMExec.h
src/FDM/JSBSim/FGJSBBase.cpp
src/FDM/JSBSim/JSBSim.cxx
src/FDM/JSBSim/JSBSim.hxx
src/FDM/JSBSim/initialization/FGLinearization.cpp [new file with mode: 0644]
src/FDM/JSBSim/initialization/FGLinearization.h [new file with mode: 0644]
src/FDM/JSBSim/initialization/FGSimplexTrim.cpp
src/FDM/JSBSim/initialization/FGSimplexTrim.h
src/FDM/JSBSim/initialization/FGTrimmer.cpp
src/FDM/JSBSim/initialization/FGTrimmer.h
src/FDM/JSBSim/input_output/FGGroundCallback.h
src/FDM/JSBSim/input_output/FGOutputType.cpp
src/FDM/JSBSim/input_output/FGOutputType.h
src/FDM/JSBSim/input_output/FGPropertyManager.cpp
src/FDM/JSBSim/input_output/FGPropertyManager.h
src/FDM/JSBSim/input_output/FGScript.cpp
src/FDM/JSBSim/input_output/FGScript.h
src/FDM/JSBSim/math/FGCondition.cpp
src/FDM/JSBSim/math/FGFunction.cpp
src/FDM/JSBSim/math/FGFunction.h
src/FDM/JSBSim/math/FGNelderMead.cpp
src/FDM/JSBSim/math/FGNelderMead.h
src/FDM/JSBSim/math/FGPropertyValue.cpp
src/FDM/JSBSim/math/FGPropertyValue.h
src/FDM/JSBSim/math/FGStateSpace.cpp
src/FDM/JSBSim/math/FGStateSpace.h
src/FDM/JSBSim/math/FGTable.cpp
src/FDM/JSBSim/math/FGTable.h
src/FDM/JSBSim/models/FGAerodynamics.cpp
src/FDM/JSBSim/models/FGAtmosphere.cpp
src/FDM/JSBSim/models/FGAuxiliary.cpp
src/FDM/JSBSim/models/FGAuxiliary.h
src/FDM/JSBSim/models/FGFCS.cpp
src/FDM/JSBSim/models/FGFCSChannel.h
src/FDM/JSBSim/models/FGGasCell.cpp
src/FDM/JSBSim/models/FGGasCell.h
src/FDM/JSBSim/models/FGInput.cpp
src/FDM/JSBSim/models/FGLGear.cpp
src/FDM/JSBSim/models/FGOutput.cpp
src/FDM/JSBSim/models/FGOutput.h
src/FDM/JSBSim/models/FGPropagate.cpp
src/FDM/JSBSim/models/FGPropagate.h
src/FDM/JSBSim/models/flight_control/FGActuator.cpp
src/FDM/JSBSim/models/flight_control/FGActuator.h
src/FDM/JSBSim/models/flight_control/FGDeadBand.h
src/FDM/JSBSim/models/flight_control/FGFCSComponent.cpp
src/FDM/JSBSim/models/flight_control/FGFCSComponent.h
src/FDM/JSBSim/models/flight_control/FGFilter.h
src/FDM/JSBSim/models/flight_control/FGGain.h
src/FDM/JSBSim/models/flight_control/FGPID.cpp
src/FDM/JSBSim/models/flight_control/FGPID.h
src/FDM/JSBSim/models/flight_control/FGSensor.h
src/FDM/JSBSim/models/flight_control/FGSwitch.h
src/FDM/JSBSim/models/propulsion/FGRocket.cpp
src/FDM/JSBSim/models/propulsion/FGRotor.h
src/FDM/JSBSim/models/propulsion/FGTank.cpp

index b136ccb7dbd4fc628bf0ecc1b3e6381bece8057f..85c1fef7c244b209bddbe4e2a4c681210ed6ca7d 100644 (file)
@@ -9,6 +9,7 @@ set(HEADERS
     initialization/FGTrimAxis.h
     initialization/FGSimplexTrim.h
     initialization/FGTrimmer.h
+    initialization/FGLinearization.h
     input_output/FGXMLParse.h
     input_output/FGXMLFileRead.h
     input_output/FGPropertyManager.h
@@ -100,6 +101,7 @@ set(SOURCES
     initialization/FGTrimAxis.cpp
     initialization/FGSimplexTrim.cpp
     initialization/FGTrimmer.cpp
+    initialization/FGLinearization.cpp
     input_output/FGGroundCallback.cpp
     input_output/FGPropertyManager.cpp
     input_output/FGScript.cpp
index e8bb6a1b38fedc244eb0891987534b5968e3f2c6..6f75b26c087d5464507654aa27a1c96e3fe60aaa 100644 (file)
@@ -65,6 +65,7 @@ INCLUDES
 #include "models/FGOutput.h"
 #include "initialization/FGInitialCondition.h"
 #include "initialization/FGSimplexTrim.h"
+#include "initialization/FGLinearization.h"
 #include "input_output/FGPropertyManager.h"
 #include "input_output/FGScript.h"
 
@@ -72,7 +73,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGFDMExec.cpp,v 1.145 2012/11/11 18:43:07 bcoconni Exp $";
+static const char *IdSrc = "$Id: FGFDMExec.cpp,v 1.148 2013/06/10 01:46:27 jberndt Exp $";
 static const char *IdHdr = ID_FDMEXEC;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -133,7 +134,8 @@ FGFDMExec::FGFDMExec(FGPropertyManager* root, unsigned int* fdmctr) : Root(root)
   // Prepare FDMctr for the next child FDM id
   (*FDMctr)++;       // instance. "child" instances are loaded last.
 
-  instance = Root->GetNode("/fdm/jsbsim",IdFDM,true);
+  FGPropertyNode* instanceRoot = Root->GetNode("/fdm/jsbsim",IdFDM,true);
+  instance = new FGPropertyManager(instanceRoot);
   Debug(0);
   // this is to catch errors in binding member functions to the property tree.
   try {
@@ -153,6 +155,7 @@ FGFDMExec::FGFDMExec(FGPropertyManager* root, unsigned int* fdmctr) : Root(root)
 //  instance->Tie("simulation/do_trim_analysis", this, (iPMF)0, &FGFDMExec::DoTrimAnalysis, false);
   instance->Tie("simulation/do_simple_trim", this, (iPMF)0, &FGFDMExec::DoTrim, false);
   instance->Tie("simulation/do_simplex_trim", this, (iPMF)0, &FGFDMExec::DoSimplexTrim);
+  instance->Tie("simulation/do_linearization", this, (iPMF)0, &FGFDMExec::DoLinearization);
   instance->Tie("simulation/reset", this, (iPMF)0, &FGFDMExec::ResetToInitialConditions, false);
   instance->Tie("simulation/randomseed", this, (iPMF)0, &FGFDMExec::SRand, false);
   instance->Tie("simulation/terminate", (int *)&Terminate);
@@ -161,56 +164,46 @@ FGFDMExec::FGFDMExec(FGPropertyManager* root, unsigned int* fdmctr) : Root(root)
   instance->Tie("simulation/frame", (int *)&Frame, false);
 
   // simplex trim properties
-  instance->SetDouble("trim/solver/rtol",0.0001);
-  instance->SetDouble("trim/solver/speed",2);
-  instance->SetDouble("trim/solver/abstol",0.001);
-  instance->SetDouble("trim/solver/iterMax",2000);
-  instance->SetInt("trim/solver/debugLevel",0);
-  instance->SetDouble("trim/solver/random",0);
-  instance->SetBool("trim/solver/showSimplex",false);
-//  instance->SetBool("trim/solver/showConvergence",true);
-  instance->SetBool("trim/solver/pause",false);
-
-  instance->SetDouble("trim/solver/throttleGuess",0.50);
-  instance->SetDouble("trim/solver/throttleMin",0.0);
-  instance->SetDouble("trim/solver/throttleMax",1.0);
-//  instance->SetDouble("trim/solver/throttleInitialStepSize",0.1);
-  instance->SetDouble("trim/solver/throttleStep",0.1);
-
-  instance->SetDouble("trim/solver/aileronGuess",0);
-  instance->SetDouble("trim/solver/aileronMin",-1.00);
-  instance->SetDouble("trim/solver/aileronMax",1.00);
-//  instance->SetDouble("trim/solver/aileronInitialStepSize",0.1);
-  instance->SetDouble("trim/solver/aileronStep",0.1);
-
-  instance->SetDouble("trim/solver/rudderGuess",0);
-  instance->SetDouble("trim/solver/rudderMin",-1.00);
-  instance->SetDouble("trim/solver/rudderMax",1.00);
-//  instance->SetDouble("trim/solver/rudderInitialStepSize",0.1);
-  instance->SetDouble("trim/solver/rudderStep",0.1);
-
-  instance->SetDouble("trim/solver/elevatorGuess",-0.1);
-  instance->SetDouble("trim/solver/elevatorMin",-1.0);
-  instance->SetDouble("trim/solver/elevatorMax",1.0);
-//  instance->SetDouble("trim/solver/elevatorInitialStepSize",0.1);
-  instance->SetDouble("trim/solver/elevatorStep",0.1);
-
-  instance->SetDouble("trim/solver/alphaGuess",0.05);
-  instance->SetDouble("trim/solver/alphaMin",-0.1);
-  instance->SetDouble("trim/solver/alphaMax",.18);
-//  instance->SetDouble("trim/solver/alphaInitialStepSize",0.1);
-  instance->SetDouble("trim/solver/alphaStep",0.05);
-
-  instance->SetDouble("trim/solver/betaGuess",0);
-  instance->SetDouble("trim/solver/betaMin",-0.05);
-  instance->SetDouble("trim/solver/betaMax",0.05);
-//  instance->SetDouble("trim/solver/betaInitialStepSize",0.1);
-  instance->SetDouble("trim/solver/betaStep",0.05);
-
-  instance->SetBool("trim/solver/showConvergeStatus",true);
-//  instance->SetBool("trim/solver/pause",true);
-  instance->SetBool("trim/solver/variablePropPitch",false);
-//  instance->SetBool("trim/solver/debugLevel",0);
+  instanceRoot->SetDouble("trim/solver/rtol",0.0001);
+  instanceRoot->SetDouble("trim/solver/speed",2);
+  instanceRoot->SetDouble("trim/solver/abstol",0.001);
+  instanceRoot->SetDouble("trim/solver/iterMax",2000);
+  instanceRoot->SetInt("trim/solver/debugLevel",0);
+  instanceRoot->SetDouble("trim/solver/random",0);
+  instanceRoot->SetBool("trim/solver/showSimplex",false);
+  instanceRoot->SetBool("trim/solver/showConvergence",false);
+  instanceRoot->SetBool("trim/solver/pause",false);
+  instanceRoot->SetBool("trim/solver/variablePropPitch",false);
+
+  instanceRoot->SetDouble("trim/solver/throttleGuess",0.50);
+  instanceRoot->SetDouble("trim/solver/throttleMin",0.0);
+  instanceRoot->SetDouble("trim/solver/throttleMax",1.0);
+  instanceRoot->SetDouble("trim/solver/throttleStep",0.1);
+
+  instanceRoot->SetDouble("trim/solver/aileronGuess",0);
+  instanceRoot->SetDouble("trim/solver/aileronMin",-1.00);
+  instanceRoot->SetDouble("trim/solver/aileronMax",1.00);
+  instanceRoot->SetDouble("trim/solver/aileronStep",0.1);
+
+  instanceRoot->SetDouble("trim/solver/rudderGuess",0);
+  instanceRoot->SetDouble("trim/solver/rudderMin",-1.00);
+  instanceRoot->SetDouble("trim/solver/rudderMax",1.00);
+  instanceRoot->SetDouble("trim/solver/rudderStep",0.1);
+
+  instanceRoot->SetDouble("trim/solver/elevatorGuess",-0.1);
+  instanceRoot->SetDouble("trim/solver/elevatorMin",-1.0);
+  instanceRoot->SetDouble("trim/solver/elevatorMax",1.0);
+  instanceRoot->SetDouble("trim/solver/elevatorStep",0.1);
+
+  instanceRoot->SetDouble("trim/solver/alphaGuess",0.05);
+  instanceRoot->SetDouble("trim/solver/alphaMin",-0.1);
+  instanceRoot->SetDouble("trim/solver/alphaMax",.18);
+  instanceRoot->SetDouble("trim/solver/alphaStep",0.05);
+
+  instanceRoot->SetDouble("trim/solver/betaGuess",0);
+  instanceRoot->SetDouble("trim/solver/betaMin",-0.1);
+  instanceRoot->SetDouble("trim/solver/betaMax",0.1);
+  instanceRoot->SetDouble("trim/solver/betaStep",0.0001);
 
   Constructing = false;
 }
@@ -223,6 +216,8 @@ FGFDMExec::~FGFDMExec()
     Unbind();
     DeAllocate();
 
+    delete instance;
+
     if (IdFDM == 0) { // Meaning this is no child FDM
       if(Root != 0) {
          if(StandAlone)
@@ -922,7 +917,7 @@ bool FGFDMExec::LoadModel(const string& model, bool addModelToPath)
   if (result) {
     struct PropertyCatalogStructure masterPCS;
     masterPCS.base_string = "";
-    masterPCS.node = (FGPropertyManager*)Root;
+    masterPCS.node = Root->GetNode();
     BuildPropertyCatalog(&masterPCS);
   }
 
@@ -944,6 +939,7 @@ void FGFDMExec::BuildPropertyCatalog(struct PropertyCatalogStructure* pcs)
   int node_idx = 0;
 
   for (int i=0; i<pcs->node->nChildren(); i++) {
+    string access="";
     pcsNew->base_string = pcs->base_string + "/" + pcs->node->getChild(i)->getName();
     node_idx = pcs->node->getChild(i)->getIndex();
     if (node_idx != 0) {
@@ -953,9 +949,11 @@ void FGFDMExec::BuildPropertyCatalog(struct PropertyCatalogStructure* pcs)
       if (pcsNew->base_string.substr(0,12) == string("/fdm/jsbsim/")) {
         pcsNew->base_string = pcsNew->base_string.erase(0,12);
       }
-      PropertyCatalog.push_back(pcsNew->base_string);
+      if (pcs->node->getChild(i)->getAttribute(SGPropertyNode::READ)) access="R";
+      if (pcs->node->getChild(i)->getAttribute(SGPropertyNode::WRITE)) access+="W";
+      PropertyCatalog.push_back(pcsNew->base_string+" ("+access+")");
     } else {
-      pcsNew->node = (FGPropertyManager*)pcs->node->getChild(i);
+      pcsNew->node = (FGPropertyNode*)pcs->node->getChild(i);
       BuildPropertyCatalog(pcsNew);
     }
   }
@@ -1193,8 +1191,20 @@ void FGFDMExec::DoSimplexTrim(int mode)
   FGSimplexTrim trim(this, (JSBSim::TrimMode)mode);
   sim_time = saved_time;
   Setsim_time(saved_time);
+  std::cout << "dT: " << dT << std::endl;
 }
 
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGFDMExec::DoLinearization(int mode)
+{
+  double saved_time;
+  if (Constructing) return;
+  saved_time = sim_time;
+  FGLinearization lin(this,mode);
+  sim_time = saved_time;
+  Setsim_time(saved_time);
+}
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
index 2192e11ec3d33aad70947bdc69443e8dd7f9252e..833bf41818e6a27d549e7384235c5222d75c926c 100644 (file)
@@ -56,7 +56,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_FDMEXEC "$Id: FGFDMExec.h,v 1.80 2012/10/25 04:56:57 jberndt Exp $"
+#define ID_FDMEXEC "$Id: FGFDMExec.h,v 1.83 2013/06/10 01:46:27 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -179,7 +179,7 @@ CLASS DOCUMENTATION
                                 property actually maps toa function call of DoTrim().
 
     @author Jon S. Berndt
-    @version $Revision: 1.80 $
+    @version $Revision: 1.83 $
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -392,13 +392,14 @@ public:
   /** Retrieves the value of a property.
       @param property the name of the property
       @result the value of the specified property */
-  inline double GetPropertyValue(const string& property) {return instance->GetDouble(property);}
+  inline double GetPropertyValue(const string& property)
+  { return instance->GetNode()->GetDouble(property); }
 
   /** Sets a property value.
       @param property the property to be set
       @param value the value to set the property to */
   inline void SetPropertyValue(const string& property, double value) {
-    instance->SetDouble(property, value);
+    instance->GetNode()->SetDouble(property, value);
   }
 
   /// Returns the model name.
@@ -448,12 +449,13 @@ public:
   /** Sets (or overrides) the output filename
       @param fname the name of the file to output data to
       @return true if successful, false if there is no output specified for the flight model */
-  bool SetOutputFileName(const string& fname) { return Output->SetOutputName(0, fname); }
+  bool SetOutputFileName(const int n, const string& fname) { return Output->SetOutputName(n, fname); }
 
   /** Retrieves the current output filename.
-      @return the name of the output file for the first output specified by the flight model.
+      @param n index of file
+      @return the name of the output file for the output specified by the flight model.
               If none is specified, the empty string is returned. */
-  string GetOutputFileName(void) const { return Output->GetOutputName(0); }
+  string GetOutputFileName(int n) const { return Output->GetOutputName(n); }
 
   /** Executes trimming in the selected mode.
   *   @param mode Specifies how to trim:
@@ -467,6 +469,11 @@ public:
   void DoTrim(int mode);
   void DoSimplexTrim(int mode);
 
+  /** Executes linearization with state-space output
+   * You must trim first to get an accurate state-space model
+   */
+  void DoLinearization(int mode);
+
   /// Disables data logging to all outputs.
   void DisableOutput(void) { Output->Disable(); }
   /// Enables data logging to all outputs.
@@ -490,7 +497,7 @@ public:
     /// Name of the property.
     string base_string;
     /// The node for the property.
-    FGPropertyManager *node;
+    FGPropertyNode_ptr node;
   };
 
   /** Builds a catalog of properties.
index ea646b4d758b80c44b4d09fa7f9909a5b62bd655..7a2ad6714e542e0aab58ad9bc56b8c37d8d22387 100644 (file)
@@ -44,7 +44,7 @@ INCLUDES
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGJSBBase.cpp,v 1.35 2012/03/25 11:05:36 bcoconni Exp $";
+static const char *IdSrc = "$Id: FGJSBBase.cpp,v 1.36 2013/01/25 13:39:11 jberndt Exp $";
 static const char *IdHdr = ID_JSBBASE;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -106,7 +106,7 @@ const double FGJSBBase::kgtolb = 2.20462;
 const double FGJSBBase::kgtoslug = 0.06852168;
 
 const string FGJSBBase::needed_cfg_version = "2.0";
-const string FGJSBBase::JSBSim_version = "1.0 "__DATE__" "__TIME__;
+const string FGJSBBase::JSBSim_version = "1.0 " __DATE__ " " __TIME__ ;
 
 std::queue <FGJSBBase::Message> FGJSBBase::Messages;
 FGJSBBase::Message FGJSBBase::localMsg;
index b71d8700c18f86dd7fc0844b2ab4bb0482b7396a..9ab5a192b101948914b253045de6239f17a45125 100644 (file)
@@ -90,9 +90,9 @@ public:
 
   /** Get the altitude above sea level dependent on the location. */
   virtual double GetAltitude(const FGLocation& l) const {
-    double pt[3] = { SG_FEET_TO_METER*l(eX),
-                     SG_FEET_TO_METER*l(eY),
-                     SG_FEET_TO_METER*l(eZ) };
+    double pt[3] = { SG_FEET_TO_METER*l(FGJSBBase::eX),
+                     SG_FEET_TO_METER*l(FGJSBBase::eY),
+                     SG_FEET_TO_METER*l(FGJSBBase::eZ) };
     double lat, lon, alt;
     sgCartToGeod( pt, &lat, &lon, &alt);
     return alt * SG_METER_TO_FEET;
@@ -102,7 +102,7 @@ public:
   virtual double GetAGLevel(double t, const FGLocation& l,
                             FGLocation& cont, FGColumnVector3& n,
                             FGColumnVector3& v, FGColumnVector3& w) const {
-    double loc_cart[3] = { l(eX), l(eY), l(eZ) };
+    double loc_cart[3] = { l(FGJSBBase::eX), l(FGJSBBase::eY), l(FGJSBBase::eZ) };
     double contact[3], normal[3], vel[3], angularVel[3], agl = 0;
     mInterface->get_agl_ft(t, loc_cart, SG_METER_TO_FEET*2, contact, normal,
                            vel, angularVel, &agl);
@@ -114,7 +114,7 @@ public:
   }
 
   virtual double GetTerrainGeoCentRadius(double t, const FGLocation& l) const {
-    double loc_cart[3] = { l(eX), l(eY), l(eZ) };
+    double loc_cart[3] = { l(FGJSBBase::eX), l(FGJSBBase::eY), l(FGJSBBase::eZ) };
     double contact[3], normal[3], vel[3], angularVel[3], agl = 0;
     mInterface->get_agl_ft(t, loc_cart, SG_METER_TO_FEET*2, contact, normal,
                            vel, angularVel, &agl);
@@ -192,7 +192,8 @@ FGJSBsim::FGJSBsim( double dt )
         }
     }
 
-    fdmex = new FGFDMExec( (FGPropertyManager*)globals->get_props() );
+    PropertyManager = new FGPropertyManager( (FGPropertyNode*)globals->get_props() );
+    fdmex = new FGFDMExec( PropertyManager );
 
     // Register ground callback.
     fdmex->SetGroundCallback( new FGFSGroundCallback(this) );
@@ -363,6 +364,7 @@ FGJSBsim::FGJSBsim( double dt )
 FGJSBsim::~FGJSBsim(void)
 {
   delete fdmex;
+  delete PropertyManager;
 }
 
 /******************************************************************************/
index 8471ba1b4ca3e2201392fff11371174cbeaa1922..ebb80c83ed9b65ce59ea077f03d4782206028229 100644 (file)
@@ -71,6 +71,7 @@ class FGOutput;
 class FGInitialCondition;
 class FGLocation;
 class FGAccelerations;
+class FGPropertyManager;
 }
 
 // Adding it here will cause a namespace clash in FlightGear -EMH-
@@ -235,6 +236,7 @@ private:
     JSBSim::FGGroundReactions* GroundReactions;
     JSBSim::FGInertial*        Inertial;
     JSBSim::FGAccelerations*   Accelerations;
+    JSBSim::FGPropertyManager* PropertyManager;
 
     int runcount;
     double trim_elev;
diff --git a/src/FDM/JSBSim/initialization/FGLinearization.cpp b/src/FDM/JSBSim/initialization/FGLinearization.cpp
new file mode 100644 (file)
index 0000000..c5d9caa
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * FGLinearization.cpp
+ * Copyright (C) James Goppert 2011 <james.goppert@gmail.com>
+ *
+ * FGLinearization.h 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.
+ *
+ * FGLinearization.h 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "FGLinearization.h"
+#include <ctime>
+
+namespace JSBSim {
+
+// TODO make FGLinearization have X,U,Y selectable by xml config file
+
+FGLinearization::FGLinearization(FGFDMExec * fdm, int mode)
+{
+    std::cout << "\nlinearization: " << std::endl;
+    std::clock_t time_start=clock(), time_linDone;
+    FGStateSpace ss(fdm);
+
+    ss.x.add(new FGStateSpace::Vt);
+    ss.x.add(new FGStateSpace::Alpha);
+    ss.x.add(new FGStateSpace::Theta);
+    ss.x.add(new FGStateSpace::Q);
+
+    // get propulsion pointer to determine type/ etc.
+    FGEngine * engine0 = fdm->GetPropulsion()->GetEngine(0);
+    FGThruster * thruster0 = engine0->GetThruster();
+
+    if (thruster0->GetType()==FGThruster::ttPropeller)
+    {
+        ss.x.add(new FGStateSpace::Rpm0);
+        // TODO add variable prop pitch property
+        // if (variablePropPitch) ss.x.add(new FGStateSpace::PropPitch);
+        int numEngines = fdm->GetPropulsion()->GetNumEngines();
+        if (numEngines>1) ss.x.add(new FGStateSpace::Rpm1);
+        if (numEngines>2) ss.x.add(new FGStateSpace::Rpm2);
+        if (numEngines>3) ss.x.add(new FGStateSpace::Rpm3);
+        if (numEngines>4) {
+            std::cerr << "more than 4 engines not currently handled" << std::endl;
+        }
+    }
+    ss.x.add(new FGStateSpace::Beta);
+    ss.x.add(new FGStateSpace::Phi);
+    ss.x.add(new FGStateSpace::P);
+    ss.x.add(new FGStateSpace::Psi);
+    ss.x.add(new FGStateSpace::R);
+    ss.x.add(new FGStateSpace::Latitude);
+    ss.x.add(new FGStateSpace::Longitude);
+    ss.x.add(new FGStateSpace::Alt);
+
+    ss.u.add(new FGStateSpace::ThrottleCmd);
+    ss.u.add(new FGStateSpace::DaCmd);
+    ss.u.add(new FGStateSpace::DeCmd);
+    ss.u.add(new FGStateSpace::DrCmd);
+
+    // state feedback
+    ss.y = ss.x;
+
+    std::vector< std::vector<double> > A,B,C,D;
+    std::vector<double> x0 = ss.x.get(), u0 = ss.u.get();
+    std::vector<double> y0 = x0; // state feedback
+    std::cout << ss << std::endl;
+
+    ss.linearize(x0,u0,y0,A,B,C,D);
+
+    int width=10;
+    std::cout.precision(3);
+    std::cout
+        << std::fixed
+        << std::right
+        << "\nA=\n" << std::setw(width) << A
+        << "\nB=\n" << std::setw(width) << B
+        << "\nC=\n" << std::setw(width) << C
+        << "\n* note: C should be identity, if not, indicates problem with model"
+        << "\nD=\n" << std::setw(width) << D
+        << std::endl;
+
+    // write scicoslab file
+    std::string aircraft = fdm->GetAircraft()->GetAircraftName();
+    std::ofstream scicos(std::string(aircraft+"_lin.sce").c_str());
+    scicos.precision(10);
+    width=20;
+    scicos
+    << std::scientific
+    << aircraft << ".x0=..\n" << std::setw(width) << x0 << ";\n"
+    << aircraft << ".u0=..\n" << std::setw(width) << u0 << ";\n"
+    << aircraft << ".sys = syslin('c',..\n"
+    << std::setw(width) << A << ",..\n"
+    << std::setw(width) << B << ",..\n"
+    << std::setw(width) << C << ",..\n"
+    << std::setw(width) << D << ");\n"
+    << aircraft << ".tfm = ss2tf(" << aircraft << ".sys);\n"
+    << std::endl;
+
+    time_linDone = std::clock();
+    std::cout << "\nlinearization computation time: " << (time_linDone - time_start)/double(CLOCKS_PER_SEC) << " s\n" << std::endl;
+}
+
+
+} // JSBSim
+
+// vim:ts=4:sw=4
diff --git a/src/FDM/JSBSim/initialization/FGLinearization.h b/src/FDM/JSBSim/initialization/FGLinearization.h
new file mode 100644 (file)
index 0000000..e267544
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * FGLinearization.h
+ * Copyright (C) James Goppert 2010 <james.goppert@gmail.com>
+ *
+ * FGLinearization.h 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.
+ *
+ * FGLinearization.h 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef FGLinearization_H_
+#define FGLinearization_H_
+
+#include "initialization/FGTrimmer.h"
+#include "math/FGStateSpace.h"
+#include <iomanip>
+#include <fstream>
+#include "models/FGAircraft.h"
+#include "models/propulsion/FGEngine.h"
+#include "models/propulsion/FGTurbine.h"
+#include "models/propulsion/FGTurboProp.h"
+#include "math/FGNelderMead.h"
+#include <stdexcept>
+#include <fstream>
+#include <cstdlib>
+
+namespace JSBSim {
+
+class FGLinearization
+{
+public:
+    FGLinearization(FGFDMExec * fdmPtr, int mode);
+};
+
+} // JSBSim
+
+#endif //FGLinearization_H_
+
+// vim:ts=4:sw=4
index ec6ca6fc0e0e957687038c95a649eb66cd96613c..b8e645a4c0721b3e30f50ef2e53649c27ddfc32e 100644 (file)
@@ -3,16 +3,16 @@
  * Copyright (C) James Goppert 2010 <james.goppert@gmail.com>
  *
  * FGSimplexTrim.cpp is free software: you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
+ * 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.
  *
  * FGSimplexTrim.cpp 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 General Public License for more details.
+ * See the GNU Lesser General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License along
+ * You should have received a copy of the GNU Lesser General Public License along
  * with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
@@ -23,246 +23,95 @@ namespace JSBSim {
 
 FGSimplexTrim::FGSimplexTrim(FGFDMExec * fdm, TrimMode mode)
 {
-       std::clock_t time_start=clock(), time_trimDone, time_linDone;
+    std::clock_t time_start=clock(), time_trimDone, time_linDone;
+
+    // variables
+    FGTrimmer::Constraints constraints;
+
+    if (fdm->GetDebugLevel() > 0) {
+        std::cout << "\n-----Performing Simplex Based Trim --------------\n" << std::endl;
+    }
+
+    // defaults
+    std::string aircraftName = fdm->GetAircraft()->GetAircraftName();
+    FGPropertyNode* node = fdm->GetPropertyManager()->GetNode();
+    double rtol = node->GetDouble("trim/solver/rtol");
+    double abstol = node->GetDouble("trim/solver/abstol");
+    double speed = node->GetDouble("trim/solver/speed"); // must be > 1, 2 typical
+    double random = node->GetDouble("trim/solver/random");
+    int iterMax = node->GetDouble("trim/solver/iterMax");
+    bool showConvergence = node->GetBool("trim/solver/showConvergence");
+    bool pause = node->GetBool("trim/solver/pause");
+    bool showSimplex = node->GetBool("trim/solver/showSimplex");
+    bool variablePropPitch = node->GetBool("trim/solver/variablePropPitch");
+
+    // flight conditions
+    double phi = fdm->GetIC()->GetPhiRadIC();
+    double theta = fdm->GetIC()->GetThetaRadIC();
+    double psi = fdm->GetIC()->GetPsiRadIC();
+    double gd = fdm->GetInertial()->gravity();
+
+    constraints.velocity = fdm->GetIC()->GetVtrueFpsIC();
+    constraints.altitude = fdm->GetIC()->GetAltitudeASLFtIC();
+    constraints.gamma = fdm->GetIC()->GetFlightPathAngleRadIC();
+    constraints.rollRate = 0;
+    constraints.pitchRate = 0;
+    constraints.yawRate = tan(phi)*gd*cos(theta)/constraints.velocity;
 
-       // variables
-       fdm->Setdt(1./120);
-       FGTrimmer::Constraints constraints;
-
-       std::cout << "\n-----Performing Simplex Based Trim --------------\n" << std::endl;
-
-       // defaults
-       constraints.velocity = fdm->GetAuxiliary()->GetVt();
-       constraints.altitude = fdm->GetPropagate()->GetAltitudeASL();
-       std::string aircraft = fdm->GetAircraft()->GetAircraftName();
-       double rtol = fdm->GetPropertyManager()->GetDouble("trim/solver/rtol");
-       double abstol = fdm->GetPropertyManager()->GetDouble("trim/solver/abstol");
-       double speed = fdm->GetPropertyManager()->GetDouble("trim/solver/speed"); // must be > 1, 2 typical
-       double random = fdm->GetPropertyManager()->GetDouble("trim/solver/random");
-       int iterMax = fdm->GetPropertyManager()->GetDouble("trim/solver/iterMax");
-       bool showConvergeStatus = fdm->GetPropertyManager()->GetBool("trim/solver/showConvergeStatus");
-       bool pause = fdm->GetPropertyManager()->GetBool("trim/solver/pause");
-       bool showSimplex = fdm->GetPropertyManager()->GetBool("trim/solver/showSimplex");
-       bool variablePropPitch = fdm->GetPropertyManager()->GetBool("trim/solver/variablePropPitch");
-       //int debugLevel = fdm->GetPropertyManager()->GetInt("trim/solver/debugLevel");
-
-       std::string fileName = aircraft;
-
-       // input
-       //std::cout << "input ( press enter to accept [default] )\n" << std::endl;
-
-       // load model
-       std::string aircraftName = fdm->GetAircraft()->GetAircraftName();
-       //prompt("\tdebug level\t\t",debugLevel);
-       //fdm->SetDebugLevel(debugLevel);
-       //std::cout << "model selection" << std::endl;
-       //while (1)
-       //{
-               //prompt("\taircraft\t\t",aircraft);
-               //prompt("\toutput file name\t",fileName);
-               //fdm->LoadModel("../aircraft","../engine","../systems",aircraft);
-               //aircraftName = fdm->GetAircraft()->GetAircraftName();
-               //if (aircraftName == "")
-               //{
-                       //std::cout << "\tfailed to load aircraft" << std::endl;
-               //}
-               //else
-               //{
-                       //std::cout << "\tsuccessfully loaded: " <<  aircraftName << std::endl;
-                       //break;
-               //}
-       //}
-
-       // Turn on propulsion system
-       fdm->GetPropulsion()->InitRunning(-1);
-
-       // get propulsion pointer to determine type/ etc.
-       FGEngine * engine0 = fdm->GetPropulsion()->GetEngine(0);
-       FGThruster * thruster0 = engine0->GetThruster();
-
-       // flight conditions
-       //std::cout << "\nflight conditions: " << std::endl;
-       //prompt("\taltitude, ft\t\t",constraints.altitude);
-       //prompt("\tvelocity, ft/s\t\t",constraints.velocity);
-       //prompt("\tgamma, deg\t\t",constraints.gamma); constraints.gamma = constraints.gamma*M_PI/180;
-       
-       //double phi = fdm->GetPropagate()->GetEuler(1);
-       double theta = fdm->GetPropagate()->GetEuler(2);
-       //double psi = fdm->GetPropagate()->GetEuler(3);
-
-       // TODO check that this works properly
-       constraints.gamma = theta;
-
-       //if (thruster0->GetType()==FGThruster::ttPropeller)
-               //prompt("\tvariable prop pitch?\t\t",variablePropPitch);
-       // FIXME, enable
-               
-    constraints.rollRate = fdm->GetIC()->GetPRadpsIC();
-    constraints.pitchRate = fdm->GetIC()->GetQRadpsIC();
-    constraints.yawRate = fdm->GetIC()->GetRRadpsIC();
     constraints.stabAxisRoll = true; // FIXME, make this an option
 
-       // solver properties
-       // TODO make these options
-       //std::cout << "\nsolver properties: " << std::endl;
-       //std::cout << std::scientific;
-       //prompt("\tshow converge status?\t",showConvergeStatus);
-       //prompt("\tshow simplex?\t\t",showSimplex);
-       //prompt("\tpause?\t\t\t",pause);
-       //prompt("\trelative tolerance\t",rtol);
-       //prompt("\tabsolute tolerance\t",abstol);
-       //prompt("\tmax iterations\t\t",iterMax);
-       //prompt("\tconvergence speed\t",speed);
-       //prompt("\trandomization ratio\t",random);
-       //std::cout << std::fixed;
-
-       // initial solver state
-       int n = 6;
-       std::vector<double> initialGuess(n), lowerBound(n), upperBound(n), initialStepSize(n);
-
-       lowerBound[0] = fdm->GetPropertyManager()->GetDouble("trim/solver/throttleMin");
-       lowerBound[1] = fdm->GetPropertyManager()->GetDouble("trim/solver/elevatorMin");
-       lowerBound[2] = fdm->GetPropertyManager()->GetDouble("trim/solver/alphaMin");
-       lowerBound[3] = fdm->GetPropertyManager()->GetDouble("trim/solver/aileronMin");
-       lowerBound[4] = fdm->GetPropertyManager()->GetDouble("trim/solver/rudderMin");
-       lowerBound[5] = fdm->GetPropertyManager()->GetDouble("trim/solver/betaMin");
-
-       upperBound[0] = fdm->GetPropertyManager()->GetDouble("trim/solver/throttleMax");
-       upperBound[1] = fdm->GetPropertyManager()->GetDouble("trim/solver/elevatorMax");
-       upperBound[2] = fdm->GetPropertyManager()->GetDouble("trim/solver/alphaMax");
-       upperBound[3] = fdm->GetPropertyManager()->GetDouble("trim/solver/aileronMax");
-       upperBound[4] = fdm->GetPropertyManager()->GetDouble("trim/solver/rudderMax");
-       upperBound[5] = fdm->GetPropertyManager()->GetDouble("trim/solver/betaMax");
-
-    initialStepSize[0] = fdm->GetPropertyManager()->GetDouble("trim/solver/throttleStep");
-       initialStepSize[1] = fdm->GetPropertyManager()->GetDouble("trim/solver/elevatorStep");
-       initialStepSize[2] = fdm->GetPropertyManager()->GetDouble("trim/solver/alphaStep");
-       initialStepSize[3] = fdm->GetPropertyManager()->GetDouble("trim/solver/aileronStep");
-       initialStepSize[4] = fdm->GetPropertyManager()->GetDouble("trim/solver/rudderStep");
-       initialStepSize[5] = fdm->GetPropertyManager()->GetDouble("trim/solver/betaStep");
-
-    initialGuess[0] = fdm->GetPropertyManager()->GetDouble("trim/solver/throttleGuess");
-       initialGuess[1] = fdm->GetPropertyManager()->GetDouble("trim/solver/elevatorGuess");
-       initialGuess[2] = fdm->GetPropertyManager()->GetDouble("trim/solver/alphaGuess");
-       initialGuess[3] = fdm->GetPropertyManager()->GetDouble("trim/solver/aileronGuess");
-       initialGuess[4] = fdm->GetPropertyManager()->GetDouble("trim/solver/rudderGuess");
-       initialGuess[5] = fdm->GetPropertyManager()->GetDouble("trim/solver/betaGuess");
-
-       // solve
-       FGTrimmer trimmer(fdm, &constraints);
-       Callback callback(fileName,&trimmer);
-       FGNelderMead * solver = NULL;
-       try
-       {
-                solver = new FGNelderMead(&trimmer,initialGuess,
-                       lowerBound, upperBound, initialStepSize,iterMax,rtol,
-                       abstol,speed,random,showConvergeStatus,showSimplex,pause,&callback);
-                while(solver->status()==1) solver->update();
-       }
-       catch (const std::runtime_error & e)
-       {
-               std::cout << e.what() << std::endl;
-               //exit(1);
-       }
-
-       // output
-       try
-       {
-               trimmer.printSolution(std::cout,solver->getSolution()); // this also loads the solution into the fdm
-               std::cout << "\nfinal cost: " << std::scientific << std::setw(10) << trimmer.eval(solver->getSolution()) << std::endl;
-       }
-       catch(std::runtime_error & e)
-       {
-               std::cout << "caught std::runtime error" << std::endl;
-               std::cout << "exception: " << e.what() << std::endl;
-               exit(1);
-       }
-
-       time_trimDone = std::clock();
-       std::cout << "\ntrim computation time: " << (time_trimDone - time_start)/double(CLOCKS_PER_SEC) << "s \n" << std::endl;
-
-       //std::cout << "\nsimulating flight to determine trim stability" << std::endl;
-
-       //std::cout << "\nt = 5 seconds" << std::endl;
-       //for (int i=0;i<5*120;i++) fdm->Run();
-       //trimmer.printState();
-
-       //std::cout << "\nt = 10 seconds" << std::endl;
-       //for (int i=0;i<5*120;i++) fdm->Run();
-       //trimmer.printState();
-
-       std::cout << "\nlinearization: " << std::endl;
-       FGStateSpace ss(fdm);
-
-       ss.x.add(new FGStateSpace::Vt);
-       ss.x.add(new FGStateSpace::Alpha);
-       ss.x.add(new FGStateSpace::Theta);
-       ss.x.add(new FGStateSpace::Q);
-
-       if (thruster0->GetType()==FGThruster::ttPropeller)
-       {
-               ss.x.add(new FGStateSpace::Rpm0);
-               if (variablePropPitch) ss.x.add(new FGStateSpace::PropPitch);
-               int numEngines = fdm->GetPropulsion()->GetNumEngines();
-               if (numEngines>1) ss.x.add(new FGStateSpace::Rpm1);
-               if (numEngines>2) ss.x.add(new FGStateSpace::Rpm2);
-               if (numEngines>3) ss.x.add(new FGStateSpace::Rpm3);
-       }
-       ss.x.add(new FGStateSpace::Beta);
-       ss.x.add(new FGStateSpace::Phi);
-       ss.x.add(new FGStateSpace::P);
-       ss.x.add(new FGStateSpace::Psi);
-       ss.x.add(new FGStateSpace::R);
-       ss.x.add(new FGStateSpace::Latitude);
-       ss.x.add(new FGStateSpace::Longitude);
-       ss.x.add(new FGStateSpace::Alt);
-
-       ss.u.add(new FGStateSpace::ThrottleCmd);
-       ss.u.add(new FGStateSpace::DaCmd);
-       ss.u.add(new FGStateSpace::DeCmd);
-       ss.u.add(new FGStateSpace::DrCmd);
-
-       // state feedback
-       ss.y = ss.x;
-
-       std::vector< std::vector<double> > A,B,C,D;
-       std::vector<double> x0 = ss.x.get(), u0 = ss.u.get();
-       std::vector<double> y0 = x0; // state feedback
-       std::cout << ss << std::endl;
-
-       ss.linearize(x0,u0,y0,A,B,C,D);
-
-       int width=10;
-       std::cout.precision(3);
-       std::cout
-               << std::fixed
-               << std::right
-               << "\nA=\n" << std::setw(width) << A
-               << "\nB=\n" << std::setw(width) << B
-               << "\nC=\n" << std::setw(width) << C
-               << "\nD=\n" << std::setw(width) << D
-               << std::endl;
-
-       // write scicoslab file
-       std::ofstream scicos(std::string(aircraft+"_lin.sce").c_str());
-       scicos.precision(10);
-       width=20;
-       scicos
-       << std::scientific
-       << aircraft << ".x0=..\n" << std::setw(width) << x0 << ";\n"
-       << aircraft << ".u0=..\n" << std::setw(width) << u0 << ";\n"
-       << aircraft << ".sys = syslin('c',..\n"
-       << std::setw(width) << A << ",..\n"
-       << std::setw(width) << B << ",..\n"
-       << std::setw(width) << C << ",..\n"
-       << std::setw(width) << D << ");\n"
-       << aircraft << ".tfm = ss2tf(" << aircraft << ".sys);\n"
-       << std::endl;
-
-       time_linDone = std::clock();
-       std::cout << "\nlinearization computation time: " << (time_linDone - time_trimDone)/double(CLOCKS_PER_SEC) << " s\n" << std::endl;
+    // initial solver state
+    int n = 6;
+    std::vector<double> initialGuess(n), lowerBound(n), upperBound(n), initialStepSize(n);
+
+    lowerBound[0] = node->GetDouble("trim/solver/throttleMin");
+    lowerBound[1] = node->GetDouble("trim/solver/elevatorMin");
+    lowerBound[2] = node->GetDouble("trim/solver/alphaMin");
+    lowerBound[3] = node->GetDouble("trim/solver/aileronMin");
+    lowerBound[4] = node->GetDouble("trim/solver/rudderMin");
+    lowerBound[5] = node->GetDouble("trim/solver/betaMin");
+
+    upperBound[0] = node->GetDouble("trim/solver/throttleMax");
+    upperBound[1] = node->GetDouble("trim/solver/elevatorMax");
+    upperBound[2] = node->GetDouble("trim/solver/alphaMax");
+    upperBound[3] = node->GetDouble("trim/solver/aileronMax");
+    upperBound[4] = node->GetDouble("trim/solver/rudderMax");
+    upperBound[5] = node->GetDouble("trim/solver/betaMax");
+
+    initialStepSize[0] = node->GetDouble("trim/solver/throttleStep");
+    initialStepSize[1] = node->GetDouble("trim/solver/elevatorStep");
+    initialStepSize[2] = node->GetDouble("trim/solver/alphaStep");
+    initialStepSize[3] = node->GetDouble("trim/solver/aileronStep");
+    initialStepSize[4] = node->GetDouble("trim/solver/rudderStep");
+    initialStepSize[5] = node->GetDouble("trim/solver/betaStep");
+
+    initialGuess[0] = node->GetDouble("trim/solver/throttleGuess");
+    initialGuess[1] = node->GetDouble("trim/solver/elevatorGuess");
+    initialGuess[2] = node->GetDouble("trim/solver/alphaGuess");
+    initialGuess[3] = node->GetDouble("trim/solver/aileronGuess");
+    initialGuess[4] = node->GetDouble("trim/solver/rudderGuess");
+    initialGuess[5] = node->GetDouble("trim/solver/betaGuess");
+
+    // solve
+    FGTrimmer * trimmer = new FGTrimmer(fdm, &constraints);
+    Callback callback(aircraftName, trimmer);
+    FGNelderMead * solver = NULL;
+
+    solver = new FGNelderMead(trimmer,initialGuess,
+        lowerBound, upperBound, initialStepSize,iterMax,rtol,
+        abstol,speed,random,showConvergence,showSimplex,pause,&callback);
+    while(solver->status()==1) solver->update();
+    time_trimDone = std::clock();
+
+    // output
+    if (fdm->GetDebugLevel() > 0) {
+        trimmer->printSolution(std::cout,solver->getSolution());
+        std::cout << "\nfinal cost: " << std::scientific << std::setw(10) << trimmer->eval(solver->getSolution()) << std::endl;
+        std::cout << "\ntrim computation time: " << (time_trimDone - time_start)/double(CLOCKS_PER_SEC) << "s \n" << std::endl;
+    }
 
     if (solver) delete solver;
+    if (trimmer) delete trimmer;
 }
 
 } // JSBSim
index 3ee0dd3f0308410785f34c1de92c2d56b422210c..9bfe51c3e225b8d708d5dfe1206fa757b9bc9ceb 100644 (file)
@@ -3,16 +3,16 @@
  * Copyright (C) James Goppert 2010 <james.goppert@gmail.com>
  *
  * FGSimplexTrim.h is free software: you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
+ * 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.
  *
  * FGSimplexTrim.h 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 General Public License for more details.
+ * See the GNU Lesser General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License along
+ * You should have received a copy of the GNU Lesser General Public License along
  * with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
@@ -37,41 +37,41 @@ namespace JSBSim {
 class FGSimplexTrim
 {
 public:
-       FGSimplexTrim(FGFDMExec * fdmPtr, TrimMode mode);
+    FGSimplexTrim(FGFDMExec * fdmPtr, TrimMode mode);
 private:
-       template <class varType>
-       void prompt(const std::string & str, varType & var)
-       {
-               std::cout << str + " [" << std::setw(10) << var << "]\t: ";
-               if (std::cin.peek() != '\n')
-               {
-                       std::cin >> var;
-                       std::cin.ignore(1000, '\n');
-               }
-               else std::cin.get();
-       }
+    template <class varType>
+    void prompt(const std::string & str, varType & var)
+    {
+        std::cout << str + " [" << std::setw(10) << var << "]\t: ";
+        if (std::cin.peek() != '\n')
+        {
+            std::cin >> var;
+            std::cin.ignore(1000, '\n');
+        }
+        else std::cin.get();
+    }
 
-       class Callback : public JSBSim::FGNelderMead::Callback
-       {       
-       private:
-               std::ofstream _outputFile;
-               JSBSim::FGTrimmer * _trimmer;
-       public:
-               Callback(std::string fileName, JSBSim::FGTrimmer * trimmer) : 
-                       _outputFile((fileName + std::string("_simplexTrim.log")).c_str()),
-                       _trimmer(trimmer) {
-               }
-               virtual ~Callback() {
-                       _outputFile.close();
-               }
-               void eval(const std::vector<double> &v)
-               {
-                       _outputFile << _trimmer->eval(v) << std::endl;;
-                       //std::cout << "v: ";
-                       //for (int i=0;i<v.size();i++) std::cout << v[i] << " ";
-                       //std::cout << std::endl;
-               }
-       };
+    class Callback : public JSBSim::FGNelderMead::Callback
+    {   
+    private:
+        std::ofstream _outputFile;
+        JSBSim::FGTrimmer * _trimmer;
+    public:
+        Callback(std::string fileName, JSBSim::FGTrimmer * trimmer) : 
+            _outputFile((fileName + std::string("_simplexTrim.log")).c_str()),
+            _trimmer(trimmer) {
+        }
+        virtual ~Callback() {
+            _outputFile.close();
+        }
+        void eval(const std::vector<double> &v)
+        {
+            _outputFile << _trimmer->eval(v) << std::endl;;
+            //std::cout << "v: ";
+            //for (int i=0;i<v.size();i++) std::cout << v[i] << " ";
+            //std::cout << std::endl;
+        }
+    };
 };
 
 } // JSBSim
index 3cc77bad4edb12e4e0591e00eff996381f05103f..b0194865a1c3cdd663be883fb165f3474d2f1cd0 100644 (file)
@@ -3,16 +3,16 @@
  * Copyright (C) James Goppert 2010 <james.goppert@gmail.com>
  *
  * FGTrimmer.cpp is free software: you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
+ * 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.
  *
  * FGTrimmer.cpp 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 General Public License for more details.
+ * See the GNU Lesser General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License along
+ * You should have received a copy of the GNU Lesser General Public License along
  * with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
@@ -39,44 +39,56 @@ FGTrimmer::FGTrimmer(FGFDMExec * fdm, Constraints * constraints) :
 {
 }
 
-std::vector<double> FGTrimmer::constrain(const std::vector<double> & v)
+FGTrimmer::~FGTrimmer()
+{
+}
+
+std::vector<double> FGTrimmer::constrain(const std::vector<double> & dv)
 {
     // unpack design vector
-    double throttle = v[0];
-    double elevator = v[1];
-    double alpha = v[2];
-    double aileron = v[3];
-    double rudder = v[4];
-    double beta = v[5];
+    double throttle = dv[0];
+    double elevator = dv[1];
+    double alpha = dv[2];
+    double aileron = dv[3];
+    double rudder = dv[4];
+    double beta = dv[5];
 
     // initialize constraints
     double vt = m_constraints->velocity;
     double altitude = m_constraints->altitude;
-    double phi = 0.0, theta = 0.0, psi = 0.0*M_PI/180.0;
+    double gamma = m_constraints->gamma;
+    double phi = m_fdm->GetIC()->GetPhiRadIC();
+    double theta = m_fdm->GetIC()->GetThetaRadIC();
+    double psi = m_fdm->GetIC()->GetPsiRadIC();
     double p = 0.0, q = 0.0, r= 0.0;
+    double u = vt*cos(alpha)*cos(beta);
+    double v = vt*sin(beta);
+    double w = vt*sin(alpha)*cos(beta);
+    double lat = m_fdm->GetIC()->GetLatitudeRadIC();
+    double lon = m_fdm->GetIC()->GetLongitudeRadIC();
 
     // precomputation
-    double sGam = sin(m_constraints->gamma);
+    double sGam = sin(gamma);
     double sBeta = sin(beta);
     double cBeta = cos(beta);
     double tAlpha = tan(alpha);
     double cAlpha = cos(alpha);
 
-    // rate of climb constraint
-    double a = cAlpha*cBeta;
-    double b = sin(phi)*sBeta+cos(phi)*sin(alpha)*cBeta;
-    theta = atan((a*b+sGam*sqrt(a*a-sGam*sGam+b*b))/(a*a-sGam*sGam));
-
     // turn coordination constraint, lewis pg. 190
     double gd = m_fdm->GetInertial()->gravity();
     double gc = m_constraints->yawRate*vt/gd;
-    a = 1 - gc*tAlpha*sBeta;
-    b = sGam/cBeta;
+    double a = 1 - gc*tAlpha*sBeta;
+    double b = sGam/cBeta;
     double c = 1 + gc*gc*cBeta*cBeta;
     phi = atan((gc*cBeta*((a-b*b)+
                 b*tAlpha*sqrt(c*(1-b*b)+gc*gc*sBeta*sBeta)))/
                (cAlpha*(a*a-b*b*(1+c*tAlpha*tAlpha))));
 
+    // rate of climb constraint
+    a = cAlpha*cBeta;
+    b = sin(phi)*sBeta+cos(phi)*sin(alpha)*cBeta;
+    theta = atan((a*b+sGam*sqrt(a*a-sGam*sGam+b*b))/(a*a-sGam*sGam));
+
     // turn rates
     if (m_constraints->rollRate != 0.0) // rolling
     {
@@ -104,28 +116,13 @@ std::vector<double> FGTrimmer::constrain(const std::vector<double> & v)
         r = 0.0;
     }
 
-    // state
-    m_fdm->GetIC()->SetVtrueFpsIC(vt);
-    m_fdm->GetIC()->SetAlphaRadIC(alpha);
-    m_fdm->GetIC()->SetThetaRadIC(theta);
-    m_fdm->GetIC()->SetFlightPathAngleRadIC(m_constraints->gamma);
-    m_fdm->GetIC()->SetQRadpsIC(q);
-    // thrust handled below
-    m_fdm->GetIC()->SetBetaRadIC(beta);
-    m_fdm->GetIC()->SetPhiRadIC(phi);
-    m_fdm->GetIC()->SetPRadpsIC(p);
-    m_fdm->GetIC()->SetRRadpsIC(r);
-
-    // actuator states handled below
-
-    // nav state
-    m_fdm->GetIC()->SetAltitudeASLFtIC(altitude);
-    m_fdm->GetIC()->SetPsiRadIC(psi);
-    //m_fdm->GetIC()->SetLatitudeRadIC(0);
-    //m_fdm->GetIC()->SetLongitudeRadIC(0);
-
     // apply state
-    m_fdm->RunIC();
+    m_fdm->GetIC()->ResetIC(u, v, w,
+            p, q, r,
+            alpha, beta,
+            phi, theta, psi, 
+            lat, lon, altitude,
+            gamma);
 
     // set controls
     m_fdm->GetFCS()->SetDeCmd(elevator);
@@ -140,37 +137,46 @@ std::vector<double> FGTrimmer::constrain(const std::vector<double> & v)
 
     for (unsigned int i=0; i<m_fdm->GetPropulsion()->GetNumEngines(); i++)
     {
-        //FGEngine * engine = m_fdm->GetPropulsion()->GetEngine(i);
-        m_fdm->GetPropulsion()->GetEngine(i)->InitRunning();
         m_fdm->GetFCS()->SetThrottleCmd(i,throttle);
         m_fdm->GetFCS()->SetThrottlePos(i,throttle);
     }
 
+    // initialize
+    m_fdm->Initialize(m_fdm->GetIC());
+    for (unsigned int i=0; i<m_fdm->GetPropulsion()->GetNumEngines(); i++) {
+        m_fdm->GetPropulsion()->GetEngine(i)->InitRunning();
+    }
 
-    // wait for steady-state
-    //double thrust0 = m_fdm->GetPropulsion()->GetEngine(0)->GetThruster()->GetThrust();
-    //double dThrustMag0 = 0;
-    //for(int i=0;;i++) {
-        //m_fdm->RunIC();
-        //m_fdm->Run();
-        //double thrust = m_fdm->GetPropulsion()->GetEngine(0)->GetThruster()->GetThrust();
-        //double dThrustMag = std::abs(thrust - thrust0);
-        //double d2Thrust = dThrustMag - dThrustMag0;
-        //thrust0= thrust;
-        //dThrustMag0 = dThrustMag;
-        //if (d2Thrust < std::numeric_limits<double>::epsilon() ) {
-            //// thrust difference has converged to minimum
-            //// if d2Thrust > 0 clearly, more interations won't help
-            //// so not using abs(d2Thrust)
-            //break;
-        //} else if (i> 1000) {
-            //std::cout << "thrust failed to converge" << std::endl;
-            //std::cout << "difference: " << dThrustMag << std::endl;
-            //throw std::runtime_error("thrust failed to converge");
-            //break;
-        //}
-    //}
-    //m_fdm->RunIC();
+    // wait for stable state
+    double cost = compute_cost();
+    for(int i=0;;i++) {
+        m_fdm->GetPropulsion()->GetSteadyState();
+        m_fdm->SetTrimStatus(true);
+        m_fdm->DisableOutput();
+        m_fdm->SuspendIntegration();
+        m_fdm->Run();
+        m_fdm->SetTrimStatus(false);
+        m_fdm->EnableOutput();
+        m_fdm->ResumeIntegration();
+
+        double costNew = compute_cost();
+        double dcost = fabs(costNew - cost);
+        if (dcost < std::numeric_limits<double>::epsilon()) {
+            if(m_fdm->GetDebugLevel() > 1) {
+                std::cout << "cost convergd, i: " << i << std::endl;
+            }
+            break;
+        }
+        if (i > 1000) {
+            if(m_fdm->GetDebugLevel() > 1) {
+                std::cout << "cost failed to converge, dcost: " 
+                    << std::scientific
+                    << dcost << std::endl;
+            }
+            break;
+        }
+        cost = costNew;
+    }
 
     std::vector<double> data;
     data.push_back(phi);
@@ -182,7 +188,7 @@ void FGTrimmer::printSolution(std::ostream & stream, const std::vector<double> &
 {
     eval(v);
 
-    double dt = m_fdm->GetDeltaT();
+    //double dt = m_fdm->GetDeltaT();
     double thrust = m_fdm->GetPropulsion()->GetEngine(0)->GetThruster()->GetThrust();
     double elevator = m_fdm->GetFCS()->GetDePos(ofNorm);
     double aileron = m_fdm->GetFCS()->GetDaLPos(ofNorm);
@@ -192,23 +198,15 @@ void FGTrimmer::printSolution(std::ostream & stream, const std::vector<double> &
     double lon = m_fdm->GetPropagate()->GetLongitudeDeg();
     double vt = m_fdm->GetAuxiliary()->GetVt();
 
-    // run a step to compute derivatives
-    //for (int i=0;i<10000;i++) {
-        //while (old - m_fdm->GetPropulsion()->GetEngine(i)->CalcFuelNeed() < 1e-5) {
-            //m_fdm->RunIC();
-            //m_fdm->Run();
-        //}
-    //}
-
-    double dthrust = (m_fdm->GetPropulsion()->GetEngine(0)->
-            GetThruster()->GetThrust()-thrust)/dt;
-    double delevator = (m_fdm->GetFCS()->GetDePos(ofNorm)-elevator)/dt;
-    double daileron = (m_fdm->GetFCS()->GetDaLPos(ofNorm)-aileron)/dt;
-    double drudder = (m_fdm->GetFCS()->GetDrPos(ofNorm)-rudder)/dt;
-    double dthrottle = (m_fdm->GetFCS()->GetThrottlePos(0)-throttle)/dt;
-    double dlat = (m_fdm->GetPropagate()->GetLatitudeDeg()-lat)/dt;
-    double dlon = (m_fdm->GetPropagate()->GetLongitudeDeg()-lon)/dt;
-    double dvt = (m_fdm->GetAuxiliary()->GetVt()-vt)/dt;
+    //double dthrust = (m_fdm->GetPropulsion()->GetEngine(0)->
+            //GetThruster()->GetThrust()-thrust)/dt;
+    //double delevator = (m_fdm->GetFCS()->GetDePos(ofNorm)-elevator)/dt;
+    //double daileron = (m_fdm->GetFCS()->GetDaLPos(ofNorm)-aileron)/dt;
+    //double drudder = (m_fdm->GetFCS()->GetDrPos(ofNorm)-rudder)/dt;
+    //double dthrottle = (m_fdm->GetFCS()->GetThrottlePos(0)-throttle)/dt;
+    //double dlat = (m_fdm->GetPropagate()->GetLatitudeDeg()-lat)/dt;
+    //double dlon = (m_fdm->GetPropagate()->GetLongitudeDeg()-lon)/dt;
+    //double dvt = (m_fdm->GetAuxiliary()->GetVt()-vt)/dt;
 
     // reinitialize with correct state
     eval(v);
@@ -247,29 +245,29 @@ void FGTrimmer::printSolution(std::ostream & stream, const std::vector<double> &
               << "\n\naircraft d/dt state"
               << std::scientific
 
-              << "\n\td/dt vt\t\t\t:\t" << dvt
+              //<< "\n\td/dt vt\t\t\t:\t" << dvt
               << "\n\td/dt alpha, deg/s\t:\t" << m_fdm->GetAuxiliary()->Getadot()*180/M_PI
               << "\n\td/dt theta, deg/s\t:\t" << m_fdm->GetAuxiliary()->GetEulerRates(2)*180/M_PI
               << "\n\td/dt q, rad/s^2\t\t:\t" << m_fdm->GetAccelerations()->GetPQRdot(2)
-              << "\n\td/dt thrust, lbf\t:\t" << dthrust
+              //<< "\n\td/dt thrust, lbf\t:\t" << dthrust
               << "\n\td/dt beta, deg/s\t:\t" << m_fdm->GetAuxiliary()->Getbdot()*180/M_PI
               << "\n\td/dt phi, deg/s\t\t:\t" << m_fdm->GetAuxiliary()->GetEulerRates(1)*180/M_PI
               << "\n\td/dt p, rad/s^2\t\t:\t" << m_fdm->GetAccelerations()->GetPQRdot(1)
               << "\n\td/dt r, rad/s^2\t\t:\t" << m_fdm->GetAccelerations()->GetPQRdot(3)
 
               // d/dt actuator states
-              << "\n\nd/dt actuator state"
-              << "\n\td/dt throttle, %/s\t:\t" << dthrottle
-              << "\n\td/dt elevator, %/s\t:\t" << delevator
-              << "\n\td/dt aileron, %/s\t:\t" << daileron
-              << "\n\td/dt rudder, %/s\t:\t" << drudder
+              //<< "\n\nd/dt actuator state"
+              //<< "\n\td/dt throttle, %/s\t:\t" << dthrottle
+              //<< "\n\td/dt elevator, %/s\t:\t" << delevator
+              //<< "\n\td/dt aileron, %/s\t:\t" << daileron
+              //<< "\n\td/dt rudder, %/s\t:\t" << drudder
 
               // nav state
               << "\n\nd/dt nav state"
               << "\n\td/dt altitude, ft/s\t:\t" << m_fdm->GetPropagate()->Gethdot()
               << "\n\td/dt psi, deg/s\t\t:\t" << m_fdm->GetAuxiliary()->GetEulerRates(3)
-              << "\n\td/dt lat, deg/s\t\t:\t" << dlat
-              << "\n\td/dt lon, deg/s\t\t:\t" << dlon
+              //<< "\n\td/dt lat, deg/s\t\t:\t" << dlat
+              //<< "\n\td/dt lon, deg/s\t\t:\t" << dlon
               << std::fixed
 
               << "\n\npropulsion system state"
@@ -343,39 +341,17 @@ void FGTrimmer::printState(std::ostream & stream)
 
 }
 
-double FGTrimmer::eval(const std::vector<double> & v)
+double FGTrimmer::compute_cost()
 {
-    double cost = 0;
-    double cost0 = -1;
-
-    double dvt=0;
-    double dalpha = 0;
-    double dbeta = 0;
-    double dp = 0;
-    double dq = 0;
-    double dr = 0;
-
-    double dvt0 = 0;
-    double dalpha0 = 0;
-    double dbeta0 = 0;
-    double dp0 = 0;
-    double dq0 = 0;
-    double dr0 = 0;
-
-    uint16_t steadyCount = 0;
-
-    for(int i=0;;i++) {
-        constrain(v);
-
-        dvt = (m_fdm->GetPropagate()->GetUVW(1)*m_fdm->GetAccelerations()->GetUVWdot(1) +
+    double dvt = (m_fdm->GetPropagate()->GetUVW(1)*m_fdm->GetAccelerations()->GetUVWdot(1) +
                m_fdm->GetPropagate()->GetUVW(2)*m_fdm->GetAccelerations()->GetUVWdot(2) +
                m_fdm->GetPropagate()->GetUVW(3)*m_fdm->GetAccelerations()->GetUVWdot(3))/
               m_fdm->GetAuxiliary()->GetVt(); // from lewis, vtrue dot
-        dalpha = m_fdm->GetAuxiliary()->Getadot();
-        dbeta = m_fdm->GetAuxiliary()->Getbdot();
-        dp = m_fdm->GetAccelerations()->GetPQRdot(1);
-        dq = m_fdm->GetAccelerations()->GetPQRdot(2);
-        dr = m_fdm->GetAccelerations()->GetPQRdot(3);
+    double dalpha = m_fdm->GetAuxiliary()->Getadot();
+    double dbeta = m_fdm->GetAuxiliary()->Getbdot();
+    double dp = m_fdm->GetAccelerations()->GetPQRdot(1);
+    double dq = m_fdm->GetAccelerations()->GetPQRdot(2);
+    double dr = m_fdm->GetAccelerations()->GetPQRdot(3);
 
         if(m_fdm->GetDebugLevel() > 1) {
             std::cout
@@ -388,33 +364,15 @@ double FGTrimmer::eval(const std::vector<double> & v)
                 << std::endl;
         }
 
-        cost = dvt*dvt +
+    return dvt*dvt +
                100.0*(dalpha*dalpha + dbeta*dbeta) +
                10.0*(dp*dp + dq*dq + dr*dr);
-
-        double deltaCost = std::abs(cost - cost0);
-        cost0 = cost;
-        dvt0 = dvt;
-        dalpha0 = dalpha;
-        dbeta0 = dbeta;
-        dp0 = dp;
-        dq0 = dq;
-        dr0 = dr;
-
-        if (deltaCost < 1e-10) {
-            if (steadyCount++ > 3) break;
-        } else if (i> 1000) {
-            std::cout << "deltaCost: " << std::scientific << std::setw(10) 
-                << deltaCost << std::endl;
-            break;
-            //throw std::runtime_error("cost failed to converge");
-        } else {
-            steadyCount=0;
         }
 
-    }
-
-    return cost;
+double FGTrimmer::eval(const std::vector<double> & v)
+{
+    constrain(v);
+    return compute_cost();
 }
 
 } // JSBSim
index 3cca7f320f3b7279f52c2e0f16a64b1b166cf282..ad116f5daf1779c1c5f6e9a9ddf23a14f313fb1b 100644 (file)
@@ -3,16 +3,16 @@
  * Copyright (C) James Goppert 2010 <james.goppert@gmail.com>
  *
  * FGTrimmer.h is free software: you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
+ * 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.
  *
  * FGTrimmer.h 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 General Public License for more details.
+ * See the GNU Lesser General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License along
+ * You should have received a copy of the GNU Lesser General Public License along
  * with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
@@ -42,9 +42,11 @@ public:
         bool coordinatedTurn, stabAxisRoll;
     };
     FGTrimmer(FGFDMExec * fdm, Constraints * constraints);
-       std::vector<double> constrain(const vector<double> & v);
+    ~FGTrimmer();
+    std::vector<double> constrain(const vector<double> & v);
     void printSolution(std::ostream & stream, const vector<double> & v);
     void printState(std::ostream & stream);
+    double compute_cost();
     double eval(const vector<double> & v);
     static void limit(double min, double max, double &val)
     {
index 91937956df507bfd47a7d755626325f63e66ccc8..7af9ee787dc0933598cf20fd5f39faca80a63c78 100644 (file)
@@ -38,7 +38,6 @@ SENTRY
 INCLUDES
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#include "FGJSBBase.h"
 #include "simgear/structure/SGReferenced.hxx"
 #include "simgear/structure/SGSharedPtr.hxx"
 
@@ -46,7 +45,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_GROUNDCALLBACK "$Id: FGGroundCallback.h,v 1.15 2011/11/19 14:14:57 bcoconni Exp $"
+#define ID_GROUNDCALLBACK "$Id: FGGroundCallback.h,v 1.16 2013/02/02 13:23:40 bcoconni Exp $"
 
 namespace JSBSim {
 
@@ -63,14 +62,14 @@ CLASS DOCUMENTATION
     ball formed earth with an adjustable terrain elevation.
 
     @author Mathias Froehlich
-    @version $Id: FGGroundCallback.h,v 1.15 2011/11/19 14:14:57 bcoconni Exp $
+    @version $Id: FGGroundCallback.h,v 1.16 2013/02/02 13:23:40 bcoconni Exp $
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 CLASS DECLARATION
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-class FGGroundCallback : public FGJSBBase, public SGReferenced
+class FGGroundCallback : public SGReferenced
 {
 public:
 
index cdf568ee16eb5751edc3514adcca5969f0bcded4..1abae8bdb19d5e97c1581a8b0f49d5348201faf2 100644 (file)
@@ -46,7 +46,7 @@ INCLUDES
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGOutputType.cpp,v 1.5 2013/01/14 22:44:51 bcoconni Exp $";
+static const char *IdSrc = "$Id: FGOutputType.cpp,v 1.6 2013/01/26 17:06:49 bcoconni Exp $";
 static const char *IdHdr = ID_OUTPUTTYPE;
 
 using namespace std;
@@ -136,7 +136,7 @@ bool FGOutputType::Load(Element* element)
   while (property_element) {
     string caption="";
     string property_str = property_element->GetDataLine();
-    FGPropertyManager* node = PropertyManager->GetNode(property_str);
+    FGPropertyNode* node = PropertyManager->GetNode(property_str);
     if (!node) {
       cerr << fgred << highint << endl << "  No property by the name "
            << property_str << " has been defined. This property will " << endl
index d06ea2cb80ee4ead2870c5027918cb2154566bbd..cbc63dc464396cde9ceb0ccbbf7a66eb0b0f1c0d 100644 (file)
@@ -44,7 +44,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_OUTPUTTYPE "$Id: FGOutputType.h,v 1.4 2013/01/12 20:56:19 bcoconni Exp $"
+#define ID_OUTPUTTYPE "$Id: FGOutputType.h,v 1.5 2013/01/26 17:06:49 bcoconni Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -53,7 +53,6 @@ FORWARD DECLARATIONS
 namespace JSBSim {
 
 class FGFDMExec;
-class FGPropertyManager;
 class Element;
 class FGAerodynamics;
 class FGAuxiliary;
@@ -122,7 +121,7 @@ public:
   /** Set the list of properties that should be output for this output instance.
       @param outputProperties list of properties that should be output
   */
-  void SetOutputProperties(std::vector<FGPropertyManager *> & outputProperties)
+  void SetOutputProperties(std::vector<FGPropertyNode_ptr> & outputProperties)
   {
     OutputProperties = outputProperties;
   }
@@ -197,7 +196,7 @@ public:
 protected:
   int OutputIdx;
   int SubSystems;
-  std::vector <FGPropertyManager*> OutputProperties;
+  std::vector <FGPropertyNode_ptr> OutputProperties;
   std::vector <std::string> OutputCaptions;
   bool enabled;
 
index 39e095a8a457dd60ebcf168e1022345a4bd3c374..aed2f322f421bdcd8bda586097f0708cba75a69a 100644 (file)
@@ -48,8 +48,6 @@ COMMENTS, REFERENCES, and NOTES [use "class documentation" below for API docs]
 
 namespace JSBSim {
 
-std::vector<SGPropertyNode_ptr> FGPropertyManager::tied_properties;
-
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 void FGPropertyManager::Unbind(void)
@@ -81,32 +79,32 @@ string FGPropertyManager::mkPropertyName(string name, bool lowercase) {
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-FGPropertyManager*
-FGPropertyManager::GetNode (const string &path, bool create)
+FGPropertyNode*
+FGPropertyNode::GetNode (const string &path, bool create)
 {
   SGPropertyNode* node = getNode(path.c_str(), create);
   if (node == 0) {
     cerr << "FGPropertyManager::GetNode() No node found for " << path << endl;
   }
-  return (FGPropertyManager*)node;
+  return (FGPropertyNode*)node;
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-FGPropertyManager*
-FGPropertyManager::GetNode (const string &relpath, int index, bool create)
+FGPropertyNode*
+FGPropertyNode::GetNode (const string &relpath, int index, bool create)
 {
   SGPropertyNode* node = getNode(relpath.c_str(), index, create);
   if (node == 0) {
     cerr << "FGPropertyManager::GetNode() No node found for " << relpath
          << "[" << index << "]" << endl;
   }
-  return (FGPropertyManager*)node;
+  return (FGPropertyNode*)node;
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-bool FGPropertyManager::HasNode (const string &path)
+bool FGPropertyNode::HasNode (const string &path)
 {
   const SGPropertyNode* node = getNode(path.c_str(), false);
   return (node != 0);
@@ -114,14 +112,14 @@ bool FGPropertyManager::HasNode (const string &path)
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-string FGPropertyManager::GetName( void ) const
+string FGPropertyNode::GetName( void ) const
 {
   return string( getName() );
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-string FGPropertyManager::GetPrintableName( void ) const
+string FGPropertyNode::GetPrintableName( void ) const
 {
   string temp_string(getName());
   size_t initial_location=0;
@@ -142,7 +140,7 @@ string FGPropertyManager::GetPrintableName( void ) const
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-string FGPropertyManager::GetFullyQualifiedName(void) const
+string FGPropertyNode::GetFullyQualifiedName(void) const
 {
     vector<string> stack;
     stack.push_back( getDisplayName(true) );
@@ -168,7 +166,7 @@ string FGPropertyManager::GetFullyQualifiedName(void) const
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-string FGPropertyManager::GetRelativeName( const string &path ) const
+string FGPropertyNode::GetRelativeName( const string &path ) const
 {
   string temp_string = GetFullyQualifiedName();
   size_t len = path.length();
@@ -182,91 +180,91 @@ string FGPropertyManager::GetRelativeName( const string &path ) const
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-bool FGPropertyManager::GetBool (const string &name, bool defaultValue) const
+bool FGPropertyNode::GetBool (const string &name, bool defaultValue) const
 {
   return getBoolValue(name.c_str(), defaultValue);
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-int FGPropertyManager::GetInt (const string &name, int defaultValue ) const
+int FGPropertyNode::GetInt (const string &name, int defaultValue ) const
 {
   return getIntValue(name.c_str(), defaultValue);
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-int FGPropertyManager::GetLong (const string &name, long defaultValue ) const
+int FGPropertyNode::GetLong (const string &name, long defaultValue ) const
 {
   return getLongValue(name.c_str(), defaultValue);
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-float FGPropertyManager::GetFloat (const string &name, float defaultValue ) const
+float FGPropertyNode::GetFloat (const string &name, float defaultValue ) const
 {
   return getFloatValue(name.c_str(), defaultValue);
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-double FGPropertyManager::GetDouble (const string &name, double defaultValue ) const
+double FGPropertyNode::GetDouble (const string &name, double defaultValue ) const
 {
   return getDoubleValue(name.c_str(), defaultValue);
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-string FGPropertyManager::GetString (const string &name, string defaultValue ) const
+string FGPropertyNode::GetString (const string &name, string defaultValue ) const
 {
   return string(getStringValue(name.c_str(), defaultValue.c_str()));
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-bool FGPropertyManager::SetBool (const string &name, bool val)
+bool FGPropertyNode::SetBool (const string &name, bool val)
 {
   return setBoolValue(name.c_str(), val);
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-bool FGPropertyManager::SetInt (const string &name, int val)
+bool FGPropertyNode::SetInt (const string &name, int val)
 {
   return setIntValue(name.c_str(), val);
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-bool FGPropertyManager::SetLong (const string &name, long val)
+bool FGPropertyNode::SetLong (const string &name, long val)
 {
   return setLongValue(name.c_str(), val);
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-bool FGPropertyManager::SetFloat (const string &name, float val)
+bool FGPropertyNode::SetFloat (const string &name, float val)
 {
   return setFloatValue(name.c_str(), val);
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-bool FGPropertyManager::SetDouble (const string &name, double val)
+bool FGPropertyNode::SetDouble (const string &name, double val)
 {
   return setDoubleValue(name.c_str(), val);
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-bool FGPropertyManager::SetString (const string &name, const string &val)
+bool FGPropertyNode::SetString (const string &name, const string &val)
 {
   return setStringValue(name.c_str(), val.c_str());
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-void FGPropertyManager::SetArchivable (const string &name, bool state )
+void FGPropertyNode::SetArchivable (const string &name, bool state )
 {
   SGPropertyNode * node = getNode(name.c_str());
   if (node == 0)
@@ -279,7 +277,7 @@ void FGPropertyManager::SetArchivable (const string &name, bool state )
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-void FGPropertyManager::SetReadable (const string &name, bool state )
+void FGPropertyNode::SetReadable (const string &name, bool state )
 {
   SGPropertyNode * node = getNode(name.c_str());
   if (node == 0)
@@ -292,7 +290,7 @@ void FGPropertyManager::SetReadable (const string &name, bool state )
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-void FGPropertyManager::SetWritable (const string &name, bool state )
+void FGPropertyNode::SetWritable (const string &name, bool state )
 {
   SGPropertyNode * node = getNode(name.c_str());
   if (node == 0)
@@ -307,7 +305,7 @@ void FGPropertyManager::SetWritable (const string &name, bool state )
 
 void FGPropertyManager::Untie (const string &name)
 {
-  SGPropertyNode* property = getNode(name.c_str());
+  SGPropertyNode* property = root->getNode(name.c_str());
   if (!property) {
     cerr << "Attempt to untie a non-existant property." << name << endl;
     return;
@@ -331,7 +329,7 @@ void FGPropertyManager::Untie (const string &name)
 
 void FGPropertyManager::Tie (const string &name, bool *pointer, bool useDefault)
 {
-  SGPropertyNode* property = getNode(name.c_str(), true);
+  SGPropertyNode* property = root->getNode(name.c_str(), true);
   if (!property) {
     cerr << "Could not get or create property " << name << endl;
     return;
@@ -350,7 +348,7 @@ void FGPropertyManager::Tie (const string &name, bool *pointer, bool useDefault)
 void FGPropertyManager::Tie (const string &name, int *pointer,
                                           bool useDefault )
 {
-  SGPropertyNode* property = getNode(name.c_str(), true);
+  SGPropertyNode* property = root->getNode(name.c_str(), true);
   if (!property) {
     cerr << "Could not get or create property " << name << endl;
     return;
@@ -369,7 +367,7 @@ void FGPropertyManager::Tie (const string &name, int *pointer,
 void FGPropertyManager::Tie (const string &name, long *pointer,
                                           bool useDefault )
 {
-  SGPropertyNode* property = getNode(name.c_str(), true);
+  SGPropertyNode* property = root->getNode(name.c_str(), true);
   if (!property) {
     cerr << "Could not get or create property " << name << endl;
     return;
@@ -388,7 +386,7 @@ void FGPropertyManager::Tie (const string &name, long *pointer,
 void FGPropertyManager::Tie (const string &name, float *pointer,
                                           bool useDefault )
 {
-  SGPropertyNode* property = getNode(name.c_str(), true);
+  SGPropertyNode* property = root->getNode(name.c_str(), true);
   if (!property) {
     cerr << "Could not get or create property " << name << endl;
     return;
@@ -406,7 +404,7 @@ void FGPropertyManager::Tie (const string &name, float *pointer,
 
 void FGPropertyManager::Tie (const string &name, double *pointer, bool useDefault)
 {
-  SGPropertyNode* property = getNode(name.c_str(), true);
+  SGPropertyNode* property = root->getNode(name.c_str(), true);
   if (!property) {
     cerr << "Could not get or create property " << name << endl;
     return;
index e8156a0bb5bcc33114ea981fd41b5292654f1893..57b523cb81d0c39bf52fb952adc4bd47ceda9cf6 100644 (file)
@@ -53,7 +53,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_PROPERTYMANAGER "$Id: FGPropertyManager.h,v 1.24 2013/01/06 14:50:31 bcoconni Exp $"
+#define ID_PROPERTYMANAGER "$Id: FGPropertyManager.h,v 1.26 2013/06/10 01:49:06 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -73,24 +73,11 @@ CLASS DOCUMENTATION
 CLASS DECLARATION
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-class FGPropertyManager : public SGPropertyNode
+class FGPropertyNode : public SGPropertyNode
 {
-  private:
-    static std::vector<SGPropertyNode_ptr> tied_properties;
   public:
-    /// Constructor
-    FGPropertyManager(void) {}
     /// Destructor
-    virtual ~FGPropertyManager(void) {}
-
-    /** Property-ify a name
-     *  replaces spaces with '-' and, optionally, makes name all lower case
-     *  @param name string to change
-     *  @param lowercase true to change all upper case chars to lower
-     *  NOTE: this function changes its argument and thus relies
-     *  on pass by value
-     */
-    std::string mkPropertyName(std::string name, bool lowercase);
+    virtual ~FGPropertyNode(void) {}
 
     /**
      * Get a property node.
@@ -99,10 +86,10 @@ class FGPropertyManager : public SGPropertyNode
      * @param create true to create the node if it doesn't exist.
      * @return The node, or 0 if none exists and none was created.
      */
-    FGPropertyManager*
+    FGPropertyNode*
     GetNode (const std::string &path, bool create = false);
 
-    FGPropertyManager*
+    FGPropertyNode*
     GetNode (const std::string &relpath, int index, bool create = false);
 
     /**
@@ -384,7 +371,38 @@ class FGPropertyManager : public SGPropertyNode
      * @param state The state of the write attribute (defaults to true).
      */
     void SetWritable (const std::string &name, bool state = true);
+};
 
+typedef SGSharedPtr<FGPropertyNode> FGPropertyNode_ptr;
+typedef SGSharedPtr<const FGPropertyNode> FGConstPropertyNode_ptr;
+
+class FGPropertyManager
+{
+  public:
+    /// Default constructor
+    FGPropertyManager(void) { root = new FGPropertyNode; }
+
+    /// Constructor
+    FGPropertyManager(FGPropertyNode* _root) : root(_root) {};
+
+    /// Destructor
+    virtual ~FGPropertyManager(void) { Unbind(); }
+
+    FGPropertyNode* GetNode(void) const { return root; }
+    FGPropertyNode* GetNode(const std::string &path, bool create = false)
+    { return root->GetNode(path, create); }
+    FGPropertyNode* GetNode(const std::string &relpath, int index, bool create = false)
+    { return root->GetNode(relpath, index, create); }
+    bool HasNode(const std::string& path) const { return root->HasNode(path); }
+
+    /** Property-ify a name
+     *  replaces spaces with '-' and, optionally, makes name all lower case
+     *  @param name string to change
+     *  @param lowercase true to change all upper case chars to lower
+     *  NOTE: this function changes its argument and thus relies
+     *  on pass by value
+     */
+    std::string mkPropertyName(std::string name, bool lowercase);
 
     ////////////////////////////////////////////////////////////////////////
     // Convenience functions for tying properties, with logging.
@@ -531,7 +549,7 @@ class FGPropertyManager : public SGPropertyNode
     template <class V> inline void
     Tie (const std::string &name, V (*getter)(), void (*setter)(V) = 0, bool useDefault = true)
     {
-      SGPropertyNode* property = getNode(name.c_str(), true);
+      SGPropertyNode* property = root->getNode(name.c_str(), true);
       if (!property) {
         std::cerr << "Could not get or create property " << name << std::endl;
         return;
@@ -540,6 +558,8 @@ class FGPropertyManager : public SGPropertyNode
       if (!property->tie(SGRawValueFunctions<V>(getter, setter), useDefault))
         std::cerr << "Failed to tie property " << name << " to functions" << std::endl;
       else {
+        if (setter == 0) property->setAttribute(SGPropertyNode::WRITE, false);
+        if (getter == 0) property->setAttribute(SGPropertyNode::READ, false);
         tied_properties.push_back(property);
         if (FGJSBBase::debug_lvl & 0x20) std::cout << name << std::endl;
       }
@@ -567,7 +587,7 @@ class FGPropertyManager : public SGPropertyNode
     template <class V> inline void Tie (const std::string &name, int index, V (*getter)(int),
                                 void (*setter)(int, V) = 0, bool useDefault = true)
     {
-      SGPropertyNode* property = getNode(name.c_str(), true);
+      SGPropertyNode* property = root->getNode(name.c_str(), true);
       if (!property) {
         std::cerr << "Could not get or create property " << name << std::endl;
         return;
@@ -576,6 +596,8 @@ class FGPropertyManager : public SGPropertyNode
       if (!property->tie(SGRawValueFunctionsIndexed<V>(index, getter, setter), useDefault))
         std::cerr << "Failed to tie property " << name << " to indexed functions" << std::endl;
       else {
+        if (setter == 0) property->setAttribute(SGPropertyNode::WRITE, false);
+        if (getter == 0) property->setAttribute(SGPropertyNode::READ, false);
         tied_properties.push_back(property);
         if (FGJSBBase::debug_lvl & 0x20) std::cout << name << std::endl;
       }
@@ -605,7 +627,7 @@ class FGPropertyManager : public SGPropertyNode
     Tie (const std::string &name, T * obj, V (T::*getter)() const,
            void (T::*setter)(V) = 0, bool useDefault = true)
     {
-      SGPropertyNode* property = getNode(name.c_str(), true);
+      SGPropertyNode* property = root->getNode(name.c_str(), true);
       if (!property) {
         std::cerr << "Could not get or create property " << name << std::endl;
         return;
@@ -614,6 +636,8 @@ class FGPropertyManager : public SGPropertyNode
       if (!property->tie(SGRawValueMethods<T,V>(*obj, getter, setter), useDefault))
         std::cerr << "Failed to tie property " << name << " to object methods" << std::endl;
       else {
+        if (setter == 0) property->setAttribute(SGPropertyNode::WRITE, false);
+        if (getter == 0) property->setAttribute(SGPropertyNode::READ, false);
         tied_properties.push_back(property);
         if (FGJSBBase::debug_lvl & 0x20) std::cout << name << std::endl;
       }
@@ -642,7 +666,7 @@ class FGPropertyManager : public SGPropertyNode
     Tie (const std::string &name, T * obj, int index, V (T::*getter)(int) const,
                          void (T::*setter)(int, V) = 0, bool useDefault = true)
     {
-      SGPropertyNode* property = getNode(name.c_str(), true);
+      SGPropertyNode* property = root->getNode(name.c_str(), true);
       if (!property) {
         std::cerr << "Could not get or create property " << name << std::endl;
         return;
@@ -651,10 +675,16 @@ class FGPropertyManager : public SGPropertyNode
       if (!property->tie(SGRawValueMethodsIndexed<T,V>(*obj, index, getter, setter), useDefault))
         std::cerr << "Failed to tie property " << name << " to indexed object methods" << std::endl;
       else {
+        if (setter == 0) property->setAttribute(SGPropertyNode::WRITE, false);
+        if (getter == 0) property->setAttribute(SGPropertyNode::READ, false);
         tied_properties.push_back(property);
         if (FGJSBBase::debug_lvl & 0x20) std::cout << name << std::endl;
       }
    }
+
+  private:
+    std::vector<SGPropertyNode_ptr> tied_properties;
+    FGPropertyNode_ptr root;
 };
 }
 #endif // FGPROPERTYMANAGER_H
index bc512ad90ded702e0e89bc8c240980f76f5d9002..4d2b6ed0a81846f48bd8d54ec1cd3ee79cc114c8 100644 (file)
@@ -55,7 +55,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGScript.cpp,v 1.50 2012/09/05 04:49:13 jberndt Exp $";
+static const char *IdSrc = "$Id: FGScript.cpp,v 1.51 2013/06/10 01:50:43 jberndt Exp $";
 static const char *IdHdr = ID_FGSCRIPT;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -309,7 +309,14 @@ bool FGScript::LoadScript(string script, double deltaT, const string initfile)
     set_element = event_element->FindElement("set");
     while (set_element) {
       prop_name = set_element->GetAttributeValue("name");
+      if (PropertyManager->HasNode(prop_name)) {
       newEvent->SetParam.push_back( PropertyManager->GetNode(prop_name) );
+      } else {
+        newEvent->SetParam.push_back( 0L );
+        cerr << "Property " << prop_name << " will be late-bound." << endl;
+      }
+      newEvent->SetParamName.push_back( prop_name );
+
       //Todo - should probably do some safety checking here to make sure one or the other
       //of value or function is specified.
       if (!set_element->GetAttributeValue("value").empty()) {
@@ -374,104 +381,114 @@ bool FGScript::RunScript(void)
 
   // Iterate over all events.
   for (unsigned int ev_ctr=0; ev_ctr < Events.size(); ev_ctr++) {
+
+    struct event &thisEvent = Events[ev_ctr];
+
     // Determine whether the set of conditional tests for this condition equate
     // to true and should cause the event to execute. If the conditions evaluate 
     // to true, then the event is triggered. If the event is not persistent,
     // then this trigger will remain set true. If the event is persistent,
     // the trigger will reset to false when the condition evaluates to false.
-    if (Events[ev_ctr].Condition->Evaluate()) {
-      if (!Events[ev_ctr].Triggered) {
+    if (thisEvent.Condition->Evaluate()) {
+      if (!thisEvent.Triggered) {
 
         // The conditions are true, do the setting of the desired Event parameters
-        for (i=0; i<Events[ev_ctr].SetValue.size(); i++) {
-          Events[ev_ctr].OriginalValue[i] = Events[ev_ctr].SetParam[i]->getDoubleValue();
-          if (Events[ev_ctr].Functions[i] != 0) { // Parameter should be set to a function value
+        for (i=0; i<thisEvent.SetValue.size(); i++) {
+          if (thisEvent.SetParam[i] == 0L) { // Late bind property if necessary
+            if (PropertyManager->HasNode(thisEvent.SetParamName[i])) {
+              thisEvent.SetParam[i] = PropertyManager->GetNode(thisEvent.SetParamName[i]);
+            } else {
+              throw("No property, \""+thisEvent.SetParamName[i]+"\" is defined.");
+            }
+          }
+          thisEvent.OriginalValue[i] = thisEvent.SetParam[i]->getDoubleValue();
+          if (thisEvent.Functions[i] != 0) { // Parameter should be set to a function value
             try {
-              Events[ev_ctr].SetValue[i] = Events[ev_ctr].Functions[i]->GetValue();
+              thisEvent.SetValue[i] = thisEvent.Functions[i]->GetValue();
             } catch (string msg) {
               std::cerr << std::endl << "A problem occurred in the execution of the script. " << msg << endl;
               throw;
             }
           }
-          switch (Events[ev_ctr].Type[i]) {
+          switch (thisEvent.Type[i]) {
           case FG_VALUE:
           case FG_BOOL:
-            Events[ev_ctr].newValue[i] = Events[ev_ctr].SetValue[i];
+            thisEvent.newValue[i] = thisEvent.SetValue[i];
             break;
           case FG_DELTA:
-            Events[ev_ctr].newValue[i] = Events[ev_ctr].OriginalValue[i] + Events[ev_ctr].SetValue[i];
+            thisEvent.newValue[i] = thisEvent.OriginalValue[i] + thisEvent.SetValue[i];
             break;
           default:
             cerr << "Invalid Type specified" << endl;
             break;
           }
-          Events[ev_ctr].StartTime = currentTime + Events[ev_ctr].Delay;
-          Events[ev_ctr].ValueSpan[i] = Events[ev_ctr].newValue[i] - Events[ev_ctr].OriginalValue[i];
-          Events[ev_ctr].Transiting[i] = true;
+          thisEvent.StartTime = currentTime + thisEvent.Delay;
+          thisEvent.ValueSpan[i] = thisEvent.newValue[i] - thisEvent.OriginalValue[i];
+          thisEvent.Transiting[i] = true;
         }
       }
-      Events[ev_ctr].Triggered = true;
-
-    } else if (Events[ev_ctr].Persistent) { // If the event is persistent, reset the trigger.
-      Events[ev_ctr].Triggered = false; // Reset the trigger for persistent events
-      Events[ev_ctr].Notified = false;  // Also reset the notification flag
-    } else if (Events[ev_ctr].Continuous) { // If the event is continuous, reset the trigger.
-      Events[ev_ctr].Triggered = false; // Reset the trigger for persistent events
-      Events[ev_ctr].Notified = false;  // Also reset the notification flag
+      thisEvent.Triggered = true;
+
+    } else if (thisEvent.Persistent) { // If the event is persistent, reset the trigger.
+      thisEvent.Triggered = false; // Reset the trigger for persistent events
+      thisEvent.Notified = false;  // Also reset the notification flag
+    } else if (thisEvent.Continuous) { // If the event is continuous, reset the trigger.
+      thisEvent.Triggered = false; // Reset the trigger for persistent events
+      thisEvent.Notified = false;  // Also reset the notification flag
     }
 
-    if ((currentTime >= Events[ev_ctr].StartTime) && Events[ev_ctr].Triggered) {
+    if ((currentTime >= thisEvent.StartTime) && thisEvent.Triggered) {
 
-      for (i=0; i<Events[ev_ctr].SetValue.size(); i++) {
-        if (Events[ev_ctr].Transiting[i]) {
-          Events[ev_ctr].TimeSpan = currentTime - Events[ev_ctr].StartTime;
-          switch (Events[ev_ctr].Action[i]) {
+      for (i=0; i<thisEvent.SetValue.size(); i++) {
+        if (thisEvent.Transiting[i]) {
+          thisEvent.TimeSpan = currentTime - thisEvent.StartTime;
+          switch (thisEvent.Action[i]) {
           case FG_RAMP:
-            if (Events[ev_ctr].TimeSpan <= Events[ev_ctr].TC[i]) {
-              newSetValue = Events[ev_ctr].TimeSpan/Events[ev_ctr].TC[i] * Events[ev_ctr].ValueSpan[i] + Events[ev_ctr].OriginalValue[i];
+            if (thisEvent.TimeSpan <= thisEvent.TC[i]) {
+              newSetValue = thisEvent.TimeSpan/thisEvent.TC[i] * thisEvent.ValueSpan[i] + thisEvent.OriginalValue[i];
             } else {
-              newSetValue = Events[ev_ctr].newValue[i];
-              if (Events[ev_ctr].Continuous != true) Events[ev_ctr].Transiting[i] = false;
+              newSetValue = thisEvent.newValue[i];
+              if (thisEvent.Continuous != true) thisEvent.Transiting[i] = false;
             }
             break;
           case FG_STEP:
-            newSetValue = Events[ev_ctr].newValue[i];
+            newSetValue = thisEvent.newValue[i];
 
             // If this is not a continuous event, reset the transiting flag.
             // Otherwise, it is known that the event is a continuous event.
             // Furthermore, if the event is to be determined by a function,
             // then the function will be continuously calculated.
-            if (Events[ev_ctr].Continuous != true)
-              Events[ev_ctr].Transiting[i] = false;
-            else if (Events[ev_ctr].Functions[i] != 0)
-              newSetValue = Events[ev_ctr].Functions[i]->GetValue();
+            if (thisEvent.Continuous != true)
+              thisEvent.Transiting[i] = false;
+            else if (thisEvent.Functions[i] != 0)
+              newSetValue = thisEvent.Functions[i]->GetValue();
 
             break;
           case FG_EXP:
-            newSetValue = (1 - exp( -Events[ev_ctr].TimeSpan/Events[ev_ctr].TC[i] )) * Events[ev_ctr].ValueSpan[i] + Events[ev_ctr].OriginalValue[i];
+            newSetValue = (1 - exp( -thisEvent.TimeSpan/thisEvent.TC[i] )) * thisEvent.ValueSpan[i] + thisEvent.OriginalValue[i];
             break;
           default:
             cerr << "Invalid Action specified" << endl;
             break;
           }
-          Events[ev_ctr].SetParam[i]->setDoubleValue(newSetValue);
+          thisEvent.SetParam[i]->setDoubleValue(newSetValue);
         }
       }
 
       // Print notification values after setting them
-      if (Events[ev_ctr].Notify && !Events[ev_ctr].Notified) {
-        cout << endl << "  Event " << event_ctr << " (" << Events[ev_ctr].Name << ")"
+      if (thisEvent.Notify && !thisEvent.Notified) {
+        cout << endl << "  Event " << event_ctr << " (" << thisEvent.Name << ")"
              << " executed at time: " << currentTime << endl;
-        if (!Events[ev_ctr].Description.empty()) {
-          cout << "    " << Events[ev_ctr].Description << endl;
+        if (!thisEvent.Description.empty()) {
+          cout << "    " << thisEvent.Description << endl;
         }
-        for (j=0; j<Events[ev_ctr].NotifyProperties.size();j++) {
-//          cout << "    " << Events[ev_ctr].NotifyProperties[j]->GetRelativeName()
-          cout << "    " << Events[ev_ctr].DisplayString[j]
-               << " = " << Events[ev_ctr].NotifyProperties[j]->getDoubleValue() << endl;
+        for (j=0; j<thisEvent.NotifyProperties.size();j++) {
+//          cout << "    " << thisEvent.NotifyProperties[j]->GetRelativeName()
+          cout << "    " << thisEvent.DisplayString[j]
+               << " = " << thisEvent.NotifyProperties[j]->getDoubleValue() << endl;
         }
         cout << endl;
-        Events[ev_ctr].Notified = true;
+        thisEvent.Notified = true;
       }
 
     }
index 187b1a8c763800a85ed4a1f7d8bdd0c2c1fe6926..17abb4b383087cc89d8273222dd9a1933b319437 100644 (file)
@@ -49,7 +49,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_FGSCRIPT "$Id: FGScript.h,v 1.22 2012/09/05 04:49:13 jberndt Exp $"
+#define ID_FGSCRIPT "$Id: FGScript.h,v 1.24 2013/06/10 01:50:43 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -158,7 +158,7 @@ CLASS DOCUMENTATION
     comes the &quot;run&quot; section, where the conditions are
     described in &quot;event&quot; clauses.</p>
     @author Jon S. Berndt
-    @version "$Id: FGScript.h,v 1.22 2012/09/05 04:49:13 jberndt Exp $"
+    @version "$Id: FGScript.h,v 1.24 2013/06/10 01:50:43 jberndt Exp $"
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -220,8 +220,9 @@ private:
     double           TimeSpan;
     string           Name;
     string           Description;
-    vector <FGPropertyManager*>  SetParam;
-    vector <FGPropertyManager*>  NotifyProperties;
+    vector <FGPropertyNode_ptr>  SetParam;
+    vector <std::string>  SetParamName;
+    vector <FGPropertyNode_ptr>  NotifyProperties;
     vector <string>              DisplayString;
     vector <eAction> Action;
     vector <eType>   Type;
index ddaf418298f5cc474d971c2e00ad6e4eb6fe13e4..e24cd2f621e1e601f0c3b5ee6e2b19606437504a 100644 (file)
@@ -45,7 +45,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGCondition.cpp,v 1.17 2012/10/27 20:29:01 jberndt Exp $";
+static const char *IdSrc = "$Id: FGCondition.cpp,v 1.18 2013/01/26 17:06:49 bcoconni Exp $";
 static const char *IdHdr = ID_CONDITION;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -126,7 +126,7 @@ FGCondition::FGCondition(const string& test, FGPropertyManager* PropertyManager)
     exit(-1);
   }
 
-  FGPropertyManager *node = PropertyManager->GetNode(property1, false);
+  FGPropertyNode *node = PropertyManager->GetNode(property1, false);
   if (node) {
     TestParam1 = new FGPropertyValue(node);
   } else {
index 0cad19512ec6b337c6ff6b77eb64a261e337879e..c64de4b507ff48a1b1d18e19693288d895859d86 100644 (file)
@@ -43,7 +43,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGFunction.cpp,v 1.46 2012/09/25 12:43:13 jberndt Exp $";
+static const char *IdSrc = "$Id: FGFunction.cpp,v 1.50 2013/06/10 02:05:12 jberndt Exp $";
 static const char *IdHdr = ID_FUNCTION;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -64,6 +64,9 @@ const std::string FGFunction::difference_string = "difference";
 const std::string FGFunction::product_string = "product";
 const std::string FGFunction::quotient_string = "quotient";
 const std::string FGFunction::pow_string = "pow";
+const std::string FGFunction::sqrt_string = "sqrt";
+const std::string FGFunction::toradians_string = "toradians";
+const std::string FGFunction::todegrees_string = "todegrees";
 const std::string FGFunction::exp_string = "exp";
 const std::string FGFunction::log2_string = "log2";
 const std::string FGFunction::ln_string = "ln";
@@ -121,6 +124,11 @@ FGFunction::FGFunction(FGPropertyManager* propMan, Element* el, const string& pr
   if (operation == function_string) {
     sCopyTo = el->GetAttributeValue("copyto");
     if (!sCopyTo.empty()) {
+
+      if (sCopyTo.find("#") != string::npos) {
+        if (is_number(Prefix)) sCopyTo = replace(sCopyTo,"#",Prefix);
+      }
+
       pCopyTo = PropertyManager->GetNode(sCopyTo);
       if (pCopyTo == 0L) cerr << "Property \"" << sCopyTo << "\" must be previously defined in function "
                               << Name << endl;
@@ -136,6 +144,12 @@ FGFunction::FGFunction(FGPropertyManager* propMan, Element* el, const string& pr
     Type = eQuotient;
   } else if (operation == pow_string) {
     Type = ePow;
+  } else if (operation == sqrt_string) {
+    Type = eSqrt;
+  } else if (operation == toradians_string) {
+    Type = eToRadians;
+  } else if (operation == todegrees_string) {
+    Type = eToDegrees;
   } else if (operation == log2_string) {
     Type = eLog2;
   } else if (operation == ln_string) {
@@ -240,13 +254,13 @@ FGFunction::FGFunction(FGPropertyManager* propMan, Element* el, const string& pr
           property_name = replace(property_name,"#",Prefix);
         }
       }
-      FGPropertyManager* newNode = 0L;
+      FGPropertyNode* newNode = 0L;
       if (PropertyManager->HasNode(property_name)) {
         newNode = PropertyManager->GetNode(property_name);
         Parameters.push_back(new FGPropertyValue( newNode ));
       } else {
-        cerr << fgcyan << "Warning: The property " + property_name + " is initially undefined."
-             << reset << endl;
+        // cerr << fgcyan << "Warning: The property " + property_name + " is initially undefined."
+        //      << reset << endl;
         Parameters.push_back(new FGPropertyValue( property_name,
                                                   PropertyManager ));
       }
@@ -260,6 +274,9 @@ FGFunction::FGFunction(FGPropertyManager* propMan, Element* el, const string& pr
                operation == sum_string ||
                operation == quotient_string ||
                operation == pow_string ||
+               operation == sqrt_string ||
+               operation == toradians_string ||
+               operation == todegrees_string ||
                operation == exp_string ||
                operation == log2_string ||
                operation == ln_string ||
@@ -385,6 +402,15 @@ double FGFunction::GetValue(void) const
   case ePow:
     temp = pow(temp,Parameters[1]->GetValue());
     break;
+  case eSqrt:
+    temp = sqrt(temp);
+    break;
+  case eToRadians:
+    temp *= M_PI/180.0;
+    break;
+  case eToDegrees:
+    temp *= 180.0/M_PI;
+    break;
   case eExp:
     temp = exp(temp);
     break;
@@ -780,13 +806,15 @@ void FGFunction::bind(void)
       }
     }
 
- // JMT commenting out on 2013/01/28 on advice of jentron - temporary fix
- // for in-flux JSBSim property tie changes.
- //   if (PropertyManager->HasNode(tmp)) {
- //     cout << "Property " << tmp << " has already been successfully bound (late)." << endl;
- //   } else {
+    if (PropertyManager->HasNode(tmp)) {
+      FGPropertyNode* property = PropertyManager->GetNode(tmp);
+      if (property->isTied()) {
+        cout << "Property " << tmp << " has already been successfully bound (late)." << endl;
+        return;
+      }
+    }
+
     PropertyManager->Tie( tmp, this, &FGFunction::GetValue);
- //   }
   }
 }
 
index 785648a827184324006a8ce09f870494c6467422..43fe4212d86b3dc4264e5b22526fdeff10209071 100644 (file)
@@ -37,12 +37,13 @@ INCLUDES
 #include <vector>
 #include <string>
 #include "FGParameter.h"
+#include "input_output/FGPropertyManager.h"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_FUNCTION "$Id: FGFunction.h,v 1.26 2012/09/25 12:43:13 jberndt Exp $"
+#define ID_FUNCTION "$Id: FGFunction.h,v 1.30 2013/06/10 02:25:18 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -50,7 +51,6 @@ FORWARD DECLARATIONS
 
 namespace JSBSim {
 
-class FGPropertyManager;
 class Element;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -69,6 +69,9 @@ A function definition consists of an operation, a value, a table, or a property
 - product (takes n args)
 - quotient (takes 2 args)
 - pow (takes 2 args)
+- sqrt (takes one argument)
+- toradians (takes one argument)
+- todegrees (takes one argument)
 - exp (takes 2 args)
 - log2 (takes 1 arg)
 - ln (takes 1 arg)
@@ -125,7 +128,7 @@ members of the function element. Almost always, the first operation within the
 function element will be a product or sum. For example:
 
 @code
-<function name="aero/coefficient/Clr">
+<function name="aero/moment/Clr">
     <description>Roll moment due to yaw rate</description>
     <product>
         <property>aero/qbar-area</property>
@@ -155,6 +158,535 @@ an operation (such as sum) which can contain other items. The point to keep in
 mind is that it evaluates to a single value - which is just what the trigonometric
 functions require (except atan2, which takes two arguments).
 
+<h2>Specific Function Definitions</h2>
+
+Note: In the definitions below, a "property" refers to a single property specified
+within either the <property></property> tag or the shortcut tag, \<p>\</p>. The
+keyword "value" refers to a single numeric value specified either within the \<value>\</value>
+tag or the shortcut <v></v> tag. The keyword "table" refers to a single table specified
+either within the \<table>\</table> tag or the shortcut <t></t> tag. The plural form of any
+of the three words refers to one or more instances of a property, value, or table.
+
+- @b sum, sums the values of all immediate child elements:
+    @code
+    <sum>
+      {properties, values, tables, or other function elements}
+    </sum>
+
+    Example: Mach + 0.01
+
+    <sum>
+      <p> velocities/mach </p>
+      <v> 0.01 </v>
+    </sum>
+    @endcode
+- @b difference, subtracts the values of all immediate child elements from the value of the first child element:
+    @code
+    <difference>
+      {properties, values, tables, or other function elements}
+    </difference>
+
+    Example: Mach - 0.01
+
+    <difference>
+      <p> velocities/mach </p>
+      <v> 0.01 </v>
+    </difference>
+    @endcode
+- @b product multiplies together the values of all immediate child elements:
+    @code
+    <product>
+      {properties, values, tables, or other function elements}
+    </product>
+
+    Example: qbar*S*beta*CY_beta
+
+    <product>
+      <property> aero/qbar-psf            </property>
+      <property> metrics/Sw-sqft          </property>
+      <property> aero/beta-rad            </property>
+      <property> aero/coefficient/CY_beta </property>
+    </product>
+    @endcode
+- @b quotient, divides the value of the first immediate child element by the second immediate child element:
+    @code
+    <quotient>
+      {property, value, table, or other function element}
+      {property, value, table, or other function element}
+    </quotient>
+
+    Example: (2*GM)/R
+
+    <quotient>
+      <product>
+        <v> 2.0 </v>
+        <p> guidance/executive/gm </p>
+      </product>
+      <p> position/radius-to-vehicle-ft </p>
+    </quotient>
+    @endcode
+- @b pow, raises the value of the first immediate child element to the power of the value
+          of the second immediate child element:
+    @code
+    <pow>
+      {property, value, table, or other function element}
+      {property, value, table, or other function element}
+    </pow>
+
+    Example: Mach^2
+
+    <pow>
+      <p> velocities/mach </p>
+      <v> 2.0 </v>
+    </pow>
+    @endcode
+- @b sqrt, takes the square root of the value of the immediate child element:
+    @code
+    <sqrt>
+      {property, value, table, or other function element}
+    </sqrt>
+
+    Example: square root of 25
+
+    <sqrt> <v> 25.0 </v> </sqrt>
+    @endcode
+- @b toradians, converts a presumed argument in degrees to radians by multiplying
+                the value of the immediate child element by pi/180:
+    @code
+    <toradians>
+      {property, value, table, or other function element}
+    </toradians>
+
+    Example: convert 45 degrees to radians
+
+    <toradians> <v> 45 </v> </toradians>
+    @endcode
+- @b todegrees, converts a presumed argument in radians to degrees by multiplying
+     the value of the immediate child element by 180/pi:
+    @code
+    <todegrees>
+      {property, value, table, or other function element}
+    </todegrees>
+
+    Example: convert 0.5*pi radians to degrees
+
+    <todegrees>
+      <product> <v> 0.5 </v> <pi/> </product>
+    </todegrees>
+    @endcode
+- @b exp, raises "e" to the power of the immediate child element:
+    @code
+    <exp>
+      {property, value, table, or other function element}
+    </exp>
+
+    Example: raise "e" to the 1.5 power, e^1.5
+
+    <exp> <v> 1.5 </v> </exp>
+    @endcode
+- @b log2, calculates the log base 2 value of the immediate child element:
+    @code
+    <log2>
+      {property, value, table, or other function element} 
+    </log2>
+
+    Example:
+    <log2> <v> 128 </v> </log2>
+    @endcode
+- @b ln, calculates the natural logarithm of the value of the immediate child element:
+    @code
+    <ln>
+      {property, value, table, or other function element}
+    </ln>
+    
+    Example: ln(128)
+
+    <ln> <v> 200 </v> </ln>
+    @endcode
+- @b log10 calculates the base 10 logarithm of the value of the immediate child element
+    @code
+    <log10>
+      {property, value, table, or other function element}
+    </log10>
+
+    Example log(Mach)
+
+    <log10> <p> velocities/mach </p> </log10>
+    @endcode
+- @b abs calculates the absolute value of the immediate child element
+    @code
+    <abs>
+      {property, value, table, or other function element}
+    </abs>
+
+    Example:
+
+    <abs> <p> flight-path/gamma-rad </p> </abs>
+    @endcode
+- @b sin calculates the sine of the value of the immediate child element (the argument is expected to be in radians)
+    @code
+    <sin>
+      {property, value, table, or other function element}
+    </sin>
+
+    Example:
+
+    <sin> <toradians> <p> fcs/heading-true-degrees </p> </toradians> </sin>
+    @endcode
+- @b cos calculates the cosine of the value of the immediate child element (the argument is expected to be in radians)
+    @code
+    <cos>
+      {property, value, table, or other function element}
+    </cos>
+
+    Example:
+
+    <cos> <toradians> <p> fcs/heading-true-degrees </p> </toradians> </cos>
+    @endcode
+- @b tan calculates the tangent of the value of the immediate child element (the argument is expected to be in radians)
+    @code
+    <tan>
+      {property, value, table, or other function element}
+    </tan>
+
+    Example:
+
+    <tan> <toradians> <p> fcs/heading-true-degrees </p> </toradians> </tan>
+    @endcode
+- @b asin calculates the arcsine (inverse sine) of the value of the immediate child element. The
+          value provided should be in the range from -1 to +1. The value returned
+          will be expressed in radians, and will be in the range from -pi/2 to
+          +pi/2.
+    @code
+    <asin>
+      {property, value, table, or other function element}
+    </asin>
+
+    Example:
+
+    <asin> <v> 0.5 </v> </asin>
+    @endcode
+- @b acos calculates the arccosine (inverse cosine) of the value of the immediate child element. The
+          value provided should be in the range from -1 to +1. The value returned
+          will be expressed in radians, and will be in the range from 0 to pi.
+    @code
+    <acos>
+      {property, value, table, or other function element}
+    </acos>
+
+    Example:
+
+    <acos> <v> 0.5 </v> </acos>
+    @endcode
+- @b atan calculates the inverse tangent of the value of the immediate child element.
+          The value returned will be expressed in radians, and will be in the
+          range from -pi/2 to +pi/2.
+    @code
+    <atan>
+      {property, value, table, or other function element}
+    </atan>
+
+    Example:
+
+    <atan> <v> 0.5 </v> </atan>
+    @endcode
+- @b atan2 calculates the inverse tangent of the value of the immediate child
+           elements, Y/X (in that order). It even works for X values near zero.
+           The value returned will be expressed in radians, and in the range
+           -pi to +pi.
+    @code
+    <atan2>
+      {property, value, table, or other function element} {property, value, table, or other function element}
+    </atan2>
+
+    Example: inverse tangent of 0.5/0.25, evaluates to: 1.107 radians
+
+    <atan2> <v> 0.5 </<v> <v> 0.25 </v> </atan2>
+    @endcode
+- @b min returns the smallest value from all the immediate child elements
+    @code
+    <min>
+      {properties, values, tables, or other function elements}
+    </min>
+    
+    Example: returns the lesser of velocity and 2500
+
+    <min>
+      <p> velocities/eci-velocity-mag-fps </p>
+      <v> 2500.0 </v>
+    </min>
+    @endcode
+- @b max returns the largest value from all the immediate child elements
+    @code
+    <max>
+      {properties, values, tables, or other function elements}
+    </max>
+    
+    Example: returns the greater of velocity and 15000
+
+    <max>
+      <p> velocities/eci-velocity-mag-fps </p>
+      <v> 15000.0 </v>
+    </max>
+    @endcode
+- @b avg returns the average value of all the immediate child elements
+    @code
+    <avg>
+      {properties, values, tables, or other function elements} 
+    </avg>
+
+    Example: returns the average of the four numbers below, evaluates to 0.50.
+
+    <avg>
+      <v> 0.25 </v>
+      <v> 0.50 </v>
+      <v> 0.75 </v>
+      <v> 0.50 </v>
+    </avg>
+    @endcode
+- @b fraction returns the fractional part of the value of the immediate child element 
+    @code
+    <fraction>
+      {property, value, table, or other function element}
+    </fraction>
+
+    Example: returns the fractional part of pi - or, roughly, 0.1415926...
+
+    <fraction> <pi/> </fraction>
+    @endcode
+- @b integer returns the integer portion of the value of the immediate child element
+    @code
+    <integer>
+      {property, value, table, or other function element}
+    </integer>
+    @endcode
+- @b mod returns the remainder from the integer division of the value of the
+         first immediate child element by the second immediate child element,
+         X/Y (X modulo Y). The value returned is the value X-I*Y, for the
+         largest  integer I such  that if Y is nonzero, the result has the
+         same sign as X and magnitude less than the magnitude of Y. For
+         instance, the expression "5 mod 2" would evaluate to 1 because 5
+         divided by 2 leaves a quotient of 2 and a remainder of 1, while
+         "9 mod 3" would evaluate to 0 because the division of 9 by 3 has a
+         quotient of 3 and leaves a remainder of 0.
+    @code
+    <mod>
+      {property, value, table, or other function element} {property, value, table, or other function element}
+    </mod>
+
+    Example: 5 mod 2, evaluates to 1
+
+    <mod> <v> 5 </v> <v> 2 </v> </mod>
+    @endcode
+- @b lt returns a 1 if the value of the first immediate child element is less
+        than the value of the second immediate child element, returns 0
+        otherwise
+    @code
+    <lt>
+      {property, value, table, or other function element}
+      {property, value, table, or other function element}
+    </lt>
+
+    Example: returns 1 if thrust is less than 10,000, returns 0 otherwise
+
+    <lt>
+      <p> propulsion/engine[2]/thrust-lbs </p>
+      <v> 10000.0 </v>
+    </lt>
+    @endcode
+- @b le returns a 1 if the value of the first immediate child element is less
+        than or equal to the value of the second immediate child element, returns 0
+        otherwise
+    @code
+    <le>
+      {property, value, table, or other function element}
+      {property, value, table, or other function element}
+    </le>
+
+    Example: returns 1 if thrust is less than or equal to 10,000, returns 0 otherwise
+
+    <le>
+      <p> propulsion/engine[2]/thrust-lbs </p>
+      <v> 10000.0 </v>
+    </le>
+    @endcode
+- @b gt returns a 1 if the value of the first immediate child element is greater
+        than the value of the second immediate child element, returns 0
+        otherwise
+    @code
+    <gt>
+      {property, value, table, or other function element}
+      {property, value, table, or other function element}
+    </gt>
+
+    Example: returns 1 if thrust is greater than 10,000, returns 0 otherwise
+
+    <gt>
+      <p> propulsion/engine[2]/thrust-lbs </p>
+      <v> 10000.0 </v>
+    </gt>
+    @endcode
+- @b ge returns a 1 if the value of the first immediate child element is greater
+        than or equal to the value of the second immediate child element, returns 0
+        otherwise
+    @code
+    <ge>
+      {property, value, table, or other function element}
+      {property, value, table, or other function element}
+    </ge>
+
+    Example: returns 1 if thrust is greater than or equal to 10,000, returns 0 otherwise
+
+    <ge>
+      <p> propulsion/engine[2]/thrust-lbs </p>
+      <v> 10000.0 </v>
+    </ge>
+    @endcode
+- @b eq returns a 1 if the value of the first immediate child element is 
+        equal to the second immediate child element, returns 0
+        otherwise
+    @code
+    <eq>
+      {property, value, table, or other function element}
+      {property, value, table, or other function element}
+    </eq>
+
+    Example: returns 1 if thrust is equal to 10,000, returns 0 otherwise
+
+    <eq>
+      <p> propulsion/engine[2]/thrust-lbs </p>
+      <v> 10000.0 </v>
+    </eq>
+    @endcode
+- @b nq returns a 1 if the value of the first immediate child element is not
+        equal to the value of the second immediate child element, returns 0
+        otherwise
+    @code
+    <nq>
+      {property, value, table, or other function element}
+      {property, value, table, or other function element}
+    </nq>
+
+    Example: returns 1 if thrust is not 0, returns 0 otherwise
+
+    <nq>
+      <p> propulsion/engine[2]/thrust-lbs </p>
+      <v> 0.0 </v>
+    </nq>
+    @endcode
+- @b and returns a 1 if the values of the immediate child elements are all 1,
+         returns 0 otherwise. Values provided are expected to be either 1 or 0
+         within machine precision.
+    @code
+    <and>
+      {properties, values, tables, or other function elements}
+    </and>
+
+    Example: returns 1 if the specified flags are all 1
+
+    <and>
+      <p> guidance/first-stage-flight-flag </p>
+      <p> control/engines-running-flag </p>
+    </and>
+    @endcode
+- @b or returns a 1 if the values of any of the immediate child elements 1,
+         returns 0 otherwise. Values provided are expected to be either 1 or 0
+         within machine precision.
+    @code
+    <or>
+      {properties, values, tables, or other function elements}
+    </or>
+
+    Example: returns 1 if any of the specified flags are 1
+
+    <or>
+      <p> guidance/first-stage-flight-flag </p>
+      <p> control/engines-running-flag </p>
+    </or>
+    @endcode
+- @b not returns the inverse of the value of the supplied immediate child element
+         (e.g., returns 1 if supplied a 0)
+    @code
+    <not>
+      {property, value, table, or other function element} 
+    </not>
+
+    Example: returns 0 if the value of the supplied flag is 1
+
+    <not> <p> guidance/first-stage-flight-flag </p> </not>
+    @endcode
+- @b ifthen if the value of the first immediate child element is 1, then the
+             value of the second immediate child element is returned, otherwise
+             the value of the third child element is returned
+     @code
+     <ifthen>
+       {property, value, table, or other function element}
+       {property, value, table, or other function element}
+       {property, value, table, or other function element}
+     </ifthen>
+
+     Example: if flight-mode is greater than 2, then a value of 0.00 is returned, 
+              otherwise the value of the property control/pitch-lag is returned.
+
+     <ifthen>
+       <gt> <p> executive/flight-mode </p> <v> 2 </v> </gt>
+       <v> 0.00 </v>
+       <p> control/pitch-lag </p>
+     </ifthen>
+     @endcode
+- @b switch uses the integer value of the first immediate child element as an
+            index to select one of the subsequent immediate child elements to
+            return the value of
+     @code
+     <switch>
+       {property, value, table, or other function element}
+       {property, value, table, or other function element}
+       {property, value, table, or other function element}
+       ...
+     </switch>
+
+     Example: if flight-mode is 2, the switch function returns 0.50
+
+     <switch>
+       <p> executive/flight-mode </p>
+       <v> 0.25 </v>
+       <v> 0.50 </v>
+       <v> 0.75 </v>
+       <v> 1.00 </v>
+     </switch>
+     @endcode
+- @b random Takes no arguments and returns a Gaussian distributed random number
+    @code <random/> @endcode
+- @b urandom Takes no arguments and returns a uniformly distributed random number
+             between -1 and +1
+    @code<urandom/>@endcode
+- @b pi Takes no argument and returns the value of Pi
+    @code<pi/>@endcode
+- @b interpolate1d returns the result from a 1-dimensional interpolation of the
+                   supplied values, with the value of the first immediate child
+                   element representing the lookup value into the table, and the
+                   following pairs of values representing the independent and
+                   dependent values. The first provided child element is expected
+                   to be a property. The interpolation does not extrapolate, but
+                   holds the highest value if the provided lookup value goes
+                   outside of the provided range.
+     @code
+     <interpolate1d>
+       {property, value, table, or other function element}
+       {property, value, table, or other function element} {property, value, table, or other function element}
+       ...
+     </interpolate1d>
+
+     Example: If mach is 0.4, the interpolation will return 0.375. If mach is 1.5, the interpolation
+              will return 0.60.
+
+     <interpolate1d>
+       <p> velocities/mach </p>
+       <v> 0.00 </v>  <v> 0.25 </v>
+       <v> 0.80 </v>  <v> 0.50 </v>
+       <v> 0.90 </v>  <v> 0.60 </v>
+       </interpolate1d>
+     @endcode
 @author Jon Berndt
 */
 
@@ -225,6 +757,9 @@ private:
   static const std::string product_string;
   static const std::string quotient_string;
   static const std::string pow_string;
+  static const std::string sqrt_string;
+  static const std::string toradians_string;
+  static const std::string todegrees_string;
   static const std::string exp_string;
   static const std::string log2_string;
   static const std::string ln_string;
@@ -265,8 +800,8 @@ private:
   static const std::string switch_string;
   static const std::string interpolate1d_string;
   double cachedValue;
-  enum functionType {eTopLevel=0, eProduct, eDifference, eSum, eQuotient, ePow,
-                     eExp, eAbs, eSign, eSin, eCos, eTan, eASin, eACos, eATan, eATan2,
+  enum functionType {eTopLevel=0, eProduct, eDifference, eSum, eQuotient, ePow, eSqrt, eToRadians,
+                     eToDegrees, eExp, eAbs, eSign, eSin, eCos, eTan, eASin, eACos, eATan, eATan2,
                      eMin, eMax, eAvg, eFrac, eInteger, eMod, eRandom, eUrandom, ePi,
                      eLog2, eLn, eLog10, eLT, eLE, eGE, eGT, eEQ, eNE,  eAND, eOR, eNOT,
                      eIfThen, eSwitch, eInterpolate1D, eRotation_alpha_local,
@@ -274,7 +809,7 @@ private:
                      eRotation_wf_to_bf} Type;
   std::string Name;
   std::string sCopyTo;        // Property name to copy function value to
-  FGPropertyManager* pCopyTo; // Property node for CopyTo property string
+  FGPropertyNode_ptr pCopyTo; // Property node for CopyTo property string
 
   unsigned int GetBinary(double) const;
   void bind(void);
index 55fe50018fdd2181df1d293e6fbc02d8dc307977..c38cb5d500cc786d904f7fbd17d7e718d3bab9fb 100644 (file)
@@ -3,16 +3,16 @@
  * Copyright (C) James Goppert 2010 <james.goppert@gmail.com>
  *
  * FGNelderMead.cpp is free software: you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
+ * 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.
  *
  * FGNelderMead.cpp 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 General Public License for more details.
+ * See the GNU Lesser General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License along
+ * You should have received a copy of the GNU Lesser General Public License along
  * with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
@@ -22,6 +22,7 @@
 #include <cstdlib>
 #include <iomanip>
 #include <iostream>
+#include <sstream>
 #include <stdexcept>
 #include <ctime>
 
@@ -33,7 +34,7 @@ FGNelderMead::FGNelderMead(Function * f, const std::vector<double> & initialGues
                            const std::vector<double> & upperBound,
                            const std::vector<double> & initialStepSize, int iterMax,
                            double rtol, double abstol, double speed, double randomization,
-                                                  bool showConvergeStatus,
+                           bool showConvergeStatus,
                            bool showSimplex, bool pause, Callback * callback) :
         m_f(f), m_callback(callback), m_randomization(randomization),
         m_lowerBound(lowerBound), m_upperBound(upperBound),
@@ -41,227 +42,227 @@ FGNelderMead::FGNelderMead(Function * f, const std::vector<double> & initialGues
         m_iMax(1), m_iNextMax(1), m_iMin(1),
         m_simplex(m_nVert), m_cost(m_nVert), m_elemSum(m_nDim),
         m_status(1),
-               initialGuess(initialGuess), initialStepSize(initialStepSize),
-               iterMax(iterMax), iter(), rtol(rtol), abstol(abstol),
-               speed(speed), showConvergeStatus(showConvergeStatus), showSimplex(showSimplex),
-               pause(pause), rtolI(), minCostPrevResize(1), minCost(), minCostPrev(), maxCost(),
-               nextMaxCost()
+        initialGuess(initialGuess), initialStepSize(initialStepSize),
+        iterMax(iterMax), iter(), rtol(rtol), abstol(abstol),
+        speed(speed), showConvergeStatus(showConvergeStatus), showSimplex(showSimplex),
+        pause(pause), rtolI(), minCostPrevResize(1), minCost(), minCostPrev(), maxCost(),
+        nextMaxCost()
 {
-       srand ( time(NULL) ); // seed random number generator
+    srand ( time(NULL) ); // seed random number generator
 }
 
 void FGNelderMead::update()
 {
     std::cout.precision(3);
 
-       // reinitialize simplex whenever rtol condition is met
-       if ( rtolI < rtol || iter == 0)
-       {
-               std::vector<double> guess(m_nDim);
-               if (iter == 0)
-               {
-                       //std::cout << "constructing simplex" << std::endl;
-                       guess = initialGuess;
-               }
-               else
-               {
-                       if (std::abs(minCost-minCostPrevResize) < abstol)
-                       {
-                               std::cout << "\nunable to escape local minimum" << std::endl;
-                               m_status = -1;
-                               return;
-                       }
-                       //std::cout << "reinitializing step size" << std::endl;
-                       guess = m_simplex[m_iMin];
-                       minCostPrevResize = minCost;
-               }
-               constructSimplex(guess,initialStepSize);
-       }
-
-       // find vertex costs
-       for (int vertex=0;vertex<m_nVert;vertex++)
-       {
-               try
-               {
-                       m_cost[vertex] = m_f->eval(m_simplex[vertex]);
-               }
-               catch (const std::exception & e)
-               {
-                       m_status = -1;
-                       throw;
-                       return;
-               }
-       }
-
-       // find max cost, next max cost, and min cost
-       m_iMax = m_iNextMax = m_iMin = 0;
-       for (int vertex=0;vertex<m_nVert;vertex++)
-       {
-               if ( m_cost[vertex] > m_cost[m_iMax] )
-               {
-                       m_iMax = vertex;
-               }
-               else if ( m_cost[vertex] > m_cost[m_iNextMax] || m_iMax == m_iNextMax ) m_iNextMax = vertex;
-               else if ( m_cost[vertex] < m_cost[m_iMin] ) m_iMin = vertex;
-
-       }
-
-       // callback
-       if (m_callback) m_callback->eval(m_simplex[m_iMin]);
-
-       // compute relative tolerance
-       rtolI = 2*std::abs(m_cost[m_iMax] -
-                                          m_cost[m_iMin])/(std::abs(m_cost[m_iMax]+std::abs(m_cost[m_iMin])+
-                                                                                                std::numeric_limits<double>::epsilon()));
-
-       // check for max iteration break condition
-       if (iter > iterMax)
-       {
-               std::cout << "\nmax iterations exceeded" << std::endl;
-               m_status = -1;
-               return;
-       }
-       // check for convergence break condition
-       else if ( m_cost[m_iMin] < abstol )
-       {
-               std::cout << "\nsimplex converged" << std::endl;
-               m_status = 0;
-               return;
-       }
-
-       // compute element sum of simplex vertices
-       for (int dim=0;dim<m_nDim;dim++)
-       {
-               m_elemSum[dim] = 0;
-               for (int vertex=0;vertex<m_nVert;vertex++)
-                       m_elemSum[dim] += m_simplex[vertex][dim];
-       }
-
-       // min and max costs
-       minCostPrev = minCost;
-       minCost = m_cost[m_iMin];
-       maxCost = m_cost[m_iMax];
-       nextMaxCost = m_cost[m_iNextMax];
-
-       // output cost and simplex
-       if (showConvergeStatus)
-       {
-               if ( (minCostPrev + std::numeric_limits<float>::epsilon() )
-                               < minCost && minCostPrev != 0)
-               {
-                       std::cout << "\twarning: simplex cost increased"
-                                         << std::scientific
-                                         << "\n\tcost: " << minCost
-                                         << "\n\tcost previous: " << minCostPrev
-                                         << std::fixed << std::endl;
-               }
-
-               std::cout << "i: " << iter
-                                 << std::scientific
-                                 << "\tcost: " << m_cost[m_iMin]
-                                 << "\trtol: " << rtolI
-                                 << std::fixed
-                                 << "\talpha: " << m_simplex[m_iMin][2]*180/M_PI
-                                 << "\tbeta: " << m_simplex[m_iMin][5]*180/M_PI
-                                 << "\tthrottle: " << m_simplex[m_iMin][0]
-                                 << "\televator: " << m_simplex[m_iMin][1]
-                                 << "\taileron: " << m_simplex[m_iMin][3]
-                                 << "\trudder: " << m_simplex[m_iMin][4]
-                                 << std::endl;
-       }
-       if (showSimplex)
-       {
-               std::cout << "simplex: " << std::endl;;
-               for (int j=0;j<m_nVert;j++)
-                       std::cout << "\t" << std::scientific
-                                         << std::setw(10) << m_cost[j];
-               std::cout << std::endl;
-               for (int j=0;j<m_nVert;j++) std::cout << "\t\t" << j;
-               std::cout << std::endl;
-               for (int i=0;i<m_nDim;i++)
-               {
-                       for (int j=0;j<m_nVert;j++)
-                               std::cout << "\t" << std::setw(10) << m_simplex[j][i];
-                       std::cout << std::endl;
-               }
-               std::cout << std::fixed
-                                 << "\n\tiMax: " <<  m_iMax
-                                 << "\t\tiNextMax: " <<  m_iNextMax
-                                 << "\t\tiMin: " <<  m_iMin << std::endl;
-       }
-
-       if (pause)
-       {
-               std::cout << "paused, press any key to continue" << std::endl;
-               std::cin.get();
-       }
-
-
-       // costs
-       
-       try
-       {
-               // try inversion
-               double costTry = tryStretch(-1.0);
-               //std::cout << "cost Try 0: " << costTry << std::endl;
-
-               // if lower cost than best, then try further stretch by double speed factor
-               if (costTry < minCost)
-               {
-                       double costTry0 = costTry;
-                       costTry = tryStretch(speed);
-                       //std::cout << "cost Try 1: " << costTry << std::endl;
-
-                       if (showSimplex)
-                       {
-                               if (costTry < costTry0) std::cout << "inversion about: " << m_iMax << std::endl;
-                               else std::cout << "inversion and stretch about: " << m_iMax << std::endl;
-                       }
-               }
-               // otherwise try a contraction
-               else if (costTry > nextMaxCost)
-               {
-                       // 1d contraction
-                       costTry = tryStretch(1./speed);
-                       //std::cout << "cost Try 2: " << costTry << std::endl;
-
-                       // if greater than max cost, contract about min
-                       if (costTry > maxCost)
-                       {
-                               if (showSimplex)
-                                       std::cout << "multiD contraction about: " << m_iMin << std::endl;
-                               contract();
-                       }
-                       else
-                       {
-                               if (showSimplex)
-                                       std::cout << "contraction about: " << m_iMin << std::endl;
-                       }
-               }
-       }
-
-       catch (const std::exception & e)
-       {
-               throw;
-               m_status = -1;
-               return;
-       }
-
-       // iteration
-       iter++;
+    // reinitialize simplex whenever rtol condition is met
+    if ( rtolI < rtol || iter == 0)
+    {
+        std::vector<double> guess(m_nDim);
+        if (iter == 0)
+        {
+            //std::cout << "constructing simplex" << std::endl;
+            guess = initialGuess;
+        }
+        else
+        {
+            if (std::abs(minCost-minCostPrevResize) < std::numeric_limits<float>::epsilon())
+            {
+                throw std::runtime_error("unable to escape local minimum!");
+                m_status = -1;
+                return;
+            }
+            //std::cout << "reinitializing step size" << std::endl;
+            guess = m_simplex[m_iMin];
+            minCostPrevResize = minCost;
+        }
+        constructSimplex(guess,initialStepSize);
+    }
+
+    // find vertex costs
+    for (int vertex=0;vertex<m_nVert;vertex++)
+    {
+        try
+        {
+            m_cost[vertex] = eval(m_simplex[vertex]);   
+        }
+        catch (const std::exception & e)
+        {
+            m_status = -1;
+            throw;
+            return;
+        }
+    }
+
+    // find max cost, next max cost, and min cost
+    m_iMax = m_iNextMax = m_iMin = 0;
+    for (int vertex=0;vertex<m_nVert;vertex++)
+    {
+        if ( m_cost[vertex] > m_cost[m_iMax] )
+        {
+            m_iMax = vertex;
+        }
+        else if ( m_cost[vertex] > m_cost[m_iNextMax] || m_iMax == m_iNextMax ) m_iNextMax = vertex;
+        else if ( m_cost[vertex] < m_cost[m_iMin] ) m_iMin = vertex;
+
+    }
+
+    // callback
+    if (m_callback) m_callback->eval(m_simplex[m_iMin]);
+
+    // compute relative tolerance
+    rtolI = 2*std::abs(m_cost[m_iMax] -
+                       m_cost[m_iMin])/(std::abs(m_cost[m_iMax]+std::abs(m_cost[m_iMin])+
+                                                 std::numeric_limits<double>::epsilon()));
+
+    // check for max iteration break condition
+    if (iter > iterMax)
+    {
+        m_status = -1;
+        throw std::runtime_error("max iterations exceeded!");
+        return;
+    }
+    // check for convergence break condition
+    else if ( m_cost[m_iMin] < abstol )
+    {
+        //std::cout << "\nsimplex converged" << std::endl;
+        m_status = 0;
+        return;
+    }
+
+    // compute element sum of simplex vertices
+    for (int dim=0;dim<m_nDim;dim++)
+    {
+        m_elemSum[dim] = 0;
+        for (int vertex=0;vertex<m_nVert;vertex++)
+            m_elemSum[dim] += m_simplex[vertex][dim];
+    }
+
+    // min and max costs
+    minCostPrev = minCost;
+    minCost = m_cost[m_iMin];
+    maxCost = m_cost[m_iMax];
+    nextMaxCost = m_cost[m_iNextMax];
+
+    // output cost and simplex
+    if (showConvergeStatus)
+    {
+        if ( (minCostPrev + std::numeric_limits<float>::epsilon() )
+                < minCost && minCostPrev != 0)
+        {
+            std::cout << "\twarning: simplex cost increased"
+                      << std::scientific
+                      << "\n\tcost: " << minCost
+                      << "\n\tcost previous: " << minCostPrev
+                      << std::fixed << std::endl;
+        }
+
+        std::cout << "i: " << iter
+                  << std::scientific
+                  << "\tcost: " << m_cost[m_iMin]
+                  << "\trtol: " << rtolI
+                  << std::fixed
+                  << "\talpha: " << m_simplex[m_iMin][2]*180/M_PI
+                  << "\tbeta: " << m_simplex[m_iMin][5]*180/M_PI
+                  << "\tthrottle: " << m_simplex[m_iMin][0]
+                  << "\televator: " << m_simplex[m_iMin][1]
+                  << "\taileron: " << m_simplex[m_iMin][3]
+                  << "\trudder: " << m_simplex[m_iMin][4]
+                  << std::endl;
+    }
+    if (showSimplex)
+    {
+        std::cout << "simplex: " << std::endl;;
+        for (int j=0;j<m_nVert;j++)
+            std::cout << "\t" << std::scientific
+                      << std::setw(10) << m_cost[j];
+        std::cout << std::endl;
+        for (int j=0;j<m_nVert;j++) std::cout << "\t\t" << j;
+        std::cout << std::endl;
+        for (int i=0;i<m_nDim;i++)
+        {
+            for (int j=0;j<m_nVert;j++)
+                std::cout << "\t" << std::setw(10) << m_simplex[j][i];
+            std::cout << std::endl;
+        }
+        std::cout << std::fixed
+                  << "\n\tiMax: " <<  m_iMax
+                  << "\t\tiNextMax: " <<  m_iNextMax
+                  << "\t\tiMin: " <<  m_iMin << std::endl;
+    }
+
+    if (pause)
+    {
+        std::cout << "paused, press any key to continue" << std::endl;
+        std::cin.get();
+    }
+
+
+    // costs
+    
+    try
+    {
+        // try inversion
+        double costTry = tryStretch(-1.0);
+        //std::cout << "cost Try 0: " << costTry << std::endl;
+
+        // if lower cost than best, then try further stretch by double speed factor
+        if (costTry < minCost)
+        {
+            double costTry0 = costTry;
+            costTry = tryStretch(speed);
+            //std::cout << "cost Try 1: " << costTry << std::endl;
+
+            if (showSimplex)
+            {
+                if (costTry < costTry0) std::cout << "inversion about: " << m_iMax << std::endl;
+                else std::cout << "inversion and stretch about: " << m_iMax << std::endl;
+            }
+        }
+        // otherwise try a contraction
+        else if (costTry > nextMaxCost)
+        {
+            // 1d contraction
+            costTry = tryStretch(1./speed);
+            //std::cout << "cost Try 2: " << costTry << std::endl;
+
+            // if greater than max cost, contract about min
+            if (costTry > maxCost)
+            {
+                if (showSimplex)
+                    std::cout << "multiD contraction about: " << m_iMin << std::endl;
+                contract();
+            }
+            else
+            {
+                if (showSimplex)
+                    std::cout << "contraction about: " << m_iMin << std::endl;
+            }
+        }
+    }
+
+    catch (const std::exception & e)
+    {
+        throw;
+        m_status = -1;
+        return;
+    }
+
+    // iteration
+    iter++;
 
 }
 
 int FGNelderMead::status()
 {
-       return m_status;
+    return m_status;
 }
 
 double FGNelderMead::getRandomFactor()
 {
-       double randFact = 1+(float(rand() % 1000)/500-1)*m_randomization;
-       //std::cout << "random factor: " << randFact << std::endl;;
-       return randFact;
+    double randFact = 1+(float(rand() % 1000)/500-1)*m_randomization;
+    //std::cout << "random factor: " << randFact << std::endl;;
+    return randFact;
 }
 
 std::vector<double> FGNelderMead::getSolution()
@@ -271,8 +272,8 @@ std::vector<double> FGNelderMead::getSolution()
 
 double FGNelderMead::tryStretch(double factor)
 {
-       // randomize factor so we can avoid locking situations
-       factor = factor*getRandomFactor();
+    // randomize factor so we can avoid locking situations
+    factor = factor*getRandomFactor();
 
     // create trial vertex
     double a= (1.0-factor)/m_nDim;
@@ -285,23 +286,7 @@ double FGNelderMead::tryStretch(double factor)
     }
 
     // find trial cost
-       double costTry0 = 0, costTry = 0;
-       try
-       {
-       costTry0 = m_f->eval(tryVertex);
-       costTry = m_f->eval(tryVertex);
-       }
-       catch(const std::exception & e)
-       {
-               throw;
-               return 0;
-       }
-
-    if (std::abs(costTry0-costTry) > std::numeric_limits<float>::epsilon())
-    {
-               //std::cout << "\twarning: dynamics not stable!" << std::endl;
-        //return 1000000*m_cost[m_iMax];
-    }
+    double costTry = eval(tryVertex);
 
     // if trial cost lower than max
     if (costTry < m_cost[m_iMax])
@@ -337,7 +322,7 @@ void FGNelderMead::constructSimplex(const std::vector<double> & guess,
     for (int vertex=0;vertex<m_nVert;vertex++)
     {
         m_simplex[vertex] = guess;
-       }
+    }
 
     for (int dim=0;dim<m_nDim;dim++)
     {
@@ -370,6 +355,30 @@ void FGNelderMead::boundVertex(std::vector<double> & vertex,
     }
 }
 
+double FGNelderMead::eval(const std::vector<double> & vertex, bool check)
+{
+    if (check) {
+        double cost0 = m_f->eval(vertex);
+        double cost1 = m_f->eval(vertex);
+        if ((cost0 - cost1) > std::numeric_limits<float>::epsilon()) {
+            std::stringstream msg;
+            msg.precision(10);
+            msg << std::scientific
+                << "dynamics not stable!"
+                << "\tdiff: " << cost1 - cost0
+                << "\tcost0: " << cost0
+                << "\tcost1: " << cost1
+                << std::endl;
+            std::cout << msg.str();
+            //throw std::runtime_error(msg.str());
+        } else {
+            return cost1;
+        }
+    } else {
+        return m_f->eval(vertex);
+    }
+}
+
 } // JSBSim
 
 
index 64eb43fc4a7486bb1b4e385d258d50a1c6550ad4..474f1fb9b6b6bd4a8719f556f7f9f26a23ad6df1 100644 (file)
@@ -3,16 +3,16 @@
  * Copyright (C) James Goppert 2010 <james.goppert@gmail.com>
  *
  * FGNelderMead.h is free software: you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
+ * 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.
  *
  * FGNelderMead.h 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 General Public License for more details.
+ * See the GNU Lesser General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License along
+ * You should have received a copy of the GNU Lesser General Public License along
  * with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
@@ -35,7 +35,7 @@ public:
         virtual double eval(const std::vector<double> & v)  = 0;
         virtual ~Function() {};
     };
-       class Callback
+    class Callback
     {
     public:
         virtual void eval(const std::vector<double> & v)  = 0;
@@ -49,43 +49,44 @@ public:
                  double rtol=std::numeric_limits<float>::epsilon(),
                  double abstol=std::numeric_limits<float>::epsilon(),
                  double speed = 2.0,
-                                double randomization=0.1,
+                 double randomization=0.1,
                  bool showConvergeStatus=true,bool showSimplex=false,
                  bool pause=false,
-                                Callback * callback=NULL);
+                 Callback * callback=NULL);
     std::vector<double> getSolution();
 
-       void update();
-       int status();
+    void update();
+    int status();
 
 private:
     // attributes
     Function * m_f;
-       Callback * m_callback;
-       double m_randomization;
+    Callback * m_callback;
+    double m_randomization;
     const std::vector<double> & m_lowerBound;
     const std::vector<double> & m_upperBound;
     int m_nDim, m_nVert, m_iMax, m_iNextMax, m_iMin;
     std::vector< std::vector<double> > m_simplex;
     std::vector<double> m_cost;
     std::vector<double> m_elemSum;
-       int m_status;
+    int m_status;
     const std::vector<double> & initialGuess;
     const std::vector<double> & initialStepSize;
-       int iterMax, iter;
-       double rtol,abstol,speed;
-       bool showConvergeStatus, showSimplex, pause;
-       double rtolI, minCostPrevResize, minCost, minCostPrev,
-                  maxCost, nextMaxCost;
+    int iterMax, iter;
+    double rtol,abstol,speed;
+    bool showConvergeStatus, showSimplex, pause;
+    double rtolI, minCostPrevResize, minCost, minCostPrev,
+           maxCost, nextMaxCost;
 
     // methods
-       double getRandomFactor();
+    double getRandomFactor();
     double tryStretch(double factor);
     void contract();
     void constructSimplex(const std::vector<double> & guess, const std::vector<double> & stepSize);
     void boundVertex(std::vector<double> & vertex,
                      const std::vector<double> & upperBound,
                      const std::vector<double> & lowerBound);
+    double eval(const std::vector<double> & vertex, bool check = false);
 };
 
 } // JSBSim
index 7f448da3c4a770af605d162c75b905974b5c0142..1407a0cb72b03ee57e00b5cd442a12b8842180f6 100644 (file)
@@ -30,17 +30,18 @@ INCLUDES
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
 #include "FGPropertyValue.h"
+#include "input_output/FGPropertyManager.h"
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGPropertyValue.cpp,v 1.7 2011/04/05 20:20:21 andgi Exp $";
+static const char *IdSrc = "$Id: FGPropertyValue.cpp,v 1.8 2013/01/26 17:06:49 bcoconni Exp $";
 static const char *IdHdr = ID_PROPERTYVALUE;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 CLASS IMPLEMENTATION
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-FGPropertyValue::FGPropertyValue(FGPropertyManager* propNode)
+FGPropertyValue::FGPropertyValue(FGPropertyNode* propNode)
   : PropertyManager(0L), PropertyNode(propNode)
 {
 }
@@ -56,7 +57,7 @@ FGPropertyValue::FGPropertyValue(std::string propName, FGPropertyManager* proper
 
 double FGPropertyValue::GetValue(void) const
 {
-  FGPropertyManager* node = PropertyNode;
+  FGPropertyNode* node = PropertyNode;
 
   if (!PropertyNode) {
     // The node cannot be cached since this is a const method.
index c716cf59976dfe6ee4cc5116e3a28784c6bbc547..4ea0e5393dee00259806accfeee7817822329220 100644 (file)
@@ -42,7 +42,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_PROPERTYVALUE "$Id: FGPropertyValue.h,v 1.9 2011/04/05 20:20:21 andgi Exp $"
+#define ID_PROPERTYVALUE "$Id: FGPropertyValue.h,v 1.10 2013/01/26 17:06:49 bcoconni Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -66,18 +66,18 @@ class FGPropertyValue : public FGParameter
 {
 public:
 
-  FGPropertyValue(FGPropertyManager* propNode);
+  FGPropertyValue(FGPropertyNode* propNode);
   FGPropertyValue(std::string propName, FGPropertyManager* propertyManager);
   ~FGPropertyValue() {};
 
   double GetValue(void) const;
-  void SetNode(FGPropertyManager* node) {PropertyNode = node;} 
+  void SetNode(FGPropertyNode* node) {PropertyNode = node;}
 
   std::string GetName(void) const;
 
 private:
   FGPropertyManager* PropertyManager; // Property root used to do late binding.
-  FGPropertyManager* PropertyNode;
+  FGPropertyNode_ptr PropertyNode;
   std::string PropertyName;
 };
 
index b659950988c3ba1d11bbcfe91e8dd7e1a439e591..77f080ba131446557401f97714a71564e4a36ad5 100644 (file)
@@ -3,22 +3,23 @@
  * Copyright (C) James Goppert 2010 <james.goppert@gmail.com>
  *
  * FGStateSpace.cpp is free software: you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
+ * 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.
  *
  * FGStateSpace.cpp 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 General Public License for more details.
+ * See the GNU Lesser General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License along
+ * You should have received a copy of the GNU Lesser General Public License along
  * with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
 #include "FGStateSpace.h"
 #include <limits>
 #include <iomanip>
+#include <string>
 
 namespace JSBSim
 {
@@ -77,7 +78,23 @@ void FGStateSpace::numericalJacobian(std::vector< std::vector<double> >  & J, Co
             if (computeYDerivative) fn2 = y.getDeriv(iY);
             else fn2 = y.get(iY);
 
-            J[iY][iX] = (8*(f1-fn1)-(f2-fn2))/(12*h); // 3rd order taylor approx from lewis, pg 203
+                       double diff1 = f1-fn1;
+                       double diff2 = f2-fn2;
+
+                       // correct for angle wrap
+                       if (x.getComp(iX)->getUnit().compare("rad") == 0) {
+                               while(diff1 > M_PI) diff1 -= 2*M_PI;
+                               if(diff1 < -M_PI) diff1 += 2*M_PI;
+                               if(diff2 > M_PI) diff2 -= 2*M_PI;
+                               if(diff2 < -M_PI) diff2 += 2*M_PI;
+                       } else if (x.getComp(iX)->getUnit().compare("deg") == 0) {
+                               if(diff1 > 180) diff1 -= 360;
+                               if(diff1 < -180) diff1 += 360;
+                               if(diff2 > 180) diff2 -= 360;
+                               if(diff2 < -180) diff2 += 360;
+                       }
+            J[iY][iX] = (8*diff1-diff2)/(12*h); // 3rd order taylor approx from lewis, pg 203
+
             x.set(x0);
 
             if (m_fdm->GetDebugLevel() > 1)
index e91257ab004f52465160584430d6796ae5841553..ffbf63f3e25a9a8f5dadd59b1ff4a6b75a1576da 100644 (file)
@@ -3,16 +3,16 @@
  * Copyright (C) James Goppert 2010 <james.goppert@gmail.com>
  *
  * FGStateSpace.h is free software: you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
+ * 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.
  *
  * FGStateSpace.h 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 General Public License for more details.
+ * See the GNU Lesser General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License along
+ * You should have received a copy of the GNU Lesser General Public License along
  * with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
@@ -30,6 +30,7 @@
 #include "models/FGFCS.h"
 #include <fstream>
 #include <iostream>
+#include <limits>
 
 namespace JSBSim
 {
@@ -57,9 +58,9 @@ public:
             std::vector<double> x0 = m_stateSpace->x.get();
             double f0 = get();
             double dt0 = m_fdm->GetDeltaT();
-                       double time0 = m_fdm->GetSimTime();
+            double time0 = m_fdm->GetSimTime();
             m_fdm->Setdt(1./120.);
-                       m_fdm->DisableOutput();
+            m_fdm->DisableOutput();
             m_fdm->Run();
             double f1 = get();
             m_stateSpace->x.set(x0);
@@ -75,8 +76,8 @@ public:
             }
             double deriv = (f1-f0)/m_fdm->GetDeltaT();
             m_fdm->Setdt(dt0); // restore original value
-                       m_fdm->Setsim_time(time0);
-                       m_fdm->EnableOutput();
+            m_fdm->Setsim_time(time0);
+            m_fdm->EnableOutput();
             return deriv;
         }
         void setStateSpace(FGStateSpace * stateSpace)
@@ -141,7 +142,7 @@ public:
         void set(int i, double val)
         {
             m_components[i]->set(val);
-            m_fdm->RunIC();
+            m_stateSpace->run();
         };
         double get(int i)
         {
@@ -174,12 +175,12 @@ public:
         void set(vector<double> vals)
         {
             for (int i=0;i<getSize();i++) m_components[i]->set(vals[i]);
-            m_fdm->RunIC();
+            m_stateSpace->run();
         }
         void set(double * array)
         {
             for (int i=0;i<getSize();i++) m_components[i]->set(array[i]);
-            m_fdm->RunIC();
+            m_stateSpace->run();
         }
         std::string getName(int i) const
         {
@@ -218,6 +219,51 @@ public:
 
     void setFdm(FGFDMExec * fdm) { m_fdm = fdm; }
 
+    void run() {
+        // initialize
+        m_fdm->Initialize(m_fdm->GetIC());
+        for (unsigned int i=0; i<m_fdm->GetPropulsion()->GetNumEngines(); i++) {
+            m_fdm->GetPropulsion()->GetEngine(i)->InitRunning();
+        }
+
+        // wait for stable state
+        double cost = stateSum();
+        for(int i=0;i<1000;i++) {
+            m_fdm->GetPropulsion()->GetSteadyState();
+            m_fdm->SetTrimStatus(true);
+            m_fdm->DisableOutput();
+            m_fdm->SuspendIntegration();
+            m_fdm->Run();
+            m_fdm->SetTrimStatus(false);
+            m_fdm->EnableOutput();
+            m_fdm->ResumeIntegration();
+
+            double costNew = stateSum();
+            double dcost = fabs(costNew - cost);
+            if (dcost < std::numeric_limits<double>::epsilon()) {
+                if(m_fdm->GetDebugLevel() > 1) {
+                    std::cout << "cost convergd, i: " << i << std::endl;
+                }
+                break;
+            }
+            if (i > 1000) {
+                if(m_fdm->GetDebugLevel() > 1) {
+                    std::cout << "cost failed to converge, dcost: " 
+                        << std::scientific
+                        << dcost << std::endl;
+                }
+                break;
+            }
+            cost = costNew;
+        }
+    }
+
+    double stateSum() {
+        double sum = 0;
+        for (int i=0;i<x.getSize();i++) sum += x.get(i);
+        return sum;
+    }
+
     void clear() {
         x.clear();
         u.clear();
@@ -272,7 +318,7 @@ public:
 
     };
 
-       class VGround : public Component
+    class VGround : public Component
     {
     public:
         VGround() : Component("VGround","ft/s") {};
@@ -282,11 +328,11 @@ public:
         }
         void set(double val)
         {
-                       m_fdm->GetIC()->SetVgroundFpsIC(val);
+            m_fdm->GetIC()->SetVgroundFpsIC(val);
         }
     };
 
-       class AccelX : public Component
+    class AccelX : public Component
     {
     public:
         AccelX() : Component("AccelX","ft/s^2") {};
@@ -296,11 +342,11 @@ public:
         }
         void set(double val)
         {
-                       // XXX: not possible to implement currently
+            // XXX: not possible to implement currently
         }
     };
 
-       class AccelY : public Component
+    class AccelY : public Component
     {
     public:
         AccelY() : Component("AccelY","ft/s^2") {};
@@ -310,11 +356,11 @@ public:
         }
         void set(double val)
         {
-                       // XXX: not possible to implement currently
+            // XXX: not possible to implement currently
         }
     };
 
-       class AccelZ : public Component
+    class AccelZ : public Component
     {
     public:
         AccelZ() : Component("AccelZ","ft/s^2") {};
@@ -324,7 +370,7 @@ public:
         }
         void set(double val)
         {
-                       // XXX: not possible to implement currently
+            // XXX: not possible to implement currently
         }
     };
 
@@ -338,8 +384,13 @@ public:
         }
         void set(double val)
         {
-            m_fdm->GetIC()->SetFlightPathAngleRadIC(m_fdm->GetIC()->GetThetaRadIC()-val);
+            double beta = m_fdm->GetIC()->GetBetaDegIC();
+            double psi = m_fdm->GetIC()->GetPsiRadIC();
+            double theta = m_fdm->GetIC()->GetThetaRadIC();
             m_fdm->GetIC()->SetAlphaRadIC(val);
+            m_fdm->GetIC()->SetBetaRadIC(beta);
+            m_fdm->GetIC()->SetPsiRadIC(psi);
+            m_fdm->GetIC()->SetThetaRadIC(theta);
         }
         double getDeriv() const
         {
@@ -357,8 +408,8 @@ public:
         }
         void set(double val)
         {
-            m_fdm->GetIC()->SetFlightPathAngleRadIC(val-m_fdm->GetIC()->GetAlphaRadIC());
-            m_fdm->GetIC()->SetThetaRadIC(val);
+                       m_fdm->GetIC()->SetFlightPathAngleRadIC(val-m_fdm->GetIC()->GetAlphaRadIC());
+            //m_fdm->GetIC()->SetThetaRadIC(val);
         }
         double getDeriv() const
         {
@@ -412,7 +463,9 @@ public:
         }
         void set(double val)
         {
+            double psi = m_fdm->GetIC()->GetPsiRadIC();
             m_fdm->GetIC()->SetBetaRadIC(val);
+            m_fdm->GetIC()->SetPsiRadIC(psi);
         }
         double getDeriv() const
         {
@@ -621,11 +674,11 @@ public:
         }
         void set(double val)
         {
-               m_fdm->GetPropulsion()->GetEngine(0)->GetThruster()->SetRPM(val);
+            m_fdm->GetPropulsion()->GetEngine(0)->GetThruster()->SetRPM(val);
         }
     };
 
-       class Rpm1 : public Component
+    class Rpm1 : public Component
     {
     public:
         Rpm1() : Component("Rpm1","rev/min") {};
@@ -635,25 +688,25 @@ public:
         }
         void set(double val)
         {
-               m_fdm->GetPropulsion()->GetEngine(1)->GetThruster()->SetRPM(val);
+            m_fdm->GetPropulsion()->GetEngine(1)->GetThruster()->SetRPM(val);
         }
     };
 
-       class Rpm2 : public Component
+    class Rpm2 : public Component
     {
     public:
-        Rpm2() : Component("Rpmr2","rev/min") {};
+        Rpm2() : Component("Rpm2","rev/min") {};
         double get() const
         {
             return m_fdm->GetPropulsion()->GetEngine(2)->GetThruster()->GetRPM();
         }
         void set(double val)
         {
-               m_fdm->GetPropulsion()->GetEngine(2)->GetThruster()->SetRPM(val);
+            m_fdm->GetPropulsion()->GetEngine(2)->GetThruster()->SetRPM(val);
         }
     };
 
-       class Rpm3 : public Component
+    class Rpm3 : public Component
     {
     public:
         Rpm3() : Component("Rpm3","rev/min") {};
@@ -663,7 +716,7 @@ public:
         }
         void set(double val)
         {
-               m_fdm->GetPropulsion()->GetEngine(3)->GetThruster()->SetRPM(val);
+            m_fdm->GetPropulsion()->GetEngine(3)->GetThruster()->SetRPM(val);
         }
     };
 
@@ -718,7 +771,7 @@ public:
         }
     };
 
-       class Pi : public Component
+    class Pi : public Component
     {
     public:
         Pi() : Component("P inertial","rad/s") {};
@@ -728,10 +781,10 @@ public:
         }
         void set(double val)
         {
-                       //Set PQR from PQRi
-                       //VState.vPQR = VState.vPQRi - Ti2b * vOmegaEarth;
+            //Set PQR from PQRi
+            //VState.vPQR = VState.vPQRi - Ti2b * vOmegaEarth;
             m_fdm->GetIC()->SetQRadpsIC(val + \
-                                       (m_fdm->GetPropagate()->GetPQR(1) - m_fdm->GetPropagate()->GetPQRi(1)));
+                    (m_fdm->GetPropagate()->GetPQR(1) - m_fdm->GetPropagate()->GetPQRi(1)));
         }
         double getDeriv() const
         {
@@ -739,7 +792,7 @@ public:
         }
     };
 
-       class Qi : public Component
+    class Qi : public Component
     {
     public:
         Qi() : Component("Q inertial","rad/s") {};
@@ -749,10 +802,10 @@ public:
         }
         void set(double val)
         {
-                       //Set PQR from PQRi
-                       //VState.vPQR = VState.vPQRi - Ti2b * vOmegaEarth;
+            //Set PQR from PQRi
+            //VState.vPQR = VState.vPQRi - Ti2b * vOmegaEarth;
             m_fdm->GetIC()->SetQRadpsIC(val + \
-                                       (m_fdm->GetPropagate()->GetPQR(2) - m_fdm->GetPropagate()->GetPQRi(2)));
+                    (m_fdm->GetPropagate()->GetPQR(2) - m_fdm->GetPropagate()->GetPQRi(2)));
         }
         double getDeriv() const
         {
@@ -760,7 +813,7 @@ public:
         }
     };
 
-       class Ri : public Component
+    class Ri : public Component
     {
     public:
         Ri() : Component("R inertial","rad/s") {};
@@ -770,10 +823,10 @@ public:
         }
         void set(double val)
         {
-                       //Set PQR from PQRi
-                       //VState.vPQR = VState.vPQRi - Ti2b * vOmegaEarth;
+            //Set PQR from PQRi
+            //VState.vPQR = VState.vPQRi - Ti2b * vOmegaEarth;
             m_fdm->GetIC()->SetQRadpsIC(val + \
-                                       (m_fdm->GetPropagate()->GetPQR(3) - m_fdm->GetPropagate()->GetPQRi(3)));
+                    (m_fdm->GetPropagate()->GetPQR(3) - m_fdm->GetPropagate()->GetPQRi(3)));
         }
         double getDeriv() const
         {
@@ -781,7 +834,7 @@ public:
         }
     };
 
-       class Vn : public Component
+    class Vn : public Component
     {
     public:
         Vn() : Component("Vel north","feet/s") {};
@@ -795,12 +848,12 @@ public:
         }
         double getDeriv() const
         {
-                       //get NED accel from body accel
+            //get NED accel from body accel
             return (m_fdm->GetPropagate()->GetTb2l()*m_fdm->GetAccelerations()->GetUVWdot())(1);
         }
     };
 
-       class Ve : public Component
+    class Ve : public Component
     {
     public:
         Ve() : Component("Vel east","feet/s") {};
@@ -814,12 +867,12 @@ public:
         }
         double getDeriv() const
         {
-                       //get NED accel from body accel
+            //get NED accel from body accel
             return (m_fdm->GetPropagate()->GetTb2l()*m_fdm->GetAccelerations()->GetUVWdot())(2);
-               }
+        }
     };
 
-       class Vd : public Component
+    class Vd : public Component
     {
     public:
         Vd() : Component("Vel down","feet/s") {};
@@ -833,35 +886,35 @@ public:
         }
         double getDeriv() const
         {
-                       //get NED accel from body accel
+            //get NED accel from body accel
             return (m_fdm->GetPropagate()->GetTb2l()*m_fdm->GetAccelerations()->GetUVWdot())(3);
         }
     };
 
-       class COG : public Component
+    class COG : public Component
     {
     public:
         COG() : Component("Course Over Ground","rad") {};
         double get() const
         {
-                       //cog = atan2(Ve,Vn)
+            //cog = atan2(Ve,Vn)
             return atan2(m_fdm->GetPropagate()->GetVel(2),m_fdm->GetPropagate()->GetVel(1));
         }
         void set(double val)
         {
-                       //set Vn and Ve according to vGround and COG
-                       m_fdm->GetIC()->SetVNorthFpsIC(m_fdm->GetAuxiliary()->GetVground()*cos(val));
-                       m_fdm->GetIC()->SetVEastFpsIC(m_fdm->GetAuxiliary()->GetVground()*sin(val));
+            //set Vn and Ve according to vGround and COG
+            m_fdm->GetIC()->SetVNorthFpsIC(m_fdm->GetAuxiliary()->GetVground()*cos(val));
+            m_fdm->GetIC()->SetVEastFpsIC(m_fdm->GetAuxiliary()->GetVground()*sin(val));
         }
         double getDeriv() const
         {
-                       double Vn = m_fdm->GetPropagate()->GetVel(1);
-                       double Vndot = (m_fdm->GetPropagate()->GetTb2l()*m_fdm->GetAccelerations()->GetUVWdot())(1);
-                       double Ve = m_fdm->GetPropagate()->GetVel(2);
-                       double Vedot = (m_fdm->GetPropagate()->GetTb2l()*m_fdm->GetAccelerations()->GetUVWdot())(2); 
+            double Vn = m_fdm->GetPropagate()->GetVel(1);
+            double Vndot = (m_fdm->GetPropagate()->GetTb2l()*m_fdm->GetAccelerations()->GetUVWdot())(1);
+            double Ve = m_fdm->GetPropagate()->GetVel(2);
+            double Vedot = (m_fdm->GetPropagate()->GetTb2l()*m_fdm->GetAccelerations()->GetUVWdot())(2); 
 
-                       //dCOG/dt = dCOG/dVe*dVe/dt + dCOG/dVn*dVn/dt
-                       return Vn/(Vn*Vn+Ve*Ve)*Vedot - Ve/(Vn*Vn+Ve*Ve)*Vndot;
+            //dCOG/dt = dCOG/dVe*dVe/dt + dCOG/dVn*dVn/dt
+            return Vn/(Vn*Vn+Ve*Ve)*Vedot - Ve/(Vn*Vn+Ve*Ve)*Vndot;
         }
     };
 
index 08396eaaeeb7680b67730068c4eba1ad1bbe4fc5..2bc2b7499a0b797b012cbf864dd22970330d97b4 100644 (file)
@@ -47,7 +47,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGTable.cpp,v 1.28 2011/06/13 12:07:10 jberndt Exp $";
+static const char *IdSrc = "$Id: FGTable.cpp,v 1.29 2013/01/26 17:06:49 bcoconni Exp $";
 static const char *IdHdr = ID_TABLE;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -122,7 +122,7 @@ FGTable::FGTable(FGPropertyManager* propMan, Element* el) : PropertyManager(prop
   string call_type;
   string parent_type;
   string brkpt_string;
-  FGPropertyManager* node;
+  FGPropertyNode* node;
   Element *tableData=0;
   Element *parent_element=0;
   Element *axisElement=0;
index 1989de4c26876aec3a2ef07b845d9bfc9d10d421..377750b5af44c13dd3d3f54e30bf20eef331d770 100644 (file)
@@ -38,16 +38,17 @@ SENTRY
 INCLUDES
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#include "FGParameter.h"
 #include <iosfwd>
 #include <vector>
 #include <string>
+#include "FGParameter.h"
+#include "input_output/FGPropertyManager.h"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_TABLE "$Id: FGTable.h,v 1.14 2011/06/13 11:46:08 jberndt Exp $"
+#define ID_TABLE "$Id: FGTable.h,v 1.15 2013/01/26 17:06:49 bcoconni Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -55,7 +56,6 @@ FORWARD DECLARATIONS
 
 namespace JSBSim {
 
-class FGPropertyManager;
 class Element;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -233,7 +233,7 @@ combustion_efficiency = Lookup_Combustion_Efficiency->GetValue(equivalence_ratio
 @endcode
 
 @author Jon S. Berndt
-@version $Id: FGTable.h,v 1.14 2011/06/13 11:46:08 jberndt Exp $
+@version $Id: FGTable.h,v 1.15 2013/01/26 17:06:49 bcoconni Exp $
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -290,8 +290,8 @@ public:
   double operator()(unsigned int r, unsigned int c) const {return GetElement(r, c);}
 //  double operator()(unsigned int r, unsigned int c, unsigned int t) {GetElement(r, c, t);}
 
-  void SetRowIndexProperty(FGPropertyManager *node) {lookupProperty[eRow] = node;}
-  void SetColumnIndexProperty(FGPropertyManager *node) {lookupProperty[eColumn] = node;}
+  void SetRowIndexProperty(FGPropertyNode *node) {lookupProperty[eRow] = node;}
+  void SetColumnIndexProperty(FGPropertyNode *node) {lookupProperty[eColumn] = node;}
 
   unsigned int GetNumRows() const {return nRows;}
 
@@ -303,7 +303,7 @@ private:
   enum type {tt1D, tt2D, tt3D} Type;
   enum axis {eRow=0, eColumn, eTable};
   bool internal;
-  FGPropertyManager *lookupProperty[3];
+  FGPropertyNode_ptr lookupProperty[3];
   double** Data;
   std::vector <FGTable*> Tables;
   unsigned int nRows, nCols, nTables, dimension;
index b4df456fde4d6c8d86ca3a9d98485a6ec2dd9d01..cb6152991af8599b6b22b9206abc264bf4a3909c 100644 (file)
@@ -48,7 +48,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGAerodynamics.cpp,v 1.46 2012/07/26 04:33:46 jberndt Exp $";
+static const char *IdSrc = "$Id: FGAerodynamics.cpp,v 1.47 2013/06/10 01:59:16 jberndt Exp $";
 static const char *IdHdr = ID_AERODYNAMICS;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -180,6 +180,12 @@ bool FGAerodynamics::Run(bool Holding)
   // JSB 4/27/12 - After use, convert wind axes to produce normal lift
   // and drag values - not negative ones!
 
+  // As a clarification, JSBSim assumes that drag and lift values are defined 
+  // in wind axes - BUT with a 180 rotation about the Y axis. That is, lift and
+  // drag will be positive up and aft, respectively, so that they are reported
+  // as positive numbers. However, the wind axes themselves assume that the X
+  // and Z forces are positive forward and down.
+
   switch (axisType) {
     case atBodyXYZ:       // Forces already in body axes; no manipulation needed
       vFw = in.Tb2w*vFnative;
index 4d52bd78971563524b1263a0e16fdcb3f7c87539..9ac2439fd52dffd0ff08d866043acf4b6be18a65 100644 (file)
@@ -50,7 +50,7 @@ INCLUDES
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGAtmosphere.cpp,v 1.54 2012/09/17 12:38:07 jberndt Exp $";
+static const char *IdSrc = "$Id: FGAtmosphere.cpp,v 1.55 2013/01/26 17:06:49 bcoconni Exp $";
 static const char *IdHdr = ID_ATMOSPHERE;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -111,20 +111,21 @@ bool FGAtmosphere::Run(bool Holding)
 
 void FGAtmosphere::Calculate(double altitude)
 {
+  FGPropertyNode* node = PropertyManager->GetNode();
   if (!PropertyManager->HasNode("atmosphere/override/temperature"))
-  Temperature = GetTemperature(altitude);
-  else 
-    Temperature = PropertyManager->getDoubleValue("atmosphere/override/temperature");
+    Temperature = GetTemperature(altitude);
+  else
+    Temperature = node->GetDouble("atmosphere/override/temperature");
 
   if (!PropertyManager->HasNode("atmosphere/override/pressure"))
-  Pressure    = GetPressure(altitude);
-  else 
-    Pressure = PropertyManager->getDoubleValue("atmosphere/override/pressure");
+    Pressure = GetPressure(altitude);
+  else
+    Pressure = node->GetDouble("atmosphere/override/pressure");
 
   if (!PropertyManager->HasNode("atmosphere/override/density"))
-  Density     = Pressure/(Reng*Temperature);
-  else 
-    Density = PropertyManager->getDoubleValue("atmosphere/override/density");
+    Density = Pressure/(Reng*Temperature);
+  else
+    Density = node->GetDouble("atmosphere/override/density");
 
   Soundspeed  = sqrt(SHRatio*Reng*(Temperature));
   PressureAltitude = altitude;
index 5eed15f61bbeeade7327665bdc1c36cdd15934b0..557b7e366a362b36373df27860701ecd88a99dad 100644 (file)
@@ -50,7 +50,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGAuxiliary.cpp,v 1.60 2012/09/30 16:49:17 bcoconni Exp $";
+static const char *IdSrc = "$Id: FGAuxiliary.cpp,v 1.61 2013/06/10 01:56:14 jberndt Exp $";
 static const char *IdHdr = ID_AUXILIARY;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -76,7 +76,7 @@ FGAuxiliary::FGAuxiliary(FGFDMExec* fdmex) : FGModel(fdmex)
   seconds_in_day = 0.0;
   hoverbmac = hoverbcg = 0.0;
   Re = 0.0;
-  Nz = 0.0;
+  Nz = Ny = 0.0;
   lon_relative_position = lat_relative_position = relative_position = 0.0;
 
   vPilotAccel.InitMatrix();
@@ -111,7 +111,7 @@ bool FGAuxiliary::InitModel(void)
   seconds_in_day = 0.0;
   hoverbmac = hoverbcg = 0.0;
   Re = 0.0;
-  Nz = 0.0;
+  Nz = Ny = 0.0;
   lon_relative_position = lat_relative_position = relative_position = 0.0;
 
   vPilotAccel.InitMatrix();
@@ -228,6 +228,7 @@ bool FGAuxiliary::Run(bool Holding)
   vNcg = in.vBodyAccel/in.SLGravity;
   // Nz is Acceleration in "g's", along normal axis (-Z body axis)
   Nz = -vNcg(eZ);
+  Ny =  vNcg(eY);
   vPilotAccel = in.vBodyAccel + in.vPQRdot * in.ToEyePt;
   vPilotAccel += in.vPQR * (in.vPQR * in.ToEyePt);
 
@@ -373,6 +374,7 @@ void FGAuxiliary::bind(void)
   PropertyManager->Tie("accelerations/n-pilot-y-norm", this, eY, (PMF)&FGAuxiliary::GetNpilot);
   PropertyManager->Tie("accelerations/n-pilot-z-norm", this, eZ, (PMF)&FGAuxiliary::GetNpilot);
   PropertyManager->Tie("accelerations/Nz", this, &FGAuxiliary::GetNz);
+  PropertyManager->Tie("accelerations/Ny", this, &FGAuxiliary::GetNy);
   PropertyManager->Tie("forces/load-factor", this, &FGAuxiliary::GetNlf);
   /* PropertyManager->Tie("atmosphere/headwind-fps", this, &FGAuxiliary::GetHeadWind, true);
   PropertyManager->Tie("atmosphere/crosswind-fps", this, &FGAuxiliary::GetCrossWind, true); */
index 4f2250e6df964574180c21edeb1bdea30dec0dd3..8835335fe0723e0f705be3645c6604daa2ac47a0 100644 (file)
@@ -48,7 +48,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_AUXILIARY "$Id: FGAuxiliary.h,v 1.27 2012/09/15 11:17:21 bcoconni Exp $"
+#define ID_AUXILIARY "$Id: FGAuxiliary.h,v 1.28 2013/06/10 01:56:27 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -99,7 +99,7 @@ CLASS DOCUMENTATION
     to the JSBSim vPQRdot vector, and the w parameter is equivalent to vPQR.
 
     @author Tony Peden, Jon Berndt
-    @version $Id: FGAuxiliary.h,v 1.27 2012/09/15 11:17:21 bcoconni Exp $
+    @version $Id: FGAuxiliary.h,v 1.28 2013/06/10 01:56:27 jberndt Exp $
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -225,6 +225,9 @@ public:
   /** The vertical acceleration in g's of the aircraft center of gravity. */
   double GetNz            (void) const { return Nz;         }
 
+  /** The lateral acceleration in g's of the aircraft center of gravity. */
+  double GetNy            (void) const { return Ny;         }
+
   const FGColumnVector3& GetNwcg(void) const { return vNwcg; }
 
   double GetHOverBCG(void) const { return hoverbcg; }
@@ -312,7 +315,7 @@ private:
   double alpha, beta;
   double adot,bdot;
   double psigt, gamma;
-  double Nz;
+  double Nz, Ny;
   double seconds_in_day;  // seconds since current GMT day began
   int    day_of_year;     // GMT day, 1 .. 366
 
index 872a7326dd5dd28af521e65e44271c7ca2e0f518..bc9d703c988aa50bd1ab6bc16fe2e0b2f35684a0 100644 (file)
@@ -66,7 +66,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGFCS.cpp,v 1.79 2012/12/12 06:19:57 jberndt Exp $";
+static const char *IdSrc = "$Id: FGFCS.cpp,v 1.80 2013/01/26 17:06:49 bcoconni Exp $";
 static const char *IdHdr = ID_FCS;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -541,7 +541,7 @@ bool FGFCS::Load(Element* el, SystemType systype)
 
       interface_property_string = property_element->GetDataLine();
       if (PropertyManager->HasNode(interface_property_string)) {
-        FGPropertyManager* node = PropertyManager->GetNode(interface_property_string);
+        FGPropertyNode* node = PropertyManager->GetNode(interface_property_string);
         if (debug_lvl > 0)
           cout << "      " << "Overriding value for property " << interface_property_string
                << " (old value: " << node->getDoubleValue() << "  new value: " << value << ")" << endl;
@@ -564,7 +564,7 @@ bool FGFCS::Load(Element* el, SystemType systype)
     FGFCSChannel* newChannel = 0;
 
     string sOnOffProperty = channel_element->GetAttributeValue("execute");
-    FGPropertyManager* OnOffPropertyNode = 0;
+    FGPropertyNode* OnOffPropertyNode = 0;
     if (sOnOffProperty.length() > 0) {
       OnOffPropertyNode = PropertyManager->GetNode(sOnOffProperty);
       if (OnOffPropertyNode == 0) {
index 16f13b78461591c9b9fed1b2178664ef57b7b3fe..fafd7230ffb04347c11848f30856e24ecec60b61 100644 (file)
@@ -44,7 +44,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_FCSCHANNEL "$Id: FGFCSChannel.h,v 1.1 2012/10/15 05:02:29 jberndt Exp $"
+#define ID_FCSCHANNEL "$Id: FGFCSChannel.h,v 1.2 2013/01/26 17:06:50 bcoconni Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -70,7 +70,7 @@ typedef std::vector <FGFCSComponent*> FCSCompVec;
 class FGFCSChannel {
 public:
   /// Constructor
-  FGFCSChannel(FGPropertyManager* node=0) :
+  FGFCSChannel(FGPropertyNode* node=0) :
   OnOffNode(node)
   {
   }
@@ -120,7 +120,7 @@ public:
 
   private:
     FCSCompVec FCSComponents;
-    const FGPropertyManager* OnOffNode;
+    FGConstPropertyNode_ptr OnOffNode;
 };
 
 }
index f2f6688c33cf6e78ade4944085d8a48c10f5a7b1..77e547412f05101081e943015eb7f22fd74cbc43 100644 (file)
@@ -4,7 +4,7 @@
  Author:       Anders Gidenstam
  Date started: 01/21/2006
 
- ----- Copyright (C) 2006 - 2011  Anders Gidenstam (anders(at)gidenstam.org) --
+ ----- Copyright (C) 2006 - 2013  Anders Gidenstam (anders(at)gidenstam.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
@@ -50,14 +50,14 @@ using std::max;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGGasCell.cpp,v 1.15 2011/08/06 13:47:59 jberndt Exp $";
+static const char *IdSrc = "$Id: FGGasCell.cpp,v 1.18 2013/04/17 20:24:27 andgi Exp $";
 static const char *IdHdr = ID_GASCELL;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 CLASS IMPLEMENTATION
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 /* Constants. */
-const double FGGasCell::R = 3.4071;              // [lbs ft/(mol Rankine)]
+const double FGGasCell::R = 3.4071;              // [lbf ft/(mol Rankine)]
 const double FGGasCell::M_air = 0.0019186;       // [slug/mol]
 const double FGGasCell::M_hydrogen = 0.00013841; // [slug/mol]
 const double FGGasCell::M_helium = 0.00027409;   // [slug/mol]
@@ -202,7 +202,7 @@ FGGasCell::FGGasCell(FGFDMExec* exec, Element* el, int num, const struct Inputs&
 
   property_name = base_property_name + "/max_volume-ft3";
   PropertyManager->Tie( property_name.c_str(), &MaxVolume, false );
-  PropertyManager->SetWritable( property_name, false );
+  PropertyManager->GetNode()->SetWritable( property_name, false );
   property_name = base_property_name + "/temp-R";
   PropertyManager->Tie( property_name.c_str(), &Temperature, false );
   property_name = base_property_name + "/pressure-psf";
@@ -325,7 +325,7 @@ void FGGasCell::Calculate(double dt)
     // FixMe: CellHeight should depend on current volume.
     const double CellHeight = 2 * Zradius + Zwidth;                   // [ft]
     const double GasMass    = Contents * M_gas();                     // [slug]
-    const double GasVolume  = Contents * R * Temperature / Pressure;  // [ft³]
+    const double GasVolume  = Contents * R * Temperature / Pressure;  // [ft^3]
     const double GasDensity = GasMass / GasVolume;
     const double DeltaPressure =
       Pressure + CellHeight * g * (AirDensity - GasDensity) - AirPressure;
@@ -468,7 +468,7 @@ void FGGasCell::Debug(int from)
       cout << "      Initial pressure: " << Pressure << " lbs/ft2" << endl;
       cout << "      Initial volume: " << Volume << " ft3" << endl;
       cout << "      Initial mass: " << GetMass() << " slug mass" << endl;
-      cout << "      Initial weight: " << GetMass()*lbtoslug << " lbs force" <<
+      cout << "      Initial weight: " << GetMass()*slugtolb << " lbs force" <<
         endl;
       cout << "      Heat transfer: " << endl;
     }
@@ -485,7 +485,7 @@ void FGGasCell::Debug(int from)
       cout << "      Pressure: " << Pressure << " lbs/ft2" << endl;
       cout << "      Volume: " << Volume << " ft3" << endl;
       cout << "      Mass: " << GetMass() << " slug mass" << endl;
-      cout << "      Weight: " << GetMass()*lbtoslug << " lbs force" << endl;
+      cout << "      Weight: " << GetMass()*slugtolb << " lbs force" << endl;
   }
   if (debug_lvl & 16) { // Sanity checking
   }
@@ -634,7 +634,7 @@ FGBallonet::FGBallonet(FGFDMExec* exec, Element* el, int num, FGGasCell* parent,
 
   property_name = base_property_name + "/max_volume-ft3";
   PropertyManager->Tie( property_name, &MaxVolume, false );
-  PropertyManager->SetWritable( property_name, false );
+  PropertyManager->GetNode()->SetWritable( property_name, false );
 
   property_name = base_property_name + "/temp-R";
   PropertyManager->Tie( property_name, &Temperature, false );
@@ -820,7 +820,7 @@ void FGBallonet::Debug(int from)
       cout << "        Initial pressure: " << Pressure << " lbs/ft2" << endl;
       cout << "        Initial volume: " << Volume << " ft3" << endl;
       cout << "        Initial mass: " << GetMass() << " slug mass" << endl;
-      cout << "        Initial weight: " << GetMass()*lbtoslug <<
+      cout << "        Initial weight: " << GetMass()*slugtolb <<
         " lbs force" << endl;
       cout << "        Heat transfer: " << endl;
     }
@@ -838,7 +838,7 @@ void FGBallonet::Debug(int from)
       cout << "        Pressure: " << Pressure << " lbs/ft2" << endl;
       cout << "        Volume: " << Volume << " ft3" << endl;
       cout << "        Mass: " << GetMass() << " slug mass" << endl;
-      cout << "        Weight: " << GetMass()*lbtoslug << " lbs force" << endl;
+      cout << "        Weight: " << GetMass()*slugtolb << " lbs force" << endl;
   }
   if (debug_lvl & 16) { // Sanity checking
   }
index ff3613c17bd0c2d9fcbfe416e51090b61b0a5d40..a4851e9b9e5146868cd2771effeb408ca8a1a219 100644 (file)
@@ -4,7 +4,7 @@
  Author:       Anders Gidenstam
  Date started: 01/21/2006
 
- ----- Copyright (C) 2006 - 2011  Anders Gidenstam (anders(at)gidenstam.org) --
+ ----- Copyright (C) 2006 - 2013  Anders Gidenstam (anders(at)gidenstam.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
@@ -50,7 +50,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_GASCELL "$Id: FGGasCell.h,v 1.12 2011/08/06 13:47:59 jberndt Exp $"
+#define ID_GASCELL "$Id: FGGasCell.h,v 1.13 2013/04/17 20:24:27 andgi Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -238,7 +238,7 @@ private:
   std::string type;
   int CellNum;
   // Structural constants
-  double MaxVolume;                 // [ft^2]
+  double MaxVolume;                 // [ft^3]
   double MaxOverpressure;           // [lbs/ft^2]
   FGColumnVector3 vXYZ;             // [in]
   double Xradius, Yradius, Zradius; // [ft]
@@ -251,8 +251,8 @@ private:
   // Variables
   double Pressure;          // [lbs/ft^2]
   double Contents;          // [mol]
-  double Volume;            // [ft^2]
-  double dVolumeIdeal;      // [ft^2]
+  double Volume;            // [ft^3]
+  double dVolumeIdeal;      // [ft^3]
   double Temperature;       // [Rankine]
   double Buoyancy;          // [lbs] Note: Gross lift.
                             // Does not include the weight of the gas itself.
@@ -344,7 +344,7 @@ public:
 private:
   int CellNum;
   // Structural constants
-  double MaxVolume;                 // [ft^2]
+  double MaxVolume;                 // [ft^3]
   double MaxOverpressure;           // [lbs/ft^2]
   FGColumnVector3 vXYZ;             // [in]
   double Xradius, Yradius, Zradius; // [ft]
@@ -357,8 +357,8 @@ private:
   // Variables
   double Pressure;         // [lbs/ft^2]
   double Contents;         // [mol]
-  double Volume;           // [ft^2]
-  double dVolumeIdeal;     // [ft^2]
+  double Volume;           // [ft^3]
+  double dVolumeIdeal;     // [ft^3]
   double dU;               // [lbs ft / sec]
   double Temperature;      // [Rankine]
   double ValveOpen;        // 0 <= ValveOpen <= 1 (or higher).
index 87455e3cdd2e18dc80f4c3bf8da7ba552873b8b4..d10ceacee6827e7c8b60499f96059690a3c0ecc2 100644 (file)
@@ -53,7 +53,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGInput.cpp,v 1.24 2012/11/23 16:30:36 bcoconni Exp $";
+static const char *IdSrc = "$Id: FGInput.cpp,v 1.25 2013/01/26 17:06:50 bcoconni Exp $";
 static const char *IdHdr = ID_INPUT;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -94,7 +94,7 @@ bool FGInput::Run(bool Holding)
   string line, token;
   size_t start=0, string_start=0, string_end=0;
   double value=0;
-  FGPropertyManager* node=0;
+  FGPropertyNode* node=0;
 
   if (FGModel::Run(Holding)) return true; // fast exit if nothing to do
   if (port == 0) return false;      // Do nothing here if port not defined
index c1d60699317263d26f1b52eb962a26566a1b331a..c31f4f2d4fb6c72d6ce292636a2ec79ff194a432 100644 (file)
@@ -61,7 +61,7 @@ DEFINITIONS
 GLOBAL DATA
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-static const char *IdSrc = "$Id: FGLGear.cpp,v 1.103 2013/01/13 12:44:52 bcoconni Exp $";
+static const char *IdSrc = "$Id: FGLGear.cpp,v 1.104 2013/01/25 14:02:13 jberndt Exp $";
 static const char *IdHdr = ID_LGEAR;
 
 // Body To Structural (body frame is rotated 180 deg about Y and lengths are given in
@@ -357,8 +357,9 @@ const FGColumnVector3& FGLGear::GetBodyForces(void)
 
       ResetReporting();
     }
-  }
-  else if (gearPos < 0.01) { // Gear UP
+
+  } else if (gearPos < 0.01) { // Gear UP
+
     WOW = false;
     vWhlVelVec.InitMatrix();
   }
index 28248fc34e590690aa6db8d71002087b509b78ae..b77ba859ee69b15d4303e4b91d9d32ce82c827fe 100644 (file)
@@ -49,7 +49,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGOutput.cpp,v 1.71 2012/12/15 16:13:58 bcoconni Exp $";
+static const char *IdSrc = "$Id: FGOutput.cpp,v 1.72 2013/01/26 17:06:50 bcoconni Exp $";
 static const char *IdHdr = ID_OUTPUT;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -207,7 +207,7 @@ bool FGOutput::SetDirectivesFile(const std::string& fname)
 
 bool FGOutput::Load(int subSystems, std::string protocol, std::string type,
                     std::string port, std::string name, double outRate,
-                    std::vector<FGPropertyManager *> & outputProperties)
+                    std::vector<FGPropertyNode_ptr> & outputProperties)
 {
   unsigned int idx = OutputTypes.size();
   FGOutputType* Output = 0;
index ce2674010dc60a8b91306cebeeff7bf469a1c11b..dcbc8adc153c9e9cc28b9b71cbcc602881eee9d4 100644 (file)
@@ -48,7 +48,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_OUTPUT "$Id: FGOutput.h,v 1.26 2012/09/05 21:49:19 bcoconni Exp $"
+#define ID_OUTPUT "$Id: FGOutput.h,v 1.27 2013/01/26 17:06:50 bcoconni Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -122,7 +122,7 @@ CLASS DOCUMENTATION
 
     The class FGOutput is the manager of the outputs requested by the user. It
     manages a list of instances derived from the abstract class FGOutputType.
-    @version $Id: FGOutput.h,v 1.26 2012/09/05 21:49:19 bcoconni Exp $
+    @version $Id: FGOutput.h,v 1.27 2013/01/26 17:06:50 bcoconni Exp $
  */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -216,7 +216,7 @@ public:
       @result true if the execution succeeded. */
   bool Load(int subSystems, std::string protocol, std::string type,
             std::string port, std::string name, double outRate,
-            std::vector<FGPropertyManager *> & outputProperties);
+            std::vector<FGPropertyNode_ptr> & outputProperties);
   /** Get the name identifier to which the output will be directed.
       @param idx ID of the output instance from which the name identifier must
                  be obtained
index a2181e56e8eb749659beded90c3e05ea1d926d27..a0ca06c37089fd9836381aaa640c87ff24fa498d 100644 (file)
@@ -77,7 +77,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGPropagate.cpp,v 1.111 2013/01/19 13:49:37 bcoconni Exp $";
+static const char *IdSrc = "$Id: FGPropagate.cpp,v 1.112 2013/06/10 01:57:52 jberndt Exp $";
 static const char *IdHdr = ID_PROPAGATE;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -673,6 +673,10 @@ void FGPropagate::bind(void)
   PropertyManager->Tie("attitude/theta-rad", this, (int)eTht, (PMF)&FGPropagate::GetEuler);
   PropertyManager->Tie("attitude/psi-rad", this, (int)ePsi, (PMF)&FGPropagate::GetEuler);
 
+  PropertyManager->Tie("attitude/phi-deg", this, (int)ePhi, (PMF)&FGPropagate::GetEulerDeg);
+  PropertyManager->Tie("attitude/theta-deg", this, (int)eTht, (PMF)&FGPropagate::GetEulerDeg);
+  PropertyManager->Tie("attitude/psi-deg", this, (int)ePsi, (PMF)&FGPropagate::GetEulerDeg);
+
   PropertyManager->Tie("attitude/roll-rad", this, (int)ePhi, (PMF)&FGPropagate::GetEuler);
   PropertyManager->Tie("attitude/pitch-rad", this, (int)eTht, (PMF)&FGPropagate::GetEuler);
   PropertyManager->Tie("attitude/heading-true-rad", this, (int)ePsi, (PMF)&FGPropagate::GetEuler);
index 20841c10d105cb3c23eab364dbe25fce9efaadf1..aead73c27936bdc8c4945db05f326ada522fafbc 100644 (file)
@@ -49,7 +49,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_PROPAGATE "$Id: FGPropagate.h,v 1.74 2013/01/19 13:49:37 bcoconni Exp $"
+#define ID_PROPAGATE "$Id: FGPropagate.h,v 1.75 2013/06/10 01:58:01 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -93,7 +93,7 @@ CLASS DOCUMENTATION
     @endcode
 
     @author Jon S. Berndt, Mathias Froehlich, Bertrand Coconnier
-    @version $Id: FGPropagate.h,v 1.74 2013/01/19 13:49:37 bcoconni Exp $
+    @version $Id: FGPropagate.h,v 1.75 2013/06/10 01:58:01 jberndt Exp $
   */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -247,6 +247,23 @@ public:
   */
   const FGColumnVector3& GetEuler(void) const { return VState.qAttitudeLocal.GetEuler(); }
 
+  /** Retrieves the Euler angles (in degrees) that define the vehicle orientation.
+      Extracts the Euler angles from the quaternion that stores the orientation
+      in the Local frame. The order of rotation used is Yaw-Pitch-Roll. The
+      vector returned is represented by an FGColumnVector reference. The vector
+      for the Euler angles is organized (Phi, Theta, Psi). The vector
+      is 1-based, so that the first element can be retrieved using the "()" operator.
+      In other words, the returned vector item with subscript (1) is Phi.
+      Various convenience enumerators are defined in FGJSBBase. The relevant
+      enumerators for the vector returned by this call are, ePhi=1, eTht=2, ePsi=3.
+      units degrees
+      @return The Euler angle vector, where the first item in the
+              vector is the angle about the X axis, the second is the
+              angle about the Y axis, and the third item is the angle
+              about the Z axis (Phi, Theta, Psi).
+  */
+  const FGColumnVector3& GetEulerDeg(void) const { return VState.qAttitudeLocal.GetEuler() * radtodeg; }
+
   /** Retrieves a body frame velocity component.
       Retrieves a body frame velocity component. The velocity returned is
       extracted from the vUVW vector (an FGColumnVector). The vector for the
@@ -341,6 +358,18 @@ public:
   */
   double GetEuler(int axis) const { return VState.qAttitudeLocal.GetEuler(axis); }
 
+  /** Retrieves a vehicle Euler angle component in degrees.
+      Retrieves an Euler angle (Phi, Theta, or Psi) from the quaternion that
+      stores the vehicle orientation relative to the Local frame. The order of
+      rotations used is Yaw-Pitch-Roll. The Euler angle with subscript (1) is
+      Phi. Various convenience enumerators are defined in FGJSBBase. The
+      relevant enumerators for the Euler angle returned by this call are,
+      ePhi=1, eTht=2, ePsi=3 (e.g. GetEuler(eTht) returns Theta).
+      units degrees
+      @return An Euler angle in degrees.
+  */
+  double GetEulerDeg(int axis) const { return VState.qAttitudeLocal.GetEuler(axis) * radtodeg; }
+
   /** Retrieves the cosine of a vehicle Euler angle component.
       Retrieves the cosine of an Euler angle (Phi, Theta, or Psi) from the
       quaternion that stores the vehicle orientation relative to the Local frame.
index f739a76a7dcc9867524bd69c7efba689c22d3e9c..a335689c5c4282956d3be41af3e46b47608c14ed 100644 (file)
@@ -43,7 +43,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGActuator.cpp,v 1.25 2013/01/12 19:24:05 jberndt Exp $";
+static const char *IdSrc = "$Id: FGActuator.cpp,v 1.28 2013/06/10 02:04:50 jberndt Exp $";
 static const char *IdHdr = ID_ACTUATOR;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -83,12 +83,12 @@ FGActuator::FGActuator(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, eleme
   Element* ratelim_el = element->FindElement("rate_limit");
   while ( ratelim_el ) {
     rate_limited = true;
-    FGPropertyManager* rate_limit_prop=0;
+    FGPropertyNode* rate_limit_prop=0;
 
     string rate_limit_str = ratelim_el->GetDataLine();
     trim(rate_limit_str);
     if (is_number(rate_limit_str)) {
-    rate_limit = fabs(element->FindElementValueAsNumber("rate_limit"));
+      rate_limit = fabs(element->FindElementValueAsNumber("rate_limit"));
     } else {
       if (rate_limit_str[0] == '-') rate_limit_str.erase(0,1);
       rate_limit_prop = PropertyManager->GetNode(rate_limit_str, true);
@@ -104,7 +104,7 @@ FGActuator::FGActuator(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, eleme
       } 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 {
       rate_limit_incr =  rate_limit;
       rate_limit_decr = -rate_limit;
@@ -157,7 +157,8 @@ bool FGActuator::Run(void )
     Output = PreviousOutput;
   } else {
     if (lag != 0.0)              Lag();        // models actuator lag
-    if (rate_limit != 0)         RateLimit();  // limit the actuator rate
+    if (rate_limit != 0 || (rate_limit_incr_prop != 0
+        || rate_limit_decr_prop != 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
index 650af2f9a699a4ff678f3dc0b449669bd51e3093..a8e8d59328203a0ea87730d52cd1a061d30dffc7 100644 (file)
@@ -44,7 +44,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_ACTUATOR "$Id: FGActuator.h,v 1.14 2013/01/12 19:24:05 jberndt Exp $"
+#define ID_ACTUATOR "$Id: FGActuator.h,v 1.15 2013/01/26 17:06:50 bcoconni Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -120,7 +120,7 @@ Example:
 @endcode
 
 @author Jon S. Berndt
-@version $Revision: 1.14 $
+@version $Revision: 1.15 $
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -160,8 +160,8 @@ private:
   double rate_limit;
   double rate_limit_incr;
   double rate_limit_decr;
-  FGPropertyManager* rate_limit_incr_prop;
-  FGPropertyManager* rate_limit_decr_prop;
+  FGPropertyNode_ptr rate_limit_incr_prop;
+  FGPropertyNode_ptr rate_limit_decr_prop;
   double hysteresis_width;
   double deadband_width;
   double lag;
index 80464769f6ef2618a92fa9a724fffde3ad73dad7..d1aab83e103ccef6739a33518402f444a39b9fe7 100644 (file)
@@ -43,7 +43,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_DEADBAND "$Id: FGDeadBand.h,v 1.9 2009/10/24 22:59:30 jberndt Exp $"
+#define ID_DEADBAND "$Id: FGDeadBand.h,v 1.10 2013/01/26 17:06:50 bcoconni Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -53,7 +53,6 @@ namespace JSBSim {
 
 class FGFCS;
 class Element;
-class FGPropertyManager;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 CLASS DOCUMENTATION
@@ -80,7 +79,7 @@ CLASS DOCUMENTATION
     produce no output. For example, say that the width value is 2.0. If the
     input is between -1.0 and +1.0, the output will be zero.
     @author Jon S. Berndt
-    @version $Id: FGDeadBand.h,v 1.9 2009/10/24 22:59:30 jberndt Exp $
+    @version $Id: FGDeadBand.h,v 1.10 2013/01/26 17:06:50 bcoconni Exp $
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -98,7 +97,7 @@ public:
 private:
   double width;
   double gain;
-  FGPropertyManager* WidthPropertyNode;
+  FGPropertyNode_ptr WidthPropertyNode;
   double WidthPropertySign;
 
   void Debug(int from);
index dfa2e46b1caca2cf4796b0117e0e0f007bdf672f..0de61898443dab6868e7c9880616b51dac08658c 100644 (file)
@@ -48,7 +48,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGFCSComponent.cpp,v 1.34 2011/09/11 11:36:04 bcoconni Exp $";
+static const char *IdSrc = "$Id: FGFCSComponent.cpp,v 1.35 2013/01/26 17:06:50 bcoconni Exp $";
 static const char *IdHdr = ID_FCSCOMPONENT;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -121,7 +121,7 @@ FGFCSComponent::FGFCSComponent(FGFCS* _fcs, Element* element) : fcs(_fcs)
     } else {
       InputSigns.push_back( 1.0);
     }
-    FGPropertyManager* node = 0L;
+    FGPropertyNode* node = 0L;
     if (PropertyManager->HasNode(input)) {
       node = PropertyManager->GetNode(input);
       InputNodes.push_back(new FGPropertyValue( node ));
@@ -138,7 +138,7 @@ FGFCSComponent::FGFCSComponent(FGFCS* _fcs, Element* element) : fcs(_fcs)
   while (out_elem) {
     IsOutput = true;
     string output_node_name = out_elem->GetDataLine();
-    FGPropertyManager* OutputNode = PropertyManager->GetNode( output_node_name, true );
+    FGPropertyNode* OutputNode = PropertyManager->GetNode( output_node_name, true );
     OutputNodes.push_back(OutputNode);
     if (!OutputNode) {
       cerr << endl << "  Unable to process property: " << output_node_name << endl;
index d79a2e66cc56dc63b50dcc32847db7b61990aa9a..d050a2833a31ca144e2c00b91bfb542c72b3e61f 100644 (file)
@@ -46,7 +46,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_FCSCOMPONENT "$Id: FGFCSComponent.h,v 1.20 2011/06/16 03:39:38 jberndt Exp $"
+#define ID_FCSCOMPONENT "$Id: FGFCSComponent.h,v 1.21 2013/01/26 17:06:50 bcoconni Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -55,7 +55,6 @@ FORWARD DECLARATIONS
 namespace JSBSim {
 
 class FGFCS;
-class FGPropertyManager;
 class Element;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -81,7 +80,7 @@ CLASS DOCUMENTATION
     - FGActuator
 
     @author Jon S. Berndt
-    @version $Id: FGFCSComponent.h,v 1.20 2011/06/16 03:39:38 jberndt Exp $
+    @version $Id: FGFCSComponent.h,v 1.21 2013/01/26 17:06:50 bcoconni Exp $
     @see Documentation for the FGFCS class, and for the configuration file class
 */
 
@@ -107,10 +106,10 @@ public:
 protected:
   FGFCS* fcs;
   FGPropertyManager* PropertyManager;
-  FGPropertyManager* treenode;
-  std::vector <FGPropertyManager*> OutputNodes;
-  FGPropertyManager* ClipMinPropertyNode;
-  FGPropertyManager* ClipMaxPropertyNode;
+  FGPropertyNode_ptr treenode;
+  std::vector <FGPropertyNode_ptr> OutputNodes;
+  FGPropertyNode_ptr ClipMinPropertyNode;
+  FGPropertyNode_ptr ClipMaxPropertyNode;
   std::vector <FGPropertyValue*> InputNodes;
   std::vector <std::string> InputNames;
   std::vector <float> InputSigns;
index efb03541cef6cd4f63575456105a6a01ec68aa73..4211ccc72facbd3ec89a29d350be70f59c49fe27 100644 (file)
@@ -43,7 +43,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_FILTER "$Id: FGFilter.h,v 1.12 2009/10/24 22:59:30 jberndt Exp $"
+#define ID_FILTER "$Id: FGFilter.h,v 1.13 2013/01/26 17:06:50 bcoconni Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -228,7 +228,7 @@ is so that the last component in a "string" can copy its value to the appropriat
 output, such as the elevator, or speedbrake, etc.
 
 @author Jon S. Berndt
-@version $Revision: 1.12 $
+@version $Revision: 1.13 $
 
 */
 
@@ -263,8 +263,8 @@ private:
   double PreviousInput2;
   double PreviousOutput1;
   double PreviousOutput2;
-  FGPropertyManager* Trigger;
-  FGPropertyManager* PropertyNode[7];
+  FGPropertyNode_ptr Trigger;
+  FGPropertyNode_ptr PropertyNode[7];
   void CalculateDynamicFilters(void);
   void ReadFilterCoefficients(Element* el, int index);
   bool DynamicFilter;
index 5383cab20908080e5a540a9e7725bbf34ecdd666..2105ff2a1e0884eb1b82ddfbd1e043a1d82b4da9 100644 (file)
@@ -44,7 +44,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_GAIN "$Id: FGGain.h,v 1.14 2009/10/24 22:59:30 jberndt Exp $"
+#define ID_GAIN "$Id: FGGain.h,v 1.15 2013/01/26 17:06:50 bcoconni Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -208,7 +208,7 @@ CLASS DOCUMENTATION
     @endcode
 
     @author Jon S. Berndt
-    @version $Revision: 1.14 $
+    @version $Revision: 1.15 $
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -225,7 +225,7 @@ public:
 
 private:
   FGTable* Table;
-  FGPropertyManager* GainPropertyNode;
+  FGPropertyNode_ptr GainPropertyNode;
   double GainPropertySign;
   double Gain;
   double InMin, InMax, OutMin, OutMax;
index c541a5c5579e9a4f37b4bc3e04fe49b99411429b..95efe6039effa9e35de457db04171dc460a8ebd8 100644 (file)
@@ -44,7 +44,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGPID.cpp,v 1.20 2012/05/10 12:10:48 jberndt Exp $";
+static const char *IdSrc = "$Id: FGPID.cpp,v 1.21 2013/02/02 06:05:26 jberndt Exp $";
 static const char *IdHdr = ID_PID;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -135,6 +135,14 @@ FGPID::FGPID(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element)
   }
 
   FGFCSComponent::bind();
+  string tmp;
+  if (Name.find("/") == string::npos) {
+    tmp = "fcs/" + PropertyManager->mkPropertyName(Name, true);
+  } else {
+    tmp = Name;
+  }
+  typedef double (FGPID::*PMF)(void) const;
+  PropertyManager->Tie(tmp+"/initial-integrator-value", this, (PMF)0, &FGPID::SetInitialOutput);
 
   Debug(0);
 }
index 74d9aeae9badb9beb9da61e1f1e3a793ac32e09d..6069d3b523ca4d8de0db9035ae0178209173d30d 100644 (file)
@@ -44,7 +44,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_PID "$Id: FGPID.h,v 1.13 2012/05/10 12:10:48 jberndt Exp $"
+#define ID_PID "$Id: FGPID.h,v 1.15 2013/02/02 06:05:26 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -116,7 +116,7 @@ For example,
 </pre>
 
     @author Jon S. Berndt
-    @version $Revision: 1.13 $
+    @version $Revision: 1.15 $
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -135,6 +135,11 @@ public:
     /// These define the indices use to select the various integrators.
   enum eIntegrateType {eNone = 0, eRectEuler, eTrapezoidal, eAdamsBashforth2, eAdamsBashforth3};
 
+  void SetInitialOutput(double val) {
+    I_out_total = val;
+    Output = val;
+  }
+
 private:
   double Kp, Ki, Kd;
   double I_out_total;
@@ -147,11 +152,11 @@ private:
 
   eIntegrateType IntType;
 
-  FGPropertyManager *Trigger;
-  FGPropertyManager* KpPropertyNode;
-  FGPropertyManager* KiPropertyNode;
-  FGPropertyManager* KdPropertyNode;
-  FGPropertyManager* ProcessVariableDot;
+  FGPropertyNode_ptr Trigger;
+  FGPropertyNode_ptr KpPropertyNode;
+  FGPropertyNode_ptr KiPropertyNode;
+  FGPropertyNode_ptr KdPropertyNode;
+  FGPropertyNode_ptr ProcessVariableDot;
 
   void Debug(int from);
 };
index 09b037696fe31cd6e9e0cf5a5d434ed6ddb62552..be0eea212bf52db22e2b3b7f6024ecbd28ee0c46 100644 (file)
@@ -44,7 +44,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_SENSOR "$Id: FGSensor.h,v 1.21 2012/01/08 12:39:14 bcoconni Exp $"
+#define ID_SENSOR "$Id: FGSensor.h,v 1.22 2013/06/10 01:59:16 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -76,7 +76,7 @@ Syntax:
   <drift_rate> number </drift_rate>
   <gain> number </gain>
   <bias> number </bias>
-  <delay> number < /delay>
+  <delay [type="time|frames"]> number < /delay>
 </sensor>
 @endcode
 
@@ -124,7 +124,7 @@ The delay element can specify a frame delay. The integer number provided is
 the number of frames to delay the output signal.
 
 @author Jon S. Berndt
-@version $Revision: 1.21 $
+@version $Revision: 1.22 $
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index 238e6776c1f6bdbf36c91d99f4548676ed3dd545..625bdb179a6d7b48c4b978b59fd52fe44b937ac2 100644 (file)
@@ -48,7 +48,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_SWITCH "$Id: FGSwitch.h,v 1.15 2012/10/27 20:29:01 jberndt Exp $"
+#define ID_SWITCH "$Id: FGSwitch.h,v 1.16 2013/01/26 17:06:50 bcoconni Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -127,7 +127,7 @@ ap/attitude_hold takes the value 1), the value of the switch component will be
 whatever value fcs/roll-ap-error-summer is.
 
 @author Jon S. Berndt
-@version $Id: FGSwitch.h,v 1.15 2012/10/27 20:29:01 jberndt Exp $
+@version $Id: FGSwitch.h,v 1.16 2013/01/26 17:06:50 bcoconni Exp $
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -185,7 +185,7 @@ private:
           } else {
             sign = 1.0;
           }
-          FGPropertyManager *node = propMan->GetNode(value, false);
+          FGPropertyNode *node = propMan->GetNode(value, false);
           if (node) {
             OutputProp = new FGPropertyValue(node);
           } else {
index 9693c3f0fe7052364199f6b4df1da375f10e465c..b17cf31e2fd411b3b7036477b2ead93eaf89fa4f 100644 (file)
@@ -47,7 +47,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGRocket.cpp,v 1.29 2013/01/12 21:11:59 jberndt Exp $";
+static const char *IdSrc = "$Id: FGRocket.cpp,v 1.30 2013/06/10 02:00:11 jberndt Exp $";
 static const char *IdHdr = ID_ROCKET;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -250,8 +250,8 @@ string FGRocket::GetEngineLabels(const string& delimiter)
 {
   std::ostringstream buf;
 
-  buf << Name << " Total Impulse (engine " << EngineNumber << " in psf)" << delimiter
-      << Name << " Total Vacuum Impulse (engine " << EngineNumber << " in psf)" << delimiter
+  buf << Name << " Total Impulse (engine " << EngineNumber << " in lbf)" << delimiter
+      << Name << " Total Vacuum Impulse (engine " << EngineNumber << " in lbf)" << delimiter
       << Thruster->GetThrusterLabels(EngineNumber, delimiter);
 
   return buf.str();
index eb3e465d3702721ba7bc47402f69aa0355ae3b41..8bb4b743c0152f59fa4e3cdf10b080ab0a769734 100644 (file)
@@ -48,7 +48,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_ROTOR "$Id: FGRotor.h,v 1.14 2012/03/18 15:48:36 jentron Exp $"
+#define ID_ROTOR "$Id: FGRotor.h,v 1.15 2013/01/26 17:06:50 bcoconni Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -230,7 +230,7 @@ CLASS DOCUMENTATION
     </dl>
 
     @author Thomas Kreitler
-    @version $Id: FGRotor.h,v 1.14 2012/03/18 15:48:36 jentron Exp $
+    @version $Id: FGRotor.h,v 1.15 2013/01/26 17:06:50 bcoconni Exp $
   */
 
 
@@ -369,7 +369,7 @@ private:
   double MaximalRPM;
   int    ExternalRPM;
   int    RPMdefinition;
-  FGPropertyManager* ExtRPMsource;
+  FGPropertyNode_ptr ExtRPMsource;
   double SourceGearRatio;
 
   // 'real' rotor parameters
index a6ac568aa24f7d13272bc56460f6592bfc3be862..c59be5c923e6ab786e2b1673906eee68d3d889e3 100644 (file)
@@ -47,7 +47,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGTank.cpp,v 1.36 2013/01/12 19:25:30 jberndt Exp $";
+static const char *IdSrc = "$Id: FGTank.cpp,v 1.37 2013/06/10 02:04:12 jberndt Exp $";
 static const char *IdHdr = ID_TANK;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -118,6 +118,13 @@ FGTank::FGTank(FGFDMExec* exec, Element* el, int tank_number)
     Capacity = 0.00001;
     Contents = 0.0;
   }
+  if (Contents > Capacity) {
+    cerr << "Tank content (" << Contents << " lbs) is greater than tank capacity ("
+         << Capacity << " lbs) for tank " << tank_number
+         << "! Did you accidentally swap contents and capacity?" << endl;
+    throw("tank definition error");
+  }
+
   PctFull = 100.0*Contents/Capacity;            // percent full; 0 to 100.0
 
   // Check whether this is a solid propellant "tank". Initialize it if true.