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();
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));
239 } else if (engType == "FG_SIMTURBINE") {
240 Engines.push_back(new FGSimTurbine(FDMExec, &Eng_cfg));
242 cerr << fgred << " Unrecognized engine type: " << underon << engType
243 << underoff << " found in config file." << fgdef << endl;
247 AC_cfg->GetNextConfigLine();
248 while ((token = AC_cfg->GetValue()) != string("/AC_ENGINE")) {
250 if (token == "XLOC") { *AC_cfg >> xLoc; }
251 else if (token == "YLOC") { *AC_cfg >> yLoc; }
252 else if (token == "ZLOC") { *AC_cfg >> zLoc; }
253 else if (token == "PITCH") { *AC_cfg >> Pitch;}
254 else if (token == "YAW") { *AC_cfg >> Yaw;}
255 else if (token == "FEED") {
257 Engines[numEngines]->AddFeedTank(Feed);
258 if (debug_lvl > 0) cout << " Feed tank: " << Feed << endl;
259 } else cerr << "Unknown identifier: " << token << " in engine file: "
260 << engineFileName << endl;
264 cout << " X = " << xLoc << endl;
265 cout << " Y = " << yLoc << endl;
266 cout << " Z = " << zLoc << endl;
267 cout << " Pitch = " << Pitch << endl;
268 cout << " Yaw = " << Yaw << endl;
271 Engines[numEngines]->SetPlacement(xLoc, yLoc, zLoc, Pitch, Yaw);
272 Engines[numEngines]->SetEngineNumber(numEngines);
277 cerr << fgred << "\n Could not read engine config file: " << underon <<
278 fullpath + engineFileName + ".xml" << underoff << fgdef << endl;
282 } else if (token == "AC_TANK") { // ============== READING TANKS
284 if (debug_lvl > 0) cout << "\n Reading tank definition" << endl;
285 Tanks.push_back(new FGTank(AC_cfg));
286 switch(Tanks[numTanks]->GetType()) {
288 numSelectedFuelTanks++;
291 case FGTank::ttOXIDIZER:
292 numSelectedOxiTanks++;
299 } else if (token == "AC_THRUSTER") { // ========== READING THRUSTERS
301 thrusterFileName = AC_cfg->GetValue("FILE");
303 if (debug_lvl > 0) cout << "\n Reading thruster from file: " <<
304 fullpath + thrusterFileName + ".xml" << endl;
305 FGConfigFile Thruster_cfg(fullpath + thrusterFileName + ".xml");
307 if (Thruster_cfg.IsOpen()) {
308 Thruster_cfg.GetNextConfigLine();
309 thrType = Thruster_cfg.GetValue();
311 if (thrType == "FG_PROPELLER") {
312 Thrusters.push_back(new FGPropeller(FDMExec, &Thruster_cfg));
313 } else if (thrType == "FG_NOZZLE") {
314 Thrusters.push_back(new FGNozzle(FDMExec, &Thruster_cfg ));
315 } else if (thrType == "FG_DIRECT") {
316 Thrusters.push_back(new FGThruster( FDMExec, &Thruster_cfg) );
319 AC_cfg->GetNextConfigLine();
320 while ((token = AC_cfg->GetValue()) != string("/AC_THRUSTER")) {
322 if (token == "XLOC") *AC_cfg >> xLoc;
323 else if (token == "YLOC") *AC_cfg >> yLoc;
324 else if (token == "ZLOC") *AC_cfg >> zLoc;
325 else if (token == "PITCH") *AC_cfg >> Pitch;
326 else if (token == "YAW") *AC_cfg >> Yaw;
327 else if (token == "P_FACTOR") *AC_cfg >> P_Factor;
328 else if (token == "SENSE") *AC_cfg >> Sense;
329 else cerr << "Unknown identifier: " << token << " in engine file: "
330 << engineFileName << endl;
333 Thrusters[numThrusters]->SetLocation(xLoc, yLoc, zLoc);
334 Thrusters[numThrusters]->SetAnglesToBody(0, Pitch, Yaw);
335 if (thrType == "FG_PROPELLER" && P_Factor > 0.001) {
336 ((FGPropeller*)Thrusters[numThrusters])->SetPFactor(P_Factor);
337 if (debug_lvl > 0) cout << " P-Factor: " << P_Factor << endl;
338 ((FGPropeller*)Thrusters[numThrusters])->SetSense(fabs(Sense)/Sense);
339 if (debug_lvl > 0) cout << " Sense: " << Sense << endl;
341 Thrusters[numThrusters]->SetdeltaT(dt*rate);
342 Thrusters[numThrusters]->SetThrusterNumber(numThrusters);
346 cerr << "Could not read thruster config file: " << fullpath
347 + thrusterFileName + ".xml" << endl;
352 AC_cfg->GetNextConfigLine();
355 if (!ThrottleAdded) FCS->AddThrottle(); // need to have at least one throttle
360 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
362 string FGPropulsion::GetPropulsionStrings(void)
364 string PropulsionStrings = "";
365 bool firstime = true;
368 for (unsigned int i=0;i<Engines.size();i++) {
369 if (firstime) firstime = false;
370 else PropulsionStrings += ", ";
372 sprintf(buffer, "%d", i);
374 switch(Engines[i]->GetType()) {
375 case FGEngine::etPiston:
376 PropulsionStrings += (Engines[i]->GetName() + "_PwrAvail[" + buffer + "]");
378 case FGEngine::etRocket:
379 PropulsionStrings += (Engines[i]->GetName() + "_ChamberPress[" + buffer + "]");
381 case FGEngine::etTurbine:
383 case FGEngine::etSimTurbine:
386 PropulsionStrings += "INVALID ENGINE TYPE";
390 PropulsionStrings += ", ";
392 FGPropeller* Propeller = (FGPropeller*)Thrusters[i];
393 switch(Thrusters[i]->GetType()) {
394 case FGThruster::ttNozzle:
395 PropulsionStrings += (Thrusters[i]->GetName() + "_Thrust[" + buffer + "]");
397 case FGThruster::ttRotor:
399 case FGThruster::ttPropeller:
400 PropulsionStrings += (Thrusters[i]->GetName() + "_Torque[" + buffer + "], ");
401 PropulsionStrings += (Thrusters[i]->GetName() + "_PFactor_Roll[" + buffer + "], ");
402 PropulsionStrings += (Thrusters[i]->GetName() + "_PFactor_Pitch[" + buffer + "], ");
403 PropulsionStrings += (Thrusters[i]->GetName() + "_PFactor_Yaw[" + buffer + "], ");
404 PropulsionStrings += (Thrusters[i]->GetName() + "_Thrust[" + buffer + "], ");
405 if (Propeller->IsVPitch())
406 PropulsionStrings += (Thrusters[i]->GetName() + "_Pitch[" + buffer + "], ");
407 PropulsionStrings += (Thrusters[i]->GetName() + "_RPM[" + buffer + "]");
410 PropulsionStrings += "INVALID THRUSTER TYPE";
415 return PropulsionStrings;
418 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
420 string FGPropulsion::GetPropulsionValues(void)
423 string PropulsionValues = "";
424 bool firstime = true;
426 for (unsigned int i=0;i<Engines.size();i++) {
427 if (firstime) firstime = false;
428 else PropulsionValues += ", ";
430 switch(Engines[i]->GetType()) {
431 case FGEngine::etPiston:
432 PropulsionValues += (string(gcvt(((FGPiston*)Engines[i])->GetPowerAvailable(), 10, buff)));
434 case FGEngine::etRocket:
435 PropulsionValues += (string(gcvt(((FGRocket*)Engines[i])->GetChamberPressure(), 10, buff)));
437 case FGEngine::etTurbine:
439 case FGEngine::etSimTurbine:
443 PropulsionValues += ", ";
445 switch(Thrusters[i]->GetType()) {
446 case FGThruster::ttNozzle:
447 PropulsionValues += (string(gcvt(((FGNozzle*)Thrusters[i])->GetThrust(), 10, buff)));
449 case FGThruster::ttRotor:
451 case FGThruster::ttPropeller:
452 FGPropeller* Propeller = (FGPropeller*)Thrusters[i];
453 FGColumnVector3 vPFactor = Propeller->GetPFactor();
454 PropulsionValues += string(gcvt(Propeller->GetTorque(), 10, buff)) + ", ";
455 PropulsionValues += string(gcvt(vPFactor(eRoll), 10, buff)) + ", ";
456 PropulsionValues += string(gcvt(vPFactor(ePitch), 10, buff)) + ", ";
457 PropulsionValues += string(gcvt(vPFactor(eYaw), 10, buff)) + ", ";
458 PropulsionValues += string(gcvt(Propeller->GetThrust(), 10, buff)) + ", ";
459 if (Propeller->IsVPitch())
460 PropulsionValues += string(gcvt(Propeller->GetPitch(), 10, buff)) + ", ";
461 PropulsionValues += string(gcvt(Propeller->GetRPM(), 10, buff));
466 return PropulsionValues;
469 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
471 FGColumnVector3& FGPropulsion::GetTanksMoment(void)
473 iTank = Tanks.begin();
474 vXYZtank.InitMatrix();
475 while (iTank < Tanks.end()) {
476 vXYZtank(eX) += (*iTank)->GetX()*(*iTank)->GetContents();
477 vXYZtank(eY) += (*iTank)->GetY()*(*iTank)->GetContents();
478 vXYZtank(eZ) += (*iTank)->GetZ()*(*iTank)->GetContents();
484 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
486 double FGPropulsion::GetTanksWeight(void)
490 iTank = Tanks.begin();
491 while (iTank < Tanks.end()) {
492 Tw += (*iTank)->GetContents();
498 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
500 double FGPropulsion::GetTanksIxx(const FGColumnVector3& vXYZcg)
503 iTank = Tanks.begin();
504 while (iTank < Tanks.end()) {
505 I += ((*iTank)->GetX() - vXYZcg(eX))*((*iTank)->GetX() - vXYZcg(eX)) * (*iTank)->GetContents()/(144.0*Inertial->gravity());
511 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
513 double FGPropulsion::GetTanksIyy(const FGColumnVector3& vXYZcg)
516 iTank = Tanks.begin();
517 while (iTank < Tanks.end()) {
518 I += ((*iTank)->GetY() - vXYZcg(eY))*((*iTank)->GetY() - vXYZcg(eY)) * (*iTank)->GetContents()/(144.0*Inertial->gravity());
524 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
526 double FGPropulsion::GetTanksIzz(const FGColumnVector3& vXYZcg)
529 iTank = Tanks.begin();
530 while (iTank < Tanks.end()) {
531 I += ((*iTank)->GetZ() - vXYZcg(eZ))*((*iTank)->GetZ() - vXYZcg(eZ)) * (*iTank)->GetContents()/(144.0*Inertial->gravity());
537 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
539 double FGPropulsion::GetTanksIxz(const FGColumnVector3& vXYZcg)
542 iTank = Tanks.begin();
543 while (iTank < Tanks.end()) {
544 I += ((*iTank)->GetX() - vXYZcg(eX))*((*iTank)->GetZ() - vXYZcg(eZ)) * (*iTank)->GetContents()/(144.0*Inertial->gravity());
550 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
552 double FGPropulsion::GetTanksIxy(const FGColumnVector3& vXYZcg)
555 iTank = Tanks.begin();
556 while (iTank != Tanks.end()) {
557 I += ((*iTank)->GetX() - vXYZcg(eX))*((*iTank)->GetY() - vXYZcg(eY)) * (*iTank)->GetContents()/(144.0*Inertial->gravity());
563 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
565 void FGPropulsion::SetMagnetos(int setting)
567 if (ActiveEngine == -1) {
568 for (unsigned i=0; i<Engines.size(); i++) {
569 Engines[i]->SetMagnetos(setting);
572 Engines[ActiveEngine]->SetMagnetos(setting);
576 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
578 void FGPropulsion::SetStarter(int setting)
580 if (ActiveEngine == -1) {
581 for (unsigned i=0; i<Engines.size(); i++) {
582 Engines[i]->SetStarter(setting);
586 Engines[ActiveEngine]->SetStarter(false);
588 Engines[ActiveEngine]->SetStarter(true);
592 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
594 void FGPropulsion::SetActiveEngine(int engine)
596 if ( unsigned(engine) > Engines.size())
599 ActiveEngine = engine;
602 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
604 void FGPropulsion::bind(void)
606 typedef double (FGPropulsion::*PMF)(int) const;
607 typedef int (FGPropulsion::*iPMF)(void) const;
608 /* PropertyManager->Tie("propulsion/num-engines", this,
609 &FGPropulsion::GetNumEngines);
610 PropertyManager->Tie("propulsion/num-tanks", this,
611 &FGPropulsion::GetNumTanks); */
613 PropertyManager->Tie("propulsion/magneto_cmd", this,
615 &FGPropulsion::SetMagnetos,
617 PropertyManager->Tie("propulsion/starter_cmd", this,
619 &FGPropulsion::SetStarter,
621 PropertyManager->Tie("propulsion/active_engine", this,
623 &FGPropulsion::SetActiveEngine,
626 PropertyManager->Tie("propulsion/num-sel-fuel-tanks", this,
627 &FGPropulsion::GetnumSelectedFuelTanks);
628 PropertyManager->Tie("propulsion/num-sel-ox-tanks", this,
629 &FGPropulsion::GetnumSelectedOxiTanks);
630 PropertyManager->Tie("forces/fbx-prop-lbs", this,1,
631 (PMF)&FGPropulsion::GetForces);
632 PropertyManager->Tie("forces/fby-prop-lbs", this,2,
633 (PMF)&FGPropulsion::GetForces);
634 PropertyManager->Tie("forces/fbz-prop-lbs", this,3,
635 (PMF)&FGPropulsion::GetForces);
636 PropertyManager->Tie("moments/l-prop-lbsft", this,1,
637 (PMF)&FGPropulsion::GetMoments);
638 PropertyManager->Tie("moments/m-prop-lbsft", this,2,
639 (PMF)&FGPropulsion::GetMoments);
640 PropertyManager->Tie("moments/n-prop-lbsft", this,3,
641 (PMF)&FGPropulsion::GetMoments);
642 //PropertyManager->Tie("propulsion/tanks-weight-lbs", this,
643 // &FGPropulsion::GetTanksWeight);
646 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
648 void FGPropulsion::unbind(void)
650 /* PropertyManager->Untie("propulsion/num-engines");
651 PropertyManager->Untie("propulsion/num-tanks"); */
652 PropertyManager->Untie("propulsion/num-sel-fuel-tanks");
653 PropertyManager->Untie("propulsion/num-sel-ox-tanks");
654 PropertyManager->Untie("propulsion/magneto_cmd");
655 PropertyManager->Untie("propulsion/starter_cmd");
656 PropertyManager->Untie("propulsion/active_engine");
657 PropertyManager->Untie("forces/fbx-prop-lbs");
658 PropertyManager->Untie("forces/fby-prop-lbs");
659 PropertyManager->Untie("forces/fbz-prop-lbs");
660 PropertyManager->Untie("moments/l-prop-lbsft");
661 PropertyManager->Untie("moments/m-prop-lbsft");
662 PropertyManager->Untie("moments/n-prop-lbsft");
663 //PropertyManager->Untie("propulsion/tanks-weight-lbs");
666 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
667 // The bitmasked value choices are as follows:
668 // unset: In this case (the default) JSBSim would only print
669 // out the normally expected messages, essentially echoing
670 // the config files as they are read. If the environment
671 // variable is not set, debug_lvl is set to 1 internally
672 // 0: This requests JSBSim not to output any messages
674 // 1: This value explicity requests the normal JSBSim
676 // 2: This value asks for a message to be printed out when
677 // a class is instantiated
678 // 4: When this value is set, a message is displayed when a
679 // FGModel object executes its Run() method
680 // 8: When this value is set, various runtime state variables
681 // are printed out periodically
682 // 16: When set various parameters are sanity checked and
683 // a message is printed out when they go out of bounds
685 void FGPropulsion::Debug(int from)
687 if (debug_lvl <= 0) return;
689 if (debug_lvl & 1) { // Standard console startup message output
690 if (from == 0) { // Constructor
694 if (debug_lvl & 2 ) { // Instantiation/Destruction notification
695 if (from == 0) cout << "Instantiated: FGPropulsion" << endl;
696 if (from == 1) cout << "Destroyed: FGPropulsion" << endl;
698 if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
700 if (debug_lvl & 8 ) { // Runtime state variables
702 if (debug_lvl & 16) { // Sanity checking
704 if (debug_lvl & 64) {
705 if (from == 0) { // Constructor
706 cout << IdSrc << endl;
707 cout << IdHdr << endl;