1
0
Fork 0

Update to the latest version of JSBSim

This commit is contained in:
ehofman 2003-10-19 09:48:44 +00:00
parent 2ca827a3a4
commit bf859a91c3
13 changed files with 188 additions and 96 deletions

View file

@ -66,17 +66,12 @@ DEFINITIONS
#define ID_AERODYNAMICS "$Id$" #define ID_AERODYNAMICS "$Id$"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS FORWARD DECLARATIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
namespace JSBSim { namespace JSBSim {
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
COMMENTS, REFERENCES, and NOTES [use "class documentation" below for API docs]
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DOCUMENTATION CLASS DOCUMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
@ -86,11 +81,8 @@ CLASS DOCUMENTATION
aerodynamic properties of this aircraft. Here also, such unique phenomena aerodynamic properties of this aircraft. Here also, such unique phenomena
as ground effect and maximum lift curve tailoff are handled. as ground effect and maximum lift curve tailoff are handled.
@author Jon S. Berndt @author Jon S. Berndt
@author Tony Peden
@version $Id$ @version $Id$
@see <a href="http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/jsbsim/JSBSim/FGAerodynamics.h?rev=HEAD&content-type=text/vnd.viewcvs-markup">
Header File </a>
@see <a href="http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/jsbsim/JSBSim/FGAerodynamics.cpp?rev=HEAD&content-type=text/vnd.viewcvs-markup">
Source File </a>
*/ */
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -102,7 +94,7 @@ class FGAerodynamics : public FGModel {
public: public:
/** Constructor /** Constructor
@param Executive a pointer to the parent executive object */ @param Executive a pointer to the parent executive object */
FGAerodynamics(FGFDMExec*); FGAerodynamics(FGFDMExec* Executive);
/// Destructor /// Destructor
~FGAerodynamics(); ~FGAerodynamics();
@ -110,18 +102,31 @@ public:
@return false if no error */ @return false if no error */
bool Run(void); bool Run(void);
/** Loads the Aerodynamics model /** Loads the Aerodynamics model.
The Load function for this class expects the configuration file to
have found the AERODYNAMICS keyword in the configution file and to
have set that line to the current line.
@param AC_cfg pointer to the current configuration file.
@return true if successful */ @return true if successful */
bool Load(FGConfigFile* AC_cfg); bool Load(FGConfigFile* AC_cfg);
/** Gets the total aerodynamic force vector. /** Gets the total aerodynamic force vector.
@return a force vector reference. */ @return a force vector reference. */
FGColumnVector3& GetForces(void) {return vForces;} FGColumnVector3& GetForces(void) {return vForces;}
/** Gets the aerodynamic force for an axis.
@param n Axis index. This could be 0, 1, or 2, or one of the
axis enums: eX, eY, eZ.
@return the force acting on an axis */
double GetForces(int n) const {return vForces(n);} double GetForces(int n) const {return vForces(n);}
/** Gets the total aerodynamic moment vector. /** Gets the total aerodynamic moment vector.
@return a moment vector reference. */ @return a moment vector reference. */
FGColumnVector3& GetMoments(void) {return vMoments;} FGColumnVector3& GetMoments(void) {return vMoments;}
/** Gets the aerodynamic moment for an axis.
@return the moment about a single axis (as described also in the
similar call to GetForces(int n).*/
double GetMoments(int n) const {return vMoments(n);} double GetMoments(int n) const {return vMoments(n);}
FGColumnVector3& GetvLastFs(void) { return vLastFs; } FGColumnVector3& GetvLastFs(void) { return vLastFs; }
@ -145,7 +150,7 @@ public:
inline void SetAlphaCLMax(double tt) { alphaclmax=tt; } inline void SetAlphaCLMax(double tt) { alphaclmax=tt; }
inline void SetAlphaCLMin(double tt) { alphaclmin=tt; } inline void SetAlphaCLMin(double tt) { alphaclmin=tt; }
/** Gets the strings for the current set of coefficients. /** Gets the strings for the current set of coefficients.
@return a string containing the descriptive names for all coefficients */ @return a string containing the descriptive names for all coefficients */
string GetCoefficientStrings(void); string GetCoefficientStrings(void);

View file

@ -93,7 +93,7 @@ FGAtmosphere::FGAtmosphere(FGFDMExec* fdmex) : FGModel(fdmex)
// turbType = ttBerndt; // turbType = ttBerndt;
TurbGain = 0.0; TurbGain = 0.0;
TurbRate = 1.0; TurbRate = 1.0;
bind(); bind();
Debug(0); Debug(0);
} }
@ -141,7 +141,7 @@ bool FGAtmosphere::Run(void)
Calculate(h); Calculate(h);
} }
if (turbType != ttNone && TurbGain > 0.0) { if (turbType != ttNone) {
Turbulence(); Turbulence();
vWindNED += vTurbulence; vWindNED += vTurbulence;
} }
@ -278,7 +278,7 @@ void FGAtmosphere::Turbulence(void)
vDirectiondAccelDt(eY) = 1 - 2.0*(double(rand())/double(RAND_MAX)); vDirectiondAccelDt(eY) = 1 - 2.0*(double(rand())/double(RAND_MAX));
vDirectiondAccelDt(eZ) = 1 - 2.0*(double(rand())/double(RAND_MAX)); vDirectiondAccelDt(eZ) = 1 - 2.0*(double(rand())/double(RAND_MAX));
MagnitudedAccelDt = 1 - 2.0*(double(rand())/double(RAND_MAX)); MagnitudedAccelDt = 1 - 2.0*(double(rand())/double(RAND_MAX)) - Magnitude;
// Scale the magnitude so that it moves // Scale the magnitude so that it moves
// away from the peaks // away from the peaks
MagnitudedAccelDt = ((MagnitudedAccelDt - Magnitude) / MagnitudedAccelDt = ((MagnitudedAccelDt - Magnitude) /

View file

@ -94,6 +94,7 @@ DEFINITIONS
FORWARD DECLARATIONS FORWARD DECLARATIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
namespace JSBSim {
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
COMMENTS, REFERENCES, and NOTES [use "class documentation" below for API docs] COMMENTS, REFERENCES, and NOTES [use "class documentation" below for API docs]
@ -112,8 +113,6 @@ CLASS DOCUMENTATION
CLASS DECLARATION CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
namespace JSBSim {
class FGJSBBase { class FGJSBBase {
public: public:
/// Constructor for FGJSBBase. /// Constructor for FGJSBBase.

View file

@ -94,6 +94,7 @@ FGLGear::FGLGear(FGConfigFile* AC_cfg, FGFDMExec* fdmex) : Exec(fdmex)
GearUp = false; GearUp = false;
GearDown = true; GearDown = true;
Servicable = true;
// Add some AI here to determine if gear is located properly according to its // Add some AI here to determine if gear is located properly according to its
// brake group type ?? // brake group type ??
@ -132,6 +133,8 @@ FGLGear::FGLGear(FGConfigFile* AC_cfg, FGFDMExec* fdmex) : Exec(fdmex)
brakePct = 0.0; brakePct = 0.0;
maxCompLen = 0.0; maxCompLen = 0.0;
TirePressureNorm = 1.0;
Debug(0); Debug(0);
} }
@ -188,6 +191,8 @@ FGLGear::FGLGear(const FGLGear& lgear)
GearDown = lgear.GearDown; GearDown = lgear.GearDown;
WheelSlip = lgear.WheelSlip; WheelSlip = lgear.WheelSlip;
lastWheelSlip = lgear.lastWheelSlip; lastWheelSlip = lgear.lastWheelSlip;
TirePressureNorm = lgear.TirePressureNorm;
Servicable = lgear.Servicable;
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -296,30 +301,30 @@ FGColumnVector3& FGLGear::Force(void)
switch (eBrakeGrp) { switch (eBrakeGrp) {
case bgLeft: case bgLeft:
SteerGain = 0.10; SteerGain = 0.10;
BrakeFCoeff = rollingFCoeff*(1.0 - FCS->GetBrake(bgLeft)) + BrakeFCoeff = ( rollingFCoeff*(1.0 - FCS->GetBrake(bgLeft)) +
staticFCoeff*FCS->GetBrake(bgLeft); staticFCoeff*FCS->GetBrake(bgLeft) );
break; break;
case bgRight: case bgRight:
SteerGain = 0.10; SteerGain = 0.10;
BrakeFCoeff = rollingFCoeff*(1.0 - FCS->GetBrake(bgRight)) + BrakeFCoeff = ( rollingFCoeff*(1.0 - FCS->GetBrake(bgRight)) +
staticFCoeff*FCS->GetBrake(bgRight); staticFCoeff*FCS->GetBrake(bgRight) );
break; break;
case bgCenter: case bgCenter:
SteerGain = 0.10; SteerGain = 0.10;
BrakeFCoeff = rollingFCoeff*(1.0 - FCS->GetBrake(bgCenter)) + BrakeFCoeff = ( rollingFCoeff*(1.0 - FCS->GetBrake(bgCenter)) +
staticFCoeff*FCS->GetBrake(bgCenter); staticFCoeff*FCS->GetBrake(bgCenter) );
break; break;
case bgNose: case bgNose:
SteerGain = -0.50; SteerGain = -0.50;
BrakeFCoeff = rollingFCoeff; BrakeFCoeff = rollingFCoeff;
break; break;
case bgTail: case bgTail:
SteerGain = -0.10; SteerGain = -0.10;
BrakeFCoeff = rollingFCoeff; BrakeFCoeff = rollingFCoeff;
break; break;
case bgNone: case bgNone:
SteerGain = 0.0; SteerGain = 0.0;
BrakeFCoeff = rollingFCoeff; BrakeFCoeff = rollingFCoeff;
break; break;
default: default:
cerr << "Improper brake group membership detected for this gear." << endl; cerr << "Improper brake group membership detected for this gear." << endl;
@ -400,7 +405,9 @@ FGColumnVector3& FGLGear::Force(void)
RollingForce = 0; RollingForce = 0;
if (fabs(RollingWhlVel) > 1E-3) { if (fabs(RollingWhlVel) > 1E-3) {
RollingForce = vLocalForce(eZ) * BrakeFCoeff * fabs(RollingWhlVel)/RollingWhlVel; RollingForce = (1.0 - TirePressureNorm) * 30
+ vLocalForce(eZ) * BrakeFCoeff
* fabs(RollingWhlVel)/RollingWhlVel;
} }
SideForce = vLocalForce(eZ) * FCoeff; SideForce = vLocalForce(eZ) * FCoeff;

View file

@ -224,6 +224,11 @@ public:
/// Gets the gear compression force in pounds /// Gets the gear compression force in pounds
inline double GetCompForce(void) {return Force()(3); } inline double GetCompForce(void) {return Force()(3); }
inline double GetBrakeFCoeff(void) {return BrakeFCoeff;} inline double GetBrakeFCoeff(void) {return BrakeFCoeff;}
/// Gets the current normalized tire pressure
inline double GetTirePressure(void) { return TirePressureNorm; }
/// Sets the new normalized tire pressure
inline void SetTirePressure(double p) { TirePressureNorm = p; }
/// Sets the brake value in percent (0 - 100) /// Sets the brake value in percent (0 - 100)
inline void SetBrake(double bp) {brakePct = bp;} inline void SetBrake(double bp) {brakePct = bp;}
@ -278,6 +283,7 @@ private:
double RollingForce, SideForce, FCoeff; double RollingForce, SideForce, FCoeff;
double WheelSlip; double WheelSlip;
double lastWheelSlip; double lastWheelSlip;
double TirePressureNorm;
bool WOW; bool WOW;
bool lastWOW; bool lastWOW;
bool FirstContact; bool FirstContact;
@ -287,6 +293,7 @@ private:
bool ReportEnable; bool ReportEnable;
bool isRetractable; bool isRetractable;
bool GearUp, GearDown; bool GearUp, GearDown;
bool Servicable;
string name; string name;
string sSteerType; string sSteerType;
string sBrakeGroup; string sBrakeGroup;

View file

@ -137,7 +137,7 @@ FGPiston::~FGPiston()
double FGPiston::Calculate(double PowerRequired) double FGPiston::Calculate(double PowerRequired)
{ {
ConsumeFuel(); if (FuelFlow_gph > 0.0) ConsumeFuel();
Throttle = FCS->GetThrottlePos(EngineNumber); Throttle = FCS->GetThrottlePos(EngineNumber);
Mixture = FCS->GetMixturePos(EngineNumber); Mixture = FCS->GetMixturePos(EngineNumber);

View file

@ -139,8 +139,8 @@ double FGSimTurbine::Run(void)
{ {
double idlethrust, milthrust, thrust; double idlethrust, milthrust, thrust;
double N2norm; // 0.0 = idle N2, 1.0 = maximum N2 double N2norm; // 0.0 = idle N2, 1.0 = maximum N2
idlethrust = MaxMilThrust * ThrustTables[0]->TotalValue(); idlethrust = MilThrust * ThrustTables[0]->TotalValue();
milthrust = (MaxMilThrust - idlethrust) * ThrustTables[1]->TotalValue(); milthrust = (MilThrust - idlethrust) * ThrustTables[1]->TotalValue();
Running = true; Running = true;
Starter = false; Starter = false;
@ -149,13 +149,13 @@ double FGSimTurbine::Run(void)
N1 = Seek(&N1, IdleN1 + ThrottleCmd * N1_factor, delay, delay * 2.4); N1 = Seek(&N1, IdleN1 + ThrottleCmd * N1_factor, delay, delay * 2.4);
N2norm = (N2 - IdleN2) / N2_factor; N2norm = (N2 - IdleN2) / N2_factor;
thrust = idlethrust + (milthrust * N2norm * N2norm); thrust = idlethrust + (milthrust * N2norm * N2norm);
FuelFlow_pph = thrust * TSFC;
thrust = thrust * (1.0 - BleedDemand); thrust = thrust * (1.0 - BleedDemand);
FuelFlow_pph = thrust * TSFC;
if (FuelFlow_pph < IdleFF) FuelFlow_pph = IdleFF; if (FuelFlow_pph < IdleFF) FuelFlow_pph = IdleFF;
EGT_degC = TAT + 363.1 + ThrottleCmd * 357.1; EGT_degC = TAT + 363.1 + ThrottleCmd * 357.1;
OilPressure_psi = N2 * 0.62; OilPressure_psi = N2 * 0.62;
OilTemp_degK = Seek(&OilTemp_degK, 366.0, 1.2, 0); OilTemp_degK = Seek(&OilTemp_degK, 366.0, 1.2, 0);
EPR = 1.0 + thrust/MaxMilThrust; EPR = 1.0 + thrust/MilThrust;
NozzlePosition = Seek(&NozzlePosition, 1.0 - N2norm, 0.8, 0.8); NozzlePosition = Seek(&NozzlePosition, 1.0 - N2norm, 0.8, 0.8);
if (Reversed) thrust = thrust * -0.2; if (Reversed) thrust = thrust * -0.2;
@ -165,9 +165,9 @@ double FGSimTurbine::Run(void)
} }
if ((Augmented == 1) && Augmentation) { if ((Augmented == 1) && Augmentation) {
thrust = thrust * ThrustTables[2]->TotalValue(); thrust = MaxThrust * ThrustTables[2]->TotalValue();
FuelFlow_pph = thrust * ATSFC; FuelFlow_pph = thrust * ATSFC;
NozzlePosition = Seek(&NozzlePosition, 1.0, 0.8, 0); NozzlePosition = Seek(&NozzlePosition, 1.0, 0.8, 0.8);
} }
if ((Injected == 1) && Injection) if ((Injected == 1) && Injection)
@ -200,7 +200,7 @@ double FGSimTurbine::SpinUp(void)
double FGSimTurbine::Start(void) double FGSimTurbine::Start(void)
{ {
if ((N2 > 15.0) && !Starved) { // minimum 15% N2 needed for start if ((N2 > 15.0) && !Starved) { // minimum 15% N2 needed for start
Cranking = true; Cranking = true; // provided for sound effects signal
if (N2 < IdleN2) { if (N2 < IdleN2) {
N2 = Seek(&N2, IdleN2, 2.0, N2/2.0); N2 = Seek(&N2, IdleN2, 2.0, N2/2.0);
N1 = Seek(&N1, IdleN1, 1.4, N1/2.0); N1 = Seek(&N1, IdleN1, 1.4, N1/2.0);
@ -254,8 +254,8 @@ double FGSimTurbine::Seize(void)
double FGSimTurbine::Trim(void) double FGSimTurbine::Trim(void)
{ {
double idlethrust, milthrust, thrust; double idlethrust, milthrust, thrust;
idlethrust = MaxMilThrust * ThrustTables[0]->TotalValue(); idlethrust = MilThrust * ThrustTables[0]->TotalValue();
milthrust = (MaxMilThrust - idlethrust) * ThrustTables[1]->TotalValue(); milthrust = (MilThrust - idlethrust) * ThrustTables[1]->TotalValue();
thrust = idlethrust + (milthrust * ThrottleCmd * ThrottleCmd); thrust = idlethrust + (milthrust * ThrottleCmd * ThrottleCmd);
return thrust; return thrust;
} }
@ -295,7 +295,8 @@ double FGSimTurbine::Seek(double *var, double target, double accel, double decel
void FGSimTurbine::SetDefaults(void) void FGSimTurbine::SetDefaults(void)
{ {
Name = "None_Defined"; Name = "None_Defined";
MaxMilThrust = 10000.0; MilThrust = 10000.0;
MaxThrust = 10000.0;
BypassRatio = 0.0; BypassRatio = 0.0;
TSFC = 0.8; TSFC = 0.8;
ATSFC = 1.7; ATSFC = 1.7;
@ -329,7 +330,8 @@ bool FGSimTurbine::Load(FGConfigFile *Eng_cfg)
Name = Eng_cfg->GetValue("NAME"); Name = Eng_cfg->GetValue("NAME");
cout << Name << endl; cout << Name << endl;
Eng_cfg->GetNextConfigLine(); Eng_cfg->GetNextConfigLine();
*Eng_cfg >> token >> MaxMilThrust; *Eng_cfg >> token >> MilThrust;
*Eng_cfg >> token >> MaxThrust;
*Eng_cfg >> token >> BypassRatio; *Eng_cfg >> token >> BypassRatio;
*Eng_cfg >> token >> TSFC; *Eng_cfg >> token >> TSFC;
*Eng_cfg >> token >> ATSFC; *Eng_cfg >> token >> ATSFC;
@ -352,7 +354,7 @@ bool FGSimTurbine::Load(FGConfigFile *Eng_cfg)
N1_factor = MaxN1 - IdleN1; N1_factor = MaxN1 - IdleN1;
N2_factor = MaxN2 - IdleN2; N2_factor = MaxN2 - IdleN2;
OilTemp_degK = (Auxiliary->GetTotalTemperature() - 491.69) * 0.5555556 + 273.0; OilTemp_degK = (Auxiliary->GetTotalTemperature() - 491.69) * 0.5555556 + 273.0;
IdleFF = pow(MaxMilThrust, 0.2) * 107.0; // just an estimate IdleFF = pow(MilThrust, 0.2) * 107.0; // just an estimate
return true; return true;
} }

View file

@ -25,14 +25,14 @@
HISTORY HISTORY
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
03/11/2003 DPC Created 03/11/2003 DPC Created, based on FGTurbine
09/22/2003 DPC Added starting, stopping 09/22/2003 DPC Added starting, stopping, new framework
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
COMMENTS, REFERENCES, and NOTES COMMENTS, REFERENCES, and NOTES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
SENTRY SENTRY
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
@ -51,15 +51,56 @@ INCLUDES
#define ID_SIMTURBINE "$Id$" #define ID_SIMTURBINE "$Id$"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DECLARATION FORWARD DECLARATIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
namespace JSBSim { namespace JSBSim {
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DOCUMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/** This class models a turbine engine. Based on Jon Berndt's FGTurbine module.
Here the term "phase" signifies the engine's mode of operation. At any given
time the engine is in only one phase. At simulator startup the engine will be
placed in the Trim phase in order to provide a simplified thrust value without
throttle lag. When trimming is complete the engine will go to the Off phase,
unless the value FGEngine::Running has been previously set to true, in which
case the engine will go to the Run phase. Once an engine is in the Off phase
the full starting procedure (or airstart) must be used to get it running.
<P>
-STARTING (on ground):
-# Set the control FGEngine::Starter to true. The engine will spin up to
a maximum of about %25 N2 (%5.2 N1). This simulates the action of a
pneumatic starter.
-# After reaching %15 N2 set the control FGEngine::Cutoff to false. If fuel
is available the engine will now accelerate to idle. The starter will
automatically be set to false after the start cycle.
<P>
-STARTING (in air):
-# Increase speed to obtain a minimum of %15 N2. If this is not possible,
the starter may be used to assist.
-# Place the control FGEngine::Cutoff to false.
<P>
Ignition is assumed to be on anytime the Cutoff control is set to false,
therefore a seperate ignition system is not modeled.
@author David P. Culp
@version $Id$
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
class FGSimTurbine : public FGEngine class FGSimTurbine : public FGEngine
{ {
public: public:
/** Constructor
@param exec pointer to executive structure
@param Eng_Cfg pointer to engine config file instance */
FGSimTurbine(FGFDMExec* exec, FGConfigFile* Eng_cfg); FGSimTurbine(FGFDMExec* exec, FGConfigFile* Eng_cfg);
/// Destructor
~FGSimTurbine(); ~FGSimTurbine();
enum phaseType { tpOff, tpRun, tpSpinUp, tpStart, tpStall, tpSeize, tpTrim }; enum phaseType { tpOff, tpRun, tpSpinUp, tpStart, tpStall, tpSeize, tpTrim };
@ -80,32 +121,31 @@ private:
typedef vector<FGCoefficient*> CoeffArray; typedef vector<FGCoefficient*> CoeffArray;
CoeffArray ThrustTables; CoeffArray ThrustTables;
phaseType phase; // Operating mode, or "phase" phaseType phase; ///< Operating mode, or "phase"
double MaxMilThrust; // Maximum Rated Thrust, static @ S.L. (lbf) double MilThrust; ///< Maximum Unaugmented Thrust, static @ S.L. (lbf)
double BypassRatio; // Bypass Ratio double MaxThrust; ///< Maximum Augmented Thrust, static @ S.L. (lbf)
double TSFC; // Thrust Specific Fuel Consumption (lbm/hr/lbf) double BypassRatio; ///< Bypass Ratio
double ATSFC; // Augmented TSFC (lbm/hr/lbf) double TSFC; ///< Thrust Specific Fuel Consumption (lbm/hr/lbf)
double IdleN1; // Idle N1 double ATSFC; ///< Augmented TSFC (lbm/hr/lbf)
double IdleN2; // Idle N2 double IdleN1; ///< Idle N1
double MaxN1; // N1 at 100% throttle double IdleN2; ///< Idle N2
double MaxN2; // N2 at 100% throttle double MaxN1; ///< N1 at 100% throttle
double IdleFF; // Idle Fuel Flow (lbm/hr) double MaxN2; ///< N2 at 100% throttle
double delay; // Inverse spool-up time from idle to 100% (seconds) double IdleFF; ///< Idle Fuel Flow (lbm/hr)
double dt; // Simulator time slice double delay; ///< Inverse spool-up time from idle to 100% (seconds)
double N1_factor; // factor to tie N1 and throttle double dt; ///< Simulator time slice
double N2_factor; // factor to tie N2 and throttle double N1_factor; ///< factor to tie N1 and throttle
double ThrottleCmd; // FCS-supplied throttle position double N2_factor; ///< factor to tie N2 and throttle
double throttle; // virtual throttle position double ThrottleCmd; ///< FCS-supplied throttle position
double TAT; // total air temperature (deg C) double TAT; ///< total air temperature (deg C)
bool Stalled; // true if engine is compressor-stalled bool Stalled; ///< true if engine is compressor-stalled
bool Seized; // true if inner spool is seized bool Seized; ///< true if inner spool is seized
bool Overtemp; // true if EGT exceeds limits bool Overtemp; ///< true if EGT exceeds limits
bool Fire; // true if engine fire detected bool Fire; ///< true if engine fire detected
bool start_running; // true if user wants engine running at start int Augmented; ///< = 1 if augmentation installed
int Augmented; // = 1 if augmentation installed int Injected; ///< = 1 if water injection installed
int Injected; // = 1 if water injection installed int AugMethod; ///< = 0 if using property /engine[n]/augmentation
int AugMethod; // = 0 if using property /engine[n]/augmentation ///< = 1 if using last 1% of throttle movement
// = 1 if using last 1% of throttle movement
double Off(void); double Off(void);
double Run(void); double Run(void);

View file

@ -224,8 +224,6 @@ void FGJSBsim::init() {
Atmosphere->SetTurbGain(tmp * tmp * 100.0); Atmosphere->SetTurbGain(tmp * tmp * 100.0);
tmp = turbulence_rate->getDoubleValue(); tmp = turbulence_rate->getDoubleValue();
if (tmp <= 0)
tmp = 1.0;
Atmosphere->SetTurbRate(tmp); Atmosphere->SetTurbRate(tmp);
} else { } else {
@ -427,10 +425,7 @@ bool FGJSBsim::copy_to_JSBsim() {
tmp = turbulence_gain->getDoubleValue(); tmp = turbulence_gain->getDoubleValue();
Atmosphere->SetTurbGain(tmp * tmp * 100.0); Atmosphere->SetTurbGain(tmp * tmp * 100.0);
if (turbulence_rate->hasValue()) tmp = turbulence_rate->getDoubleValue();
tmp = turbulence_rate->getDoubleValue();
else
tmp = 1.0;
Atmosphere->SetTurbRate(tmp); Atmosphere->SetTurbRate(tmp);
Atmosphere->SetWindNED( wind_from_north->getDoubleValue(), Atmosphere->SetWindNED( wind_from_north->getDoubleValue(),
@ -819,6 +814,7 @@ void FGJSBsim::init_gear(void ) {
node->setBoolValue("wow", gr->GetGearUnit(i)->GetWOW()); node->setBoolValue("wow", gr->GetGearUnit(i)->GetWOW());
node->setBoolValue("has-brake", gr->GetGearUnit(i)->GetBrakeGroup() > 0); node->setBoolValue("has-brake", gr->GetGearUnit(i)->GetBrakeGroup() > 0);
node->setDoubleValue("position-norm", FCS->GetGearPos()); node->setDoubleValue("position-norm", FCS->GetGearPos());
node->setDoubleValue("tire-pressure-norm", gr->GetGearUnit(i)->GetTirePressure());
} }
} }
@ -832,6 +828,7 @@ void FGJSBsim::update_gear(void) {
->setBoolValue(gr->GetGearUnit(i)->GetWOW()); ->setBoolValue(gr->GetGearUnit(i)->GetWOW());
node->getChild("position-norm", 0, true) node->getChild("position-norm", 0, true)
->setDoubleValue(FCS->GetGearPos()); ->setDoubleValue(FCS->GetGearPos());
gr->GetGearUnit(i)->SetTirePressure(node->getDoubleValue("tire-pressure-norm"));
} }
} }

View file

@ -61,8 +61,8 @@ FGGain::FGGain(FGFCS* fcs, FGConfigFile* AC_cfg) : FGFCSComponent(fcs),
Gain = 1.000; Gain = 1.000;
Rows = 0; Rows = 0;
Min = Max = 0.0; Min = Max = 0.0;
OutputPct=0; OutputPct = 0;
invert=false; invert = false;
ScheduledBy = 0; ScheduledBy = 0;
Type = AC_cfg->GetValue("TYPE"); Type = AC_cfg->GetValue("TYPE");
@ -73,6 +73,12 @@ FGGain::FGGain(FGFCS* fcs, FGConfigFile* AC_cfg) : FGFCSComponent(fcs),
*AC_cfg >> token; *AC_cfg >> token;
if (token == "INPUT") { if (token == "INPUT") {
token = AC_cfg->GetValue("INPUT"); token = AC_cfg->GetValue("INPUT");
if (token[0] == '-') {
invert = true;
token.erase(0,1);
}
if (InputNodes.size() > 0) { if (InputNodes.size() > 0) {
cerr << "Gains can only accept one input" << endl; cerr << "Gains can only accept one input" << endl;
} else { } else {
@ -86,7 +92,10 @@ FGGain::FGGain(FGFCS* fcs, FGConfigFile* AC_cfg) : FGFCSComponent(fcs),
} else if (token == "MAX") { } else if (token == "MAX") {
*AC_cfg >> Max; *AC_cfg >> Max;
} else if (token == "INVERT") { } else if (token == "INVERT") {
invert=true; invert = true;
cerr << endl << "The INVERT keyword is being deprecated and will not be "
"supported in the future. Please use a minus sign in front "
"of an input property in the future." << endl << endl;
} else if (token == "ROWS") { } else if (token == "ROWS") {
*AC_cfg >> Rows; *AC_cfg >> Rows;
Table = new FGTable(Rows); Table = new FGTable(Rows);
@ -128,23 +137,26 @@ bool FGGain::Run(void )
FGFCSComponent::Run(); // call the base class for initialization of Input FGFCSComponent::Run(); // call the base class for initialization of Input
Input = InputNodes[0]->getDoubleValue(); Input = InputNodes[0]->getDoubleValue();
if (Type == "PURE_GAIN") {
if (invert) Input = -Input;
if (Type == "PURE_GAIN") { // PURE_GAIN
Output = Gain * Input; Output = Gain * Input;
} else if (Type == "SCHEDULED_GAIN") {
} else if (Type == "SCHEDULED_GAIN") { // SCHEDULED_GAIN
LookupVal = ScheduledBy->getDoubleValue(); LookupVal = ScheduledBy->getDoubleValue();
SchedGain = Table->GetValue(LookupVal); SchedGain = Table->GetValue(LookupVal);
Output = Gain * SchedGain * Input; Output = Gain * SchedGain * Input;
} else if (Type == "AEROSURFACE_SCALE") {
if (!invert) { } else if (Type == "AEROSURFACE_SCALE") { // AEROSURFACE_SCALE
OutputPct = Input;
if (Input >= 0.0) Output = Input * Max; OutputPct = Input;
else Output = Input * -Min; if (Input >= 0.0) Output = Input * Max;
} else { else Output = Input * -Min;
OutputPct=-1*Input;
if (Input <= 0.0) Output = Input * -Max;
else Output = Input * Min;
}
Output *= Gain; Output *= Gain;
} }
if (IsOutput) SetOutput(); if (IsOutput) SetOutput();
@ -177,7 +189,11 @@ void FGGain::Debug(int from)
if (debug_lvl & 1) { // Standard console startup message output if (debug_lvl & 1) { // Standard console startup message output
if (from == 0) { // Constructor if (from == 0) { // Constructor
cout << " INPUT: " << InputNodes[0]->getName() << endl; if (invert)
cout << " INPUT: -" << InputNodes[0]->getName() << endl;
else
cout << " INPUT: " << InputNodes[0]->getName() << endl;
cout << " GAIN: " << Gain << endl; cout << " GAIN: " << Gain << endl;
if (IsOutput) cout << " OUTPUT: " << OutputNode->getName() << endl; if (IsOutput) cout << " OUTPUT: " << OutputNode->getName() << endl;
cout << " MIN: " << Min << endl; cout << " MIN: " << Min << endl;

View file

@ -77,6 +77,8 @@ FGSummer::FGSummer(FGFCS* fcs, FGConfigFile* AC_cfg) : FGFCSComponent(fcs),
} }
InputNodes.push_back( resolveSymbol(token) ); InputNodes.push_back( resolveSymbol(token) );
} else if (token == "BIAS") {
*AC_cfg >> Bias;
} else if (token == "CLIPTO") { } else if (token == "CLIPTO") {
*AC_cfg >> clipmin >> clipmax; *AC_cfg >> clipmin >> clipmax;
if (clipmax > clipmin) { if (clipmax > clipmin) {
@ -116,6 +118,8 @@ bool FGSummer::Run(void )
Output += InputNodes[idx]->getDoubleValue()*InputSigns[idx]; Output += InputNodes[idx]->getDoubleValue()*InputSigns[idx];
} }
Output += Bias;
if (clip) { if (clip) {
if (Output > clipmax) Output = clipmax; if (Output > clipmax) Output = clipmax;
else if (Output < clipmin) Output = clipmin; else if (Output < clipmin) Output = clipmin;
@ -153,8 +157,12 @@ void FGSummer::Debug(int from)
if (from == 0) { // Constructor if (from == 0) { // Constructor
cout << " INPUTS: " << endl; cout << " INPUTS: " << endl;
for (unsigned i=0;i<InputNodes.size();i++) { for (unsigned i=0;i<InputNodes.size();i++) {
cout << " " << InputNodes[i]->getName() << endl; if (InputSigns[i] < 0)
cout << " -" << InputNodes[i]->getName() << endl;
else
cout << " " << InputNodes[i]->getName() << endl;
} }
if (Bias != 0.0) cout << " Bias: " << Bias << endl;
if (clip) cout << " CLIPTO: " << clipmin if (clip) cout << " CLIPTO: " << clipmin
<< ", " << clipmax << endl; << ", " << clipmax << endl;
if (IsOutput) cout << " OUTPUT: " <<OutputNode->getName() << endl; if (IsOutput) cout << " OUTPUT: " <<OutputNode->getName() << endl;

View file

@ -110,6 +110,12 @@ FGSwitch::FGSwitch(FGFCS* fcs, FGConfigFile* AC_cfg) : FGFCSComponent(fcs),
current_test->OutputVal = atof(value.c_str()); current_test->OutputVal = atof(value.c_str());
} else { } else {
// "value" must be a property if execution passes to here. // "value" must be a property if execution passes to here.
if (value[0] == '-') {
current_test->sign = -1.0;
value.erase(0,1);
} else {
current_test->sign = 1.0;
}
current_test->OutputProp = PropertyManager->GetNode(value); current_test->OutputProp = PropertyManager->GetNode(value);
} }
} }
@ -230,7 +236,10 @@ void FGSwitch::Debug(int from)
} }
if (iTests->OutputProp != 0L) if (iTests->OutputProp != 0L)
cout << indent << "Switch VALUE is " << iTests->OutputProp->GetName() << scratch << endl; if (iTests->sign < 0)
cout << indent << "Switch VALUE is - " << iTests->OutputProp->GetName() << scratch << endl;
else
cout << indent << "Switch VALUE is " << iTests->OutputProp->GetName() << scratch << endl;
else else
cout << indent << "Switch VALUE is " << iTests->OutputVal << scratch << endl; cout << indent << "Switch VALUE is " << iTests->OutputVal << scratch << endl;

View file

@ -127,16 +127,18 @@ private:
eLogic Logic; eLogic Logic;
double OutputVal; double OutputVal;
FGPropertyManager *OutputProp; FGPropertyManager *OutputProp;
float sign;
double GetValue(void) { double GetValue(void) {
if (OutputProp == 0L) return OutputVal; if (OutputProp == 0L) return OutputVal;
else return OutputProp->getDoubleValue(); else return OutputProp->getDoubleValue()*sign;
} }
test(void) { // constructor for the test structure test(void) { // constructor for the test structure
Logic = elUndef; Logic = elUndef;
OutputVal = 0.0; OutputVal = 0.0;
OutputProp = 0L; OutputProp = 0L;
sign = 1.0;
} }
}; };