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"
58 #if defined (__APPLE__)
59 /* Not all systems have the gcvt function */
60 inline char* gcvt (double value, int ndigits, char *buf) {
61 /* note that this is not exactly what gcvt is supposed to do! */
62 snprintf (buf, ndigits+1, "%f", value);
69 static const char *IdSrc = "$Id$";
70 static const char *IdHdr = ID_PROPULSION;
72 extern short debug_lvl;
75 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
77 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
79 FGPropulsion::FGPropulsion(FGFDMExec* exec) : FGModel(exec)
81 Name = "FGPropulsion";
82 numSelectedFuelTanks = numSelectedOxiTanks = 0;
83 numTanks = numEngines = numThrusters = 0;
84 numOxiTanks = numFuelTanks = 0;
86 ActiveEngine = -1; // -1: ALL, 0: Engine 1, 1: Engine 2 ...
91 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
93 FGPropulsion::~FGPropulsion()
95 for (unsigned int i=0; i<Engines.size(); i++) delete Engines[i];
101 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
103 bool FGPropulsion::Run(void)
105 double PowerAvailable;
108 vForces.InitMatrix();
109 vMoments.InitMatrix();
111 if (!FGModel::Run()) {
112 for (unsigned int i=0; i<numEngines; i++) {
113 Thrusters[i]->SetdeltaT(dt*rate);
114 PowerAvailable = Engines[i]->Calculate(Thrusters[i]->GetPowerRequired());
115 Thrusters[i]->Calculate(PowerAvailable);
116 vForces += Thrusters[i]->GetBodyForces(); // sum body frame forces
117 vMoments += Thrusters[i]->GetMoments(); // sum body frame moments
125 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
127 bool FGPropulsion::GetSteadyState(void)
129 double PowerAvailable;
130 double currentThrust = 0, lastThrust=-1;
132 int steady_count,j=0;
135 vForces.InitMatrix();
136 vMoments.InitMatrix();
138 if (!FGModel::Run()) {
139 for (unsigned int i=0; i<numEngines; i++) {
140 Engines[i]->SetTrimMode(true);
141 Thrusters[i]->SetdeltaT(dt*rate);
144 while (!steady && j < 6000) {
145 PowerAvailable = Engines[i]->Calculate(Thrusters[i]->GetPowerRequired());
146 lastThrust = currentThrust;
147 currentThrust = Thrusters[i]->Calculate(PowerAvailable);
148 if (fabs(lastThrust-currentThrust) < 0.0001) {
150 if (steady_count > 120) { steady=true; }
156 vForces += Thrusters[i]->GetBodyForces(); // sum body frame forces
157 vMoments += Thrusters[i]->GetMoments(); // sum body frame moments
158 Engines[i]->SetTrimMode(false);
167 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
169 bool FGPropulsion::ICEngineStart(void)
171 double PowerAvailable;
175 vForces.InitMatrix();
176 vMoments.InitMatrix();
178 for (unsigned int i=0; i<numEngines; i++) {
179 Engines[i]->SetTrimMode(true);
180 Thrusters[i]->SetdeltaT(dt*rate);
182 while (!Engines[i]->GetRunning() && j < 2000) {
183 PowerAvailable = Engines[i]->Calculate(Thrusters[i]->GetPowerRequired());
184 Thrusters[i]->Calculate(PowerAvailable);
187 vForces += Thrusters[i]->GetBodyForces(); // sum body frame forces
188 vMoments += Thrusters[i]->GetMoments(); // sum body frame moments
189 Engines[i]->SetTrimMode(false);
194 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
196 bool FGPropulsion::Load(FGConfigFile* AC_cfg)
198 string token, fullpath;
199 string engineFileName, engType;
200 string thrusterFileName, thrType;
202 string enginePath = FDMExec->GetEnginePath();
203 double xLoc, yLoc, zLoc, Pitch, Yaw;
204 double P_Factor = 0, Sense = 0.0;
206 bool ThrottleAdded = false;
209 fullpath = enginePath + "/";
211 fullpath = enginePath + ";";
214 AC_cfg->GetNextConfigLine();
216 while ((token = AC_cfg->GetValue()) != string("/PROPULSION")) {
218 if (token == "AC_ENGINE") { // ============ READING ENGINES
220 engineFileName = AC_cfg->GetValue("FILE");
222 if (debug_lvl > 0) cout << "\n Reading engine from file: " << fullpath
223 + engineFileName + ".xml"<< endl;
224 FGConfigFile Eng_cfg(fullpath + engineFileName + ".xml");
226 if (Eng_cfg.IsOpen()) {
227 Eng_cfg.GetNextConfigLine();
228 engType = Eng_cfg.GetValue();
229 cout << engType << endl;
232 ThrottleAdded = true;
234 if (engType == "FG_ROCKET") {
235 Engines.push_back(new FGRocket(FDMExec, &Eng_cfg));
236 } else if (engType == "FG_PISTON") {
237 Engines.push_back(new FGPiston(FDMExec, &Eng_cfg));
238 } else if (engType == "FG_TURBINE") {
239 Engines.push_back(new FGTurbine(FDMExec, &Eng_cfg));
241 cerr << fgred << " Unrecognized engine type: " << underon << engType
242 << underoff << " found in config file." << fgdef << endl;
246 AC_cfg->GetNextConfigLine();
247 while ((token = AC_cfg->GetValue()) != string("/AC_ENGINE")) {
249 if (token == "XLOC") { *AC_cfg >> xLoc; }
250 else if (token == "YLOC") { *AC_cfg >> yLoc; }
251 else if (token == "ZLOC") { *AC_cfg >> zLoc; }
252 else if (token == "PITCH") { *AC_cfg >> Pitch;}
253 else if (token == "YAW") { *AC_cfg >> Yaw;}
254 else if (token == "FEED") {
256 Engines[numEngines]->AddFeedTank(Feed);
257 if (debug_lvl > 0) cout << " Feed tank: " << Feed << endl;
258 } else cerr << "Unknown identifier: " << token << " in engine file: "
259 << engineFileName << endl;
263 cout << " X = " << xLoc << endl;
264 cout << " Y = " << yLoc << endl;
265 cout << " Z = " << zLoc << endl;
266 cout << " Pitch = " << Pitch << endl;
267 cout << " Yaw = " << Yaw << endl;
270 Engines[numEngines]->SetPlacement(xLoc, yLoc, zLoc, Pitch, Yaw);
271 Engines[numEngines]->SetEngineNumber(numEngines);
276 cerr << fgred << "\n Could not read engine config file: " << underon <<
277 fullpath + engineFileName + ".xml" << underoff << fgdef << endl;
281 } else if (token == "AC_TANK") { // ============== READING TANKS
283 if (debug_lvl > 0) cout << "\n Reading tank definition" << endl;
284 Tanks.push_back(new FGTank(AC_cfg));
285 switch(Tanks[numTanks]->GetType()) {
287 numSelectedFuelTanks++;
290 case FGTank::ttOXIDIZER:
291 numSelectedOxiTanks++;
298 } else if (token == "AC_THRUSTER") { // ========== READING THRUSTERS
300 thrusterFileName = AC_cfg->GetValue("FILE");
302 if (debug_lvl > 0) cout << "\n Reading thruster from file: " <<
303 fullpath + thrusterFileName + ".xml" << endl;
304 FGConfigFile Thruster_cfg(fullpath + thrusterFileName + ".xml");
306 if (Thruster_cfg.IsOpen()) {
307 Thruster_cfg.GetNextConfigLine();
308 thrType = Thruster_cfg.GetValue();
310 if (thrType == "FG_PROPELLER") {
311 Thrusters.push_back(new FGPropeller(FDMExec, &Thruster_cfg));
312 } else if (thrType == "FG_NOZZLE") {
313 Thrusters.push_back(new FGNozzle(FDMExec, &Thruster_cfg ));
314 } else if (thrType == "FG_DIRECT") {
315 Thrusters.push_back(new FGThruster( FDMExec, &Thruster_cfg) );
318 AC_cfg->GetNextConfigLine();
319 while ((token = AC_cfg->GetValue()) != string("/AC_THRUSTER")) {
321 if (token == "XLOC") *AC_cfg >> xLoc;
322 else if (token == "YLOC") *AC_cfg >> yLoc;
323 else if (token == "ZLOC") *AC_cfg >> zLoc;
324 else if (token == "PITCH") *AC_cfg >> Pitch;
325 else if (token == "YAW") *AC_cfg >> Yaw;
326 else if (token == "P_FACTOR") *AC_cfg >> P_Factor;
327 else if (token == "SENSE") *AC_cfg >> Sense;
328 else cerr << "Unknown identifier: " << token << " in engine file: "
329 << engineFileName << endl;
332 Thrusters[numThrusters]->SetLocation(xLoc, yLoc, zLoc);
333 Thrusters[numThrusters]->SetAnglesToBody(0, Pitch, Yaw);
334 if (thrType == "FG_PROPELLER" && P_Factor > 0.001) {
335 ((FGPropeller*)Thrusters[numThrusters])->SetPFactor(P_Factor);
336 if (debug_lvl > 0) cout << " P-Factor: " << P_Factor << endl;
337 ((FGPropeller*)Thrusters[numThrusters])->SetSense(fabs(Sense)/Sense);
338 if (debug_lvl > 0) cout << " Sense: " << Sense << endl;
340 Thrusters[numThrusters]->SetdeltaT(dt*rate);
341 Thrusters[numThrusters]->SetThrusterNumber(numThrusters);
345 cerr << "Could not read thruster config file: " << fullpath
346 + thrusterFileName + ".xml" << endl;
351 AC_cfg->GetNextConfigLine();
354 if (!ThrottleAdded) FCS->AddThrottle(); // need to have at least one throttle
359 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
361 string FGPropulsion::GetPropulsionStrings(void)
363 string PropulsionStrings = "";
364 bool firstime = true;
367 for (unsigned int i=0;i<Engines.size();i++) {
368 if (firstime) firstime = false;
369 else PropulsionStrings += ", ";
371 sprintf(buffer, "%d", i);
373 switch(Engines[i]->GetType()) {
374 case FGEngine::etPiston:
375 PropulsionStrings += (Engines[i]->GetName() + "_PwrAvail[" + buffer + "]");
377 case FGEngine::etRocket:
378 PropulsionStrings += (Engines[i]->GetName() + "_ChamberPress[" + buffer + "]");
380 case FGEngine::etTurbine:
383 PropulsionStrings += "INVALID ENGINE TYPE";
387 PropulsionStrings += ", ";
389 FGPropeller* Propeller = (FGPropeller*)Thrusters[i];
390 switch(Thrusters[i]->GetType()) {
391 case FGThruster::ttNozzle:
392 PropulsionStrings += (Thrusters[i]->GetName() + "_Thrust[" + buffer + "]");
394 case FGThruster::ttRotor:
396 case FGThruster::ttPropeller:
397 PropulsionStrings += (Thrusters[i]->GetName() + "_Torque[" + buffer + "], ");
398 PropulsionStrings += (Thrusters[i]->GetName() + "_PFactor_Roll[" + buffer + "], ");
399 PropulsionStrings += (Thrusters[i]->GetName() + "_PFactor_Pitch[" + buffer + "], ");
400 PropulsionStrings += (Thrusters[i]->GetName() + "_PFactor_Yaw[" + buffer + "], ");
401 PropulsionStrings += (Thrusters[i]->GetName() + "_Thrust[" + buffer + "], ");
402 if (Propeller->IsVPitch())
403 PropulsionStrings += (Thrusters[i]->GetName() + "_Pitch[" + buffer + "], ");
404 PropulsionStrings += (Thrusters[i]->GetName() + "_RPM[" + buffer + "]");
407 PropulsionStrings += "INVALID THRUSTER TYPE";
412 return PropulsionStrings;
415 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
417 string FGPropulsion::GetPropulsionValues(void)
420 string PropulsionValues = "";
421 bool firstime = true;
423 for (unsigned int i=0;i<Engines.size();i++) {
424 if (firstime) firstime = false;
425 else PropulsionValues += ", ";
427 switch(Engines[i]->GetType()) {
428 case FGEngine::etPiston:
429 PropulsionValues += (string(gcvt(((FGPiston*)Engines[i])->GetPowerAvailable(), 10, buff)));
431 case FGEngine::etRocket:
432 PropulsionValues += (string(gcvt(((FGRocket*)Engines[i])->GetChamberPressure(), 10, buff)));
434 case FGEngine::etTurbine:
438 PropulsionValues += ", ";
440 switch(Thrusters[i]->GetType()) {
441 case FGThruster::ttNozzle:
442 PropulsionValues += (string(gcvt(((FGNozzle*)Thrusters[i])->GetThrust(), 10, buff)));
444 case FGThruster::ttRotor:
446 case FGThruster::ttPropeller:
447 FGPropeller* Propeller = (FGPropeller*)Thrusters[i];
448 FGColumnVector3 vPFactor = Propeller->GetPFactor();
449 PropulsionValues += string(gcvt(Propeller->GetTorque(), 10, buff)) + ", ";
450 PropulsionValues += string(gcvt(vPFactor(eRoll), 10, buff)) + ", ";
451 PropulsionValues += string(gcvt(vPFactor(ePitch), 10, buff)) + ", ";
452 PropulsionValues += string(gcvt(vPFactor(eYaw), 10, buff)) + ", ";
453 PropulsionValues += string(gcvt(Propeller->GetThrust(), 10, buff)) + ", ";
454 if (Propeller->IsVPitch())
455 PropulsionValues += string(gcvt(Propeller->GetPitch(), 10, buff)) + ", ";
456 PropulsionValues += string(gcvt(Propeller->GetRPM(), 10, buff));
461 return PropulsionValues;
464 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
466 FGColumnVector3& FGPropulsion::GetTanksMoment(void)
468 iTank = Tanks.begin();
469 vXYZtank.InitMatrix();
470 while (iTank < Tanks.end()) {
471 vXYZtank(eX) += (*iTank)->GetX()*(*iTank)->GetContents();
472 vXYZtank(eY) += (*iTank)->GetY()*(*iTank)->GetContents();
473 vXYZtank(eZ) += (*iTank)->GetZ()*(*iTank)->GetContents();
479 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
481 double FGPropulsion::GetTanksWeight(void)
485 iTank = Tanks.begin();
486 while (iTank < Tanks.end()) {
487 Tw += (*iTank)->GetContents();
493 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
495 double FGPropulsion::GetTanksIxx(const FGColumnVector3& vXYZcg)
498 iTank = Tanks.begin();
499 while (iTank < Tanks.end()) {
500 I += ((*iTank)->GetX() - vXYZcg(eX))*((*iTank)->GetX() - vXYZcg(eX)) * (*iTank)->GetContents()/(144.0*Inertial->gravity());
506 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
508 double FGPropulsion::GetTanksIyy(const FGColumnVector3& vXYZcg)
511 iTank = Tanks.begin();
512 while (iTank < Tanks.end()) {
513 I += ((*iTank)->GetY() - vXYZcg(eY))*((*iTank)->GetY() - vXYZcg(eY)) * (*iTank)->GetContents()/(144.0*Inertial->gravity());
519 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
521 double FGPropulsion::GetTanksIzz(const FGColumnVector3& vXYZcg)
524 iTank = Tanks.begin();
525 while (iTank < Tanks.end()) {
526 I += ((*iTank)->GetZ() - vXYZcg(eZ))*((*iTank)->GetZ() - vXYZcg(eZ)) * (*iTank)->GetContents()/(144.0*Inertial->gravity());
532 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
534 double FGPropulsion::GetTanksIxz(const FGColumnVector3& vXYZcg)
537 iTank = Tanks.begin();
538 while (iTank < Tanks.end()) {
539 I += ((*iTank)->GetX() - vXYZcg(eX))*((*iTank)->GetZ() - vXYZcg(eZ)) * (*iTank)->GetContents()/(144.0*Inertial->gravity());
545 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
547 double FGPropulsion::GetTanksIxy(const FGColumnVector3& vXYZcg)
550 iTank = Tanks.begin();
551 while (iTank != Tanks.end()) {
552 I += ((*iTank)->GetX() - vXYZcg(eX))*((*iTank)->GetY() - vXYZcg(eY)) * (*iTank)->GetContents()/(144.0*Inertial->gravity());
558 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
560 void FGPropulsion::SetMagnetos(int setting)
562 if (ActiveEngine == -1) {
563 for (unsigned i=0; i<Engines.size(); i++) {
564 Engines[i]->SetMagnetos(setting);
567 Engines[ActiveEngine]->SetMagnetos(setting);
571 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
573 void FGPropulsion::SetStarter(int setting)
575 if (ActiveEngine == -1) {
576 for (unsigned i=0; i<Engines.size(); i++) {
577 Engines[i]->SetStarter(setting);
581 Engines[ActiveEngine]->SetStarter(false);
583 Engines[ActiveEngine]->SetStarter(true);
587 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
589 void FGPropulsion::SetActiveEngine(int engine)
591 if ( unsigned(engine) > Engines.size())
594 ActiveEngine = engine;
597 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
599 void FGPropulsion::bind(void)
601 typedef double (FGPropulsion::*PMF)(int) const;
602 typedef int (FGPropulsion::*iPMF)(void) const;
603 /* PropertyManager->Tie("propulsion/num-engines", this,
604 &FGPropulsion::GetNumEngines);
605 PropertyManager->Tie("propulsion/num-tanks", this,
606 &FGPropulsion::GetNumTanks); */
608 PropertyManager->Tie("propulsion/magneto_cmd", this,
610 &FGPropulsion::SetMagnetos,
612 PropertyManager->Tie("propulsion/starter_cmd", this,
614 &FGPropulsion::SetStarter,
616 PropertyManager->Tie("propulsion/active_engine", this,
618 &FGPropulsion::SetActiveEngine,
621 PropertyManager->Tie("propulsion/num-sel-fuel-tanks", this,
622 &FGPropulsion::GetnumSelectedFuelTanks);
623 PropertyManager->Tie("propulsion/num-sel-ox-tanks", this,
624 &FGPropulsion::GetnumSelectedOxiTanks);
625 PropertyManager->Tie("forces/fbx-prop-lbs", this,1,
626 (PMF)&FGPropulsion::GetForces);
627 PropertyManager->Tie("forces/fby-prop-lbs", this,2,
628 (PMF)&FGPropulsion::GetForces);
629 PropertyManager->Tie("forces/fbz-prop-lbs", this,3,
630 (PMF)&FGPropulsion::GetForces);
631 PropertyManager->Tie("moments/l-prop-lbsft", this,1,
632 (PMF)&FGPropulsion::GetMoments);
633 PropertyManager->Tie("moments/m-prop-lbsft", this,2,
634 (PMF)&FGPropulsion::GetMoments);
635 PropertyManager->Tie("moments/n-prop-lbsft", this,3,
636 (PMF)&FGPropulsion::GetMoments);
637 //PropertyManager->Tie("propulsion/tanks-weight-lbs", this,
638 // &FGPropulsion::GetTanksWeight);
641 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
643 void FGPropulsion::unbind(void)
645 /* PropertyManager->Untie("propulsion/num-engines");
646 PropertyManager->Untie("propulsion/num-tanks"); */
647 PropertyManager->Untie("propulsion/num-sel-fuel-tanks");
648 PropertyManager->Untie("propulsion/num-sel-ox-tanks");
649 PropertyManager->Untie("propulsion/magneto_cmd");
650 PropertyManager->Untie("propulsion/starter_cmd");
651 PropertyManager->Untie("propulsion/active_engine");
652 PropertyManager->Untie("forces/fbx-prop-lbs");
653 PropertyManager->Untie("forces/fby-prop-lbs");
654 PropertyManager->Untie("forces/fbz-prop-lbs");
655 PropertyManager->Untie("moments/l-prop-lbsft");
656 PropertyManager->Untie("moments/m-prop-lbsft");
657 PropertyManager->Untie("moments/n-prop-lbsft");
658 //PropertyManager->Untie("propulsion/tanks-weight-lbs");
661 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
662 // The bitmasked value choices are as follows:
663 // unset: In this case (the default) JSBSim would only print
664 // out the normally expected messages, essentially echoing
665 // the config files as they are read. If the environment
666 // variable is not set, debug_lvl is set to 1 internally
667 // 0: This requests JSBSim not to output any messages
669 // 1: This value explicity requests the normal JSBSim
671 // 2: This value asks for a message to be printed out when
672 // a class is instantiated
673 // 4: When this value is set, a message is displayed when a
674 // FGModel object executes its Run() method
675 // 8: When this value is set, various runtime state variables
676 // are printed out periodically
677 // 16: When set various parameters are sanity checked and
678 // a message is printed out when they go out of bounds
680 void FGPropulsion::Debug(int from)
682 if (debug_lvl <= 0) return;
684 if (debug_lvl & 1) { // Standard console startup message output
685 if (from == 0) { // Constructor
689 if (debug_lvl & 2 ) { // Instantiation/Destruction notification
690 if (from == 0) cout << "Instantiated: FGPropulsion" << endl;
691 if (from == 1) cout << "Destroyed: FGPropulsion" << endl;
693 if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
695 if (debug_lvl & 8 ) { // Runtime state variables
697 if (debug_lvl & 16) { // Sanity checking
699 if (debug_lvl & 64) {
700 if (from == 0) { // Constructor
701 cout << IdSrc << endl;
702 cout << IdHdr << endl;