1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 Module: FGPropulsion.cpp
6 Purpose: Encapsulates the set of engines, tanks, and thrusters associated
9 ------------- Copyright (C) 2000 Jon S. Berndt (jsb@hal-pc.org) -------------
11 This program is free software; you can redistribute it and/or modify it under
12 the terms of the GNU General Public License as published by the Free Software
13 Foundation; either version 2 of the License, or (at your option) any later
16 This program is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
21 You should have received a copy of the GNU General Public License along with
22 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
23 Place - Suite 330, Boston, MA 02111-1307, USA.
25 Further information about the GNU General Public License can also be found on
26 the world wide web at http://www.gnu.org.
28 FUNCTIONAL DESCRIPTION
29 --------------------------------------------------------------------------------
30 The Propulsion class is the container for the entire propulsion system, which is
31 comprised of engines, tanks, and "thrusters" (the device that transforms the
32 engine power into a force that acts on the aircraft, such as a nozzle or
33 propeller). Once the Propulsion class gets the config file, it reads in
34 information which is specific to a type of engine. Then:
36 1) The appropriate engine type instance is created
37 2) A thruster object is instantiated, and is linked to the engine
38 3) At least one tank object is created, and is linked to an engine.
40 At Run time each engines Calculate() method is called to return the excess power
41 generated during that iteration. The drag from the previous iteration is sub-
42 tracted to give the excess power available for thrust this pass. That quantity
43 is passed to the thrusters associated with a particular engine - perhaps with a
44 scaling mechanism (gearing?) to allow the engine to give its associated thrust-
45 ers specific distributed portions of the excess power.
48 --------------------------------------------------------------------------------
51 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
53 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
55 #include "FGPropulsion.h"
56 #include "FGPropertyManager.h"
59 static const char *IdSrc = "$Id$";
60 static const char *IdHdr = ID_PROPULSION;
62 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
64 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
66 FGPropulsion::FGPropulsion(FGFDMExec* exec) : FGModel(exec)
68 Name = "FGPropulsion";
69 numSelectedFuelTanks = numSelectedOxiTanks = 0;
70 numTanks = numEngines = numThrusters = 0;
71 numOxiTanks = numFuelTanks = 0;
76 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
78 FGPropulsion::~FGPropulsion()
80 for (unsigned int i=0; i<Engines.size(); i++) delete Engines[i];
86 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
88 bool FGPropulsion::Run(void)
90 double PowerAvailable;
94 vMoments.InitMatrix();
96 if (!FGModel::Run()) {
97 for (unsigned int i=0; i<numEngines; i++) {
98 Thrusters[i]->SetdeltaT(dt*rate);
99 PowerAvailable = Engines[i]->Calculate(Thrusters[i]->GetPowerRequired());
100 Thrusters[i]->Calculate(PowerAvailable);
101 vForces += Thrusters[i]->GetBodyForces(); // sum body frame forces
102 vMoments += Thrusters[i]->GetMoments(); // sum body frame moments
110 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
112 bool FGPropulsion::GetSteadyState(void)
114 double PowerAvailable;
115 double currentThrust = 0, lastThrust=-1;
117 int steady_count,j=0;
120 vForces.InitMatrix();
121 vMoments.InitMatrix();
123 if (!FGModel::Run()) {
124 for (unsigned int i=0; i<numEngines; i++) {
125 Engines[i]->SetTrimMode(true);
126 Thrusters[i]->SetdeltaT(dt*rate);
129 while (!steady && j < 6000) {
130 PowerAvailable = Engines[i]->Calculate(Thrusters[i]->GetPowerRequired());
131 lastThrust = currentThrust;
132 currentThrust = Thrusters[i]->Calculate(PowerAvailable);
133 if(fabs(lastThrust-currentThrust) < 0.0001) {
135 if(steady_count > 120) { steady=true; }
141 vForces += Thrusters[i]->GetBodyForces(); // sum body frame forces
142 vMoments += Thrusters[i]->GetMoments(); // sum body frame moments
143 Engines[i]->SetTrimMode(false);
152 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
154 bool FGPropulsion::ICEngineStart(void)
156 double PowerAvailable;
160 vForces.InitMatrix();
161 vMoments.InitMatrix();
163 for (unsigned int i=0; i<numEngines; i++) {
164 Engines[i]->SetTrimMode(true);
165 Thrusters[i]->SetdeltaT(dt*rate);
167 while (!Engines[i]->GetRunning() && j < 2000) {
168 PowerAvailable = Engines[i]->Calculate(Thrusters[i]->GetPowerRequired());
169 Thrusters[i]->Calculate(PowerAvailable);
172 vForces += Thrusters[i]->GetBodyForces(); // sum body frame forces
173 vMoments += Thrusters[i]->GetMoments(); // sum body frame moments
174 Engines[i]->SetTrimMode(false);
179 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
181 bool FGPropulsion::Load(FGConfigFile* AC_cfg)
183 string token, fullpath;
184 string engineFileName, engType;
185 string thrusterFileName, thrType;
187 string enginePath = FDMExec->GetEnginePath();
188 double xLoc, yLoc, zLoc, Pitch, Yaw;
189 double P_Factor = 0, Sense = 0.0;
191 bool ThrottleAdded = false;
194 fullpath = enginePath + "/";
196 fullpath = enginePath + ";";
199 AC_cfg->GetNextConfigLine();
201 while ((token = AC_cfg->GetValue()) != string("/PROPULSION")) {
203 if (token == "AC_ENGINE") { // ============ READING ENGINES
205 engineFileName = AC_cfg->GetValue("FILE");
207 if (debug_lvl > 0) cout << "\n Reading engine from file: " << fullpath
208 + engineFileName + ".xml"<< endl;
209 FGConfigFile Eng_cfg(fullpath + engineFileName + ".xml");
211 if (Eng_cfg.IsOpen()) {
212 Eng_cfg.GetNextConfigLine();
213 engType = Eng_cfg.GetValue();
216 ThrottleAdded = true;
218 if (engType == "FG_ROCKET") {
219 Engines.push_back(new FGRocket(FDMExec, &Eng_cfg));
220 } else if (engType == "FG_PISTON") {
221 Engines.push_back(new FGPiston(FDMExec, &Eng_cfg));
222 } else if (engType == "FG_TURBOJET") {
223 Engines.push_back(new FGTurboJet(FDMExec, &Eng_cfg));
224 } else if (engType == "FG_TURBOSHAFT") {
225 Engines.push_back(new FGTurboShaft(FDMExec, &Eng_cfg));
226 } else if (engType == "FG_TURBOPROP") {
227 Engines.push_back(new FGTurboProp(FDMExec, &Eng_cfg));
229 cerr << fgred << " Unrecognized engine type: " << underon << engType
230 << underoff << " found in config file." << fgdef << endl;
234 AC_cfg->GetNextConfigLine();
235 while ((token = AC_cfg->GetValue()) != string("/AC_ENGINE")) {
237 if (token == "XLOC") { *AC_cfg >> xLoc; }
238 else if (token == "YLOC") { *AC_cfg >> yLoc; }
239 else if (token == "ZLOC") { *AC_cfg >> zLoc; }
240 else if (token == "PITCH") { *AC_cfg >> Pitch;}
241 else if (token == "YAW") { *AC_cfg >> Yaw;}
242 else if (token == "FEED") {
244 Engines[numEngines]->AddFeedTank(Feed);
245 if (debug_lvl > 0) cout << " Feed tank: " << Feed << endl;
246 } else cerr << "Unknown identifier: " << token << " in engine file: "
247 << engineFileName << endl;
251 cout << " X = " << xLoc << endl;
252 cout << " Y = " << yLoc << endl;
253 cout << " Z = " << zLoc << endl;
254 cout << " Pitch = " << Pitch << endl;
255 cout << " Yaw = " << Yaw << endl;
258 Engines[numEngines]->SetPlacement(xLoc, yLoc, zLoc, Pitch, Yaw);
259 Engines[numEngines]->SetEngineNumber(numEngines);
264 cerr << fgred << "\n Could not read engine config file: " << underon <<
265 fullpath + engineFileName + ".xml" << underoff << fgdef << endl;
269 } else if (token == "AC_TANK") { // ============== READING TANKS
271 if (debug_lvl > 0) cout << "\n Reading tank definition" << endl;
272 Tanks.push_back(new FGTank(AC_cfg));
273 switch(Tanks[numTanks]->GetType()) {
275 numSelectedFuelTanks++;
278 case FGTank::ttOXIDIZER:
279 numSelectedOxiTanks++;
286 } else if (token == "AC_THRUSTER") { // ========== READING THRUSTERS
288 thrusterFileName = AC_cfg->GetValue("FILE");
290 if (debug_lvl > 0) cout << "\n Reading thruster from file: " <<
291 fullpath + thrusterFileName + ".xml" << endl;
292 FGConfigFile Thruster_cfg(fullpath + thrusterFileName + ".xml");
294 if (Thruster_cfg.IsOpen()) {
295 Thruster_cfg.GetNextConfigLine();
296 thrType = Thruster_cfg.GetValue();
298 if (thrType == "FG_PROPELLER") {
299 Thrusters.push_back(new FGPropeller(FDMExec, &Thruster_cfg));
300 } else if (thrType == "FG_NOZZLE") {
301 Thrusters.push_back(new FGNozzle(FDMExec, &Thruster_cfg));
304 AC_cfg->GetNextConfigLine();
305 while ((token = AC_cfg->GetValue()) != string("/AC_THRUSTER")) {
307 if (token == "XLOC") *AC_cfg >> xLoc;
308 else if (token == "YLOC") *AC_cfg >> yLoc;
309 else if (token == "ZLOC") *AC_cfg >> zLoc;
310 else if (token == "PITCH") *AC_cfg >> Pitch;
311 else if (token == "YAW") *AC_cfg >> Yaw;
312 else if (token == "P_FACTOR") *AC_cfg >> P_Factor;
313 else if (token == "SENSE") *AC_cfg >> Sense;
314 else cerr << "Unknown identifier: " << token << " in engine file: "
315 << engineFileName << endl;
318 Thrusters[numThrusters]->SetLocation(xLoc, yLoc, zLoc);
319 Thrusters[numThrusters]->SetAnglesToBody(0, Pitch, Yaw);
320 if (thrType == "FG_PROPELLER" && P_Factor > 0.001) {
321 ((FGPropeller*)Thrusters[numThrusters])->SetPFactor(P_Factor);
322 if (debug_lvl > 0) cout << " P-Factor: " << P_Factor << endl;
323 ((FGPropeller*)Thrusters[numThrusters])->SetSense(fabs(Sense)/Sense);
324 if (debug_lvl > 0) cout << " Sense: " << Sense << endl;
326 Thrusters[numThrusters]->SetdeltaT(dt*rate);
327 Thrusters[numThrusters]->SetThrusterNumber(numThrusters);
331 cerr << "Could not read thruster config file: " << fullpath
332 + thrusterFileName + ".xml" << endl;
337 AC_cfg->GetNextConfigLine();
340 if (!ThrottleAdded) FCS->AddThrottle(); // need to have at least one throttle
345 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
347 string FGPropulsion::GetPropulsionStrings(void)
349 string PropulsionStrings = "";
350 bool firstime = true;
353 for (unsigned int i=0;i<Engines.size();i++) {
354 if (firstime) firstime = false;
355 else PropulsionStrings += ", ";
357 sprintf(buffer, "%d", i);
359 switch(Engines[i]->GetType()) {
360 case FGEngine::etPiston:
361 PropulsionStrings += (Engines[i]->GetName() + "_PwrAvail[" + buffer + "]");
363 case FGEngine::etRocket:
364 PropulsionStrings += (Engines[i]->GetName() + "_ChamberPress[" + buffer + "]");
366 case FGEngine::etTurboJet:
367 case FGEngine::etTurboProp:
368 case FGEngine::etTurboShaft:
371 PropulsionStrings += "INVALID ENGINE TYPE";
375 PropulsionStrings += ", ";
377 FGPropeller* Propeller = (FGPropeller*)Thrusters[i];
378 switch(Thrusters[i]->GetType()) {
379 case FGThruster::ttNozzle:
380 PropulsionStrings += (Thrusters[i]->GetName() + "_Thrust[" + buffer + "]");
382 case FGThruster::ttRotor:
384 case FGThruster::ttPropeller:
385 PropulsionStrings += (Thrusters[i]->GetName() + "_Torque[" + buffer + "], ");
386 PropulsionStrings += (Thrusters[i]->GetName() + "_PFactor_Roll[" + buffer + "], ");
387 PropulsionStrings += (Thrusters[i]->GetName() + "_PFactor_Pitch[" + buffer + "], ");
388 PropulsionStrings += (Thrusters[i]->GetName() + "_PFactor_Yaw[" + buffer + "], ");
389 PropulsionStrings += (Thrusters[i]->GetName() + "_Thrust[" + buffer + "], ");
390 if (Propeller->IsVPitch())
391 PropulsionStrings += (Thrusters[i]->GetName() + "_Pitch[" + buffer + "], ");
392 PropulsionStrings += (Thrusters[i]->GetName() + "_RPM[" + buffer + "]");
395 PropulsionStrings += "INVALID THRUSTER TYPE";
400 return PropulsionStrings;
403 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
405 string FGPropulsion::GetPropulsionValues(void)
408 string PropulsionValues = "";
409 bool firstime = true;
411 for (unsigned int i=0;i<Engines.size();i++) {
412 if (firstime) firstime = false;
413 else PropulsionValues += ", ";
415 switch(Engines[i]->GetType()) {
416 case FGEngine::etPiston:
417 PropulsionValues += (string(gcvt(((FGPiston*)Engines[i])->GetPowerAvailable(), 10, buff)));
419 case FGEngine::etRocket:
420 PropulsionValues += (string(gcvt(((FGRocket*)Engines[i])->GetChamberPressure(), 10, buff)));
422 case FGEngine::etTurboJet:
423 case FGEngine::etTurboProp:
424 case FGEngine::etTurboShaft:
428 PropulsionValues += ", ";
430 switch(Thrusters[i]->GetType()) {
431 case FGThruster::ttNozzle:
432 PropulsionValues += (string(gcvt(((FGNozzle*)Thrusters[i])->GetThrust(), 10, buff)));
434 case FGThruster::ttRotor:
436 case FGThruster::ttPropeller:
437 FGPropeller* Propeller = (FGPropeller*)Thrusters[i];
438 FGColumnVector3 vPFactor = Propeller->GetPFactor();
439 PropulsionValues += string(gcvt(Propeller->GetTorque(), 10, buff)) + ", ";
440 PropulsionValues += string(gcvt(vPFactor(eRoll), 10, buff)) + ", ";
441 PropulsionValues += string(gcvt(vPFactor(ePitch), 10, buff)) + ", ";
442 PropulsionValues += string(gcvt(vPFactor(eYaw), 10, buff)) + ", ";
443 PropulsionValues += string(gcvt(Propeller->GetThrust(), 10, buff)) + ", ";
444 if (Propeller->IsVPitch())
445 PropulsionValues += string(gcvt(Propeller->GetPitch(), 10, buff)) + ", ";
446 PropulsionValues += string(gcvt(Propeller->GetRPM(), 10, buff));
451 return PropulsionValues;
454 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
456 FGColumnVector3& FGPropulsion::GetTanksCG(void)
458 iTank = Tanks.begin();
459 vXYZtank.InitMatrix();
460 while (iTank < Tanks.end()) {
461 vXYZtank(eX) += (*iTank)->GetX()*(*iTank)->GetContents();
462 vXYZtank(eY) += (*iTank)->GetY()*(*iTank)->GetContents();
463 vXYZtank(eZ) += (*iTank)->GetZ()*(*iTank)->GetContents();
469 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
471 double FGPropulsion::GetTanksWeight(void)
475 iTank = Tanks.begin();
476 while (iTank < Tanks.end()) {
477 Tw += (*iTank)->GetContents();
483 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
485 double FGPropulsion::GetTanksIxx(const FGColumnVector3& vXYZcg)
488 iTank = Tanks.begin();
489 while (iTank < Tanks.end()) {
490 I += ((*iTank)->GetX() - vXYZcg(eX))*((*iTank)->GetX() - vXYZcg(eX)) * (*iTank)->GetContents()/(144.0*Inertial->gravity());
496 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
498 double FGPropulsion::GetTanksIyy(const FGColumnVector3& vXYZcg)
501 iTank = Tanks.begin();
502 while (iTank < Tanks.end()) {
503 I += ((*iTank)->GetY() - vXYZcg(eY))*((*iTank)->GetY() - vXYZcg(eY)) * (*iTank)->GetContents()/(144.0*Inertial->gravity());
509 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
511 double FGPropulsion::GetTanksIzz(const FGColumnVector3& vXYZcg)
514 iTank = Tanks.begin();
515 while (iTank < Tanks.end()) {
516 I += ((*iTank)->GetZ() - vXYZcg(eZ))*((*iTank)->GetZ() - vXYZcg(eZ)) * (*iTank)->GetContents()/(144.0*Inertial->gravity());
522 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
524 double FGPropulsion::GetTanksIxz(const FGColumnVector3& vXYZcg)
527 iTank = Tanks.begin();
528 while (iTank < Tanks.end()) {
529 I += ((*iTank)->GetX() - vXYZcg(eX))*((*iTank)->GetZ() - vXYZcg(eZ)) * (*iTank)->GetContents()/(144.0*Inertial->gravity());
535 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
537 double FGPropulsion::GetTanksIxy(const FGColumnVector3& vXYZcg)
540 iTank = Tanks.begin();
541 while (iTank != Tanks.end()) {
542 I += ((*iTank)->GetX() - vXYZcg(eX))*((*iTank)->GetY() - vXYZcg(eY)) * (*iTank)->GetContents()/(144.0*Inertial->gravity());
548 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
550 void FGPropulsion::bind(void){
551 /* PropertyManager->Tie("propulsion/num-engines", this,
552 &FGPropulsion::GetNumEngines);
553 PropertyManager->Tie("propulsion/num-tanks", this,
554 &FGPropulsion::GetNumTanks); */
555 PropertyManager->Tie("propulsion/num-sel-fuel-tanks", this,
556 &FGPropulsion::GetnumSelectedFuelTanks);
557 PropertyManager->Tie("propulsion/num-sel-ox-tanks", this,
558 &FGPropulsion::GetnumSelectedOxiTanks);
559 PropertyManager->Tie("forces/fbx-prop-lbs", this,1,
560 &FGPropulsion::GetForces);
561 PropertyManager->Tie("forces/fby-prop-lbs", this,2,
562 &FGPropulsion::GetForces);
563 PropertyManager->Tie("forces/fbz-prop-lbs", this,3,
564 &FGPropulsion::GetForces);
565 PropertyManager->Tie("moments/l-prop-lbsft", this,1,
566 &FGPropulsion::GetMoments);
567 PropertyManager->Tie("moments/m-prop-lbsft", this,2,
568 &FGPropulsion::GetMoments);
569 PropertyManager->Tie("moments/n-prop-lbsft", this,3,
570 &FGPropulsion::GetMoments);
571 //PropertyManager->Tie("propulsion/tanks-weight-lbs", this,
572 // &FGPropulsion::GetTanksWeight);
575 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
577 void FGPropulsion::unbind(void){
578 /* PropertyManager->Untie("propulsion/num-engines");
579 PropertyManager->Untie("propulsion/num-tanks"); */
580 PropertyManager->Untie("propulsion/num-sel-fuel-tanks");
581 PropertyManager->Untie("propulsion/num-sel-ox-tanks");
582 PropertyManager->Untie("forces/fbx-prop-lbs");
583 PropertyManager->Untie("forces/fby-prop-lbs");
584 PropertyManager->Untie("forces/fbz-prop-lbs");
585 PropertyManager->Untie("moments/l-prop-lbsft");
586 PropertyManager->Untie("moments/m-prop-lbsft");
587 PropertyManager->Untie("moments/n-prop-lbsft");
588 //PropertyManager->Untie("propulsion/tanks-weight-lbs");
591 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
592 // The bitmasked value choices are as follows:
593 // unset: In this case (the default) JSBSim would only print
594 // out the normally expected messages, essentially echoing
595 // the config files as they are read. If the environment
596 // variable is not set, debug_lvl is set to 1 internally
597 // 0: This requests JSBSim not to output any messages
599 // 1: This value explicity requests the normal JSBSim
601 // 2: This value asks for a message to be printed out when
602 // a class is instantiated
603 // 4: When this value is set, a message is displayed when a
604 // FGModel object executes its Run() method
605 // 8: When this value is set, various runtime state variables
606 // are printed out periodically
607 // 16: When set various parameters are sanity checked and
608 // a message is printed out when they go out of bounds
610 void FGPropulsion::Debug(int from)
612 if (debug_lvl <= 0) return;
614 if (debug_lvl & 1) { // Standard console startup message output
615 if (from == 0) { // Constructor
619 if (debug_lvl & 2 ) { // Instantiation/Destruction notification
620 if (from == 0) cout << "Instantiated: FGPropulsion" << endl;
621 if (from == 1) cout << "Destroyed: FGPropulsion" << endl;
623 if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
625 if (debug_lvl & 8 ) { // Runtime state variables
627 if (debug_lvl & 16) { // Sanity checking
629 if (debug_lvl & 64) {
630 if (from == 0) { // Constructor
631 cout << IdSrc << endl;
632 cout << IdHdr << endl;