#define ID_AERODYNAMICS "$Id$"
-
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
namespace JSBSim {
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-COMMENTS, REFERENCES, and NOTES [use "class documentation" below for API docs]
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS DOCUMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
aerodynamic properties of this aircraft. Here also, such unique phenomena
as ground effect and maximum lift curve tailoff are handled.
@author Jon S. Berndt
+ @author Tony Peden
@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>
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
public:
/** Constructor
@param Executive a pointer to the parent executive object */
- FGAerodynamics(FGFDMExec*);
+ FGAerodynamics(FGFDMExec* Executive);
/// Destructor
~FGAerodynamics();
@return false if no error */
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 */
bool Load(FGConfigFile* AC_cfg);
/** Gets the total aerodynamic force vector.
@return a force vector reference. */
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);}
/** Gets the total aerodynamic moment vector.
@return a moment vector reference. */
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);}
FGColumnVector3& GetvLastFs(void) { return vLastFs; }
inline void SetAlphaCLMax(double tt) { alphaclmax=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 */
string GetCoefficientStrings(void);
// turbType = ttBerndt;
TurbGain = 0.0;
TurbRate = 1.0;
-
+
bind();
Debug(0);
}
Calculate(h);
}
- if (turbType != ttNone && TurbGain > 0.0) {
+ if (turbType != ttNone) {
Turbulence();
vWindNED += vTurbulence;
}
vDirectiondAccelDt(eY) = 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
// away from the peaks
MagnitudedAccelDt = ((MagnitudedAccelDt - Magnitude) /
FORWARD DECLARATIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+namespace JSBSim {
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
COMMENTS, REFERENCES, and NOTES [use "class documentation" below for API docs]
CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-namespace JSBSim {
-
class FGJSBBase {
public:
/// Constructor for FGJSBBase.
GearUp = false;
GearDown = true;
+ Servicable = true;
// Add some AI here to determine if gear is located properly according to its
// brake group type ??
brakePct = 0.0;
maxCompLen = 0.0;
+ TirePressureNorm = 1.0;
+
Debug(0);
}
GearDown = lgear.GearDown;
WheelSlip = lgear.WheelSlip;
lastWheelSlip = lgear.lastWheelSlip;
+ TirePressureNorm = lgear.TirePressureNorm;
+ Servicable = lgear.Servicable;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
switch (eBrakeGrp) {
case bgLeft:
SteerGain = 0.10;
- BrakeFCoeff = rollingFCoeff*(1.0 - FCS->GetBrake(bgLeft)) +
- staticFCoeff*FCS->GetBrake(bgLeft);
+ BrakeFCoeff = ( rollingFCoeff*(1.0 - FCS->GetBrake(bgLeft)) +
+ staticFCoeff*FCS->GetBrake(bgLeft) );
break;
case bgRight:
SteerGain = 0.10;
- BrakeFCoeff = rollingFCoeff*(1.0 - FCS->GetBrake(bgRight)) +
- staticFCoeff*FCS->GetBrake(bgRight);
+ BrakeFCoeff = ( rollingFCoeff*(1.0 - FCS->GetBrake(bgRight)) +
+ staticFCoeff*FCS->GetBrake(bgRight) );
break;
case bgCenter:
SteerGain = 0.10;
- BrakeFCoeff = rollingFCoeff*(1.0 - FCS->GetBrake(bgCenter)) +
- staticFCoeff*FCS->GetBrake(bgCenter);
+ BrakeFCoeff = ( rollingFCoeff*(1.0 - FCS->GetBrake(bgCenter)) +
+ staticFCoeff*FCS->GetBrake(bgCenter) );
break;
case bgNose:
SteerGain = -0.50;
- BrakeFCoeff = rollingFCoeff;
+ BrakeFCoeff = rollingFCoeff;
break;
case bgTail:
SteerGain = -0.10;
- BrakeFCoeff = rollingFCoeff;
+ BrakeFCoeff = rollingFCoeff;
break;
case bgNone:
SteerGain = 0.0;
- BrakeFCoeff = rollingFCoeff;
+ BrakeFCoeff = rollingFCoeff;
break;
default:
cerr << "Improper brake group membership detected for this gear." << endl;
RollingForce = 0;
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;
/// Gets the gear compression force in pounds
inline double GetCompForce(void) {return Force()(3); }
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)
inline void SetBrake(double bp) {brakePct = bp;}
double RollingForce, SideForce, FCoeff;
double WheelSlip;
double lastWheelSlip;
+ double TirePressureNorm;
bool WOW;
bool lastWOW;
bool FirstContact;
bool ReportEnable;
bool isRetractable;
bool GearUp, GearDown;
+ bool Servicable;
string name;
string sSteerType;
string sBrakeGroup;
double FGPiston::Calculate(double PowerRequired)
{
- ConsumeFuel();
+ if (FuelFlow_gph > 0.0) ConsumeFuel();
Throttle = FCS->GetThrottlePos(EngineNumber);
Mixture = FCS->GetMixturePos(EngineNumber);
{
double idlethrust, milthrust, thrust;
double N2norm; // 0.0 = idle N2, 1.0 = maximum N2
- idlethrust = MaxMilThrust * ThrustTables[0]->TotalValue();
- milthrust = (MaxMilThrust - idlethrust) * ThrustTables[1]->TotalValue();
+ idlethrust = MilThrust * ThrustTables[0]->TotalValue();
+ milthrust = (MilThrust - idlethrust) * ThrustTables[1]->TotalValue();
Running = true;
Starter = false;
N1 = Seek(&N1, IdleN1 + ThrottleCmd * N1_factor, delay, delay * 2.4);
N2norm = (N2 - IdleN2) / N2_factor;
thrust = idlethrust + (milthrust * N2norm * N2norm);
- FuelFlow_pph = thrust * TSFC;
thrust = thrust * (1.0 - BleedDemand);
+ FuelFlow_pph = thrust * TSFC;
if (FuelFlow_pph < IdleFF) FuelFlow_pph = IdleFF;
EGT_degC = TAT + 363.1 + ThrottleCmd * 357.1;
OilPressure_psi = N2 * 0.62;
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);
if (Reversed) thrust = thrust * -0.2;
}
if ((Augmented == 1) && Augmentation) {
- thrust = thrust * ThrustTables[2]->TotalValue();
+ thrust = MaxThrust * ThrustTables[2]->TotalValue();
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)
double FGSimTurbine::Start(void)
{
if ((N2 > 15.0) && !Starved) { // minimum 15% N2 needed for start
- Cranking = true;
+ Cranking = true; // provided for sound effects signal
if (N2 < IdleN2) {
N2 = Seek(&N2, IdleN2, 2.0, N2/2.0);
N1 = Seek(&N1, IdleN1, 1.4, N1/2.0);
double FGSimTurbine::Trim(void)
{
double idlethrust, milthrust, thrust;
- idlethrust = MaxMilThrust * ThrustTables[0]->TotalValue();
- milthrust = (MaxMilThrust - idlethrust) * ThrustTables[1]->TotalValue();
+ idlethrust = MilThrust * ThrustTables[0]->TotalValue();
+ milthrust = (MilThrust - idlethrust) * ThrustTables[1]->TotalValue();
thrust = idlethrust + (milthrust * ThrottleCmd * ThrottleCmd);
return thrust;
}
void FGSimTurbine::SetDefaults(void)
{
Name = "None_Defined";
- MaxMilThrust = 10000.0;
+ MilThrust = 10000.0;
+ MaxThrust = 10000.0;
BypassRatio = 0.0;
TSFC = 0.8;
ATSFC = 1.7;
Name = Eng_cfg->GetValue("NAME");
cout << Name << endl;
Eng_cfg->GetNextConfigLine();
- *Eng_cfg >> token >> MaxMilThrust;
+ *Eng_cfg >> token >> MilThrust;
+ *Eng_cfg >> token >> MaxThrust;
*Eng_cfg >> token >> BypassRatio;
*Eng_cfg >> token >> TSFC;
*Eng_cfg >> token >> ATSFC;
N1_factor = MaxN1 - IdleN1;
N2_factor = MaxN2 - IdleN2;
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;
}
HISTORY
--------------------------------------------------------------------------------
-03/11/2003 DPC Created
-09/22/2003 DPC Added starting, stopping
+03/11/2003 DPC Created, based on FGTurbine
+09/22/2003 DPC Added starting, stopping, new framework
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
COMMENTS, REFERENCES, and NOTES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
SENTRY
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_SIMTURBINE "$Id$"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DECLARATION
+FORWARD DECLARATIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
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
{
public:
+ /** Constructor
+ @param exec pointer to executive structure
+ @param Eng_Cfg pointer to engine config file instance */
FGSimTurbine(FGFDMExec* exec, FGConfigFile* Eng_cfg);
+ /// Destructor
~FGSimTurbine();
enum phaseType { tpOff, tpRun, tpSpinUp, tpStart, tpStall, tpSeize, tpTrim };
typedef vector<FGCoefficient*> CoeffArray;
CoeffArray ThrustTables;
- phaseType phase; // Operating mode, or "phase"
- double MaxMilThrust; // Maximum Rated Thrust, static @ S.L. (lbf)
- double BypassRatio; // Bypass Ratio
- double TSFC; // Thrust Specific Fuel Consumption (lbm/hr/lbf)
- double ATSFC; // Augmented TSFC (lbm/hr/lbf)
- double IdleN1; // Idle N1
- double IdleN2; // Idle N2
- double MaxN1; // N1 at 100% throttle
- double MaxN2; // N2 at 100% throttle
- double IdleFF; // Idle Fuel Flow (lbm/hr)
- double delay; // Inverse spool-up time from idle to 100% (seconds)
- double dt; // Simulator time slice
- double N1_factor; // factor to tie N1 and throttle
- double N2_factor; // factor to tie N2 and throttle
- double ThrottleCmd; // FCS-supplied throttle position
- double throttle; // virtual throttle position
- double TAT; // total air temperature (deg C)
- bool Stalled; // true if engine is compressor-stalled
- bool Seized; // true if inner spool is seized
- bool Overtemp; // true if EGT exceeds limits
- 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 Injected; // = 1 if water injection installed
- int AugMethod; // = 0 if using property /engine[n]/augmentation
- // = 1 if using last 1% of throttle movement
+ phaseType phase; ///< Operating mode, or "phase"
+ double MilThrust; ///< Maximum Unaugmented Thrust, static @ S.L. (lbf)
+ double MaxThrust; ///< Maximum Augmented Thrust, static @ S.L. (lbf)
+ double BypassRatio; ///< Bypass Ratio
+ double TSFC; ///< Thrust Specific Fuel Consumption (lbm/hr/lbf)
+ double ATSFC; ///< Augmented TSFC (lbm/hr/lbf)
+ double IdleN1; ///< Idle N1
+ double IdleN2; ///< Idle N2
+ double MaxN1; ///< N1 at 100% throttle
+ double MaxN2; ///< N2 at 100% throttle
+ double IdleFF; ///< Idle Fuel Flow (lbm/hr)
+ double delay; ///< Inverse spool-up time from idle to 100% (seconds)
+ double dt; ///< Simulator time slice
+ double N1_factor; ///< factor to tie N1 and throttle
+ double N2_factor; ///< factor to tie N2 and throttle
+ double ThrottleCmd; ///< FCS-supplied throttle position
+ double TAT; ///< total air temperature (deg C)
+ bool Stalled; ///< true if engine is compressor-stalled
+ bool Seized; ///< true if inner spool is seized
+ bool Overtemp; ///< true if EGT exceeds limits
+ bool Fire; ///< true if engine fire detected
+ int Augmented; ///< = 1 if augmentation installed
+ int Injected; ///< = 1 if water injection installed
+ int AugMethod; ///< = 0 if using property /engine[n]/augmentation
+ ///< = 1 if using last 1% of throttle movement
double Off(void);
double Run(void);
Atmosphere->SetTurbGain(tmp * tmp * 100.0);
tmp = turbulence_rate->getDoubleValue();
- if (tmp <= 0)
- tmp = 1.0;
Atmosphere->SetTurbRate(tmp);
} else {
tmp = turbulence_gain->getDoubleValue();
Atmosphere->SetTurbGain(tmp * tmp * 100.0);
- if (turbulence_rate->hasValue())
- tmp = turbulence_rate->getDoubleValue();
- else
- tmp = 1.0;
+ tmp = turbulence_rate->getDoubleValue();
Atmosphere->SetTurbRate(tmp);
Atmosphere->SetWindNED( wind_from_north->getDoubleValue(),
node->setBoolValue("wow", gr->GetGearUnit(i)->GetWOW());
node->setBoolValue("has-brake", gr->GetGearUnit(i)->GetBrakeGroup() > 0);
node->setDoubleValue("position-norm", FCS->GetGearPos());
+ node->setDoubleValue("tire-pressure-norm", gr->GetGearUnit(i)->GetTirePressure());
}
}
->setBoolValue(gr->GetGearUnit(i)->GetWOW());
node->getChild("position-norm", 0, true)
->setDoubleValue(FCS->GetGearPos());
+ gr->GetGearUnit(i)->SetTirePressure(node->getDoubleValue("tire-pressure-norm"));
}
}
Gain = 1.000;
Rows = 0;
Min = Max = 0.0;
- OutputPct=0;
- invert=false;
+ OutputPct = 0;
+ invert = false;
ScheduledBy = 0;
Type = AC_cfg->GetValue("TYPE");
*AC_cfg >> token;
if (token == "INPUT") {
token = AC_cfg->GetValue("INPUT");
+
+ if (token[0] == '-') {
+ invert = true;
+ token.erase(0,1);
+ }
+
if (InputNodes.size() > 0) {
cerr << "Gains can only accept one input" << endl;
} else {
} else if (token == "MAX") {
*AC_cfg >> Max;
} 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") {
*AC_cfg >> Rows;
Table = new FGTable(Rows);
FGFCSComponent::Run(); // call the base class for initialization of Input
Input = InputNodes[0]->getDoubleValue();
- if (Type == "PURE_GAIN") {
+
+ if (invert) Input = -Input;
+
+ if (Type == "PURE_GAIN") { // PURE_GAIN
+
Output = Gain * Input;
- } else if (Type == "SCHEDULED_GAIN") {
+
+ } else if (Type == "SCHEDULED_GAIN") { // SCHEDULED_GAIN
+
LookupVal = ScheduledBy->getDoubleValue();
SchedGain = Table->GetValue(LookupVal);
Output = Gain * SchedGain * Input;
- } else if (Type == "AEROSURFACE_SCALE") {
- if (!invert) {
- OutputPct = Input;
- if (Input >= 0.0) Output = Input * Max;
- else Output = Input * -Min;
- } else {
- OutputPct=-1*Input;
- if (Input <= 0.0) Output = Input * -Max;
- else Output = Input * Min;
- }
+
+ } else if (Type == "AEROSURFACE_SCALE") { // AEROSURFACE_SCALE
+
+ OutputPct = Input;
+ if (Input >= 0.0) Output = Input * Max;
+ else Output = Input * -Min;
Output *= Gain;
+
}
if (IsOutput) SetOutput();
if (debug_lvl & 1) { // Standard console startup message output
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;
if (IsOutput) cout << " OUTPUT: " << OutputNode->getName() << endl;
cout << " MIN: " << Min << endl;
}
InputNodes.push_back( resolveSymbol(token) );
+ } else if (token == "BIAS") {
+ *AC_cfg >> Bias;
} else if (token == "CLIPTO") {
*AC_cfg >> clipmin >> clipmax;
if (clipmax > clipmin) {
Output += InputNodes[idx]->getDoubleValue()*InputSigns[idx];
}
+ Output += Bias;
+
if (clip) {
if (Output > clipmax) Output = clipmax;
else if (Output < clipmin) Output = clipmin;
if (from == 0) { // Constructor
cout << " INPUTS: " << endl;
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
<< ", " << clipmax << endl;
if (IsOutput) cout << " OUTPUT: " <<OutputNode->getName() << endl;
current_test->OutputVal = atof(value.c_str());
} else {
// "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);
}
}
}
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
cout << indent << "Switch VALUE is " << iTests->OutputVal << scratch << endl;
eLogic Logic;
double OutputVal;
FGPropertyManager *OutputProp;
+ float sign;
double GetValue(void) {
if (OutputProp == 0L) return OutputVal;
- else return OutputProp->getDoubleValue();
+ else return OutputProp->getDoubleValue()*sign;
}
test(void) { // constructor for the test structure
Logic = elUndef;
OutputVal = 0.0;
OutputProp = 0L;
+ sign = 1.0;
}
};