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();
228 cout << engType << endl;
231 ThrottleAdded = true;
233 if (engType == "FG_ROCKET") {
234 Engines.push_back(new FGRocket(FDMExec, &Eng_cfg));
235 } else if (engType == "FG_PISTON") {
236 Engines.push_back(new FGPiston(FDMExec, &Eng_cfg));
237 } else if (engType == "FG_TURBINE") {
238 Engines.push_back(new FGTurbine(FDMExec, &Eng_cfg));
240 cerr << fgred << " Unrecognized engine type: " << underon << engType
241 << underoff << " found in config file." << fgdef << endl;
245 AC_cfg->GetNextConfigLine();
246 while ((token = AC_cfg->GetValue()) != string("/AC_ENGINE")) {
248 if (token == "XLOC") { *AC_cfg >> xLoc; }
249 else if (token == "YLOC") { *AC_cfg >> yLoc; }
250 else if (token == "ZLOC") { *AC_cfg >> zLoc; }
251 else if (token == "PITCH") { *AC_cfg >> Pitch;}
252 else if (token == "YAW") { *AC_cfg >> Yaw;}
253 else if (token == "FEED") {
255 Engines[numEngines]->AddFeedTank(Feed);
256 if (debug_lvl > 0) cout << " Feed tank: " << Feed << endl;
257 } else cerr << "Unknown identifier: " << token << " in engine file: "
258 << engineFileName << endl;
262 cout << " X = " << xLoc << endl;
263 cout << " Y = " << yLoc << endl;
264 cout << " Z = " << zLoc << endl;
265 cout << " Pitch = " << Pitch << endl;
266 cout << " Yaw = " << Yaw << endl;
269 Engines[numEngines]->SetPlacement(xLoc, yLoc, zLoc, Pitch, Yaw);
270 Engines[numEngines]->SetEngineNumber(numEngines);
275 cerr << fgred << "\n Could not read engine config file: " << underon <<
276 fullpath + engineFileName + ".xml" << underoff << fgdef << endl;
280 } else if (token == "AC_TANK") { // ============== READING TANKS
282 if (debug_lvl > 0) cout << "\n Reading tank definition" << endl;
283 Tanks.push_back(new FGTank(AC_cfg));
284 switch(Tanks[numTanks]->GetType()) {
286 numSelectedFuelTanks++;
289 case FGTank::ttOXIDIZER:
290 numSelectedOxiTanks++;
297 } else if (token == "AC_THRUSTER") { // ========== READING THRUSTERS
299 thrusterFileName = AC_cfg->GetValue("FILE");
301 if (debug_lvl > 0) cout << "\n Reading thruster from file: " <<
302 fullpath + thrusterFileName + ".xml" << endl;
303 FGConfigFile Thruster_cfg(fullpath + thrusterFileName + ".xml");
305 if (Thruster_cfg.IsOpen()) {
306 Thruster_cfg.GetNextConfigLine();
307 thrType = Thruster_cfg.GetValue();
309 if (thrType == "FG_PROPELLER") {
310 Thrusters.push_back(new FGPropeller(FDMExec, &Thruster_cfg));
311 } else if (thrType == "FG_NOZZLE") {
312 Thrusters.push_back(new FGNozzle(FDMExec, &Thruster_cfg ));
313 } else if (thrType == "FG_DIRECT") {
314 Thrusters.push_back(new FGThruster( 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::etTurbine:
382 PropulsionStrings += "INVALID ENGINE TYPE";
386 PropulsionStrings += ", ";
388 FGPropeller* Propeller = (FGPropeller*)Thrusters[i];
389 switch(Thrusters[i]->GetType()) {
390 case FGThruster::ttNozzle:
391 PropulsionStrings += (Thrusters[i]->GetName() + "_Thrust[" + buffer + "]");
393 case FGThruster::ttRotor:
395 case FGThruster::ttPropeller:
396 PropulsionStrings += (Thrusters[i]->GetName() + "_Torque[" + buffer + "], ");
397 PropulsionStrings += (Thrusters[i]->GetName() + "_PFactor_Roll[" + buffer + "], ");
398 PropulsionStrings += (Thrusters[i]->GetName() + "_PFactor_Pitch[" + buffer + "], ");
399 PropulsionStrings += (Thrusters[i]->GetName() + "_PFactor_Yaw[" + buffer + "], ");
400 PropulsionStrings += (Thrusters[i]->GetName() + "_Thrust[" + buffer + "], ");
401 if (Propeller->IsVPitch())
402 PropulsionStrings += (Thrusters[i]->GetName() + "_Pitch[" + buffer + "], ");
403 PropulsionStrings += (Thrusters[i]->GetName() + "_RPM[" + buffer + "]");
406 PropulsionStrings += "INVALID THRUSTER TYPE";
411 return PropulsionStrings;
414 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
416 string FGPropulsion::GetPropulsionValues(void)
419 string PropulsionValues = "";
420 bool firstime = true;
422 for (unsigned int i=0;i<Engines.size();i++) {
423 if (firstime) firstime = false;
424 else PropulsionValues += ", ";
426 switch(Engines[i]->GetType()) {
427 case FGEngine::etPiston:
428 PropulsionValues += (string(gcvt(((FGPiston*)Engines[i])->GetPowerAvailable(), 10, buff)));
430 case FGEngine::etRocket:
431 PropulsionValues += (string(gcvt(((FGRocket*)Engines[i])->GetChamberPressure(), 10, buff)));
433 case FGEngine::etTurbine:
437 PropulsionValues += ", ";
439 switch(Thrusters[i]->GetType()) {
440 case FGThruster::ttNozzle:
441 PropulsionValues += (string(gcvt(((FGNozzle*)Thrusters[i])->GetThrust(), 10, buff)));
443 case FGThruster::ttRotor:
445 case FGThruster::ttPropeller:
446 FGPropeller* Propeller = (FGPropeller*)Thrusters[i];
447 FGColumnVector3 vPFactor = Propeller->GetPFactor();
448 PropulsionValues += string(gcvt(Propeller->GetTorque(), 10, buff)) + ", ";
449 PropulsionValues += string(gcvt(vPFactor(eRoll), 10, buff)) + ", ";
450 PropulsionValues += string(gcvt(vPFactor(ePitch), 10, buff)) + ", ";
451 PropulsionValues += string(gcvt(vPFactor(eYaw), 10, buff)) + ", ";
452 PropulsionValues += string(gcvt(Propeller->GetThrust(), 10, buff)) + ", ";
453 if (Propeller->IsVPitch())
454 PropulsionValues += string(gcvt(Propeller->GetPitch(), 10, buff)) + ", ";
455 PropulsionValues += string(gcvt(Propeller->GetRPM(), 10, buff));
460 return PropulsionValues;
463 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
465 FGColumnVector3& FGPropulsion::GetTanksMoment(void)
467 iTank = Tanks.begin();
468 vXYZtank.InitMatrix();
469 while (iTank < Tanks.end()) {
470 vXYZtank(eX) += (*iTank)->GetX()*(*iTank)->GetContents();
471 vXYZtank(eY) += (*iTank)->GetY()*(*iTank)->GetContents();
472 vXYZtank(eZ) += (*iTank)->GetZ()*(*iTank)->GetContents();
478 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
480 double FGPropulsion::GetTanksWeight(void)
484 iTank = Tanks.begin();
485 while (iTank < Tanks.end()) {
486 Tw += (*iTank)->GetContents();
492 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
494 double FGPropulsion::GetTanksIxx(const FGColumnVector3& vXYZcg)
497 iTank = Tanks.begin();
498 while (iTank < Tanks.end()) {
499 I += ((*iTank)->GetX() - vXYZcg(eX))*((*iTank)->GetX() - vXYZcg(eX)) * (*iTank)->GetContents()/(144.0*Inertial->gravity());
505 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
507 double FGPropulsion::GetTanksIyy(const FGColumnVector3& vXYZcg)
510 iTank = Tanks.begin();
511 while (iTank < Tanks.end()) {
512 I += ((*iTank)->GetY() - vXYZcg(eY))*((*iTank)->GetY() - vXYZcg(eY)) * (*iTank)->GetContents()/(144.0*Inertial->gravity());
518 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
520 double FGPropulsion::GetTanksIzz(const FGColumnVector3& vXYZcg)
523 iTank = Tanks.begin();
524 while (iTank < Tanks.end()) {
525 I += ((*iTank)->GetZ() - vXYZcg(eZ))*((*iTank)->GetZ() - vXYZcg(eZ)) * (*iTank)->GetContents()/(144.0*Inertial->gravity());
531 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
533 double FGPropulsion::GetTanksIxz(const FGColumnVector3& vXYZcg)
536 iTank = Tanks.begin();
537 while (iTank < Tanks.end()) {
538 I += ((*iTank)->GetX() - vXYZcg(eX))*((*iTank)->GetZ() - vXYZcg(eZ)) * (*iTank)->GetContents()/(144.0*Inertial->gravity());
544 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
546 double FGPropulsion::GetTanksIxy(const FGColumnVector3& vXYZcg)
549 iTank = Tanks.begin();
550 while (iTank != Tanks.end()) {
551 I += ((*iTank)->GetX() - vXYZcg(eX))*((*iTank)->GetY() - vXYZcg(eY)) * (*iTank)->GetContents()/(144.0*Inertial->gravity());
557 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
559 void FGPropulsion::SetMagnetos(int setting)
561 if (ActiveEngine == -1) {
562 for (unsigned i=0; i<Engines.size(); i++) {
563 Engines[i]->SetMagnetos(setting);
566 Engines[ActiveEngine]->SetMagnetos(setting);
570 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
572 void FGPropulsion::SetStarter(int setting)
574 if (ActiveEngine == -1) {
575 for (unsigned i=0; i<Engines.size(); i++) {
576 Engines[i]->SetStarter(setting);
580 Engines[ActiveEngine]->SetStarter(false);
582 Engines[ActiveEngine]->SetStarter(true);
586 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
588 void FGPropulsion::SetActiveEngine(int engine)
590 if ( unsigned(engine) > Engines.size())
593 ActiveEngine = engine;
596 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
598 void FGPropulsion::bind(void)
600 typedef double (FGPropulsion::*PMF)(int) const;
601 typedef int (FGPropulsion::*iPMF)(void) const;
602 /* PropertyManager->Tie("propulsion/num-engines", this,
603 &FGPropulsion::GetNumEngines);
604 PropertyManager->Tie("propulsion/num-tanks", this,
605 &FGPropulsion::GetNumTanks); */
607 PropertyManager->Tie("propulsion/magneto_cmd", this,
609 &FGPropulsion::SetMagnetos,
611 PropertyManager->Tie("propulsion/starter_cmd", this,
613 &FGPropulsion::SetStarter,
615 PropertyManager->Tie("propulsion/active_engine", this,
617 &FGPropulsion::SetActiveEngine,
620 PropertyManager->Tie("propulsion/num-sel-fuel-tanks", this,
621 &FGPropulsion::GetnumSelectedFuelTanks);
622 PropertyManager->Tie("propulsion/num-sel-ox-tanks", this,
623 &FGPropulsion::GetnumSelectedOxiTanks);
624 PropertyManager->Tie("forces/fbx-prop-lbs", this,1,
625 (PMF)&FGPropulsion::GetForces);
626 PropertyManager->Tie("forces/fby-prop-lbs", this,2,
627 (PMF)&FGPropulsion::GetForces);
628 PropertyManager->Tie("forces/fbz-prop-lbs", this,3,
629 (PMF)&FGPropulsion::GetForces);
630 PropertyManager->Tie("moments/l-prop-lbsft", this,1,
631 (PMF)&FGPropulsion::GetMoments);
632 PropertyManager->Tie("moments/m-prop-lbsft", this,2,
633 (PMF)&FGPropulsion::GetMoments);
634 PropertyManager->Tie("moments/n-prop-lbsft", this,3,
635 (PMF)&FGPropulsion::GetMoments);
636 //PropertyManager->Tie("propulsion/tanks-weight-lbs", this,
637 // &FGPropulsion::GetTanksWeight);
640 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
642 void FGPropulsion::unbind(void)
644 /* PropertyManager->Untie("propulsion/num-engines");
645 PropertyManager->Untie("propulsion/num-tanks"); */
646 PropertyManager->Untie("propulsion/num-sel-fuel-tanks");
647 PropertyManager->Untie("propulsion/num-sel-ox-tanks");
648 PropertyManager->Untie("propulsion/magneto_cmd");
649 PropertyManager->Untie("propulsion/starter_cmd");
650 PropertyManager->Untie("propulsion/active_engine");
651 PropertyManager->Untie("forces/fbx-prop-lbs");
652 PropertyManager->Untie("forces/fby-prop-lbs");
653 PropertyManager->Untie("forces/fbz-prop-lbs");
654 PropertyManager->Untie("moments/l-prop-lbsft");
655 PropertyManager->Untie("moments/m-prop-lbsft");
656 PropertyManager->Untie("moments/n-prop-lbsft");
657 //PropertyManager->Untie("propulsion/tanks-weight-lbs");
660 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
661 // The bitmasked value choices are as follows:
662 // unset: In this case (the default) JSBSim would only print
663 // out the normally expected messages, essentially echoing
664 // the config files as they are read. If the environment
665 // variable is not set, debug_lvl is set to 1 internally
666 // 0: This requests JSBSim not to output any messages
668 // 1: This value explicity requests the normal JSBSim
670 // 2: This value asks for a message to be printed out when
671 // a class is instantiated
672 // 4: When this value is set, a message is displayed when a
673 // FGModel object executes its Run() method
674 // 8: When this value is set, various runtime state variables
675 // are printed out periodically
676 // 16: When set various parameters are sanity checked and
677 // a message is printed out when they go out of bounds
679 void FGPropulsion::Debug(int from)
681 if (debug_lvl <= 0) return;
683 if (debug_lvl & 1) { // Standard console startup message output
684 if (from == 0) { // Constructor
688 if (debug_lvl & 2 ) { // Instantiation/Destruction notification
689 if (from == 0) cout << "Instantiated: FGPropulsion" << endl;
690 if (from == 1) cout << "Destroyed: FGPropulsion" << endl;
692 if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
694 if (debug_lvl & 8 ) { // Runtime state variables
696 if (debug_lvl & 16) { // Sanity checking
698 if (debug_lvl & 64) {
699 if (from == 0) { // Constructor
700 cout << IdSrc << endl;
701 cout << IdHdr << endl;