From f9689a561c4b5853dd45c06a74ebee25214d07f8 Mon Sep 17 00:00:00 2001 From: Anders Gidenstam Date: Tue, 11 Jun 2013 22:06:35 +0200 Subject: [PATCH] Synchronized with JSBSim/CVS. --- src/FDM/JSBSim/CMakeLists.txt | 2 + src/FDM/JSBSim/FGFDMExec.cpp | 120 ++-- src/FDM/JSBSim/FGFDMExec.h | 23 +- src/FDM/JSBSim/FGJSBBase.cpp | 4 +- src/FDM/JSBSim/JSBSim.cxx | 14 +- src/FDM/JSBSim/JSBSim.hxx | 2 + .../JSBSim/initialization/FGLinearization.cpp | 114 ++++ .../JSBSim/initialization/FGLinearization.h | 47 ++ .../JSBSim/initialization/FGSimplexTrim.cpp | 325 +++-------- src/FDM/JSBSim/initialization/FGSimplexTrim.h | 72 +-- src/FDM/JSBSim/initialization/FGTrimmer.cpp | 248 ++++---- src/FDM/JSBSim/initialization/FGTrimmer.h | 10 +- .../JSBSim/input_output/FGGroundCallback.h | 7 +- src/FDM/JSBSim/input_output/FGOutputType.cpp | 4 +- src/FDM/JSBSim/input_output/FGOutputType.h | 7 +- .../JSBSim/input_output/FGPropertyManager.cpp | 66 +-- .../JSBSim/input_output/FGPropertyManager.h | 74 ++- src/FDM/JSBSim/input_output/FGScript.cpp | 109 ++-- src/FDM/JSBSim/input_output/FGScript.h | 9 +- src/FDM/JSBSim/math/FGCondition.cpp | 4 +- src/FDM/JSBSim/math/FGFunction.cpp | 48 +- src/FDM/JSBSim/math/FGFunction.h | 547 +++++++++++++++++- src/FDM/JSBSim/math/FGNelderMead.cpp | 467 +++++++-------- src/FDM/JSBSim/math/FGNelderMead.h | 35 +- src/FDM/JSBSim/math/FGPropertyValue.cpp | 7 +- src/FDM/JSBSim/math/FGPropertyValue.h | 8 +- src/FDM/JSBSim/math/FGStateSpace.cpp | 25 +- src/FDM/JSBSim/math/FGStateSpace.h | 171 ++++-- src/FDM/JSBSim/math/FGTable.cpp | 4 +- src/FDM/JSBSim/math/FGTable.h | 14 +- src/FDM/JSBSim/models/FGAerodynamics.cpp | 8 +- src/FDM/JSBSim/models/FGAtmosphere.cpp | 21 +- src/FDM/JSBSim/models/FGAuxiliary.cpp | 8 +- src/FDM/JSBSim/models/FGAuxiliary.h | 9 +- src/FDM/JSBSim/models/FGFCS.cpp | 6 +- src/FDM/JSBSim/models/FGFCSChannel.h | 6 +- src/FDM/JSBSim/models/FGGasCell.cpp | 20 +- src/FDM/JSBSim/models/FGGasCell.h | 16 +- src/FDM/JSBSim/models/FGInput.cpp | 4 +- src/FDM/JSBSim/models/FGLGear.cpp | 7 +- src/FDM/JSBSim/models/FGOutput.cpp | 4 +- src/FDM/JSBSim/models/FGOutput.h | 6 +- src/FDM/JSBSim/models/FGPropagate.cpp | 6 +- src/FDM/JSBSim/models/FGPropagate.h | 33 +- .../models/flight_control/FGActuator.cpp | 11 +- .../JSBSim/models/flight_control/FGActuator.h | 8 +- .../JSBSim/models/flight_control/FGDeadBand.h | 7 +- .../models/flight_control/FGFCSComponent.cpp | 6 +- .../models/flight_control/FGFCSComponent.h | 13 +- .../JSBSim/models/flight_control/FGFilter.h | 8 +- src/FDM/JSBSim/models/flight_control/FGGain.h | 6 +- .../JSBSim/models/flight_control/FGPID.cpp | 10 +- src/FDM/JSBSim/models/flight_control/FGPID.h | 19 +- .../JSBSim/models/flight_control/FGSensor.h | 6 +- .../JSBSim/models/flight_control/FGSwitch.h | 6 +- src/FDM/JSBSim/models/propulsion/FGRocket.cpp | 6 +- src/FDM/JSBSim/models/propulsion/FGRotor.h | 6 +- src/FDM/JSBSim/models/propulsion/FGTank.cpp | 9 +- 58 files changed, 1804 insertions(+), 1058 deletions(-) create mode 100644 src/FDM/JSBSim/initialization/FGLinearization.cpp create mode 100644 src/FDM/JSBSim/initialization/FGLinearization.h diff --git a/src/FDM/JSBSim/CMakeLists.txt b/src/FDM/JSBSim/CMakeLists.txt index b136ccb7d..85c1fef7c 100644 --- a/src/FDM/JSBSim/CMakeLists.txt +++ b/src/FDM/JSBSim/CMakeLists.txt @@ -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 diff --git a/src/FDM/JSBSim/FGFDMExec.cpp b/src/FDM/JSBSim/FGFDMExec.cpp index e8bb6a1b3..6f75b26c0 100644 --- a/src/FDM/JSBSim/FGFDMExec.cpp +++ b/src/FDM/JSBSim/FGFDMExec.cpp @@ -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; inode->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); +} //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/FDM/JSBSim/FGFDMExec.h b/src/FDM/JSBSim/FGFDMExec.h index 2192e11ec..833bf4181 100644 --- a/src/FDM/JSBSim/FGFDMExec.h +++ b/src/FDM/JSBSim/FGFDMExec.h @@ -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. diff --git a/src/FDM/JSBSim/FGJSBBase.cpp b/src/FDM/JSBSim/FGJSBBase.cpp index ea646b4d7..7a2ad6714 100644 --- a/src/FDM/JSBSim/FGJSBBase.cpp +++ b/src/FDM/JSBSim/FGJSBBase.cpp @@ -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::Messages; FGJSBBase::Message FGJSBBase::localMsg; diff --git a/src/FDM/JSBSim/JSBSim.cxx b/src/FDM/JSBSim/JSBSim.cxx index b71d8700c..9ab5a192b 100644 --- a/src/FDM/JSBSim/JSBSim.cxx +++ b/src/FDM/JSBSim/JSBSim.cxx @@ -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; } /******************************************************************************/ diff --git a/src/FDM/JSBSim/JSBSim.hxx b/src/FDM/JSBSim/JSBSim.hxx index 8471ba1b4..ebb80c83e 100644 --- a/src/FDM/JSBSim/JSBSim.hxx +++ b/src/FDM/JSBSim/JSBSim.hxx @@ -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 index 000000000..c5d9caa87 --- /dev/null +++ b/src/FDM/JSBSim/initialization/FGLinearization.cpp @@ -0,0 +1,114 @@ +/* + * FGLinearization.cpp + * Copyright (C) James Goppert 2011 + * + * 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 . + */ + +#include "FGLinearization.h" +#include + +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 > A,B,C,D; + std::vector x0 = ss.x.get(), u0 = ss.u.get(); + std::vector 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 index 000000000..e26754430 --- /dev/null +++ b/src/FDM/JSBSim/initialization/FGLinearization.h @@ -0,0 +1,47 @@ +/* + * FGLinearization.h + * Copyright (C) James Goppert 2010 + * + * 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 . + */ + +#ifndef FGLinearization_H_ +#define FGLinearization_H_ + +#include "initialization/FGTrimmer.h" +#include "math/FGStateSpace.h" +#include +#include +#include "models/FGAircraft.h" +#include "models/propulsion/FGEngine.h" +#include "models/propulsion/FGTurbine.h" +#include "models/propulsion/FGTurboProp.h" +#include "math/FGNelderMead.h" +#include +#include +#include + +namespace JSBSim { + +class FGLinearization +{ +public: + FGLinearization(FGFDMExec * fdmPtr, int mode); +}; + +} // JSBSim + +#endif //FGLinearization_H_ + +// vim:ts=4:sw=4 diff --git a/src/FDM/JSBSim/initialization/FGSimplexTrim.cpp b/src/FDM/JSBSim/initialization/FGSimplexTrim.cpp index ec6ca6fc0..b8e645a4c 100644 --- a/src/FDM/JSBSim/initialization/FGSimplexTrim.cpp +++ b/src/FDM/JSBSim/initialization/FGSimplexTrim.cpp @@ -3,16 +3,16 @@ * Copyright (C) James Goppert 2010 * * 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 . */ @@ -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 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 > A,B,C,D; - std::vector x0 = ss.x.get(), u0 = ss.u.get(); - std::vector 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 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 diff --git a/src/FDM/JSBSim/initialization/FGSimplexTrim.h b/src/FDM/JSBSim/initialization/FGSimplexTrim.h index 3ee0dd3f0..9bfe51c3e 100644 --- a/src/FDM/JSBSim/initialization/FGSimplexTrim.h +++ b/src/FDM/JSBSim/initialization/FGSimplexTrim.h @@ -3,16 +3,16 @@ * Copyright (C) James Goppert 2010 * * 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 . */ @@ -37,41 +37,41 @@ namespace JSBSim { class FGSimplexTrim { public: - FGSimplexTrim(FGFDMExec * fdmPtr, TrimMode mode); + FGSimplexTrim(FGFDMExec * fdmPtr, TrimMode mode); private: - template - 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 + 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 &v) - { - _outputFile << _trimmer->eval(v) << std::endl;; - //std::cout << "v: "; - //for (int i=0;i &v) + { + _outputFile << _trimmer->eval(v) << std::endl;; + //std::cout << "v: "; + //for (int i=0;i * * 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 . */ @@ -39,44 +39,56 @@ FGTrimmer::FGTrimmer(FGFDMExec * fdm, Constraints * constraints) : { } -std::vector FGTrimmer::constrain(const std::vector & v) +FGTrimmer::~FGTrimmer() +{ +} + +std::vector FGTrimmer::constrain(const std::vector & 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 FGTrimmer::constrain(const std::vector & 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 FGTrimmer::constrain(const std::vector & v) for (unsigned int i=0; iGetPropulsion()->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; iGetPropulsion()->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::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::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 data; data.push_back(phi); @@ -182,7 +188,7 @@ void FGTrimmer::printSolution(std::ostream & stream, const std::vector & { 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 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 & << "\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 & 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 & 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 & v) +{ + constrain(v); + return compute_cost(); } } // JSBSim diff --git a/src/FDM/JSBSim/initialization/FGTrimmer.h b/src/FDM/JSBSim/initialization/FGTrimmer.h index 3cca7f320..ad116f5da 100644 --- a/src/FDM/JSBSim/initialization/FGTrimmer.h +++ b/src/FDM/JSBSim/initialization/FGTrimmer.h @@ -3,16 +3,16 @@ * Copyright (C) James Goppert 2010 * * 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 . */ @@ -42,9 +42,11 @@ public: bool coordinatedTurn, stabAxisRoll; }; FGTrimmer(FGFDMExec * fdm, Constraints * constraints); - std::vector constrain(const vector & v); + ~FGTrimmer(); + std::vector constrain(const vector & v); void printSolution(std::ostream & stream, const vector & v); void printState(std::ostream & stream); + double compute_cost(); double eval(const vector & v); static void limit(double min, double max, double &val) { diff --git a/src/FDM/JSBSim/input_output/FGGroundCallback.h b/src/FDM/JSBSim/input_output/FGGroundCallback.h index 91937956d..7af9ee787 100644 --- a/src/FDM/JSBSim/input_output/FGGroundCallback.h +++ b/src/FDM/JSBSim/input_output/FGGroundCallback.h @@ -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: diff --git a/src/FDM/JSBSim/input_output/FGOutputType.cpp b/src/FDM/JSBSim/input_output/FGOutputType.cpp index cdf568ee1..1abae8bdb 100644 --- a/src/FDM/JSBSim/input_output/FGOutputType.cpp +++ b/src/FDM/JSBSim/input_output/FGOutputType.cpp @@ -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 diff --git a/src/FDM/JSBSim/input_output/FGOutputType.h b/src/FDM/JSBSim/input_output/FGOutputType.h index d06ea2cb8..cbc63dc46 100644 --- a/src/FDM/JSBSim/input_output/FGOutputType.h +++ b/src/FDM/JSBSim/input_output/FGOutputType.h @@ -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 & outputProperties) + void SetOutputProperties(std::vector & outputProperties) { OutputProperties = outputProperties; } @@ -197,7 +196,7 @@ public: protected: int OutputIdx; int SubSystems; - std::vector OutputProperties; + std::vector OutputProperties; std::vector OutputCaptions; bool enabled; diff --git a/src/FDM/JSBSim/input_output/FGPropertyManager.cpp b/src/FDM/JSBSim/input_output/FGPropertyManager.cpp index 39e095a8a..aed2f322f 100644 --- a/src/FDM/JSBSim/input_output/FGPropertyManager.cpp +++ b/src/FDM/JSBSim/input_output/FGPropertyManager.cpp @@ -48,8 +48,6 @@ COMMENTS, REFERENCES, and NOTES [use "class documentation" below for API docs] namespace JSBSim { -std::vector 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 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; diff --git a/src/FDM/JSBSim/input_output/FGPropertyManager.h b/src/FDM/JSBSim/input_output/FGPropertyManager.h index e8156a0bb..57b523cb8 100644 --- a/src/FDM/JSBSim/input_output/FGPropertyManager.h +++ b/src/FDM/JSBSim/input_output/FGPropertyManager.h @@ -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 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_ptr; +typedef SGSharedPtr 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 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(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 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(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(*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(*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 tied_properties; + FGPropertyNode_ptr root; }; } #endif // FGPROPERTYMANAGER_H diff --git a/src/FDM/JSBSim/input_output/FGScript.cpp b/src/FDM/JSBSim/input_output/FGScript.cpp index bc512ad90..4d2b6ed0a 100644 --- a/src/FDM/JSBSim/input_output/FGScript.cpp +++ b/src/FDM/JSBSim/input_output/FGScript.cpp @@ -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; igetDoubleValue(); - if (Events[ev_ctr].Functions[i] != 0) { // Parameter should be set to a function value + for (i=0; iHasNode(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; iGetValue(); + 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; jGetRelativeName() - cout << " " << Events[ev_ctr].DisplayString[j] - << " = " << Events[ev_ctr].NotifyProperties[j]->getDoubleValue() << endl; + for (j=0; jGetRelativeName() + cout << " " << thisEvent.DisplayString[j] + << " = " << thisEvent.NotifyProperties[j]->getDoubleValue() << endl; } cout << endl; - Events[ev_ctr].Notified = true; + thisEvent.Notified = true; } } diff --git a/src/FDM/JSBSim/input_output/FGScript.h b/src/FDM/JSBSim/input_output/FGScript.h index 187b1a8c7..17abb4b38 100644 --- a/src/FDM/JSBSim/input_output/FGScript.h +++ b/src/FDM/JSBSim/input_output/FGScript.h @@ -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 "run" section, where the conditions are described in "event" clauses.

@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 SetParam; - vector NotifyProperties; + vector SetParam; + vector SetParamName; + vector NotifyProperties; vector DisplayString; vector Action; vector Type; diff --git a/src/FDM/JSBSim/math/FGCondition.cpp b/src/FDM/JSBSim/math/FGCondition.cpp index ddaf41829..e24cd2f62 100644 --- a/src/FDM/JSBSim/math/FGCondition.cpp +++ b/src/FDM/JSBSim/math/FGCondition.cpp @@ -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 { diff --git a/src/FDM/JSBSim/math/FGFunction.cpp b/src/FDM/JSBSim/math/FGFunction.cpp index 0cad19512..c64de4b50 100644 --- a/src/FDM/JSBSim/math/FGFunction.cpp +++ b/src/FDM/JSBSim/math/FGFunction.cpp @@ -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); - // } } } diff --git a/src/FDM/JSBSim/math/FGFunction.h b/src/FDM/JSBSim/math/FGFunction.h index 785648a82..43fe4212d 100644 --- a/src/FDM/JSBSim/math/FGFunction.h +++ b/src/FDM/JSBSim/math/FGFunction.h @@ -37,12 +37,13 @@ INCLUDES #include #include #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 - + Roll moment due to yaw rate aero/qbar-area @@ -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). +

Specific Function Definitions

+ +Note: In the definitions below, a "property" refers to a single property specified +within either the tag or the shortcut tag, \

\

. The +keyword "value" refers to a single numeric value specified either within the \\ +tag or the shortcut tag. The keyword "table" refers to a single table specified +either within the \\
tag or the shortcut 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 + + {properties, values, tables, or other function elements} + + + Example: Mach + 0.01 + + +

velocities/mach

+ 0.01 +
+ @endcode +- @b difference, subtracts the values of all immediate child elements from the value of the first child element: + @code + + {properties, values, tables, or other function elements} + + + Example: Mach - 0.01 + + +

velocities/mach

+ 0.01 +
+ @endcode +- @b product multiplies together the values of all immediate child elements: + @code + + {properties, values, tables, or other function elements} + + + Example: qbar*S*beta*CY_beta + + + aero/qbar-psf + metrics/Sw-sqft + aero/beta-rad + aero/coefficient/CY_beta + + @endcode +- @b quotient, divides the value of the first immediate child element by the second immediate child element: + @code + + {property, value, table, or other function element} + {property, value, table, or other function element} + + + Example: (2*GM)/R + + + + 2.0 +

guidance/executive/gm

+
+

position/radius-to-vehicle-ft

+
+ @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 + + {property, value, table, or other function element} + {property, value, table, or other function element} + + + Example: Mach^2 + + +

velocities/mach

+ 2.0 +
+ @endcode +- @b sqrt, takes the square root of the value of the immediate child element: + @code + + {property, value, table, or other function element} + + + Example: square root of 25 + + 25.0 + @endcode +- @b toradians, converts a presumed argument in degrees to radians by multiplying + the value of the immediate child element by pi/180: + @code + + {property, value, table, or other function element} + + + Example: convert 45 degrees to radians + + 45 + @endcode +- @b todegrees, converts a presumed argument in radians to degrees by multiplying + the value of the immediate child element by 180/pi: + @code + + {property, value, table, or other function element} + + + Example: convert 0.5*pi radians to degrees + + + 0.5 + + @endcode +- @b exp, raises "e" to the power of the immediate child element: + @code + + {property, value, table, or other function element} + + + Example: raise "e" to the 1.5 power, e^1.5 + + 1.5 + @endcode +- @b log2, calculates the log base 2 value of the immediate child element: + @code + + {property, value, table, or other function element} + + + Example: + 128 + @endcode +- @b ln, calculates the natural logarithm of the value of the immediate child element: + @code + + {property, value, table, or other function element} + + + Example: ln(128) + + 200 + @endcode +- @b log10 calculates the base 10 logarithm of the value of the immediate child element + @code + + {property, value, table, or other function element} + + + Example log(Mach) + +

velocities/mach

+ @endcode +- @b abs calculates the absolute value of the immediate child element + @code + + {property, value, table, or other function element} + + + Example: + +

flight-path/gamma-rad

+ @endcode +- @b sin calculates the sine of the value of the immediate child element (the argument is expected to be in radians) + @code + + {property, value, table, or other function element} + + + Example: + +

fcs/heading-true-degrees

+ @endcode +- @b cos calculates the cosine of the value of the immediate child element (the argument is expected to be in radians) + @code + + {property, value, table, or other function element} + + + Example: + +

fcs/heading-true-degrees

+ @endcode +- @b tan calculates the tangent of the value of the immediate child element (the argument is expected to be in radians) + @code + + {property, value, table, or other function element} + + + Example: + +

fcs/heading-true-degrees

+ @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 + + {property, value, table, or other function element} + + + Example: + + 0.5 + @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 + + {property, value, table, or other function element} + + + Example: + + 0.5 + @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 + + {property, value, table, or other function element} + + + Example: + + 0.5 + @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 + + {property, value, table, or other function element} {property, value, table, or other function element} + + + Example: inverse tangent of 0.5/0.25, evaluates to: 1.107 radians + + 0.5 0.25 + @endcode +- @b min returns the smallest value from all the immediate child elements + @code + + {properties, values, tables, or other function elements} + + + Example: returns the lesser of velocity and 2500 + + +

velocities/eci-velocity-mag-fps

+ 2500.0 +
+ @endcode +- @b max returns the largest value from all the immediate child elements + @code + + {properties, values, tables, or other function elements} + + + Example: returns the greater of velocity and 15000 + + +

velocities/eci-velocity-mag-fps

+ 15000.0 +
+ @endcode +- @b avg returns the average value of all the immediate child elements + @code + + {properties, values, tables, or other function elements} + + + Example: returns the average of the four numbers below, evaluates to 0.50. + + + 0.25 + 0.50 + 0.75 + 0.50 + + @endcode +- @b fraction returns the fractional part of the value of the immediate child element + @code + + {property, value, table, or other function element} + + + Example: returns the fractional part of pi - or, roughly, 0.1415926... + + + @endcode +- @b integer returns the integer portion of the value of the immediate child element + @code + + {property, value, table, or other function element} + + @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 + + {property, value, table, or other function element} {property, value, table, or other function element} + + + Example: 5 mod 2, evaluates to 1 + + 5 2 + @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 + + {property, value, table, or other function element} + {property, value, table, or other function element} + + + Example: returns 1 if thrust is less than 10,000, returns 0 otherwise + + +

propulsion/engine[2]/thrust-lbs

+ 10000.0 +
+ @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 + + {property, value, table, or other function element} + {property, value, table, or other function element} + + + Example: returns 1 if thrust is less than or equal to 10,000, returns 0 otherwise + + +

propulsion/engine[2]/thrust-lbs

+ 10000.0 +
+ @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 + + {property, value, table, or other function element} + {property, value, table, or other function element} + + + Example: returns 1 if thrust is greater than 10,000, returns 0 otherwise + + +

propulsion/engine[2]/thrust-lbs

+ 10000.0 +
+ @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 + + {property, value, table, or other function element} + {property, value, table, or other function element} + + + Example: returns 1 if thrust is greater than or equal to 10,000, returns 0 otherwise + + +

propulsion/engine[2]/thrust-lbs

+ 10000.0 +
+ @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 + + {property, value, table, or other function element} + {property, value, table, or other function element} + + + Example: returns 1 if thrust is equal to 10,000, returns 0 otherwise + + +

propulsion/engine[2]/thrust-lbs

+ 10000.0 +
+ @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 + + {property, value, table, or other function element} + {property, value, table, or other function element} + + + Example: returns 1 if thrust is not 0, returns 0 otherwise + + +

propulsion/engine[2]/thrust-lbs

+ 0.0 +
+ @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 + + {properties, values, tables, or other function elements} + + + Example: returns 1 if the specified flags are all 1 + + +

guidance/first-stage-flight-flag

+

control/engines-running-flag

+
+ @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 + + {properties, values, tables, or other function elements} + + + Example: returns 1 if any of the specified flags are 1 + + +

guidance/first-stage-flight-flag

+

control/engines-running-flag

+
+ @endcode +- @b not returns the inverse of the value of the supplied immediate child element + (e.g., returns 1 if supplied a 0) + @code + + {property, value, table, or other function element} + + + Example: returns 0 if the value of the supplied flag is 1 + +

guidance/first-stage-flight-flag

+ @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 + + {property, value, table, or other function element} + {property, value, table, or other function element} + {property, value, table, or other function element} + + + 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. + + +

executive/flight-mode

2
+ 0.00 +

control/pitch-lag

+
+ @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 + + {property, value, table, or other function element} + {property, value, table, or other function element} + {property, value, table, or other function element} + ... + + + Example: if flight-mode is 2, the switch function returns 0.50 + + +

executive/flight-mode

+ 0.25 + 0.50 + 0.75 + 1.00 +
+ @endcode +- @b random Takes no arguments and returns a Gaussian distributed random number + @code @endcode +- @b urandom Takes no arguments and returns a uniformly distributed random number + between -1 and +1 + @code@endcode +- @b pi Takes no argument and returns the value of Pi + @code@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 + + {property, value, table, or other function element} + {property, value, table, or other function element} {property, value, table, or other function element} + ... + + + Example: If mach is 0.4, the interpolation will return 0.375. If mach is 1.5, the interpolation + will return 0.60. + + +

velocities/mach

+ 0.00 0.25 + 0.80 0.50 + 0.90 0.60 +
+ @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); diff --git a/src/FDM/JSBSim/math/FGNelderMead.cpp b/src/FDM/JSBSim/math/FGNelderMead.cpp index 55fe50018..c38cb5d50 100644 --- a/src/FDM/JSBSim/math/FGNelderMead.cpp +++ b/src/FDM/JSBSim/math/FGNelderMead.cpp @@ -3,16 +3,16 @@ * Copyright (C) James Goppert 2010 * * 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 . */ @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -33,7 +34,7 @@ FGNelderMead::FGNelderMead(Function * f, const std::vector & initialGues const std::vector & upperBound, const std::vector & 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 & 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 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;vertexeval(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_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::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::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 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 guess(m_nDim); + if (iter == 0) + { + //std::cout << "constructing simplex" << std::endl; + guess = initialGuess; + } + else + { + if (std::abs(minCost-minCostPrevResize) < std::numeric_limits::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_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::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::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 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 FGNelderMead::getSolution() @@ -271,8 +272,8 @@ std::vector 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::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 & guess, for (int vertex=0;vertex & vertex, } } +double FGNelderMead::eval(const std::vector & vertex, bool check) +{ + if (check) { + double cost0 = m_f->eval(vertex); + double cost1 = m_f->eval(vertex); + if ((cost0 - cost1) > std::numeric_limits::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 diff --git a/src/FDM/JSBSim/math/FGNelderMead.h b/src/FDM/JSBSim/math/FGNelderMead.h index 64eb43fc4..474f1fb9b 100644 --- a/src/FDM/JSBSim/math/FGNelderMead.h +++ b/src/FDM/JSBSim/math/FGNelderMead.h @@ -3,16 +3,16 @@ * Copyright (C) James Goppert 2010 * * 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 . */ @@ -35,7 +35,7 @@ public: virtual double eval(const std::vector & v) = 0; virtual ~Function() {}; }; - class Callback + class Callback { public: virtual void eval(const std::vector & v) = 0; @@ -49,43 +49,44 @@ public: double rtol=std::numeric_limits::epsilon(), double abstol=std::numeric_limits::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 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 & m_lowerBound; const std::vector & m_upperBound; int m_nDim, m_nVert, m_iMax, m_iNextMax, m_iMin; std::vector< std::vector > m_simplex; std::vector m_cost; std::vector m_elemSum; - int m_status; + int m_status; const std::vector & initialGuess; const std::vector & 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 & guess, const std::vector & stepSize); void boundVertex(std::vector & vertex, const std::vector & upperBound, const std::vector & lowerBound); + double eval(const std::vector & vertex, bool check = false); }; } // JSBSim diff --git a/src/FDM/JSBSim/math/FGPropertyValue.cpp b/src/FDM/JSBSim/math/FGPropertyValue.cpp index 7f448da3c..1407a0cb7 100644 --- a/src/FDM/JSBSim/math/FGPropertyValue.cpp +++ b/src/FDM/JSBSim/math/FGPropertyValue.cpp @@ -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. diff --git a/src/FDM/JSBSim/math/FGPropertyValue.h b/src/FDM/JSBSim/math/FGPropertyValue.h index c716cf599..4ea0e5393 100644 --- a/src/FDM/JSBSim/math/FGPropertyValue.h +++ b/src/FDM/JSBSim/math/FGPropertyValue.h @@ -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; }; diff --git a/src/FDM/JSBSim/math/FGStateSpace.cpp b/src/FDM/JSBSim/math/FGStateSpace.cpp index b65995098..77f080ba1 100644 --- a/src/FDM/JSBSim/math/FGStateSpace.cpp +++ b/src/FDM/JSBSim/math/FGStateSpace.cpp @@ -3,22 +3,23 @@ * Copyright (C) James Goppert 2010 * * 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 . */ #include "FGStateSpace.h" #include #include +#include namespace JSBSim { @@ -77,7 +78,23 @@ void FGStateSpace::numericalJacobian(std::vector< std::vector > & 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) diff --git a/src/FDM/JSBSim/math/FGStateSpace.h b/src/FDM/JSBSim/math/FGStateSpace.h index e91257ab0..ffbf63f3e 100644 --- a/src/FDM/JSBSim/math/FGStateSpace.h +++ b/src/FDM/JSBSim/math/FGStateSpace.h @@ -3,16 +3,16 @@ * Copyright (C) James Goppert 2010 * * 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 . */ @@ -30,6 +30,7 @@ #include "models/FGFCS.h" #include #include +#include namespace JSBSim { @@ -57,9 +58,9 @@ public: std::vector 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 vals) { for (int i=0;iset(vals[i]); - m_fdm->RunIC(); + m_stateSpace->run(); } void set(double * array) { for (int i=0;iset(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; iGetPropulsion()->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::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;iGetIC()->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; } }; diff --git a/src/FDM/JSBSim/math/FGTable.cpp b/src/FDM/JSBSim/math/FGTable.cpp index 08396eaae..2bc2b7499 100644 --- a/src/FDM/JSBSim/math/FGTable.cpp +++ b/src/FDM/JSBSim/math/FGTable.cpp @@ -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; diff --git a/src/FDM/JSBSim/math/FGTable.h b/src/FDM/JSBSim/math/FGTable.h index 1989de4c2..377750b5a 100644 --- a/src/FDM/JSBSim/math/FGTable.h +++ b/src/FDM/JSBSim/math/FGTable.h @@ -38,16 +38,17 @@ SENTRY INCLUDES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -#include "FGParameter.h" #include #include #include +#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 Tables; unsigned int nRows, nCols, nTables, dimension; diff --git a/src/FDM/JSBSim/models/FGAerodynamics.cpp b/src/FDM/JSBSim/models/FGAerodynamics.cpp index b4df456fd..cb6152991 100644 --- a/src/FDM/JSBSim/models/FGAerodynamics.cpp +++ b/src/FDM/JSBSim/models/FGAerodynamics.cpp @@ -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; diff --git a/src/FDM/JSBSim/models/FGAtmosphere.cpp b/src/FDM/JSBSim/models/FGAtmosphere.cpp index 4d52bd789..9ac2439fd 100644 --- a/src/FDM/JSBSim/models/FGAtmosphere.cpp +++ b/src/FDM/JSBSim/models/FGAtmosphere.cpp @@ -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; diff --git a/src/FDM/JSBSim/models/FGAuxiliary.cpp b/src/FDM/JSBSim/models/FGAuxiliary.cpp index 5eed15f61..557b7e366 100644 --- a/src/FDM/JSBSim/models/FGAuxiliary.cpp +++ b/src/FDM/JSBSim/models/FGAuxiliary.cpp @@ -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); */ diff --git a/src/FDM/JSBSim/models/FGAuxiliary.h b/src/FDM/JSBSim/models/FGAuxiliary.h index 4f2250e6d..8835335fe 100644 --- a/src/FDM/JSBSim/models/FGAuxiliary.h +++ b/src/FDM/JSBSim/models/FGAuxiliary.h @@ -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 diff --git a/src/FDM/JSBSim/models/FGFCS.cpp b/src/FDM/JSBSim/models/FGFCS.cpp index 872a7326d..bc9d703c9 100644 --- a/src/FDM/JSBSim/models/FGFCS.cpp +++ b/src/FDM/JSBSim/models/FGFCS.cpp @@ -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) { diff --git a/src/FDM/JSBSim/models/FGFCSChannel.h b/src/FDM/JSBSim/models/FGFCSChannel.h index 16f13b784..fafd7230f 100644 --- a/src/FDM/JSBSim/models/FGFCSChannel.h +++ b/src/FDM/JSBSim/models/FGFCSChannel.h @@ -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 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; }; } diff --git a/src/FDM/JSBSim/models/FGGasCell.cpp b/src/FDM/JSBSim/models/FGGasCell.cpp index f2f6688c3..77e547412 100644 --- a/src/FDM/JSBSim/models/FGGasCell.cpp +++ b/src/FDM/JSBSim/models/FGGasCell.cpp @@ -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 } diff --git a/src/FDM/JSBSim/models/FGGasCell.h b/src/FDM/JSBSim/models/FGGasCell.h index ff3613c17..a4851e9b9 100644 --- a/src/FDM/JSBSim/models/FGGasCell.h +++ b/src/FDM/JSBSim/models/FGGasCell.h @@ -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). diff --git a/src/FDM/JSBSim/models/FGInput.cpp b/src/FDM/JSBSim/models/FGInput.cpp index 87455e3cd..d10ceacee 100644 --- a/src/FDM/JSBSim/models/FGInput.cpp +++ b/src/FDM/JSBSim/models/FGInput.cpp @@ -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 diff --git a/src/FDM/JSBSim/models/FGLGear.cpp b/src/FDM/JSBSim/models/FGLGear.cpp index c1d606993..c31f4f2d4 100644 --- a/src/FDM/JSBSim/models/FGLGear.cpp +++ b/src/FDM/JSBSim/models/FGLGear.cpp @@ -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(); } diff --git a/src/FDM/JSBSim/models/FGOutput.cpp b/src/FDM/JSBSim/models/FGOutput.cpp index 28248fc34..b77ba859e 100644 --- a/src/FDM/JSBSim/models/FGOutput.cpp +++ b/src/FDM/JSBSim/models/FGOutput.cpp @@ -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 & outputProperties) + std::vector & outputProperties) { unsigned int idx = OutputTypes.size(); FGOutputType* Output = 0; diff --git a/src/FDM/JSBSim/models/FGOutput.h b/src/FDM/JSBSim/models/FGOutput.h index ce2674010..dcbc8adc1 100644 --- a/src/FDM/JSBSim/models/FGOutput.h +++ b/src/FDM/JSBSim/models/FGOutput.h @@ -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 & outputProperties); + std::vector & 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 diff --git a/src/FDM/JSBSim/models/FGPropagate.cpp b/src/FDM/JSBSim/models/FGPropagate.cpp index a2181e56e..a0ca06c37 100644 --- a/src/FDM/JSBSim/models/FGPropagate.cpp +++ b/src/FDM/JSBSim/models/FGPropagate.cpp @@ -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); diff --git a/src/FDM/JSBSim/models/FGPropagate.h b/src/FDM/JSBSim/models/FGPropagate.h index 20841c10d..aead73c27 100644 --- a/src/FDM/JSBSim/models/FGPropagate.h +++ b/src/FDM/JSBSim/models/FGPropagate.h @@ -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. diff --git a/src/FDM/JSBSim/models/flight_control/FGActuator.cpp b/src/FDM/JSBSim/models/flight_control/FGActuator.cpp index f739a76a7..a335689c5 100644 --- a/src/FDM/JSBSim/models/flight_control/FGActuator.cpp +++ b/src/FDM/JSBSim/models/flight_control/FGActuator.cpp @@ -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 diff --git a/src/FDM/JSBSim/models/flight_control/FGActuator.h b/src/FDM/JSBSim/models/flight_control/FGActuator.h index 650af2f9a..a8e8d5932 100644 --- a/src/FDM/JSBSim/models/flight_control/FGActuator.h +++ b/src/FDM/JSBSim/models/flight_control/FGActuator.h @@ -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; diff --git a/src/FDM/JSBSim/models/flight_control/FGDeadBand.h b/src/FDM/JSBSim/models/flight_control/FGDeadBand.h index 80464769f..d1aab83e1 100644 --- a/src/FDM/JSBSim/models/flight_control/FGDeadBand.h +++ b/src/FDM/JSBSim/models/flight_control/FGDeadBand.h @@ -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); diff --git a/src/FDM/JSBSim/models/flight_control/FGFCSComponent.cpp b/src/FDM/JSBSim/models/flight_control/FGFCSComponent.cpp index dfa2e46b1..0de618984 100644 --- a/src/FDM/JSBSim/models/flight_control/FGFCSComponent.cpp +++ b/src/FDM/JSBSim/models/flight_control/FGFCSComponent.cpp @@ -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; diff --git a/src/FDM/JSBSim/models/flight_control/FGFCSComponent.h b/src/FDM/JSBSim/models/flight_control/FGFCSComponent.h index d79a2e66c..d050a2833 100644 --- a/src/FDM/JSBSim/models/flight_control/FGFCSComponent.h +++ b/src/FDM/JSBSim/models/flight_control/FGFCSComponent.h @@ -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 OutputNodes; - FGPropertyManager* ClipMinPropertyNode; - FGPropertyManager* ClipMaxPropertyNode; + FGPropertyNode_ptr treenode; + std::vector OutputNodes; + FGPropertyNode_ptr ClipMinPropertyNode; + FGPropertyNode_ptr ClipMaxPropertyNode; std::vector InputNodes; std::vector InputNames; std::vector InputSigns; diff --git a/src/FDM/JSBSim/models/flight_control/FGFilter.h b/src/FDM/JSBSim/models/flight_control/FGFilter.h index efb03541c..4211ccc72 100644 --- a/src/FDM/JSBSim/models/flight_control/FGFilter.h +++ b/src/FDM/JSBSim/models/flight_control/FGFilter.h @@ -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; diff --git a/src/FDM/JSBSim/models/flight_control/FGGain.h b/src/FDM/JSBSim/models/flight_control/FGGain.h index 5383cab20..2105ff2a1 100644 --- a/src/FDM/JSBSim/models/flight_control/FGGain.h +++ b/src/FDM/JSBSim/models/flight_control/FGGain.h @@ -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; diff --git a/src/FDM/JSBSim/models/flight_control/FGPID.cpp b/src/FDM/JSBSim/models/flight_control/FGPID.cpp index c541a5c55..95efe6039 100644 --- a/src/FDM/JSBSim/models/flight_control/FGPID.cpp +++ b/src/FDM/JSBSim/models/flight_control/FGPID.cpp @@ -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); } diff --git a/src/FDM/JSBSim/models/flight_control/FGPID.h b/src/FDM/JSBSim/models/flight_control/FGPID.h index 74d9aeae9..6069d3b52 100644 --- a/src/FDM/JSBSim/models/flight_control/FGPID.h +++ b/src/FDM/JSBSim/models/flight_control/FGPID.h @@ -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, @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); }; diff --git a/src/FDM/JSBSim/models/flight_control/FGSensor.h b/src/FDM/JSBSim/models/flight_control/FGSensor.h index 09b037696..be0eea212 100644 --- a/src/FDM/JSBSim/models/flight_control/FGSensor.h +++ b/src/FDM/JSBSim/models/flight_control/FGSensor.h @@ -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: number number number - number < /delay> + number < /delay> @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 $ */ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/FDM/JSBSim/models/flight_control/FGSwitch.h b/src/FDM/JSBSim/models/flight_control/FGSwitch.h index 238e6776c..625bdb179 100644 --- a/src/FDM/JSBSim/models/flight_control/FGSwitch.h +++ b/src/FDM/JSBSim/models/flight_control/FGSwitch.h @@ -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 { diff --git a/src/FDM/JSBSim/models/propulsion/FGRocket.cpp b/src/FDM/JSBSim/models/propulsion/FGRocket.cpp index 9693c3f0f..b17cf31e2 100644 --- a/src/FDM/JSBSim/models/propulsion/FGRocket.cpp +++ b/src/FDM/JSBSim/models/propulsion/FGRocket.cpp @@ -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(); diff --git a/src/FDM/JSBSim/models/propulsion/FGRotor.h b/src/FDM/JSBSim/models/propulsion/FGRotor.h index eb3e465d3..8bb4b743c 100644 --- a/src/FDM/JSBSim/models/propulsion/FGRotor.h +++ b/src/FDM/JSBSim/models/propulsion/FGRotor.h @@ -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 @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 diff --git a/src/FDM/JSBSim/models/propulsion/FGTank.cpp b/src/FDM/JSBSim/models/propulsion/FGTank.cpp index a6ac568aa..c59be5c92 100644 --- a/src/FDM/JSBSim/models/propulsion/FGTank.cpp +++ b/src/FDM/JSBSim/models/propulsion/FGTank.cpp @@ -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. -- 2.39.5