1
0
Fork 0

Synchronized with JSBSim/CVS.

This commit is contained in:
Anders Gidenstam 2013-06-11 22:06:35 +02:00
parent dfa583c014
commit f9689a561c
58 changed files with 1767 additions and 1021 deletions

View file

@ -9,6 +9,7 @@ set(HEADERS
initialization/FGTrimAxis.h initialization/FGTrimAxis.h
initialization/FGSimplexTrim.h initialization/FGSimplexTrim.h
initialization/FGTrimmer.h initialization/FGTrimmer.h
initialization/FGLinearization.h
input_output/FGXMLParse.h input_output/FGXMLParse.h
input_output/FGXMLFileRead.h input_output/FGXMLFileRead.h
input_output/FGPropertyManager.h input_output/FGPropertyManager.h
@ -100,6 +101,7 @@ set(SOURCES
initialization/FGTrimAxis.cpp initialization/FGTrimAxis.cpp
initialization/FGSimplexTrim.cpp initialization/FGSimplexTrim.cpp
initialization/FGTrimmer.cpp initialization/FGTrimmer.cpp
initialization/FGLinearization.cpp
input_output/FGGroundCallback.cpp input_output/FGGroundCallback.cpp
input_output/FGPropertyManager.cpp input_output/FGPropertyManager.cpp
input_output/FGScript.cpp input_output/FGScript.cpp

View file

@ -65,6 +65,7 @@ INCLUDES
#include "models/FGOutput.h" #include "models/FGOutput.h"
#include "initialization/FGInitialCondition.h" #include "initialization/FGInitialCondition.h"
#include "initialization/FGSimplexTrim.h" #include "initialization/FGSimplexTrim.h"
#include "initialization/FGLinearization.h"
#include "input_output/FGPropertyManager.h" #include "input_output/FGPropertyManager.h"
#include "input_output/FGScript.h" #include "input_output/FGScript.h"
@ -72,7 +73,7 @@ using namespace std;
namespace JSBSim { 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; 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 // Prepare FDMctr for the next child FDM id
(*FDMctr)++; // instance. "child" instances are loaded last. (*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); Debug(0);
// this is to catch errors in binding member functions to the property tree. // this is to catch errors in binding member functions to the property tree.
try { 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_trim_analysis", this, (iPMF)0, &FGFDMExec::DoTrimAnalysis, false);
instance->Tie("simulation/do_simple_trim", this, (iPMF)0, &FGFDMExec::DoTrim, 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_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/reset", this, (iPMF)0, &FGFDMExec::ResetToInitialConditions, false);
instance->Tie("simulation/randomseed", this, (iPMF)0, &FGFDMExec::SRand, false); instance->Tie("simulation/randomseed", this, (iPMF)0, &FGFDMExec::SRand, false);
instance->Tie("simulation/terminate", (int *)&Terminate); 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); instance->Tie("simulation/frame", (int *)&Frame, false);
// simplex trim properties // simplex trim properties
instance->SetDouble("trim/solver/rtol",0.0001); instanceRoot->SetDouble("trim/solver/rtol",0.0001);
instance->SetDouble("trim/solver/speed",2); instanceRoot->SetDouble("trim/solver/speed",2);
instance->SetDouble("trim/solver/abstol",0.001); instanceRoot->SetDouble("trim/solver/abstol",0.001);
instance->SetDouble("trim/solver/iterMax",2000); instanceRoot->SetDouble("trim/solver/iterMax",2000);
instance->SetInt("trim/solver/debugLevel",0); instanceRoot->SetInt("trim/solver/debugLevel",0);
instance->SetDouble("trim/solver/random",0); instanceRoot->SetDouble("trim/solver/random",0);
instance->SetBool("trim/solver/showSimplex",false); instanceRoot->SetBool("trim/solver/showSimplex",false);
// instance->SetBool("trim/solver/showConvergence",true); instanceRoot->SetBool("trim/solver/showConvergence",false);
instance->SetBool("trim/solver/pause",false); instanceRoot->SetBool("trim/solver/pause",false);
instanceRoot->SetBool("trim/solver/variablePropPitch",false);
instance->SetDouble("trim/solver/throttleGuess",0.50); instanceRoot->SetDouble("trim/solver/throttleGuess",0.50);
instance->SetDouble("trim/solver/throttleMin",0.0); instanceRoot->SetDouble("trim/solver/throttleMin",0.0);
instance->SetDouble("trim/solver/throttleMax",1.0); instanceRoot->SetDouble("trim/solver/throttleMax",1.0);
// instance->SetDouble("trim/solver/throttleInitialStepSize",0.1); instanceRoot->SetDouble("trim/solver/throttleStep",0.1);
instance->SetDouble("trim/solver/throttleStep",0.1);
instance->SetDouble("trim/solver/aileronGuess",0); instanceRoot->SetDouble("trim/solver/aileronGuess",0);
instance->SetDouble("trim/solver/aileronMin",-1.00); instanceRoot->SetDouble("trim/solver/aileronMin",-1.00);
instance->SetDouble("trim/solver/aileronMax",1.00); instanceRoot->SetDouble("trim/solver/aileronMax",1.00);
// instance->SetDouble("trim/solver/aileronInitialStepSize",0.1); instanceRoot->SetDouble("trim/solver/aileronStep",0.1);
instance->SetDouble("trim/solver/aileronStep",0.1);
instance->SetDouble("trim/solver/rudderGuess",0); instanceRoot->SetDouble("trim/solver/rudderGuess",0);
instance->SetDouble("trim/solver/rudderMin",-1.00); instanceRoot->SetDouble("trim/solver/rudderMin",-1.00);
instance->SetDouble("trim/solver/rudderMax",1.00); instanceRoot->SetDouble("trim/solver/rudderMax",1.00);
// instance->SetDouble("trim/solver/rudderInitialStepSize",0.1); instanceRoot->SetDouble("trim/solver/rudderStep",0.1);
instance->SetDouble("trim/solver/rudderStep",0.1);
instance->SetDouble("trim/solver/elevatorGuess",-0.1); instanceRoot->SetDouble("trim/solver/elevatorGuess",-0.1);
instance->SetDouble("trim/solver/elevatorMin",-1.0); instanceRoot->SetDouble("trim/solver/elevatorMin",-1.0);
instance->SetDouble("trim/solver/elevatorMax",1.0); instanceRoot->SetDouble("trim/solver/elevatorMax",1.0);
// instance->SetDouble("trim/solver/elevatorInitialStepSize",0.1); instanceRoot->SetDouble("trim/solver/elevatorStep",0.1);
instance->SetDouble("trim/solver/elevatorStep",0.1);
instance->SetDouble("trim/solver/alphaGuess",0.05); instanceRoot->SetDouble("trim/solver/alphaGuess",0.05);
instance->SetDouble("trim/solver/alphaMin",-0.1); instanceRoot->SetDouble("trim/solver/alphaMin",-0.1);
instance->SetDouble("trim/solver/alphaMax",.18); instanceRoot->SetDouble("trim/solver/alphaMax",.18);
// instance->SetDouble("trim/solver/alphaInitialStepSize",0.1); instanceRoot->SetDouble("trim/solver/alphaStep",0.05);
instance->SetDouble("trim/solver/alphaStep",0.05);
instance->SetDouble("trim/solver/betaGuess",0); instanceRoot->SetDouble("trim/solver/betaGuess",0);
instance->SetDouble("trim/solver/betaMin",-0.05); instanceRoot->SetDouble("trim/solver/betaMin",-0.1);
instance->SetDouble("trim/solver/betaMax",0.05); instanceRoot->SetDouble("trim/solver/betaMax",0.1);
// instance->SetDouble("trim/solver/betaInitialStepSize",0.1); instanceRoot->SetDouble("trim/solver/betaStep",0.0001);
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);
Constructing = false; Constructing = false;
} }
@ -223,6 +216,8 @@ FGFDMExec::~FGFDMExec()
Unbind(); Unbind();
DeAllocate(); DeAllocate();
delete instance;
if (IdFDM == 0) { // Meaning this is no child FDM if (IdFDM == 0) { // Meaning this is no child FDM
if(Root != 0) { if(Root != 0) {
if(StandAlone) if(StandAlone)
@ -922,7 +917,7 @@ bool FGFDMExec::LoadModel(const string& model, bool addModelToPath)
if (result) { if (result) {
struct PropertyCatalogStructure masterPCS; struct PropertyCatalogStructure masterPCS;
masterPCS.base_string = ""; masterPCS.base_string = "";
masterPCS.node = (FGPropertyManager*)Root; masterPCS.node = Root->GetNode();
BuildPropertyCatalog(&masterPCS); BuildPropertyCatalog(&masterPCS);
} }
@ -944,6 +939,7 @@ void FGFDMExec::BuildPropertyCatalog(struct PropertyCatalogStructure* pcs)
int node_idx = 0; int node_idx = 0;
for (int i=0; i<pcs->node->nChildren(); i++) { for (int i=0; i<pcs->node->nChildren(); i++) {
string access="";
pcsNew->base_string = pcs->base_string + "/" + pcs->node->getChild(i)->getName(); pcsNew->base_string = pcs->base_string + "/" + pcs->node->getChild(i)->getName();
node_idx = pcs->node->getChild(i)->getIndex(); node_idx = pcs->node->getChild(i)->getIndex();
if (node_idx != 0) { if (node_idx != 0) {
@ -953,9 +949,11 @@ void FGFDMExec::BuildPropertyCatalog(struct PropertyCatalogStructure* pcs)
if (pcsNew->base_string.substr(0,12) == string("/fdm/jsbsim/")) { if (pcsNew->base_string.substr(0,12) == string("/fdm/jsbsim/")) {
pcsNew->base_string = pcsNew->base_string.erase(0,12); 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 { } else {
pcsNew->node = (FGPropertyManager*)pcs->node->getChild(i); pcsNew->node = (FGPropertyNode*)pcs->node->getChild(i);
BuildPropertyCatalog(pcsNew); BuildPropertyCatalog(pcsNew);
} }
} }
@ -1193,8 +1191,20 @@ void FGFDMExec::DoSimplexTrim(int mode)
FGSimplexTrim trim(this, (JSBSim::TrimMode)mode); FGSimplexTrim trim(this, (JSBSim::TrimMode)mode);
sim_time = saved_time; sim_time = saved_time;
Setsim_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);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -56,7 +56,7 @@ INCLUDES
DEFINITIONS 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 FORWARD DECLARATIONS
@ -179,7 +179,7 @@ CLASS DOCUMENTATION
property actually maps toa function call of DoTrim(). property actually maps toa function call of DoTrim().
@author Jon S. Berndt @author Jon S. Berndt
@version $Revision: 1.80 $ @version $Revision: 1.83 $
*/ */
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -392,13 +392,14 @@ public:
/** Retrieves the value of a property. /** Retrieves the value of a property.
@param property the name of the property @param property the name of the property
@result the value of the specified 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. /** Sets a property value.
@param property the property to be set @param property the property to be set
@param value the value to set the property to */ @param value the value to set the property to */
inline void SetPropertyValue(const string& property, double value) { inline void SetPropertyValue(const string& property, double value) {
instance->SetDouble(property, value); instance->GetNode()->SetDouble(property, value);
} }
/// Returns the model name. /// Returns the model name.
@ -448,12 +449,13 @@ public:
/** Sets (or overrides) the output filename /** Sets (or overrides) the output filename
@param fname the name of the file to output data to @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 */ @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. /** 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. */ 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. /** Executes trimming in the selected mode.
* @param mode Specifies how to trim: * @param mode Specifies how to trim:
@ -467,6 +469,11 @@ public:
void DoTrim(int mode); void DoTrim(int mode);
void DoSimplexTrim(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. /// Disables data logging to all outputs.
void DisableOutput(void) { Output->Disable(); } void DisableOutput(void) { Output->Disable(); }
/// Enables data logging to all outputs. /// Enables data logging to all outputs.
@ -490,7 +497,7 @@ public:
/// Name of the property. /// Name of the property.
string base_string; string base_string;
/// The node for the property. /// The node for the property.
FGPropertyManager *node; FGPropertyNode_ptr node;
}; };
/** Builds a catalog of properties. /** Builds a catalog of properties.

View file

@ -44,7 +44,7 @@ INCLUDES
namespace JSBSim { 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; static const char *IdHdr = ID_JSBBASE;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -106,7 +106,7 @@ const double FGJSBBase::kgtolb = 2.20462;
const double FGJSBBase::kgtoslug = 0.06852168; const double FGJSBBase::kgtoslug = 0.06852168;
const string FGJSBBase::needed_cfg_version = "2.0"; const string FGJSBBase::needed_cfg_version = "2.0";
const string FGJSBBase::JSBSim_version = "1.0 "__DATE__" "__TIME__; const string FGJSBBase::JSBSim_version = "1.0 " __DATE__ " " __TIME__ ;
std::queue <FGJSBBase::Message> FGJSBBase::Messages; std::queue <FGJSBBase::Message> FGJSBBase::Messages;
FGJSBBase::Message FGJSBBase::localMsg; FGJSBBase::Message FGJSBBase::localMsg;

View file

@ -90,9 +90,9 @@ public:
/** Get the altitude above sea level dependent on the location. */ /** Get the altitude above sea level dependent on the location. */
virtual double GetAltitude(const FGLocation& l) const { virtual double GetAltitude(const FGLocation& l) const {
double pt[3] = { SG_FEET_TO_METER*l(eX), double pt[3] = { SG_FEET_TO_METER*l(FGJSBBase::eX),
SG_FEET_TO_METER*l(eY), SG_FEET_TO_METER*l(FGJSBBase::eY),
SG_FEET_TO_METER*l(eZ) }; SG_FEET_TO_METER*l(FGJSBBase::eZ) };
double lat, lon, alt; double lat, lon, alt;
sgCartToGeod( pt, &lat, &lon, &alt); sgCartToGeod( pt, &lat, &lon, &alt);
return alt * SG_METER_TO_FEET; return alt * SG_METER_TO_FEET;
@ -102,7 +102,7 @@ public:
virtual double GetAGLevel(double t, const FGLocation& l, virtual double GetAGLevel(double t, const FGLocation& l,
FGLocation& cont, FGColumnVector3& n, FGLocation& cont, FGColumnVector3& n,
FGColumnVector3& v, FGColumnVector3& w) const { 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; 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, mInterface->get_agl_ft(t, loc_cart, SG_METER_TO_FEET*2, contact, normal,
vel, angularVel, &agl); vel, angularVel, &agl);
@ -114,7 +114,7 @@ public:
} }
virtual double GetTerrainGeoCentRadius(double t, const FGLocation& l) const { 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; 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, mInterface->get_agl_ft(t, loc_cart, SG_METER_TO_FEET*2, contact, normal,
vel, angularVel, &agl); 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. // Register ground callback.
fdmex->SetGroundCallback( new FGFSGroundCallback(this) ); fdmex->SetGroundCallback( new FGFSGroundCallback(this) );
@ -363,6 +364,7 @@ FGJSBsim::FGJSBsim( double dt )
FGJSBsim::~FGJSBsim(void) FGJSBsim::~FGJSBsim(void)
{ {
delete fdmex; delete fdmex;
delete PropertyManager;
} }
/******************************************************************************/ /******************************************************************************/

View file

@ -71,6 +71,7 @@ class FGOutput;
class FGInitialCondition; class FGInitialCondition;
class FGLocation; class FGLocation;
class FGAccelerations; class FGAccelerations;
class FGPropertyManager;
} }
// Adding it here will cause a namespace clash in FlightGear -EMH- // Adding it here will cause a namespace clash in FlightGear -EMH-
@ -235,6 +236,7 @@ private:
JSBSim::FGGroundReactions* GroundReactions; JSBSim::FGGroundReactions* GroundReactions;
JSBSim::FGInertial* Inertial; JSBSim::FGInertial* Inertial;
JSBSim::FGAccelerations* Accelerations; JSBSim::FGAccelerations* Accelerations;
JSBSim::FGPropertyManager* PropertyManager;
int runcount; int runcount;
double trim_elev; double trim_elev;

View file

@ -0,0 +1,114 @@
/*
* FGLinearization.cpp
* Copyright (C) James Goppert 2011 <james.goppert@gmail.com>
*
* FGLinearization.h is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* FGLinearization.h is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "FGLinearization.h"
#include <ctime>
namespace JSBSim {
// TODO make FGLinearization have X,U,Y selectable by xml config file
FGLinearization::FGLinearization(FGFDMExec * fdm, int mode)
{
std::cout << "\nlinearization: " << std::endl;
std::clock_t time_start=clock(), time_linDone;
FGStateSpace ss(fdm);
ss.x.add(new FGStateSpace::Vt);
ss.x.add(new FGStateSpace::Alpha);
ss.x.add(new FGStateSpace::Theta);
ss.x.add(new FGStateSpace::Q);
// get propulsion pointer to determine type/ etc.
FGEngine * engine0 = fdm->GetPropulsion()->GetEngine(0);
FGThruster * thruster0 = engine0->GetThruster();
if (thruster0->GetType()==FGThruster::ttPropeller)
{
ss.x.add(new FGStateSpace::Rpm0);
// TODO add variable prop pitch property
// if (variablePropPitch) ss.x.add(new FGStateSpace::PropPitch);
int numEngines = fdm->GetPropulsion()->GetNumEngines();
if (numEngines>1) ss.x.add(new FGStateSpace::Rpm1);
if (numEngines>2) ss.x.add(new FGStateSpace::Rpm2);
if (numEngines>3) ss.x.add(new FGStateSpace::Rpm3);
if (numEngines>4) {
std::cerr << "more than 4 engines not currently handled" << std::endl;
}
}
ss.x.add(new FGStateSpace::Beta);
ss.x.add(new FGStateSpace::Phi);
ss.x.add(new FGStateSpace::P);
ss.x.add(new FGStateSpace::Psi);
ss.x.add(new FGStateSpace::R);
ss.x.add(new FGStateSpace::Latitude);
ss.x.add(new FGStateSpace::Longitude);
ss.x.add(new FGStateSpace::Alt);
ss.u.add(new FGStateSpace::ThrottleCmd);
ss.u.add(new FGStateSpace::DaCmd);
ss.u.add(new FGStateSpace::DeCmd);
ss.u.add(new FGStateSpace::DrCmd);
// state feedback
ss.y = ss.x;
std::vector< std::vector<double> > A,B,C,D;
std::vector<double> x0 = ss.x.get(), u0 = ss.u.get();
std::vector<double> y0 = x0; // state feedback
std::cout << ss << std::endl;
ss.linearize(x0,u0,y0,A,B,C,D);
int width=10;
std::cout.precision(3);
std::cout
<< std::fixed
<< std::right
<< "\nA=\n" << std::setw(width) << A
<< "\nB=\n" << std::setw(width) << B
<< "\nC=\n" << std::setw(width) << C
<< "\n* note: C should be identity, if not, indicates problem with model"
<< "\nD=\n" << std::setw(width) << D
<< std::endl;
// write scicoslab file
std::string aircraft = fdm->GetAircraft()->GetAircraftName();
std::ofstream scicos(std::string(aircraft+"_lin.sce").c_str());
scicos.precision(10);
width=20;
scicos
<< std::scientific
<< aircraft << ".x0=..\n" << std::setw(width) << x0 << ";\n"
<< aircraft << ".u0=..\n" << std::setw(width) << u0 << ";\n"
<< aircraft << ".sys = syslin('c',..\n"
<< std::setw(width) << A << ",..\n"
<< std::setw(width) << B << ",..\n"
<< std::setw(width) << C << ",..\n"
<< std::setw(width) << D << ");\n"
<< aircraft << ".tfm = ss2tf(" << aircraft << ".sys);\n"
<< std::endl;
time_linDone = std::clock();
std::cout << "\nlinearization computation time: " << (time_linDone - time_start)/double(CLOCKS_PER_SEC) << " s\n" << std::endl;
}
} // JSBSim
// vim:ts=4:sw=4

View file

@ -0,0 +1,47 @@
/*
* FGLinearization.h
* Copyright (C) James Goppert 2010 <james.goppert@gmail.com>
*
* FGLinearization.h is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* FGLinearization.h is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef FGLinearization_H_
#define FGLinearization_H_
#include "initialization/FGTrimmer.h"
#include "math/FGStateSpace.h"
#include <iomanip>
#include <fstream>
#include "models/FGAircraft.h"
#include "models/propulsion/FGEngine.h"
#include "models/propulsion/FGTurbine.h"
#include "models/propulsion/FGTurboProp.h"
#include "math/FGNelderMead.h"
#include <stdexcept>
#include <fstream>
#include <cstdlib>
namespace JSBSim {
class FGLinearization
{
public:
FGLinearization(FGFDMExec * fdmPtr, int mode);
};
} // JSBSim
#endif //FGLinearization_H_
// vim:ts=4:sw=4

View file

@ -3,16 +3,16 @@
* Copyright (C) James Goppert 2010 <james.goppert@gmail.com> * Copyright (C) James Goppert 2010 <james.goppert@gmail.com>
* *
* FGSimplexTrim.cpp is free software: you can redistribute it and/or modify it * 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 * Free Software Foundation, either version 2 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* FGSimplexTrim.cpp is distributed in the hope that it will be useful, but * FGSimplexTrim.cpp is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. * See the GNU Lesser General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU Lesser General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>. * with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@ -23,246 +23,95 @@ namespace JSBSim {
FGSimplexTrim::FGSimplexTrim(FGFDMExec * fdm, TrimMode mode) 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 // variables
fdm->Setdt(1./120); FGTrimmer::Constraints constraints;
FGTrimmer::Constraints constraints;
std::cout << "\n-----Performing Simplex Based Trim --------------\n" << std::endl; if (fdm->GetDebugLevel() > 0) {
std::cout << "\n-----Performing Simplex Based Trim --------------\n" << std::endl;
}
// defaults // defaults
constraints.velocity = fdm->GetAuxiliary()->GetVt(); std::string aircraftName = fdm->GetAircraft()->GetAircraftName();
constraints.altitude = fdm->GetPropagate()->GetAltitudeASL(); FGPropertyNode* node = fdm->GetPropertyManager()->GetNode();
std::string aircraft = fdm->GetAircraft()->GetAircraftName(); double rtol = node->GetDouble("trim/solver/rtol");
double rtol = fdm->GetPropertyManager()->GetDouble("trim/solver/rtol"); double abstol = node->GetDouble("trim/solver/abstol");
double abstol = fdm->GetPropertyManager()->GetDouble("trim/solver/abstol"); double speed = node->GetDouble("trim/solver/speed"); // must be > 1, 2 typical
double speed = fdm->GetPropertyManager()->GetDouble("trim/solver/speed"); // must be > 1, 2 typical double random = node->GetDouble("trim/solver/random");
double random = fdm->GetPropertyManager()->GetDouble("trim/solver/random"); int iterMax = node->GetDouble("trim/solver/iterMax");
int iterMax = fdm->GetPropertyManager()->GetDouble("trim/solver/iterMax"); bool showConvergence = node->GetBool("trim/solver/showConvergence");
bool showConvergeStatus = fdm->GetPropertyManager()->GetBool("trim/solver/showConvergeStatus"); bool pause = node->GetBool("trim/solver/pause");
bool pause = fdm->GetPropertyManager()->GetBool("trim/solver/pause"); bool showSimplex = node->GetBool("trim/solver/showSimplex");
bool showSimplex = fdm->GetPropertyManager()->GetBool("trim/solver/showSimplex"); bool variablePropPitch = node->GetBool("trim/solver/variablePropPitch");
bool variablePropPitch = fdm->GetPropertyManager()->GetBool("trim/solver/variablePropPitch");
//int debugLevel = fdm->GetPropertyManager()->GetInt("trim/solver/debugLevel");
std::string fileName = aircraft; // flight conditions
double phi = fdm->GetIC()->GetPhiRadIC();
double theta = fdm->GetIC()->GetThetaRadIC();
double psi = fdm->GetIC()->GetPsiRadIC();
double gd = fdm->GetInertial()->gravity();
// input constraints.velocity = fdm->GetIC()->GetVtrueFpsIC();
//std::cout << "input ( press enter to accept [default] )\n" << std::endl; 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;
// 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 constraints.stabAxisRoll = true; // FIXME, make this an option
// solver properties // initial solver state
// TODO make these options int n = 6;
//std::cout << "\nsolver properties: " << std::endl; std::vector<double> initialGuess(n), lowerBound(n), upperBound(n), initialStepSize(n);
//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 lowerBound[0] = node->GetDouble("trim/solver/throttleMin");
int n = 6; lowerBound[1] = node->GetDouble("trim/solver/elevatorMin");
std::vector<double> initialGuess(n), lowerBound(n), upperBound(n), initialStepSize(n); 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");
lowerBound[0] = fdm->GetPropertyManager()->GetDouble("trim/solver/throttleMin"); upperBound[0] = node->GetDouble("trim/solver/throttleMax");
lowerBound[1] = fdm->GetPropertyManager()->GetDouble("trim/solver/elevatorMin"); upperBound[1] = node->GetDouble("trim/solver/elevatorMax");
lowerBound[2] = fdm->GetPropertyManager()->GetDouble("trim/solver/alphaMin"); upperBound[2] = node->GetDouble("trim/solver/alphaMax");
lowerBound[3] = fdm->GetPropertyManager()->GetDouble("trim/solver/aileronMin"); upperBound[3] = node->GetDouble("trim/solver/aileronMax");
lowerBound[4] = fdm->GetPropertyManager()->GetDouble("trim/solver/rudderMin"); upperBound[4] = node->GetDouble("trim/solver/rudderMax");
lowerBound[5] = fdm->GetPropertyManager()->GetDouble("trim/solver/betaMin"); upperBound[5] = node->GetDouble("trim/solver/betaMax");
upperBound[0] = fdm->GetPropertyManager()->GetDouble("trim/solver/throttleMax"); initialStepSize[0] = node->GetDouble("trim/solver/throttleStep");
upperBound[1] = fdm->GetPropertyManager()->GetDouble("trim/solver/elevatorMax"); initialStepSize[1] = node->GetDouble("trim/solver/elevatorStep");
upperBound[2] = fdm->GetPropertyManager()->GetDouble("trim/solver/alphaMax"); initialStepSize[2] = node->GetDouble("trim/solver/alphaStep");
upperBound[3] = fdm->GetPropertyManager()->GetDouble("trim/solver/aileronMax"); initialStepSize[3] = node->GetDouble("trim/solver/aileronStep");
upperBound[4] = fdm->GetPropertyManager()->GetDouble("trim/solver/rudderMax"); initialStepSize[4] = node->GetDouble("trim/solver/rudderStep");
upperBound[5] = fdm->GetPropertyManager()->GetDouble("trim/solver/betaMax"); initialStepSize[5] = node->GetDouble("trim/solver/betaStep");
initialStepSize[0] = fdm->GetPropertyManager()->GetDouble("trim/solver/throttleStep"); initialGuess[0] = node->GetDouble("trim/solver/throttleGuess");
initialStepSize[1] = fdm->GetPropertyManager()->GetDouble("trim/solver/elevatorStep"); initialGuess[1] = node->GetDouble("trim/solver/elevatorGuess");
initialStepSize[2] = fdm->GetPropertyManager()->GetDouble("trim/solver/alphaStep"); initialGuess[2] = node->GetDouble("trim/solver/alphaGuess");
initialStepSize[3] = fdm->GetPropertyManager()->GetDouble("trim/solver/aileronStep"); initialGuess[3] = node->GetDouble("trim/solver/aileronGuess");
initialStepSize[4] = fdm->GetPropertyManager()->GetDouble("trim/solver/rudderStep"); initialGuess[4] = node->GetDouble("trim/solver/rudderGuess");
initialStepSize[5] = fdm->GetPropertyManager()->GetDouble("trim/solver/betaStep"); initialGuess[5] = node->GetDouble("trim/solver/betaGuess");
initialGuess[0] = fdm->GetPropertyManager()->GetDouble("trim/solver/throttleGuess"); // solve
initialGuess[1] = fdm->GetPropertyManager()->GetDouble("trim/solver/elevatorGuess"); FGTrimmer * trimmer = new FGTrimmer(fdm, &constraints);
initialGuess[2] = fdm->GetPropertyManager()->GetDouble("trim/solver/alphaGuess"); Callback callback(aircraftName, trimmer);
initialGuess[3] = fdm->GetPropertyManager()->GetDouble("trim/solver/aileronGuess"); FGNelderMead * solver = NULL;
initialGuess[4] = fdm->GetPropertyManager()->GetDouble("trim/solver/rudderGuess");
initialGuess[5] = fdm->GetPropertyManager()->GetDouble("trim/solver/betaGuess");
// solve solver = new FGNelderMead(trimmer,initialGuess,
FGTrimmer trimmer(fdm, &constraints); lowerBound, upperBound, initialStepSize,iterMax,rtol,
Callback callback(fileName,&trimmer); abstol,speed,random,showConvergence,showSimplex,pause,&callback);
FGNelderMead * solver = NULL; while(solver->status()==1) solver->update();
try time_trimDone = std::clock();
{
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 // output
try if (fdm->GetDebugLevel() > 0) {
{ trimmer->printSolution(std::cout,solver->getSolution());
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;
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;
} }
catch(std::runtime_error & e)
{
std::cout << "caught std::runtime error" << std::endl;
std::cout << "exception: " << e.what() << std::endl;
exit(1);
}
time_trimDone = std::clock();
std::cout << "\ntrim computation time: " << (time_trimDone - time_start)/double(CLOCKS_PER_SEC) << "s \n" << std::endl;
//std::cout << "\nsimulating flight to determine trim stability" << std::endl;
//std::cout << "\nt = 5 seconds" << std::endl;
//for (int i=0;i<5*120;i++) fdm->Run();
//trimmer.printState();
//std::cout << "\nt = 10 seconds" << std::endl;
//for (int i=0;i<5*120;i++) fdm->Run();
//trimmer.printState();
std::cout << "\nlinearization: " << std::endl;
FGStateSpace ss(fdm);
ss.x.add(new FGStateSpace::Vt);
ss.x.add(new FGStateSpace::Alpha);
ss.x.add(new FGStateSpace::Theta);
ss.x.add(new FGStateSpace::Q);
if (thruster0->GetType()==FGThruster::ttPropeller)
{
ss.x.add(new FGStateSpace::Rpm0);
if (variablePropPitch) ss.x.add(new FGStateSpace::PropPitch);
int numEngines = fdm->GetPropulsion()->GetNumEngines();
if (numEngines>1) ss.x.add(new FGStateSpace::Rpm1);
if (numEngines>2) ss.x.add(new FGStateSpace::Rpm2);
if (numEngines>3) ss.x.add(new FGStateSpace::Rpm3);
}
ss.x.add(new FGStateSpace::Beta);
ss.x.add(new FGStateSpace::Phi);
ss.x.add(new FGStateSpace::P);
ss.x.add(new FGStateSpace::Psi);
ss.x.add(new FGStateSpace::R);
ss.x.add(new FGStateSpace::Latitude);
ss.x.add(new FGStateSpace::Longitude);
ss.x.add(new FGStateSpace::Alt);
ss.u.add(new FGStateSpace::ThrottleCmd);
ss.u.add(new FGStateSpace::DaCmd);
ss.u.add(new FGStateSpace::DeCmd);
ss.u.add(new FGStateSpace::DrCmd);
// state feedback
ss.y = ss.x;
std::vector< std::vector<double> > A,B,C,D;
std::vector<double> x0 = ss.x.get(), u0 = ss.u.get();
std::vector<double> y0 = x0; // state feedback
std::cout << ss << std::endl;
ss.linearize(x0,u0,y0,A,B,C,D);
int width=10;
std::cout.precision(3);
std::cout
<< std::fixed
<< std::right
<< "\nA=\n" << std::setw(width) << A
<< "\nB=\n" << std::setw(width) << B
<< "\nC=\n" << std::setw(width) << C
<< "\nD=\n" << std::setw(width) << D
<< std::endl;
// write scicoslab file
std::ofstream scicos(std::string(aircraft+"_lin.sce").c_str());
scicos.precision(10);
width=20;
scicos
<< std::scientific
<< aircraft << ".x0=..\n" << std::setw(width) << x0 << ";\n"
<< aircraft << ".u0=..\n" << std::setw(width) << u0 << ";\n"
<< aircraft << ".sys = syslin('c',..\n"
<< std::setw(width) << A << ",..\n"
<< std::setw(width) << B << ",..\n"
<< std::setw(width) << C << ",..\n"
<< std::setw(width) << D << ");\n"
<< aircraft << ".tfm = ss2tf(" << aircraft << ".sys);\n"
<< std::endl;
time_linDone = std::clock();
std::cout << "\nlinearization computation time: " << (time_linDone - time_trimDone)/double(CLOCKS_PER_SEC) << " s\n" << std::endl;
if (solver) delete solver; if (solver) delete solver;
if (trimmer) delete trimmer;
} }
} // JSBSim } // JSBSim

View file

@ -3,16 +3,16 @@
* Copyright (C) James Goppert 2010 <james.goppert@gmail.com> * Copyright (C) James Goppert 2010 <james.goppert@gmail.com>
* *
* FGSimplexTrim.h is free software: you can redistribute it and/or modify it * 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 * Free Software Foundation, either version 2 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* FGSimplexTrim.h is distributed in the hope that it will be useful, but * FGSimplexTrim.h is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. * See the GNU Lesser General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU Lesser General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>. * with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@ -37,41 +37,41 @@ namespace JSBSim {
class FGSimplexTrim class FGSimplexTrim
{ {
public: public:
FGSimplexTrim(FGFDMExec * fdmPtr, TrimMode mode); FGSimplexTrim(FGFDMExec * fdmPtr, TrimMode mode);
private: private:
template <class varType> template <class varType>
void prompt(const std::string & str, varType & var) void prompt(const std::string & str, varType & var)
{ {
std::cout << str + " [" << std::setw(10) << var << "]\t: "; std::cout << str + " [" << std::setw(10) << var << "]\t: ";
if (std::cin.peek() != '\n') if (std::cin.peek() != '\n')
{ {
std::cin >> var; std::cin >> var;
std::cin.ignore(1000, '\n'); std::cin.ignore(1000, '\n');
} }
else std::cin.get(); else std::cin.get();
} }
class Callback : public JSBSim::FGNelderMead::Callback class Callback : public JSBSim::FGNelderMead::Callback
{ {
private: private:
std::ofstream _outputFile; std::ofstream _outputFile;
JSBSim::FGTrimmer * _trimmer; JSBSim::FGTrimmer * _trimmer;
public: public:
Callback(std::string fileName, JSBSim::FGTrimmer * trimmer) : Callback(std::string fileName, JSBSim::FGTrimmer * trimmer) :
_outputFile((fileName + std::string("_simplexTrim.log")).c_str()), _outputFile((fileName + std::string("_simplexTrim.log")).c_str()),
_trimmer(trimmer) { _trimmer(trimmer) {
} }
virtual ~Callback() { virtual ~Callback() {
_outputFile.close(); _outputFile.close();
} }
void eval(const std::vector<double> &v) void eval(const std::vector<double> &v)
{ {
_outputFile << _trimmer->eval(v) << std::endl;; _outputFile << _trimmer->eval(v) << std::endl;;
//std::cout << "v: "; //std::cout << "v: ";
//for (int i=0;i<v.size();i++) std::cout << v[i] << " "; //for (int i=0;i<v.size();i++) std::cout << v[i] << " ";
//std::cout << std::endl; //std::cout << std::endl;
} }
}; };
}; };
} // JSBSim } // JSBSim

View file

@ -3,16 +3,16 @@
* Copyright (C) James Goppert 2010 <james.goppert@gmail.com> * Copyright (C) James Goppert 2010 <james.goppert@gmail.com>
* *
* FGTrimmer.cpp is free software: you can redistribute it and/or modify it * 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 * Free Software Foundation, either version 2 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* FGTrimmer.cpp is distributed in the hope that it will be useful, but * FGTrimmer.cpp is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. * See the GNU Lesser General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU Lesser General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>. * with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@ -39,44 +39,56 @@ FGTrimmer::FGTrimmer(FGFDMExec * fdm, Constraints * constraints) :
{ {
} }
std::vector<double> FGTrimmer::constrain(const std::vector<double> & v) FGTrimmer::~FGTrimmer()
{
}
std::vector<double> FGTrimmer::constrain(const std::vector<double> & dv)
{ {
// unpack design vector // unpack design vector
double throttle = v[0]; double throttle = dv[0];
double elevator = v[1]; double elevator = dv[1];
double alpha = v[2]; double alpha = dv[2];
double aileron = v[3]; double aileron = dv[3];
double rudder = v[4]; double rudder = dv[4];
double beta = v[5]; double beta = dv[5];
// initialize constraints // initialize constraints
double vt = m_constraints->velocity; double vt = m_constraints->velocity;
double altitude = m_constraints->altitude; 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 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 // precomputation
double sGam = sin(m_constraints->gamma); double sGam = sin(gamma);
double sBeta = sin(beta); double sBeta = sin(beta);
double cBeta = cos(beta); double cBeta = cos(beta);
double tAlpha = tan(alpha); double tAlpha = tan(alpha);
double cAlpha = cos(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 // turn coordination constraint, lewis pg. 190
double gd = m_fdm->GetInertial()->gravity(); double gd = m_fdm->GetInertial()->gravity();
double gc = m_constraints->yawRate*vt/gd; double gc = m_constraints->yawRate*vt/gd;
a = 1 - gc*tAlpha*sBeta; double a = 1 - gc*tAlpha*sBeta;
b = sGam/cBeta; double b = sGam/cBeta;
double c = 1 + gc*gc*cBeta*cBeta; double c = 1 + gc*gc*cBeta*cBeta;
phi = atan((gc*cBeta*((a-b*b)+ phi = atan((gc*cBeta*((a-b*b)+
b*tAlpha*sqrt(c*(1-b*b)+gc*gc*sBeta*sBeta)))/ b*tAlpha*sqrt(c*(1-b*b)+gc*gc*sBeta*sBeta)))/
(cAlpha*(a*a-b*b*(1+c*tAlpha*tAlpha)))); (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 // turn rates
if (m_constraints->rollRate != 0.0) // rolling if (m_constraints->rollRate != 0.0) // rolling
{ {
@ -104,28 +116,13 @@ std::vector<double> FGTrimmer::constrain(const std::vector<double> & v)
r = 0.0; 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 // 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 // set controls
m_fdm->GetFCS()->SetDeCmd(elevator); m_fdm->GetFCS()->SetDeCmd(elevator);
@ -140,37 +137,46 @@ std::vector<double> FGTrimmer::constrain(const std::vector<double> & v)
for (unsigned int i=0; i<m_fdm->GetPropulsion()->GetNumEngines(); i++) for (unsigned int i=0; i<m_fdm->GetPropulsion()->GetNumEngines(); i++)
{ {
//FGEngine * engine = m_fdm->GetPropulsion()->GetEngine(i);
m_fdm->GetPropulsion()->GetEngine(i)->InitRunning();
m_fdm->GetFCS()->SetThrottleCmd(i,throttle); m_fdm->GetFCS()->SetThrottleCmd(i,throttle);
m_fdm->GetFCS()->SetThrottlePos(i,throttle); m_fdm->GetFCS()->SetThrottlePos(i,throttle);
} }
// initialize
m_fdm->Initialize(m_fdm->GetIC());
for (unsigned int i=0; i<m_fdm->GetPropulsion()->GetNumEngines(); i++) {
m_fdm->GetPropulsion()->GetEngine(i)->InitRunning();
}
// wait for steady-state // wait for stable state
//double thrust0 = m_fdm->GetPropulsion()->GetEngine(0)->GetThruster()->GetThrust(); double cost = compute_cost();
//double dThrustMag0 = 0; for(int i=0;;i++) {
//for(int i=0;;i++) { m_fdm->GetPropulsion()->GetSteadyState();
//m_fdm->RunIC(); m_fdm->SetTrimStatus(true);
//m_fdm->Run(); m_fdm->DisableOutput();
//double thrust = m_fdm->GetPropulsion()->GetEngine(0)->GetThruster()->GetThrust(); m_fdm->SuspendIntegration();
//double dThrustMag = std::abs(thrust - thrust0); m_fdm->Run();
//double d2Thrust = dThrustMag - dThrustMag0; m_fdm->SetTrimStatus(false);
//thrust0= thrust; m_fdm->EnableOutput();
//dThrustMag0 = dThrustMag; m_fdm->ResumeIntegration();
//if (d2Thrust < std::numeric_limits<double>::epsilon() ) {
//// thrust difference has converged to minimum double costNew = compute_cost();
//// if d2Thrust > 0 clearly, more interations won't help double dcost = fabs(costNew - cost);
//// so not using abs(d2Thrust) if (dcost < std::numeric_limits<double>::epsilon()) {
//break; if(m_fdm->GetDebugLevel() > 1) {
//} else if (i> 1000) { std::cout << "cost convergd, i: " << i << std::endl;
//std::cout << "thrust failed to converge" << std::endl; }
//std::cout << "difference: " << dThrustMag << std::endl; break;
//throw std::runtime_error("thrust failed to converge"); }
//break; if (i > 1000) {
//} if(m_fdm->GetDebugLevel() > 1) {
//} std::cout << "cost failed to converge, dcost: "
//m_fdm->RunIC(); << std::scientific
<< dcost << std::endl;
}
break;
}
cost = costNew;
}
std::vector<double> data; std::vector<double> data;
data.push_back(phi); data.push_back(phi);
@ -182,7 +188,7 @@ void FGTrimmer::printSolution(std::ostream & stream, const std::vector<double> &
{ {
eval(v); eval(v);
double dt = m_fdm->GetDeltaT(); //double dt = m_fdm->GetDeltaT();
double thrust = m_fdm->GetPropulsion()->GetEngine(0)->GetThruster()->GetThrust(); double thrust = m_fdm->GetPropulsion()->GetEngine(0)->GetThruster()->GetThrust();
double elevator = m_fdm->GetFCS()->GetDePos(ofNorm); double elevator = m_fdm->GetFCS()->GetDePos(ofNorm);
double aileron = m_fdm->GetFCS()->GetDaLPos(ofNorm); double aileron = m_fdm->GetFCS()->GetDaLPos(ofNorm);
@ -192,23 +198,15 @@ void FGTrimmer::printSolution(std::ostream & stream, const std::vector<double> &
double lon = m_fdm->GetPropagate()->GetLongitudeDeg(); double lon = m_fdm->GetPropagate()->GetLongitudeDeg();
double vt = m_fdm->GetAuxiliary()->GetVt(); double vt = m_fdm->GetAuxiliary()->GetVt();
// run a step to compute derivatives //double dthrust = (m_fdm->GetPropulsion()->GetEngine(0)->
//for (int i=0;i<10000;i++) { //GetThruster()->GetThrust()-thrust)/dt;
//while (old - m_fdm->GetPropulsion()->GetEngine(i)->CalcFuelNeed() < 1e-5) { //double delevator = (m_fdm->GetFCS()->GetDePos(ofNorm)-elevator)/dt;
//m_fdm->RunIC(); //double daileron = (m_fdm->GetFCS()->GetDaLPos(ofNorm)-aileron)/dt;
//m_fdm->Run(); //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 dthrust = (m_fdm->GetPropulsion()->GetEngine(0)-> //double dvt = (m_fdm->GetAuxiliary()->GetVt()-vt)/dt;
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 // reinitialize with correct state
eval(v); eval(v);
@ -247,29 +245,29 @@ void FGTrimmer::printSolution(std::ostream & stream, const std::vector<double> &
<< "\n\naircraft d/dt state" << "\n\naircraft d/dt state"
<< std::scientific << 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 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 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 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 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 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 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) << "\n\td/dt r, rad/s^2\t\t:\t" << m_fdm->GetAccelerations()->GetPQRdot(3)
// d/dt actuator states // d/dt actuator states
<< "\n\nd/dt actuator state" //<< "\n\nd/dt actuator state"
<< "\n\td/dt throttle, %/s\t:\t" << dthrottle //<< "\n\td/dt throttle, %/s\t:\t" << dthrottle
<< "\n\td/dt elevator, %/s\t:\t" << delevator //<< "\n\td/dt elevator, %/s\t:\t" << delevator
<< "\n\td/dt aileron, %/s\t:\t" << daileron //<< "\n\td/dt aileron, %/s\t:\t" << daileron
<< "\n\td/dt rudder, %/s\t:\t" << drudder //<< "\n\td/dt rudder, %/s\t:\t" << drudder
// nav state // nav state
<< "\n\nd/dt nav state" << "\n\nd/dt nav state"
<< "\n\td/dt altitude, ft/s\t:\t" << m_fdm->GetPropagate()->Gethdot() << "\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 psi, deg/s\t\t:\t" << m_fdm->GetAuxiliary()->GetEulerRates(3)
<< "\n\td/dt lat, deg/s\t\t:\t" << dlat //<< "\n\td/dt lat, deg/s\t\t:\t" << dlat
<< "\n\td/dt lon, deg/s\t\t:\t" << dlon //<< "\n\td/dt lon, deg/s\t\t:\t" << dlon
<< std::fixed << std::fixed
<< "\n\npropulsion system state" << "\n\npropulsion system state"
@ -343,39 +341,17 @@ void FGTrimmer::printState(std::ostream & stream)
} }
double FGTrimmer::eval(const std::vector<double> & v) double FGTrimmer::compute_cost()
{ {
double cost = 0; double dvt = (m_fdm->GetPropagate()->GetUVW(1)*m_fdm->GetAccelerations()->GetUVWdot(1) +
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) +
m_fdm->GetPropagate()->GetUVW(2)*m_fdm->GetAccelerations()->GetUVWdot(2) + m_fdm->GetPropagate()->GetUVW(2)*m_fdm->GetAccelerations()->GetUVWdot(2) +
m_fdm->GetPropagate()->GetUVW(3)*m_fdm->GetAccelerations()->GetUVWdot(3))/ m_fdm->GetPropagate()->GetUVW(3)*m_fdm->GetAccelerations()->GetUVWdot(3))/
m_fdm->GetAuxiliary()->GetVt(); // from lewis, vtrue dot m_fdm->GetAuxiliary()->GetVt(); // from lewis, vtrue dot
dalpha = m_fdm->GetAuxiliary()->Getadot(); double dalpha = m_fdm->GetAuxiliary()->Getadot();
dbeta = m_fdm->GetAuxiliary()->Getbdot(); double dbeta = m_fdm->GetAuxiliary()->Getbdot();
dp = m_fdm->GetAccelerations()->GetPQRdot(1); double dp = m_fdm->GetAccelerations()->GetPQRdot(1);
dq = m_fdm->GetAccelerations()->GetPQRdot(2); double dq = m_fdm->GetAccelerations()->GetPQRdot(2);
dr = m_fdm->GetAccelerations()->GetPQRdot(3); double dr = m_fdm->GetAccelerations()->GetPQRdot(3);
if(m_fdm->GetDebugLevel() > 1) { if(m_fdm->GetDebugLevel() > 1) {
std::cout std::cout
@ -388,33 +364,15 @@ double FGTrimmer::eval(const std::vector<double> & v)
<< std::endl; << std::endl;
} }
cost = dvt*dvt + return dvt*dvt +
100.0*(dalpha*dalpha + dbeta*dbeta) + 100.0*(dalpha*dalpha + dbeta*dbeta) +
10.0*(dp*dp + dq*dq + dr*dr); 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;
} }
} double FGTrimmer::eval(const std::vector<double> & v)
{
return cost; constrain(v);
return compute_cost();
} }
} // JSBSim } // JSBSim

View file

@ -3,16 +3,16 @@
* Copyright (C) James Goppert 2010 <james.goppert@gmail.com> * Copyright (C) James Goppert 2010 <james.goppert@gmail.com>
* *
* FGTrimmer.h is free software: you can redistribute it and/or modify it * 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 * Free Software Foundation, either version 2 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* FGTrimmer.h is distributed in the hope that it will be useful, but * FGTrimmer.h is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. * See the GNU Lesser General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU Lesser General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>. * with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@ -42,9 +42,11 @@ public:
bool coordinatedTurn, stabAxisRoll; bool coordinatedTurn, stabAxisRoll;
}; };
FGTrimmer(FGFDMExec * fdm, Constraints * constraints); FGTrimmer(FGFDMExec * fdm, Constraints * constraints);
std::vector<double> constrain(const vector<double> & v); ~FGTrimmer();
std::vector<double> constrain(const vector<double> & v);
void printSolution(std::ostream & stream, const vector<double> & v); void printSolution(std::ostream & stream, const vector<double> & v);
void printState(std::ostream & stream); void printState(std::ostream & stream);
double compute_cost();
double eval(const vector<double> & v); double eval(const vector<double> & v);
static void limit(double min, double max, double &val) static void limit(double min, double max, double &val)
{ {

View file

@ -38,7 +38,6 @@ SENTRY
INCLUDES INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGJSBBase.h"
#include "simgear/structure/SGReferenced.hxx" #include "simgear/structure/SGReferenced.hxx"
#include "simgear/structure/SGSharedPtr.hxx" #include "simgear/structure/SGSharedPtr.hxx"
@ -46,7 +45,7 @@ INCLUDES
DEFINITIONS 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 { namespace JSBSim {
@ -63,14 +62,14 @@ CLASS DOCUMENTATION
ball formed earth with an adjustable terrain elevation. ball formed earth with an adjustable terrain elevation.
@author Mathias Froehlich @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 DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
class FGGroundCallback : public FGJSBBase, public SGReferenced class FGGroundCallback : public SGReferenced
{ {
public: public:

View file

@ -46,7 +46,7 @@ INCLUDES
namespace JSBSim { 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; static const char *IdHdr = ID_OUTPUTTYPE;
using namespace std; using namespace std;
@ -136,7 +136,7 @@ bool FGOutputType::Load(Element* element)
while (property_element) { while (property_element) {
string caption=""; string caption="";
string property_str = property_element->GetDataLine(); string property_str = property_element->GetDataLine();
FGPropertyManager* node = PropertyManager->GetNode(property_str); FGPropertyNode* node = PropertyManager->GetNode(property_str);
if (!node) { if (!node) {
cerr << fgred << highint << endl << " No property by the name " cerr << fgred << highint << endl << " No property by the name "
<< property_str << " has been defined. This property will " << endl << property_str << " has been defined. This property will " << endl

View file

@ -44,7 +44,7 @@ INCLUDES
DEFINITIONS 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 FORWARD DECLARATIONS
@ -53,7 +53,6 @@ FORWARD DECLARATIONS
namespace JSBSim { namespace JSBSim {
class FGFDMExec; class FGFDMExec;
class FGPropertyManager;
class Element; class Element;
class FGAerodynamics; class FGAerodynamics;
class FGAuxiliary; class FGAuxiliary;
@ -122,7 +121,7 @@ public:
/** Set the list of properties that should be output for this output instance. /** Set the list of properties that should be output for this output instance.
@param outputProperties list of properties that should be output @param outputProperties list of properties that should be output
*/ */
void SetOutputProperties(std::vector<FGPropertyManager *> & outputProperties) void SetOutputProperties(std::vector<FGPropertyNode_ptr> & outputProperties)
{ {
OutputProperties = outputProperties; OutputProperties = outputProperties;
} }
@ -197,7 +196,7 @@ public:
protected: protected:
int OutputIdx; int OutputIdx;
int SubSystems; int SubSystems;
std::vector <FGPropertyManager*> OutputProperties; std::vector <FGPropertyNode_ptr> OutputProperties;
std::vector <std::string> OutputCaptions; std::vector <std::string> OutputCaptions;
bool enabled; bool enabled;

View file

@ -48,8 +48,6 @@ COMMENTS, REFERENCES, and NOTES [use "class documentation" below for API docs]
namespace JSBSim { namespace JSBSim {
std::vector<SGPropertyNode_ptr> FGPropertyManager::tied_properties;
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGPropertyManager::Unbind(void) void FGPropertyManager::Unbind(void)
@ -81,32 +79,32 @@ string FGPropertyManager::mkPropertyName(string name, bool lowercase) {
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGPropertyManager* FGPropertyNode*
FGPropertyManager::GetNode (const string &path, bool create) FGPropertyNode::GetNode (const string &path, bool create)
{ {
SGPropertyNode* node = getNode(path.c_str(), create); SGPropertyNode* node = getNode(path.c_str(), create);
if (node == 0) { if (node == 0) {
cerr << "FGPropertyManager::GetNode() No node found for " << path << endl; cerr << "FGPropertyManager::GetNode() No node found for " << path << endl;
} }
return (FGPropertyManager*)node; return (FGPropertyNode*)node;
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGPropertyManager* FGPropertyNode*
FGPropertyManager::GetNode (const string &relpath, int index, bool create) FGPropertyNode::GetNode (const string &relpath, int index, bool create)
{ {
SGPropertyNode* node = getNode(relpath.c_str(), index, create); SGPropertyNode* node = getNode(relpath.c_str(), index, create);
if (node == 0) { if (node == 0) {
cerr << "FGPropertyManager::GetNode() No node found for " << relpath cerr << "FGPropertyManager::GetNode() No node found for " << relpath
<< "[" << index << "]" << endl; << "[" << 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); const SGPropertyNode* node = getNode(path.c_str(), false);
return (node != 0); 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() ); return string( getName() );
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
string FGPropertyManager::GetPrintableName( void ) const string FGPropertyNode::GetPrintableName( void ) const
{ {
string temp_string(getName()); string temp_string(getName());
size_t initial_location=0; size_t initial_location=0;
@ -142,7 +140,7 @@ string FGPropertyManager::GetPrintableName( void ) const
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
string FGPropertyManager::GetFullyQualifiedName(void) const string FGPropertyNode::GetFullyQualifiedName(void) const
{ {
vector<string> stack; vector<string> stack;
stack.push_back( getDisplayName(true) ); 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(); string temp_string = GetFullyQualifiedName();
size_t len = path.length(); 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); 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); 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); 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); 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); 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())); 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); 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); 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); 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); 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); 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()); 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()); SGPropertyNode * node = getNode(name.c_str());
if (node == 0) 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()); SGPropertyNode * node = getNode(name.c_str());
if (node == 0) 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()); SGPropertyNode * node = getNode(name.c_str());
if (node == 0) if (node == 0)
@ -307,7 +305,7 @@ void FGPropertyManager::SetWritable (const string &name, bool state )
void FGPropertyManager::Untie (const string &name) void FGPropertyManager::Untie (const string &name)
{ {
SGPropertyNode* property = getNode(name.c_str()); SGPropertyNode* property = root->getNode(name.c_str());
if (!property) { if (!property) {
cerr << "Attempt to untie a non-existant property." << name << endl; cerr << "Attempt to untie a non-existant property." << name << endl;
return; return;
@ -331,7 +329,7 @@ void FGPropertyManager::Untie (const string &name)
void FGPropertyManager::Tie (const string &name, bool *pointer, bool useDefault) 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) { if (!property) {
cerr << "Could not get or create property " << name << endl; cerr << "Could not get or create property " << name << endl;
return; return;
@ -350,7 +348,7 @@ void FGPropertyManager::Tie (const string &name, bool *pointer, bool useDefault)
void FGPropertyManager::Tie (const string &name, int *pointer, void FGPropertyManager::Tie (const string &name, int *pointer,
bool useDefault ) bool useDefault )
{ {
SGPropertyNode* property = getNode(name.c_str(), true); SGPropertyNode* property = root->getNode(name.c_str(), true);
if (!property) { if (!property) {
cerr << "Could not get or create property " << name << endl; cerr << "Could not get or create property " << name << endl;
return; return;
@ -369,7 +367,7 @@ void FGPropertyManager::Tie (const string &name, int *pointer,
void FGPropertyManager::Tie (const string &name, long *pointer, void FGPropertyManager::Tie (const string &name, long *pointer,
bool useDefault ) bool useDefault )
{ {
SGPropertyNode* property = getNode(name.c_str(), true); SGPropertyNode* property = root->getNode(name.c_str(), true);
if (!property) { if (!property) {
cerr << "Could not get or create property " << name << endl; cerr << "Could not get or create property " << name << endl;
return; return;
@ -388,7 +386,7 @@ void FGPropertyManager::Tie (const string &name, long *pointer,
void FGPropertyManager::Tie (const string &name, float *pointer, void FGPropertyManager::Tie (const string &name, float *pointer,
bool useDefault ) bool useDefault )
{ {
SGPropertyNode* property = getNode(name.c_str(), true); SGPropertyNode* property = root->getNode(name.c_str(), true);
if (!property) { if (!property) {
cerr << "Could not get or create property " << name << endl; cerr << "Could not get or create property " << name << endl;
return; return;
@ -406,7 +404,7 @@ void FGPropertyManager::Tie (const string &name, float *pointer,
void FGPropertyManager::Tie (const string &name, double *pointer, bool useDefault) 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) { if (!property) {
cerr << "Could not get or create property " << name << endl; cerr << "Could not get or create property " << name << endl;
return; return;

View file

@ -53,7 +53,7 @@ INCLUDES
DEFINITIONS 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 FORWARD DECLARATIONS
@ -73,24 +73,11 @@ CLASS DOCUMENTATION
CLASS DECLARATION CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
class FGPropertyManager : public SGPropertyNode class FGPropertyNode : public SGPropertyNode
{ {
private:
static std::vector<SGPropertyNode_ptr> tied_properties;
public: public:
/// Constructor
FGPropertyManager(void) {}
/// Destructor /// Destructor
virtual ~FGPropertyManager(void) {} virtual ~FGPropertyNode(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);
/** /**
* Get a property node. * Get a property node.
@ -99,10 +86,10 @@ class FGPropertyManager : public SGPropertyNode
* @param create true to create the node if it doesn't exist. * @param create true to create the node if it doesn't exist.
* @return The node, or 0 if none exists and none was created. * @return The node, or 0 if none exists and none was created.
*/ */
FGPropertyManager* FGPropertyNode*
GetNode (const std::string &path, bool create = false); GetNode (const std::string &path, bool create = false);
FGPropertyManager* FGPropertyNode*
GetNode (const std::string &relpath, int index, bool create = false); 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). * @param state The state of the write attribute (defaults to true).
*/ */
void SetWritable (const std::string &name, bool state = true); void SetWritable (const std::string &name, bool state = true);
};
typedef SGSharedPtr<FGPropertyNode> FGPropertyNode_ptr;
typedef SGSharedPtr<const FGPropertyNode> FGConstPropertyNode_ptr;
class FGPropertyManager
{
public:
/// Default constructor
FGPropertyManager(void) { root = new FGPropertyNode; }
/// Constructor
FGPropertyManager(FGPropertyNode* _root) : root(_root) {};
/// Destructor
virtual ~FGPropertyManager(void) { Unbind(); }
FGPropertyNode* GetNode(void) const { return root; }
FGPropertyNode* GetNode(const std::string &path, bool create = false)
{ return root->GetNode(path, create); }
FGPropertyNode* GetNode(const std::string &relpath, int index, bool create = false)
{ return root->GetNode(relpath, index, create); }
bool HasNode(const std::string& path) const { return root->HasNode(path); }
/** Property-ify a name
* replaces spaces with '-' and, optionally, makes name all lower case
* @param name string to change
* @param lowercase true to change all upper case chars to lower
* NOTE: this function changes its argument and thus relies
* on pass by value
*/
std::string mkPropertyName(std::string name, bool lowercase);
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
// Convenience functions for tying properties, with logging. // Convenience functions for tying properties, with logging.
@ -531,7 +549,7 @@ class FGPropertyManager : public SGPropertyNode
template <class V> inline void template <class V> inline void
Tie (const std::string &name, V (*getter)(), void (*setter)(V) = 0, bool useDefault = true) 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) { if (!property) {
std::cerr << "Could not get or create property " << name << std::endl; std::cerr << "Could not get or create property " << name << std::endl;
return; return;
@ -540,6 +558,8 @@ class FGPropertyManager : public SGPropertyNode
if (!property->tie(SGRawValueFunctions<V>(getter, setter), useDefault)) if (!property->tie(SGRawValueFunctions<V>(getter, setter), useDefault))
std::cerr << "Failed to tie property " << name << " to functions" << std::endl; std::cerr << "Failed to tie property " << name << " to functions" << std::endl;
else { else {
if (setter == 0) property->setAttribute(SGPropertyNode::WRITE, false);
if (getter == 0) property->setAttribute(SGPropertyNode::READ, false);
tied_properties.push_back(property); tied_properties.push_back(property);
if (FGJSBBase::debug_lvl & 0x20) std::cout << name << std::endl; if (FGJSBBase::debug_lvl & 0x20) std::cout << name << std::endl;
} }
@ -567,7 +587,7 @@ class FGPropertyManager : public SGPropertyNode
template <class V> inline void Tie (const std::string &name, int index, V (*getter)(int), template <class V> inline void Tie (const std::string &name, int index, V (*getter)(int),
void (*setter)(int, V) = 0, bool useDefault = true) 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) { if (!property) {
std::cerr << "Could not get or create property " << name << std::endl; std::cerr << "Could not get or create property " << name << std::endl;
return; return;
@ -576,6 +596,8 @@ class FGPropertyManager : public SGPropertyNode
if (!property->tie(SGRawValueFunctionsIndexed<V>(index, getter, setter), useDefault)) if (!property->tie(SGRawValueFunctionsIndexed<V>(index, getter, setter), useDefault))
std::cerr << "Failed to tie property " << name << " to indexed functions" << std::endl; std::cerr << "Failed to tie property " << name << " to indexed functions" << std::endl;
else { else {
if (setter == 0) property->setAttribute(SGPropertyNode::WRITE, false);
if (getter == 0) property->setAttribute(SGPropertyNode::READ, false);
tied_properties.push_back(property); tied_properties.push_back(property);
if (FGJSBBase::debug_lvl & 0x20) std::cout << name << std::endl; 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, Tie (const std::string &name, T * obj, V (T::*getter)() const,
void (T::*setter)(V) = 0, bool useDefault = true) 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) { if (!property) {
std::cerr << "Could not get or create property " << name << std::endl; std::cerr << "Could not get or create property " << name << std::endl;
return; return;
@ -614,6 +636,8 @@ class FGPropertyManager : public SGPropertyNode
if (!property->tie(SGRawValueMethods<T,V>(*obj, getter, setter), useDefault)) if (!property->tie(SGRawValueMethods<T,V>(*obj, getter, setter), useDefault))
std::cerr << "Failed to tie property " << name << " to object methods" << std::endl; std::cerr << "Failed to tie property " << name << " to object methods" << std::endl;
else { else {
if (setter == 0) property->setAttribute(SGPropertyNode::WRITE, false);
if (getter == 0) property->setAttribute(SGPropertyNode::READ, false);
tied_properties.push_back(property); tied_properties.push_back(property);
if (FGJSBBase::debug_lvl & 0x20) std::cout << name << std::endl; 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, Tie (const std::string &name, T * obj, int index, V (T::*getter)(int) const,
void (T::*setter)(int, V) = 0, bool useDefault = true) 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) { if (!property) {
std::cerr << "Could not get or create property " << name << std::endl; std::cerr << "Could not get or create property " << name << std::endl;
return; return;
@ -651,10 +675,16 @@ class FGPropertyManager : public SGPropertyNode
if (!property->tie(SGRawValueMethodsIndexed<T,V>(*obj, index, getter, setter), useDefault)) if (!property->tie(SGRawValueMethodsIndexed<T,V>(*obj, index, getter, setter), useDefault))
std::cerr << "Failed to tie property " << name << " to indexed object methods" << std::endl; std::cerr << "Failed to tie property " << name << " to indexed object methods" << std::endl;
else { else {
if (setter == 0) property->setAttribute(SGPropertyNode::WRITE, false);
if (getter == 0) property->setAttribute(SGPropertyNode::READ, false);
tied_properties.push_back(property); tied_properties.push_back(property);
if (FGJSBBase::debug_lvl & 0x20) std::cout << name << std::endl; if (FGJSBBase::debug_lvl & 0x20) std::cout << name << std::endl;
} }
} }
private:
std::vector<SGPropertyNode_ptr> tied_properties;
FGPropertyNode_ptr root;
}; };
} }
#endif // FGPROPERTYMANAGER_H #endif // FGPROPERTYMANAGER_H

View file

@ -55,7 +55,7 @@ using namespace std;
namespace JSBSim { 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; 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"); set_element = event_element->FindElement("set");
while (set_element) { while (set_element) {
prop_name = set_element->GetAttributeValue("name"); prop_name = set_element->GetAttributeValue("name");
if (PropertyManager->HasNode(prop_name)) {
newEvent->SetParam.push_back( PropertyManager->GetNode(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 //Todo - should probably do some safety checking here to make sure one or the other
//of value or function is specified. //of value or function is specified.
if (!set_element->GetAttributeValue("value").empty()) { if (!set_element->GetAttributeValue("value").empty()) {
@ -374,104 +381,114 @@ bool FGScript::RunScript(void)
// Iterate over all events. // Iterate over all events.
for (unsigned int ev_ctr=0; ev_ctr < Events.size(); ev_ctr++) { 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 // 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 and should cause the event to execute. If the conditions evaluate
// to true, then the event is triggered. If the event is not persistent, // 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, // then this trigger will remain set true. If the event is persistent,
// the trigger will reset to false when the condition evaluates to false. // the trigger will reset to false when the condition evaluates to false.
if (Events[ev_ctr].Condition->Evaluate()) { if (thisEvent.Condition->Evaluate()) {
if (!Events[ev_ctr].Triggered) { if (!thisEvent.Triggered) {
// The conditions are true, do the setting of the desired Event parameters // The conditions are true, do the setting of the desired Event parameters
for (i=0; i<Events[ev_ctr].SetValue.size(); i++) { for (i=0; i<thisEvent.SetValue.size(); i++) {
Events[ev_ctr].OriginalValue[i] = Events[ev_ctr].SetParam[i]->getDoubleValue(); if (thisEvent.SetParam[i] == 0L) { // Late bind property if necessary
if (Events[ev_ctr].Functions[i] != 0) { // Parameter should be set to a function value if (PropertyManager->HasNode(thisEvent.SetParamName[i])) {
thisEvent.SetParam[i] = PropertyManager->GetNode(thisEvent.SetParamName[i]);
} else {
throw("No property, \""+thisEvent.SetParamName[i]+"\" is defined.");
}
}
thisEvent.OriginalValue[i] = thisEvent.SetParam[i]->getDoubleValue();
if (thisEvent.Functions[i] != 0) { // Parameter should be set to a function value
try { try {
Events[ev_ctr].SetValue[i] = Events[ev_ctr].Functions[i]->GetValue(); thisEvent.SetValue[i] = thisEvent.Functions[i]->GetValue();
} catch (string msg) { } catch (string msg) {
std::cerr << std::endl << "A problem occurred in the execution of the script. " << msg << endl; std::cerr << std::endl << "A problem occurred in the execution of the script. " << msg << endl;
throw; throw;
} }
} }
switch (Events[ev_ctr].Type[i]) { switch (thisEvent.Type[i]) {
case FG_VALUE: case FG_VALUE:
case FG_BOOL: case FG_BOOL:
Events[ev_ctr].newValue[i] = Events[ev_ctr].SetValue[i]; thisEvent.newValue[i] = thisEvent.SetValue[i];
break; break;
case FG_DELTA: 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; break;
default: default:
cerr << "Invalid Type specified" << endl; cerr << "Invalid Type specified" << endl;
break; break;
} }
Events[ev_ctr].StartTime = currentTime + Events[ev_ctr].Delay; thisEvent.StartTime = currentTime + thisEvent.Delay;
Events[ev_ctr].ValueSpan[i] = Events[ev_ctr].newValue[i] - Events[ev_ctr].OriginalValue[i]; thisEvent.ValueSpan[i] = thisEvent.newValue[i] - thisEvent.OriginalValue[i];
Events[ev_ctr].Transiting[i] = true; thisEvent.Transiting[i] = true;
} }
} }
Events[ev_ctr].Triggered = true; thisEvent.Triggered = true;
} else if (Events[ev_ctr].Persistent) { // If the event is persistent, reset the trigger. } else if (thisEvent.Persistent) { // If the event is persistent, reset the trigger.
Events[ev_ctr].Triggered = false; // Reset the trigger for persistent events thisEvent.Triggered = false; // Reset the trigger for persistent events
Events[ev_ctr].Notified = false; // Also reset the notification flag thisEvent.Notified = false; // Also reset the notification flag
} else if (Events[ev_ctr].Continuous) { // If the event is continuous, reset the trigger. } else if (thisEvent.Continuous) { // If the event is continuous, reset the trigger.
Events[ev_ctr].Triggered = false; // Reset the trigger for persistent events thisEvent.Triggered = false; // Reset the trigger for persistent events
Events[ev_ctr].Notified = false; // Also reset the notification flag thisEvent.Notified = false; // Also reset the notification flag
} }
if ((currentTime >= Events[ev_ctr].StartTime) && Events[ev_ctr].Triggered) { if ((currentTime >= thisEvent.StartTime) && thisEvent.Triggered) {
for (i=0; i<Events[ev_ctr].SetValue.size(); i++) { for (i=0; i<thisEvent.SetValue.size(); i++) {
if (Events[ev_ctr].Transiting[i]) { if (thisEvent.Transiting[i]) {
Events[ev_ctr].TimeSpan = currentTime - Events[ev_ctr].StartTime; thisEvent.TimeSpan = currentTime - thisEvent.StartTime;
switch (Events[ev_ctr].Action[i]) { switch (thisEvent.Action[i]) {
case FG_RAMP: case FG_RAMP:
if (Events[ev_ctr].TimeSpan <= Events[ev_ctr].TC[i]) { if (thisEvent.TimeSpan <= thisEvent.TC[i]) {
newSetValue = Events[ev_ctr].TimeSpan/Events[ev_ctr].TC[i] * Events[ev_ctr].ValueSpan[i] + Events[ev_ctr].OriginalValue[i]; newSetValue = thisEvent.TimeSpan/thisEvent.TC[i] * thisEvent.ValueSpan[i] + thisEvent.OriginalValue[i];
} else { } else {
newSetValue = Events[ev_ctr].newValue[i]; newSetValue = thisEvent.newValue[i];
if (Events[ev_ctr].Continuous != true) Events[ev_ctr].Transiting[i] = false; if (thisEvent.Continuous != true) thisEvent.Transiting[i] = false;
} }
break; break;
case FG_STEP: case FG_STEP:
newSetValue = Events[ev_ctr].newValue[i]; newSetValue = thisEvent.newValue[i];
// If this is not a continuous event, reset the transiting flag. // If this is not a continuous event, reset the transiting flag.
// Otherwise, it is known that the event is a continuous event. // Otherwise, it is known that the event is a continuous event.
// Furthermore, if the event is to be determined by a function, // Furthermore, if the event is to be determined by a function,
// then the function will be continuously calculated. // then the function will be continuously calculated.
if (Events[ev_ctr].Continuous != true) if (thisEvent.Continuous != true)
Events[ev_ctr].Transiting[i] = false; thisEvent.Transiting[i] = false;
else if (Events[ev_ctr].Functions[i] != 0) else if (thisEvent.Functions[i] != 0)
newSetValue = Events[ev_ctr].Functions[i]->GetValue(); newSetValue = thisEvent.Functions[i]->GetValue();
break; break;
case FG_EXP: 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; break;
default: default:
cerr << "Invalid Action specified" << endl; cerr << "Invalid Action specified" << endl;
break; break;
} }
Events[ev_ctr].SetParam[i]->setDoubleValue(newSetValue); thisEvent.SetParam[i]->setDoubleValue(newSetValue);
} }
} }
// Print notification values after setting them // Print notification values after setting them
if (Events[ev_ctr].Notify && !Events[ev_ctr].Notified) { if (thisEvent.Notify && !thisEvent.Notified) {
cout << endl << " Event " << event_ctr << " (" << Events[ev_ctr].Name << ")" cout << endl << " Event " << event_ctr << " (" << thisEvent.Name << ")"
<< " executed at time: " << currentTime << endl; << " executed at time: " << currentTime << endl;
if (!Events[ev_ctr].Description.empty()) { if (!thisEvent.Description.empty()) {
cout << " " << Events[ev_ctr].Description << endl; cout << " " << thisEvent.Description << endl;
} }
for (j=0; j<Events[ev_ctr].NotifyProperties.size();j++) { for (j=0; j<thisEvent.NotifyProperties.size();j++) {
// cout << " " << Events[ev_ctr].NotifyProperties[j]->GetRelativeName() // cout << " " << thisEvent.NotifyProperties[j]->GetRelativeName()
cout << " " << Events[ev_ctr].DisplayString[j] cout << " " << thisEvent.DisplayString[j]
<< " = " << Events[ev_ctr].NotifyProperties[j]->getDoubleValue() << endl; << " = " << thisEvent.NotifyProperties[j]->getDoubleValue() << endl;
} }
cout << endl; cout << endl;
Events[ev_ctr].Notified = true; thisEvent.Notified = true;
} }
} }

View file

@ -49,7 +49,7 @@ INCLUDES
DEFINITIONS 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 FORWARD DECLARATIONS
@ -158,7 +158,7 @@ CLASS DOCUMENTATION
comes the &quot;run&quot; section, where the conditions are comes the &quot;run&quot; section, where the conditions are
described in &quot;event&quot; clauses.</p> described in &quot;event&quot; clauses.</p>
@author Jon S. Berndt @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; double TimeSpan;
string Name; string Name;
string Description; string Description;
vector <FGPropertyManager*> SetParam; vector <FGPropertyNode_ptr> SetParam;
vector <FGPropertyManager*> NotifyProperties; vector <std::string> SetParamName;
vector <FGPropertyNode_ptr> NotifyProperties;
vector <string> DisplayString; vector <string> DisplayString;
vector <eAction> Action; vector <eAction> Action;
vector <eType> Type; vector <eType> Type;

View file

@ -45,7 +45,7 @@ using namespace std;
namespace JSBSim { 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; static const char *IdHdr = ID_CONDITION;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -126,7 +126,7 @@ FGCondition::FGCondition(const string& test, FGPropertyManager* PropertyManager)
exit(-1); exit(-1);
} }
FGPropertyManager *node = PropertyManager->GetNode(property1, false); FGPropertyNode *node = PropertyManager->GetNode(property1, false);
if (node) { if (node) {
TestParam1 = new FGPropertyValue(node); TestParam1 = new FGPropertyValue(node);
} else { } else {

View file

@ -43,7 +43,7 @@ using namespace std;
namespace JSBSim { 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; 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::product_string = "product";
const std::string FGFunction::quotient_string = "quotient"; const std::string FGFunction::quotient_string = "quotient";
const std::string FGFunction::pow_string = "pow"; 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::exp_string = "exp";
const std::string FGFunction::log2_string = "log2"; const std::string FGFunction::log2_string = "log2";
const std::string FGFunction::ln_string = "ln"; const std::string FGFunction::ln_string = "ln";
@ -121,6 +124,11 @@ FGFunction::FGFunction(FGPropertyManager* propMan, Element* el, const string& pr
if (operation == function_string) { if (operation == function_string) {
sCopyTo = el->GetAttributeValue("copyto"); sCopyTo = el->GetAttributeValue("copyto");
if (!sCopyTo.empty()) { if (!sCopyTo.empty()) {
if (sCopyTo.find("#") != string::npos) {
if (is_number(Prefix)) sCopyTo = replace(sCopyTo,"#",Prefix);
}
pCopyTo = PropertyManager->GetNode(sCopyTo); pCopyTo = PropertyManager->GetNode(sCopyTo);
if (pCopyTo == 0L) cerr << "Property \"" << sCopyTo << "\" must be previously defined in function " if (pCopyTo == 0L) cerr << "Property \"" << sCopyTo << "\" must be previously defined in function "
<< Name << endl; << Name << endl;
@ -136,6 +144,12 @@ FGFunction::FGFunction(FGPropertyManager* propMan, Element* el, const string& pr
Type = eQuotient; Type = eQuotient;
} else if (operation == pow_string) { } else if (operation == pow_string) {
Type = ePow; 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) { } else if (operation == log2_string) {
Type = eLog2; Type = eLog2;
} else if (operation == ln_string) { } else if (operation == ln_string) {
@ -240,13 +254,13 @@ FGFunction::FGFunction(FGPropertyManager* propMan, Element* el, const string& pr
property_name = replace(property_name,"#",Prefix); property_name = replace(property_name,"#",Prefix);
} }
} }
FGPropertyManager* newNode = 0L; FGPropertyNode* newNode = 0L;
if (PropertyManager->HasNode(property_name)) { if (PropertyManager->HasNode(property_name)) {
newNode = PropertyManager->GetNode(property_name); newNode = PropertyManager->GetNode(property_name);
Parameters.push_back(new FGPropertyValue( newNode )); Parameters.push_back(new FGPropertyValue( newNode ));
} else { } else {
cerr << fgcyan << "Warning: The property " + property_name + " is initially undefined." // cerr << fgcyan << "Warning: The property " + property_name + " is initially undefined."
<< reset << endl; // << reset << endl;
Parameters.push_back(new FGPropertyValue( property_name, Parameters.push_back(new FGPropertyValue( property_name,
PropertyManager )); PropertyManager ));
} }
@ -260,6 +274,9 @@ FGFunction::FGFunction(FGPropertyManager* propMan, Element* el, const string& pr
operation == sum_string || operation == sum_string ||
operation == quotient_string || operation == quotient_string ||
operation == pow_string || operation == pow_string ||
operation == sqrt_string ||
operation == toradians_string ||
operation == todegrees_string ||
operation == exp_string || operation == exp_string ||
operation == log2_string || operation == log2_string ||
operation == ln_string || operation == ln_string ||
@ -385,6 +402,15 @@ double FGFunction::GetValue(void) const
case ePow: case ePow:
temp = pow(temp,Parameters[1]->GetValue()); temp = pow(temp,Parameters[1]->GetValue());
break; 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: case eExp:
temp = exp(temp); temp = exp(temp);
break; break;
@ -780,13 +806,15 @@ void FGFunction::bind(void)
} }
} }
// JMT commenting out on 2013/01/28 on advice of jentron - temporary fix if (PropertyManager->HasNode(tmp)) {
// for in-flux JSBSim property tie changes. FGPropertyNode* property = PropertyManager->GetNode(tmp);
// if (PropertyManager->HasNode(tmp)) { if (property->isTied()) {
// cout << "Property " << tmp << " has already been successfully bound (late)." << endl; cout << "Property " << tmp << " has already been successfully bound (late)." << endl;
// } else { return;
}
}
PropertyManager->Tie( tmp, this, &FGFunction::GetValue); PropertyManager->Tie( tmp, this, &FGFunction::GetValue);
// }
} }
} }

View file

@ -37,12 +37,13 @@ INCLUDES
#include <vector> #include <vector>
#include <string> #include <string>
#include "FGParameter.h" #include "FGParameter.h"
#include "input_output/FGPropertyManager.h"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS 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 FORWARD DECLARATIONS
@ -50,7 +51,6 @@ FORWARD DECLARATIONS
namespace JSBSim { namespace JSBSim {
class FGPropertyManager;
class Element; class Element;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -69,6 +69,9 @@ A function definition consists of an operation, a value, a table, or a property
- product (takes n args) - product (takes n args)
- quotient (takes 2 args) - quotient (takes 2 args)
- pow (takes 2 args) - pow (takes 2 args)
- sqrt (takes one argument)
- toradians (takes one argument)
- todegrees (takes one argument)
- exp (takes 2 args) - exp (takes 2 args)
- log2 (takes 1 arg) - log2 (takes 1 arg)
- ln (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: function element will be a product or sum. For example:
@code @code
<function name="aero/coefficient/Clr"> <function name="aero/moment/Clr">
<description>Roll moment due to yaw rate</description> <description>Roll moment due to yaw rate</description>
<product> <product>
<property>aero/qbar-area</property> <property>aero/qbar-area</property>
@ -155,6 +158,535 @@ an operation (such as sum) which can contain other items. The point to keep in
mind is that it evaluates to a single value - which is just what the trigonometric mind is that it evaluates to a single value - which is just what the trigonometric
functions require (except atan2, which takes two arguments). functions require (except atan2, which takes two arguments).
<h2>Specific Function Definitions</h2>
Note: In the definitions below, a "property" refers to a single property specified
within either the <property></property> tag or the shortcut tag, \<p>\</p>. The
keyword "value" refers to a single numeric value specified either within the \<value>\</value>
tag or the shortcut <v></v> tag. The keyword "table" refers to a single table specified
either within the \<table>\</table> tag or the shortcut <t></t> tag. The plural form of any
of the three words refers to one or more instances of a property, value, or table.
- @b sum, sums the values of all immediate child elements:
@code
<sum>
{properties, values, tables, or other function elements}
</sum>
Example: Mach + 0.01
<sum>
<p> velocities/mach </p>
<v> 0.01 </v>
</sum>
@endcode
- @b difference, subtracts the values of all immediate child elements from the value of the first child element:
@code
<difference>
{properties, values, tables, or other function elements}
</difference>
Example: Mach - 0.01
<difference>
<p> velocities/mach </p>
<v> 0.01 </v>
</difference>
@endcode
- @b product multiplies together the values of all immediate child elements:
@code
<product>
{properties, values, tables, or other function elements}
</product>
Example: qbar*S*beta*CY_beta
<product>
<property> aero/qbar-psf </property>
<property> metrics/Sw-sqft </property>
<property> aero/beta-rad </property>
<property> aero/coefficient/CY_beta </property>
</product>
@endcode
- @b quotient, divides the value of the first immediate child element by the second immediate child element:
@code
<quotient>
{property, value, table, or other function element}
{property, value, table, or other function element}
</quotient>
Example: (2*GM)/R
<quotient>
<product>
<v> 2.0 </v>
<p> guidance/executive/gm </p>
</product>
<p> position/radius-to-vehicle-ft </p>
</quotient>
@endcode
- @b pow, raises the value of the first immediate child element to the power of the value
of the second immediate child element:
@code
<pow>
{property, value, table, or other function element}
{property, value, table, or other function element}
</pow>
Example: Mach^2
<pow>
<p> velocities/mach </p>
<v> 2.0 </v>
</pow>
@endcode
- @b sqrt, takes the square root of the value of the immediate child element:
@code
<sqrt>
{property, value, table, or other function element}
</sqrt>
Example: square root of 25
<sqrt> <v> 25.0 </v> </sqrt>
@endcode
- @b toradians, converts a presumed argument in degrees to radians by multiplying
the value of the immediate child element by pi/180:
@code
<toradians>
{property, value, table, or other function element}
</toradians>
Example: convert 45 degrees to radians
<toradians> <v> 45 </v> </toradians>
@endcode
- @b todegrees, converts a presumed argument in radians to degrees by multiplying
the value of the immediate child element by 180/pi:
@code
<todegrees>
{property, value, table, or other function element}
</todegrees>
Example: convert 0.5*pi radians to degrees
<todegrees>
<product> <v> 0.5 </v> <pi/> </product>
</todegrees>
@endcode
- @b exp, raises "e" to the power of the immediate child element:
@code
<exp>
{property, value, table, or other function element}
</exp>
Example: raise "e" to the 1.5 power, e^1.5
<exp> <v> 1.5 </v> </exp>
@endcode
- @b log2, calculates the log base 2 value of the immediate child element:
@code
<log2>
{property, value, table, or other function element}
</log2>
Example:
<log2> <v> 128 </v> </log2>
@endcode
- @b ln, calculates the natural logarithm of the value of the immediate child element:
@code
<ln>
{property, value, table, or other function element}
</ln>
Example: ln(128)
<ln> <v> 200 </v> </ln>
@endcode
- @b log10 calculates the base 10 logarithm of the value of the immediate child element
@code
<log10>
{property, value, table, or other function element}
</log10>
Example log(Mach)
<log10> <p> velocities/mach </p> </log10>
@endcode
- @b abs calculates the absolute value of the immediate child element
@code
<abs>
{property, value, table, or other function element}
</abs>
Example:
<abs> <p> flight-path/gamma-rad </p> </abs>
@endcode
- @b sin calculates the sine of the value of the immediate child element (the argument is expected to be in radians)
@code
<sin>
{property, value, table, or other function element}
</sin>
Example:
<sin> <toradians> <p> fcs/heading-true-degrees </p> </toradians> </sin>
@endcode
- @b cos calculates the cosine of the value of the immediate child element (the argument is expected to be in radians)
@code
<cos>
{property, value, table, or other function element}
</cos>
Example:
<cos> <toradians> <p> fcs/heading-true-degrees </p> </toradians> </cos>
@endcode
- @b tan calculates the tangent of the value of the immediate child element (the argument is expected to be in radians)
@code
<tan>
{property, value, table, or other function element}
</tan>
Example:
<tan> <toradians> <p> fcs/heading-true-degrees </p> </toradians> </tan>
@endcode
- @b asin calculates the arcsine (inverse sine) of the value of the immediate child element. The
value provided should be in the range from -1 to +1. The value returned
will be expressed in radians, and will be in the range from -pi/2 to
+pi/2.
@code
<asin>
{property, value, table, or other function element}
</asin>
Example:
<asin> <v> 0.5 </v> </asin>
@endcode
- @b acos calculates the arccosine (inverse cosine) of the value of the immediate child element. The
value provided should be in the range from -1 to +1. The value returned
will be expressed in radians, and will be in the range from 0 to pi.
@code
<acos>
{property, value, table, or other function element}
</acos>
Example:
<acos> <v> 0.5 </v> </acos>
@endcode
- @b atan calculates the inverse tangent of the value of the immediate child element.
The value returned will be expressed in radians, and will be in the
range from -pi/2 to +pi/2.
@code
<atan>
{property, value, table, or other function element}
</atan>
Example:
<atan> <v> 0.5 </v> </atan>
@endcode
- @b atan2 calculates the inverse tangent of the value of the immediate child
elements, Y/X (in that order). It even works for X values near zero.
The value returned will be expressed in radians, and in the range
-pi to +pi.
@code
<atan2>
{property, value, table, or other function element} {property, value, table, or other function element}
</atan2>
Example: inverse tangent of 0.5/0.25, evaluates to: 1.107 radians
<atan2> <v> 0.5 </<v> <v> 0.25 </v> </atan2>
@endcode
- @b min returns the smallest value from all the immediate child elements
@code
<min>
{properties, values, tables, or other function elements}
</min>
Example: returns the lesser of velocity and 2500
<min>
<p> velocities/eci-velocity-mag-fps </p>
<v> 2500.0 </v>
</min>
@endcode
- @b max returns the largest value from all the immediate child elements
@code
<max>
{properties, values, tables, or other function elements}
</max>
Example: returns the greater of velocity and 15000
<max>
<p> velocities/eci-velocity-mag-fps </p>
<v> 15000.0 </v>
</max>
@endcode
- @b avg returns the average value of all the immediate child elements
@code
<avg>
{properties, values, tables, or other function elements}
</avg>
Example: returns the average of the four numbers below, evaluates to 0.50.
<avg>
<v> 0.25 </v>
<v> 0.50 </v>
<v> 0.75 </v>
<v> 0.50 </v>
</avg>
@endcode
- @b fraction returns the fractional part of the value of the immediate child element
@code
<fraction>
{property, value, table, or other function element}
</fraction>
Example: returns the fractional part of pi - or, roughly, 0.1415926...
<fraction> <pi/> </fraction>
@endcode
- @b integer returns the integer portion of the value of the immediate child element
@code
<integer>
{property, value, table, or other function element}
</integer>
@endcode
- @b mod returns the remainder from the integer division of the value of the
first immediate child element by the second immediate child element,
X/Y (X modulo Y). The value returned is the value X-I*Y, for the
largest integer I such that if Y is nonzero, the result has the
same sign as X and magnitude less than the magnitude of Y. For
instance, the expression "5 mod 2" would evaluate to 1 because 5
divided by 2 leaves a quotient of 2 and a remainder of 1, while
"9 mod 3" would evaluate to 0 because the division of 9 by 3 has a
quotient of 3 and leaves a remainder of 0.
@code
<mod>
{property, value, table, or other function element} {property, value, table, or other function element}
</mod>
Example: 5 mod 2, evaluates to 1
<mod> <v> 5 </v> <v> 2 </v> </mod>
@endcode
- @b lt returns a 1 if the value of the first immediate child element is less
than the value of the second immediate child element, returns 0
otherwise
@code
<lt>
{property, value, table, or other function element}
{property, value, table, or other function element}
</lt>
Example: returns 1 if thrust is less than 10,000, returns 0 otherwise
<lt>
<p> propulsion/engine[2]/thrust-lbs </p>
<v> 10000.0 </v>
</lt>
@endcode
- @b le returns a 1 if the value of the first immediate child element is less
than or equal to the value of the second immediate child element, returns 0
otherwise
@code
<le>
{property, value, table, or other function element}
{property, value, table, or other function element}
</le>
Example: returns 1 if thrust is less than or equal to 10,000, returns 0 otherwise
<le>
<p> propulsion/engine[2]/thrust-lbs </p>
<v> 10000.0 </v>
</le>
@endcode
- @b gt returns a 1 if the value of the first immediate child element is greater
than the value of the second immediate child element, returns 0
otherwise
@code
<gt>
{property, value, table, or other function element}
{property, value, table, or other function element}
</gt>
Example: returns 1 if thrust is greater than 10,000, returns 0 otherwise
<gt>
<p> propulsion/engine[2]/thrust-lbs </p>
<v> 10000.0 </v>
</gt>
@endcode
- @b ge returns a 1 if the value of the first immediate child element is greater
than or equal to the value of the second immediate child element, returns 0
otherwise
@code
<ge>
{property, value, table, or other function element}
{property, value, table, or other function element}
</ge>
Example: returns 1 if thrust is greater than or equal to 10,000, returns 0 otherwise
<ge>
<p> propulsion/engine[2]/thrust-lbs </p>
<v> 10000.0 </v>
</ge>
@endcode
- @b eq returns a 1 if the value of the first immediate child element is
equal to the second immediate child element, returns 0
otherwise
@code
<eq>
{property, value, table, or other function element}
{property, value, table, or other function element}
</eq>
Example: returns 1 if thrust is equal to 10,000, returns 0 otherwise
<eq>
<p> propulsion/engine[2]/thrust-lbs </p>
<v> 10000.0 </v>
</eq>
@endcode
- @b nq returns a 1 if the value of the first immediate child element is not
equal to the value of the second immediate child element, returns 0
otherwise
@code
<nq>
{property, value, table, or other function element}
{property, value, table, or other function element}
</nq>
Example: returns 1 if thrust is not 0, returns 0 otherwise
<nq>
<p> propulsion/engine[2]/thrust-lbs </p>
<v> 0.0 </v>
</nq>
@endcode
- @b and returns a 1 if the values of the immediate child elements are all 1,
returns 0 otherwise. Values provided are expected to be either 1 or 0
within machine precision.
@code
<and>
{properties, values, tables, or other function elements}
</and>
Example: returns 1 if the specified flags are all 1
<and>
<p> guidance/first-stage-flight-flag </p>
<p> control/engines-running-flag </p>
</and>
@endcode
- @b or returns a 1 if the values of any of the immediate child elements 1,
returns 0 otherwise. Values provided are expected to be either 1 or 0
within machine precision.
@code
<or>
{properties, values, tables, or other function elements}
</or>
Example: returns 1 if any of the specified flags are 1
<or>
<p> guidance/first-stage-flight-flag </p>
<p> control/engines-running-flag </p>
</or>
@endcode
- @b not returns the inverse of the value of the supplied immediate child element
(e.g., returns 1 if supplied a 0)
@code
<not>
{property, value, table, or other function element}
</not>
Example: returns 0 if the value of the supplied flag is 1
<not> <p> guidance/first-stage-flight-flag </p> </not>
@endcode
- @b ifthen if the value of the first immediate child element is 1, then the
value of the second immediate child element is returned, otherwise
the value of the third child element is returned
@code
<ifthen>
{property, value, table, or other function element}
{property, value, table, or other function element}
{property, value, table, or other function element}
</ifthen>
Example: if flight-mode is greater than 2, then a value of 0.00 is returned,
otherwise the value of the property control/pitch-lag is returned.
<ifthen>
<gt> <p> executive/flight-mode </p> <v> 2 </v> </gt>
<v> 0.00 </v>
<p> control/pitch-lag </p>
</ifthen>
@endcode
- @b switch uses the integer value of the first immediate child element as an
index to select one of the subsequent immediate child elements to
return the value of
@code
<switch>
{property, value, table, or other function element}
{property, value, table, or other function element}
{property, value, table, or other function element}
...
</switch>
Example: if flight-mode is 2, the switch function returns 0.50
<switch>
<p> executive/flight-mode </p>
<v> 0.25 </v>
<v> 0.50 </v>
<v> 0.75 </v>
<v> 1.00 </v>
</switch>
@endcode
- @b random Takes no arguments and returns a Gaussian distributed random number
@code <random/> @endcode
- @b urandom Takes no arguments and returns a uniformly distributed random number
between -1 and +1
@code<urandom/>@endcode
- @b pi Takes no argument and returns the value of Pi
@code<pi/>@endcode
- @b interpolate1d returns the result from a 1-dimensional interpolation of the
supplied values, with the value of the first immediate child
element representing the lookup value into the table, and the
following pairs of values representing the independent and
dependent values. The first provided child element is expected
to be a property. The interpolation does not extrapolate, but
holds the highest value if the provided lookup value goes
outside of the provided range.
@code
<interpolate1d>
{property, value, table, or other function element}
{property, value, table, or other function element} {property, value, table, or other function element}
...
</interpolate1d>
Example: If mach is 0.4, the interpolation will return 0.375. If mach is 1.5, the interpolation
will return 0.60.
<interpolate1d>
<p> velocities/mach </p>
<v> 0.00 </v> <v> 0.25 </v>
<v> 0.80 </v> <v> 0.50 </v>
<v> 0.90 </v> <v> 0.60 </v>
</interpolate1d>
@endcode
@author Jon Berndt @author Jon Berndt
*/ */
@ -225,6 +757,9 @@ private:
static const std::string product_string; static const std::string product_string;
static const std::string quotient_string; static const std::string quotient_string;
static const std::string pow_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 exp_string;
static const std::string log2_string; static const std::string log2_string;
static const std::string ln_string; static const std::string ln_string;
@ -265,8 +800,8 @@ private:
static const std::string switch_string; static const std::string switch_string;
static const std::string interpolate1d_string; static const std::string interpolate1d_string;
double cachedValue; double cachedValue;
enum functionType {eTopLevel=0, eProduct, eDifference, eSum, eQuotient, ePow, enum functionType {eTopLevel=0, eProduct, eDifference, eSum, eQuotient, ePow, eSqrt, eToRadians,
eExp, eAbs, eSign, eSin, eCos, eTan, eASin, eACos, eATan, eATan2, eToDegrees, eExp, eAbs, eSign, eSin, eCos, eTan, eASin, eACos, eATan, eATan2,
eMin, eMax, eAvg, eFrac, eInteger, eMod, eRandom, eUrandom, ePi, eMin, eMax, eAvg, eFrac, eInteger, eMod, eRandom, eUrandom, ePi,
eLog2, eLn, eLog10, eLT, eLE, eGE, eGT, eEQ, eNE, eAND, eOR, eNOT, eLog2, eLn, eLog10, eLT, eLE, eGE, eGT, eEQ, eNE, eAND, eOR, eNOT,
eIfThen, eSwitch, eInterpolate1D, eRotation_alpha_local, eIfThen, eSwitch, eInterpolate1D, eRotation_alpha_local,
@ -274,7 +809,7 @@ private:
eRotation_wf_to_bf} Type; eRotation_wf_to_bf} Type;
std::string Name; std::string Name;
std::string sCopyTo; // Property name to copy function value to 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; unsigned int GetBinary(double) const;
void bind(void); void bind(void);

View file

@ -3,16 +3,16 @@
* Copyright (C) James Goppert 2010 <james.goppert@gmail.com> * Copyright (C) James Goppert 2010 <james.goppert@gmail.com>
* *
* FGNelderMead.cpp is free software: you can redistribute it and/or modify it * 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 * Free Software Foundation, either version 2 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* FGNelderMead.cpp is distributed in the hope that it will be useful, but * FGNelderMead.cpp is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. * See the GNU Lesser General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU Lesser General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>. * with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@ -22,6 +22,7 @@
#include <cstdlib> #include <cstdlib>
#include <iomanip> #include <iomanip>
#include <iostream> #include <iostream>
#include <sstream>
#include <stdexcept> #include <stdexcept>
#include <ctime> #include <ctime>
@ -33,7 +34,7 @@ FGNelderMead::FGNelderMead(Function * f, const std::vector<double> & initialGues
const std::vector<double> & upperBound, const std::vector<double> & upperBound,
const std::vector<double> & initialStepSize, int iterMax, const std::vector<double> & initialStepSize, int iterMax,
double rtol, double abstol, double speed, double randomization, double rtol, double abstol, double speed, double randomization,
bool showConvergeStatus, bool showConvergeStatus,
bool showSimplex, bool pause, Callback * callback) : bool showSimplex, bool pause, Callback * callback) :
m_f(f), m_callback(callback), m_randomization(randomization), m_f(f), m_callback(callback), m_randomization(randomization),
m_lowerBound(lowerBound), m_upperBound(upperBound), m_lowerBound(lowerBound), m_upperBound(upperBound),
@ -41,227 +42,227 @@ FGNelderMead::FGNelderMead(Function * f, const std::vector<double> & initialGues
m_iMax(1), m_iNextMax(1), m_iMin(1), m_iMax(1), m_iNextMax(1), m_iMin(1),
m_simplex(m_nVert), m_cost(m_nVert), m_elemSum(m_nDim), m_simplex(m_nVert), m_cost(m_nVert), m_elemSum(m_nDim),
m_status(1), m_status(1),
initialGuess(initialGuess), initialStepSize(initialStepSize), initialGuess(initialGuess), initialStepSize(initialStepSize),
iterMax(iterMax), iter(), rtol(rtol), abstol(abstol), iterMax(iterMax), iter(), rtol(rtol), abstol(abstol),
speed(speed), showConvergeStatus(showConvergeStatus), showSimplex(showSimplex), speed(speed), showConvergeStatus(showConvergeStatus), showSimplex(showSimplex),
pause(pause), rtolI(), minCostPrevResize(1), minCost(), minCostPrev(), maxCost(), pause(pause), rtolI(), minCostPrevResize(1), minCost(), minCostPrev(), maxCost(),
nextMaxCost() nextMaxCost()
{ {
srand ( time(NULL) ); // seed random number generator srand ( time(NULL) ); // seed random number generator
} }
void FGNelderMead::update() void FGNelderMead::update()
{ {
std::cout.precision(3); std::cout.precision(3);
// reinitialize simplex whenever rtol condition is met // reinitialize simplex whenever rtol condition is met
if ( rtolI < rtol || iter == 0) if ( rtolI < rtol || iter == 0)
{ {
std::vector<double> guess(m_nDim); std::vector<double> guess(m_nDim);
if (iter == 0) if (iter == 0)
{ {
//std::cout << "constructing simplex" << std::endl; //std::cout << "constructing simplex" << std::endl;
guess = initialGuess; guess = initialGuess;
} }
else else
{ {
if (std::abs(minCost-minCostPrevResize) < abstol) if (std::abs(minCost-minCostPrevResize) < std::numeric_limits<float>::epsilon())
{ {
std::cout << "\nunable to escape local minimum" << std::endl; throw std::runtime_error("unable to escape local minimum!");
m_status = -1; m_status = -1;
return; return;
} }
//std::cout << "reinitializing step size" << std::endl; //std::cout << "reinitializing step size" << std::endl;
guess = m_simplex[m_iMin]; guess = m_simplex[m_iMin];
minCostPrevResize = minCost; minCostPrevResize = minCost;
} }
constructSimplex(guess,initialStepSize); constructSimplex(guess,initialStepSize);
} }
// find vertex costs // find vertex costs
for (int vertex=0;vertex<m_nVert;vertex++) for (int vertex=0;vertex<m_nVert;vertex++)
{ {
try try
{ {
m_cost[vertex] = m_f->eval(m_simplex[vertex]); m_cost[vertex] = eval(m_simplex[vertex]);
} }
catch (const std::exception & e) catch (const std::exception & e)
{ {
m_status = -1; m_status = -1;
throw; throw;
return; return;
} }
} }
// find max cost, next max cost, and min cost // find max cost, next max cost, and min cost
m_iMax = m_iNextMax = m_iMin = 0; m_iMax = m_iNextMax = m_iMin = 0;
for (int vertex=0;vertex<m_nVert;vertex++) for (int vertex=0;vertex<m_nVert;vertex++)
{ {
if ( m_cost[vertex] > m_cost[m_iMax] ) if ( m_cost[vertex] > m_cost[m_iMax] )
{ {
m_iMax = vertex; 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_iNextMax] || m_iMax == m_iNextMax ) m_iNextMax = vertex;
else if ( m_cost[vertex] < m_cost[m_iMin] ) m_iMin = vertex; else if ( m_cost[vertex] < m_cost[m_iMin] ) m_iMin = vertex;
} }
// callback // callback
if (m_callback) m_callback->eval(m_simplex[m_iMin]); if (m_callback) m_callback->eval(m_simplex[m_iMin]);
// compute relative tolerance // compute relative tolerance
rtolI = 2*std::abs(m_cost[m_iMax] - rtolI = 2*std::abs(m_cost[m_iMax] -
m_cost[m_iMin])/(std::abs(m_cost[m_iMax]+std::abs(m_cost[m_iMin])+ m_cost[m_iMin])/(std::abs(m_cost[m_iMax]+std::abs(m_cost[m_iMin])+
std::numeric_limits<double>::epsilon())); std::numeric_limits<double>::epsilon()));
// check for max iteration break condition // check for max iteration break condition
if (iter > iterMax) if (iter > iterMax)
{ {
std::cout << "\nmax iterations exceeded" << std::endl; m_status = -1;
m_status = -1; throw std::runtime_error("max iterations exceeded!");
return; return;
} }
// check for convergence break condition // check for convergence break condition
else if ( m_cost[m_iMin] < abstol ) else if ( m_cost[m_iMin] < abstol )
{ {
std::cout << "\nsimplex converged" << std::endl; //std::cout << "\nsimplex converged" << std::endl;
m_status = 0; m_status = 0;
return; return;
} }
// compute element sum of simplex vertices // compute element sum of simplex vertices
for (int dim=0;dim<m_nDim;dim++) for (int dim=0;dim<m_nDim;dim++)
{ {
m_elemSum[dim] = 0; m_elemSum[dim] = 0;
for (int vertex=0;vertex<m_nVert;vertex++) for (int vertex=0;vertex<m_nVert;vertex++)
m_elemSum[dim] += m_simplex[vertex][dim]; m_elemSum[dim] += m_simplex[vertex][dim];
} }
// min and max costs // min and max costs
minCostPrev = minCost; minCostPrev = minCost;
minCost = m_cost[m_iMin]; minCost = m_cost[m_iMin];
maxCost = m_cost[m_iMax]; maxCost = m_cost[m_iMax];
nextMaxCost = m_cost[m_iNextMax]; nextMaxCost = m_cost[m_iNextMax];
// output cost and simplex // output cost and simplex
if (showConvergeStatus) if (showConvergeStatus)
{ {
if ( (minCostPrev + std::numeric_limits<float>::epsilon() ) if ( (minCostPrev + std::numeric_limits<float>::epsilon() )
< minCost && minCostPrev != 0) < minCost && minCostPrev != 0)
{ {
std::cout << "\twarning: simplex cost increased" std::cout << "\twarning: simplex cost increased"
<< std::scientific << std::scientific
<< "\n\tcost: " << minCost << "\n\tcost: " << minCost
<< "\n\tcost previous: " << minCostPrev << "\n\tcost previous: " << minCostPrev
<< std::fixed << std::endl; << std::fixed << std::endl;
} }
std::cout << "i: " << iter std::cout << "i: " << iter
<< std::scientific << std::scientific
<< "\tcost: " << m_cost[m_iMin] << "\tcost: " << m_cost[m_iMin]
<< "\trtol: " << rtolI << "\trtol: " << rtolI
<< std::fixed << std::fixed
<< "\talpha: " << m_simplex[m_iMin][2]*180/M_PI << "\talpha: " << m_simplex[m_iMin][2]*180/M_PI
<< "\tbeta: " << m_simplex[m_iMin][5]*180/M_PI << "\tbeta: " << m_simplex[m_iMin][5]*180/M_PI
<< "\tthrottle: " << m_simplex[m_iMin][0] << "\tthrottle: " << m_simplex[m_iMin][0]
<< "\televator: " << m_simplex[m_iMin][1] << "\televator: " << m_simplex[m_iMin][1]
<< "\taileron: " << m_simplex[m_iMin][3] << "\taileron: " << m_simplex[m_iMin][3]
<< "\trudder: " << m_simplex[m_iMin][4] << "\trudder: " << m_simplex[m_iMin][4]
<< std::endl; << std::endl;
} }
if (showSimplex) if (showSimplex)
{ {
std::cout << "simplex: " << std::endl;; std::cout << "simplex: " << std::endl;;
for (int j=0;j<m_nVert;j++) for (int j=0;j<m_nVert;j++)
std::cout << "\t" << std::scientific std::cout << "\t" << std::scientific
<< std::setw(10) << m_cost[j]; << std::setw(10) << m_cost[j];
std::cout << std::endl; std::cout << std::endl;
for (int j=0;j<m_nVert;j++) std::cout << "\t\t" << j; for (int j=0;j<m_nVert;j++) std::cout << "\t\t" << j;
std::cout << std::endl; std::cout << std::endl;
for (int i=0;i<m_nDim;i++) for (int i=0;i<m_nDim;i++)
{ {
for (int j=0;j<m_nVert;j++) for (int j=0;j<m_nVert;j++)
std::cout << "\t" << std::setw(10) << m_simplex[j][i]; std::cout << "\t" << std::setw(10) << m_simplex[j][i];
std::cout << std::endl; std::cout << std::endl;
} }
std::cout << std::fixed std::cout << std::fixed
<< "\n\tiMax: " << m_iMax << "\n\tiMax: " << m_iMax
<< "\t\tiNextMax: " << m_iNextMax << "\t\tiNextMax: " << m_iNextMax
<< "\t\tiMin: " << m_iMin << std::endl; << "\t\tiMin: " << m_iMin << std::endl;
} }
if (pause) if (pause)
{ {
std::cout << "paused, press any key to continue" << std::endl; std::cout << "paused, press any key to continue" << std::endl;
std::cin.get(); std::cin.get();
} }
// costs // costs
try try
{ {
// try inversion // try inversion
double costTry = tryStretch(-1.0); double costTry = tryStretch(-1.0);
//std::cout << "cost Try 0: " << costTry << std::endl; //std::cout << "cost Try 0: " << costTry << std::endl;
// if lower cost than best, then try further stretch by double speed factor // if lower cost than best, then try further stretch by double speed factor
if (costTry < minCost) if (costTry < minCost)
{ {
double costTry0 = costTry; double costTry0 = costTry;
costTry = tryStretch(speed); costTry = tryStretch(speed);
//std::cout << "cost Try 1: " << costTry << std::endl; //std::cout << "cost Try 1: " << costTry << std::endl;
if (showSimplex) if (showSimplex)
{ {
if (costTry < costTry0) std::cout << "inversion about: " << m_iMax << std::endl; if (costTry < costTry0) std::cout << "inversion about: " << m_iMax << std::endl;
else std::cout << "inversion and stretch about: " << m_iMax << std::endl; else std::cout << "inversion and stretch about: " << m_iMax << std::endl;
} }
} }
// otherwise try a contraction // otherwise try a contraction
else if (costTry > nextMaxCost) else if (costTry > nextMaxCost)
{ {
// 1d contraction // 1d contraction
costTry = tryStretch(1./speed); costTry = tryStretch(1./speed);
//std::cout << "cost Try 2: " << costTry << std::endl; //std::cout << "cost Try 2: " << costTry << std::endl;
// if greater than max cost, contract about min // if greater than max cost, contract about min
if (costTry > maxCost) if (costTry > maxCost)
{ {
if (showSimplex) if (showSimplex)
std::cout << "multiD contraction about: " << m_iMin << std::endl; std::cout << "multiD contraction about: " << m_iMin << std::endl;
contract(); contract();
} }
else else
{ {
if (showSimplex) if (showSimplex)
std::cout << "contraction about: " << m_iMin << std::endl; std::cout << "contraction about: " << m_iMin << std::endl;
} }
} }
} }
catch (const std::exception & e) catch (const std::exception & e)
{ {
throw; throw;
m_status = -1; m_status = -1;
return; return;
} }
// iteration // iteration
iter++; iter++;
} }
int FGNelderMead::status() int FGNelderMead::status()
{ {
return m_status; return m_status;
} }
double FGNelderMead::getRandomFactor() double FGNelderMead::getRandomFactor()
{ {
double randFact = 1+(float(rand() % 1000)/500-1)*m_randomization; double randFact = 1+(float(rand() % 1000)/500-1)*m_randomization;
//std::cout << "random factor: " << randFact << std::endl;; //std::cout << "random factor: " << randFact << std::endl;;
return randFact; return randFact;
} }
std::vector<double> FGNelderMead::getSolution() std::vector<double> FGNelderMead::getSolution()
@ -271,8 +272,8 @@ std::vector<double> FGNelderMead::getSolution()
double FGNelderMead::tryStretch(double factor) double FGNelderMead::tryStretch(double factor)
{ {
// randomize factor so we can avoid locking situations // randomize factor so we can avoid locking situations
factor = factor*getRandomFactor(); factor = factor*getRandomFactor();
// create trial vertex // create trial vertex
double a= (1.0-factor)/m_nDim; double a= (1.0-factor)/m_nDim;
@ -285,23 +286,7 @@ double FGNelderMead::tryStretch(double factor)
} }
// find trial cost // find trial cost
double costTry0 = 0, costTry = 0; double costTry = eval(tryVertex);
try
{
costTry0 = m_f->eval(tryVertex);
costTry = m_f->eval(tryVertex);
}
catch(const std::exception & e)
{
throw;
return 0;
}
if (std::abs(costTry0-costTry) > std::numeric_limits<float>::epsilon())
{
//std::cout << "\twarning: dynamics not stable!" << std::endl;
//return 1000000*m_cost[m_iMax];
}
// if trial cost lower than max // if trial cost lower than max
if (costTry < m_cost[m_iMax]) if (costTry < m_cost[m_iMax])
@ -337,7 +322,7 @@ void FGNelderMead::constructSimplex(const std::vector<double> & guess,
for (int vertex=0;vertex<m_nVert;vertex++) for (int vertex=0;vertex<m_nVert;vertex++)
{ {
m_simplex[vertex] = guess; m_simplex[vertex] = guess;
} }
for (int dim=0;dim<m_nDim;dim++) for (int dim=0;dim<m_nDim;dim++)
{ {
@ -370,6 +355,30 @@ void FGNelderMead::boundVertex(std::vector<double> & vertex,
} }
} }
double FGNelderMead::eval(const std::vector<double> & vertex, bool check)
{
if (check) {
double cost0 = m_f->eval(vertex);
double cost1 = m_f->eval(vertex);
if ((cost0 - cost1) > std::numeric_limits<float>::epsilon()) {
std::stringstream msg;
msg.precision(10);
msg << std::scientific
<< "dynamics not stable!"
<< "\tdiff: " << cost1 - cost0
<< "\tcost0: " << cost0
<< "\tcost1: " << cost1
<< std::endl;
std::cout << msg.str();
//throw std::runtime_error(msg.str());
} else {
return cost1;
}
} else {
return m_f->eval(vertex);
}
}
} // JSBSim } // JSBSim

View file

@ -3,16 +3,16 @@
* Copyright (C) James Goppert 2010 <james.goppert@gmail.com> * Copyright (C) James Goppert 2010 <james.goppert@gmail.com>
* *
* FGNelderMead.h is free software: you can redistribute it and/or modify it * 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 * Free Software Foundation, either version 2 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* FGNelderMead.h is distributed in the hope that it will be useful, but * FGNelderMead.h is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. * See the GNU Lesser General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU Lesser General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>. * with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@ -35,7 +35,7 @@ public:
virtual double eval(const std::vector<double> & v) = 0; virtual double eval(const std::vector<double> & v) = 0;
virtual ~Function() {}; virtual ~Function() {};
}; };
class Callback class Callback
{ {
public: public:
virtual void eval(const std::vector<double> & v) = 0; virtual void eval(const std::vector<double> & v) = 0;
@ -49,43 +49,44 @@ public:
double rtol=std::numeric_limits<float>::epsilon(), double rtol=std::numeric_limits<float>::epsilon(),
double abstol=std::numeric_limits<float>::epsilon(), double abstol=std::numeric_limits<float>::epsilon(),
double speed = 2.0, double speed = 2.0,
double randomization=0.1, double randomization=0.1,
bool showConvergeStatus=true,bool showSimplex=false, bool showConvergeStatus=true,bool showSimplex=false,
bool pause=false, bool pause=false,
Callback * callback=NULL); Callback * callback=NULL);
std::vector<double> getSolution(); std::vector<double> getSolution();
void update(); void update();
int status(); int status();
private: private:
// attributes // attributes
Function * m_f; Function * m_f;
Callback * m_callback; Callback * m_callback;
double m_randomization; double m_randomization;
const std::vector<double> & m_lowerBound; const std::vector<double> & m_lowerBound;
const std::vector<double> & m_upperBound; const std::vector<double> & m_upperBound;
int m_nDim, m_nVert, m_iMax, m_iNextMax, m_iMin; int m_nDim, m_nVert, m_iMax, m_iNextMax, m_iMin;
std::vector< std::vector<double> > m_simplex; std::vector< std::vector<double> > m_simplex;
std::vector<double> m_cost; std::vector<double> m_cost;
std::vector<double> m_elemSum; std::vector<double> m_elemSum;
int m_status; int m_status;
const std::vector<double> & initialGuess; const std::vector<double> & initialGuess;
const std::vector<double> & initialStepSize; const std::vector<double> & initialStepSize;
int iterMax, iter; int iterMax, iter;
double rtol,abstol,speed; double rtol,abstol,speed;
bool showConvergeStatus, showSimplex, pause; bool showConvergeStatus, showSimplex, pause;
double rtolI, minCostPrevResize, minCost, minCostPrev, double rtolI, minCostPrevResize, minCost, minCostPrev,
maxCost, nextMaxCost; maxCost, nextMaxCost;
// methods // methods
double getRandomFactor(); double getRandomFactor();
double tryStretch(double factor); double tryStretch(double factor);
void contract(); void contract();
void constructSimplex(const std::vector<double> & guess, const std::vector<double> & stepSize); void constructSimplex(const std::vector<double> & guess, const std::vector<double> & stepSize);
void boundVertex(std::vector<double> & vertex, void boundVertex(std::vector<double> & vertex,
const std::vector<double> & upperBound, const std::vector<double> & upperBound,
const std::vector<double> & lowerBound); const std::vector<double> & lowerBound);
double eval(const std::vector<double> & vertex, bool check = false);
}; };
} // JSBSim } // JSBSim

View file

@ -30,17 +30,18 @@ INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGPropertyValue.h" #include "FGPropertyValue.h"
#include "input_output/FGPropertyManager.h"
namespace JSBSim { 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; static const char *IdHdr = ID_PROPERTYVALUE;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
FGPropertyValue::FGPropertyValue(FGPropertyManager* propNode) FGPropertyValue::FGPropertyValue(FGPropertyNode* propNode)
: PropertyManager(0L), PropertyNode(propNode) : PropertyManager(0L), PropertyNode(propNode)
{ {
} }
@ -56,7 +57,7 @@ FGPropertyValue::FGPropertyValue(std::string propName, FGPropertyManager* proper
double FGPropertyValue::GetValue(void) const double FGPropertyValue::GetValue(void) const
{ {
FGPropertyManager* node = PropertyNode; FGPropertyNode* node = PropertyNode;
if (!PropertyNode) { if (!PropertyNode) {
// The node cannot be cached since this is a const method. // The node cannot be cached since this is a const method.

View file

@ -42,7 +42,7 @@ INCLUDES
DEFINITIONS 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 FORWARD DECLARATIONS
@ -66,18 +66,18 @@ class FGPropertyValue : public FGParameter
{ {
public: public:
FGPropertyValue(FGPropertyManager* propNode); FGPropertyValue(FGPropertyNode* propNode);
FGPropertyValue(std::string propName, FGPropertyManager* propertyManager); FGPropertyValue(std::string propName, FGPropertyManager* propertyManager);
~FGPropertyValue() {}; ~FGPropertyValue() {};
double GetValue(void) const; double GetValue(void) const;
void SetNode(FGPropertyManager* node) {PropertyNode = node;} void SetNode(FGPropertyNode* node) {PropertyNode = node;}
std::string GetName(void) const; std::string GetName(void) const;
private: private:
FGPropertyManager* PropertyManager; // Property root used to do late binding. FGPropertyManager* PropertyManager; // Property root used to do late binding.
FGPropertyManager* PropertyNode; FGPropertyNode_ptr PropertyNode;
std::string PropertyName; std::string PropertyName;
}; };

View file

@ -3,22 +3,23 @@
* Copyright (C) James Goppert 2010 <james.goppert@gmail.com> * Copyright (C) James Goppert 2010 <james.goppert@gmail.com>
* *
* FGStateSpace.cpp is free software: you can redistribute it and/or modify it * 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 * Free Software Foundation, either version 2 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* FGStateSpace.cpp is distributed in the hope that it will be useful, but * FGStateSpace.cpp is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. * See the GNU Lesser General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU Lesser General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>. * with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "FGStateSpace.h" #include "FGStateSpace.h"
#include <limits> #include <limits>
#include <iomanip> #include <iomanip>
#include <string>
namespace JSBSim namespace JSBSim
{ {
@ -77,7 +78,23 @@ void FGStateSpace::numericalJacobian(std::vector< std::vector<double> > & J, Co
if (computeYDerivative) fn2 = y.getDeriv(iY); if (computeYDerivative) fn2 = y.getDeriv(iY);
else fn2 = y.get(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); x.set(x0);
if (m_fdm->GetDebugLevel() > 1) if (m_fdm->GetDebugLevel() > 1)

View file

@ -3,16 +3,16 @@
* Copyright (C) James Goppert 2010 <james.goppert@gmail.com> * Copyright (C) James Goppert 2010 <james.goppert@gmail.com>
* *
* FGStateSpace.h is free software: you can redistribute it and/or modify it * 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 * Free Software Foundation, either version 2 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* FGStateSpace.h is distributed in the hope that it will be useful, but * FGStateSpace.h is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. * See the GNU Lesser General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU Lesser General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>. * with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@ -30,6 +30,7 @@
#include "models/FGFCS.h" #include "models/FGFCS.h"
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
#include <limits>
namespace JSBSim namespace JSBSim
{ {
@ -57,9 +58,9 @@ public:
std::vector<double> x0 = m_stateSpace->x.get(); std::vector<double> x0 = m_stateSpace->x.get();
double f0 = get(); double f0 = get();
double dt0 = m_fdm->GetDeltaT(); double dt0 = m_fdm->GetDeltaT();
double time0 = m_fdm->GetSimTime(); double time0 = m_fdm->GetSimTime();
m_fdm->Setdt(1./120.); m_fdm->Setdt(1./120.);
m_fdm->DisableOutput(); m_fdm->DisableOutput();
m_fdm->Run(); m_fdm->Run();
double f1 = get(); double f1 = get();
m_stateSpace->x.set(x0); m_stateSpace->x.set(x0);
@ -75,8 +76,8 @@ public:
} }
double deriv = (f1-f0)/m_fdm->GetDeltaT(); double deriv = (f1-f0)/m_fdm->GetDeltaT();
m_fdm->Setdt(dt0); // restore original value m_fdm->Setdt(dt0); // restore original value
m_fdm->Setsim_time(time0); m_fdm->Setsim_time(time0);
m_fdm->EnableOutput(); m_fdm->EnableOutput();
return deriv; return deriv;
} }
void setStateSpace(FGStateSpace * stateSpace) void setStateSpace(FGStateSpace * stateSpace)
@ -141,7 +142,7 @@ public:
void set(int i, double val) void set(int i, double val)
{ {
m_components[i]->set(val); m_components[i]->set(val);
m_fdm->RunIC(); m_stateSpace->run();
}; };
double get(int i) double get(int i)
{ {
@ -174,12 +175,12 @@ public:
void set(vector<double> vals) void set(vector<double> vals)
{ {
for (int i=0;i<getSize();i++) m_components[i]->set(vals[i]); for (int i=0;i<getSize();i++) m_components[i]->set(vals[i]);
m_fdm->RunIC(); m_stateSpace->run();
} }
void set(double * array) void set(double * array)
{ {
for (int i=0;i<getSize();i++) m_components[i]->set(array[i]); for (int i=0;i<getSize();i++) m_components[i]->set(array[i]);
m_fdm->RunIC(); m_stateSpace->run();
} }
std::string getName(int i) const std::string getName(int i) const
{ {
@ -218,6 +219,51 @@ public:
void setFdm(FGFDMExec * fdm) { m_fdm = fdm; } void setFdm(FGFDMExec * fdm) { m_fdm = fdm; }
void run() {
// initialize
m_fdm->Initialize(m_fdm->GetIC());
for (unsigned int i=0; i<m_fdm->GetPropulsion()->GetNumEngines(); i++) {
m_fdm->GetPropulsion()->GetEngine(i)->InitRunning();
}
// wait for stable state
double cost = stateSum();
for(int i=0;i<1000;i++) {
m_fdm->GetPropulsion()->GetSteadyState();
m_fdm->SetTrimStatus(true);
m_fdm->DisableOutput();
m_fdm->SuspendIntegration();
m_fdm->Run();
m_fdm->SetTrimStatus(false);
m_fdm->EnableOutput();
m_fdm->ResumeIntegration();
double costNew = stateSum();
double dcost = fabs(costNew - cost);
if (dcost < std::numeric_limits<double>::epsilon()) {
if(m_fdm->GetDebugLevel() > 1) {
std::cout << "cost convergd, i: " << i << std::endl;
}
break;
}
if (i > 1000) {
if(m_fdm->GetDebugLevel() > 1) {
std::cout << "cost failed to converge, dcost: "
<< std::scientific
<< dcost << std::endl;
}
break;
}
cost = costNew;
}
}
double stateSum() {
double sum = 0;
for (int i=0;i<x.getSize();i++) sum += x.get(i);
return sum;
}
void clear() { void clear() {
x.clear(); x.clear();
u.clear(); u.clear();
@ -272,7 +318,7 @@ public:
}; };
class VGround : public Component class VGround : public Component
{ {
public: public:
VGround() : Component("VGround","ft/s") {}; VGround() : Component("VGround","ft/s") {};
@ -282,11 +328,11 @@ public:
} }
void set(double val) void set(double val)
{ {
m_fdm->GetIC()->SetVgroundFpsIC(val); m_fdm->GetIC()->SetVgroundFpsIC(val);
} }
}; };
class AccelX : public Component class AccelX : public Component
{ {
public: public:
AccelX() : Component("AccelX","ft/s^2") {}; AccelX() : Component("AccelX","ft/s^2") {};
@ -296,11 +342,11 @@ public:
} }
void set(double val) 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: public:
AccelY() : Component("AccelY","ft/s^2") {}; AccelY() : Component("AccelY","ft/s^2") {};
@ -310,11 +356,11 @@ public:
} }
void set(double val) 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: public:
AccelZ() : Component("AccelZ","ft/s^2") {}; AccelZ() : Component("AccelZ","ft/s^2") {};
@ -324,7 +370,7 @@ public:
} }
void set(double val) 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) 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()->SetAlphaRadIC(val);
m_fdm->GetIC()->SetBetaRadIC(beta);
m_fdm->GetIC()->SetPsiRadIC(psi);
m_fdm->GetIC()->SetThetaRadIC(theta);
} }
double getDeriv() const double getDeriv() const
{ {
@ -357,8 +408,8 @@ public:
} }
void set(double val) void set(double val)
{ {
m_fdm->GetIC()->SetFlightPathAngleRadIC(val-m_fdm->GetIC()->GetAlphaRadIC()); m_fdm->GetIC()->SetFlightPathAngleRadIC(val-m_fdm->GetIC()->GetAlphaRadIC());
m_fdm->GetIC()->SetThetaRadIC(val); //m_fdm->GetIC()->SetThetaRadIC(val);
} }
double getDeriv() const double getDeriv() const
{ {
@ -412,7 +463,9 @@ public:
} }
void set(double val) void set(double val)
{ {
double psi = m_fdm->GetIC()->GetPsiRadIC();
m_fdm->GetIC()->SetBetaRadIC(val); m_fdm->GetIC()->SetBetaRadIC(val);
m_fdm->GetIC()->SetPsiRadIC(psi);
} }
double getDeriv() const double getDeriv() const
{ {
@ -621,11 +674,11 @@ public:
} }
void set(double val) 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: public:
Rpm1() : Component("Rpm1","rev/min") {}; Rpm1() : Component("Rpm1","rev/min") {};
@ -635,25 +688,25 @@ public:
} }
void set(double val) 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: public:
Rpm2() : Component("Rpmr2","rev/min") {}; Rpm2() : Component("Rpm2","rev/min") {};
double get() const double get() const
{ {
return m_fdm->GetPropulsion()->GetEngine(2)->GetThruster()->GetRPM(); return m_fdm->GetPropulsion()->GetEngine(2)->GetThruster()->GetRPM();
} }
void set(double val) 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: public:
Rpm3() : Component("Rpm3","rev/min") {}; Rpm3() : Component("Rpm3","rev/min") {};
@ -663,7 +716,7 @@ public:
} }
void set(double val) 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: public:
Pi() : Component("P inertial","rad/s") {}; Pi() : Component("P inertial","rad/s") {};
@ -728,10 +781,10 @@ public:
} }
void set(double val) void set(double val)
{ {
//Set PQR from PQRi //Set PQR from PQRi
//VState.vPQR = VState.vPQRi - Ti2b * vOmegaEarth; //VState.vPQR = VState.vPQRi - Ti2b * vOmegaEarth;
m_fdm->GetIC()->SetQRadpsIC(val + \ 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 double getDeriv() const
{ {
@ -739,7 +792,7 @@ public:
} }
}; };
class Qi : public Component class Qi : public Component
{ {
public: public:
Qi() : Component("Q inertial","rad/s") {}; Qi() : Component("Q inertial","rad/s") {};
@ -749,10 +802,10 @@ public:
} }
void set(double val) void set(double val)
{ {
//Set PQR from PQRi //Set PQR from PQRi
//VState.vPQR = VState.vPQRi - Ti2b * vOmegaEarth; //VState.vPQR = VState.vPQRi - Ti2b * vOmegaEarth;
m_fdm->GetIC()->SetQRadpsIC(val + \ 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 double getDeriv() const
{ {
@ -760,7 +813,7 @@ public:
} }
}; };
class Ri : public Component class Ri : public Component
{ {
public: public:
Ri() : Component("R inertial","rad/s") {}; Ri() : Component("R inertial","rad/s") {};
@ -770,10 +823,10 @@ public:
} }
void set(double val) void set(double val)
{ {
//Set PQR from PQRi //Set PQR from PQRi
//VState.vPQR = VState.vPQRi - Ti2b * vOmegaEarth; //VState.vPQR = VState.vPQRi - Ti2b * vOmegaEarth;
m_fdm->GetIC()->SetQRadpsIC(val + \ 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 double getDeriv() const
{ {
@ -781,7 +834,7 @@ public:
} }
}; };
class Vn : public Component class Vn : public Component
{ {
public: public:
Vn() : Component("Vel north","feet/s") {}; Vn() : Component("Vel north","feet/s") {};
@ -795,12 +848,12 @@ public:
} }
double getDeriv() const 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); return (m_fdm->GetPropagate()->GetTb2l()*m_fdm->GetAccelerations()->GetUVWdot())(1);
} }
}; };
class Ve : public Component class Ve : public Component
{ {
public: public:
Ve() : Component("Vel east","feet/s") {}; Ve() : Component("Vel east","feet/s") {};
@ -814,12 +867,12 @@ public:
} }
double getDeriv() const 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); return (m_fdm->GetPropagate()->GetTb2l()*m_fdm->GetAccelerations()->GetUVWdot())(2);
} }
}; };
class Vd : public Component class Vd : public Component
{ {
public: public:
Vd() : Component("Vel down","feet/s") {}; Vd() : Component("Vel down","feet/s") {};
@ -833,35 +886,35 @@ public:
} }
double getDeriv() const 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); return (m_fdm->GetPropagate()->GetTb2l()*m_fdm->GetAccelerations()->GetUVWdot())(3);
} }
}; };
class COG : public Component class COG : public Component
{ {
public: public:
COG() : Component("Course Over Ground","rad") {}; COG() : Component("Course Over Ground","rad") {};
double get() const double get() const
{ {
//cog = atan2(Ve,Vn) //cog = atan2(Ve,Vn)
return atan2(m_fdm->GetPropagate()->GetVel(2),m_fdm->GetPropagate()->GetVel(1)); return atan2(m_fdm->GetPropagate()->GetVel(2),m_fdm->GetPropagate()->GetVel(1));
} }
void set(double val) void set(double val)
{ {
//set Vn and Ve according to vGround and COG //set Vn and Ve according to vGround and COG
m_fdm->GetIC()->SetVNorthFpsIC(m_fdm->GetAuxiliary()->GetVground()*cos(val)); m_fdm->GetIC()->SetVNorthFpsIC(m_fdm->GetAuxiliary()->GetVground()*cos(val));
m_fdm->GetIC()->SetVEastFpsIC(m_fdm->GetAuxiliary()->GetVground()*sin(val)); m_fdm->GetIC()->SetVEastFpsIC(m_fdm->GetAuxiliary()->GetVground()*sin(val));
} }
double getDeriv() const double getDeriv() const
{ {
double Vn = m_fdm->GetPropagate()->GetVel(1); double Vn = m_fdm->GetPropagate()->GetVel(1);
double Vndot = (m_fdm->GetPropagate()->GetTb2l()*m_fdm->GetAccelerations()->GetUVWdot())(1); double Vndot = (m_fdm->GetPropagate()->GetTb2l()*m_fdm->GetAccelerations()->GetUVWdot())(1);
double Ve = m_fdm->GetPropagate()->GetVel(2); double Ve = m_fdm->GetPropagate()->GetVel(2);
double Vedot = (m_fdm->GetPropagate()->GetTb2l()*m_fdm->GetAccelerations()->GetUVWdot())(2); double Vedot = (m_fdm->GetPropagate()->GetTb2l()*m_fdm->GetAccelerations()->GetUVWdot())(2);
//dCOG/dt = dCOG/dVe*dVe/dt + dCOG/dVn*dVn/dt //dCOG/dt = dCOG/dVe*dVe/dt + dCOG/dVn*dVn/dt
return Vn/(Vn*Vn+Ve*Ve)*Vedot - Ve/(Vn*Vn+Ve*Ve)*Vndot; return Vn/(Vn*Vn+Ve*Ve)*Vedot - Ve/(Vn*Vn+Ve*Ve)*Vndot;
} }
}; };

View file

@ -47,7 +47,7 @@ using namespace std;
namespace JSBSim { 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; static const char *IdHdr = ID_TABLE;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -122,7 +122,7 @@ FGTable::FGTable(FGPropertyManager* propMan, Element* el) : PropertyManager(prop
string call_type; string call_type;
string parent_type; string parent_type;
string brkpt_string; string brkpt_string;
FGPropertyManager* node; FGPropertyNode* node;
Element *tableData=0; Element *tableData=0;
Element *parent_element=0; Element *parent_element=0;
Element *axisElement=0; Element *axisElement=0;

View file

@ -38,16 +38,17 @@ SENTRY
INCLUDES INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGParameter.h"
#include <iosfwd> #include <iosfwd>
#include <vector> #include <vector>
#include <string> #include <string>
#include "FGParameter.h"
#include "input_output/FGPropertyManager.h"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS 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 FORWARD DECLARATIONS
@ -55,7 +56,6 @@ FORWARD DECLARATIONS
namespace JSBSim { namespace JSBSim {
class FGPropertyManager;
class Element; class Element;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -233,7 +233,7 @@ combustion_efficiency = Lookup_Combustion_Efficiency->GetValue(equivalence_ratio
@endcode @endcode
@author Jon S. Berndt @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) const {return GetElement(r, c);}
// double operator()(unsigned int r, unsigned int c, unsigned int t) {GetElement(r, c, t);} // double operator()(unsigned int r, unsigned int c, unsigned int t) {GetElement(r, c, t);}
void SetRowIndexProperty(FGPropertyManager *node) {lookupProperty[eRow] = node;} void SetRowIndexProperty(FGPropertyNode *node) {lookupProperty[eRow] = node;}
void SetColumnIndexProperty(FGPropertyManager *node) {lookupProperty[eColumn] = node;} void SetColumnIndexProperty(FGPropertyNode *node) {lookupProperty[eColumn] = node;}
unsigned int GetNumRows() const {return nRows;} unsigned int GetNumRows() const {return nRows;}
@ -303,7 +303,7 @@ private:
enum type {tt1D, tt2D, tt3D} Type; enum type {tt1D, tt2D, tt3D} Type;
enum axis {eRow=0, eColumn, eTable}; enum axis {eRow=0, eColumn, eTable};
bool internal; bool internal;
FGPropertyManager *lookupProperty[3]; FGPropertyNode_ptr lookupProperty[3];
double** Data; double** Data;
std::vector <FGTable*> Tables; std::vector <FGTable*> Tables;
unsigned int nRows, nCols, nTables, dimension; unsigned int nRows, nCols, nTables, dimension;

View file

@ -48,7 +48,7 @@ using namespace std;
namespace JSBSim { 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; 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 // JSB 4/27/12 - After use, convert wind axes to produce normal lift
// and drag values - not negative ones! // 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) { switch (axisType) {
case atBodyXYZ: // Forces already in body axes; no manipulation needed case atBodyXYZ: // Forces already in body axes; no manipulation needed
vFw = in.Tb2w*vFnative; vFw = in.Tb2w*vFnative;

View file

@ -50,7 +50,7 @@ INCLUDES
namespace JSBSim { 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; static const char *IdHdr = ID_ATMOSPHERE;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -111,20 +111,21 @@ bool FGAtmosphere::Run(bool Holding)
void FGAtmosphere::Calculate(double altitude) void FGAtmosphere::Calculate(double altitude)
{ {
FGPropertyNode* node = PropertyManager->GetNode();
if (!PropertyManager->HasNode("atmosphere/override/temperature")) if (!PropertyManager->HasNode("atmosphere/override/temperature"))
Temperature = GetTemperature(altitude); Temperature = GetTemperature(altitude);
else else
Temperature = PropertyManager->getDoubleValue("atmosphere/override/temperature"); Temperature = node->GetDouble("atmosphere/override/temperature");
if (!PropertyManager->HasNode("atmosphere/override/pressure")) if (!PropertyManager->HasNode("atmosphere/override/pressure"))
Pressure = GetPressure(altitude); Pressure = GetPressure(altitude);
else else
Pressure = PropertyManager->getDoubleValue("atmosphere/override/pressure"); Pressure = node->GetDouble("atmosphere/override/pressure");
if (!PropertyManager->HasNode("atmosphere/override/density")) if (!PropertyManager->HasNode("atmosphere/override/density"))
Density = Pressure/(Reng*Temperature); Density = Pressure/(Reng*Temperature);
else else
Density = PropertyManager->getDoubleValue("atmosphere/override/density"); Density = node->GetDouble("atmosphere/override/density");
Soundspeed = sqrt(SHRatio*Reng*(Temperature)); Soundspeed = sqrt(SHRatio*Reng*(Temperature));
PressureAltitude = altitude; PressureAltitude = altitude;

View file

@ -50,7 +50,7 @@ using namespace std;
namespace JSBSim { 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; static const char *IdHdr = ID_AUXILIARY;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -76,7 +76,7 @@ FGAuxiliary::FGAuxiliary(FGFDMExec* fdmex) : FGModel(fdmex)
seconds_in_day = 0.0; seconds_in_day = 0.0;
hoverbmac = hoverbcg = 0.0; hoverbmac = hoverbcg = 0.0;
Re = 0.0; Re = 0.0;
Nz = 0.0; Nz = Ny = 0.0;
lon_relative_position = lat_relative_position = relative_position = 0.0; lon_relative_position = lat_relative_position = relative_position = 0.0;
vPilotAccel.InitMatrix(); vPilotAccel.InitMatrix();
@ -111,7 +111,7 @@ bool FGAuxiliary::InitModel(void)
seconds_in_day = 0.0; seconds_in_day = 0.0;
hoverbmac = hoverbcg = 0.0; hoverbmac = hoverbcg = 0.0;
Re = 0.0; Re = 0.0;
Nz = 0.0; Nz = Ny = 0.0;
lon_relative_position = lat_relative_position = relative_position = 0.0; lon_relative_position = lat_relative_position = relative_position = 0.0;
vPilotAccel.InitMatrix(); vPilotAccel.InitMatrix();
@ -228,6 +228,7 @@ bool FGAuxiliary::Run(bool Holding)
vNcg = in.vBodyAccel/in.SLGravity; vNcg = in.vBodyAccel/in.SLGravity;
// Nz is Acceleration in "g's", along normal axis (-Z body axis) // Nz is Acceleration in "g's", along normal axis (-Z body axis)
Nz = -vNcg(eZ); Nz = -vNcg(eZ);
Ny = vNcg(eY);
vPilotAccel = in.vBodyAccel + in.vPQRdot * in.ToEyePt; vPilotAccel = in.vBodyAccel + in.vPQRdot * in.ToEyePt;
vPilotAccel += in.vPQR * (in.vPQR * 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-y-norm", this, eY, (PMF)&FGAuxiliary::GetNpilot);
PropertyManager->Tie("accelerations/n-pilot-z-norm", this, eZ, (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/Nz", this, &FGAuxiliary::GetNz);
PropertyManager->Tie("accelerations/Ny", this, &FGAuxiliary::GetNy);
PropertyManager->Tie("forces/load-factor", this, &FGAuxiliary::GetNlf); PropertyManager->Tie("forces/load-factor", this, &FGAuxiliary::GetNlf);
/* PropertyManager->Tie("atmosphere/headwind-fps", this, &FGAuxiliary::GetHeadWind, true); /* PropertyManager->Tie("atmosphere/headwind-fps", this, &FGAuxiliary::GetHeadWind, true);
PropertyManager->Tie("atmosphere/crosswind-fps", this, &FGAuxiliary::GetCrossWind, true); */ PropertyManager->Tie("atmosphere/crosswind-fps", this, &FGAuxiliary::GetCrossWind, true); */

View file

@ -48,7 +48,7 @@ INCLUDES
DEFINITIONS 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 FORWARD DECLARATIONS
@ -99,7 +99,7 @@ CLASS DOCUMENTATION
to the JSBSim vPQRdot vector, and the w parameter is equivalent to vPQR. to the JSBSim vPQRdot vector, and the w parameter is equivalent to vPQR.
@author Tony Peden, Jon Berndt @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. */ /** The vertical acceleration in g's of the aircraft center of gravity. */
double GetNz (void) const { return Nz; } 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; } const FGColumnVector3& GetNwcg(void) const { return vNwcg; }
double GetHOverBCG(void) const { return hoverbcg; } double GetHOverBCG(void) const { return hoverbcg; }
@ -312,7 +315,7 @@ private:
double alpha, beta; double alpha, beta;
double adot,bdot; double adot,bdot;
double psigt, gamma; double psigt, gamma;
double Nz; double Nz, Ny;
double seconds_in_day; // seconds since current GMT day began double seconds_in_day; // seconds since current GMT day began
int day_of_year; // GMT day, 1 .. 366 int day_of_year; // GMT day, 1 .. 366

View file

@ -66,7 +66,7 @@ using namespace std;
namespace JSBSim { 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; static const char *IdHdr = ID_FCS;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -541,7 +541,7 @@ bool FGFCS::Load(Element* el, SystemType systype)
interface_property_string = property_element->GetDataLine(); interface_property_string = property_element->GetDataLine();
if (PropertyManager->HasNode(interface_property_string)) { if (PropertyManager->HasNode(interface_property_string)) {
FGPropertyManager* node = PropertyManager->GetNode(interface_property_string); FGPropertyNode* node = PropertyManager->GetNode(interface_property_string);
if (debug_lvl > 0) if (debug_lvl > 0)
cout << " " << "Overriding value for property " << interface_property_string cout << " " << "Overriding value for property " << interface_property_string
<< " (old value: " << node->getDoubleValue() << " new value: " << value << ")" << endl; << " (old value: " << node->getDoubleValue() << " new value: " << value << ")" << endl;
@ -564,7 +564,7 @@ bool FGFCS::Load(Element* el, SystemType systype)
FGFCSChannel* newChannel = 0; FGFCSChannel* newChannel = 0;
string sOnOffProperty = channel_element->GetAttributeValue("execute"); string sOnOffProperty = channel_element->GetAttributeValue("execute");
FGPropertyManager* OnOffPropertyNode = 0; FGPropertyNode* OnOffPropertyNode = 0;
if (sOnOffProperty.length() > 0) { if (sOnOffProperty.length() > 0) {
OnOffPropertyNode = PropertyManager->GetNode(sOnOffProperty); OnOffPropertyNode = PropertyManager->GetNode(sOnOffProperty);
if (OnOffPropertyNode == 0) { if (OnOffPropertyNode == 0) {

View file

@ -44,7 +44,7 @@ INCLUDES
DEFINITIONS 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 FORWARD DECLARATIONS
@ -70,7 +70,7 @@ typedef std::vector <FGFCSComponent*> FCSCompVec;
class FGFCSChannel { class FGFCSChannel {
public: public:
/// Constructor /// Constructor
FGFCSChannel(FGPropertyManager* node=0) : FGFCSChannel(FGPropertyNode* node=0) :
OnOffNode(node) OnOffNode(node)
{ {
} }
@ -120,7 +120,7 @@ public:
private: private:
FCSCompVec FCSComponents; FCSCompVec FCSComponents;
const FGPropertyManager* OnOffNode; FGConstPropertyNode_ptr OnOffNode;
}; };
} }

View file

@ -4,7 +4,7 @@
Author: Anders Gidenstam Author: Anders Gidenstam
Date started: 01/21/2006 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 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 the terms of the GNU Lesser General Public License as published by the Free Software
@ -50,14 +50,14 @@ using std::max;
namespace JSBSim { 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; static const char *IdHdr = ID_GASCELL;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/* Constants. */ /* 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_air = 0.0019186; // [slug/mol]
const double FGGasCell::M_hydrogen = 0.00013841; // [slug/mol] const double FGGasCell::M_hydrogen = 0.00013841; // [slug/mol]
const double FGGasCell::M_helium = 0.00027409; // [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"; property_name = base_property_name + "/max_volume-ft3";
PropertyManager->Tie( property_name.c_str(), &MaxVolume, false ); 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"; property_name = base_property_name + "/temp-R";
PropertyManager->Tie( property_name.c_str(), &Temperature, false ); PropertyManager->Tie( property_name.c_str(), &Temperature, false );
property_name = base_property_name + "/pressure-psf"; property_name = base_property_name + "/pressure-psf";
@ -325,7 +325,7 @@ void FGGasCell::Calculate(double dt)
// FixMe: CellHeight should depend on current volume. // FixMe: CellHeight should depend on current volume.
const double CellHeight = 2 * Zradius + Zwidth; // [ft] const double CellHeight = 2 * Zradius + Zwidth; // [ft]
const double GasMass = Contents * M_gas(); // [slug] 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 GasDensity = GasMass / GasVolume;
const double DeltaPressure = const double DeltaPressure =
Pressure + CellHeight * g * (AirDensity - GasDensity) - AirPressure; Pressure + CellHeight * g * (AirDensity - GasDensity) - AirPressure;
@ -468,7 +468,7 @@ void FGGasCell::Debug(int from)
cout << " Initial pressure: " << Pressure << " lbs/ft2" << endl; cout << " Initial pressure: " << Pressure << " lbs/ft2" << endl;
cout << " Initial volume: " << Volume << " ft3" << endl; cout << " Initial volume: " << Volume << " ft3" << endl;
cout << " Initial mass: " << GetMass() << " slug mass" << endl; cout << " Initial mass: " << GetMass() << " slug mass" << endl;
cout << " Initial weight: " << GetMass()*lbtoslug << " lbs force" << cout << " Initial weight: " << GetMass()*slugtolb << " lbs force" <<
endl; endl;
cout << " Heat transfer: " << endl; cout << " Heat transfer: " << endl;
} }
@ -485,7 +485,7 @@ void FGGasCell::Debug(int from)
cout << " Pressure: " << Pressure << " lbs/ft2" << endl; cout << " Pressure: " << Pressure << " lbs/ft2" << endl;
cout << " Volume: " << Volume << " ft3" << endl; cout << " Volume: " << Volume << " ft3" << endl;
cout << " Mass: " << GetMass() << " slug mass" << 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 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"; property_name = base_property_name + "/max_volume-ft3";
PropertyManager->Tie( property_name, &MaxVolume, false ); PropertyManager->Tie( property_name, &MaxVolume, false );
PropertyManager->SetWritable( property_name, false ); PropertyManager->GetNode()->SetWritable( property_name, false );
property_name = base_property_name + "/temp-R"; property_name = base_property_name + "/temp-R";
PropertyManager->Tie( property_name, &Temperature, false ); PropertyManager->Tie( property_name, &Temperature, false );
@ -820,7 +820,7 @@ void FGBallonet::Debug(int from)
cout << " Initial pressure: " << Pressure << " lbs/ft2" << endl; cout << " Initial pressure: " << Pressure << " lbs/ft2" << endl;
cout << " Initial volume: " << Volume << " ft3" << endl; cout << " Initial volume: " << Volume << " ft3" << endl;
cout << " Initial mass: " << GetMass() << " slug mass" << endl; cout << " Initial mass: " << GetMass() << " slug mass" << endl;
cout << " Initial weight: " << GetMass()*lbtoslug << cout << " Initial weight: " << GetMass()*slugtolb <<
" lbs force" << endl; " lbs force" << endl;
cout << " Heat transfer: " << endl; cout << " Heat transfer: " << endl;
} }
@ -838,7 +838,7 @@ void FGBallonet::Debug(int from)
cout << " Pressure: " << Pressure << " lbs/ft2" << endl; cout << " Pressure: " << Pressure << " lbs/ft2" << endl;
cout << " Volume: " << Volume << " ft3" << endl; cout << " Volume: " << Volume << " ft3" << endl;
cout << " Mass: " << GetMass() << " slug mass" << 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 if (debug_lvl & 16) { // Sanity checking
} }

View file

@ -4,7 +4,7 @@
Author: Anders Gidenstam Author: Anders Gidenstam
Date started: 01/21/2006 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 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 the terms of the GNU Lesser General Public License as published by the Free Software
@ -50,7 +50,7 @@ INCLUDES
DEFINITIONS 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 FORWARD DECLARATIONS
@ -238,7 +238,7 @@ private:
std::string type; std::string type;
int CellNum; int CellNum;
// Structural constants // Structural constants
double MaxVolume; // [ft^2] double MaxVolume; // [ft^3]
double MaxOverpressure; // [lbs/ft^2] double MaxOverpressure; // [lbs/ft^2]
FGColumnVector3 vXYZ; // [in] FGColumnVector3 vXYZ; // [in]
double Xradius, Yradius, Zradius; // [ft] double Xradius, Yradius, Zradius; // [ft]
@ -251,8 +251,8 @@ private:
// Variables // Variables
double Pressure; // [lbs/ft^2] double Pressure; // [lbs/ft^2]
double Contents; // [mol] double Contents; // [mol]
double Volume; // [ft^2] double Volume; // [ft^3]
double dVolumeIdeal; // [ft^2] double dVolumeIdeal; // [ft^3]
double Temperature; // [Rankine] double Temperature; // [Rankine]
double Buoyancy; // [lbs] Note: Gross lift. double Buoyancy; // [lbs] Note: Gross lift.
// Does not include the weight of the gas itself. // Does not include the weight of the gas itself.
@ -344,7 +344,7 @@ public:
private: private:
int CellNum; int CellNum;
// Structural constants // Structural constants
double MaxVolume; // [ft^2] double MaxVolume; // [ft^3]
double MaxOverpressure; // [lbs/ft^2] double MaxOverpressure; // [lbs/ft^2]
FGColumnVector3 vXYZ; // [in] FGColumnVector3 vXYZ; // [in]
double Xradius, Yradius, Zradius; // [ft] double Xradius, Yradius, Zradius; // [ft]
@ -357,8 +357,8 @@ private:
// Variables // Variables
double Pressure; // [lbs/ft^2] double Pressure; // [lbs/ft^2]
double Contents; // [mol] double Contents; // [mol]
double Volume; // [ft^2] double Volume; // [ft^3]
double dVolumeIdeal; // [ft^2] double dVolumeIdeal; // [ft^3]
double dU; // [lbs ft / sec] double dU; // [lbs ft / sec]
double Temperature; // [Rankine] double Temperature; // [Rankine]
double ValveOpen; // 0 <= ValveOpen <= 1 (or higher). double ValveOpen; // 0 <= ValveOpen <= 1 (or higher).

View file

@ -53,7 +53,7 @@ using namespace std;
namespace JSBSim { 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; static const char *IdHdr = ID_INPUT;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -94,7 +94,7 @@ bool FGInput::Run(bool Holding)
string line, token; string line, token;
size_t start=0, string_start=0, string_end=0; size_t start=0, string_start=0, string_end=0;
double value=0; double value=0;
FGPropertyManager* node=0; FGPropertyNode* node=0;
if (FGModel::Run(Holding)) return true; // fast exit if nothing to do if (FGModel::Run(Holding)) return true; // fast exit if nothing to do
if (port == 0) return false; // Do nothing here if port not defined if (port == 0) return false; // Do nothing here if port not defined

View file

@ -61,7 +61,7 @@ DEFINITIONS
GLOBAL DATA 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; static const char *IdHdr = ID_LGEAR;
// Body To Structural (body frame is rotated 180 deg about Y and lengths are given in // 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(); ResetReporting();
} }
}
else if (gearPos < 0.01) { // Gear UP } else if (gearPos < 0.01) { // Gear UP
WOW = false; WOW = false;
vWhlVelVec.InitMatrix(); vWhlVelVec.InitMatrix();
} }

View file

@ -49,7 +49,7 @@ using namespace std;
namespace JSBSim { 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; 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, bool FGOutput::Load(int subSystems, std::string protocol, std::string type,
std::string port, std::string name, double outRate, std::string port, std::string name, double outRate,
std::vector<FGPropertyManager *> & outputProperties) std::vector<FGPropertyNode_ptr> & outputProperties)
{ {
unsigned int idx = OutputTypes.size(); unsigned int idx = OutputTypes.size();
FGOutputType* Output = 0; FGOutputType* Output = 0;

View file

@ -48,7 +48,7 @@ INCLUDES
DEFINITIONS 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 FORWARD DECLARATIONS
@ -122,7 +122,7 @@ CLASS DOCUMENTATION
The class FGOutput is the manager of the outputs requested by the user. It 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. 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. */ @result true if the execution succeeded. */
bool Load(int subSystems, std::string protocol, std::string type, bool Load(int subSystems, std::string protocol, std::string type,
std::string port, std::string name, double outRate, std::string port, std::string name, double outRate,
std::vector<FGPropertyManager *> & outputProperties); std::vector<FGPropertyNode_ptr> & outputProperties);
/** Get the name identifier to which the output will be directed. /** Get the name identifier to which the output will be directed.
@param idx ID of the output instance from which the name identifier must @param idx ID of the output instance from which the name identifier must
be obtained be obtained

View file

@ -77,7 +77,7 @@ using namespace std;
namespace JSBSim { 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; 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/theta-rad", this, (int)eTht, (PMF)&FGPropagate::GetEuler);
PropertyManager->Tie("attitude/psi-rad", this, (int)ePsi, (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/roll-rad", this, (int)ePhi, (PMF)&FGPropagate::GetEuler);
PropertyManager->Tie("attitude/pitch-rad", this, (int)eTht, (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); PropertyManager->Tie("attitude/heading-true-rad", this, (int)ePsi, (PMF)&FGPropagate::GetEuler);

View file

@ -49,7 +49,7 @@ INCLUDES
DEFINITIONS 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 FORWARD DECLARATIONS
@ -93,7 +93,7 @@ CLASS DOCUMENTATION
@endcode @endcode
@author Jon S. Berndt, Mathias Froehlich, Bertrand Coconnier @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(); } 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.
Retrieves a body frame velocity component. The velocity returned is Retrieves a body frame velocity component. The velocity returned is
extracted from the vUVW vector (an FGColumnVector). The vector for the 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); } 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 a vehicle Euler angle component.
Retrieves the cosine of an Euler angle (Phi, Theta, or Psi) from the Retrieves the cosine of an Euler angle (Phi, Theta, or Psi) from the
quaternion that stores the vehicle orientation relative to the Local frame. quaternion that stores the vehicle orientation relative to the Local frame.

View file

@ -43,7 +43,7 @@ using namespace std;
namespace JSBSim { 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; 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"); Element* ratelim_el = element->FindElement("rate_limit");
while ( ratelim_el ) { while ( ratelim_el ) {
rate_limited = true; rate_limited = true;
FGPropertyManager* rate_limit_prop=0; FGPropertyNode* rate_limit_prop=0;
string rate_limit_str = ratelim_el->GetDataLine(); string rate_limit_str = ratelim_el->GetDataLine();
trim(rate_limit_str); trim(rate_limit_str);
if (is_number(rate_limit_str)) { if (is_number(rate_limit_str)) {
rate_limit = fabs(element->FindElementValueAsNumber("rate_limit")); rate_limit = fabs(element->FindElementValueAsNumber("rate_limit"));
} else { } else {
if (rate_limit_str[0] == '-') rate_limit_str.erase(0,1); if (rate_limit_str[0] == '-') rate_limit_str.erase(0,1);
rate_limit_prop = PropertyManager->GetNode(rate_limit_str, true); 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") { } else if (sense.substr(0,4) == "decr") {
if (rate_limit_prop != 0) rate_limit_decr_prop = rate_limit_prop; if (rate_limit_prop != 0) rate_limit_decr_prop = rate_limit_prop;
else rate_limit_decr = -rate_limit; else rate_limit_decr = -rate_limit;
} }
} else { } else {
rate_limit_incr = rate_limit; rate_limit_incr = rate_limit;
rate_limit_decr = -rate_limit; rate_limit_decr = -rate_limit;
@ -157,7 +157,8 @@ bool FGActuator::Run(void )
Output = PreviousOutput; Output = PreviousOutput;
} else { } else {
if (lag != 0.0) Lag(); // models actuator lag 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 (deadband_width != 0.0) Deadband();
if (hysteresis_width != 0.0) Hysteresis(); if (hysteresis_width != 0.0) Hysteresis();
if (bias != 0.0) Bias(); // models a finite bias if (bias != 0.0) Bias(); // models a finite bias

View file

@ -44,7 +44,7 @@ INCLUDES
DEFINITIONS 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 FORWARD DECLARATIONS
@ -120,7 +120,7 @@ Example:
@endcode @endcode
@author Jon S. Berndt @author Jon S. Berndt
@version $Revision: 1.14 $ @version $Revision: 1.15 $
*/ */
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -160,8 +160,8 @@ private:
double rate_limit; double rate_limit;
double rate_limit_incr; double rate_limit_incr;
double rate_limit_decr; double rate_limit_decr;
FGPropertyManager* rate_limit_incr_prop; FGPropertyNode_ptr rate_limit_incr_prop;
FGPropertyManager* rate_limit_decr_prop; FGPropertyNode_ptr rate_limit_decr_prop;
double hysteresis_width; double hysteresis_width;
double deadband_width; double deadband_width;
double lag; double lag;

View file

@ -43,7 +43,7 @@ INCLUDES
DEFINITIONS 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 FORWARD DECLARATIONS
@ -53,7 +53,6 @@ namespace JSBSim {
class FGFCS; class FGFCS;
class Element; class Element;
class FGPropertyManager;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DOCUMENTATION CLASS DOCUMENTATION
@ -80,7 +79,7 @@ CLASS DOCUMENTATION
produce no output. For example, say that the width value is 2.0. If the 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. input is between -1.0 and +1.0, the output will be zero.
@author Jon S. Berndt @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: private:
double width; double width;
double gain; double gain;
FGPropertyManager* WidthPropertyNode; FGPropertyNode_ptr WidthPropertyNode;
double WidthPropertySign; double WidthPropertySign;
void Debug(int from); void Debug(int from);

View file

@ -48,7 +48,7 @@ using namespace std;
namespace JSBSim { 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; static const char *IdHdr = ID_FCSCOMPONENT;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -121,7 +121,7 @@ FGFCSComponent::FGFCSComponent(FGFCS* _fcs, Element* element) : fcs(_fcs)
} else { } else {
InputSigns.push_back( 1.0); InputSigns.push_back( 1.0);
} }
FGPropertyManager* node = 0L; FGPropertyNode* node = 0L;
if (PropertyManager->HasNode(input)) { if (PropertyManager->HasNode(input)) {
node = PropertyManager->GetNode(input); node = PropertyManager->GetNode(input);
InputNodes.push_back(new FGPropertyValue( node )); InputNodes.push_back(new FGPropertyValue( node ));
@ -138,7 +138,7 @@ FGFCSComponent::FGFCSComponent(FGFCS* _fcs, Element* element) : fcs(_fcs)
while (out_elem) { while (out_elem) {
IsOutput = true; IsOutput = true;
string output_node_name = out_elem->GetDataLine(); 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); OutputNodes.push_back(OutputNode);
if (!OutputNode) { if (!OutputNode) {
cerr << endl << " Unable to process property: " << output_node_name << endl; cerr << endl << " Unable to process property: " << output_node_name << endl;

View file

@ -46,7 +46,7 @@ INCLUDES
DEFINITIONS 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 FORWARD DECLARATIONS
@ -55,7 +55,6 @@ FORWARD DECLARATIONS
namespace JSBSim { namespace JSBSim {
class FGFCS; class FGFCS;
class FGPropertyManager;
class Element; class Element;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -81,7 +80,7 @@ CLASS DOCUMENTATION
- FGActuator - FGActuator
@author Jon S. Berndt @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 @see Documentation for the FGFCS class, and for the configuration file class
*/ */
@ -107,10 +106,10 @@ public:
protected: protected:
FGFCS* fcs; FGFCS* fcs;
FGPropertyManager* PropertyManager; FGPropertyManager* PropertyManager;
FGPropertyManager* treenode; FGPropertyNode_ptr treenode;
std::vector <FGPropertyManager*> OutputNodes; std::vector <FGPropertyNode_ptr> OutputNodes;
FGPropertyManager* ClipMinPropertyNode; FGPropertyNode_ptr ClipMinPropertyNode;
FGPropertyManager* ClipMaxPropertyNode; FGPropertyNode_ptr ClipMaxPropertyNode;
std::vector <FGPropertyValue*> InputNodes; std::vector <FGPropertyValue*> InputNodes;
std::vector <std::string> InputNames; std::vector <std::string> InputNames;
std::vector <float> InputSigns; std::vector <float> InputSigns;

View file

@ -43,7 +43,7 @@ INCLUDES
DEFINITIONS 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 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. output, such as the elevator, or speedbrake, etc.
@author Jon S. Berndt @author Jon S. Berndt
@version $Revision: 1.12 $ @version $Revision: 1.13 $
*/ */
@ -263,8 +263,8 @@ private:
double PreviousInput2; double PreviousInput2;
double PreviousOutput1; double PreviousOutput1;
double PreviousOutput2; double PreviousOutput2;
FGPropertyManager* Trigger; FGPropertyNode_ptr Trigger;
FGPropertyManager* PropertyNode[7]; FGPropertyNode_ptr PropertyNode[7];
void CalculateDynamicFilters(void); void CalculateDynamicFilters(void);
void ReadFilterCoefficients(Element* el, int index); void ReadFilterCoefficients(Element* el, int index);
bool DynamicFilter; bool DynamicFilter;

View file

@ -44,7 +44,7 @@ INCLUDES
DEFINITIONS 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 FORWARD DECLARATIONS
@ -208,7 +208,7 @@ CLASS DOCUMENTATION
@endcode @endcode
@author Jon S. Berndt @author Jon S. Berndt
@version $Revision: 1.14 $ @version $Revision: 1.15 $
*/ */
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -225,7 +225,7 @@ public:
private: private:
FGTable* Table; FGTable* Table;
FGPropertyManager* GainPropertyNode; FGPropertyNode_ptr GainPropertyNode;
double GainPropertySign; double GainPropertySign;
double Gain; double Gain;
double InMin, InMax, OutMin, OutMax; double InMin, InMax, OutMin, OutMax;

View file

@ -44,7 +44,7 @@ using namespace std;
namespace JSBSim { 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; static const char *IdHdr = ID_PID;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -135,6 +135,14 @@ FGPID::FGPID(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element)
} }
FGFCSComponent::bind(); 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); Debug(0);
} }

View file

@ -44,7 +44,7 @@ INCLUDES
DEFINITIONS 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 FORWARD DECLARATIONS
@ -116,7 +116,7 @@ For example,
</pre> </pre>
@author Jon S. Berndt @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. /// These define the indices use to select the various integrators.
enum eIntegrateType {eNone = 0, eRectEuler, eTrapezoidal, eAdamsBashforth2, eAdamsBashforth3}; enum eIntegrateType {eNone = 0, eRectEuler, eTrapezoidal, eAdamsBashforth2, eAdamsBashforth3};
void SetInitialOutput(double val) {
I_out_total = val;
Output = val;
}
private: private:
double Kp, Ki, Kd; double Kp, Ki, Kd;
double I_out_total; double I_out_total;
@ -147,11 +152,11 @@ private:
eIntegrateType IntType; eIntegrateType IntType;
FGPropertyManager *Trigger; FGPropertyNode_ptr Trigger;
FGPropertyManager* KpPropertyNode; FGPropertyNode_ptr KpPropertyNode;
FGPropertyManager* KiPropertyNode; FGPropertyNode_ptr KiPropertyNode;
FGPropertyManager* KdPropertyNode; FGPropertyNode_ptr KdPropertyNode;
FGPropertyManager* ProcessVariableDot; FGPropertyNode_ptr ProcessVariableDot;
void Debug(int from); void Debug(int from);
}; };

View file

@ -44,7 +44,7 @@ INCLUDES
DEFINITIONS 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 FORWARD DECLARATIONS
@ -76,7 +76,7 @@ Syntax:
<drift_rate> number </drift_rate> <drift_rate> number </drift_rate>
<gain> number </gain> <gain> number </gain>
<bias> number </bias> <bias> number </bias>
<delay> number < /delay> <delay [type="time|frames"]> number < /delay>
</sensor> </sensor>
@endcode @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. the number of frames to delay the output signal.
@author Jon S. Berndt @author Jon S. Berndt
@version $Revision: 1.21 $ @version $Revision: 1.22 $
*/ */
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -48,7 +48,7 @@ INCLUDES
DEFINITIONS 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 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. whatever value fcs/roll-ap-error-summer is.
@author Jon S. Berndt @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 { } else {
sign = 1.0; sign = 1.0;
} }
FGPropertyManager *node = propMan->GetNode(value, false); FGPropertyNode *node = propMan->GetNode(value, false);
if (node) { if (node) {
OutputProp = new FGPropertyValue(node); OutputProp = new FGPropertyValue(node);
} else { } else {

View file

@ -47,7 +47,7 @@ using namespace std;
namespace JSBSim { 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; static const char *IdHdr = ID_ROCKET;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -250,8 +250,8 @@ string FGRocket::GetEngineLabels(const string& delimiter)
{ {
std::ostringstream buf; std::ostringstream buf;
buf << Name << " Total Impulse (engine " << EngineNumber << " in psf)" << delimiter buf << Name << " Total Impulse (engine " << EngineNumber << " in lbf)" << delimiter
<< Name << " Total Vacuum Impulse (engine " << EngineNumber << " in psf)" << delimiter << Name << " Total Vacuum Impulse (engine " << EngineNumber << " in lbf)" << delimiter
<< Thruster->GetThrusterLabels(EngineNumber, delimiter); << Thruster->GetThrusterLabels(EngineNumber, delimiter);
return buf.str(); return buf.str();

View file

@ -48,7 +48,7 @@ INCLUDES
DEFINITIONS 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 FORWARD DECLARATIONS
@ -230,7 +230,7 @@ CLASS DOCUMENTATION
</dl> </dl>
@author Thomas Kreitler @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; double MaximalRPM;
int ExternalRPM; int ExternalRPM;
int RPMdefinition; int RPMdefinition;
FGPropertyManager* ExtRPMsource; FGPropertyNode_ptr ExtRPMsource;
double SourceGearRatio; double SourceGearRatio;
// 'real' rotor parameters // 'real' rotor parameters

View file

@ -47,7 +47,7 @@ using namespace std;
namespace JSBSim { 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; static const char *IdHdr = ID_TANK;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -118,6 +118,13 @@ FGTank::FGTank(FGFDMExec* exec, Element* el, int tank_number)
Capacity = 0.00001; Capacity = 0.00001;
Contents = 0.0; 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 PctFull = 100.0*Contents/Capacity; // percent full; 0 to 100.0
// Check whether this is a solid propellant "tank". Initialize it if true. // Check whether this is a solid propellant "tank". Initialize it if true.