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