CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-FGElectric::FGElectric(FGFDMExec* exec, FGConfigFile* Eng_cfg) : FGEngine(exec)
+FGElectric::FGElectric(FGFDMExec* exec, FGConfigFile* Eng_cfg, int engine_number)
+ : FGEngine(exec, engine_number)
{
string token;
Type = etElectric;
- EngineNumber = 0;
PowerWatts = 745.7;
hptowatts = 745.7;
{
public:
/// Constructor
- FGElectric(FGFDMExec* exec, FGConfigFile* Eng_cfg);
+ FGElectric(FGFDMExec* exec, FGConfigFile* Eng_cfg, int engine_number);
/// Destructor
~FGElectric();
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-FGEngine::FGEngine(FGFDMExec* exec)
+FGEngine::FGEngine(FGFDMExec* exec, int engine_number) : EngineNumber(engine_number)
{
Name = "";
Type = etUnknown;
FuelNeed = OxidizerNeed = 0.0;
Starved = Running = Cranking = false;
PctPower = 0.0;
- EngineNumber = -1;
TrimMode = false;
FuelFlow_gph = 0.0;
FuelFlow_pph = 0.0;
if (TrimMode) return;
Fshortage = Oshortage = TanksWithFuel = 0.0;
-
+
// count how many assigned tanks have fuel
for (unsigned int i=0; i<SourceTanks.size(); i++) {
Tank = Propulsion->GetTank(SourceTanks[i]);
class FGEngine : public FGJSBBase
{
public:
- FGEngine(FGFDMExec* exec);
+ FGEngine(FGFDMExec* exec, int engine_number);
virtual ~FGEngine();
enum EngineType {etUnknown, etRocket, etPiston, etTurbine, etElectric};
/// Sets engine placement information
virtual void SetPlacement(double x, double y, double z, double pitch, double yaw);
- /// Sets the engine number
- virtual void SetEngineNumber(int nn) {EngineNumber = nn;}
-
virtual double GetPowerAvailable(void) {return 0.0;};
virtual bool GetTrimMode(void) {return TrimMode;}
protected:
FGPropertyManager* PropertyManager;
string Name;
+ const int EngineNumber;
EngineType Type;
double X, Y, Z;
double EnginePitch;
double FuelNeed;
double OxidizerNeed;
double PctPower;
- int EngineNumber;
bool Starter;
bool Starved;
bool Running;
unsigned i;
char tmp[80];
-
for (i=0; i<ThrottleCmd.size(); i++) {
snprintf(tmp,80,"fcs/throttle-cmd-norm[%u]",i);
PropertyManager->Tie( tmp,this,i,
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-bool FGFDMExec::LoadModel(string AircraftPath, string EnginePath, string model)
+bool FGFDMExec::LoadModel(string AircraftPath, string EnginePath, string model,
+ bool addModelToPath)
{
+
FGFDMExec::AircraftPath = AircraftPath;
FGFDMExec::EnginePath = EnginePath;
- return LoadModel(model);
+ return LoadModel(model, addModelToPath);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-bool FGFDMExec::LoadModel(string model)
+
+bool FGFDMExec::LoadModel(string model, bool addModelToPath)
{
+
bool result = true;
string token;
string aircraftCfgFileName;
return false;
}
+ aircraftCfgFileName = AircraftPath;
# ifndef macintosh
- aircraftCfgFileName = AircraftPath + "/" + model + ".xml";
+ if (addModelToPath) aircraftCfgFileName += "/" + model;
+ aircraftCfgFileName += "/" + model + ".xml";
# else
- aircraftCfgFileName = AircraftPath + ";" + model + ".xml";
+ if (addModelToPath) aircraftCfgFileName += ";" + model;
+ aircraftCfgFileName += ";" + model + ".xml";
# endif
FGConfigFile AC_cfg(aircraftCfgFileName);
be looked for in the directory specified in the AircraftPath variable,
and in turn under the directory with the same name as the model. For
instance: "aircraft/x15/x15.xml"
+ @param addModelToPath set to true to add the model name to the
+ AircraftPath, defaults to true
@return true if successful*/
- bool LoadModel(string AircraftPath, string EnginePath, string model);
+ bool LoadModel(string AircraftPath, string EnginePath, string model,
+ bool addModelToPath = true);
/** Loads an aircraft model. The paths to the aircraft and engine
be looked for in the directory specified in the AircraftPath variable,
and in turn under the directory with the same name as the model. For
instance: "aircraft/x15/x15.xml"
+ @param addModelToPath set to true to add the model name to the
+ AircraftPath, defaults to true
@return true if successful*/
- bool LoadModel(string model);
+ bool LoadModel(string model, bool addModelToPath = true);
/** Sets the path to the engine config file directories.
return celsius * 1.8 + 32.0;
}
-
/** Finite precision comparison.
@param a first value to compare
@param b second value to compare
if (RollingWhlVel == 0.0 && SideWhlVel == 0.0) {
WheelSlip = 0.0;
} else if (fabs(RollingWhlVel) < 1.0) {
- WheelSlip = 0.05*radtodeg*atan2(SideWhlVel, RollingWhlVel) + 0.95*WheelSlip;
+ WheelSlip = 0.05*radtodeg*atan2(SideWhlVel, fabs(RollingWhlVel)) + 0.95*WheelSlip;
} else {
- WheelSlip = radtodeg*atan2(SideWhlVel, RollingWhlVel);
+ WheelSlip = radtodeg*atan2(SideWhlVel, fabs(RollingWhlVel));
}
/*
double maxdeltaSlip = 0.5*deltaT;
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-FGPiston::FGPiston(FGFDMExec* exec, FGConfigFile* Eng_cfg) : FGEngine(exec),
+FGPiston::FGPiston(FGFDMExec* exec, FGConfigFile* Eng_cfg, int engine_number)
+ : FGEngine(exec, engine_number),
R_air(287.3),
rho_fuel(800), // estimate
calorific_value_fuel(47.3e6),
Type = etPiston;
crank_counter = 0;
- EngineNumber = 0;
OilTemp_degK = 298;
MinManifoldPressure_inHg = 6.5;
MaxManifoldPressure_inHg = 28.5;
{
public:
/// Constructor
- FGPiston(FGFDMExec* exec, FGConfigFile* Eng_cfg);
+ FGPiston(FGFDMExec* exec, FGConfigFile* Eng_cfg, int engine_number);
/// Destructor
~FGPiston();
for (unsigned int i=0; i<numTanks; i++) {
Tanks[i]->Calculate( dt * rate );
- }
+ }
if (refuel) DoRefuel( dt * rate );
ThrottleAdded = true;
if (engType == "FG_ROCKET") {
- Engines.push_back(new FGRocket(FDMExec, Cfg_ptr));
+ Engines.push_back(new FGRocket(FDMExec, Cfg_ptr, numEngines));
} else if (engType == "FG_PISTON") {
- Engines.push_back(new FGPiston(FDMExec, Cfg_ptr));
+ Engines.push_back(new FGPiston(FDMExec, Cfg_ptr, numEngines));
} else if (engType == "FG_TURBINE") {
- Engines.push_back(new FGTurbine(FDMExec, Cfg_ptr));
+ Engines.push_back(new FGTurbine(FDMExec, Cfg_ptr, numEngines));
} else if (engType == "FG_SIMTURBINE") {
cerr << endl;
cerr << "The FG_SIMTURBINE engine type has been renamed to FG_TURBINE." << endl;
cerr << "To fix this problem, simply replace the FG_SIMTURBINE name " << endl;
cerr << "in your engine file to FG_TURBINE." << endl;
cerr << endl;
- Engines.push_back(new FGTurbine(FDMExec, Cfg_ptr));
+ Engines.push_back(new FGTurbine(FDMExec, Cfg_ptr, numEngines));
} else if (engType == "FG_ELECTRIC") {
- Engines.push_back(new FGElectric(FDMExec, Cfg_ptr));
+ Engines.push_back(new FGElectric(FDMExec, Cfg_ptr, numEngines));
} else {
cerr << fgred << " Unrecognized engine type: " << underon << engType
<< underoff << " found in config file." << fgdef << endl;
}
Engines[numEngines]->SetPlacement(xLoc, yLoc, zLoc, Pitch, Yaw);
- Engines[numEngines]->SetEngineNumber(numEngines);
numEngines++;
} else {
if (firstime) firstime = false;
else PropulsionStrings += ", ";
- PropulsionStrings += Engines[i]->GetEngineLabels() + ", ";
+ PropulsionStrings += Engines[i]->GetEngineLabels();
}
return PropulsionStrings;
if (firstime) firstime = false;
else PropulsionValues += ", ";
- PropulsionValues += Engines[i]->GetEngineValues() + ", ";
+ PropulsionValues += Engines[i]->GetEngineValues();
}
return PropulsionValues;
if (Tanks[i]->GetPctFull() < 99.99)
Transfer(-1, i, fillrate/TanksNotFull);
}
- }
+ }
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-FGRocket::FGRocket(FGFDMExec* exec, FGConfigFile* Eng_cfg) : FGEngine(exec)
+FGRocket::FGRocket(FGFDMExec* exec, FGConfigFile* Eng_cfg, int engine_number)
+ : FGEngine(exec, engine_number)
{
string token;
Debug(0);
- EngineNumber = 0;
Type = etRocket;
Flameout = false;
} else {
PctPower = Throttle / MaxThrottle;
PC = maxPC*PctPower * (1.0 + Variance * ((double)rand()/(double)RAND_MAX - 0.5));
+ // The Cf (below) is CF from Eqn. 3-30, "Rocket Propulsion Elements", Fifth Edition,
+ // George P. Sutton. Note that the thruster function GetPowerRequired() might
+ // be better called GetResistance() or something; this function returns the
+ // nozzle exit pressure.
Cf = sqrt(kFactor*(1 - pow(Thruster->GetPowerRequired()/(PC), (SHR-1)/SHR)));
Flameout = false;
}
public:
/** Constructor.
@param exec pointer to JSBSim parent object, the FDM Executive.
- @param Eng_cfg pointer to the config file object. */
- FGRocket(FGFDMExec* exec, FGConfigFile* Eng_cfg);
+ @param Eng_cfg pointer to the config file object.
+ @param engine_number engine number */
+ FGRocket(FGFDMExec* exec, FGConfigFile* Eng_cfg, int engine_number);
/** Destructor */
~FGRocket(void);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-FGTurbine::FGTurbine(FGFDMExec* exec, FGConfigFile* cfg) : FGEngine(exec)
+FGTurbine::FGTurbine(FGFDMExec* exec, FGConfigFile* cfg, int engine_number)
+ : FGEngine(exec, engine_number)
{
SetDefaults();
FGTurbine::~FGTurbine()
{
+ unbind();
Debug(1);
}
NozzlePosition = Seek(&NozzlePosition, 1.0, 0.8, 0.8);
}
- if ((AugmentCmd > 0.0) && (AugMethod == 2)) {
- Augmentation = true;
- double tdiff = (MaxThrust * ThrustTables[2]->TotalValue()) - thrust;
- thrust += (tdiff * AugmentCmd);
- FuelFlow_pph = Seek(&FuelFlow_pph, thrust * ATSFC, 5000.0, 10000.0);
- NozzlePosition = Seek(&NozzlePosition, 1.0, 0.8, 0.8);
- } else {
- Augmentation = false;
+ if (AugMethod == 2) {
+ if (AugmentCmd > 0.0) {
+ Augmentation = true;
+ double tdiff = (MaxThrust * ThrustTables[2]->TotalValue()) - thrust;
+ thrust += (tdiff * AugmentCmd);
+ FuelFlow_pph = Seek(&FuelFlow_pph, thrust * ATSFC, 5000.0, 10000.0);
+ NozzlePosition = Seek(&NozzlePosition, 1.0, 0.8, 0.8);
+ } else {
+ Augmentation = false;
+ }
}
if ((Injected == 1) && Injection)
OilTemp_degK = (Auxiliary->GetTotalTemperature() - 491.69) * 0.5555556 + 273.0;
IdleFF = pow(MilThrust, 0.2) * 107.0; // just an estimate
+ bindmodel();
return true;
}
return buf.str();
}
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGTurbine::bindmodel()
+{
+ char property_name[80];
+
+ snprintf(property_name, 80, "propulsion/n1[%u]", EngineNumber);
+ PropertyManager->Tie( property_name, &N1);
+ snprintf(property_name, 80, "propulsion/n2[%u]", EngineNumber);
+ PropertyManager->Tie( property_name, &N2);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGTurbine::unbind()
+{
+ char property_name[80];
+
+ snprintf(property_name, 80, "propulsion/n1[%u]", EngineNumber);
+ PropertyManager->Untie(property_name);
+ snprintf(property_name, 80, "propulsion/n2[%u]", EngineNumber);
+ PropertyManager->Untie(property_name);
+}
+
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// The bitmasked value choices are as follows:
// unset: In this case (the default) JSBSim would only print
public:
/** Constructor
@param Executive pointer to executive structure
- @param Eng_cfg pointer to engine config file instance */
- FGTurbine(FGFDMExec* Executive, FGConfigFile* Eng_cfg);
+ @param Eng_cfg pointer to engine config file instance
+ @param engine_number engine number*/
+ FGTurbine(FGFDMExec* Executive, FGConfigFile* Eng_cfg, int engine_number);
/// Destructor
~FGTurbine();
void SetDefaults(void);
bool Load(FGConfigFile *ENG_cfg);
+ void bindmodel(void);
+ void unbind(void);
void Debug(int from);
};
result = fdmex->LoadModel( aircraft_path.str(),
engine_path.str(),
- fgGetString("/sim/aero") );
+ fgGetString("/sim/aero"), false );
if (result) {
SG_LOG( SG_FLIGHT, SG_INFO, " loaded aero.");
} else if (Trigger != 0) {
test = Trigger->getIntValue();
if (test < 0) {
- Output = PreviousOutput1 = PreviousOutput2 = 0.0;
Input = PreviousInput1 = PreviousInput2 = 0.0;
} else {
Output = PreviousOutput1 = PreviousOutput2 = 0.0;