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_TURBOJET") {
237 Engines.push_back(new FGTurboJet(FDMExec, &Eng_cfg));
238 } else if (engType == "FG_TURBOSHAFT") {
239 Engines.push_back(new FGTurboShaft(FDMExec, &Eng_cfg));
240 } else if (engType == "FG_TURBOPROP") {
241 Engines.push_back(new FGTurboProp(FDMExec, &Eng_cfg));
243 cerr << fgred << " Unrecognized engine type: " << underon << engType
244 << underoff << " found in config file." << fgdef << endl;
248 AC_cfg->GetNextConfigLine();
249 while ((token = AC_cfg->GetValue()) != string("/AC_ENGINE")) {
251 if (token == "XLOC") { *AC_cfg >> xLoc; }
252 else if (token == "YLOC") { *AC_cfg >> yLoc; }
253 else if (token == "ZLOC") { *AC_cfg >> zLoc; }
254 else if (token == "PITCH") { *AC_cfg >> Pitch;}
255 else if (token == "YAW") { *AC_cfg >> Yaw;}
256 else if (token == "FEED") {
258 Engines[numEngines]->AddFeedTank(Feed);
259 if (debug_lvl > 0) cout << " Feed tank: " << Feed << endl;
260 } else cerr << "Unknown identifier: " << token << " in engine file: "
261 << engineFileName << endl;
265 cout << " X = " << xLoc << endl;
266 cout << " Y = " << yLoc << endl;
267 cout << " Z = " << zLoc << endl;
268 cout << " Pitch = " << Pitch << endl;
269 cout << " Yaw = " << Yaw << endl;
272 Engines[numEngines]->SetPlacement(xLoc, yLoc, zLoc, Pitch, Yaw);
273 Engines[numEngines]->SetEngineNumber(numEngines);
278 cerr << fgred << "\n Could not read engine config file: " << underon <<
279 fullpath + engineFileName + ".xml" << underoff << fgdef << endl;
283 } else if (token == "AC_TANK") { // ============== READING TANKS
285 if (debug_lvl > 0) cout << "\n Reading tank definition" << endl;
286 Tanks.push_back(new FGTank(AC_cfg));
287 switch(Tanks[numTanks]->GetType()) {
289 numSelectedFuelTanks++;
292 case FGTank::ttOXIDIZER:
293 numSelectedOxiTanks++;
300 } else if (token == "AC_THRUSTER") { // ========== READING THRUSTERS
302 thrusterFileName = AC_cfg->GetValue("FILE");
304 if (debug_lvl > 0) cout << "\n Reading thruster from file: " <<
305 fullpath + thrusterFileName + ".xml" << endl;
306 FGConfigFile Thruster_cfg(fullpath + thrusterFileName + ".xml");
308 if (Thruster_cfg.IsOpen()) {
309 Thruster_cfg.GetNextConfigLine();
310 thrType = Thruster_cfg.GetValue();
312 if (thrType == "FG_PROPELLER") {
313 Thrusters.push_back(new FGPropeller(FDMExec, &Thruster_cfg));
314 } else if (thrType == "FG_NOZZLE") {
315 Thrusters.push_back(new FGNozzle(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 + "]");
381 PropulsionStrings += "INVALID ENGINE TYPE";
385 PropulsionStrings += ", ";
387 FGPropeller* Propeller = (FGPropeller*)Thrusters[i];
388 switch(Thrusters[i]->GetType()) {
389 case FGThruster::ttNozzle:
390 PropulsionStrings += (Thrusters[i]->GetName() + "_Thrust[" + buffer + "]");
392 case FGThruster::ttRotor:
394 case FGThruster::ttPropeller:
395 PropulsionStrings += (Thrusters[i]->GetName() + "_Torque[" + buffer + "], ");
396 PropulsionStrings += (Thrusters[i]->GetName() + "_PFactor_Roll[" + buffer + "], ");
397 PropulsionStrings += (Thrusters[i]->GetName() + "_PFactor_Pitch[" + buffer + "], ");
398 PropulsionStrings += (Thrusters[i]->GetName() + "_PFactor_Yaw[" + buffer + "], ");
399 PropulsionStrings += (Thrusters[i]->GetName() + "_Thrust[" + buffer + "], ");
400 if (Propeller->IsVPitch())
401 PropulsionStrings += (Thrusters[i]->GetName() + "_Pitch[" + buffer + "], ");
402 PropulsionStrings += (Thrusters[i]->GetName() + "_RPM[" + buffer + "]");
405 PropulsionStrings += "INVALID THRUSTER TYPE";
410 return PropulsionStrings;
413 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
415 string FGPropulsion::GetPropulsionValues(void)
418 string PropulsionValues = "";
419 bool firstime = true;
421 for (unsigned int i=0;i<Engines.size();i++) {
422 if (firstime) firstime = false;
423 else PropulsionValues += ", ";
425 switch(Engines[i]->GetType()) {
426 case FGEngine::etPiston:
427 PropulsionValues += (string(gcvt(((FGPiston*)Engines[i])->GetPowerAvailable(), 10, buff)));
429 case FGEngine::etRocket:
430 PropulsionValues += (string(gcvt(((FGRocket*)Engines[i])->GetChamberPressure(), 10, buff)));
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;