]> git.mxchange.org Git - flightgear.git/blob - src/FDM/JSBSim/FGPropulsion.cpp
Latest JSBSim changes.
[flightgear.git] / src / FDM / JSBSim / FGPropulsion.cpp
1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2
3  Module:       FGPropulsion.cpp
4  Author:       Jon S. Berndt
5  Date started: 08/20/00
6  Purpose:      Encapsulates the set of engines, tanks, and thrusters associated
7                with this aircraft
8
9  ------------- Copyright (C) 2000  Jon S. Berndt (jsb@hal-pc.org) -------------
10
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
14  version.
15
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
19  details.
20
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.
24
25  Further information about the GNU General Public License can also be found on
26  the world wide web at http://www.gnu.org.
27
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:
35
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.
39
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.
46
47 HISTORY
48 --------------------------------------------------------------------------------
49 08/20/00   JSB   Created
50
51 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
52 INCLUDES
53 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
54
55 #include "FGPropulsion.h"
56
57 static const char *IdSrc = "$Id$";
58 static const char *IdHdr = ID_PROPULSION;
59
60 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
61 CLASS IMPLEMENTATION
62 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
63
64 FGPropulsion::FGPropulsion(FGFDMExec* exec) : FGModel(exec)
65 {
66   Name = "FGPropulsion";
67   numSelectedFuelTanks = numSelectedOxiTanks = 0;
68   numTanks = numEngines = numThrusters = 0;
69   numOxiTanks = numFuelTanks = 0;
70
71   Debug(0);
72 }
73
74 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
75
76 FGPropulsion::~FGPropulsion()
77 {
78   for (unsigned int i=0; i<Engines.size(); i++) delete Engines[i];
79   Engines.clear();
80   Debug(1);
81 }
82
83 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
84
85 bool FGPropulsion::Run(void)
86 {
87   double PowerAvailable;
88   dt = State->Getdt();
89
90   vForces.InitMatrix();
91   vMoments.InitMatrix();
92
93   if (!FGModel::Run()) {
94     for (unsigned int i=0; i<numEngines; i++) {
95       Thrusters[i]->SetdeltaT(dt*rate);
96       PowerAvailable = Engines[i]->Calculate(Thrusters[i]->GetPowerRequired());
97       Thrusters[i]->Calculate(PowerAvailable);
98       vForces  += Thrusters[i]->GetBodyForces();  // sum body frame forces
99       vMoments += Thrusters[i]->GetMoments();     // sum body frame moments
100     }
101     return false;
102   } else {
103     return true;
104   }
105 }
106
107 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
108
109 bool FGPropulsion::GetSteadyState(void)
110 {
111   double PowerAvailable;
112   double currentThrust = 0, lastThrust=-1;
113   dt = State->Getdt();
114   int steady_count,j=0;
115   bool steady=false;
116
117   vForces.InitMatrix();
118   vMoments.InitMatrix();
119
120   if (!FGModel::Run()) {
121     for (unsigned int i=0; i<numEngines; i++) {
122       Engines[i]->SetTrimMode(true);
123       Thrusters[i]->SetdeltaT(dt*rate);
124       steady=false;
125       steady_count=0;
126       while (!steady && j < 6000) {
127         PowerAvailable = Engines[i]->Calculate(Thrusters[i]->GetPowerRequired());
128         lastThrust = currentThrust;
129         currentThrust = Thrusters[i]->Calculate(PowerAvailable);
130         if(fabs(lastThrust-currentThrust) < 0.0001) {
131           steady_count++;
132           if(steady_count > 120) { steady=true; }
133         } else {
134           steady_count=0;
135         }
136         j++;    
137       }
138       vForces  += Thrusters[i]->GetBodyForces();  // sum body frame forces
139       vMoments += Thrusters[i]->GetMoments();     // sum body frame moments
140       Engines[i]->SetTrimMode(false);
141     }
142
143     return false;
144   } else {
145     return true;
146   }
147 }
148
149 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
150
151 bool FGPropulsion::ICEngineStart(void)
152 {
153   double PowerAvailable;
154   int j;
155   dt = State->Getdt();
156
157   vForces.InitMatrix();
158   vMoments.InitMatrix();
159     
160   for (unsigned int i=0; i<numEngines; i++) {
161     Engines[i]->SetTrimMode(true);
162     Thrusters[i]->SetdeltaT(dt*rate);
163     j=0;
164     while (!Engines[i]->GetRunning() && j < 2000) {
165       PowerAvailable = Engines[i]->Calculate(Thrusters[i]->GetPowerRequired());
166       Thrusters[i]->Calculate(PowerAvailable);
167       j++;    
168     }
169     vForces  += Thrusters[i]->GetBodyForces();  // sum body frame forces
170     vMoments += Thrusters[i]->GetMoments();     // sum body frame moments
171     Engines[i]->SetTrimMode(false);
172   }
173   return true;
174 }
175
176 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
177
178 bool FGPropulsion::Load(FGConfigFile* AC_cfg)
179 {
180   string token, fullpath;
181   string engineFileName, engType;
182   string thrusterFileName, thrType;
183   string parameter;
184   string enginePath = FDMExec->GetEnginePath();
185   double xLoc, yLoc, zLoc, Pitch, Yaw;
186   double P_Factor = 0, Sense = 0.0;
187   int Feed;
188   bool ThrottleAdded = false;
189
190 # ifndef macintosh
191       fullpath = enginePath + "/";
192 # else
193       fullpath = enginePath + ";";
194 # endif
195
196   AC_cfg->GetNextConfigLine();
197
198   while ((token = AC_cfg->GetValue()) != string("/PROPULSION")) {
199
200     if (token == "AC_ENGINE") {                   // ============ READING ENGINES
201
202       engineFileName = AC_cfg->GetValue("FILE");
203
204       if (debug_lvl > 0) cout << "\n    Reading engine from file: " << fullpath
205                                                 + engineFileName + ".xml"<< endl;
206       FGConfigFile Eng_cfg(fullpath + engineFileName + ".xml");
207
208       if (Eng_cfg.IsOpen()) {
209         Eng_cfg.GetNextConfigLine();
210         engType = Eng_cfg.GetValue();
211
212         FCS->AddThrottle();
213         ThrottleAdded = true;
214
215         if (engType == "FG_ROCKET") {
216           Engines.push_back(new FGRocket(FDMExec, &Eng_cfg));
217         } else if (engType == "FG_PISTON") {
218           Engines.push_back(new FGPiston(FDMExec, &Eng_cfg));
219         } else if (engType == "FG_TURBOJET") {
220           Engines.push_back(new FGTurboJet(FDMExec, &Eng_cfg));
221         } else if (engType == "FG_TURBOSHAFT") {
222           Engines.push_back(new FGTurboShaft(FDMExec, &Eng_cfg));
223         } else if (engType == "FG_TURBOPROP") {
224           Engines.push_back(new FGTurboProp(FDMExec, &Eng_cfg));
225         } else {
226           cerr << fgred << "    Unrecognized engine type: " << underon << engType
227                     << underoff << " found in config file." << fgdef << endl;
228           return false;
229         }
230
231         AC_cfg->GetNextConfigLine();
232         while ((token = AC_cfg->GetValue()) != string("/AC_ENGINE")) {
233           *AC_cfg >> token;
234           if      (token == "XLOC")  { *AC_cfg >> xLoc; }
235           else if (token == "YLOC")  { *AC_cfg >> yLoc; }
236           else if (token == "ZLOC")  { *AC_cfg >> zLoc; }
237           else if (token == "PITCH") { *AC_cfg >> Pitch;}
238           else if (token == "YAW")   { *AC_cfg >> Yaw;}
239           else if (token == "FEED")  {
240             *AC_cfg >> Feed;
241             Engines[numEngines]->AddFeedTank(Feed);
242             if (debug_lvl > 0) cout << "      Feed tank: " << Feed << endl;
243           } else cerr << "Unknown identifier: " << token << " in engine file: "
244                                                         << engineFileName << endl;
245         }
246
247         if (debug_lvl > 0)  {
248           cout << "      X = " << xLoc << endl;
249           cout << "      Y = " << yLoc << endl;
250           cout << "      Z = " << zLoc << endl;
251           cout << "      Pitch = " << Pitch << endl;
252           cout << "      Yaw = " << Yaw << endl;
253         }
254
255         Engines[numEngines]->SetPlacement(xLoc, yLoc, zLoc, Pitch, Yaw);
256         Engines[numEngines]->SetEngineNumber(numEngines);
257         numEngines++;
258
259       } else {
260
261         cerr << fgred << "\n  Could not read engine config file: " << underon <<
262                     fullpath + engineFileName + ".xml" << underoff << fgdef << endl;
263         return false;
264       }
265
266     } else if (token == "AC_TANK") {              // ============== READING TANKS
267
268       if (debug_lvl > 0) cout << "\n    Reading tank definition" << endl;
269       Tanks.push_back(new FGTank(AC_cfg));
270       switch(Tanks[numTanks]->GetType()) {
271       case FGTank::ttFUEL:
272         numSelectedFuelTanks++;
273         numFuelTanks++;
274         break;
275       case FGTank::ttOXIDIZER:
276         numSelectedOxiTanks++;
277         numOxiTanks++;
278         break;
279       }
280
281       numTanks++;
282
283     } else if (token == "AC_THRUSTER") {          // ========== READING THRUSTERS
284
285       thrusterFileName = AC_cfg->GetValue("FILE");
286
287       if (debug_lvl > 0) cout << "\n    Reading thruster from file: " <<
288                                     fullpath + thrusterFileName + ".xml" << endl;
289       FGConfigFile Thruster_cfg(fullpath + thrusterFileName + ".xml");
290
291       if (Thruster_cfg.IsOpen()) {
292         Thruster_cfg.GetNextConfigLine();
293         thrType = Thruster_cfg.GetValue();
294
295         if (thrType == "FG_PROPELLER") {
296           Thrusters.push_back(new FGPropeller(FDMExec, &Thruster_cfg));
297         } else if (thrType == "FG_NOZZLE") {
298           Thrusters.push_back(new FGNozzle(FDMExec, &Thruster_cfg));
299         }
300
301         AC_cfg->GetNextConfigLine();
302         while ((token = AC_cfg->GetValue()) != string("/AC_THRUSTER")) {
303           *AC_cfg >> token;
304           if (token == "XLOC") *AC_cfg >> xLoc;
305           else if (token == "YLOC") *AC_cfg >> yLoc;
306           else if (token == "ZLOC") *AC_cfg >> zLoc;
307           else if (token == "PITCH") *AC_cfg >> Pitch;
308           else if (token == "YAW") *AC_cfg >> Yaw;
309           else if (token == "P_FACTOR") *AC_cfg >> P_Factor;
310           else if (token == "SENSE")   *AC_cfg >> Sense;
311           else cerr << "Unknown identifier: " << token << " in engine file: "
312                                                         << engineFileName << endl;
313         }
314
315         Thrusters[numThrusters]->SetLocation(xLoc, yLoc, zLoc);
316         Thrusters[numThrusters]->SetAnglesToBody(0, Pitch, Yaw);
317         if (thrType == "FG_PROPELLER" && P_Factor > 0.001) {
318           ((FGPropeller*)Thrusters[numThrusters])->SetPFactor(P_Factor);
319           if (debug_lvl > 0) cout << "      P-Factor: " << P_Factor << endl;
320           ((FGPropeller*)Thrusters[numThrusters])->SetSense(Sense);
321           if (debug_lvl > 0) cout << "      Sense: " << Sense <<  endl;
322         }
323         Thrusters[numThrusters]->SetdeltaT(dt*rate);
324         Thrusters[numThrusters]->SetThrusterNumber(numThrusters);
325         numThrusters++;
326
327       } else {
328         cerr << "Could not read thruster config file: " << fullpath
329                                                 + thrusterFileName + ".xml" << endl;
330         return false;
331       }
332
333     }
334     AC_cfg->GetNextConfigLine();
335   }
336
337   if (!ThrottleAdded) FCS->AddThrottle(); // need to have at least one throttle
338
339   return true;
340 }
341
342 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
343
344 string FGPropulsion::GetPropulsionStrings(void)
345 {
346   string PropulsionStrings = "";
347   bool firstime = true;
348   char buffer[5];
349
350   for (unsigned int i=0;i<Engines.size();i++) {
351     if (firstime)  firstime = false;
352     else           PropulsionStrings += ", ";
353
354     sprintf(buffer, "%d", i);
355
356     switch(Engines[i]->GetType()) {
357     case FGEngine::etPiston:
358       PropulsionStrings += (Engines[i]->GetName() + "_PwrAvail[" + buffer + "]");
359       break;
360     case FGEngine::etRocket:
361       PropulsionStrings += (Engines[i]->GetName() + "_ChamberPress[" + buffer + "]");
362       break;
363     case FGEngine::etTurboJet:
364     case FGEngine::etTurboProp:
365     case FGEngine::etTurboShaft:
366       break;
367     default:
368       PropulsionStrings += "INVALID ENGINE TYPE";
369       break;
370     }
371
372     PropulsionStrings += ", ";
373
374     FGPropeller* Propeller = (FGPropeller*)Thrusters[i];
375     switch(Thrusters[i]->GetType()) {
376     case FGThruster::ttNozzle:
377       PropulsionStrings += (Thrusters[i]->GetName() + "_Thrust[" + buffer + "]");
378       break;
379     case FGThruster::ttRotor:
380       break;
381     case FGThruster::ttPropeller:
382       PropulsionStrings += (Thrusters[i]->GetName() + "_Torque[" + buffer + "], ");
383       PropulsionStrings += (Thrusters[i]->GetName() + "_PFactor_Roll[" + buffer + "], ");
384       PropulsionStrings += (Thrusters[i]->GetName() + "_PFactor_Pitch[" + buffer + "], ");
385       PropulsionStrings += (Thrusters[i]->GetName() + "_PFactor_Yaw[" + buffer + "], ");
386       PropulsionStrings += (Thrusters[i]->GetName() + "_Thrust[" + buffer + "], ");
387       if (Propeller->IsVPitch())
388         PropulsionStrings += (Thrusters[i]->GetName() + "_Pitch[" + buffer + "], ");
389       PropulsionStrings += (Thrusters[i]->GetName() + "_RPM[" + buffer + "]");
390       break;
391     default:
392       PropulsionStrings += "INVALID THRUSTER TYPE";
393       break;
394     }    
395   }
396
397   return PropulsionStrings;
398 }
399
400 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
401
402 string FGPropulsion::GetPropulsionValues(void)
403 {
404   char buff[20];
405   string PropulsionValues = "";
406   bool firstime = true;
407
408   for (unsigned int i=0;i<Engines.size();i++) {
409     if (firstime)  firstime = false;
410     else           PropulsionValues += ", ";
411
412     switch(Engines[i]->GetType()) {
413     case FGEngine::etPiston:
414       PropulsionValues += (string(gcvt(((FGPiston*)Engines[i])->GetPowerAvailable(), 10, buff)));
415       break;
416     case FGEngine::etRocket:
417       PropulsionValues += (string(gcvt(((FGRocket*)Engines[i])->GetChamberPressure(), 10, buff)));
418       break;
419     case FGEngine::etTurboJet:
420     case FGEngine::etTurboProp:
421     case FGEngine::etTurboShaft:
422       break;
423     }
424
425     PropulsionValues += ", ";
426
427     switch(Thrusters[i]->GetType()) {
428     case FGThruster::ttNozzle:
429       PropulsionValues += (string(gcvt(((FGNozzle*)Thrusters[i])->GetThrust(), 10, buff)));
430       break;
431     case FGThruster::ttRotor:
432       break;
433     case FGThruster::ttPropeller:
434       FGPropeller* Propeller = (FGPropeller*)Thrusters[i];
435       FGColumnVector3 vPFactor = Propeller->GetPFactor();
436       PropulsionValues += string(gcvt(Propeller->GetTorque(), 10, buff)) + ", ";
437       PropulsionValues += string(gcvt(vPFactor(eRoll), 10, buff)) + ", ";
438       PropulsionValues += string(gcvt(vPFactor(ePitch), 10, buff)) + ", ";
439       PropulsionValues += string(gcvt(vPFactor(eYaw), 10, buff)) + ", ";
440       PropulsionValues += string(gcvt(Propeller->GetThrust(), 10, buff)) + ", ";
441       if (Propeller->IsVPitch())
442         PropulsionValues += string(gcvt(Propeller->GetPitch(), 10, buff)) + ", ";
443       PropulsionValues += string(gcvt(Propeller->GetRPM(), 10, buff));
444       break;
445     }
446   }
447
448   return PropulsionValues;
449 }
450
451 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
452
453 FGColumnVector3& FGPropulsion::GetTanksCG(void)
454 {
455   iTank = Tanks.begin();
456   vXYZtank.InitMatrix();
457   while (iTank < Tanks.end()) {
458     vXYZtank(eX) += (*iTank)->GetX()*(*iTank)->GetContents();
459     vXYZtank(eY) += (*iTank)->GetY()*(*iTank)->GetContents();
460     vXYZtank(eZ) += (*iTank)->GetZ()*(*iTank)->GetContents();
461     iTank++;
462   }
463   return vXYZtank;
464 }
465
466 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
467
468 double FGPropulsion::GetTanksWeight(void)
469 {
470   double Tw = 0.0;
471
472   iTank = Tanks.begin();
473   while (iTank < Tanks.end()) {
474     Tw += (*iTank)->GetContents();
475     iTank++;
476   }
477   return Tw;
478 }
479
480 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
481
482 double FGPropulsion::GetTanksIxx(const FGColumnVector3& vXYZcg)
483 {
484   double I = 0.0;
485   iTank = Tanks.begin();
486   while (iTank < Tanks.end()) {
487     I += ((*iTank)->GetX() - vXYZcg(eX))*((*iTank)->GetX() - vXYZcg(eX)) * (*iTank)->GetContents()/(144.0*Inertial->gravity());
488     iTank++;
489   }
490   return I;
491 }
492
493 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
494
495 double FGPropulsion::GetTanksIyy(const FGColumnVector3& vXYZcg)
496 {
497   double I = 0.0;
498   iTank = Tanks.begin();
499   while (iTank < Tanks.end()) {
500     I += ((*iTank)->GetY() - vXYZcg(eY))*((*iTank)->GetY() - vXYZcg(eY)) * (*iTank)->GetContents()/(144.0*Inertial->gravity());
501     iTank++;
502   }
503   return I;
504 }
505
506 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
507
508 double FGPropulsion::GetTanksIzz(const FGColumnVector3& vXYZcg)
509 {
510   double I = 0.0;
511   iTank = Tanks.begin();
512   while (iTank < Tanks.end()) {
513     I += ((*iTank)->GetZ() - vXYZcg(eZ))*((*iTank)->GetZ() - vXYZcg(eZ)) * (*iTank)->GetContents()/(144.0*Inertial->gravity());
514     iTank++;
515   }
516   return I;
517 }
518
519 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
520
521 double FGPropulsion::GetTanksIxz(const FGColumnVector3& vXYZcg)
522 {
523   double I = 0.0;
524   iTank = Tanks.begin();
525   while (iTank < Tanks.end()) {
526     I += ((*iTank)->GetX() - vXYZcg(eX))*((*iTank)->GetZ() - vXYZcg(eZ)) * (*iTank)->GetContents()/(144.0*Inertial->gravity());
527     iTank++;
528   }
529   return I;
530 }
531
532 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
533
534 double FGPropulsion::GetTanksIxy(const FGColumnVector3& vXYZcg)
535 {
536   double I = 0.0;
537   iTank = Tanks.begin();
538   while (iTank != Tanks.end()) {
539     I += ((*iTank)->GetX() - vXYZcg(eX))*((*iTank)->GetY() - vXYZcg(eY)) * (*iTank)->GetContents()/(144.0*Inertial->gravity());
540     iTank++;
541   }
542   return I;
543 }
544
545 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
546 //    The bitmasked value choices are as follows:
547 //    unset: In this case (the default) JSBSim would only print
548 //       out the normally expected messages, essentially echoing
549 //       the config files as they are read. If the environment
550 //       variable is not set, debug_lvl is set to 1 internally
551 //    0: This requests JSBSim not to output any messages
552 //       whatsoever.
553 //    1: This value explicity requests the normal JSBSim
554 //       startup messages
555 //    2: This value asks for a message to be printed out when
556 //       a class is instantiated
557 //    4: When this value is set, a message is displayed when a
558 //       FGModel object executes its Run() method
559 //    8: When this value is set, various runtime state variables
560 //       are printed out periodically
561 //    16: When set various parameters are sanity checked and
562 //       a message is printed out when they go out of bounds
563
564 void FGPropulsion::Debug(int from)
565 {
566   if (debug_lvl <= 0) return;
567
568   if (debug_lvl & 1) { // Standard console startup message output
569     if (from == 0) { // Constructor
570
571     }
572   }
573   if (debug_lvl & 2 ) { // Instantiation/Destruction notification
574     if (from == 0) cout << "Instantiated: FGPropulsion" << endl;
575     if (from == 1) cout << "Destroyed:    FGPropulsion" << endl;
576   }
577   if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
578   }
579   if (debug_lvl & 8 ) { // Runtime state variables
580   }
581   if (debug_lvl & 16) { // Sanity checking
582   }
583 }
584