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;
85 ActiveEngine = -1; // -1: ALL, 0: Engine 1, 1: Engine 2 ...
90 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
92 FGPropulsion::~FGPropulsion()
94 for (unsigned int i=0; i<Engines.size(); i++) delete Engines[i];
100 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
102 bool FGPropulsion::Run(void)
104 double PowerAvailable;
107 vForces.InitMatrix();
108 vMoments.InitMatrix();
110 if (!FGModel::Run()) {
111 for (unsigned int i=0; i<numEngines; i++) {
112 Thrusters[i]->SetdeltaT(dt*rate);
113 PowerAvailable = Engines[i]->Calculate(Thrusters[i]->GetPowerRequired());
114 Thrusters[i]->Calculate(PowerAvailable);
115 vForces += Thrusters[i]->GetBodyForces(); // sum body frame forces
116 vMoments += Thrusters[i]->GetMoments(); // sum body frame moments
124 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
126 bool FGPropulsion::GetSteadyState(void)
128 double PowerAvailable;
129 double currentThrust = 0, lastThrust=-1;
131 int steady_count,j=0;
134 vForces.InitMatrix();
135 vMoments.InitMatrix();
137 if (!FGModel::Run()) {
138 for (unsigned int i=0; i<numEngines; i++) {
139 Engines[i]->SetTrimMode(true);
140 Thrusters[i]->SetdeltaT(dt*rate);
143 while (!steady && j < 6000) {
144 PowerAvailable = Engines[i]->Calculate(Thrusters[i]->GetPowerRequired());
145 lastThrust = currentThrust;
146 currentThrust = Thrusters[i]->Calculate(PowerAvailable);
147 if (fabs(lastThrust-currentThrust) < 0.0001) {
149 if (steady_count > 120) { steady=true; }
155 vForces += Thrusters[i]->GetBodyForces(); // sum body frame forces
156 vMoments += Thrusters[i]->GetMoments(); // sum body frame moments
157 Engines[i]->SetTrimMode(false);
166 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
168 bool FGPropulsion::ICEngineStart(void)
170 double PowerAvailable;
174 vForces.InitMatrix();
175 vMoments.InitMatrix();
177 for (unsigned int i=0; i<numEngines; i++) {
178 Engines[i]->SetTrimMode(true);
179 Thrusters[i]->SetdeltaT(dt*rate);
181 while (!Engines[i]->GetRunning() && j < 2000) {
182 PowerAvailable = Engines[i]->Calculate(Thrusters[i]->GetPowerRequired());
183 Thrusters[i]->Calculate(PowerAvailable);
186 vForces += Thrusters[i]->GetBodyForces(); // sum body frame forces
187 vMoments += Thrusters[i]->GetMoments(); // sum body frame moments
188 Engines[i]->SetTrimMode(false);
193 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
195 bool FGPropulsion::Load(FGConfigFile* AC_cfg)
197 string token, fullpath;
198 string engineFileName, engType;
199 string thrusterFileName, thrType;
201 string enginePath = FDMExec->GetEnginePath();
202 double xLoc, yLoc, zLoc, Pitch, Yaw;
203 double P_Factor = 0, Sense = 0.0;
205 bool ThrottleAdded = false;
208 fullpath = enginePath + "/";
210 fullpath = enginePath + ";";
213 AC_cfg->GetNextConfigLine();
215 while ((token = AC_cfg->GetValue()) != string("/PROPULSION")) {
217 if (token == "AC_ENGINE") { // ============ READING ENGINES
219 engineFileName = AC_cfg->GetValue("FILE");
221 if (debug_lvl > 0) cout << "\n Reading engine from file: " << fullpath
222 + engineFileName + ".xml"<< endl;
223 FGConfigFile Eng_cfg(fullpath + engineFileName + ".xml");
225 if (Eng_cfg.IsOpen()) {
226 Eng_cfg.GetNextConfigLine();
227 engType = Eng_cfg.GetValue();
230 ThrottleAdded = true;
232 if (engType == "FG_ROCKET") {
233 Engines.push_back(new FGRocket(FDMExec, &Eng_cfg));
234 } else if (engType == "FG_PISTON") {
235 Engines.push_back(new FGPiston(FDMExec, &Eng_cfg));
236 } else if (engType == "FG_TURBINE") {
237 Engines.push_back(new FGTurbine(FDMExec, &Eng_cfg));
239 cerr << fgred << " Unrecognized engine type: " << underon << engType
240 << underoff << " found in config file." << fgdef << endl;
244 AC_cfg->GetNextConfigLine();
245 while ((token = AC_cfg->GetValue()) != string("/AC_ENGINE")) {
247 if (token == "XLOC") { *AC_cfg >> xLoc; }
248 else if (token == "YLOC") { *AC_cfg >> yLoc; }
249 else if (token == "ZLOC") { *AC_cfg >> zLoc; }
250 else if (token == "PITCH") { *AC_cfg >> Pitch;}
251 else if (token == "YAW") { *AC_cfg >> Yaw;}
252 else if (token == "FEED") {
254 Engines[numEngines]->AddFeedTank(Feed);
255 if (debug_lvl > 0) cout << " Feed tank: " << Feed << endl;
256 } else cerr << "Unknown identifier: " << token << " in engine file: "
257 << engineFileName << endl;
261 cout << " X = " << xLoc << endl;
262 cout << " Y = " << yLoc << endl;
263 cout << " Z = " << zLoc << endl;
264 cout << " Pitch = " << Pitch << endl;
265 cout << " Yaw = " << Yaw << endl;
268 Engines[numEngines]->SetPlacement(xLoc, yLoc, zLoc, Pitch, Yaw);
269 Engines[numEngines]->SetEngineNumber(numEngines);
274 cerr << fgred << "\n Could not read engine config file: " << underon <<
275 fullpath + engineFileName + ".xml" << underoff << fgdef << endl;
279 } else if (token == "AC_TANK") { // ============== READING TANKS
281 if (debug_lvl > 0) cout << "\n Reading tank definition" << endl;
282 Tanks.push_back(new FGTank(AC_cfg));
283 switch(Tanks[numTanks]->GetType()) {
285 numSelectedFuelTanks++;
288 case FGTank::ttOXIDIZER:
289 numSelectedOxiTanks++;
296 } else if (token == "AC_THRUSTER") { // ========== READING THRUSTERS
298 thrusterFileName = AC_cfg->GetValue("FILE");
300 if (debug_lvl > 0) cout << "\n Reading thruster from file: " <<
301 fullpath + thrusterFileName + ".xml" << endl;
302 FGConfigFile Thruster_cfg(fullpath + thrusterFileName + ".xml");
304 if (Thruster_cfg.IsOpen()) {
305 Thruster_cfg.GetNextConfigLine();
306 thrType = Thruster_cfg.GetValue();
308 if (thrType == "FG_PROPELLER") {
309 Thrusters.push_back(new FGPropeller(FDMExec, &Thruster_cfg));
310 } else if (thrType == "FG_NOZZLE") {
311 Thrusters.push_back(new FGNozzle(FDMExec, &Thruster_cfg));
314 AC_cfg->GetNextConfigLine();
315 while ((token = AC_cfg->GetValue()) != string("/AC_THRUSTER")) {
317 if (token == "XLOC") *AC_cfg >> xLoc;
318 else if (token == "YLOC") *AC_cfg >> yLoc;
319 else if (token == "ZLOC") *AC_cfg >> zLoc;
320 else if (token == "PITCH") *AC_cfg >> Pitch;
321 else if (token == "YAW") *AC_cfg >> Yaw;
322 else if (token == "P_FACTOR") *AC_cfg >> P_Factor;
323 else if (token == "SENSE") *AC_cfg >> Sense;
324 else cerr << "Unknown identifier: " << token << " in engine file: "
325 << engineFileName << endl;
328 Thrusters[numThrusters]->SetLocation(xLoc, yLoc, zLoc);
329 Thrusters[numThrusters]->SetAnglesToBody(0, Pitch, Yaw);
330 if (thrType == "FG_PROPELLER" && P_Factor > 0.001) {
331 ((FGPropeller*)Thrusters[numThrusters])->SetPFactor(P_Factor);
332 if (debug_lvl > 0) cout << " P-Factor: " << P_Factor << endl;
333 ((FGPropeller*)Thrusters[numThrusters])->SetSense(fabs(Sense)/Sense);
334 if (debug_lvl > 0) cout << " Sense: " << Sense << endl;
336 Thrusters[numThrusters]->SetdeltaT(dt*rate);
337 Thrusters[numThrusters]->SetThrusterNumber(numThrusters);
341 cerr << "Could not read thruster config file: " << fullpath
342 + thrusterFileName + ".xml" << endl;
347 AC_cfg->GetNextConfigLine();
350 if (!ThrottleAdded) FCS->AddThrottle(); // need to have at least one throttle
355 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
357 string FGPropulsion::GetPropulsionStrings(void)
359 string PropulsionStrings = "";
360 bool firstime = true;
363 for (unsigned int i=0;i<Engines.size();i++) {
364 if (firstime) firstime = false;
365 else PropulsionStrings += ", ";
367 sprintf(buffer, "%d", i);
369 switch(Engines[i]->GetType()) {
370 case FGEngine::etPiston:
371 PropulsionStrings += (Engines[i]->GetName() + "_PwrAvail[" + buffer + "]");
373 case FGEngine::etRocket:
374 PropulsionStrings += (Engines[i]->GetName() + "_ChamberPress[" + buffer + "]");
376 case FGEngine::etTurbine:
379 PropulsionStrings += "INVALID ENGINE TYPE";
383 PropulsionStrings += ", ";
385 FGPropeller* Propeller = (FGPropeller*)Thrusters[i];
386 switch(Thrusters[i]->GetType()) {
387 case FGThruster::ttNozzle:
388 PropulsionStrings += (Thrusters[i]->GetName() + "_Thrust[" + buffer + "]");
390 case FGThruster::ttRotor:
392 case FGThruster::ttPropeller:
393 PropulsionStrings += (Thrusters[i]->GetName() + "_Torque[" + buffer + "], ");
394 PropulsionStrings += (Thrusters[i]->GetName() + "_PFactor_Roll[" + buffer + "], ");
395 PropulsionStrings += (Thrusters[i]->GetName() + "_PFactor_Pitch[" + buffer + "], ");
396 PropulsionStrings += (Thrusters[i]->GetName() + "_PFactor_Yaw[" + buffer + "], ");
397 PropulsionStrings += (Thrusters[i]->GetName() + "_Thrust[" + buffer + "], ");
398 if (Propeller->IsVPitch())
399 PropulsionStrings += (Thrusters[i]->GetName() + "_Pitch[" + buffer + "], ");
400 PropulsionStrings += (Thrusters[i]->GetName() + "_RPM[" + buffer + "]");
403 PropulsionStrings += "INVALID THRUSTER TYPE";
408 return PropulsionStrings;
411 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
413 string FGPropulsion::GetPropulsionValues(void)
416 string PropulsionValues = "";
417 bool firstime = true;
419 for (unsigned int i=0;i<Engines.size();i++) {
420 if (firstime) firstime = false;
421 else PropulsionValues += ", ";
423 switch(Engines[i]->GetType()) {
424 case FGEngine::etPiston:
425 PropulsionValues += (string(gcvt(((FGPiston*)Engines[i])->GetPowerAvailable(), 10, buff)));
427 case FGEngine::etRocket:
428 PropulsionValues += (string(gcvt(((FGRocket*)Engines[i])->GetChamberPressure(), 10, buff)));
430 case FGEngine::etTurbine:
434 PropulsionValues += ", ";
436 switch(Thrusters[i]->GetType()) {
437 case FGThruster::ttNozzle:
438 PropulsionValues += (string(gcvt(((FGNozzle*)Thrusters[i])->GetThrust(), 10, buff)));
440 case FGThruster::ttRotor:
442 case FGThruster::ttPropeller:
443 FGPropeller* Propeller = (FGPropeller*)Thrusters[i];
444 FGColumnVector3 vPFactor = Propeller->GetPFactor();
445 PropulsionValues += string(gcvt(Propeller->GetTorque(), 10, buff)) + ", ";
446 PropulsionValues += string(gcvt(vPFactor(eRoll), 10, buff)) + ", ";
447 PropulsionValues += string(gcvt(vPFactor(ePitch), 10, buff)) + ", ";
448 PropulsionValues += string(gcvt(vPFactor(eYaw), 10, buff)) + ", ";
449 PropulsionValues += string(gcvt(Propeller->GetThrust(), 10, buff)) + ", ";
450 if (Propeller->IsVPitch())
451 PropulsionValues += string(gcvt(Propeller->GetPitch(), 10, buff)) + ", ";
452 PropulsionValues += string(gcvt(Propeller->GetRPM(), 10, buff));
457 return PropulsionValues;
460 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
462 FGColumnVector3& FGPropulsion::GetTanksMoment(void)
464 iTank = Tanks.begin();
465 vXYZtank.InitMatrix();
466 while (iTank < Tanks.end()) {
467 vXYZtank(eX) += (*iTank)->GetX()*(*iTank)->GetContents();
468 vXYZtank(eY) += (*iTank)->GetY()*(*iTank)->GetContents();
469 vXYZtank(eZ) += (*iTank)->GetZ()*(*iTank)->GetContents();
475 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
477 double FGPropulsion::GetTanksWeight(void)
481 iTank = Tanks.begin();
482 while (iTank < Tanks.end()) {
483 Tw += (*iTank)->GetContents();
489 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
491 double FGPropulsion::GetTanksIxx(const FGColumnVector3& vXYZcg)
494 iTank = Tanks.begin();
495 while (iTank < Tanks.end()) {
496 I += ((*iTank)->GetX() - vXYZcg(eX))*((*iTank)->GetX() - vXYZcg(eX)) * (*iTank)->GetContents()/(144.0*Inertial->gravity());
502 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
504 double FGPropulsion::GetTanksIyy(const FGColumnVector3& vXYZcg)
507 iTank = Tanks.begin();
508 while (iTank < Tanks.end()) {
509 I += ((*iTank)->GetY() - vXYZcg(eY))*((*iTank)->GetY() - vXYZcg(eY)) * (*iTank)->GetContents()/(144.0*Inertial->gravity());
515 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
517 double FGPropulsion::GetTanksIzz(const FGColumnVector3& vXYZcg)
520 iTank = Tanks.begin();
521 while (iTank < Tanks.end()) {
522 I += ((*iTank)->GetZ() - vXYZcg(eZ))*((*iTank)->GetZ() - vXYZcg(eZ)) * (*iTank)->GetContents()/(144.0*Inertial->gravity());
528 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
530 double FGPropulsion::GetTanksIxz(const FGColumnVector3& vXYZcg)
533 iTank = Tanks.begin();
534 while (iTank < Tanks.end()) {
535 I += ((*iTank)->GetX() - vXYZcg(eX))*((*iTank)->GetZ() - vXYZcg(eZ)) * (*iTank)->GetContents()/(144.0*Inertial->gravity());
541 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
543 double FGPropulsion::GetTanksIxy(const FGColumnVector3& vXYZcg)
546 iTank = Tanks.begin();
547 while (iTank != Tanks.end()) {
548 I += ((*iTank)->GetX() - vXYZcg(eX))*((*iTank)->GetY() - vXYZcg(eY)) * (*iTank)->GetContents()/(144.0*Inertial->gravity());
554 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
556 void FGPropulsion::SetMagnetos(int setting)
558 if (ActiveEngine == -1) {
559 for (unsigned i=0; i<Engines.size(); i++) {
560 Engines[i]->SetMagnetos(setting);
563 Engines[ActiveEngine]->SetMagnetos(setting);
567 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
569 void FGPropulsion::SetStarter(int setting)
571 if (ActiveEngine == -1) {
572 for (unsigned i=0; i<Engines.size(); i++) {
573 Engines[i]->SetStarter(setting);
577 Engines[ActiveEngine]->SetStarter(false);
579 Engines[ActiveEngine]->SetStarter(true);
583 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
585 void FGPropulsion::SetActiveEngine(int engine)
587 if ( unsigned(engine) > Engines.size())
590 ActiveEngine = engine;
593 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
595 void FGPropulsion::bind(void)
597 typedef double (FGPropulsion::*PMF)(int) const;
598 typedef int (FGPropulsion::*iPMF)(void) const;
599 /* PropertyManager->Tie("propulsion/num-engines", this,
600 &FGPropulsion::GetNumEngines);
601 PropertyManager->Tie("propulsion/num-tanks", this,
602 &FGPropulsion::GetNumTanks); */
604 PropertyManager->Tie("propulsion/magneto_cmd", this,
606 &FGPropulsion::SetMagnetos,
608 PropertyManager->Tie("propulsion/starter_cmd", this,
610 &FGPropulsion::SetStarter,
612 PropertyManager->Tie("propulsion/active_engine", this,
614 &FGPropulsion::SetActiveEngine,
617 PropertyManager->Tie("propulsion/num-sel-fuel-tanks", this,
618 &FGPropulsion::GetnumSelectedFuelTanks);
619 PropertyManager->Tie("propulsion/num-sel-ox-tanks", this,
620 &FGPropulsion::GetnumSelectedOxiTanks);
621 PropertyManager->Tie("forces/fbx-prop-lbs", this,1,
622 (PMF)&FGPropulsion::GetForces);
623 PropertyManager->Tie("forces/fby-prop-lbs", this,2,
624 (PMF)&FGPropulsion::GetForces);
625 PropertyManager->Tie("forces/fbz-prop-lbs", this,3,
626 (PMF)&FGPropulsion::GetForces);
627 PropertyManager->Tie("moments/l-prop-lbsft", this,1,
628 (PMF)&FGPropulsion::GetMoments);
629 PropertyManager->Tie("moments/m-prop-lbsft", this,2,
630 (PMF)&FGPropulsion::GetMoments);
631 PropertyManager->Tie("moments/n-prop-lbsft", this,3,
632 (PMF)&FGPropulsion::GetMoments);
633 //PropertyManager->Tie("propulsion/tanks-weight-lbs", this,
634 // &FGPropulsion::GetTanksWeight);
637 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
639 void FGPropulsion::unbind(void)
641 /* PropertyManager->Untie("propulsion/num-engines");
642 PropertyManager->Untie("propulsion/num-tanks"); */
643 PropertyManager->Untie("propulsion/num-sel-fuel-tanks");
644 PropertyManager->Untie("propulsion/num-sel-ox-tanks");
645 PropertyManager->Untie("propulsion/magneto_cmd");
646 PropertyManager->Untie("propulsion/starter_cmd");
647 PropertyManager->Untie("propulsion/active_engine");
648 PropertyManager->Untie("forces/fbx-prop-lbs");
649 PropertyManager->Untie("forces/fby-prop-lbs");
650 PropertyManager->Untie("forces/fbz-prop-lbs");
651 PropertyManager->Untie("moments/l-prop-lbsft");
652 PropertyManager->Untie("moments/m-prop-lbsft");
653 PropertyManager->Untie("moments/n-prop-lbsft");
654 //PropertyManager->Untie("propulsion/tanks-weight-lbs");
657 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
658 // The bitmasked value choices are as follows:
659 // unset: In this case (the default) JSBSim would only print
660 // out the normally expected messages, essentially echoing
661 // the config files as they are read. If the environment
662 // variable is not set, debug_lvl is set to 1 internally
663 // 0: This requests JSBSim not to output any messages
665 // 1: This value explicity requests the normal JSBSim
667 // 2: This value asks for a message to be printed out when
668 // a class is instantiated
669 // 4: When this value is set, a message is displayed when a
670 // FGModel object executes its Run() method
671 // 8: When this value is set, various runtime state variables
672 // are printed out periodically
673 // 16: When set various parameters are sanity checked and
674 // a message is printed out when they go out of bounds
676 void FGPropulsion::Debug(int from)
678 if (debug_lvl <= 0) return;
680 if (debug_lvl & 1) { // Standard console startup message output
681 if (from == 0) { // Constructor
685 if (debug_lvl & 2 ) { // Instantiation/Destruction notification
686 if (from == 0) cout << "Instantiated: FGPropulsion" << endl;
687 if (from == 1) cout << "Destroyed: FGPropulsion" << endl;
689 if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
691 if (debug_lvl & 8 ) { // Runtime state variables
693 if (debug_lvl & 16) { // Sanity checking
695 if (debug_lvl & 64) {
696 if (from == 0) { // Constructor
697 cout << IdSrc << endl;
698 cout << IdHdr << endl;