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"
57 #include "FGSimTurbine.h"
58 #include "FGTurbine.h"
59 #include "FGPropeller.h"
62 #include "FGPropertyManager.h"
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);
75 static const char *IdSrc = "$Id$";
76 static const char *IdHdr = ID_PROPULSION;
78 extern short debug_lvl;
81 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
83 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
85 FGPropulsion::FGPropulsion(FGFDMExec* exec) : FGModel(exec)
87 Name = "FGPropulsion";
89 numSelectedFuelTanks = numSelectedOxiTanks = 0;
90 numTanks = numEngines = numThrusters = 0;
91 numOxiTanks = numFuelTanks = 0;
93 ActiveEngine = -1; // -1: ALL, 0: Engine 1, 1: Engine 2 ...
101 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
103 FGPropulsion::~FGPropulsion()
105 for (unsigned int i=0; i<Engines.size(); i++) delete Engines[i];
111 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
113 bool FGPropulsion::Run(void)
115 double PowerAvailable;
118 vForces.InitMatrix();
119 vMoments.InitMatrix();
121 if (!FGModel::Run()) {
122 for (unsigned int i=0; i<numEngines; i++) {
123 Thrusters[i]->SetdeltaT(dt*rate);
124 PowerAvailable = Engines[i]->Calculate(Thrusters[i]->GetPowerRequired());
125 Thrusters[i]->Calculate(PowerAvailable);
126 vForces += Thrusters[i]->GetBodyForces(); // sum body frame forces
127 vMoments += Thrusters[i]->GetMoments(); // sum body frame moments
136 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
138 bool FGPropulsion::GetSteadyState(void)
140 double PowerAvailable;
141 double currentThrust = 0, lastThrust=-1;
143 int steady_count,j=0;
146 vForces.InitMatrix();
147 vMoments.InitMatrix();
149 if (!FGModel::Run()) {
150 for (unsigned int i=0; i<numEngines; i++) {
151 Engines[i]->SetTrimMode(true);
152 Thrusters[i]->SetdeltaT(dt*rate);
155 while (!steady && j < 6000) {
156 PowerAvailable = Engines[i]->Calculate(Thrusters[i]->GetPowerRequired());
157 lastThrust = currentThrust;
158 currentThrust = Thrusters[i]->Calculate(PowerAvailable);
159 if (fabs(lastThrust-currentThrust) < 0.0001) {
161 if (steady_count > 120) { steady=true; }
167 vForces += Thrusters[i]->GetBodyForces(); // sum body frame forces
168 vMoments += Thrusters[i]->GetMoments(); // sum body frame moments
169 Engines[i]->SetTrimMode(false);
178 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
180 bool FGPropulsion::ICEngineStart(void)
182 double PowerAvailable;
186 vForces.InitMatrix();
187 vMoments.InitMatrix();
189 for (unsigned int i=0; i<numEngines; i++) {
190 Engines[i]->SetTrimMode(true);
191 Thrusters[i]->SetdeltaT(dt*rate);
193 while (!Engines[i]->GetRunning() && j < 2000) {
194 PowerAvailable = Engines[i]->Calculate(Thrusters[i]->GetPowerRequired());
195 Thrusters[i]->Calculate(PowerAvailable);
198 vForces += Thrusters[i]->GetBodyForces(); // sum body frame forces
199 vMoments += Thrusters[i]->GetMoments(); // sum body frame moments
200 Engines[i]->SetTrimMode(false);
205 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
207 bool FGPropulsion::Load(FGConfigFile* AC_cfg)
209 string token, fullpath;
210 string engineFileName, engType;
211 string thrusterFileName, thrType;
213 string enginePath = FDMExec->GetEnginePath();
214 double xLoc, yLoc, zLoc, Pitch, Yaw;
215 double P_Factor = 0, Sense = 0.0;
217 bool ThrottleAdded = false;
220 fullpath = enginePath + "/";
222 fullpath = enginePath + ";";
225 AC_cfg->GetNextConfigLine();
227 while ((token = AC_cfg->GetValue()) != string("/PROPULSION")) {
229 if (token == "AC_ENGINE") { // ============ READING ENGINES
231 engineFileName = AC_cfg->GetValue("FILE");
233 if (debug_lvl > 0) cout << "\n Reading engine from file: " << fullpath
234 + engineFileName + ".xml"<< endl;
235 FGConfigFile Eng_cfg(fullpath + engineFileName + ".xml");
237 if (Eng_cfg.IsOpen()) {
238 Eng_cfg.GetNextConfigLine();
239 engType = Eng_cfg.GetValue();
242 ThrottleAdded = true;
244 if (engType == "FG_ROCKET") {
245 Engines.push_back(new FGRocket(FDMExec, &Eng_cfg));
246 } else if (engType == "FG_PISTON") {
247 Engines.push_back(new FGPiston(FDMExec, &Eng_cfg));
248 } else if (engType == "FG_TURBINE") {
249 Engines.push_back(new FGTurbine(FDMExec, &Eng_cfg));
250 } else if (engType == "FG_SIMTURBINE") {
251 Engines.push_back(new FGSimTurbine(FDMExec, &Eng_cfg));
253 cerr << fgred << " Unrecognized engine type: " << underon << engType
254 << underoff << " found in config file." << fgdef << endl;
258 AC_cfg->GetNextConfigLine();
259 while ((token = AC_cfg->GetValue()) != string("/AC_ENGINE")) {
261 if (token == "XLOC") { *AC_cfg >> xLoc; }
262 else if (token == "YLOC") { *AC_cfg >> yLoc; }
263 else if (token == "ZLOC") { *AC_cfg >> zLoc; }
264 else if (token == "PITCH") { *AC_cfg >> Pitch;}
265 else if (token == "YAW") { *AC_cfg >> Yaw;}
266 else if (token == "FEED") {
268 Engines[numEngines]->AddFeedTank(Feed);
269 if (debug_lvl > 0) cout << " Feed tank: " << Feed << endl;
270 } else cerr << "Unknown identifier: " << token << " in engine file: "
271 << engineFileName << endl;
275 cout << " X = " << xLoc << endl;
276 cout << " Y = " << yLoc << endl;
277 cout << " Z = " << zLoc << endl;
278 cout << " Pitch = " << Pitch << endl;
279 cout << " Yaw = " << Yaw << endl;
282 Engines[numEngines]->SetPlacement(xLoc, yLoc, zLoc, Pitch, Yaw);
283 Engines[numEngines]->SetEngineNumber(numEngines);
288 cerr << fgred << "\n Could not read engine config file: " << underon <<
289 fullpath + engineFileName + ".xml" << underoff << fgdef << endl;
293 } else if (token == "AC_TANK") { // ============== READING TANKS
295 if (debug_lvl > 0) cout << "\n Reading tank definition" << endl;
296 Tanks.push_back(new FGTank(AC_cfg));
297 switch(Tanks[numTanks]->GetType()) {
299 numSelectedFuelTanks++;
302 case FGTank::ttOXIDIZER:
303 numSelectedOxiTanks++;
310 } else if (token == "AC_THRUSTER") { // ========== READING THRUSTERS
312 thrusterFileName = AC_cfg->GetValue("FILE");
314 if (debug_lvl > 0) cout << "\n Reading thruster from file: " <<
315 fullpath + thrusterFileName + ".xml" << endl;
316 FGConfigFile Thruster_cfg(fullpath + thrusterFileName + ".xml");
318 if (Thruster_cfg.IsOpen()) {
319 Thruster_cfg.GetNextConfigLine();
320 thrType = Thruster_cfg.GetValue();
322 if (thrType == "FG_PROPELLER") {
323 Thrusters.push_back(new FGPropeller(FDMExec, &Thruster_cfg));
324 } else if (thrType == "FG_NOZZLE") {
325 Thrusters.push_back(new FGNozzle(FDMExec, &Thruster_cfg ));
326 } else if (thrType == "FG_DIRECT") {
327 Thrusters.push_back(new FGThruster( FDMExec, &Thruster_cfg) );
330 AC_cfg->GetNextConfigLine();
331 while ((token = AC_cfg->GetValue()) != string("/AC_THRUSTER")) {
333 if (token == "XLOC") *AC_cfg >> xLoc;
334 else if (token == "YLOC") *AC_cfg >> yLoc;
335 else if (token == "ZLOC") *AC_cfg >> zLoc;
336 else if (token == "PITCH") *AC_cfg >> Pitch;
337 else if (token == "YAW") *AC_cfg >> Yaw;
338 else if (token == "P_FACTOR") *AC_cfg >> P_Factor;
339 else if (token == "SENSE") *AC_cfg >> Sense;
340 else cerr << "Unknown identifier: " << token << " in engine file: "
341 << engineFileName << endl;
344 Thrusters[numThrusters]->SetLocation(xLoc, yLoc, zLoc);
345 Thrusters[numThrusters]->SetAnglesToBody(0, Pitch, Yaw);
346 if (thrType == "FG_PROPELLER" && P_Factor > 0.001) {
347 ((FGPropeller*)Thrusters[numThrusters])->SetPFactor(P_Factor);
348 if (debug_lvl > 0) cout << " P-Factor: " << P_Factor << endl;
349 ((FGPropeller*)Thrusters[numThrusters])->SetSense(fabs(Sense)/Sense);
350 if (debug_lvl > 0) cout << " Sense: " << Sense << endl;
352 Thrusters[numThrusters]->SetdeltaT(dt*rate);
353 Thrusters[numThrusters]->SetThrusterNumber(numThrusters);
357 cerr << "Could not read thruster config file: " << fullpath
358 + thrusterFileName + ".xml" << endl;
363 AC_cfg->GetNextConfigLine();
366 CalculateTankInertias();
367 if (!ThrottleAdded) FCS->AddThrottle(); // need to have at least one throttle
372 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
374 string FGPropulsion::GetPropulsionStrings(void)
376 string PropulsionStrings = "";
377 bool firstime = true;
380 for (unsigned int i=0;i<Engines.size();i++) {
381 if (firstime) firstime = false;
382 else PropulsionStrings += ", ";
384 sprintf(buffer, "%d", i);
386 switch(Engines[i]->GetType()) {
387 case FGEngine::etPiston:
388 PropulsionStrings += (Engines[i]->GetName() + "_PwrAvail[" + buffer + "]");
390 case FGEngine::etRocket:
391 PropulsionStrings += (Engines[i]->GetName() + "_ChamberPress[" + buffer + "]");
393 case FGEngine::etTurbine:
395 case FGEngine::etSimTurbine:
396 PropulsionStrings += (Engines[i]->GetName() + "_N1[" + buffer + "], ");
397 PropulsionStrings += (Engines[i]->GetName() + "_N2[" + buffer + "]");
400 PropulsionStrings += "INVALID ENGINE TYPE";
404 PropulsionStrings += ", ";
406 FGPropeller* Propeller = (FGPropeller*)Thrusters[i];
407 switch(Thrusters[i]->GetType()) {
408 case FGThruster::ttNozzle:
409 PropulsionStrings += (Thrusters[i]->GetName() + "_Thrust[" + buffer + "]");
411 case FGThruster::ttRotor:
413 case FGThruster::ttPropeller:
414 PropulsionStrings += (Thrusters[i]->GetName() + "_Torque[" + buffer + "], ");
415 PropulsionStrings += (Thrusters[i]->GetName() + "_PFactor_Roll[" + buffer + "], ");
416 PropulsionStrings += (Thrusters[i]->GetName() + "_PFactor_Pitch[" + buffer + "], ");
417 PropulsionStrings += (Thrusters[i]->GetName() + "_PFactor_Yaw[" + buffer + "], ");
418 PropulsionStrings += (Thrusters[i]->GetName() + "_Thrust[" + buffer + "], ");
419 if (Propeller->IsVPitch())
420 PropulsionStrings += (Thrusters[i]->GetName() + "_Pitch[" + buffer + "], ");
421 PropulsionStrings += (Thrusters[i]->GetName() + "_RPM[" + buffer + "]");
423 case FGThruster::ttDirect:
424 PropulsionStrings += (Thrusters[i]->GetName() + "_Thrust[" + buffer + "]");
427 PropulsionStrings += "INVALID THRUSTER TYPE";
432 return PropulsionStrings;
435 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
437 string FGPropulsion::GetPropulsionValues(void)
440 string PropulsionValues = "";
441 bool firstime = true;
443 for (unsigned int i=0;i<Engines.size();i++) {
444 if (firstime) firstime = false;
445 else PropulsionValues += ", ";
447 switch(Engines[i]->GetType()) {
448 case FGEngine::etPiston:
449 PropulsionValues += (string(gcvt(((FGPiston*)Engines[i])->GetPowerAvailable(), 10, buff)));
451 case FGEngine::etRocket:
452 PropulsionValues += (string(gcvt(((FGRocket*)Engines[i])->GetChamberPressure(), 10, buff)));
454 case FGEngine::etTurbine:
456 case FGEngine::etSimTurbine:
457 PropulsionValues += (string(gcvt(((FGSimTurbine*)Engines[i])->GetN1(), 10, buff))) + ", ";
458 PropulsionValues += (string(gcvt(((FGSimTurbine*)Engines[i])->GetN2(), 10, buff)));
462 PropulsionValues += ", ";
464 switch(Thrusters[i]->GetType()) {
465 case FGThruster::ttNozzle:
466 PropulsionValues += (string(gcvt(((FGNozzle*)Thrusters[i])->GetThrust(), 10, buff)));
468 case FGThruster::ttRotor:
470 case FGThruster::ttDirect:
471 PropulsionValues += (string(gcvt(((FGThruster*)Thrusters[i])->GetThrust(), 10, buff)));
473 case FGThruster::ttPropeller:
474 FGPropeller* Propeller = (FGPropeller*)Thrusters[i];
475 FGColumnVector3 vPFactor = Propeller->GetPFactor();
476 PropulsionValues += string(gcvt(Propeller->GetTorque(), 10, buff)) + ", ";
477 PropulsionValues += string(gcvt(vPFactor(eRoll), 10, buff)) + ", ";
478 PropulsionValues += string(gcvt(vPFactor(ePitch), 10, buff)) + ", ";
479 PropulsionValues += string(gcvt(vPFactor(eYaw), 10, buff)) + ", ";
480 PropulsionValues += string(gcvt(Propeller->GetThrust(), 10, buff)) + ", ";
481 if (Propeller->IsVPitch())
482 PropulsionValues += string(gcvt(Propeller->GetPitch(), 10, buff)) + ", ";
483 PropulsionValues += string(gcvt(Propeller->GetRPM(), 10, buff));
488 return PropulsionValues;
491 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
493 FGColumnVector3& FGPropulsion::GetTanksMoment(void)
495 iTank = Tanks.begin();
496 vXYZtank_arm.InitMatrix();
497 while (iTank < Tanks.end()) {
498 vXYZtank_arm(eX) += (*iTank)->GetXYZ(eX)*(*iTank)->GetContents();
499 vXYZtank_arm(eY) += (*iTank)->GetXYZ(eY)*(*iTank)->GetContents();
500 vXYZtank_arm(eZ) += (*iTank)->GetXYZ(eZ)*(*iTank)->GetContents();
506 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
508 double FGPropulsion::GetTanksWeight(void)
512 iTank = Tanks.begin();
513 while (iTank < Tanks.end()) {
514 Tw += (*iTank)->GetContents();
520 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
522 FGMatrix33& FGPropulsion::CalculateTankInertias(void)
527 if (size == 0) return tankJ;
529 tankJ = FGMatrix33();
531 for (unsigned int i=0; i<size; i++)
532 tankJ += MassBalance->GetPointmassInertia( lbtoslug * Tanks[i]->GetContents(),
533 Tanks[i]->GetXYZ() );
538 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
540 void FGPropulsion::SetMagnetos(int setting)
542 if (ActiveEngine < 0) {
543 for (unsigned i=0; i<Engines.size(); i++) {
544 ((FGPiston*)Engines[i])->SetMagnetos(setting);
547 ((FGPiston*)Engines[ActiveEngine])->SetMagnetos(setting);
551 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
553 void FGPropulsion::SetStarter(int setting)
555 if (ActiveEngine < 0) {
556 for (unsigned i=0; i<Engines.size(); i++) {
558 Engines[i]->SetStarter(false);
560 Engines[i]->SetStarter(true);
564 Engines[ActiveEngine]->SetStarter(false);
566 Engines[ActiveEngine]->SetStarter(true);
570 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
572 void FGPropulsion::SetCutoff(int setting)
574 if (ActiveEngine < 0) {
575 for (unsigned i=0; i<Engines.size(); i++) {
577 ((FGSimTurbine*)Engines[i])->SetCutoff(false);
579 ((FGSimTurbine*)Engines[i])->SetCutoff(true);
583 ((FGSimTurbine*)Engines[ActiveEngine])->SetCutoff(false);
585 ((FGSimTurbine*)Engines[ActiveEngine])->SetCutoff(true);
589 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
591 void FGPropulsion::SetActiveEngine(int engine)
593 if (engine >= Engines.size() || engine < 0)
596 ActiveEngine = engine;
599 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
601 void FGPropulsion::bind(void)
603 typedef double (FGPropulsion::*PMF)(int) const;
604 typedef int (FGPropulsion::*iPMF)(void) const;
606 PropertyManager->Tie("propulsion/magneto_cmd", this,
607 (iPMF)0, &FGPropulsion::SetMagnetos, true);
608 PropertyManager->Tie("propulsion/starter_cmd", this,
609 (iPMF)0, &FGPropulsion::SetStarter, true);
610 PropertyManager->Tie("propulsion/cutoff_cmd", this,
611 (iPMF)0, &FGPropulsion::SetCutoff, true);
613 PropertyManager->Tie("forces/fbx-prop-lbs", this,1,
614 (PMF)&FGPropulsion::GetForces);
615 PropertyManager->Tie("forces/fby-prop-lbs", this,2,
616 (PMF)&FGPropulsion::GetForces);
617 PropertyManager->Tie("forces/fbz-prop-lbs", this,3,
618 (PMF)&FGPropulsion::GetForces);
619 PropertyManager->Tie("moments/l-prop-lbsft", this,1,
620 (PMF)&FGPropulsion::GetMoments);
621 PropertyManager->Tie("moments/m-prop-lbsft", this,2,
622 (PMF)&FGPropulsion::GetMoments);
623 PropertyManager->Tie("moments/n-prop-lbsft", this,3,
624 (PMF)&FGPropulsion::GetMoments);
626 PropertyManager->Tie("propulsion/active_engine", this,
627 (iPMF)&FGPropulsion::GetActiveEngine, &FGPropulsion::SetActiveEngine, true);
630 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
632 void FGPropulsion::unbind(void)
634 PropertyManager->Untie("propulsion/magneto_cmd");
635 PropertyManager->Untie("propulsion/starter_cmd");
636 PropertyManager->Untie("propulsion/cutoff_cmd");
637 PropertyManager->Untie("propulsion/active_engine");
638 PropertyManager->Untie("forces/fbx-prop-lbs");
639 PropertyManager->Untie("forces/fby-prop-lbs");
640 PropertyManager->Untie("forces/fbz-prop-lbs");
641 PropertyManager->Untie("moments/l-prop-lbsft");
642 PropertyManager->Untie("moments/m-prop-lbsft");
643 PropertyManager->Untie("moments/n-prop-lbsft");
646 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
647 // The bitmasked value choices are as follows:
648 // unset: In this case (the default) JSBSim would only print
649 // out the normally expected messages, essentially echoing
650 // the config files as they are read. If the environment
651 // variable is not set, debug_lvl is set to 1 internally
652 // 0: This requests JSBSim not to output any messages
654 // 1: This value explicity requests the normal JSBSim
656 // 2: This value asks for a message to be printed out when
657 // a class is instantiated
658 // 4: When this value is set, a message is displayed when a
659 // FGModel object executes its Run() method
660 // 8: When this value is set, various runtime state variables
661 // are printed out periodically
662 // 16: When set various parameters are sanity checked and
663 // a message is printed out when they go out of bounds
665 void FGPropulsion::Debug(int from)
667 if (debug_lvl <= 0) return;
669 if (debug_lvl & 1) { // Standard console startup message output
670 if (from == 0) { // Constructor
674 if (debug_lvl & 2 ) { // Instantiation/Destruction notification
675 if (from == 0) cout << "Instantiated: FGPropulsion" << endl;
676 if (from == 1) cout << "Destroyed: FGPropulsion" << endl;
678 if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
680 if (debug_lvl & 8 ) { // Runtime state variables
682 if (debug_lvl & 16) { // Sanity checking
684 if (debug_lvl & 64) {
685 if (from == 0) { // Constructor
686 cout << IdSrc << endl;
687 cout << IdHdr << endl;