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/FGSimplexTrim.h
initialization/FGTrimmer.h
initialization/FGLinearization.h
input_output/FGXMLParse.h
input_output/FGXMLFileRead.h
input_output/FGPropertyManager.h
@ -100,6 +101,7 @@ set(SOURCES
initialization/FGTrimAxis.cpp
initialization/FGSimplexTrim.cpp
initialization/FGTrimmer.cpp
initialization/FGLinearization.cpp
input_output/FGGroundCallback.cpp
input_output/FGPropertyManager.cpp
input_output/FGScript.cpp

View file

@ -65,6 +65,7 @@ INCLUDES
#include "models/FGOutput.h"
#include "initialization/FGInitialCondition.h"
#include "initialization/FGSimplexTrim.h"
#include "initialization/FGLinearization.h"
#include "input_output/FGPropertyManager.h"
#include "input_output/FGScript.h"
@ -72,7 +73,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGFDMExec.cpp,v 1.145 2012/11/11 18:43:07 bcoconni Exp $";
static const char *IdSrc = "$Id: FGFDMExec.cpp,v 1.148 2013/06/10 01:46:27 jberndt Exp $";
static const char *IdHdr = ID_FDMEXEC;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -133,7 +134,8 @@ FGFDMExec::FGFDMExec(FGPropertyManager* root, unsigned int* fdmctr) : Root(root)
// Prepare FDMctr for the next child FDM id
(*FDMctr)++; // instance. "child" instances are loaded last.
instance = Root->GetNode("/fdm/jsbsim",IdFDM,true);
FGPropertyNode* instanceRoot = Root->GetNode("/fdm/jsbsim",IdFDM,true);
instance = new FGPropertyManager(instanceRoot);
Debug(0);
// this is to catch errors in binding member functions to the property tree.
try {
@ -153,6 +155,7 @@ FGFDMExec::FGFDMExec(FGPropertyManager* root, unsigned int* fdmctr) : Root(root)
// instance->Tie("simulation/do_trim_analysis", this, (iPMF)0, &FGFDMExec::DoTrimAnalysis, false);
instance->Tie("simulation/do_simple_trim", this, (iPMF)0, &FGFDMExec::DoTrim, false);
instance->Tie("simulation/do_simplex_trim", this, (iPMF)0, &FGFDMExec::DoSimplexTrim);
instance->Tie("simulation/do_linearization", this, (iPMF)0, &FGFDMExec::DoLinearization);
instance->Tie("simulation/reset", this, (iPMF)0, &FGFDMExec::ResetToInitialConditions, false);
instance->Tie("simulation/randomseed", this, (iPMF)0, &FGFDMExec::SRand, false);
instance->Tie("simulation/terminate", (int *)&Terminate);
@ -161,56 +164,46 @@ FGFDMExec::FGFDMExec(FGPropertyManager* root, unsigned int* fdmctr) : Root(root)
instance->Tie("simulation/frame", (int *)&Frame, false);
// simplex trim properties
instance->SetDouble("trim/solver/rtol",0.0001);
instance->SetDouble("trim/solver/speed",2);
instance->SetDouble("trim/solver/abstol",0.001);
instance->SetDouble("trim/solver/iterMax",2000);
instance->SetInt("trim/solver/debugLevel",0);
instance->SetDouble("trim/solver/random",0);
instance->SetBool("trim/solver/showSimplex",false);
// instance->SetBool("trim/solver/showConvergence",true);
instance->SetBool("trim/solver/pause",false);
instanceRoot->SetDouble("trim/solver/rtol",0.0001);
instanceRoot->SetDouble("trim/solver/speed",2);
instanceRoot->SetDouble("trim/solver/abstol",0.001);
instanceRoot->SetDouble("trim/solver/iterMax",2000);
instanceRoot->SetInt("trim/solver/debugLevel",0);
instanceRoot->SetDouble("trim/solver/random",0);
instanceRoot->SetBool("trim/solver/showSimplex",false);
instanceRoot->SetBool("trim/solver/showConvergence",false);
instanceRoot->SetBool("trim/solver/pause",false);
instanceRoot->SetBool("trim/solver/variablePropPitch",false);
instance->SetDouble("trim/solver/throttleGuess",0.50);
instance->SetDouble("trim/solver/throttleMin",0.0);
instance->SetDouble("trim/solver/throttleMax",1.0);
// instance->SetDouble("trim/solver/throttleInitialStepSize",0.1);
instance->SetDouble("trim/solver/throttleStep",0.1);
instanceRoot->SetDouble("trim/solver/throttleGuess",0.50);
instanceRoot->SetDouble("trim/solver/throttleMin",0.0);
instanceRoot->SetDouble("trim/solver/throttleMax",1.0);
instanceRoot->SetDouble("trim/solver/throttleStep",0.1);
instance->SetDouble("trim/solver/aileronGuess",0);
instance->SetDouble("trim/solver/aileronMin",-1.00);
instance->SetDouble("trim/solver/aileronMax",1.00);
// instance->SetDouble("trim/solver/aileronInitialStepSize",0.1);
instance->SetDouble("trim/solver/aileronStep",0.1);
instanceRoot->SetDouble("trim/solver/aileronGuess",0);
instanceRoot->SetDouble("trim/solver/aileronMin",-1.00);
instanceRoot->SetDouble("trim/solver/aileronMax",1.00);
instanceRoot->SetDouble("trim/solver/aileronStep",0.1);
instance->SetDouble("trim/solver/rudderGuess",0);
instance->SetDouble("trim/solver/rudderMin",-1.00);
instance->SetDouble("trim/solver/rudderMax",1.00);
// instance->SetDouble("trim/solver/rudderInitialStepSize",0.1);
instance->SetDouble("trim/solver/rudderStep",0.1);
instanceRoot->SetDouble("trim/solver/rudderGuess",0);
instanceRoot->SetDouble("trim/solver/rudderMin",-1.00);
instanceRoot->SetDouble("trim/solver/rudderMax",1.00);
instanceRoot->SetDouble("trim/solver/rudderStep",0.1);
instance->SetDouble("trim/solver/elevatorGuess",-0.1);
instance->SetDouble("trim/solver/elevatorMin",-1.0);
instance->SetDouble("trim/solver/elevatorMax",1.0);
// instance->SetDouble("trim/solver/elevatorInitialStepSize",0.1);
instance->SetDouble("trim/solver/elevatorStep",0.1);
instanceRoot->SetDouble("trim/solver/elevatorGuess",-0.1);
instanceRoot->SetDouble("trim/solver/elevatorMin",-1.0);
instanceRoot->SetDouble("trim/solver/elevatorMax",1.0);
instanceRoot->SetDouble("trim/solver/elevatorStep",0.1);
instance->SetDouble("trim/solver/alphaGuess",0.05);
instance->SetDouble("trim/solver/alphaMin",-0.1);
instance->SetDouble("trim/solver/alphaMax",.18);
// instance->SetDouble("trim/solver/alphaInitialStepSize",0.1);
instance->SetDouble("trim/solver/alphaStep",0.05);
instanceRoot->SetDouble("trim/solver/alphaGuess",0.05);
instanceRoot->SetDouble("trim/solver/alphaMin",-0.1);
instanceRoot->SetDouble("trim/solver/alphaMax",.18);
instanceRoot->SetDouble("trim/solver/alphaStep",0.05);
instance->SetDouble("trim/solver/betaGuess",0);
instance->SetDouble("trim/solver/betaMin",-0.05);
instance->SetDouble("trim/solver/betaMax",0.05);
// instance->SetDouble("trim/solver/betaInitialStepSize",0.1);
instance->SetDouble("trim/solver/betaStep",0.05);
instance->SetBool("trim/solver/showConvergeStatus",true);
// instance->SetBool("trim/solver/pause",true);
instance->SetBool("trim/solver/variablePropPitch",false);
// instance->SetBool("trim/solver/debugLevel",0);
instanceRoot->SetDouble("trim/solver/betaGuess",0);
instanceRoot->SetDouble("trim/solver/betaMin",-0.1);
instanceRoot->SetDouble("trim/solver/betaMax",0.1);
instanceRoot->SetDouble("trim/solver/betaStep",0.0001);
Constructing = false;
}
@ -223,6 +216,8 @@ FGFDMExec::~FGFDMExec()
Unbind();
DeAllocate();
delete instance;
if (IdFDM == 0) { // Meaning this is no child FDM
if(Root != 0) {
if(StandAlone)
@ -922,7 +917,7 @@ bool FGFDMExec::LoadModel(const string& model, bool addModelToPath)
if (result) {
struct PropertyCatalogStructure masterPCS;
masterPCS.base_string = "";
masterPCS.node = (FGPropertyManager*)Root;
masterPCS.node = Root->GetNode();
BuildPropertyCatalog(&masterPCS);
}
@ -944,6 +939,7 @@ void FGFDMExec::BuildPropertyCatalog(struct PropertyCatalogStructure* pcs)
int node_idx = 0;
for (int i=0; i<pcs->node->nChildren(); i++) {
string access="";
pcsNew->base_string = pcs->base_string + "/" + pcs->node->getChild(i)->getName();
node_idx = pcs->node->getChild(i)->getIndex();
if (node_idx != 0) {
@ -953,9 +949,11 @@ void FGFDMExec::BuildPropertyCatalog(struct PropertyCatalogStructure* pcs)
if (pcsNew->base_string.substr(0,12) == string("/fdm/jsbsim/")) {
pcsNew->base_string = pcsNew->base_string.erase(0,12);
}
PropertyCatalog.push_back(pcsNew->base_string);
if (pcs->node->getChild(i)->getAttribute(SGPropertyNode::READ)) access="R";
if (pcs->node->getChild(i)->getAttribute(SGPropertyNode::WRITE)) access+="W";
PropertyCatalog.push_back(pcsNew->base_string+" ("+access+")");
} else {
pcsNew->node = (FGPropertyManager*)pcs->node->getChild(i);
pcsNew->node = (FGPropertyNode*)pcs->node->getChild(i);
BuildPropertyCatalog(pcsNew);
}
}
@ -1193,8 +1191,20 @@ void FGFDMExec::DoSimplexTrim(int mode)
FGSimplexTrim trim(this, (JSBSim::TrimMode)mode);
sim_time = saved_time;
Setsim_time(saved_time);
std::cout << "dT: " << dT << std::endl;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGFDMExec::DoLinearization(int mode)
{
double saved_time;
if (Constructing) return;
saved_time = sim_time;
FGLinearization lin(this,mode);
sim_time = saved_time;
Setsim_time(saved_time);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -56,7 +56,7 @@ INCLUDES
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_FDMEXEC "$Id: FGFDMExec.h,v 1.80 2012/10/25 04:56:57 jberndt Exp $"
#define ID_FDMEXEC "$Id: FGFDMExec.h,v 1.83 2013/06/10 01:46:27 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -179,7 +179,7 @@ CLASS DOCUMENTATION
property actually maps toa function call of DoTrim().
@author Jon S. Berndt
@version $Revision: 1.80 $
@version $Revision: 1.83 $
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -392,13 +392,14 @@ public:
/** Retrieves the value of a property.
@param property the name of the property
@result the value of the specified property */
inline double GetPropertyValue(const string& property) {return instance->GetDouble(property);}
inline double GetPropertyValue(const string& property)
{ return instance->GetNode()->GetDouble(property); }
/** Sets a property value.
@param property the property to be set
@param value the value to set the property to */
inline void SetPropertyValue(const string& property, double value) {
instance->SetDouble(property, value);
instance->GetNode()->SetDouble(property, value);
}
/// Returns the model name.
@ -448,12 +449,13 @@ public:
/** Sets (or overrides) the output filename
@param fname the name of the file to output data to
@return true if successful, false if there is no output specified for the flight model */
bool SetOutputFileName(const string& fname) { return Output->SetOutputName(0, fname); }
bool SetOutputFileName(const int n, const string& fname) { return Output->SetOutputName(n, fname); }
/** Retrieves the current output filename.
@return the name of the output file for the first output specified by the flight model.
@param n index of file
@return the name of the output file for the output specified by the flight model.
If none is specified, the empty string is returned. */
string GetOutputFileName(void) const { return Output->GetOutputName(0); }
string GetOutputFileName(int n) const { return Output->GetOutputName(n); }
/** Executes trimming in the selected mode.
* @param mode Specifies how to trim:
@ -467,6 +469,11 @@ public:
void DoTrim(int mode);
void DoSimplexTrim(int mode);
/** Executes linearization with state-space output
* You must trim first to get an accurate state-space model
*/
void DoLinearization(int mode);
/// Disables data logging to all outputs.
void DisableOutput(void) { Output->Disable(); }
/// Enables data logging to all outputs.
@ -490,7 +497,7 @@ public:
/// Name of the property.
string base_string;
/// The node for the property.
FGPropertyManager *node;
FGPropertyNode_ptr node;
};
/** Builds a catalog of properties.

View file

@ -44,7 +44,7 @@ INCLUDES
namespace JSBSim {
static const char *IdSrc = "$Id: FGJSBBase.cpp,v 1.35 2012/03/25 11:05:36 bcoconni Exp $";
static const char *IdSrc = "$Id: FGJSBBase.cpp,v 1.36 2013/01/25 13:39:11 jberndt Exp $";
static const char *IdHdr = ID_JSBBASE;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -106,7 +106,7 @@ const double FGJSBBase::kgtolb = 2.20462;
const double FGJSBBase::kgtoslug = 0.06852168;
const string FGJSBBase::needed_cfg_version = "2.0";
const string FGJSBBase::JSBSim_version = "1.0 "__DATE__" "__TIME__;
const string FGJSBBase::JSBSim_version = "1.0 " __DATE__ " " __TIME__ ;
std::queue <FGJSBBase::Message> FGJSBBase::Messages;
FGJSBBase::Message FGJSBBase::localMsg;

View file

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

View file

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

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>
*
* FGSimplexTrim.cpp is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* FGSimplexTrim.cpp is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* You should have received a copy of the GNU Lesser General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@ -23,246 +23,95 @@ namespace JSBSim {
FGSimplexTrim::FGSimplexTrim(FGFDMExec * fdm, TrimMode mode)
{
std::clock_t time_start=clock(), time_trimDone, time_linDone;
std::clock_t time_start=clock(), time_trimDone, time_linDone;
// variables
fdm->Setdt(1./120);
FGTrimmer::Constraints constraints;
// variables
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
constraints.velocity = fdm->GetAuxiliary()->GetVt();
constraints.altitude = fdm->GetPropagate()->GetAltitudeASL();
std::string aircraft = fdm->GetAircraft()->GetAircraftName();
double rtol = fdm->GetPropertyManager()->GetDouble("trim/solver/rtol");
double abstol = fdm->GetPropertyManager()->GetDouble("trim/solver/abstol");
double speed = fdm->GetPropertyManager()->GetDouble("trim/solver/speed"); // must be > 1, 2 typical
double random = fdm->GetPropertyManager()->GetDouble("trim/solver/random");
int iterMax = fdm->GetPropertyManager()->GetDouble("trim/solver/iterMax");
bool showConvergeStatus = fdm->GetPropertyManager()->GetBool("trim/solver/showConvergeStatus");
bool pause = fdm->GetPropertyManager()->GetBool("trim/solver/pause");
bool showSimplex = fdm->GetPropertyManager()->GetBool("trim/solver/showSimplex");
bool variablePropPitch = fdm->GetPropertyManager()->GetBool("trim/solver/variablePropPitch");
//int debugLevel = fdm->GetPropertyManager()->GetInt("trim/solver/debugLevel");
// defaults
std::string aircraftName = fdm->GetAircraft()->GetAircraftName();
FGPropertyNode* node = fdm->GetPropertyManager()->GetNode();
double rtol = node->GetDouble("trim/solver/rtol");
double abstol = node->GetDouble("trim/solver/abstol");
double speed = node->GetDouble("trim/solver/speed"); // must be > 1, 2 typical
double random = node->GetDouble("trim/solver/random");
int iterMax = node->GetDouble("trim/solver/iterMax");
bool showConvergence = node->GetBool("trim/solver/showConvergence");
bool pause = node->GetBool("trim/solver/pause");
bool showSimplex = node->GetBool("trim/solver/showSimplex");
bool variablePropPitch = node->GetBool("trim/solver/variablePropPitch");
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
//std::cout << "input ( press enter to accept [default] )\n" << std::endl;
constraints.velocity = fdm->GetIC()->GetVtrueFpsIC();
constraints.altitude = fdm->GetIC()->GetAltitudeASLFtIC();
constraints.gamma = fdm->GetIC()->GetFlightPathAngleRadIC();
constraints.rollRate = 0;
constraints.pitchRate = 0;
constraints.yawRate = tan(phi)*gd*cos(theta)/constraints.velocity;
// load model
std::string aircraftName = fdm->GetAircraft()->GetAircraftName();
//prompt("\tdebug level\t\t",debugLevel);
//fdm->SetDebugLevel(debugLevel);
//std::cout << "model selection" << std::endl;
//while (1)
//{
//prompt("\taircraft\t\t",aircraft);
//prompt("\toutput file name\t",fileName);
//fdm->LoadModel("../aircraft","../engine","../systems",aircraft);
//aircraftName = fdm->GetAircraft()->GetAircraftName();
//if (aircraftName == "")
//{
//std::cout << "\tfailed to load aircraft" << std::endl;
//}
//else
//{
//std::cout << "\tsuccessfully loaded: " << aircraftName << std::endl;
//break;
//}
//}
// Turn on propulsion system
fdm->GetPropulsion()->InitRunning(-1);
// get propulsion pointer to determine type/ etc.
FGEngine * engine0 = fdm->GetPropulsion()->GetEngine(0);
FGThruster * thruster0 = engine0->GetThruster();
// flight conditions
//std::cout << "\nflight conditions: " << std::endl;
//prompt("\taltitude, ft\t\t",constraints.altitude);
//prompt("\tvelocity, ft/s\t\t",constraints.velocity);
//prompt("\tgamma, deg\t\t",constraints.gamma); constraints.gamma = constraints.gamma*M_PI/180;
//double phi = fdm->GetPropagate()->GetEuler(1);
double theta = fdm->GetPropagate()->GetEuler(2);
//double psi = fdm->GetPropagate()->GetEuler(3);
// TODO check that this works properly
constraints.gamma = theta;
//if (thruster0->GetType()==FGThruster::ttPropeller)
//prompt("\tvariable prop pitch?\t\t",variablePropPitch);
// FIXME, enable
constraints.rollRate = fdm->GetIC()->GetPRadpsIC();
constraints.pitchRate = fdm->GetIC()->GetQRadpsIC();
constraints.yawRate = fdm->GetIC()->GetRRadpsIC();
constraints.stabAxisRoll = true; // FIXME, make this an option
// solver properties
// TODO make these options
//std::cout << "\nsolver properties: " << std::endl;
//std::cout << std::scientific;
//prompt("\tshow converge status?\t",showConvergeStatus);
//prompt("\tshow simplex?\t\t",showSimplex);
//prompt("\tpause?\t\t\t",pause);
//prompt("\trelative tolerance\t",rtol);
//prompt("\tabsolute tolerance\t",abstol);
//prompt("\tmax iterations\t\t",iterMax);
//prompt("\tconvergence speed\t",speed);
//prompt("\trandomization ratio\t",random);
//std::cout << std::fixed;
// initial solver state
int n = 6;
std::vector<double> initialGuess(n), lowerBound(n), upperBound(n), initialStepSize(n);
// initial solver state
int n = 6;
std::vector<double> initialGuess(n), lowerBound(n), upperBound(n), initialStepSize(n);
lowerBound[0] = node->GetDouble("trim/solver/throttleMin");
lowerBound[1] = node->GetDouble("trim/solver/elevatorMin");
lowerBound[2] = node->GetDouble("trim/solver/alphaMin");
lowerBound[3] = node->GetDouble("trim/solver/aileronMin");
lowerBound[4] = node->GetDouble("trim/solver/rudderMin");
lowerBound[5] = node->GetDouble("trim/solver/betaMin");
lowerBound[0] = fdm->GetPropertyManager()->GetDouble("trim/solver/throttleMin");
lowerBound[1] = fdm->GetPropertyManager()->GetDouble("trim/solver/elevatorMin");
lowerBound[2] = fdm->GetPropertyManager()->GetDouble("trim/solver/alphaMin");
lowerBound[3] = fdm->GetPropertyManager()->GetDouble("trim/solver/aileronMin");
lowerBound[4] = fdm->GetPropertyManager()->GetDouble("trim/solver/rudderMin");
lowerBound[5] = fdm->GetPropertyManager()->GetDouble("trim/solver/betaMin");
upperBound[0] = node->GetDouble("trim/solver/throttleMax");
upperBound[1] = node->GetDouble("trim/solver/elevatorMax");
upperBound[2] = node->GetDouble("trim/solver/alphaMax");
upperBound[3] = node->GetDouble("trim/solver/aileronMax");
upperBound[4] = node->GetDouble("trim/solver/rudderMax");
upperBound[5] = node->GetDouble("trim/solver/betaMax");
upperBound[0] = fdm->GetPropertyManager()->GetDouble("trim/solver/throttleMax");
upperBound[1] = fdm->GetPropertyManager()->GetDouble("trim/solver/elevatorMax");
upperBound[2] = fdm->GetPropertyManager()->GetDouble("trim/solver/alphaMax");
upperBound[3] = fdm->GetPropertyManager()->GetDouble("trim/solver/aileronMax");
upperBound[4] = fdm->GetPropertyManager()->GetDouble("trim/solver/rudderMax");
upperBound[5] = fdm->GetPropertyManager()->GetDouble("trim/solver/betaMax");
initialStepSize[0] = node->GetDouble("trim/solver/throttleStep");
initialStepSize[1] = node->GetDouble("trim/solver/elevatorStep");
initialStepSize[2] = node->GetDouble("trim/solver/alphaStep");
initialStepSize[3] = node->GetDouble("trim/solver/aileronStep");
initialStepSize[4] = node->GetDouble("trim/solver/rudderStep");
initialStepSize[5] = node->GetDouble("trim/solver/betaStep");
initialStepSize[0] = fdm->GetPropertyManager()->GetDouble("trim/solver/throttleStep");
initialStepSize[1] = fdm->GetPropertyManager()->GetDouble("trim/solver/elevatorStep");
initialStepSize[2] = fdm->GetPropertyManager()->GetDouble("trim/solver/alphaStep");
initialStepSize[3] = fdm->GetPropertyManager()->GetDouble("trim/solver/aileronStep");
initialStepSize[4] = fdm->GetPropertyManager()->GetDouble("trim/solver/rudderStep");
initialStepSize[5] = fdm->GetPropertyManager()->GetDouble("trim/solver/betaStep");
initialGuess[0] = node->GetDouble("trim/solver/throttleGuess");
initialGuess[1] = node->GetDouble("trim/solver/elevatorGuess");
initialGuess[2] = node->GetDouble("trim/solver/alphaGuess");
initialGuess[3] = node->GetDouble("trim/solver/aileronGuess");
initialGuess[4] = node->GetDouble("trim/solver/rudderGuess");
initialGuess[5] = node->GetDouble("trim/solver/betaGuess");
initialGuess[0] = fdm->GetPropertyManager()->GetDouble("trim/solver/throttleGuess");
initialGuess[1] = fdm->GetPropertyManager()->GetDouble("trim/solver/elevatorGuess");
initialGuess[2] = fdm->GetPropertyManager()->GetDouble("trim/solver/alphaGuess");
initialGuess[3] = fdm->GetPropertyManager()->GetDouble("trim/solver/aileronGuess");
initialGuess[4] = fdm->GetPropertyManager()->GetDouble("trim/solver/rudderGuess");
initialGuess[5] = fdm->GetPropertyManager()->GetDouble("trim/solver/betaGuess");
// solve
FGTrimmer * trimmer = new FGTrimmer(fdm, &constraints);
Callback callback(aircraftName, trimmer);
FGNelderMead * solver = NULL;
// solve
FGTrimmer trimmer(fdm, &constraints);
Callback callback(fileName,&trimmer);
FGNelderMead * solver = NULL;
try
{
solver = new FGNelderMead(&trimmer,initialGuess,
lowerBound, upperBound, initialStepSize,iterMax,rtol,
abstol,speed,random,showConvergeStatus,showSimplex,pause,&callback);
while(solver->status()==1) solver->update();
}
catch (const std::runtime_error & e)
{
std::cout << e.what() << std::endl;
//exit(1);
}
solver = new FGNelderMead(trimmer,initialGuess,
lowerBound, upperBound, initialStepSize,iterMax,rtol,
abstol,speed,random,showConvergence,showSimplex,pause,&callback);
while(solver->status()==1) solver->update();
time_trimDone = std::clock();
// output
try
{
trimmer.printSolution(std::cout,solver->getSolution()); // this also loads the solution into the fdm
std::cout << "\nfinal cost: " << std::scientific << std::setw(10) << trimmer.eval(solver->getSolution()) << std::endl;
}
catch(std::runtime_error & e)
{
std::cout << "caught std::runtime error" << std::endl;
std::cout << "exception: " << e.what() << std::endl;
exit(1);
}
time_trimDone = std::clock();
std::cout << "\ntrim computation time: " << (time_trimDone - time_start)/double(CLOCKS_PER_SEC) << "s \n" << std::endl;
//std::cout << "\nsimulating flight to determine trim stability" << std::endl;
//std::cout << "\nt = 5 seconds" << std::endl;
//for (int i=0;i<5*120;i++) fdm->Run();
//trimmer.printState();
//std::cout << "\nt = 10 seconds" << std::endl;
//for (int i=0;i<5*120;i++) fdm->Run();
//trimmer.printState();
std::cout << "\nlinearization: " << std::endl;
FGStateSpace ss(fdm);
ss.x.add(new FGStateSpace::Vt);
ss.x.add(new FGStateSpace::Alpha);
ss.x.add(new FGStateSpace::Theta);
ss.x.add(new FGStateSpace::Q);
if (thruster0->GetType()==FGThruster::ttPropeller)
{
ss.x.add(new FGStateSpace::Rpm0);
if (variablePropPitch) ss.x.add(new FGStateSpace::PropPitch);
int numEngines = fdm->GetPropulsion()->GetNumEngines();
if (numEngines>1) ss.x.add(new FGStateSpace::Rpm1);
if (numEngines>2) ss.x.add(new FGStateSpace::Rpm2);
if (numEngines>3) ss.x.add(new FGStateSpace::Rpm3);
}
ss.x.add(new FGStateSpace::Beta);
ss.x.add(new FGStateSpace::Phi);
ss.x.add(new FGStateSpace::P);
ss.x.add(new FGStateSpace::Psi);
ss.x.add(new FGStateSpace::R);
ss.x.add(new FGStateSpace::Latitude);
ss.x.add(new FGStateSpace::Longitude);
ss.x.add(new FGStateSpace::Alt);
ss.u.add(new FGStateSpace::ThrottleCmd);
ss.u.add(new FGStateSpace::DaCmd);
ss.u.add(new FGStateSpace::DeCmd);
ss.u.add(new FGStateSpace::DrCmd);
// state feedback
ss.y = ss.x;
std::vector< std::vector<double> > A,B,C,D;
std::vector<double> x0 = ss.x.get(), u0 = ss.u.get();
std::vector<double> y0 = x0; // state feedback
std::cout << ss << std::endl;
ss.linearize(x0,u0,y0,A,B,C,D);
int width=10;
std::cout.precision(3);
std::cout
<< std::fixed
<< std::right
<< "\nA=\n" << std::setw(width) << A
<< "\nB=\n" << std::setw(width) << B
<< "\nC=\n" << std::setw(width) << C
<< "\nD=\n" << std::setw(width) << D
<< std::endl;
// write scicoslab file
std::ofstream scicos(std::string(aircraft+"_lin.sce").c_str());
scicos.precision(10);
width=20;
scicos
<< std::scientific
<< aircraft << ".x0=..\n" << std::setw(width) << x0 << ";\n"
<< aircraft << ".u0=..\n" << std::setw(width) << u0 << ";\n"
<< aircraft << ".sys = syslin('c',..\n"
<< std::setw(width) << A << ",..\n"
<< std::setw(width) << B << ",..\n"
<< std::setw(width) << C << ",..\n"
<< std::setw(width) << D << ");\n"
<< aircraft << ".tfm = ss2tf(" << aircraft << ".sys);\n"
<< std::endl;
time_linDone = std::clock();
std::cout << "\nlinearization computation time: " << (time_linDone - time_trimDone)/double(CLOCKS_PER_SEC) << " s\n" << std::endl;
// output
if (fdm->GetDebugLevel() > 0) {
trimmer->printSolution(std::cout,solver->getSolution());
std::cout << "\nfinal cost: " << std::scientific << std::setw(10) << trimmer->eval(solver->getSolution()) << std::endl;
std::cout << "\ntrim computation time: " << (time_trimDone - time_start)/double(CLOCKS_PER_SEC) << "s \n" << std::endl;
}
if (solver) delete solver;
if (trimmer) delete trimmer;
}
} // JSBSim

View file

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

View file

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

View file

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

View file

@ -38,7 +38,6 @@ SENTRY
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGJSBBase.h"
#include "simgear/structure/SGReferenced.hxx"
#include "simgear/structure/SGSharedPtr.hxx"
@ -46,7 +45,7 @@ INCLUDES
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_GROUNDCALLBACK "$Id: FGGroundCallback.h,v 1.15 2011/11/19 14:14:57 bcoconni Exp $"
#define ID_GROUNDCALLBACK "$Id: FGGroundCallback.h,v 1.16 2013/02/02 13:23:40 bcoconni Exp $"
namespace JSBSim {
@ -63,14 +62,14 @@ CLASS DOCUMENTATION
ball formed earth with an adjustable terrain elevation.
@author Mathias Froehlich
@version $Id: FGGroundCallback.h,v 1.15 2011/11/19 14:14:57 bcoconni Exp $
@version $Id: FGGroundCallback.h,v 1.16 2013/02/02 13:23:40 bcoconni Exp $
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
class FGGroundCallback : public FGJSBBase, public SGReferenced
class FGGroundCallback : public SGReferenced
{
public:

View file

@ -46,7 +46,7 @@ INCLUDES
namespace JSBSim {
static const char *IdSrc = "$Id: FGOutputType.cpp,v 1.5 2013/01/14 22:44:51 bcoconni Exp $";
static const char *IdSrc = "$Id: FGOutputType.cpp,v 1.6 2013/01/26 17:06:49 bcoconni Exp $";
static const char *IdHdr = ID_OUTPUTTYPE;
using namespace std;
@ -136,7 +136,7 @@ bool FGOutputType::Load(Element* element)
while (property_element) {
string caption="";
string property_str = property_element->GetDataLine();
FGPropertyManager* node = PropertyManager->GetNode(property_str);
FGPropertyNode* node = PropertyManager->GetNode(property_str);
if (!node) {
cerr << fgred << highint << endl << " No property by the name "
<< property_str << " has been defined. This property will " << endl

View file

@ -44,7 +44,7 @@ INCLUDES
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_OUTPUTTYPE "$Id: FGOutputType.h,v 1.4 2013/01/12 20:56:19 bcoconni Exp $"
#define ID_OUTPUTTYPE "$Id: FGOutputType.h,v 1.5 2013/01/26 17:06:49 bcoconni Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -53,7 +53,6 @@ FORWARD DECLARATIONS
namespace JSBSim {
class FGFDMExec;
class FGPropertyManager;
class Element;
class FGAerodynamics;
class FGAuxiliary;
@ -122,7 +121,7 @@ public:
/** Set the list of properties that should be output for this output instance.
@param outputProperties list of properties that should be output
*/
void SetOutputProperties(std::vector<FGPropertyManager *> & outputProperties)
void SetOutputProperties(std::vector<FGPropertyNode_ptr> & outputProperties)
{
OutputProperties = outputProperties;
}
@ -197,7 +196,7 @@ public:
protected:
int OutputIdx;
int SubSystems;
std::vector <FGPropertyManager*> OutputProperties;
std::vector <FGPropertyNode_ptr> OutputProperties;
std::vector <std::string> OutputCaptions;
bool enabled;

View file

@ -48,8 +48,6 @@ COMMENTS, REFERENCES, and NOTES [use "class documentation" below for API docs]
namespace JSBSim {
std::vector<SGPropertyNode_ptr> FGPropertyManager::tied_properties;
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGPropertyManager::Unbind(void)
@ -81,32 +79,32 @@ string FGPropertyManager::mkPropertyName(string name, bool lowercase) {
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGPropertyManager*
FGPropertyManager::GetNode (const string &path, bool create)
FGPropertyNode*
FGPropertyNode::GetNode (const string &path, bool create)
{
SGPropertyNode* node = getNode(path.c_str(), create);
if (node == 0) {
cerr << "FGPropertyManager::GetNode() No node found for " << path << endl;
}
return (FGPropertyManager*)node;
return (FGPropertyNode*)node;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGPropertyManager*
FGPropertyManager::GetNode (const string &relpath, int index, bool create)
FGPropertyNode*
FGPropertyNode::GetNode (const string &relpath, int index, bool create)
{
SGPropertyNode* node = getNode(relpath.c_str(), index, create);
if (node == 0) {
cerr << "FGPropertyManager::GetNode() No node found for " << relpath
<< "[" << index << "]" << endl;
}
return (FGPropertyManager*)node;
return (FGPropertyNode*)node;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGPropertyManager::HasNode (const string &path)
bool FGPropertyNode::HasNode (const string &path)
{
const SGPropertyNode* node = getNode(path.c_str(), false);
return (node != 0);
@ -114,14 +112,14 @@ bool FGPropertyManager::HasNode (const string &path)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
string FGPropertyManager::GetName( void ) const
string FGPropertyNode::GetName( void ) const
{
return string( getName() );
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
string FGPropertyManager::GetPrintableName( void ) const
string FGPropertyNode::GetPrintableName( void ) const
{
string temp_string(getName());
size_t initial_location=0;
@ -142,7 +140,7 @@ string FGPropertyManager::GetPrintableName( void ) const
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
string FGPropertyManager::GetFullyQualifiedName(void) const
string FGPropertyNode::GetFullyQualifiedName(void) const
{
vector<string> stack;
stack.push_back( getDisplayName(true) );
@ -168,7 +166,7 @@ string FGPropertyManager::GetFullyQualifiedName(void) const
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
string FGPropertyManager::GetRelativeName( const string &path ) const
string FGPropertyNode::GetRelativeName( const string &path ) const
{
string temp_string = GetFullyQualifiedName();
size_t len = path.length();
@ -182,91 +180,91 @@ string FGPropertyManager::GetRelativeName( const string &path ) const
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGPropertyManager::GetBool (const string &name, bool defaultValue) const
bool FGPropertyNode::GetBool (const string &name, bool defaultValue) const
{
return getBoolValue(name.c_str(), defaultValue);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
int FGPropertyManager::GetInt (const string &name, int defaultValue ) const
int FGPropertyNode::GetInt (const string &name, int defaultValue ) const
{
return getIntValue(name.c_str(), defaultValue);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
int FGPropertyManager::GetLong (const string &name, long defaultValue ) const
int FGPropertyNode::GetLong (const string &name, long defaultValue ) const
{
return getLongValue(name.c_str(), defaultValue);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
float FGPropertyManager::GetFloat (const string &name, float defaultValue ) const
float FGPropertyNode::GetFloat (const string &name, float defaultValue ) const
{
return getFloatValue(name.c_str(), defaultValue);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double FGPropertyManager::GetDouble (const string &name, double defaultValue ) const
double FGPropertyNode::GetDouble (const string &name, double defaultValue ) const
{
return getDoubleValue(name.c_str(), defaultValue);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
string FGPropertyManager::GetString (const string &name, string defaultValue ) const
string FGPropertyNode::GetString (const string &name, string defaultValue ) const
{
return string(getStringValue(name.c_str(), defaultValue.c_str()));
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGPropertyManager::SetBool (const string &name, bool val)
bool FGPropertyNode::SetBool (const string &name, bool val)
{
return setBoolValue(name.c_str(), val);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGPropertyManager::SetInt (const string &name, int val)
bool FGPropertyNode::SetInt (const string &name, int val)
{
return setIntValue(name.c_str(), val);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGPropertyManager::SetLong (const string &name, long val)
bool FGPropertyNode::SetLong (const string &name, long val)
{
return setLongValue(name.c_str(), val);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGPropertyManager::SetFloat (const string &name, float val)
bool FGPropertyNode::SetFloat (const string &name, float val)
{
return setFloatValue(name.c_str(), val);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGPropertyManager::SetDouble (const string &name, double val)
bool FGPropertyNode::SetDouble (const string &name, double val)
{
return setDoubleValue(name.c_str(), val);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bool FGPropertyManager::SetString (const string &name, const string &val)
bool FGPropertyNode::SetString (const string &name, const string &val)
{
return setStringValue(name.c_str(), val.c_str());
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGPropertyManager::SetArchivable (const string &name, bool state )
void FGPropertyNode::SetArchivable (const string &name, bool state )
{
SGPropertyNode * node = getNode(name.c_str());
if (node == 0)
@ -279,7 +277,7 @@ void FGPropertyManager::SetArchivable (const string &name, bool state )
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGPropertyManager::SetReadable (const string &name, bool state )
void FGPropertyNode::SetReadable (const string &name, bool state )
{
SGPropertyNode * node = getNode(name.c_str());
if (node == 0)
@ -292,7 +290,7 @@ void FGPropertyManager::SetReadable (const string &name, bool state )
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGPropertyManager::SetWritable (const string &name, bool state )
void FGPropertyNode::SetWritable (const string &name, bool state )
{
SGPropertyNode * node = getNode(name.c_str());
if (node == 0)
@ -307,7 +305,7 @@ void FGPropertyManager::SetWritable (const string &name, bool state )
void FGPropertyManager::Untie (const string &name)
{
SGPropertyNode* property = getNode(name.c_str());
SGPropertyNode* property = root->getNode(name.c_str());
if (!property) {
cerr << "Attempt to untie a non-existant property." << name << endl;
return;
@ -331,7 +329,7 @@ void FGPropertyManager::Untie (const string &name)
void FGPropertyManager::Tie (const string &name, bool *pointer, bool useDefault)
{
SGPropertyNode* property = getNode(name.c_str(), true);
SGPropertyNode* property = root->getNode(name.c_str(), true);
if (!property) {
cerr << "Could not get or create property " << name << endl;
return;
@ -350,7 +348,7 @@ void FGPropertyManager::Tie (const string &name, bool *pointer, bool useDefault)
void FGPropertyManager::Tie (const string &name, int *pointer,
bool useDefault )
{
SGPropertyNode* property = getNode(name.c_str(), true);
SGPropertyNode* property = root->getNode(name.c_str(), true);
if (!property) {
cerr << "Could not get or create property " << name << endl;
return;
@ -369,7 +367,7 @@ void FGPropertyManager::Tie (const string &name, int *pointer,
void FGPropertyManager::Tie (const string &name, long *pointer,
bool useDefault )
{
SGPropertyNode* property = getNode(name.c_str(), true);
SGPropertyNode* property = root->getNode(name.c_str(), true);
if (!property) {
cerr << "Could not get or create property " << name << endl;
return;
@ -388,7 +386,7 @@ void FGPropertyManager::Tie (const string &name, long *pointer,
void FGPropertyManager::Tie (const string &name, float *pointer,
bool useDefault )
{
SGPropertyNode* property = getNode(name.c_str(), true);
SGPropertyNode* property = root->getNode(name.c_str(), true);
if (!property) {
cerr << "Could not get or create property " << name << endl;
return;
@ -406,7 +404,7 @@ void FGPropertyManager::Tie (const string &name, float *pointer,
void FGPropertyManager::Tie (const string &name, double *pointer, bool useDefault)
{
SGPropertyNode* property = getNode(name.c_str(), true);
SGPropertyNode* property = root->getNode(name.c_str(), true);
if (!property) {
cerr << "Could not get or create property " << name << endl;
return;

View file

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

View file

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

View file

@ -49,7 +49,7 @@ INCLUDES
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_FGSCRIPT "$Id: FGScript.h,v 1.22 2012/09/05 04:49:13 jberndt Exp $"
#define ID_FGSCRIPT "$Id: FGScript.h,v 1.24 2013/06/10 01:50:43 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -158,7 +158,7 @@ CLASS DOCUMENTATION
comes the &quot;run&quot; section, where the conditions are
described in &quot;event&quot; clauses.</p>
@author Jon S. Berndt
@version "$Id: FGScript.h,v 1.22 2012/09/05 04:49:13 jberndt Exp $"
@version "$Id: FGScript.h,v 1.24 2013/06/10 01:50:43 jberndt Exp $"
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -220,8 +220,9 @@ private:
double TimeSpan;
string Name;
string Description;
vector <FGPropertyManager*> SetParam;
vector <FGPropertyManager*> NotifyProperties;
vector <FGPropertyNode_ptr> SetParam;
vector <std::string> SetParamName;
vector <FGPropertyNode_ptr> NotifyProperties;
vector <string> DisplayString;
vector <eAction> Action;
vector <eType> Type;

View file

@ -45,7 +45,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGCondition.cpp,v 1.17 2012/10/27 20:29:01 jberndt Exp $";
static const char *IdSrc = "$Id: FGCondition.cpp,v 1.18 2013/01/26 17:06:49 bcoconni Exp $";
static const char *IdHdr = ID_CONDITION;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -126,7 +126,7 @@ FGCondition::FGCondition(const string& test, FGPropertyManager* PropertyManager)
exit(-1);
}
FGPropertyManager *node = PropertyManager->GetNode(property1, false);
FGPropertyNode *node = PropertyManager->GetNode(property1, false);
if (node) {
TestParam1 = new FGPropertyValue(node);
} else {

View file

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

View file

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

View file

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

View file

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

View file

@ -30,17 +30,18 @@ INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGPropertyValue.h"
#include "input_output/FGPropertyManager.h"
namespace JSBSim {
static const char *IdSrc = "$Id: FGPropertyValue.cpp,v 1.7 2011/04/05 20:20:21 andgi Exp $";
static const char *IdSrc = "$Id: FGPropertyValue.cpp,v 1.8 2013/01/26 17:06:49 bcoconni Exp $";
static const char *IdHdr = ID_PROPERTYVALUE;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
FGPropertyValue::FGPropertyValue(FGPropertyManager* propNode)
FGPropertyValue::FGPropertyValue(FGPropertyNode* propNode)
: PropertyManager(0L), PropertyNode(propNode)
{
}
@ -56,7 +57,7 @@ FGPropertyValue::FGPropertyValue(std::string propName, FGPropertyManager* proper
double FGPropertyValue::GetValue(void) const
{
FGPropertyManager* node = PropertyNode;
FGPropertyNode* node = PropertyNode;
if (!PropertyNode) {
// The node cannot be cached since this is a const method.

View file

@ -42,7 +42,7 @@ INCLUDES
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_PROPERTYVALUE "$Id: FGPropertyValue.h,v 1.9 2011/04/05 20:20:21 andgi Exp $"
#define ID_PROPERTYVALUE "$Id: FGPropertyValue.h,v 1.10 2013/01/26 17:06:49 bcoconni Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -66,18 +66,18 @@ class FGPropertyValue : public FGParameter
{
public:
FGPropertyValue(FGPropertyManager* propNode);
FGPropertyValue(FGPropertyNode* propNode);
FGPropertyValue(std::string propName, FGPropertyManager* propertyManager);
~FGPropertyValue() {};
double GetValue(void) const;
void SetNode(FGPropertyManager* node) {PropertyNode = node;}
void SetNode(FGPropertyNode* node) {PropertyNode = node;}
std::string GetName(void) const;
private:
FGPropertyManager* PropertyManager; // Property root used to do late binding.
FGPropertyManager* PropertyNode;
FGPropertyNode_ptr PropertyNode;
std::string PropertyName;
};

View file

@ -3,22 +3,23 @@
* Copyright (C) James Goppert 2010 <james.goppert@gmail.com>
*
* FGStateSpace.cpp is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* FGStateSpace.cpp is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* You should have received a copy of the GNU Lesser General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "FGStateSpace.h"
#include <limits>
#include <iomanip>
#include <string>
namespace JSBSim
{
@ -77,7 +78,23 @@ void FGStateSpace::numericalJacobian(std::vector< std::vector<double> > & J, Co
if (computeYDerivative) fn2 = y.getDeriv(iY);
else fn2 = y.get(iY);
J[iY][iX] = (8*(f1-fn1)-(f2-fn2))/(12*h); // 3rd order taylor approx from lewis, pg 203
double diff1 = f1-fn1;
double diff2 = f2-fn2;
// correct for angle wrap
if (x.getComp(iX)->getUnit().compare("rad") == 0) {
while(diff1 > M_PI) diff1 -= 2*M_PI;
if(diff1 < -M_PI) diff1 += 2*M_PI;
if(diff2 > M_PI) diff2 -= 2*M_PI;
if(diff2 < -M_PI) diff2 += 2*M_PI;
} else if (x.getComp(iX)->getUnit().compare("deg") == 0) {
if(diff1 > 180) diff1 -= 360;
if(diff1 < -180) diff1 += 360;
if(diff2 > 180) diff2 -= 360;
if(diff2 < -180) diff2 += 360;
}
J[iY][iX] = (8*diff1-diff2)/(12*h); // 3rd order taylor approx from lewis, pg 203
x.set(x0);
if (m_fdm->GetDebugLevel() > 1)

View file

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

View file

@ -47,7 +47,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGTable.cpp,v 1.28 2011/06/13 12:07:10 jberndt Exp $";
static const char *IdSrc = "$Id: FGTable.cpp,v 1.29 2013/01/26 17:06:49 bcoconni Exp $";
static const char *IdHdr = ID_TABLE;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -122,7 +122,7 @@ FGTable::FGTable(FGPropertyManager* propMan, Element* el) : PropertyManager(prop
string call_type;
string parent_type;
string brkpt_string;
FGPropertyManager* node;
FGPropertyNode* node;
Element *tableData=0;
Element *parent_element=0;
Element *axisElement=0;

View file

@ -38,16 +38,17 @@ SENTRY
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGParameter.h"
#include <iosfwd>
#include <vector>
#include <string>
#include "FGParameter.h"
#include "input_output/FGPropertyManager.h"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_TABLE "$Id: FGTable.h,v 1.14 2011/06/13 11:46:08 jberndt Exp $"
#define ID_TABLE "$Id: FGTable.h,v 1.15 2013/01/26 17:06:49 bcoconni Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -55,7 +56,6 @@ FORWARD DECLARATIONS
namespace JSBSim {
class FGPropertyManager;
class Element;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -233,7 +233,7 @@ combustion_efficiency = Lookup_Combustion_Efficiency->GetValue(equivalence_ratio
@endcode
@author Jon S. Berndt
@version $Id: FGTable.h,v 1.14 2011/06/13 11:46:08 jberndt Exp $
@version $Id: FGTable.h,v 1.15 2013/01/26 17:06:49 bcoconni Exp $
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -290,8 +290,8 @@ public:
double operator()(unsigned int r, unsigned int c) const {return GetElement(r, c);}
// double operator()(unsigned int r, unsigned int c, unsigned int t) {GetElement(r, c, t);}
void SetRowIndexProperty(FGPropertyManager *node) {lookupProperty[eRow] = node;}
void SetColumnIndexProperty(FGPropertyManager *node) {lookupProperty[eColumn] = node;}
void SetRowIndexProperty(FGPropertyNode *node) {lookupProperty[eRow] = node;}
void SetColumnIndexProperty(FGPropertyNode *node) {lookupProperty[eColumn] = node;}
unsigned int GetNumRows() const {return nRows;}
@ -303,7 +303,7 @@ private:
enum type {tt1D, tt2D, tt3D} Type;
enum axis {eRow=0, eColumn, eTable};
bool internal;
FGPropertyManager *lookupProperty[3];
FGPropertyNode_ptr lookupProperty[3];
double** Data;
std::vector <FGTable*> Tables;
unsigned int nRows, nCols, nTables, dimension;

View file

@ -48,7 +48,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGAerodynamics.cpp,v 1.46 2012/07/26 04:33:46 jberndt Exp $";
static const char *IdSrc = "$Id: FGAerodynamics.cpp,v 1.47 2013/06/10 01:59:16 jberndt Exp $";
static const char *IdHdr = ID_AERODYNAMICS;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -180,6 +180,12 @@ bool FGAerodynamics::Run(bool Holding)
// JSB 4/27/12 - After use, convert wind axes to produce normal lift
// and drag values - not negative ones!
// As a clarification, JSBSim assumes that drag and lift values are defined
// in wind axes - BUT with a 180 rotation about the Y axis. That is, lift and
// drag will be positive up and aft, respectively, so that they are reported
// as positive numbers. However, the wind axes themselves assume that the X
// and Z forces are positive forward and down.
switch (axisType) {
case atBodyXYZ: // Forces already in body axes; no manipulation needed
vFw = in.Tb2w*vFnative;

View file

@ -50,7 +50,7 @@ INCLUDES
namespace JSBSim {
static const char *IdSrc = "$Id: FGAtmosphere.cpp,v 1.54 2012/09/17 12:38:07 jberndt Exp $";
static const char *IdSrc = "$Id: FGAtmosphere.cpp,v 1.55 2013/01/26 17:06:49 bcoconni Exp $";
static const char *IdHdr = ID_ATMOSPHERE;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -111,20 +111,21 @@ bool FGAtmosphere::Run(bool Holding)
void FGAtmosphere::Calculate(double altitude)
{
FGPropertyNode* node = PropertyManager->GetNode();
if (!PropertyManager->HasNode("atmosphere/override/temperature"))
Temperature = GetTemperature(altitude);
else
Temperature = PropertyManager->getDoubleValue("atmosphere/override/temperature");
Temperature = GetTemperature(altitude);
else
Temperature = node->GetDouble("atmosphere/override/temperature");
if (!PropertyManager->HasNode("atmosphere/override/pressure"))
Pressure = GetPressure(altitude);
else
Pressure = PropertyManager->getDoubleValue("atmosphere/override/pressure");
Pressure = GetPressure(altitude);
else
Pressure = node->GetDouble("atmosphere/override/pressure");
if (!PropertyManager->HasNode("atmosphere/override/density"))
Density = Pressure/(Reng*Temperature);
else
Density = PropertyManager->getDoubleValue("atmosphere/override/density");
Density = Pressure/(Reng*Temperature);
else
Density = node->GetDouble("atmosphere/override/density");
Soundspeed = sqrt(SHRatio*Reng*(Temperature));
PressureAltitude = altitude;

View file

@ -50,7 +50,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGAuxiliary.cpp,v 1.60 2012/09/30 16:49:17 bcoconni Exp $";
static const char *IdSrc = "$Id: FGAuxiliary.cpp,v 1.61 2013/06/10 01:56:14 jberndt Exp $";
static const char *IdHdr = ID_AUXILIARY;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -76,7 +76,7 @@ FGAuxiliary::FGAuxiliary(FGFDMExec* fdmex) : FGModel(fdmex)
seconds_in_day = 0.0;
hoverbmac = hoverbcg = 0.0;
Re = 0.0;
Nz = 0.0;
Nz = Ny = 0.0;
lon_relative_position = lat_relative_position = relative_position = 0.0;
vPilotAccel.InitMatrix();
@ -111,7 +111,7 @@ bool FGAuxiliary::InitModel(void)
seconds_in_day = 0.0;
hoverbmac = hoverbcg = 0.0;
Re = 0.0;
Nz = 0.0;
Nz = Ny = 0.0;
lon_relative_position = lat_relative_position = relative_position = 0.0;
vPilotAccel.InitMatrix();
@ -228,6 +228,7 @@ bool FGAuxiliary::Run(bool Holding)
vNcg = in.vBodyAccel/in.SLGravity;
// Nz is Acceleration in "g's", along normal axis (-Z body axis)
Nz = -vNcg(eZ);
Ny = vNcg(eY);
vPilotAccel = in.vBodyAccel + in.vPQRdot * in.ToEyePt;
vPilotAccel += in.vPQR * (in.vPQR * in.ToEyePt);
@ -373,6 +374,7 @@ void FGAuxiliary::bind(void)
PropertyManager->Tie("accelerations/n-pilot-y-norm", this, eY, (PMF)&FGAuxiliary::GetNpilot);
PropertyManager->Tie("accelerations/n-pilot-z-norm", this, eZ, (PMF)&FGAuxiliary::GetNpilot);
PropertyManager->Tie("accelerations/Nz", this, &FGAuxiliary::GetNz);
PropertyManager->Tie("accelerations/Ny", this, &FGAuxiliary::GetNy);
PropertyManager->Tie("forces/load-factor", this, &FGAuxiliary::GetNlf);
/* PropertyManager->Tie("atmosphere/headwind-fps", this, &FGAuxiliary::GetHeadWind, true);
PropertyManager->Tie("atmosphere/crosswind-fps", this, &FGAuxiliary::GetCrossWind, true); */

View file

@ -48,7 +48,7 @@ INCLUDES
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_AUXILIARY "$Id: FGAuxiliary.h,v 1.27 2012/09/15 11:17:21 bcoconni Exp $"
#define ID_AUXILIARY "$Id: FGAuxiliary.h,v 1.28 2013/06/10 01:56:27 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -99,7 +99,7 @@ CLASS DOCUMENTATION
to the JSBSim vPQRdot vector, and the w parameter is equivalent to vPQR.
@author Tony Peden, Jon Berndt
@version $Id: FGAuxiliary.h,v 1.27 2012/09/15 11:17:21 bcoconni Exp $
@version $Id: FGAuxiliary.h,v 1.28 2013/06/10 01:56:27 jberndt Exp $
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -225,6 +225,9 @@ public:
/** The vertical acceleration in g's of the aircraft center of gravity. */
double GetNz (void) const { return Nz; }
/** The lateral acceleration in g's of the aircraft center of gravity. */
double GetNy (void) const { return Ny; }
const FGColumnVector3& GetNwcg(void) const { return vNwcg; }
double GetHOverBCG(void) const { return hoverbcg; }
@ -312,7 +315,7 @@ private:
double alpha, beta;
double adot,bdot;
double psigt, gamma;
double Nz;
double Nz, Ny;
double seconds_in_day; // seconds since current GMT day began
int day_of_year; // GMT day, 1 .. 366

View file

@ -66,7 +66,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGFCS.cpp,v 1.79 2012/12/12 06:19:57 jberndt Exp $";
static const char *IdSrc = "$Id: FGFCS.cpp,v 1.80 2013/01/26 17:06:49 bcoconni Exp $";
static const char *IdHdr = ID_FCS;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -541,7 +541,7 @@ bool FGFCS::Load(Element* el, SystemType systype)
interface_property_string = property_element->GetDataLine();
if (PropertyManager->HasNode(interface_property_string)) {
FGPropertyManager* node = PropertyManager->GetNode(interface_property_string);
FGPropertyNode* node = PropertyManager->GetNode(interface_property_string);
if (debug_lvl > 0)
cout << " " << "Overriding value for property " << interface_property_string
<< " (old value: " << node->getDoubleValue() << " new value: " << value << ")" << endl;
@ -564,7 +564,7 @@ bool FGFCS::Load(Element* el, SystemType systype)
FGFCSChannel* newChannel = 0;
string sOnOffProperty = channel_element->GetAttributeValue("execute");
FGPropertyManager* OnOffPropertyNode = 0;
FGPropertyNode* OnOffPropertyNode = 0;
if (sOnOffProperty.length() > 0) {
OnOffPropertyNode = PropertyManager->GetNode(sOnOffProperty);
if (OnOffPropertyNode == 0) {

View file

@ -44,7 +44,7 @@ INCLUDES
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_FCSCHANNEL "$Id: FGFCSChannel.h,v 1.1 2012/10/15 05:02:29 jberndt Exp $"
#define ID_FCSCHANNEL "$Id: FGFCSChannel.h,v 1.2 2013/01/26 17:06:50 bcoconni Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -70,7 +70,7 @@ typedef std::vector <FGFCSComponent*> FCSCompVec;
class FGFCSChannel {
public:
/// Constructor
FGFCSChannel(FGPropertyManager* node=0) :
FGFCSChannel(FGPropertyNode* node=0) :
OnOffNode(node)
{
}
@ -120,7 +120,7 @@ public:
private:
FCSCompVec FCSComponents;
const FGPropertyManager* OnOffNode;
FGConstPropertyNode_ptr OnOffNode;
};
}

View file

@ -4,7 +4,7 @@
Author: Anders Gidenstam
Date started: 01/21/2006
----- Copyright (C) 2006 - 2011 Anders Gidenstam (anders(at)gidenstam.org) --
----- Copyright (C) 2006 - 2013 Anders Gidenstam (anders(at)gidenstam.org) --
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free Software
@ -50,14 +50,14 @@ using std::max;
namespace JSBSim {
static const char *IdSrc = "$Id: FGGasCell.cpp,v 1.15 2011/08/06 13:47:59 jberndt Exp $";
static const char *IdSrc = "$Id: FGGasCell.cpp,v 1.18 2013/04/17 20:24:27 andgi Exp $";
static const char *IdHdr = ID_GASCELL;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/* Constants. */
const double FGGasCell::R = 3.4071; // [lbs ft/(mol Rankine)]
const double FGGasCell::R = 3.4071; // [lbf ft/(mol Rankine)]
const double FGGasCell::M_air = 0.0019186; // [slug/mol]
const double FGGasCell::M_hydrogen = 0.00013841; // [slug/mol]
const double FGGasCell::M_helium = 0.00027409; // [slug/mol]
@ -202,7 +202,7 @@ FGGasCell::FGGasCell(FGFDMExec* exec, Element* el, int num, const struct Inputs&
property_name = base_property_name + "/max_volume-ft3";
PropertyManager->Tie( property_name.c_str(), &MaxVolume, false );
PropertyManager->SetWritable( property_name, false );
PropertyManager->GetNode()->SetWritable( property_name, false );
property_name = base_property_name + "/temp-R";
PropertyManager->Tie( property_name.c_str(), &Temperature, false );
property_name = base_property_name + "/pressure-psf";
@ -325,7 +325,7 @@ void FGGasCell::Calculate(double dt)
// FixMe: CellHeight should depend on current volume.
const double CellHeight = 2 * Zradius + Zwidth; // [ft]
const double GasMass = Contents * M_gas(); // [slug]
const double GasVolume = Contents * R * Temperature / Pressure; // [ft³]
const double GasVolume = Contents * R * Temperature / Pressure; // [ft^3]
const double GasDensity = GasMass / GasVolume;
const double DeltaPressure =
Pressure + CellHeight * g * (AirDensity - GasDensity) - AirPressure;
@ -468,7 +468,7 @@ void FGGasCell::Debug(int from)
cout << " Initial pressure: " << Pressure << " lbs/ft2" << endl;
cout << " Initial volume: " << Volume << " ft3" << endl;
cout << " Initial mass: " << GetMass() << " slug mass" << endl;
cout << " Initial weight: " << GetMass()*lbtoslug << " lbs force" <<
cout << " Initial weight: " << GetMass()*slugtolb << " lbs force" <<
endl;
cout << " Heat transfer: " << endl;
}
@ -485,7 +485,7 @@ void FGGasCell::Debug(int from)
cout << " Pressure: " << Pressure << " lbs/ft2" << endl;
cout << " Volume: " << Volume << " ft3" << endl;
cout << " Mass: " << GetMass() << " slug mass" << endl;
cout << " Weight: " << GetMass()*lbtoslug << " lbs force" << endl;
cout << " Weight: " << GetMass()*slugtolb << " lbs force" << endl;
}
if (debug_lvl & 16) { // Sanity checking
}
@ -634,7 +634,7 @@ FGBallonet::FGBallonet(FGFDMExec* exec, Element* el, int num, FGGasCell* parent,
property_name = base_property_name + "/max_volume-ft3";
PropertyManager->Tie( property_name, &MaxVolume, false );
PropertyManager->SetWritable( property_name, false );
PropertyManager->GetNode()->SetWritable( property_name, false );
property_name = base_property_name + "/temp-R";
PropertyManager->Tie( property_name, &Temperature, false );
@ -820,7 +820,7 @@ void FGBallonet::Debug(int from)
cout << " Initial pressure: " << Pressure << " lbs/ft2" << endl;
cout << " Initial volume: " << Volume << " ft3" << endl;
cout << " Initial mass: " << GetMass() << " slug mass" << endl;
cout << " Initial weight: " << GetMass()*lbtoslug <<
cout << " Initial weight: " << GetMass()*slugtolb <<
" lbs force" << endl;
cout << " Heat transfer: " << endl;
}
@ -838,7 +838,7 @@ void FGBallonet::Debug(int from)
cout << " Pressure: " << Pressure << " lbs/ft2" << endl;
cout << " Volume: " << Volume << " ft3" << endl;
cout << " Mass: " << GetMass() << " slug mass" << endl;
cout << " Weight: " << GetMass()*lbtoslug << " lbs force" << endl;
cout << " Weight: " << GetMass()*slugtolb << " lbs force" << endl;
}
if (debug_lvl & 16) { // Sanity checking
}

View file

@ -4,7 +4,7 @@
Author: Anders Gidenstam
Date started: 01/21/2006
----- Copyright (C) 2006 - 2011 Anders Gidenstam (anders(at)gidenstam.org) --
----- Copyright (C) 2006 - 2013 Anders Gidenstam (anders(at)gidenstam.org) --
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free Software
@ -50,7 +50,7 @@ INCLUDES
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_GASCELL "$Id: FGGasCell.h,v 1.12 2011/08/06 13:47:59 jberndt Exp $"
#define ID_GASCELL "$Id: FGGasCell.h,v 1.13 2013/04/17 20:24:27 andgi Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -238,7 +238,7 @@ private:
std::string type;
int CellNum;
// Structural constants
double MaxVolume; // [ft^2]
double MaxVolume; // [ft^3]
double MaxOverpressure; // [lbs/ft^2]
FGColumnVector3 vXYZ; // [in]
double Xradius, Yradius, Zradius; // [ft]
@ -251,8 +251,8 @@ private:
// Variables
double Pressure; // [lbs/ft^2]
double Contents; // [mol]
double Volume; // [ft^2]
double dVolumeIdeal; // [ft^2]
double Volume; // [ft^3]
double dVolumeIdeal; // [ft^3]
double Temperature; // [Rankine]
double Buoyancy; // [lbs] Note: Gross lift.
// Does not include the weight of the gas itself.
@ -344,7 +344,7 @@ public:
private:
int CellNum;
// Structural constants
double MaxVolume; // [ft^2]
double MaxVolume; // [ft^3]
double MaxOverpressure; // [lbs/ft^2]
FGColumnVector3 vXYZ; // [in]
double Xradius, Yradius, Zradius; // [ft]
@ -357,8 +357,8 @@ private:
// Variables
double Pressure; // [lbs/ft^2]
double Contents; // [mol]
double Volume; // [ft^2]
double dVolumeIdeal; // [ft^2]
double Volume; // [ft^3]
double dVolumeIdeal; // [ft^3]
double dU; // [lbs ft / sec]
double Temperature; // [Rankine]
double ValveOpen; // 0 <= ValveOpen <= 1 (or higher).

View file

@ -53,7 +53,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGInput.cpp,v 1.24 2012/11/23 16:30:36 bcoconni Exp $";
static const char *IdSrc = "$Id: FGInput.cpp,v 1.25 2013/01/26 17:06:50 bcoconni Exp $";
static const char *IdHdr = ID_INPUT;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -94,7 +94,7 @@ bool FGInput::Run(bool Holding)
string line, token;
size_t start=0, string_start=0, string_end=0;
double value=0;
FGPropertyManager* node=0;
FGPropertyNode* node=0;
if (FGModel::Run(Holding)) return true; // fast exit if nothing to do
if (port == 0) return false; // Do nothing here if port not defined

View file

@ -61,7 +61,7 @@ DEFINITIONS
GLOBAL DATA
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
static const char *IdSrc = "$Id: FGLGear.cpp,v 1.103 2013/01/13 12:44:52 bcoconni Exp $";
static const char *IdSrc = "$Id: FGLGear.cpp,v 1.104 2013/01/25 14:02:13 jberndt Exp $";
static const char *IdHdr = ID_LGEAR;
// Body To Structural (body frame is rotated 180 deg about Y and lengths are given in
@ -357,8 +357,9 @@ const FGColumnVector3& FGLGear::GetBodyForces(void)
ResetReporting();
}
}
else if (gearPos < 0.01) { // Gear UP
} else if (gearPos < 0.01) { // Gear UP
WOW = false;
vWhlVelVec.InitMatrix();
}

View file

@ -49,7 +49,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGOutput.cpp,v 1.71 2012/12/15 16:13:58 bcoconni Exp $";
static const char *IdSrc = "$Id: FGOutput.cpp,v 1.72 2013/01/26 17:06:50 bcoconni Exp $";
static const char *IdHdr = ID_OUTPUT;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -207,7 +207,7 @@ bool FGOutput::SetDirectivesFile(const std::string& fname)
bool FGOutput::Load(int subSystems, std::string protocol, std::string type,
std::string port, std::string name, double outRate,
std::vector<FGPropertyManager *> & outputProperties)
std::vector<FGPropertyNode_ptr> & outputProperties)
{
unsigned int idx = OutputTypes.size();
FGOutputType* Output = 0;

View file

@ -48,7 +48,7 @@ INCLUDES
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_OUTPUT "$Id: FGOutput.h,v 1.26 2012/09/05 21:49:19 bcoconni Exp $"
#define ID_OUTPUT "$Id: FGOutput.h,v 1.27 2013/01/26 17:06:50 bcoconni Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -122,7 +122,7 @@ CLASS DOCUMENTATION
The class FGOutput is the manager of the outputs requested by the user. It
manages a list of instances derived from the abstract class FGOutputType.
@version $Id: FGOutput.h,v 1.26 2012/09/05 21:49:19 bcoconni Exp $
@version $Id: FGOutput.h,v 1.27 2013/01/26 17:06:50 bcoconni Exp $
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -216,7 +216,7 @@ public:
@result true if the execution succeeded. */
bool Load(int subSystems, std::string protocol, std::string type,
std::string port, std::string name, double outRate,
std::vector<FGPropertyManager *> & outputProperties);
std::vector<FGPropertyNode_ptr> & outputProperties);
/** Get the name identifier to which the output will be directed.
@param idx ID of the output instance from which the name identifier must
be obtained

View file

@ -77,7 +77,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGPropagate.cpp,v 1.111 2013/01/19 13:49:37 bcoconni Exp $";
static const char *IdSrc = "$Id: FGPropagate.cpp,v 1.112 2013/06/10 01:57:52 jberndt Exp $";
static const char *IdHdr = ID_PROPAGATE;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -673,6 +673,10 @@ void FGPropagate::bind(void)
PropertyManager->Tie("attitude/theta-rad", this, (int)eTht, (PMF)&FGPropagate::GetEuler);
PropertyManager->Tie("attitude/psi-rad", this, (int)ePsi, (PMF)&FGPropagate::GetEuler);
PropertyManager->Tie("attitude/phi-deg", this, (int)ePhi, (PMF)&FGPropagate::GetEulerDeg);
PropertyManager->Tie("attitude/theta-deg", this, (int)eTht, (PMF)&FGPropagate::GetEulerDeg);
PropertyManager->Tie("attitude/psi-deg", this, (int)ePsi, (PMF)&FGPropagate::GetEulerDeg);
PropertyManager->Tie("attitude/roll-rad", this, (int)ePhi, (PMF)&FGPropagate::GetEuler);
PropertyManager->Tie("attitude/pitch-rad", this, (int)eTht, (PMF)&FGPropagate::GetEuler);
PropertyManager->Tie("attitude/heading-true-rad", this, (int)ePsi, (PMF)&FGPropagate::GetEuler);

View file

@ -49,7 +49,7 @@ INCLUDES
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_PROPAGATE "$Id: FGPropagate.h,v 1.74 2013/01/19 13:49:37 bcoconni Exp $"
#define ID_PROPAGATE "$Id: FGPropagate.h,v 1.75 2013/06/10 01:58:01 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -93,7 +93,7 @@ CLASS DOCUMENTATION
@endcode
@author Jon S. Berndt, Mathias Froehlich, Bertrand Coconnier
@version $Id: FGPropagate.h,v 1.74 2013/01/19 13:49:37 bcoconni Exp $
@version $Id: FGPropagate.h,v 1.75 2013/06/10 01:58:01 jberndt Exp $
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -247,6 +247,23 @@ public:
*/
const FGColumnVector3& GetEuler(void) const { return VState.qAttitudeLocal.GetEuler(); }
/** Retrieves the Euler angles (in degrees) that define the vehicle orientation.
Extracts the Euler angles from the quaternion that stores the orientation
in the Local frame. The order of rotation used is Yaw-Pitch-Roll. The
vector returned is represented by an FGColumnVector reference. The vector
for the Euler angles is organized (Phi, Theta, Psi). The vector
is 1-based, so that the first element can be retrieved using the "()" operator.
In other words, the returned vector item with subscript (1) is Phi.
Various convenience enumerators are defined in FGJSBBase. The relevant
enumerators for the vector returned by this call are, ePhi=1, eTht=2, ePsi=3.
units degrees
@return The Euler angle vector, where the first item in the
vector is the angle about the X axis, the second is the
angle about the Y axis, and the third item is the angle
about the Z axis (Phi, Theta, Psi).
*/
const FGColumnVector3& GetEulerDeg(void) const { return VState.qAttitudeLocal.GetEuler() * radtodeg; }
/** Retrieves a body frame velocity component.
Retrieves a body frame velocity component. The velocity returned is
extracted from the vUVW vector (an FGColumnVector). The vector for the
@ -341,6 +358,18 @@ public:
*/
double GetEuler(int axis) const { return VState.qAttitudeLocal.GetEuler(axis); }
/** Retrieves a vehicle Euler angle component in degrees.
Retrieves an Euler angle (Phi, Theta, or Psi) from the quaternion that
stores the vehicle orientation relative to the Local frame. The order of
rotations used is Yaw-Pitch-Roll. The Euler angle with subscript (1) is
Phi. Various convenience enumerators are defined in FGJSBBase. The
relevant enumerators for the Euler angle returned by this call are,
ePhi=1, eTht=2, ePsi=3 (e.g. GetEuler(eTht) returns Theta).
units degrees
@return An Euler angle in degrees.
*/
double GetEulerDeg(int axis) const { return VState.qAttitudeLocal.GetEuler(axis) * radtodeg; }
/** Retrieves the cosine of a vehicle Euler angle component.
Retrieves the cosine of an Euler angle (Phi, Theta, or Psi) from the
quaternion that stores the vehicle orientation relative to the Local frame.

View file

@ -43,7 +43,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGActuator.cpp,v 1.25 2013/01/12 19:24:05 jberndt Exp $";
static const char *IdSrc = "$Id: FGActuator.cpp,v 1.28 2013/06/10 02:04:50 jberndt Exp $";
static const char *IdHdr = ID_ACTUATOR;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -83,12 +83,12 @@ FGActuator::FGActuator(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, eleme
Element* ratelim_el = element->FindElement("rate_limit");
while ( ratelim_el ) {
rate_limited = true;
FGPropertyManager* rate_limit_prop=0;
FGPropertyNode* rate_limit_prop=0;
string rate_limit_str = ratelim_el->GetDataLine();
trim(rate_limit_str);
if (is_number(rate_limit_str)) {
rate_limit = fabs(element->FindElementValueAsNumber("rate_limit"));
rate_limit = fabs(element->FindElementValueAsNumber("rate_limit"));
} else {
if (rate_limit_str[0] == '-') rate_limit_str.erase(0,1);
rate_limit_prop = PropertyManager->GetNode(rate_limit_str, true);
@ -104,7 +104,7 @@ FGActuator::FGActuator(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, eleme
} else if (sense.substr(0,4) == "decr") {
if (rate_limit_prop != 0) rate_limit_decr_prop = rate_limit_prop;
else rate_limit_decr = -rate_limit;
}
}
} else {
rate_limit_incr = rate_limit;
rate_limit_decr = -rate_limit;
@ -157,7 +157,8 @@ bool FGActuator::Run(void )
Output = PreviousOutput;
} else {
if (lag != 0.0) Lag(); // models actuator lag
if (rate_limit != 0) RateLimit(); // limit the actuator rate
if (rate_limit != 0 || (rate_limit_incr_prop != 0
|| rate_limit_decr_prop != 0)) RateLimit(); // limit the actuator rate
if (deadband_width != 0.0) Deadband();
if (hysteresis_width != 0.0) Hysteresis();
if (bias != 0.0) Bias(); // models a finite bias

View file

@ -44,7 +44,7 @@ INCLUDES
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_ACTUATOR "$Id: FGActuator.h,v 1.14 2013/01/12 19:24:05 jberndt Exp $"
#define ID_ACTUATOR "$Id: FGActuator.h,v 1.15 2013/01/26 17:06:50 bcoconni Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -120,7 +120,7 @@ Example:
@endcode
@author Jon S. Berndt
@version $Revision: 1.14 $
@version $Revision: 1.15 $
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -160,8 +160,8 @@ private:
double rate_limit;
double rate_limit_incr;
double rate_limit_decr;
FGPropertyManager* rate_limit_incr_prop;
FGPropertyManager* rate_limit_decr_prop;
FGPropertyNode_ptr rate_limit_incr_prop;
FGPropertyNode_ptr rate_limit_decr_prop;
double hysteresis_width;
double deadband_width;
double lag;

View file

@ -43,7 +43,7 @@ INCLUDES
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_DEADBAND "$Id: FGDeadBand.h,v 1.9 2009/10/24 22:59:30 jberndt Exp $"
#define ID_DEADBAND "$Id: FGDeadBand.h,v 1.10 2013/01/26 17:06:50 bcoconni Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -53,7 +53,6 @@ namespace JSBSim {
class FGFCS;
class Element;
class FGPropertyManager;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DOCUMENTATION
@ -80,7 +79,7 @@ CLASS DOCUMENTATION
produce no output. For example, say that the width value is 2.0. If the
input is between -1.0 and +1.0, the output will be zero.
@author Jon S. Berndt
@version $Id: FGDeadBand.h,v 1.9 2009/10/24 22:59:30 jberndt Exp $
@version $Id: FGDeadBand.h,v 1.10 2013/01/26 17:06:50 bcoconni Exp $
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -98,7 +97,7 @@ public:
private:
double width;
double gain;
FGPropertyManager* WidthPropertyNode;
FGPropertyNode_ptr WidthPropertyNode;
double WidthPropertySign;
void Debug(int from);

View file

@ -48,7 +48,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGFCSComponent.cpp,v 1.34 2011/09/11 11:36:04 bcoconni Exp $";
static const char *IdSrc = "$Id: FGFCSComponent.cpp,v 1.35 2013/01/26 17:06:50 bcoconni Exp $";
static const char *IdHdr = ID_FCSCOMPONENT;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -121,7 +121,7 @@ FGFCSComponent::FGFCSComponent(FGFCS* _fcs, Element* element) : fcs(_fcs)
} else {
InputSigns.push_back( 1.0);
}
FGPropertyManager* node = 0L;
FGPropertyNode* node = 0L;
if (PropertyManager->HasNode(input)) {
node = PropertyManager->GetNode(input);
InputNodes.push_back(new FGPropertyValue( node ));
@ -138,7 +138,7 @@ FGFCSComponent::FGFCSComponent(FGFCS* _fcs, Element* element) : fcs(_fcs)
while (out_elem) {
IsOutput = true;
string output_node_name = out_elem->GetDataLine();
FGPropertyManager* OutputNode = PropertyManager->GetNode( output_node_name, true );
FGPropertyNode* OutputNode = PropertyManager->GetNode( output_node_name, true );
OutputNodes.push_back(OutputNode);
if (!OutputNode) {
cerr << endl << " Unable to process property: " << output_node_name << endl;

View file

@ -46,7 +46,7 @@ INCLUDES
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_FCSCOMPONENT "$Id: FGFCSComponent.h,v 1.20 2011/06/16 03:39:38 jberndt Exp $"
#define ID_FCSCOMPONENT "$Id: FGFCSComponent.h,v 1.21 2013/01/26 17:06:50 bcoconni Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -55,7 +55,6 @@ FORWARD DECLARATIONS
namespace JSBSim {
class FGFCS;
class FGPropertyManager;
class Element;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -81,7 +80,7 @@ CLASS DOCUMENTATION
- FGActuator
@author Jon S. Berndt
@version $Id: FGFCSComponent.h,v 1.20 2011/06/16 03:39:38 jberndt Exp $
@version $Id: FGFCSComponent.h,v 1.21 2013/01/26 17:06:50 bcoconni Exp $
@see Documentation for the FGFCS class, and for the configuration file class
*/
@ -107,10 +106,10 @@ public:
protected:
FGFCS* fcs;
FGPropertyManager* PropertyManager;
FGPropertyManager* treenode;
std::vector <FGPropertyManager*> OutputNodes;
FGPropertyManager* ClipMinPropertyNode;
FGPropertyManager* ClipMaxPropertyNode;
FGPropertyNode_ptr treenode;
std::vector <FGPropertyNode_ptr> OutputNodes;
FGPropertyNode_ptr ClipMinPropertyNode;
FGPropertyNode_ptr ClipMaxPropertyNode;
std::vector <FGPropertyValue*> InputNodes;
std::vector <std::string> InputNames;
std::vector <float> InputSigns;

View file

@ -43,7 +43,7 @@ INCLUDES
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_FILTER "$Id: FGFilter.h,v 1.12 2009/10/24 22:59:30 jberndt Exp $"
#define ID_FILTER "$Id: FGFilter.h,v 1.13 2013/01/26 17:06:50 bcoconni Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -228,7 +228,7 @@ is so that the last component in a "string" can copy its value to the appropriat
output, such as the elevator, or speedbrake, etc.
@author Jon S. Berndt
@version $Revision: 1.12 $
@version $Revision: 1.13 $
*/
@ -263,8 +263,8 @@ private:
double PreviousInput2;
double PreviousOutput1;
double PreviousOutput2;
FGPropertyManager* Trigger;
FGPropertyManager* PropertyNode[7];
FGPropertyNode_ptr Trigger;
FGPropertyNode_ptr PropertyNode[7];
void CalculateDynamicFilters(void);
void ReadFilterCoefficients(Element* el, int index);
bool DynamicFilter;

View file

@ -44,7 +44,7 @@ INCLUDES
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_GAIN "$Id: FGGain.h,v 1.14 2009/10/24 22:59:30 jberndt Exp $"
#define ID_GAIN "$Id: FGGain.h,v 1.15 2013/01/26 17:06:50 bcoconni Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -208,7 +208,7 @@ CLASS DOCUMENTATION
@endcode
@author Jon S. Berndt
@version $Revision: 1.14 $
@version $Revision: 1.15 $
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -225,7 +225,7 @@ public:
private:
FGTable* Table;
FGPropertyManager* GainPropertyNode;
FGPropertyNode_ptr GainPropertyNode;
double GainPropertySign;
double Gain;
double InMin, InMax, OutMin, OutMax;

View file

@ -44,7 +44,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGPID.cpp,v 1.20 2012/05/10 12:10:48 jberndt Exp $";
static const char *IdSrc = "$Id: FGPID.cpp,v 1.21 2013/02/02 06:05:26 jberndt Exp $";
static const char *IdHdr = ID_PID;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -135,6 +135,14 @@ FGPID::FGPID(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element)
}
FGFCSComponent::bind();
string tmp;
if (Name.find("/") == string::npos) {
tmp = "fcs/" + PropertyManager->mkPropertyName(Name, true);
} else {
tmp = Name;
}
typedef double (FGPID::*PMF)(void) const;
PropertyManager->Tie(tmp+"/initial-integrator-value", this, (PMF)0, &FGPID::SetInitialOutput);
Debug(0);
}

View file

@ -44,7 +44,7 @@ INCLUDES
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_PID "$Id: FGPID.h,v 1.13 2012/05/10 12:10:48 jberndt Exp $"
#define ID_PID "$Id: FGPID.h,v 1.15 2013/02/02 06:05:26 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -116,7 +116,7 @@ For example,
</pre>
@author Jon S. Berndt
@version $Revision: 1.13 $
@version $Revision: 1.15 $
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -135,6 +135,11 @@ public:
/// These define the indices use to select the various integrators.
enum eIntegrateType {eNone = 0, eRectEuler, eTrapezoidal, eAdamsBashforth2, eAdamsBashforth3};
void SetInitialOutput(double val) {
I_out_total = val;
Output = val;
}
private:
double Kp, Ki, Kd;
double I_out_total;
@ -147,11 +152,11 @@ private:
eIntegrateType IntType;
FGPropertyManager *Trigger;
FGPropertyManager* KpPropertyNode;
FGPropertyManager* KiPropertyNode;
FGPropertyManager* KdPropertyNode;
FGPropertyManager* ProcessVariableDot;
FGPropertyNode_ptr Trigger;
FGPropertyNode_ptr KpPropertyNode;
FGPropertyNode_ptr KiPropertyNode;
FGPropertyNode_ptr KdPropertyNode;
FGPropertyNode_ptr ProcessVariableDot;
void Debug(int from);
};

View file

@ -44,7 +44,7 @@ INCLUDES
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_SENSOR "$Id: FGSensor.h,v 1.21 2012/01/08 12:39:14 bcoconni Exp $"
#define ID_SENSOR "$Id: FGSensor.h,v 1.22 2013/06/10 01:59:16 jberndt Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -76,7 +76,7 @@ Syntax:
<drift_rate> number </drift_rate>
<gain> number </gain>
<bias> number </bias>
<delay> number < /delay>
<delay [type="time|frames"]> number < /delay>
</sensor>
@endcode
@ -124,7 +124,7 @@ The delay element can specify a frame delay. The integer number provided is
the number of frames to delay the output signal.
@author Jon S. Berndt
@version $Revision: 1.21 $
@version $Revision: 1.22 $
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -48,7 +48,7 @@ INCLUDES
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_SWITCH "$Id: FGSwitch.h,v 1.15 2012/10/27 20:29:01 jberndt Exp $"
#define ID_SWITCH "$Id: FGSwitch.h,v 1.16 2013/01/26 17:06:50 bcoconni Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -127,7 +127,7 @@ ap/attitude_hold takes the value 1), the value of the switch component will be
whatever value fcs/roll-ap-error-summer is.
@author Jon S. Berndt
@version $Id: FGSwitch.h,v 1.15 2012/10/27 20:29:01 jberndt Exp $
@version $Id: FGSwitch.h,v 1.16 2013/01/26 17:06:50 bcoconni Exp $
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -185,7 +185,7 @@ private:
} else {
sign = 1.0;
}
FGPropertyManager *node = propMan->GetNode(value, false);
FGPropertyNode *node = propMan->GetNode(value, false);
if (node) {
OutputProp = new FGPropertyValue(node);
} else {

View file

@ -47,7 +47,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGRocket.cpp,v 1.29 2013/01/12 21:11:59 jberndt Exp $";
static const char *IdSrc = "$Id: FGRocket.cpp,v 1.30 2013/06/10 02:00:11 jberndt Exp $";
static const char *IdHdr = ID_ROCKET;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -250,8 +250,8 @@ string FGRocket::GetEngineLabels(const string& delimiter)
{
std::ostringstream buf;
buf << Name << " Total Impulse (engine " << EngineNumber << " in psf)" << delimiter
<< Name << " Total Vacuum Impulse (engine " << EngineNumber << " in psf)" << delimiter
buf << Name << " Total Impulse (engine " << EngineNumber << " in lbf)" << delimiter
<< Name << " Total Vacuum Impulse (engine " << EngineNumber << " in lbf)" << delimiter
<< Thruster->GetThrusterLabels(EngineNumber, delimiter);
return buf.str();

View file

@ -48,7 +48,7 @@ INCLUDES
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_ROTOR "$Id: FGRotor.h,v 1.14 2012/03/18 15:48:36 jentron Exp $"
#define ID_ROTOR "$Id: FGRotor.h,v 1.15 2013/01/26 17:06:50 bcoconni Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -230,7 +230,7 @@ CLASS DOCUMENTATION
</dl>
@author Thomas Kreitler
@version $Id: FGRotor.h,v 1.14 2012/03/18 15:48:36 jentron Exp $
@version $Id: FGRotor.h,v 1.15 2013/01/26 17:06:50 bcoconni Exp $
*/
@ -369,7 +369,7 @@ private:
double MaximalRPM;
int ExternalRPM;
int RPMdefinition;
FGPropertyManager* ExtRPMsource;
FGPropertyNode_ptr ExtRPMsource;
double SourceGearRatio;
// 'real' rotor parameters

View file

@ -47,7 +47,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGTank.cpp,v 1.36 2013/01/12 19:25:30 jberndt Exp $";
static const char *IdSrc = "$Id: FGTank.cpp,v 1.37 2013/06/10 02:04:12 jberndt Exp $";
static const char *IdHdr = ID_TANK;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -118,6 +118,13 @@ FGTank::FGTank(FGFDMExec* exec, Element* el, int tank_number)
Capacity = 0.00001;
Contents = 0.0;
}
if (Contents > Capacity) {
cerr << "Tank content (" << Contents << " lbs) is greater than tank capacity ("
<< Capacity << " lbs) for tank " << tank_number
<< "! Did you accidentally swap contents and capacity?" << endl;
throw("tank definition error");
}
PctFull = 100.0*Contents/Capacity; // percent full; 0 to 100.0
// Check whether this is a solid propellant "tank". Initialize it if true.