initialization/FGTrimAxis.h
initialization/FGSimplexTrim.h
initialization/FGTrimmer.h
+ initialization/FGLinearization.h
input_output/FGXMLParse.h
input_output/FGXMLFileRead.h
input_output/FGPropertyManager.h
initialization/FGTrimAxis.cpp
initialization/FGSimplexTrim.cpp
initialization/FGTrimmer.cpp
+ initialization/FGLinearization.cpp
input_output/FGGroundCallback.cpp
input_output/FGPropertyManager.cpp
input_output/FGScript.cpp
#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"
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;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// 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 {
// 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);
instance->Tie("simulation/frame", (int *)&Frame, false);
// simplex trim properties
- instance->SetDouble("trim/solver/rtol",0.0001);
- instance->SetDouble("trim/solver/speed",2);
- instance->SetDouble("trim/solver/abstol",0.001);
- instance->SetDouble("trim/solver/iterMax",2000);
- instance->SetInt("trim/solver/debugLevel",0);
- instance->SetDouble("trim/solver/random",0);
- instance->SetBool("trim/solver/showSimplex",false);
-// instance->SetBool("trim/solver/showConvergence",true);
- instance->SetBool("trim/solver/pause",false);
-
- instance->SetDouble("trim/solver/throttleGuess",0.50);
- instance->SetDouble("trim/solver/throttleMin",0.0);
- instance->SetDouble("trim/solver/throttleMax",1.0);
-// instance->SetDouble("trim/solver/throttleInitialStepSize",0.1);
- instance->SetDouble("trim/solver/throttleStep",0.1);
-
- instance->SetDouble("trim/solver/aileronGuess",0);
- instance->SetDouble("trim/solver/aileronMin",-1.00);
- instance->SetDouble("trim/solver/aileronMax",1.00);
-// instance->SetDouble("trim/solver/aileronInitialStepSize",0.1);
- instance->SetDouble("trim/solver/aileronStep",0.1);
-
- instance->SetDouble("trim/solver/rudderGuess",0);
- instance->SetDouble("trim/solver/rudderMin",-1.00);
- instance->SetDouble("trim/solver/rudderMax",1.00);
-// instance->SetDouble("trim/solver/rudderInitialStepSize",0.1);
- instance->SetDouble("trim/solver/rudderStep",0.1);
-
- instance->SetDouble("trim/solver/elevatorGuess",-0.1);
- instance->SetDouble("trim/solver/elevatorMin",-1.0);
- instance->SetDouble("trim/solver/elevatorMax",1.0);
-// instance->SetDouble("trim/solver/elevatorInitialStepSize",0.1);
- instance->SetDouble("trim/solver/elevatorStep",0.1);
-
- instance->SetDouble("trim/solver/alphaGuess",0.05);
- instance->SetDouble("trim/solver/alphaMin",-0.1);
- instance->SetDouble("trim/solver/alphaMax",.18);
-// instance->SetDouble("trim/solver/alphaInitialStepSize",0.1);
- instance->SetDouble("trim/solver/alphaStep",0.05);
-
- instance->SetDouble("trim/solver/betaGuess",0);
- instance->SetDouble("trim/solver/betaMin",-0.05);
- instance->SetDouble("trim/solver/betaMax",0.05);
-// instance->SetDouble("trim/solver/betaInitialStepSize",0.1);
- instance->SetDouble("trim/solver/betaStep",0.05);
-
- instance->SetBool("trim/solver/showConvergeStatus",true);
-// instance->SetBool("trim/solver/pause",true);
- instance->SetBool("trim/solver/variablePropPitch",false);
-// instance->SetBool("trim/solver/debugLevel",0);
+ instanceRoot->SetDouble("trim/solver/rtol",0.0001);
+ instanceRoot->SetDouble("trim/solver/speed",2);
+ instanceRoot->SetDouble("trim/solver/abstol",0.001);
+ instanceRoot->SetDouble("trim/solver/iterMax",2000);
+ instanceRoot->SetInt("trim/solver/debugLevel",0);
+ instanceRoot->SetDouble("trim/solver/random",0);
+ instanceRoot->SetBool("trim/solver/showSimplex",false);
+ instanceRoot->SetBool("trim/solver/showConvergence",false);
+ instanceRoot->SetBool("trim/solver/pause",false);
+ instanceRoot->SetBool("trim/solver/variablePropPitch",false);
+
+ instanceRoot->SetDouble("trim/solver/throttleGuess",0.50);
+ instanceRoot->SetDouble("trim/solver/throttleMin",0.0);
+ instanceRoot->SetDouble("trim/solver/throttleMax",1.0);
+ instanceRoot->SetDouble("trim/solver/throttleStep",0.1);
+
+ instanceRoot->SetDouble("trim/solver/aileronGuess",0);
+ instanceRoot->SetDouble("trim/solver/aileronMin",-1.00);
+ instanceRoot->SetDouble("trim/solver/aileronMax",1.00);
+ instanceRoot->SetDouble("trim/solver/aileronStep",0.1);
+
+ instanceRoot->SetDouble("trim/solver/rudderGuess",0);
+ instanceRoot->SetDouble("trim/solver/rudderMin",-1.00);
+ instanceRoot->SetDouble("trim/solver/rudderMax",1.00);
+ instanceRoot->SetDouble("trim/solver/rudderStep",0.1);
+
+ instanceRoot->SetDouble("trim/solver/elevatorGuess",-0.1);
+ instanceRoot->SetDouble("trim/solver/elevatorMin",-1.0);
+ instanceRoot->SetDouble("trim/solver/elevatorMax",1.0);
+ instanceRoot->SetDouble("trim/solver/elevatorStep",0.1);
+
+ instanceRoot->SetDouble("trim/solver/alphaGuess",0.05);
+ instanceRoot->SetDouble("trim/solver/alphaMin",-0.1);
+ instanceRoot->SetDouble("trim/solver/alphaMax",.18);
+ instanceRoot->SetDouble("trim/solver/alphaStep",0.05);
+
+ instanceRoot->SetDouble("trim/solver/betaGuess",0);
+ instanceRoot->SetDouble("trim/solver/betaMin",-0.1);
+ instanceRoot->SetDouble("trim/solver/betaMax",0.1);
+ instanceRoot->SetDouble("trim/solver/betaStep",0.0001);
Constructing = false;
}
Unbind();
DeAllocate();
+ delete instance;
+
if (IdFDM == 0) { // Meaning this is no child FDM
if(Root != 0) {
if(StandAlone)
if (result) {
struct PropertyCatalogStructure masterPCS;
masterPCS.base_string = "";
- masterPCS.node = (FGPropertyManager*)Root;
+ masterPCS.node = Root->GetNode();
BuildPropertyCatalog(&masterPCS);
}
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) {
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);
}
}
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);
+}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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
property actually maps toa function call of DoTrim().
@author Jon S. Berndt
- @version $Revision: 1.80 $
+ @version $Revision: 1.83 $
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
/** 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.
/** 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:
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.
/// Name of the property.
string base_string;
/// The node for the property.
- FGPropertyManager *node;
+ FGPropertyNode_ptr node;
};
/** Builds a catalog of properties.
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;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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;
/** 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;
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);
}
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);
}
}
- 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) );
FGJSBsim::~FGJSBsim(void)
{
delete fdmex;
+ delete PropertyManager;
}
/******************************************************************************/
class FGInitialCondition;
class FGLocation;
class FGAccelerations;
+class FGPropertyManager;
}
// Adding it here will cause a namespace clash in FlightGear -EMH-
JSBSim::FGGroundReactions* GroundReactions;
JSBSim::FGInertial* Inertial;
JSBSim::FGAccelerations* Accelerations;
+ JSBSim::FGPropertyManager* PropertyManager;
int runcount;
double trim_elev;
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
* 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/>.
*/
FGSimplexTrim::FGSimplexTrim(FGFDMExec * fdm, TrimMode mode)
{
- std::clock_t time_start=clock(), time_trimDone, time_linDone;
+ std::clock_t time_start=clock(), time_trimDone, time_linDone;
+
+ // variables
+ FGTrimmer::Constraints constraints;
+
+ if (fdm->GetDebugLevel() > 0) {
+ std::cout << "\n-----Performing Simplex Based Trim --------------\n" << std::endl;
+ }
+
+ // defaults
+ std::string aircraftName = fdm->GetAircraft()->GetAircraftName();
+ FGPropertyNode* node = fdm->GetPropertyManager()->GetNode();
+ double rtol = node->GetDouble("trim/solver/rtol");
+ double abstol = node->GetDouble("trim/solver/abstol");
+ double speed = node->GetDouble("trim/solver/speed"); // must be > 1, 2 typical
+ double random = node->GetDouble("trim/solver/random");
+ int iterMax = node->GetDouble("trim/solver/iterMax");
+ bool showConvergence = node->GetBool("trim/solver/showConvergence");
+ bool pause = node->GetBool("trim/solver/pause");
+ bool showSimplex = node->GetBool("trim/solver/showSimplex");
+ bool variablePropPitch = node->GetBool("trim/solver/variablePropPitch");
+
+ // flight conditions
+ double phi = fdm->GetIC()->GetPhiRadIC();
+ double theta = fdm->GetIC()->GetThetaRadIC();
+ double psi = fdm->GetIC()->GetPsiRadIC();
+ double gd = fdm->GetInertial()->gravity();
+
+ constraints.velocity = fdm->GetIC()->GetVtrueFpsIC();
+ constraints.altitude = fdm->GetIC()->GetAltitudeASLFtIC();
+ constraints.gamma = fdm->GetIC()->GetFlightPathAngleRadIC();
+ constraints.rollRate = 0;
+ constraints.pitchRate = 0;
+ constraints.yawRate = tan(phi)*gd*cos(theta)/constraints.velocity;
- // variables
- fdm->Setdt(1./120);
- FGTrimmer::Constraints constraints;
-
- std::cout << "\n-----Performing Simplex Based Trim --------------\n" << std::endl;
-
- // defaults
- constraints.velocity = fdm->GetAuxiliary()->GetVt();
- constraints.altitude = fdm->GetPropagate()->GetAltitudeASL();
- std::string aircraft = fdm->GetAircraft()->GetAircraftName();
- double rtol = fdm->GetPropertyManager()->GetDouble("trim/solver/rtol");
- double abstol = fdm->GetPropertyManager()->GetDouble("trim/solver/abstol");
- double speed = fdm->GetPropertyManager()->GetDouble("trim/solver/speed"); // must be > 1, 2 typical
- double random = fdm->GetPropertyManager()->GetDouble("trim/solver/random");
- int iterMax = fdm->GetPropertyManager()->GetDouble("trim/solver/iterMax");
- bool showConvergeStatus = fdm->GetPropertyManager()->GetBool("trim/solver/showConvergeStatus");
- bool pause = fdm->GetPropertyManager()->GetBool("trim/solver/pause");
- bool showSimplex = fdm->GetPropertyManager()->GetBool("trim/solver/showSimplex");
- bool variablePropPitch = fdm->GetPropertyManager()->GetBool("trim/solver/variablePropPitch");
- //int debugLevel = fdm->GetPropertyManager()->GetInt("trim/solver/debugLevel");
-
- std::string fileName = aircraft;
-
- // input
- //std::cout << "input ( press enter to accept [default] )\n" << std::endl;
-
- // load model
- std::string aircraftName = fdm->GetAircraft()->GetAircraftName();
- //prompt("\tdebug level\t\t",debugLevel);
- //fdm->SetDebugLevel(debugLevel);
- //std::cout << "model selection" << std::endl;
- //while (1)
- //{
- //prompt("\taircraft\t\t",aircraft);
- //prompt("\toutput file name\t",fileName);
- //fdm->LoadModel("../aircraft","../engine","../systems",aircraft);
- //aircraftName = fdm->GetAircraft()->GetAircraftName();
- //if (aircraftName == "")
- //{
- //std::cout << "\tfailed to load aircraft" << std::endl;
- //}
- //else
- //{
- //std::cout << "\tsuccessfully loaded: " << aircraftName << std::endl;
- //break;
- //}
- //}
-
- // Turn on propulsion system
- fdm->GetPropulsion()->InitRunning(-1);
-
- // get propulsion pointer to determine type/ etc.
- FGEngine * engine0 = fdm->GetPropulsion()->GetEngine(0);
- FGThruster * thruster0 = engine0->GetThruster();
-
- // flight conditions
- //std::cout << "\nflight conditions: " << std::endl;
- //prompt("\taltitude, ft\t\t",constraints.altitude);
- //prompt("\tvelocity, ft/s\t\t",constraints.velocity);
- //prompt("\tgamma, deg\t\t",constraints.gamma); constraints.gamma = constraints.gamma*M_PI/180;
-
- //double phi = fdm->GetPropagate()->GetEuler(1);
- double theta = fdm->GetPropagate()->GetEuler(2);
- //double psi = fdm->GetPropagate()->GetEuler(3);
-
- // TODO check that this works properly
- constraints.gamma = theta;
-
- //if (thruster0->GetType()==FGThruster::ttPropeller)
- //prompt("\tvariable prop pitch?\t\t",variablePropPitch);
- // FIXME, enable
-
- constraints.rollRate = fdm->GetIC()->GetPRadpsIC();
- constraints.pitchRate = fdm->GetIC()->GetQRadpsIC();
- constraints.yawRate = fdm->GetIC()->GetRRadpsIC();
constraints.stabAxisRoll = true; // FIXME, make this an option
- // solver properties
- // TODO make these options
- //std::cout << "\nsolver properties: " << std::endl;
- //std::cout << std::scientific;
- //prompt("\tshow converge status?\t",showConvergeStatus);
- //prompt("\tshow simplex?\t\t",showSimplex);
- //prompt("\tpause?\t\t\t",pause);
- //prompt("\trelative tolerance\t",rtol);
- //prompt("\tabsolute tolerance\t",abstol);
- //prompt("\tmax iterations\t\t",iterMax);
- //prompt("\tconvergence speed\t",speed);
- //prompt("\trandomization ratio\t",random);
- //std::cout << std::fixed;
-
- // initial solver state
- int n = 6;
- std::vector<double> initialGuess(n), lowerBound(n), upperBound(n), initialStepSize(n);
-
- lowerBound[0] = fdm->GetPropertyManager()->GetDouble("trim/solver/throttleMin");
- lowerBound[1] = fdm->GetPropertyManager()->GetDouble("trim/solver/elevatorMin");
- lowerBound[2] = fdm->GetPropertyManager()->GetDouble("trim/solver/alphaMin");
- lowerBound[3] = fdm->GetPropertyManager()->GetDouble("trim/solver/aileronMin");
- lowerBound[4] = fdm->GetPropertyManager()->GetDouble("trim/solver/rudderMin");
- lowerBound[5] = fdm->GetPropertyManager()->GetDouble("trim/solver/betaMin");
-
- upperBound[0] = fdm->GetPropertyManager()->GetDouble("trim/solver/throttleMax");
- upperBound[1] = fdm->GetPropertyManager()->GetDouble("trim/solver/elevatorMax");
- upperBound[2] = fdm->GetPropertyManager()->GetDouble("trim/solver/alphaMax");
- upperBound[3] = fdm->GetPropertyManager()->GetDouble("trim/solver/aileronMax");
- upperBound[4] = fdm->GetPropertyManager()->GetDouble("trim/solver/rudderMax");
- upperBound[5] = fdm->GetPropertyManager()->GetDouble("trim/solver/betaMax");
-
- initialStepSize[0] = fdm->GetPropertyManager()->GetDouble("trim/solver/throttleStep");
- initialStepSize[1] = fdm->GetPropertyManager()->GetDouble("trim/solver/elevatorStep");
- initialStepSize[2] = fdm->GetPropertyManager()->GetDouble("trim/solver/alphaStep");
- initialStepSize[3] = fdm->GetPropertyManager()->GetDouble("trim/solver/aileronStep");
- initialStepSize[4] = fdm->GetPropertyManager()->GetDouble("trim/solver/rudderStep");
- initialStepSize[5] = fdm->GetPropertyManager()->GetDouble("trim/solver/betaStep");
-
- initialGuess[0] = fdm->GetPropertyManager()->GetDouble("trim/solver/throttleGuess");
- initialGuess[1] = fdm->GetPropertyManager()->GetDouble("trim/solver/elevatorGuess");
- initialGuess[2] = fdm->GetPropertyManager()->GetDouble("trim/solver/alphaGuess");
- initialGuess[3] = fdm->GetPropertyManager()->GetDouble("trim/solver/aileronGuess");
- initialGuess[4] = fdm->GetPropertyManager()->GetDouble("trim/solver/rudderGuess");
- initialGuess[5] = fdm->GetPropertyManager()->GetDouble("trim/solver/betaGuess");
-
- // solve
- FGTrimmer trimmer(fdm, &constraints);
- Callback callback(fileName,&trimmer);
- FGNelderMead * solver = NULL;
- try
- {
- solver = new FGNelderMead(&trimmer,initialGuess,
- lowerBound, upperBound, initialStepSize,iterMax,rtol,
- abstol,speed,random,showConvergeStatus,showSimplex,pause,&callback);
- while(solver->status()==1) solver->update();
- }
- catch (const std::runtime_error & e)
- {
- std::cout << e.what() << std::endl;
- //exit(1);
- }
-
- // output
- try
- {
- trimmer.printSolution(std::cout,solver->getSolution()); // this also loads the solution into the fdm
- std::cout << "\nfinal cost: " << std::scientific << std::setw(10) << trimmer.eval(solver->getSolution()) << std::endl;
- }
- catch(std::runtime_error & e)
- {
- std::cout << "caught std::runtime error" << std::endl;
- std::cout << "exception: " << e.what() << std::endl;
- exit(1);
- }
-
- time_trimDone = std::clock();
- std::cout << "\ntrim computation time: " << (time_trimDone - time_start)/double(CLOCKS_PER_SEC) << "s \n" << std::endl;
-
- //std::cout << "\nsimulating flight to determine trim stability" << std::endl;
-
- //std::cout << "\nt = 5 seconds" << std::endl;
- //for (int i=0;i<5*120;i++) fdm->Run();
- //trimmer.printState();
-
- //std::cout << "\nt = 10 seconds" << std::endl;
- //for (int i=0;i<5*120;i++) fdm->Run();
- //trimmer.printState();
-
- std::cout << "\nlinearization: " << std::endl;
- FGStateSpace ss(fdm);
-
- ss.x.add(new FGStateSpace::Vt);
- ss.x.add(new FGStateSpace::Alpha);
- ss.x.add(new FGStateSpace::Theta);
- ss.x.add(new FGStateSpace::Q);
-
- if (thruster0->GetType()==FGThruster::ttPropeller)
- {
- ss.x.add(new FGStateSpace::Rpm0);
- if (variablePropPitch) ss.x.add(new FGStateSpace::PropPitch);
- int numEngines = fdm->GetPropulsion()->GetNumEngines();
- if (numEngines>1) ss.x.add(new FGStateSpace::Rpm1);
- if (numEngines>2) ss.x.add(new FGStateSpace::Rpm2);
- if (numEngines>3) ss.x.add(new FGStateSpace::Rpm3);
- }
- ss.x.add(new FGStateSpace::Beta);
- ss.x.add(new FGStateSpace::Phi);
- ss.x.add(new FGStateSpace::P);
- ss.x.add(new FGStateSpace::Psi);
- ss.x.add(new FGStateSpace::R);
- ss.x.add(new FGStateSpace::Latitude);
- ss.x.add(new FGStateSpace::Longitude);
- ss.x.add(new FGStateSpace::Alt);
-
- ss.u.add(new FGStateSpace::ThrottleCmd);
- ss.u.add(new FGStateSpace::DaCmd);
- ss.u.add(new FGStateSpace::DeCmd);
- ss.u.add(new FGStateSpace::DrCmd);
-
- // state feedback
- ss.y = ss.x;
-
- std::vector< std::vector<double> > A,B,C,D;
- std::vector<double> x0 = ss.x.get(), u0 = ss.u.get();
- std::vector<double> y0 = x0; // state feedback
- std::cout << ss << std::endl;
-
- ss.linearize(x0,u0,y0,A,B,C,D);
-
- int width=10;
- std::cout.precision(3);
- std::cout
- << std::fixed
- << std::right
- << "\nA=\n" << std::setw(width) << A
- << "\nB=\n" << std::setw(width) << B
- << "\nC=\n" << std::setw(width) << C
- << "\nD=\n" << std::setw(width) << D
- << std::endl;
-
- // write scicoslab file
- std::ofstream scicos(std::string(aircraft+"_lin.sce").c_str());
- scicos.precision(10);
- width=20;
- scicos
- << std::scientific
- << aircraft << ".x0=..\n" << std::setw(width) << x0 << ";\n"
- << aircraft << ".u0=..\n" << std::setw(width) << u0 << ";\n"
- << aircraft << ".sys = syslin('c',..\n"
- << std::setw(width) << A << ",..\n"
- << std::setw(width) << B << ",..\n"
- << std::setw(width) << C << ",..\n"
- << std::setw(width) << D << ");\n"
- << aircraft << ".tfm = ss2tf(" << aircraft << ".sys);\n"
- << std::endl;
-
- time_linDone = std::clock();
- std::cout << "\nlinearization computation time: " << (time_linDone - time_trimDone)/double(CLOCKS_PER_SEC) << " s\n" << std::endl;
+ // initial solver state
+ int n = 6;
+ std::vector<double> initialGuess(n), lowerBound(n), upperBound(n), initialStepSize(n);
+
+ lowerBound[0] = node->GetDouble("trim/solver/throttleMin");
+ lowerBound[1] = node->GetDouble("trim/solver/elevatorMin");
+ lowerBound[2] = node->GetDouble("trim/solver/alphaMin");
+ lowerBound[3] = node->GetDouble("trim/solver/aileronMin");
+ lowerBound[4] = node->GetDouble("trim/solver/rudderMin");
+ lowerBound[5] = node->GetDouble("trim/solver/betaMin");
+
+ upperBound[0] = node->GetDouble("trim/solver/throttleMax");
+ upperBound[1] = node->GetDouble("trim/solver/elevatorMax");
+ upperBound[2] = node->GetDouble("trim/solver/alphaMax");
+ upperBound[3] = node->GetDouble("trim/solver/aileronMax");
+ upperBound[4] = node->GetDouble("trim/solver/rudderMax");
+ upperBound[5] = node->GetDouble("trim/solver/betaMax");
+
+ initialStepSize[0] = node->GetDouble("trim/solver/throttleStep");
+ initialStepSize[1] = node->GetDouble("trim/solver/elevatorStep");
+ initialStepSize[2] = node->GetDouble("trim/solver/alphaStep");
+ initialStepSize[3] = node->GetDouble("trim/solver/aileronStep");
+ initialStepSize[4] = node->GetDouble("trim/solver/rudderStep");
+ initialStepSize[5] = node->GetDouble("trim/solver/betaStep");
+
+ initialGuess[0] = node->GetDouble("trim/solver/throttleGuess");
+ initialGuess[1] = node->GetDouble("trim/solver/elevatorGuess");
+ initialGuess[2] = node->GetDouble("trim/solver/alphaGuess");
+ initialGuess[3] = node->GetDouble("trim/solver/aileronGuess");
+ initialGuess[4] = node->GetDouble("trim/solver/rudderGuess");
+ initialGuess[5] = node->GetDouble("trim/solver/betaGuess");
+
+ // solve
+ FGTrimmer * trimmer = new FGTrimmer(fdm, &constraints);
+ Callback callback(aircraftName, trimmer);
+ FGNelderMead * solver = NULL;
+
+ solver = new FGNelderMead(trimmer,initialGuess,
+ lowerBound, upperBound, initialStepSize,iterMax,rtol,
+ abstol,speed,random,showConvergence,showSimplex,pause,&callback);
+ while(solver->status()==1) solver->update();
+ time_trimDone = std::clock();
+
+ // output
+ if (fdm->GetDebugLevel() > 0) {
+ trimmer->printSolution(std::cout,solver->getSolution());
+ std::cout << "\nfinal cost: " << std::scientific << std::setw(10) << trimmer->eval(solver->getSolution()) << std::endl;
+ std::cout << "\ntrim computation time: " << (time_trimDone - time_start)/double(CLOCKS_PER_SEC) << "s \n" << std::endl;
+ }
if (solver) delete solver;
+ if (trimmer) delete trimmer;
}
} // JSBSim
* 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/>.
*/
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
* 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/>.
*/
{
}
-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
{
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);
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);
{
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);
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);
<< "\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"
}
-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
<< 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
* 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/>.
*/
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)
{
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-#include "FGJSBBase.h"
#include "simgear/structure/SGReferenced.hxx"
#include "simgear/structure/SGSharedPtr.hxx"
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 {
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:
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;
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
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
namespace JSBSim {
class FGFDMExec;
-class FGPropertyManager;
class Element;
class FGAerodynamics;
class FGAuxiliary;
/** 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;
}
protected:
int OutputIdx;
int SubSystems;
- std::vector <FGPropertyManager*> OutputProperties;
+ std::vector <FGPropertyNode_ptr> OutputProperties;
std::vector <std::string> OutputCaptions;
bool enabled;
namespace JSBSim {
-std::vector<SGPropertyNode_ptr> FGPropertyManager::tied_properties;
-
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void FGPropertyManager::Unbind(void)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-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);
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-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;
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-string FGPropertyManager::GetFullyQualifiedName(void) const
+string FGPropertyNode::GetFullyQualifiedName(void) const
{
vector<string> stack;
stack.push_back( getDisplayName(true) );
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-string FGPropertyManager::GetRelativeName( const string &path ) const
+string FGPropertyNode::GetRelativeName( const string &path ) const
{
string temp_string = GetFullyQualifiedName();
size_t len = path.length();
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-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)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-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)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-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)
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;
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;
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;
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;
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;
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;
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
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.
* @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);
/**
* @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.
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;
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;
}
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;
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;
}
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;
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;
}
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;
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
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;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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()) {
// Iterate over all events.
for (unsigned int ev_ctr=0; ev_ctr < Events.size(); ev_ctr++) {
+
+ struct event &thisEvent = Events[ev_ctr];
+
// Determine whether the set of conditional tests for this condition equate
// to true and should cause the event to execute. If the conditions evaluate
// to true, then the event is triggered. If the event is not persistent,
// then this trigger will remain set true. If the event is persistent,
// the trigger will reset to false when the condition evaluates to false.
- if (Events[ev_ctr].Condition->Evaluate()) {
- if (!Events[ev_ctr].Triggered) {
+ if (thisEvent.Condition->Evaluate()) {
+ if (!thisEvent.Triggered) {
// The conditions are true, do the setting of the desired Event parameters
- for (i=0; i<Events[ev_ctr].SetValue.size(); i++) {
- Events[ev_ctr].OriginalValue[i] = Events[ev_ctr].SetParam[i]->getDoubleValue();
- if (Events[ev_ctr].Functions[i] != 0) { // Parameter should be set to a function value
+ for (i=0; i<thisEvent.SetValue.size(); i++) {
+ if (thisEvent.SetParam[i] == 0L) { // Late bind property if necessary
+ if (PropertyManager->HasNode(thisEvent.SetParamName[i])) {
+ thisEvent.SetParam[i] = PropertyManager->GetNode(thisEvent.SetParamName[i]);
+ } else {
+ throw("No property, \""+thisEvent.SetParamName[i]+"\" is defined.");
+ }
+ }
+ thisEvent.OriginalValue[i] = thisEvent.SetParam[i]->getDoubleValue();
+ if (thisEvent.Functions[i] != 0) { // Parameter should be set to a function value
try {
- Events[ev_ctr].SetValue[i] = Events[ev_ctr].Functions[i]->GetValue();
+ thisEvent.SetValue[i] = thisEvent.Functions[i]->GetValue();
} catch (string msg) {
std::cerr << std::endl << "A problem occurred in the execution of the script. " << msg << endl;
throw;
}
}
- switch (Events[ev_ctr].Type[i]) {
+ switch (thisEvent.Type[i]) {
case FG_VALUE:
case FG_BOOL:
- Events[ev_ctr].newValue[i] = Events[ev_ctr].SetValue[i];
+ thisEvent.newValue[i] = thisEvent.SetValue[i];
break;
case FG_DELTA:
- Events[ev_ctr].newValue[i] = Events[ev_ctr].OriginalValue[i] + Events[ev_ctr].SetValue[i];
+ thisEvent.newValue[i] = thisEvent.OriginalValue[i] + thisEvent.SetValue[i];
break;
default:
cerr << "Invalid Type specified" << endl;
break;
}
- Events[ev_ctr].StartTime = currentTime + Events[ev_ctr].Delay;
- Events[ev_ctr].ValueSpan[i] = Events[ev_ctr].newValue[i] - Events[ev_ctr].OriginalValue[i];
- Events[ev_ctr].Transiting[i] = true;
+ thisEvent.StartTime = currentTime + thisEvent.Delay;
+ thisEvent.ValueSpan[i] = thisEvent.newValue[i] - thisEvent.OriginalValue[i];
+ thisEvent.Transiting[i] = true;
}
}
- Events[ev_ctr].Triggered = true;
-
- } else if (Events[ev_ctr].Persistent) { // If the event is persistent, reset the trigger.
- Events[ev_ctr].Triggered = false; // Reset the trigger for persistent events
- Events[ev_ctr].Notified = false; // Also reset the notification flag
- } else if (Events[ev_ctr].Continuous) { // If the event is continuous, reset the trigger.
- Events[ev_ctr].Triggered = false; // Reset the trigger for persistent events
- Events[ev_ctr].Notified = false; // Also reset the notification flag
+ thisEvent.Triggered = true;
+
+ } else if (thisEvent.Persistent) { // If the event is persistent, reset the trigger.
+ thisEvent.Triggered = false; // Reset the trigger for persistent events
+ thisEvent.Notified = false; // Also reset the notification flag
+ } else if (thisEvent.Continuous) { // If the event is continuous, reset the trigger.
+ thisEvent.Triggered = false; // Reset the trigger for persistent events
+ thisEvent.Notified = false; // Also reset the notification flag
}
- if ((currentTime >= Events[ev_ctr].StartTime) && Events[ev_ctr].Triggered) {
+ if ((currentTime >= thisEvent.StartTime) && thisEvent.Triggered) {
- for (i=0; i<Events[ev_ctr].SetValue.size(); i++) {
- if (Events[ev_ctr].Transiting[i]) {
- Events[ev_ctr].TimeSpan = currentTime - Events[ev_ctr].StartTime;
- switch (Events[ev_ctr].Action[i]) {
+ for (i=0; i<thisEvent.SetValue.size(); i++) {
+ if (thisEvent.Transiting[i]) {
+ thisEvent.TimeSpan = currentTime - thisEvent.StartTime;
+ switch (thisEvent.Action[i]) {
case FG_RAMP:
- if (Events[ev_ctr].TimeSpan <= Events[ev_ctr].TC[i]) {
- newSetValue = Events[ev_ctr].TimeSpan/Events[ev_ctr].TC[i] * Events[ev_ctr].ValueSpan[i] + Events[ev_ctr].OriginalValue[i];
+ if (thisEvent.TimeSpan <= thisEvent.TC[i]) {
+ newSetValue = thisEvent.TimeSpan/thisEvent.TC[i] * thisEvent.ValueSpan[i] + thisEvent.OriginalValue[i];
} else {
- newSetValue = Events[ev_ctr].newValue[i];
- if (Events[ev_ctr].Continuous != true) Events[ev_ctr].Transiting[i] = false;
+ newSetValue = thisEvent.newValue[i];
+ if (thisEvent.Continuous != true) thisEvent.Transiting[i] = false;
}
break;
case FG_STEP:
- newSetValue = Events[ev_ctr].newValue[i];
+ newSetValue = thisEvent.newValue[i];
// If this is not a continuous event, reset the transiting flag.
// Otherwise, it is known that the event is a continuous event.
// Furthermore, if the event is to be determined by a function,
// then the function will be continuously calculated.
- if (Events[ev_ctr].Continuous != true)
- Events[ev_ctr].Transiting[i] = false;
- else if (Events[ev_ctr].Functions[i] != 0)
- newSetValue = Events[ev_ctr].Functions[i]->GetValue();
+ if (thisEvent.Continuous != true)
+ thisEvent.Transiting[i] = false;
+ else if (thisEvent.Functions[i] != 0)
+ newSetValue = thisEvent.Functions[i]->GetValue();
break;
case FG_EXP:
- newSetValue = (1 - exp( -Events[ev_ctr].TimeSpan/Events[ev_ctr].TC[i] )) * Events[ev_ctr].ValueSpan[i] + Events[ev_ctr].OriginalValue[i];
+ newSetValue = (1 - exp( -thisEvent.TimeSpan/thisEvent.TC[i] )) * thisEvent.ValueSpan[i] + thisEvent.OriginalValue[i];
break;
default:
cerr << "Invalid Action specified" << endl;
break;
}
- Events[ev_ctr].SetParam[i]->setDoubleValue(newSetValue);
+ thisEvent.SetParam[i]->setDoubleValue(newSetValue);
}
}
// Print notification values after setting them
- if (Events[ev_ctr].Notify && !Events[ev_ctr].Notified) {
- cout << endl << " Event " << event_ctr << " (" << Events[ev_ctr].Name << ")"
+ if (thisEvent.Notify && !thisEvent.Notified) {
+ cout << endl << " Event " << event_ctr << " (" << thisEvent.Name << ")"
<< " executed at time: " << currentTime << endl;
- if (!Events[ev_ctr].Description.empty()) {
- cout << " " << Events[ev_ctr].Description << endl;
+ if (!thisEvent.Description.empty()) {
+ cout << " " << thisEvent.Description << endl;
}
- for (j=0; j<Events[ev_ctr].NotifyProperties.size();j++) {
-// cout << " " << Events[ev_ctr].NotifyProperties[j]->GetRelativeName()
- cout << " " << Events[ev_ctr].DisplayString[j]
- << " = " << Events[ev_ctr].NotifyProperties[j]->getDoubleValue() << endl;
+ for (j=0; j<thisEvent.NotifyProperties.size();j++) {
+// cout << " " << thisEvent.NotifyProperties[j]->GetRelativeName()
+ cout << " " << thisEvent.DisplayString[j]
+ << " = " << thisEvent.NotifyProperties[j]->getDoubleValue() << endl;
}
cout << endl;
- Events[ev_ctr].Notified = true;
+ thisEvent.Notified = true;
}
}
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
comes the "run" section, where the conditions are
described in "event" 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 $"
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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;
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;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
exit(-1);
}
- FGPropertyManager *node = PropertyManager->GetNode(property1, false);
+ FGPropertyNode *node = PropertyManager->GetNode(property1, false);
if (node) {
TestParam1 = new FGPropertyValue(node);
} else {
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;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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";
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;
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) {
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 ));
}
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 ||
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;
}
}
- // 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);
- // }
}
}
#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
namespace JSBSim {
-class FGPropertyManager;
class Element;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- 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)
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>
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
*/
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;
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,
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);
* 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/>.
*/
#include <cstdlib>
#include <iomanip>
#include <iostream>
+#include <sstream>
#include <stdexcept>
#include <ctime>
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),
m_iMax(1), m_iNextMax(1), m_iMin(1),
m_simplex(m_nVert), m_cost(m_nVert), m_elemSum(m_nDim),
m_status(1),
- initialGuess(initialGuess), initialStepSize(initialStepSize),
- iterMax(iterMax), iter(), rtol(rtol), abstol(abstol),
- speed(speed), showConvergeStatus(showConvergeStatus), showSimplex(showSimplex),
- pause(pause), rtolI(), minCostPrevResize(1), minCost(), minCostPrev(), maxCost(),
- nextMaxCost()
+ initialGuess(initialGuess), initialStepSize(initialStepSize),
+ iterMax(iterMax), iter(), rtol(rtol), abstol(abstol),
+ speed(speed), showConvergeStatus(showConvergeStatus), showSimplex(showSimplex),
+ pause(pause), rtolI(), minCostPrevResize(1), minCost(), minCostPrev(), maxCost(),
+ nextMaxCost()
{
- srand ( time(NULL) ); // seed random number generator
+ srand ( time(NULL) ); // seed random number generator
}
void FGNelderMead::update()
{
std::cout.precision(3);
- // reinitialize simplex whenever rtol condition is met
- if ( rtolI < rtol || iter == 0)
- {
- std::vector<double> guess(m_nDim);
- if (iter == 0)
- {
- //std::cout << "constructing simplex" << std::endl;
- guess = initialGuess;
- }
- else
- {
- if (std::abs(minCost-minCostPrevResize) < abstol)
- {
- std::cout << "\nunable to escape local minimum" << std::endl;
- m_status = -1;
- return;
- }
- //std::cout << "reinitializing step size" << std::endl;
- guess = m_simplex[m_iMin];
- minCostPrevResize = minCost;
- }
- constructSimplex(guess,initialStepSize);
- }
-
- // find vertex costs
- for (int vertex=0;vertex<m_nVert;vertex++)
- {
- try
- {
- m_cost[vertex] = m_f->eval(m_simplex[vertex]);
- }
- catch (const std::exception & e)
- {
- m_status = -1;
- throw;
- return;
- }
- }
-
- // find max cost, next max cost, and min cost
- m_iMax = m_iNextMax = m_iMin = 0;
- for (int vertex=0;vertex<m_nVert;vertex++)
- {
- if ( m_cost[vertex] > m_cost[m_iMax] )
- {
- m_iMax = vertex;
- }
- else if ( m_cost[vertex] > m_cost[m_iNextMax] || m_iMax == m_iNextMax ) m_iNextMax = vertex;
- else if ( m_cost[vertex] < m_cost[m_iMin] ) m_iMin = vertex;
-
- }
-
- // callback
- if (m_callback) m_callback->eval(m_simplex[m_iMin]);
-
- // compute relative tolerance
- rtolI = 2*std::abs(m_cost[m_iMax] -
- m_cost[m_iMin])/(std::abs(m_cost[m_iMax]+std::abs(m_cost[m_iMin])+
- std::numeric_limits<double>::epsilon()));
-
- // check for max iteration break condition
- if (iter > iterMax)
- {
- std::cout << "\nmax iterations exceeded" << std::endl;
- m_status = -1;
- return;
- }
- // check for convergence break condition
- else if ( m_cost[m_iMin] < abstol )
- {
- std::cout << "\nsimplex converged" << std::endl;
- m_status = 0;
- return;
- }
-
- // compute element sum of simplex vertices
- for (int dim=0;dim<m_nDim;dim++)
- {
- m_elemSum[dim] = 0;
- for (int vertex=0;vertex<m_nVert;vertex++)
- m_elemSum[dim] += m_simplex[vertex][dim];
- }
-
- // min and max costs
- minCostPrev = minCost;
- minCost = m_cost[m_iMin];
- maxCost = m_cost[m_iMax];
- nextMaxCost = m_cost[m_iNextMax];
-
- // output cost and simplex
- if (showConvergeStatus)
- {
- if ( (minCostPrev + std::numeric_limits<float>::epsilon() )
- < minCost && minCostPrev != 0)
- {
- std::cout << "\twarning: simplex cost increased"
- << std::scientific
- << "\n\tcost: " << minCost
- << "\n\tcost previous: " << minCostPrev
- << std::fixed << std::endl;
- }
-
- std::cout << "i: " << iter
- << std::scientific
- << "\tcost: " << m_cost[m_iMin]
- << "\trtol: " << rtolI
- << std::fixed
- << "\talpha: " << m_simplex[m_iMin][2]*180/M_PI
- << "\tbeta: " << m_simplex[m_iMin][5]*180/M_PI
- << "\tthrottle: " << m_simplex[m_iMin][0]
- << "\televator: " << m_simplex[m_iMin][1]
- << "\taileron: " << m_simplex[m_iMin][3]
- << "\trudder: " << m_simplex[m_iMin][4]
- << std::endl;
- }
- if (showSimplex)
- {
- std::cout << "simplex: " << std::endl;;
- for (int j=0;j<m_nVert;j++)
- std::cout << "\t" << std::scientific
- << std::setw(10) << m_cost[j];
- std::cout << std::endl;
- for (int j=0;j<m_nVert;j++) std::cout << "\t\t" << j;
- std::cout << std::endl;
- for (int i=0;i<m_nDim;i++)
- {
- for (int j=0;j<m_nVert;j++)
- std::cout << "\t" << std::setw(10) << m_simplex[j][i];
- std::cout << std::endl;
- }
- std::cout << std::fixed
- << "\n\tiMax: " << m_iMax
- << "\t\tiNextMax: " << m_iNextMax
- << "\t\tiMin: " << m_iMin << std::endl;
- }
-
- if (pause)
- {
- std::cout << "paused, press any key to continue" << std::endl;
- std::cin.get();
- }
-
-
- // costs
-
- try
- {
- // try inversion
- double costTry = tryStretch(-1.0);
- //std::cout << "cost Try 0: " << costTry << std::endl;
-
- // if lower cost than best, then try further stretch by double speed factor
- if (costTry < minCost)
- {
- double costTry0 = costTry;
- costTry = tryStretch(speed);
- //std::cout << "cost Try 1: " << costTry << std::endl;
-
- if (showSimplex)
- {
- if (costTry < costTry0) std::cout << "inversion about: " << m_iMax << std::endl;
- else std::cout << "inversion and stretch about: " << m_iMax << std::endl;
- }
- }
- // otherwise try a contraction
- else if (costTry > nextMaxCost)
- {
- // 1d contraction
- costTry = tryStretch(1./speed);
- //std::cout << "cost Try 2: " << costTry << std::endl;
-
- // if greater than max cost, contract about min
- if (costTry > maxCost)
- {
- if (showSimplex)
- std::cout << "multiD contraction about: " << m_iMin << std::endl;
- contract();
- }
- else
- {
- if (showSimplex)
- std::cout << "contraction about: " << m_iMin << std::endl;
- }
- }
- }
-
- catch (const std::exception & e)
- {
- throw;
- m_status = -1;
- return;
- }
-
- // iteration
- iter++;
+ // reinitialize simplex whenever rtol condition is met
+ if ( rtolI < rtol || iter == 0)
+ {
+ std::vector<double> guess(m_nDim);
+ if (iter == 0)
+ {
+ //std::cout << "constructing simplex" << std::endl;
+ guess = initialGuess;
+ }
+ else
+ {
+ if (std::abs(minCost-minCostPrevResize) < std::numeric_limits<float>::epsilon())
+ {
+ throw std::runtime_error("unable to escape local minimum!");
+ m_status = -1;
+ return;
+ }
+ //std::cout << "reinitializing step size" << std::endl;
+ guess = m_simplex[m_iMin];
+ minCostPrevResize = minCost;
+ }
+ constructSimplex(guess,initialStepSize);
+ }
+
+ // find vertex costs
+ for (int vertex=0;vertex<m_nVert;vertex++)
+ {
+ try
+ {
+ m_cost[vertex] = eval(m_simplex[vertex]);
+ }
+ catch (const std::exception & e)
+ {
+ m_status = -1;
+ throw;
+ return;
+ }
+ }
+
+ // find max cost, next max cost, and min cost
+ m_iMax = m_iNextMax = m_iMin = 0;
+ for (int vertex=0;vertex<m_nVert;vertex++)
+ {
+ if ( m_cost[vertex] > m_cost[m_iMax] )
+ {
+ m_iMax = vertex;
+ }
+ else if ( m_cost[vertex] > m_cost[m_iNextMax] || m_iMax == m_iNextMax ) m_iNextMax = vertex;
+ else if ( m_cost[vertex] < m_cost[m_iMin] ) m_iMin = vertex;
+
+ }
+
+ // callback
+ if (m_callback) m_callback->eval(m_simplex[m_iMin]);
+
+ // compute relative tolerance
+ rtolI = 2*std::abs(m_cost[m_iMax] -
+ m_cost[m_iMin])/(std::abs(m_cost[m_iMax]+std::abs(m_cost[m_iMin])+
+ std::numeric_limits<double>::epsilon()));
+
+ // check for max iteration break condition
+ if (iter > iterMax)
+ {
+ m_status = -1;
+ throw std::runtime_error("max iterations exceeded!");
+ return;
+ }
+ // check for convergence break condition
+ else if ( m_cost[m_iMin] < abstol )
+ {
+ //std::cout << "\nsimplex converged" << std::endl;
+ m_status = 0;
+ return;
+ }
+
+ // compute element sum of simplex vertices
+ for (int dim=0;dim<m_nDim;dim++)
+ {
+ m_elemSum[dim] = 0;
+ for (int vertex=0;vertex<m_nVert;vertex++)
+ m_elemSum[dim] += m_simplex[vertex][dim];
+ }
+
+ // min and max costs
+ minCostPrev = minCost;
+ minCost = m_cost[m_iMin];
+ maxCost = m_cost[m_iMax];
+ nextMaxCost = m_cost[m_iNextMax];
+
+ // output cost and simplex
+ if (showConvergeStatus)
+ {
+ if ( (minCostPrev + std::numeric_limits<float>::epsilon() )
+ < minCost && minCostPrev != 0)
+ {
+ std::cout << "\twarning: simplex cost increased"
+ << std::scientific
+ << "\n\tcost: " << minCost
+ << "\n\tcost previous: " << minCostPrev
+ << std::fixed << std::endl;
+ }
+
+ std::cout << "i: " << iter
+ << std::scientific
+ << "\tcost: " << m_cost[m_iMin]
+ << "\trtol: " << rtolI
+ << std::fixed
+ << "\talpha: " << m_simplex[m_iMin][2]*180/M_PI
+ << "\tbeta: " << m_simplex[m_iMin][5]*180/M_PI
+ << "\tthrottle: " << m_simplex[m_iMin][0]
+ << "\televator: " << m_simplex[m_iMin][1]
+ << "\taileron: " << m_simplex[m_iMin][3]
+ << "\trudder: " << m_simplex[m_iMin][4]
+ << std::endl;
+ }
+ if (showSimplex)
+ {
+ std::cout << "simplex: " << std::endl;;
+ for (int j=0;j<m_nVert;j++)
+ std::cout << "\t" << std::scientific
+ << std::setw(10) << m_cost[j];
+ std::cout << std::endl;
+ for (int j=0;j<m_nVert;j++) std::cout << "\t\t" << j;
+ std::cout << std::endl;
+ for (int i=0;i<m_nDim;i++)
+ {
+ for (int j=0;j<m_nVert;j++)
+ std::cout << "\t" << std::setw(10) << m_simplex[j][i];
+ std::cout << std::endl;
+ }
+ std::cout << std::fixed
+ << "\n\tiMax: " << m_iMax
+ << "\t\tiNextMax: " << m_iNextMax
+ << "\t\tiMin: " << m_iMin << std::endl;
+ }
+
+ if (pause)
+ {
+ std::cout << "paused, press any key to continue" << std::endl;
+ std::cin.get();
+ }
+
+
+ // costs
+
+ try
+ {
+ // try inversion
+ double costTry = tryStretch(-1.0);
+ //std::cout << "cost Try 0: " << costTry << std::endl;
+
+ // if lower cost than best, then try further stretch by double speed factor
+ if (costTry < minCost)
+ {
+ double costTry0 = costTry;
+ costTry = tryStretch(speed);
+ //std::cout << "cost Try 1: " << costTry << std::endl;
+
+ if (showSimplex)
+ {
+ if (costTry < costTry0) std::cout << "inversion about: " << m_iMax << std::endl;
+ else std::cout << "inversion and stretch about: " << m_iMax << std::endl;
+ }
+ }
+ // otherwise try a contraction
+ else if (costTry > nextMaxCost)
+ {
+ // 1d contraction
+ costTry = tryStretch(1./speed);
+ //std::cout << "cost Try 2: " << costTry << std::endl;
+
+ // if greater than max cost, contract about min
+ if (costTry > maxCost)
+ {
+ if (showSimplex)
+ std::cout << "multiD contraction about: " << m_iMin << std::endl;
+ contract();
+ }
+ else
+ {
+ if (showSimplex)
+ std::cout << "contraction about: " << m_iMin << std::endl;
+ }
+ }
+ }
+
+ catch (const std::exception & e)
+ {
+ throw;
+ m_status = -1;
+ return;
+ }
+
+ // iteration
+ iter++;
}
int FGNelderMead::status()
{
- return m_status;
+ return m_status;
}
double FGNelderMead::getRandomFactor()
{
- double randFact = 1+(float(rand() % 1000)/500-1)*m_randomization;
- //std::cout << "random factor: " << randFact << std::endl;;
- return randFact;
+ double randFact = 1+(float(rand() % 1000)/500-1)*m_randomization;
+ //std::cout << "random factor: " << randFact << std::endl;;
+ return randFact;
}
std::vector<double> FGNelderMead::getSolution()
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;
}
// 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])
for (int vertex=0;vertex<m_nVert;vertex++)
{
m_simplex[vertex] = guess;
- }
+ }
for (int dim=0;dim<m_nDim;dim++)
{
}
}
+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
* 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/>.
*/
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;
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
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#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)
{
}
double FGPropertyValue::GetValue(void) const
{
- FGPropertyManager* node = PropertyNode;
+ FGPropertyNode* node = PropertyNode;
if (!PropertyNode) {
// The node cannot be cached since this is a const method.
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
{
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;
};
* 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
{
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)
* 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/>.
*/
#include "models/FGFCS.h"
#include <fstream>
#include <iostream>
+#include <limits>
namespace JSBSim
{
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);
}
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)
void set(int i, double val)
{
m_components[i]->set(val);
- m_fdm->RunIC();
+ m_stateSpace->run();
};
double get(int i)
{
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
{
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();
};
- class VGround : public Component
+ class VGround : public Component
{
public:
VGround() : Component("VGround","ft/s") {};
}
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") {};
}
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") {};
}
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") {};
}
void set(double val)
{
- // XXX: not possible to implement currently
+ // XXX: not possible to implement currently
}
};
}
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
{
}
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
{
}
void set(double val)
{
+ double psi = m_fdm->GetIC()->GetPsiRadIC();
m_fdm->GetIC()->SetBetaRadIC(val);
+ m_fdm->GetIC()->SetPsiRadIC(psi);
}
double getDeriv() const
{
}
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") {};
}
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") {};
}
void set(double val)
{
- m_fdm->GetPropulsion()->GetEngine(3)->GetThruster()->SetRPM(val);
+ m_fdm->GetPropulsion()->GetEngine(3)->GetThruster()->SetRPM(val);
}
};
}
};
- class Pi : public Component
+ class Pi : public Component
{
public:
Pi() : Component("P inertial","rad/s") {};
}
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
{
}
};
- class Qi : public Component
+ class Qi : public Component
{
public:
Qi() : Component("Q inertial","rad/s") {};
}
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
{
}
};
- class Ri : public Component
+ class Ri : public Component
{
public:
Ri() : Component("R inertial","rad/s") {};
}
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
{
}
};
- class Vn : public Component
+ class Vn : public Component
{
public:
Vn() : Component("Vel north","feet/s") {};
}
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") {};
}
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") {};
}
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;
}
};
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;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
string call_type;
string parent_type;
string brkpt_string;
- FGPropertyManager* node;
+ FGPropertyNode* node;
Element *tableData=0;
Element *parent_element=0;
Element *axisElement=0;
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
namespace JSBSim {
-class FGPropertyManager;
class Element;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@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 $
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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;}
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;
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;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// 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;
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;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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;
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;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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();
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();
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);
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); */
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
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 $
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
/** 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; }
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
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;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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;
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) {
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
class FGFCSChannel {
public:
/// Constructor
- FGFCSChannel(FGPropertyManager* node=0) :
+ FGFCSChannel(FGPropertyNode* node=0) :
OnOffNode(node)
{
}
private:
FCSCompVec FCSComponents;
- const FGPropertyManager* OnOffNode;
+ FGConstPropertyNode_ptr OnOffNode;
};
}
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
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]
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";
// 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;
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;
}
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
}
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 );
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;
}
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
}
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
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
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]
// 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.
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]
// 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).
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;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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
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
ResetReporting();
}
- }
- else if (gearPos < 0.01) { // Gear UP
+
+ } else if (gearPos < 0.01) { // Gear UP
+
WOW = false;
vWhlVelVec.InitMatrix();
}
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;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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;
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
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 $
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@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
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;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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);
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
@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 $
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
*/
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
*/
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.
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;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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);
} 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;
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
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
@endcode
@author Jon S. Berndt
-@version $Revision: 1.14 $
+@version $Revision: 1.15 $
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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;
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
class FGFCS;
class Element;
-class FGPropertyManager;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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 $
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
private:
double width;
double gain;
- FGPropertyManager* WidthPropertyNode;
+ FGPropertyNode_ptr WidthPropertyNode;
double WidthPropertySign;
void Debug(int from);
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;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
} 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 ));
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;
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
namespace JSBSim {
class FGFCS;
-class FGPropertyManager;
class Element;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- 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
*/
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;
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
output, such as the elevator, or speedbrake, etc.
@author Jon S. Berndt
-@version $Revision: 1.12 $
+@version $Revision: 1.13 $
*/
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;
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
@endcode
@author Jon S. Berndt
- @version $Revision: 1.14 $
+ @version $Revision: 1.15 $
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
private:
FGTable* Table;
- FGPropertyManager* GainPropertyNode;
+ FGPropertyNode_ptr GainPropertyNode;
double GainPropertySign;
double Gain;
double InMin, InMax, OutMin, OutMax;
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;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
}
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);
}
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
</pre>
@author Jon S. Berndt
- @version $Revision: 1.13 $
+ @version $Revision: 1.15 $
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
/// 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;
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);
};
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
<drift_rate> number </drift_rate>
<gain> number </gain>
<bias> number </bias>
- <delay> number < /delay>
+ <delay [type="time|frames"]> number < /delay>
</sensor>
@endcode
the number of frames to delay the output signal.
@author Jon S. Berndt
-@version $Revision: 1.21 $
+@version $Revision: 1.22 $
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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
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 $
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
} else {
sign = 1.0;
}
- FGPropertyManager *node = propMan->GetNode(value, false);
+ FGPropertyNode *node = propMan->GetNode(value, false);
if (node) {
OutputProp = new FGPropertyValue(node);
} else {
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;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
{
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();
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
</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 $
*/
double MaximalRPM;
int ExternalRPM;
int RPMdefinition;
- FGPropertyManager* ExtRPMsource;
+ FGPropertyNode_ptr ExtRPMsource;
double SourceGearRatio;
// 'real' rotor parameters
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;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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.