* The Pitot angle can now be tweaked with the <pitot_angle> tag in the <metrics> block.
* The refuel rate is now configurable with the <refuel-rate> tag in the <propulsion> block.
* Fixed C++11 compliance. JSBSim can now be compiled with a C++11 compiler.
* Avoid a spurious mass report to be issued when resetting.
* Fixed the moments computation. Previously they were computed with the previous time step CG position.
* Fixed a bug where the CG update was delayed to the next time step when point masses location were modified via the FCS.
namespace JSBSim {
-IDENT(IdSrc,"$Id: FGFDMExec.cpp,v 1.164 2014/11/30 12:35:32 bcoconni Exp $");
+IDENT(IdSrc,"$Id: FGFDMExec.cpp,v 1.170 2015/02/07 17:52:36 bcoconni Exp $");
IDENT(IdHdr,ID_FDMEXEC);
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Models.resize(eNumStandardModels);
+ // First build the inertial model since some other models are relying on
+ // the inertial model and the ground callback to build themselves.
+ // Note that this does not affect the order in which the models will be
+ // executed later.
+ Models[eInertial] = new FGInertial(this);
+ SetGroundCallback(new FGDefaultGroundCallback(static_cast<FGInertial*>(Models[eInertial])->GetRefRadius()));
+
// See the eModels enum specification in the header file. The order of the
// enums specifies the order of execution. The Models[] vector is the primary
// storage array for the list of models.
- // The model FGInertial is constructed first because some other models are
- // using its input during their construction
- Models[eInertial] = new FGInertial(this);
- SetGroundCallback(new FGDefaultGroundCallback(static_cast<FGInertial*>(Models[eInertial])->GetRefRadius()));
Models[ePropagate] = new FGPropagate(this);
Models[eInput] = new FGInput(this);
Models[eAtmosphere] = new FGStandardAtmosphere(this);
Models[eWinds] = new FGWinds(this);
- Models[eAuxiliary] = new FGAuxiliary(this);
Models[eSystems] = new FGFCS(this);
+ Models[eMassBalance] = new FGMassBalance(this);
+ Models[eAuxiliary] = new FGAuxiliary(this);
Models[ePropulsion] = new FGPropulsion(this);
Models[eAerodynamics] = new FGAerodynamics (this);
Models[eGroundReactions] = new FGGroundReactions(this);
Models[eExternalReactions] = new FGExternalReactions(this);
Models[eBuoyantForces] = new FGBuoyantForces(this);
- Models[eMassBalance] = new FGMassBalance(this);
Models[eAircraft] = new FGAircraft(this);
Models[eAccelerations] = new FGAccelerations(this);
Models[eOutput] = new FGOutput(this);
Inertial = (FGInertial*)Models[eInertial];
Atmosphere = (FGAtmosphere*)Models[eAtmosphere];
Winds = (FGWinds*)Models[eWinds];
- Auxiliary = (FGAuxiliary*)Models[eAuxiliary];
FCS = (FGFCS*)Models[eSystems];
+ MassBalance = (FGMassBalance*)Models[eMassBalance];
+ Auxiliary = (FGAuxiliary*)Models[eAuxiliary];
Propulsion = (FGPropulsion*)Models[ePropulsion];
Aerodynamics = (FGAerodynamics*)Models[eAerodynamics];
GroundReactions = (FGGroundReactions*)Models[eGroundReactions];
ExternalReactions = (FGExternalReactions*)Models[eExternalReactions];
BuoyantForces = (FGBuoyantForces*)Models[eBuoyantForces];
- MassBalance = (FGMassBalance*)Models[eMassBalance];
Aircraft = (FGAircraft*)Models[eAircraft];
Accelerations = (FGAccelerations*)Models[eAccelerations];
Output = (FGOutput*)Models[eOutput];
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-void FGFDMExec::Schedule(FGModel* model, int rate)
-{
- model->SetRate(rate);
- Models.push_back(model);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
bool FGFDMExec::Run(void)
{
bool success=true;
Auxiliary->in.TurbPQR = Winds->GetTurbPQR();
Auxiliary->in.WindPsi = Winds->GetWindPsi();
Auxiliary->in.Vwind = Winds->GetTotalWindNED().Magnitude();
+ Auxiliary->in.PitotAngle = Aircraft->GetPitotAngle();
break;
case eSystems:
// Dynamic inputs come into the components that FCS manages through properties
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-#define ID_FDMEXEC "$Id: FGFDMExec.h,v 1.93 2014/11/30 13:06:05 bcoconni Exp $"
+#define ID_FDMEXEC "$Id: FGFDMExec.h,v 1.95 2015/02/07 17:52:36 bcoconni Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
property actually maps toa function call of DoTrim().
@author Jon S. Berndt
- @version $Revision: 1.93 $
+ @version $Revision: 1.95 $
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
/// Default destructor
~FGFDMExec();
- // This list of enums is very important! The order in which models are listed here
- // determines the order of execution of the models.
+ // This list of enums is very important! The order in which models are listed
+ // here determines the order of execution of the models.
+ //
+ // There are some conditions that need to be met :
+ // 1. FCS can request mass geometry changes via the inertia/pointmass-*
+ // properties so it must be executed before MassBalance
+ // 2. MassBalance must be executed before Propulsion, Aerodynamics,
+ // GroundReactions, ExternalReactions and BuoyantForces to ensure that
+ // their moments are computed with the updated CG position.
enum eModels { ePropagate=0,
eInput,
eInertial,
eAtmosphere,
eWinds,
- eAuxiliary,
eSystems,
+ eMassBalance,
+ eAuxiliary,
ePropulsion,
eAerodynamics,
eGroundReactions,
eExternalReactions,
eBuoyantForces,
- eMassBalance,
eAircraft,
eAccelerations,
eOutput,
/** Unbind all tied JSBSim properties. */
void Unbind(void) {instance->Unbind();}
- /** This routine places a model into the runlist at the specified rate. The
- "rate" is not really a clock rate. It represents how many calls to the
- FGFDMExec::Run() method must be made before the model is executed. A
- value of 1 means that the model will be executed for each call to the
- exec's Run() method. A value of 5 means that the model will only be
- executed every 5th call to the exec's Run() method. Use of a rate other than
- one is at this time not recommended.
- @param model A pointer to the model being scheduled.
- @param rate The rate at which to execute the model as described above.
- Default is every frame (rate=1).
- @return Currently returns 0 always. */
- void Schedule(FGModel* model, int rate=1);
-
/** This function executes each scheduled model in succession.
@return true if successful, false if sim should be ended */
bool Run(void);
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-#define ID_STRINGUTILS "$Id: string_utilities.h,v 1.20 2014/06/13 22:10:33 bcoconni Exp $"
+#define ID_STRINGUTILS "$Id: string_utilities.h,v 1.21 2015/02/14 14:03:00 bcoconni Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
extern bool is_number(const std::string& str);
std::vector <std::string> split(std::string str, char d);
- // libc++ has these as built-ins for all C++ language versions
- // as well as Visual Studio for versions greater than 2010
- // (1700 -> MSVC++ 11.0 and VS 2012)
-#if !defined(_LIBCPP_VERSION) && _MSC_VER < 1700
+ // These functions are built-ins for:
+ // * C++11
+ // * libc++ for all C++ language versions
+ // * Visual Studio for versions greater than 2010 (1700 -> MSVC++ 11.0 and VS 2012)
+#if !defined(_LIBCPP_VERSION) && _MSC_VER < 1700 && __cplusplus < 201103L
extern std::string to_string(int);
extern std::string to_string(double);
extern std::string to_string(float);
return str_array;
}
-/* Comment out to_string functions when they are defined already - C++ 11 defines these */
+
+ // These functions are built-ins for:
+ // * C++11
+ // * libc++ for all C++ language versions
+ // * Visual Studio for versions greater than 2010 (1700 -> MSVC++ 11.0 and VS 2012)
+#if !defined(_LIBCPP_VERSION) && _MSC_VER < 1700 && __cplusplus < 201103L
string to_string(int i)
{
char buffer[32];
if (!(o << x)) cerr << "Bad double to string conversion" << endl;
return o.str();
}
+#endif
string replace(string str, const string& oldstr, const string& newstr)
{
GLOBAL DATA
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-IDENT(IdSrc,"$Id: FGAircraft.cpp,v 1.40 2014/05/17 15:29:30 jberndt Exp $");
+IDENT(IdSrc,"$Id: FGAircraft.cpp,v 1.43 2015/01/31 14:56:21 bcoconni Exp $");
IDENT(IdHdr,ID_AIRCRAFT);
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
lbarh = lbarv = 0.0;
vbarh = vbarv = 0.0;
WingIncidence = 0.0;
+ PitotAngle = 0.0;
bind();
VTailArea = el->FindElementValueAsNumberConvertTo("vtailarea", "FT2");
if (el->FindElement("vtailarm"))
VTailArm = el->FindElementValueAsNumberConvertTo("vtailarm", "FT");
+ if (el->FindElement("pitot_angle"))
+ PitotAngle = el->FindElementValueAsNumberConvertTo("pitot_angle", "RAD");
// Find all LOCATION elements that descend from this METRICS branch of the
// config file. This would be CG location, eyepoint, etc.
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-#define ID_AIRCRAFT "$Id: FGAircraft.h,v 1.21 2013/11/24 11:40:55 bcoconni Exp $"
+#define ID_AIRCRAFT "$Id: FGAircraft.h,v 1.24 2015/01/31 14:56:21 bcoconni Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
<vtailarea unit="{FT2 | M}"> {number} </vtailarea>
<vtailarm unit="{FT | M}"> {number} </vtailarm>
<wing_incidence unit="{RAD | DEG}"> {number} </wing_incidence>
+ <pitot_angle unit="{RAD | DEG}"> {number} </pitot_angle>
<location name="{AERORP | EYEPOINT | VRP}" unit="{IN | M}">
<x> {number} </x>
<y> {number} </y>
@endcode
@author Jon S. Berndt
- @version $Id: FGAircraft.h,v 1.21 2013/11/24 11:40:55 bcoconni Exp $
+ @version $Id: FGAircraft.h,v 1.24 2015/01/31 14:56:21 bcoconni Exp $
@see Cooke, Zyda, Pratt, and McGhee, "NPSNET: Flight Simulation Dynamic Modeling
Using Quaternions", Presence, Vol. 1, No. 4, pp. 404-420 Naval Postgraduate
School, January 1994
double GetWingSpan(void) const { return WingSpan; }
/// Gets the average wing chord
double Getcbar(void) const { return cbar; }
+ double GetPitotAngle(void) const { return PitotAngle; }
double GetWingIncidence(void) const { return WingIncidence; }
double GetWingIncidenceDeg(void) const { return WingIncidence*radtodeg; }
double GetHTailArea(void) const { return HTailArea; }
double WingArea, WingSpan, cbar, WingIncidence;
double HTailArea, VTailArea, HTailArm, VTailArm;
- double lbarh,lbarv,vbarh,vbarv;
+ double lbarh,lbarv,vbarh,vbarv,PitotAngle;
std::string AircraftName;
void Debug(int from);
namespace JSBSim {
-IDENT(IdSrc,"$Id: FGAuxiliary.cpp,v 1.67 2014/05/17 15:28:51 jberndt Exp $");
+IDENT(IdSrc,"$Id: FGAuxiliary.cpp,v 1.68 2014/12/27 05:41:11 dpculp Exp $");
IDENT(IdHdr,ID_AUXILIARY);
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
vcas = veas = 0.0;
qbar = qbarUW = qbarUV = 0.0;
- Mach = MachU = 0.0;
+ Mach = MachU = MachPitot = 0.0;
alpha = beta = 0.0;
adot = bdot = 0.0;
- gamma = Vt = Vground = 0.0;
+ gamma = Vt = Vground = Vpitot = 0.0;
psigt = 0.0;
day_of_year = 1;
seconds_in_day = 0.0;
vAeroUVW.InitMatrix();
vAeroPQR.InitMatrix();
vMachUVW.InitMatrix();
+ vWindUVW.InitMatrix();
+ vPitotUVW.InitMatrix();
vEuler.InitMatrix();
vEulerRates.InitMatrix();
vcas = veas = 0.0;
qbar = qbarUW = qbarUV = 0.0;
- Mach = MachU = 0.0;
+ Mach = MachU = MachPitot = 0.0;
alpha = beta = 0.0;
adot = bdot = 0.0;
- gamma = Vt = Vground = 0.0;
+ gamma = Vt = Vground = Vpitot = 0.0;
psigt = 0.0;
day_of_year = 1;
seconds_in_day = 0.0;
MachU = vMachUVW(eU) = vAeroUVW(eU) / in.SoundSpeed;
vMachUVW(eV) = vAeroUVW(eV) / in.SoundSpeed;
vMachUVW(eW) = vAeroUVW(eW) / in.SoundSpeed;
- double MachU2 = MachU * MachU;
// Position
tat = in.Temperature*(1 + 0.2*Mach*Mach); // Total Temperature, isentropic flow
tatc = RankineToCelsius(tat);
- if (MachU < 1) { // Calculate total pressure assuming isentropic flow
- pt = in.Pressure*pow((1 + 0.2*MachU2),3.5);
+ // Pitot
+
+ vWindUVW(eU) = Vt;
+ vPitotUVW = mTw2p * vWindUVW;
+ Vpitot = vPitotUVW(eU);
+ if (Vpitot < 0.0) Vpitot = 0.0;
+ MachPitot = Vpitot / in.SoundSpeed;
+ double MachP2 = MachPitot * MachPitot;
+
+ if (MachPitot < 1) { // Calculate total pressure assuming isentropic flow
+ pt = in.Pressure*pow((1 + 0.2*MachP2),3.5);
} else {
// Use Rayleigh pitot tube formula for normal shock in front of pitot tube
- B = 5.76 * MachU2 / (5.6*MachU2 - 0.8);
- D = (2.8 * MachU2 - 0.4) * 0.4167;
+ B = 5.76 * MachP2 / (5.6*MachP2 - 0.8);
+ D = (2.8 * MachP2 - 0.4) * 0.4167;
pt = in.Pressure*pow(B,3.5)*D;
}
A = pow(((pt-in.Pressure)/in.PressureSL + 1),0.28571);
- if (abs(MachU) > 0.0) {
+ if (abs(MachPitot) > 0.0) {
vcas = sqrt(7 * in.PressureSL / in.DensitySL * (A-1));
veas = sqrt(2 * qbar / in.DensitySL);
vtrue = 1116.43559 * Mach * sqrt(in.Temperature / 518.67);
mTw2b(3,3) = ca;
mTb2w = mTw2b.Transposed();
+
+ // The pitot frame is the same as the body frame except rotated about the
+ // Y axis by the pitot attachment angle.
+
+ ca = cos(alpha + in.PitotAngle);
+ sa = sin(alpha + in.PitotAngle);
+
+ mTw2p(1,1) = ca*cb;
+ mTw2p(1,2) = -ca*sb;
+ mTw2p(1,3) = -sa;
+ mTw2p(2,1) = sb;
+ mTw2p(2,2) = cb;
+ mTw2p(2,3) = 0.0;
+ mTw2p(3,1) = sa*cb;
+ mTw2p(3,2) = -sa*sb;
+ mTw2p(3,3) = ca;
+
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-#define ID_AUXILIARY "$Id: FGAuxiliary.h,v 1.28 2013/06/10 01:56:27 jberndt Exp $"
+#define ID_AUXILIARY "$Id: FGAuxiliary.h,v 1.29 2014/12/27 05:41:11 dpculp 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.28 2013/06/10 01:56:27 jberndt Exp $
+ @version $Id: FGAuxiliary.h,v 1.29 2014/12/27 05:41:11 dpculp Exp $
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FGColumnVector3 TurbPQR;
double WindPsi;
double Vwind;
+ double PitotAngle;
} in;
private:
FGMatrix33 mTw2b;
FGMatrix33 mTb2w;
+ FGMatrix33 mTw2p;
FGColumnVector3 vPilotAccel;
FGColumnVector3 vPilotAccelN;
FGColumnVector3 vEuler;
FGColumnVector3 vEulerRates;
FGColumnVector3 vMachUVW;
+ FGColumnVector3 vWindUVW;
+ FGColumnVector3 vPitotUVW;
FGLocation vLocationVRP;
- double Vt, Vground, Mach, MachU;
+ double Vt, Vground, Vpitot;
+ double Mach, MachU, MachPitot;
double qbar, qbarUW, qbarUV;
double Re; // Reynolds Number = V*c/mu
double alpha, beta;
namespace JSBSim {
-IDENT(IdSrc,"$Id: FGMassBalance.cpp,v 1.51 2014/11/29 13:47:19 bcoconni Exp $");
+IDENT(IdSrc,"$Id: FGMassBalance.cpp,v 1.52 2015/02/15 10:14:46 bcoconni Exp $");
IDENT(IdHdr,ID_MASSBALANCE);
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
PropertyManager->Tie("inertia/cg-z-in", this,3,
(PMF)&FGMassBalance::GetXYZcg);
typedef int (FGMassBalance::*iOPV)() const;
- PropertyManager->Tie("inertia/print-mass-properties", this, (iOPV)0, &FGMassBalance::GetMassPropertiesReport);
+ PropertyManager->Tie("inertia/print-mass-properties", this, (iOPV)0,
+ &FGMassBalance::GetMassPropertiesReport, false);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
namespace JSBSim {
-IDENT(IdSrc,"$Id: FGPropulsion.cpp,v 1.80 2014/06/29 10:18:16 bcoconni Exp $");
+IDENT(IdSrc,"$Id: FGPropulsion.cpp,v 1.83 2015/01/31 14:56:21 bcoconni Exp $");
IDENT(IdHdr,ID_PROPULSION);
extern short debug_lvl;
ActiveEngine = -1; // -1: ALL, 0: Engine 1, 1: Engine 2 ...
tankJ.InitMatrix();
refuel = dump = false;
- DumpRate = 0.0;
+ DumpRate = 0.0;
+ RefuelRate = 6000.0;
FuelFreeze = false;
TotalFuelQuantity = 0.0;
IsBound =
Debug(2);
ReadingEngine = false;
+ double FuelDensity = 6.0;
Name = "Propulsion Model: " + el->GetAttributeValue("name");
Element* tank_element = el->FindElement("tank");
while (tank_element) {
Tanks.push_back(new FGTank(FDMExec, tank_element, numTanks));
- if (Tanks.back()->GetType() == FGTank::ttFUEL) numFuelTanks++;
+ if (Tanks.back()->GetType() == FGTank::ttFUEL) {
+ FuelDensity = Tanks[numFuelTanks]->GetDensity();
+ numFuelTanks++;
+ }
else if (Tanks.back()->GetType() == FGTank::ttOXIDIZER) numOxiTanks++;
else {cerr << "Unknown tank type specified." << endl; return false;}
numTanks++;
CalculateTankInertias();
- // Process fuel dump rate
if (el->FindElement("dump-rate"))
DumpRate = el->FindElementValueAsNumberConvertTo("dump-rate", "LBS/MIN");
+ if (el->FindElement("refuel-rate"))
+ RefuelRate = el->FindElementValueAsNumberConvertTo("refuel-rate", "LBS/MIN");
+
+ unsigned int i;
+ for (i=0; i<Engines.size(); i++) {
+ Engines[i]->SetFuelDensity(FuelDensity);
+ }
+
PostLoad(el, PropertyManager);
// ToDo: first need to make sure the engine Type is really appropriate:
// do a check to see if it is of type Piston. This should be done for
// all of this kind of possibly across-the-board settings.
- ((FGPiston*)Engines[i])->SetMagnetos(setting);
+ if (Engines[i]->GetType() == FGEngine::etPiston)
+ ((FGPiston*)Engines[i])->SetMagnetos(setting);
}
} else {
((FGPiston*)Engines[ActiveEngine])->SetMagnetos(setting);
{
unsigned int i;
- double fillrate = 100 * time_slice; // 100 lbs/sec = 6000 lbs/min
+ double fillrate = RefuelRate / 60.0 * time_slice;
int TanksNotFull = 0;
for (i=0; i<numTanks; i++) {
if (Tanks[i]->GetPctFull() < 99.99) ++TanksNotFull;
}
+ // adds fuel equally to all tanks that are not full
if (TanksNotFull) {
for (i=0; i<numTanks; i++) {
if (Tanks[i]->GetPctFull() < 99.99)
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-#define ID_PROPULSION "$Id: FGPropulsion.h,v 1.34 2014/06/09 11:52:07 bcoconni Exp $"
+#define ID_PROPULSION "$Id: FGPropulsion.h,v 1.35 2015/01/07 23:22:59 dpculp Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
</tank>
... more tanks ...
<dump-rate unit="{LBS/MIN | KG/MIN}"> {number} </dump-rate>
+ <refuel-rate unit="{LBS/MIN | KG/MIN}"> {number} </refuel-rate>
</propulsion>
@endcode
@author Jon S. Berndt
- @version $Id: FGPropulsion.h,v 1.34 2014/06/09 11:52:07 bcoconni Exp $
+ @version $Id: FGPropulsion.h,v 1.35 2015/01/07 23:22:59 dpculp Exp $
@see
FGEngine
FGTank
bool FuelFreeze;
double TotalFuelQuantity;
double DumpRate;
+ double RefuelRate;
bool IsBound;
bool HavePistonEngine;
bool HaveTurbineEngine;
namespace JSBSim {
-IDENT(IdSrc,"$Id: FGEngine.cpp,v 1.60 2014/06/09 11:52:07 bcoconni Exp $");
+IDENT(IdSrc,"$Id: FGEngine.cpp,v 1.61 2015/01/07 23:22:59 dpculp Exp $");
IDENT(IdHdr,ID_ENGINE);
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FuelExpended = 0.0;
MaxThrottle = 1.0;
MinThrottle = 0.0;
-
+ FuelDensity = 6.02;
Debug(0);
}
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-#define ID_ENGINE "$Id: FGEngine.h,v 1.42 2014/06/09 11:52:07 bcoconni Exp $"
+#define ID_ENGINE "$Id: FGEngine.h,v 1.43 2015/01/07 23:22:59 dpculp Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
documentation for engine and thruster classes.
</pre>
@author Jon S. Berndt
- @version $Id: FGEngine.h,v 1.42 2014/06/09 11:52:07 bcoconni Exp $
+ @version $Id: FGEngine.h,v 1.43 2015/01/07 23:22:59 dpculp Exp $
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
enum EngineType {etUnknown, etRocket, etPiston, etTurbine, etTurboprop, etElectric};
- EngineType GetType(void) const { return Type; }
+ EngineType GetType(void) const { return Type; }
virtual const std::string& GetName(void) const { return Name; }
// Engine controls
virtual double getFuelFlow_gph () const {return FuelFlow_gph;}
virtual double getFuelFlow_pph () const {return FuelFlow_pph;}
virtual double GetFuelFlowRate(void) const {return FuelFlowRate;}
- virtual double GetFuelFlowRateGPH(void) const {return FuelFlowRate*3600/6.02;}
+ virtual double GetFuelFlowRateGPH(void) const {return FuelFlowRate*3600/FuelDensity;}
virtual double GetFuelUsedLbs(void) const {return FuelUsedLbs;}
virtual bool GetStarved(void) const { return Starved; }
virtual bool GetRunning(void) const { return Running; }
virtual void SetRunning(bool bb) { Running=bb; }
virtual void SetName(const std::string& name) { Name = name; }
virtual void SetFuelFreeze(bool f) { FuelFreeze = f; }
+ virtual void SetFuelDensity(double d) { FuelDensity = d; }
virtual void SetStarter(bool s) { Starter = s; }
double FuelFlow_gph;
double FuelFlow_pph;
double FuelUsedLbs;
+ double FuelDensity;
FGFDMExec* FDMExec;
FGThruster* Thruster;
namespace JSBSim {
-IDENT(IdSrc,"$Id: FGPiston.cpp,v 1.77 2014/06/08 12:00:35 bcoconni Exp $");
+IDENT(IdSrc,"$Id: FGPiston.cpp,v 1.78 2015/01/07 23:22:59 dpculp Exp $");
IDENT(IdHdr,ID_PISTON);
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FuelFlowRate = 0.0;
m_dot_fuel = 0.0;
}
- FuelFlow_pph = FuelFlowRate * 3600; // seconds to hours
- FuelFlow_gph = FuelFlow_pph / 6.0; // Assumes 6 lbs / gallon
+ FuelFlow_pph = FuelFlowRate * 3600;
+ FuelFlow_gph = FuelFlow_pph / FuelDensity;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
namespace JSBSim {
-IDENT(IdSrc,"$Id: FGPropeller.cpp,v 1.48 2014/01/13 10:46:10 ehofman Exp $");
+IDENT(IdSrc,"$Id: FGPropeller.cpp,v 1.49 2014/12/27 14:37:37 dpculp Exp $");
IDENT(IdHdr,ID_PROPELLER);
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double local_RPS = RPS < 0.01 ? 0.01 : RPS;
- PowerRequired = cPReq*local_RPS*RPS*local_RPS*D5*rho;
+ PowerRequired = cPReq*local_RPS*local_RPS*local_RPS*D5*rho;
vTorque(eX) = -Sense*PowerRequired / (local_RPS*2.0*M_PI);
return PowerRequired;
namespace JSBSim {
-IDENT(IdSrc,"$Id: FGTank.cpp,v 1.40 2014/05/17 15:09:42 jberndt Exp $");
+IDENT(IdSrc,"$Id: FGTank.cpp,v 1.43 2015/02/02 20:49:11 bcoconni Exp $");
IDENT(IdHdr,ID_TANK);
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
FGTank::FGTank(FGFDMExec* exec, Element* el, int tank_number)
- : TankNumber(tank_number), Exec(exec)
+ : TankNumber(tank_number)
{
string token, strFuelName;
Element* element;
Element* element_Grain;
+ FGPropertyManager *PropertyManager = exec->GetPropertyManager();
Area = 1.0;
Density = 6.6;
InitialTemperature = Temperature = -9999.0;
Ixx = Iyy = Izz = 0.0;
InertiaFactor = 1.0;
Radius = Contents = Standpipe = Length = InnerRadius = 0.0;
- PreviousUsed = 0.0;
ExternalFlow = 0.0;
InitialStandpipe = 0.0;
Capacity = 0.00001;
Priority = InitialPriority = 1;
- PropertyManager = Exec->GetPropertyManager();
vXYZ.InitMatrix();
vXYZ_drain.InitMatrix();
ixx_unit = iyy_unit = izz_unit = 1.0;
+ grainType = gtUNKNOWN; // This is the default
type = el->GetAttributeValue("type");
if (type == "FUEL") Type = ttFUEL;
PctFull = 100.0*Contents/Capacity; // percent full; 0 to 100.0
- string property_name, base_property_name;
- base_property_name = CreateIndexedPropertyName("propulsion/tank", TankNumber);
- property_name = base_property_name + "/contents-lbs";
- PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetContents,
- &FGTank::SetContents );
- property_name = base_property_name + "/pct-full";
- PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetPctFull);
-
- property_name = base_property_name + "/priority";
- PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetPriority,
- &FGTank::SetPriority );
- property_name = base_property_name + "/external-flow-rate-pps";
- PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetExternalFlow,
- &FGTank::SetExternalFlow );
- property_name = base_property_name + "/local-ixx-slug_ft2";
- PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetIxx);
- property_name = base_property_name + "/local-iyy-slug_ft2";
- PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetIyy);
- property_name = base_property_name + "/local-izz-slug_ft2";
- PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetIzz);
-
// Check whether this is a solid propellant "tank". Initialize it if true.
- grainType = gtUNKNOWN; // This is the default
-
element_Grain = el->FindElement("grain_config");
if (element_Grain) {
Density = (Contents*lbtoslug)/Volume; // slugs/in^3
}
- CalculateInertias();
+ CalculateInertias();
if (Temperature != -9999.0) InitialTemperature = Temperature = FahrenheitToCelsius(Temperature);
Area = 40.0 * pow(Capacity/1975, 0.666666667);
// A named fuel type will override a previous density value
if (!strFuelName.empty()) Density = ProcessFuelName(strFuelName);
+ bind(PropertyManager);
+
Debug(0);
}
SetContents ( InitialContents );
PctFull = 100.0*Contents/Capacity;
SetPriority( InitialPriority );
- PreviousUsed = 0.0;
+ CalculateInertias();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double FGTank::Drain(double used)
{
-// double AmountToDrain = 2.0*used - PreviousUsed;
double remaining = Contents - used;
if (remaining >= 0) { // Reduce contents by amount used.
Contents = 0.0;
PctFull = 0.0;
}
-// PreviousUsed = AmountToDrain;
- if (grainType != gtUNKNOWN) CalculateInertias();
+
+ CalculateInertias();
return remaining;
}
} else {
PctFull = Contents/Capacity*100.0;
}
+
+ CalculateInertias();
+
return overage;
}
} else {
PctFull = Contents/Capacity*100.0;
}
+
+ CalculateInertias();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if (grainType != gtUNKNOWN) { // assume solid propellant
- if (Density > 0.0) {
- Volume = (Contents*lbtoslug)/Density; // in^3
- } else if (Contents <= 0.0) {
- Volume = 0;
- } else {
- cerr << endl << " Solid propellant grain density is zero!" << endl << endl;
- exit(-1);
- }
+ if (Density > 0.0) {
+ Volume = (Contents*lbtoslug)/Density; // in^3
+ } else if (Contents <= 0.0) {
+ Volume = 0;
+ } else {
+ cerr << endl << " Solid propellant grain density is zero!" << endl << endl;
+ exit(-1);
+ }
- switch (grainType) {
+ switch (grainType) {
case gtCYLINDRICAL:
InnerRadius = sqrt(Rad2 - Volume/(M_PI * Length));
RadSumSqr = (Rad2 + InnerRadius*InnerRadius)/144.0;
Ixx = 0.5*Mass*RadSumSqr;
Iyy = Mass*(3.0*RadSumSqr + Length*Length/144.0)/12.0;
- Izz = Iyy;
+ Izz = Iyy;
break;
case gtENDBURNING:
Length = Volume/(M_PI*Rad2);
Ixx = 0.5*Mass*Rad2/144.0;
Iyy = Mass*(3.0*Rad2 + Length*Length)/(144.0*12.0);
- Izz = Iyy;
+ Izz = Iyy;
break;
- case gtFUNCTION:
- Ixx = function_ixx->GetValue()*ixx_unit;
- Iyy = function_iyy->GetValue()*iyy_unit;
- Izz = function_izz->GetValue()*izz_unit;
- break;
- case gtUNKNOWN:
+ case gtFUNCTION:
+ Ixx = function_ixx->GetValue()*ixx_unit;
+ Iyy = function_iyy->GetValue()*iyy_unit;
+ Izz = function_izz->GetValue()*izz_unit;
+ break;
+ default:
cerr << "Unknown grain type found." << endl;
exit(-1);
break;
- }
+ }
} else { // assume liquid propellant: shrinking snowball
return 6.6;
}
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGTank::bind(FGPropertyManager* PropertyManager)
+{
+ string property_name, base_property_name;
+ base_property_name = CreateIndexedPropertyName("propulsion/tank", TankNumber);
+ property_name = base_property_name + "/contents-lbs";
+ PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetContents,
+ &FGTank::SetContents );
+ property_name = base_property_name + "/pct-full";
+ PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetPctFull);
+
+ property_name = base_property_name + "/priority";
+ PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetPriority,
+ &FGTank::SetPriority );
+ property_name = base_property_name + "/external-flow-rate-pps";
+ PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetExternalFlow,
+ &FGTank::SetExternalFlow );
+ property_name = base_property_name + "/local-ixx-slug_ft2";
+ PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetIxx);
+ property_name = base_property_name + "/local-iyy-slug_ft2";
+ PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetIyy);
+ property_name = base_property_name + "/local-izz-slug_ft2";
+ PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetIzz);
+}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// The bitmasked value choices are as follows:
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-#define ID_TANK "$Id: FGTank.h,v 1.28 2014/05/17 15:09:42 jberndt Exp $"
+#define ID_TANK "$Id: FGTank.h,v 1.30 2015/02/02 20:49:11 bcoconni Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
double InertiaFactor;
double PctFull;
double Contents, InitialContents;
- double PreviousUsed;
double Area;
double Temperature, InitialTemperature;
double Standpipe, InitialStandpipe;
double ExternalFlow;
bool Selected;
int Priority, InitialPriority;
- FGFDMExec* Exec;
- FGPropertyManager* PropertyManager;
void CalculateInertias(void);
+ void bind(FGPropertyManager* PropertyManager);
void Debug(int from);
};
}