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 extern short debug_lvl;
64 #if defined (__APPLE__)
65 /* Not all systems have the gcvt function */
66 inline char* gcvt (double value, int ndigits, char *buf) {
67 /* note that this is not exactly what gcvt is supposed to do! */
68 snprintf (buf, ndigits+1, "%f", value);
74 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
76 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
78 FGPropulsion::FGPropulsion(FGFDMExec* exec) : FGModel(exec)
80 Name = "FGPropulsion";
81 numSelectedFuelTanks = numSelectedOxiTanks = 0;
82 numTanks = numEngines = numThrusters = 0;
83 numOxiTanks = numFuelTanks = 0;
89 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
91 FGPropulsion::~FGPropulsion()
93 for (unsigned int i=0; i<Engines.size(); i++) delete Engines[i];
99 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
101 bool FGPropulsion::Run(void)
103 double PowerAvailable;
106 vForces.InitMatrix();
107 vMoments.InitMatrix();
109 if (!FGModel::Run()) {
110 for (unsigned int i=0; i<numEngines; i++) {
111 Thrusters[i]->SetdeltaT(dt*rate);
112 PowerAvailable = Engines[i]->Calculate(Thrusters[i]->GetPowerRequired());
113 Thrusters[i]->Calculate(PowerAvailable);
114 vForces += Thrusters[i]->GetBodyForces(); // sum body frame forces
115 vMoments += Thrusters[i]->GetMoments(); // sum body frame moments
123 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
125 bool FGPropulsion::GetSteadyState(void)
127 double PowerAvailable;
128 double currentThrust = 0, lastThrust=-1;
130 int steady_count,j=0;
133 vForces.InitMatrix();
134 vMoments.InitMatrix();
136 if (!FGModel::Run()) {
137 for (unsigned int i=0; i<numEngines; i++) {
138 Engines[i]->SetTrimMode(true);
139 Thrusters[i]->SetdeltaT(dt*rate);
142 while (!steady && j < 6000) {
143 PowerAvailable = Engines[i]->Calculate(Thrusters[i]->GetPowerRequired());
144 lastThrust = currentThrust;
145 currentThrust = Thrusters[i]->Calculate(PowerAvailable);
146 if (fabs(lastThrust-currentThrust) < 0.0001) {
148 if (steady_count > 120) { steady=true; }
154 vForces += Thrusters[i]->GetBodyForces(); // sum body frame forces
155 vMoments += Thrusters[i]->GetMoments(); // sum body frame moments
156 Engines[i]->SetTrimMode(false);
165 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
167 bool FGPropulsion::ICEngineStart(void)
169 double PowerAvailable;
173 vForces.InitMatrix();
174 vMoments.InitMatrix();
176 for (unsigned int i=0; i<numEngines; i++) {
177 Engines[i]->SetTrimMode(true);
178 Thrusters[i]->SetdeltaT(dt*rate);
180 while (!Engines[i]->GetRunning() && j < 2000) {
181 PowerAvailable = Engines[i]->Calculate(Thrusters[i]->GetPowerRequired());
182 Thrusters[i]->Calculate(PowerAvailable);
185 vForces += Thrusters[i]->GetBodyForces(); // sum body frame forces
186 vMoments += Thrusters[i]->GetMoments(); // sum body frame moments
187 Engines[i]->SetTrimMode(false);
192 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
194 bool FGPropulsion::Load(FGConfigFile* AC_cfg)
196 string token, fullpath;
197 string engineFileName, engType;
198 string thrusterFileName, thrType;
200 string enginePath = FDMExec->GetEnginePath();
201 double xLoc, yLoc, zLoc, Pitch, Yaw;
202 double P_Factor = 0, Sense = 0.0;
204 bool ThrottleAdded = false;
207 fullpath = enginePath + "/";
209 fullpath = enginePath + ";";
212 AC_cfg->GetNextConfigLine();
214 while ((token = AC_cfg->GetValue()) != string("/PROPULSION")) {
216 if (token == "AC_ENGINE") { // ============ READING ENGINES
218 engineFileName = AC_cfg->GetValue("FILE");
220 if (debug_lvl > 0) cout << "\n Reading engine from file: " << fullpath
221 + engineFileName + ".xml"<< endl;
222 FGConfigFile Eng_cfg(fullpath + engineFileName + ".xml");
224 if (Eng_cfg.IsOpen()) {
225 Eng_cfg.GetNextConfigLine();
226 engType = Eng_cfg.GetValue();
229 ThrottleAdded = true;
231 if (engType == "FG_ROCKET") {
232 Engines.push_back(new FGRocket(FDMExec, &Eng_cfg));
233 } else if (engType == "FG_PISTON") {
234 Engines.push_back(new FGPiston(FDMExec, &Eng_cfg));
235 } else if (engType == "FG_TURBOJET") {
236 Engines.push_back(new FGTurboJet(FDMExec, &Eng_cfg));
237 } else if (engType == "FG_TURBOSHAFT") {
238 Engines.push_back(new FGTurboShaft(FDMExec, &Eng_cfg));
239 } else if (engType == "FG_TURBOPROP") {
240 Engines.push_back(new FGTurboProp(FDMExec, &Eng_cfg));
242 cerr << fgred << " Unrecognized engine type: " << underon << engType
243 << underoff << " found in config file." << fgdef << endl;
247 AC_cfg->GetNextConfigLine();
248 while ((token = AC_cfg->GetValue()) != string("/AC_ENGINE")) {
250 if (token == "XLOC") { *AC_cfg >> xLoc; }
251 else if (token == "YLOC") { *AC_cfg >> yLoc; }
252 else if (token == "ZLOC") { *AC_cfg >> zLoc; }
253 else if (token == "PITCH") { *AC_cfg >> Pitch;}
254 else if (token == "YAW") { *AC_cfg >> Yaw;}
255 else if (token == "FEED") {
257 Engines[numEngines]->AddFeedTank(Feed);
258 if (debug_lvl > 0) cout << " Feed tank: " << Feed << endl;
259 } else cerr << "Unknown identifier: " << token << " in engine file: "
260 << engineFileName << endl;
264 cout << " X = " << xLoc << endl;
265 cout << " Y = " << yLoc << endl;
266 cout << " Z = " << zLoc << endl;
267 cout << " Pitch = " << Pitch << endl;
268 cout << " Yaw = " << Yaw << endl;
271 Engines[numEngines]->SetPlacement(xLoc, yLoc, zLoc, Pitch, Yaw);
272 Engines[numEngines]->SetEngineNumber(numEngines);
277 cerr << fgred << "\n Could not read engine config file: " << underon <<
278 fullpath + engineFileName + ".xml" << underoff << fgdef << endl;
282 } else if (token == "AC_TANK") { // ============== READING TANKS
284 if (debug_lvl > 0) cout << "\n Reading tank definition" << endl;
285 Tanks.push_back(new FGTank(AC_cfg));
286 switch(Tanks[numTanks]->GetType()) {
288 numSelectedFuelTanks++;
291 case FGTank::ttOXIDIZER:
292 numSelectedOxiTanks++;
299 } else if (token == "AC_THRUSTER") { // ========== READING THRUSTERS
301 thrusterFileName = AC_cfg->GetValue("FILE");
303 if (debug_lvl > 0) cout << "\n Reading thruster from file: " <<
304 fullpath + thrusterFileName + ".xml" << endl;
305 FGConfigFile Thruster_cfg(fullpath + thrusterFileName + ".xml");
307 if (Thruster_cfg.IsOpen()) {
308 Thruster_cfg.GetNextConfigLine();
309 thrType = Thruster_cfg.GetValue();
311 if (thrType == "FG_PROPELLER") {
312 Thrusters.push_back(new FGPropeller(FDMExec, &Thruster_cfg));
313 } else if (thrType == "FG_NOZZLE") {
314 Thrusters.push_back(new FGNozzle(FDMExec, &Thruster_cfg));
317 AC_cfg->GetNextConfigLine();
318 while ((token = AC_cfg->GetValue()) != string("/AC_THRUSTER")) {
320 if (token == "XLOC") *AC_cfg >> xLoc;
321 else if (token == "YLOC") *AC_cfg >> yLoc;
322 else if (token == "ZLOC") *AC_cfg >> zLoc;
323 else if (token == "PITCH") *AC_cfg >> Pitch;
324 else if (token == "YAW") *AC_cfg >> Yaw;
325 else if (token == "P_FACTOR") *AC_cfg >> P_Factor;
326 else if (token == "SENSE") *AC_cfg >> Sense;
327 else cerr << "Unknown identifier: " << token << " in engine file: "
328 << engineFileName << endl;
331 Thrusters[numThrusters]->SetLocation(xLoc, yLoc, zLoc);
332 Thrusters[numThrusters]->SetAnglesToBody(0, Pitch, Yaw);
333 if (thrType == "FG_PROPELLER" && P_Factor > 0.001) {
334 ((FGPropeller*)Thrusters[numThrusters])->SetPFactor(P_Factor);
335 if (debug_lvl > 0) cout << " P-Factor: " << P_Factor << endl;
336 ((FGPropeller*)Thrusters[numThrusters])->SetSense(fabs(Sense)/Sense);
337 if (debug_lvl > 0) cout << " Sense: " << Sense << endl;
339 Thrusters[numThrusters]->SetdeltaT(dt*rate);
340 Thrusters[numThrusters]->SetThrusterNumber(numThrusters);
344 cerr << "Could not read thruster config file: " << fullpath
345 + thrusterFileName + ".xml" << endl;
350 AC_cfg->GetNextConfigLine();
353 if (!ThrottleAdded) FCS->AddThrottle(); // need to have at least one throttle
358 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
360 string FGPropulsion::GetPropulsionStrings(void)
362 string PropulsionStrings = "";
363 bool firstime = true;
366 for (unsigned int i=0;i<Engines.size();i++) {
367 if (firstime) firstime = false;
368 else PropulsionStrings += ", ";
370 sprintf(buffer, "%d", i);
372 switch(Engines[i]->GetType()) {
373 case FGEngine::etPiston:
374 PropulsionStrings += (Engines[i]->GetName() + "_PwrAvail[" + buffer + "]");
376 case FGEngine::etRocket:
377 PropulsionStrings += (Engines[i]->GetName() + "_ChamberPress[" + buffer + "]");
379 case FGEngine::etTurboJet:
380 case FGEngine::etTurboProp:
381 case FGEngine::etTurboShaft:
384 PropulsionStrings += "INVALID ENGINE TYPE";
388 PropulsionStrings += ", ";
390 FGPropeller* Propeller = (FGPropeller*)Thrusters[i];
391 switch(Thrusters[i]->GetType()) {
392 case FGThruster::ttNozzle:
393 PropulsionStrings += (Thrusters[i]->GetName() + "_Thrust[" + buffer + "]");
395 case FGThruster::ttRotor:
397 case FGThruster::ttPropeller:
398 PropulsionStrings += (Thrusters[i]->GetName() + "_Torque[" + buffer + "], ");
399 PropulsionStrings += (Thrusters[i]->GetName() + "_PFactor_Roll[" + buffer + "], ");
400 PropulsionStrings += (Thrusters[i]->GetName() + "_PFactor_Pitch[" + buffer + "], ");
401 PropulsionStrings += (Thrusters[i]->GetName() + "_PFactor_Yaw[" + buffer + "], ");
402 PropulsionStrings += (Thrusters[i]->GetName() + "_Thrust[" + buffer + "], ");
403 if (Propeller->IsVPitch())
404 PropulsionStrings += (Thrusters[i]->GetName() + "_Pitch[" + buffer + "], ");
405 PropulsionStrings += (Thrusters[i]->GetName() + "_RPM[" + buffer + "]");
408 PropulsionStrings += "INVALID THRUSTER TYPE";
413 return PropulsionStrings;
416 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
418 string FGPropulsion::GetPropulsionValues(void)
421 string PropulsionValues = "";
422 bool firstime = true;
424 for (unsigned int i=0;i<Engines.size();i++) {
425 if (firstime) firstime = false;
426 else PropulsionValues += ", ";
428 switch(Engines[i]->GetType()) {
429 case FGEngine::etPiston:
430 PropulsionValues += (string(gcvt(((FGPiston*)Engines[i])->GetPowerAvailable(), 10, buff)));
432 case FGEngine::etRocket:
433 PropulsionValues += (string(gcvt(((FGRocket*)Engines[i])->GetChamberPressure(), 10, buff)));
435 case FGEngine::etTurboJet:
436 case FGEngine::etTurboProp:
437 case FGEngine::etTurboShaft:
441 PropulsionValues += ", ";
443 switch(Thrusters[i]->GetType()) {
444 case FGThruster::ttNozzle:
445 PropulsionValues += (string(gcvt(((FGNozzle*)Thrusters[i])->GetThrust(), 10, buff)));
447 case FGThruster::ttRotor:
449 case FGThruster::ttPropeller:
450 FGPropeller* Propeller = (FGPropeller*)Thrusters[i];
451 FGColumnVector3 vPFactor = Propeller->GetPFactor();
452 PropulsionValues += string(gcvt(Propeller->GetTorque(), 10, buff)) + ", ";
453 PropulsionValues += string(gcvt(vPFactor(eRoll), 10, buff)) + ", ";
454 PropulsionValues += string(gcvt(vPFactor(ePitch), 10, buff)) + ", ";
455 PropulsionValues += string(gcvt(vPFactor(eYaw), 10, buff)) + ", ";
456 PropulsionValues += string(gcvt(Propeller->GetThrust(), 10, buff)) + ", ";
457 if (Propeller->IsVPitch())
458 PropulsionValues += string(gcvt(Propeller->GetPitch(), 10, buff)) + ", ";
459 PropulsionValues += string(gcvt(Propeller->GetRPM(), 10, buff));
464 return PropulsionValues;
467 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
469 FGColumnVector3& FGPropulsion::GetTanksMoment(void)
471 iTank = Tanks.begin();
472 vXYZtank.InitMatrix();
473 while (iTank < Tanks.end()) {
474 vXYZtank(eX) += (*iTank)->GetX()*(*iTank)->GetContents();
475 vXYZtank(eY) += (*iTank)->GetY()*(*iTank)->GetContents();
476 vXYZtank(eZ) += (*iTank)->GetZ()*(*iTank)->GetContents();
482 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
484 double FGPropulsion::GetTanksWeight(void)
488 iTank = Tanks.begin();
489 while (iTank < Tanks.end()) {
490 Tw += (*iTank)->GetContents();
496 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
498 double FGPropulsion::GetTanksIxx(const FGColumnVector3& vXYZcg)
501 iTank = Tanks.begin();
502 while (iTank < Tanks.end()) {
503 I += ((*iTank)->GetX() - vXYZcg(eX))*((*iTank)->GetX() - vXYZcg(eX)) * (*iTank)->GetContents()/(144.0*Inertial->gravity());
509 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
511 double FGPropulsion::GetTanksIyy(const FGColumnVector3& vXYZcg)
514 iTank = Tanks.begin();
515 while (iTank < Tanks.end()) {
516 I += ((*iTank)->GetY() - vXYZcg(eY))*((*iTank)->GetY() - vXYZcg(eY)) * (*iTank)->GetContents()/(144.0*Inertial->gravity());
522 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
524 double FGPropulsion::GetTanksIzz(const FGColumnVector3& vXYZcg)
527 iTank = Tanks.begin();
528 while (iTank < Tanks.end()) {
529 I += ((*iTank)->GetZ() - vXYZcg(eZ))*((*iTank)->GetZ() - vXYZcg(eZ)) * (*iTank)->GetContents()/(144.0*Inertial->gravity());
535 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
537 double FGPropulsion::GetTanksIxz(const FGColumnVector3& vXYZcg)
540 iTank = Tanks.begin();
541 while (iTank < Tanks.end()) {
542 I += ((*iTank)->GetX() - vXYZcg(eX))*((*iTank)->GetZ() - vXYZcg(eZ)) * (*iTank)->GetContents()/(144.0*Inertial->gravity());
548 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
550 double FGPropulsion::GetTanksIxy(const FGColumnVector3& vXYZcg)
553 iTank = Tanks.begin();
554 while (iTank != Tanks.end()) {
555 I += ((*iTank)->GetX() - vXYZcg(eX))*((*iTank)->GetY() - vXYZcg(eY)) * (*iTank)->GetContents()/(144.0*Inertial->gravity());
561 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
563 void FGPropulsion::bind(void)
565 typedef double (FGPropulsion::*PMF)(int) const;
566 /* PropertyManager->Tie("propulsion/num-engines", this,
567 &FGPropulsion::GetNumEngines);
568 PropertyManager->Tie("propulsion/num-tanks", this,
569 &FGPropulsion::GetNumTanks); */
570 PropertyManager->Tie("propulsion/num-sel-fuel-tanks", this,
571 &FGPropulsion::GetnumSelectedFuelTanks);
572 PropertyManager->Tie("propulsion/num-sel-ox-tanks", this,
573 &FGPropulsion::GetnumSelectedOxiTanks);
574 PropertyManager->Tie("forces/fbx-prop-lbs", this,1,
575 (PMF)&FGPropulsion::GetForces);
576 PropertyManager->Tie("forces/fby-prop-lbs", this,2,
577 (PMF)&FGPropulsion::GetForces);
578 PropertyManager->Tie("forces/fbz-prop-lbs", this,3,
579 (PMF)&FGPropulsion::GetForces);
580 PropertyManager->Tie("moments/l-prop-lbsft", this,1,
581 (PMF)&FGPropulsion::GetMoments);
582 PropertyManager->Tie("moments/m-prop-lbsft", this,2,
583 (PMF)&FGPropulsion::GetMoments);
584 PropertyManager->Tie("moments/n-prop-lbsft", this,3,
585 (PMF)&FGPropulsion::GetMoments);
586 //PropertyManager->Tie("propulsion/tanks-weight-lbs", this,
587 // &FGPropulsion::GetTanksWeight);
590 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
592 void FGPropulsion::unbind(void)
594 /* PropertyManager->Untie("propulsion/num-engines");
595 PropertyManager->Untie("propulsion/num-tanks"); */
596 PropertyManager->Untie("propulsion/num-sel-fuel-tanks");
597 PropertyManager->Untie("propulsion/num-sel-ox-tanks");
598 PropertyManager->Untie("forces/fbx-prop-lbs");
599 PropertyManager->Untie("forces/fby-prop-lbs");
600 PropertyManager->Untie("forces/fbz-prop-lbs");
601 PropertyManager->Untie("moments/l-prop-lbsft");
602 PropertyManager->Untie("moments/m-prop-lbsft");
603 PropertyManager->Untie("moments/n-prop-lbsft");
604 //PropertyManager->Untie("propulsion/tanks-weight-lbs");
607 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
608 // The bitmasked value choices are as follows:
609 // unset: In this case (the default) JSBSim would only print
610 // out the normally expected messages, essentially echoing
611 // the config files as they are read. If the environment
612 // variable is not set, debug_lvl is set to 1 internally
613 // 0: This requests JSBSim not to output any messages
615 // 1: This value explicity requests the normal JSBSim
617 // 2: This value asks for a message to be printed out when
618 // a class is instantiated
619 // 4: When this value is set, a message is displayed when a
620 // FGModel object executes its Run() method
621 // 8: When this value is set, various runtime state variables
622 // are printed out periodically
623 // 16: When set various parameters are sanity checked and
624 // a message is printed out when they go out of bounds
626 void FGPropulsion::Debug(int from)
628 if (debug_lvl <= 0) return;
630 if (debug_lvl & 1) { // Standard console startup message output
631 if (from == 0) { // Constructor
635 if (debug_lvl & 2 ) { // Instantiation/Destruction notification
636 if (from == 0) cout << "Instantiated: FGPropulsion" << endl;
637 if (from == 1) cout << "Destroyed: FGPropulsion" << endl;
639 if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
641 if (debug_lvl & 8 ) { // Runtime state variables
643 if (debug_lvl & 16) { // Sanity checking
645 if (debug_lvl & 64) {
646 if (from == 0) { // Constructor
647 cout << IdSrc << endl;
648 cout << IdHdr << endl;