1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
3 Module: FGPropulsion.cpp
\r
4 Author: Jon S. Berndt
\r
5 Date started: 08/20/00
\r
6 Purpose: Encapsulates the set of engines, tanks, and thrusters associated
\r
9 ------------- Copyright (C) 2000 Jon S. Berndt (jsb@hal-pc.org) -------------
\r
11 This program is free software; you can redistribute it and/or modify it under
\r
12 the terms of the GNU General Public License as published by the Free Software
\r
13 Foundation; either version 2 of the License, or (at your option) any later
\r
16 This program is distributed in the hope that it will be useful, but WITHOUT
\r
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
\r
18 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
\r
21 You should have received a copy of the GNU General Public License along with
\r
22 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
\r
23 Place - Suite 330, Boston, MA 02111-1307, USA.
\r
25 Further information about the GNU General Public License can also be found on
\r
26 the world wide web at http://www.gnu.org.
\r
28 FUNCTIONAL DESCRIPTION
\r
29 --------------------------------------------------------------------------------
\r
30 The Propulsion class is the container for the entire propulsion system, which is
\r
31 comprised of engines, tanks, and "thrusters" (the device that transforms the
\r
32 engine power into a force that acts on the aircraft, such as a nozzle or
\r
33 propeller). Once the Propulsion class gets the config file, it reads in
\r
34 information which is specific to a type of engine. Then:
\r
36 1) The appropriate engine type instance is created
\r
37 2) A thruster object is instantiated, and is linked to the engine
\r
38 3) At least one tank object is created, and is linked to an engine.
\r
40 At Run time each engines Calculate() method is called to return the excess power
\r
41 generated during that iteration. The drag from the previous iteration is sub-
\r
42 tracted to give the excess power available for thrust this pass. That quantity
\r
43 is passed to the thrusters associated with a particular engine - perhaps with a
\r
44 scaling mechanism (gearing?) to allow the engine to give its associated thrust-
\r
45 ers specific distributed portions of the excess power.
\r
48 --------------------------------------------------------------------------------
\r
49 08/20/00 JSB Created
\r
51 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
53 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
\r
55 #include "FGPropulsion.h"
\r
56 #include "FGPropertyManager.h"
\r
59 static const char *IdSrc = "$Id$";
\r
60 static const char *IdHdr = ID_PROPULSION;
\r
62 extern short debug_lvl;
\r
64 #if defined (__APPLE__)
\r
65 /* Not all systems have the gcvt function */
\r
66 inline char* gcvt (double value, int ndigits, char *buf) {
\r
67 /* note that this is not exactly what gcvt is supposed to do! */
\r
68 snprintf (buf, ndigits+1, "%f", value);
\r
74 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
75 CLASS IMPLEMENTATION
\r
76 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
\r
78 FGPropulsion::FGPropulsion(FGFDMExec* exec) : FGModel(exec)
\r
80 Name = "FGPropulsion";
\r
81 numSelectedFuelTanks = numSelectedOxiTanks = 0;
\r
82 numTanks = numEngines = numThrusters = 0;
\r
83 numOxiTanks = numFuelTanks = 0;
\r
85 ActiveEngine = -1; // -1: ALL, 0: Engine 1, 1: Engine 2 ...
\r
90 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
92 FGPropulsion::~FGPropulsion()
\r
94 for (unsigned int i=0; i<Engines.size(); i++) delete Engines[i];
\r
100 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
102 bool FGPropulsion::Run(void)
\r
104 double PowerAvailable;
\r
105 dt = State->Getdt();
\r
107 vForces.InitMatrix();
\r
108 vMoments.InitMatrix();
\r
110 if (!FGModel::Run()) {
\r
111 for (unsigned int i=0; i<numEngines; i++) {
\r
112 Thrusters[i]->SetdeltaT(dt*rate);
\r
113 PowerAvailable = Engines[i]->Calculate(Thrusters[i]->GetPowerRequired());
\r
114 Thrusters[i]->Calculate(PowerAvailable);
\r
115 vForces += Thrusters[i]->GetBodyForces(); // sum body frame forces
\r
116 vMoments += Thrusters[i]->GetMoments(); // sum body frame moments
\r
124 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
126 bool FGPropulsion::GetSteadyState(void)
\r
128 double PowerAvailable;
\r
129 double currentThrust = 0, lastThrust=-1;
\r
130 dt = State->Getdt();
\r
131 int steady_count,j=0;
\r
134 vForces.InitMatrix();
\r
135 vMoments.InitMatrix();
\r
137 if (!FGModel::Run()) {
\r
138 for (unsigned int i=0; i<numEngines; i++) {
\r
139 Engines[i]->SetTrimMode(true);
\r
140 Thrusters[i]->SetdeltaT(dt*rate);
\r
143 while (!steady && j < 6000) {
\r
144 PowerAvailable = Engines[i]->Calculate(Thrusters[i]->GetPowerRequired());
\r
145 lastThrust = currentThrust;
\r
146 currentThrust = Thrusters[i]->Calculate(PowerAvailable);
\r
147 if (fabs(lastThrust-currentThrust) < 0.0001) {
\r
149 if (steady_count > 120) { steady=true; }
\r
155 vForces += Thrusters[i]->GetBodyForces(); // sum body frame forces
\r
156 vMoments += Thrusters[i]->GetMoments(); // sum body frame moments
\r
157 Engines[i]->SetTrimMode(false);
\r
166 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
168 bool FGPropulsion::ICEngineStart(void)
\r
170 double PowerAvailable;
\r
172 dt = State->Getdt();
\r
174 vForces.InitMatrix();
\r
175 vMoments.InitMatrix();
\r
177 for (unsigned int i=0; i<numEngines; i++) {
\r
178 Engines[i]->SetTrimMode(true);
\r
179 Thrusters[i]->SetdeltaT(dt*rate);
\r
181 while (!Engines[i]->GetRunning() && j < 2000) {
\r
182 PowerAvailable = Engines[i]->Calculate(Thrusters[i]->GetPowerRequired());
\r
183 Thrusters[i]->Calculate(PowerAvailable);
\r
186 vForces += Thrusters[i]->GetBodyForces(); // sum body frame forces
\r
187 vMoments += Thrusters[i]->GetMoments(); // sum body frame moments
\r
188 Engines[i]->SetTrimMode(false);
\r
193 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
195 bool FGPropulsion::Load(FGConfigFile* AC_cfg)
\r
197 string token, fullpath;
\r
198 string engineFileName, engType;
\r
199 string thrusterFileName, thrType;
\r
201 string enginePath = FDMExec->GetEnginePath();
\r
202 double xLoc, yLoc, zLoc, Pitch, Yaw;
\r
203 double P_Factor = 0, Sense = 0.0;
\r
205 bool ThrottleAdded = false;
\r
208 fullpath = enginePath + "/";
\r
210 fullpath = enginePath + ";";
\r
213 AC_cfg->GetNextConfigLine();
\r
215 while ((token = AC_cfg->GetValue()) != string("/PROPULSION")) {
\r
217 if (token == "AC_ENGINE") { // ============ READING ENGINES
\r
219 engineFileName = AC_cfg->GetValue("FILE");
\r
221 if (debug_lvl > 0) cout << "\n Reading engine from file: " << fullpath
\r
222 + engineFileName + ".xml"<< endl;
\r
223 FGConfigFile Eng_cfg(fullpath + engineFileName + ".xml");
\r
225 if (Eng_cfg.IsOpen()) {
\r
226 Eng_cfg.GetNextConfigLine();
\r
227 engType = Eng_cfg.GetValue();
\r
229 FCS->AddThrottle();
\r
230 ThrottleAdded = true;
\r
232 if (engType == "FG_ROCKET") {
\r
233 Engines.push_back(new FGRocket(FDMExec, &Eng_cfg));
\r
234 } else if (engType == "FG_PISTON") {
\r
235 Engines.push_back(new FGPiston(FDMExec, &Eng_cfg));
\r
236 } else if (engType == "FG_TURBOJET") {
\r
237 Engines.push_back(new FGTurboJet(FDMExec, &Eng_cfg));
\r
238 } else if (engType == "FG_TURBOSHAFT") {
\r
239 Engines.push_back(new FGTurboShaft(FDMExec, &Eng_cfg));
\r
240 } else if (engType == "FG_TURBOPROP") {
\r
241 Engines.push_back(new FGTurboProp(FDMExec, &Eng_cfg));
\r
243 cerr << fgred << " Unrecognized engine type: " << underon << engType
\r
244 << underoff << " found in config file." << fgdef << endl;
\r
248 AC_cfg->GetNextConfigLine();
\r
249 while ((token = AC_cfg->GetValue()) != string("/AC_ENGINE")) {
\r
251 if (token == "XLOC") { *AC_cfg >> xLoc; }
\r
252 else if (token == "YLOC") { *AC_cfg >> yLoc; }
\r
253 else if (token == "ZLOC") { *AC_cfg >> zLoc; }
\r
254 else if (token == "PITCH") { *AC_cfg >> Pitch;}
\r
255 else if (token == "YAW") { *AC_cfg >> Yaw;}
\r
256 else if (token == "FEED") {
\r
258 Engines[numEngines]->AddFeedTank(Feed);
\r
259 if (debug_lvl > 0) cout << " Feed tank: " << Feed << endl;
\r
260 } else cerr << "Unknown identifier: " << token << " in engine file: "
\r
261 << engineFileName << endl;
\r
264 if (debug_lvl > 0) {
\r
265 cout << " X = " << xLoc << endl;
\r
266 cout << " Y = " << yLoc << endl;
\r
267 cout << " Z = " << zLoc << endl;
\r
268 cout << " Pitch = " << Pitch << endl;
\r
269 cout << " Yaw = " << Yaw << endl;
\r
272 Engines[numEngines]->SetPlacement(xLoc, yLoc, zLoc, Pitch, Yaw);
\r
273 Engines[numEngines]->SetEngineNumber(numEngines);
\r
278 cerr << fgred << "\n Could not read engine config file: " << underon <<
\r
279 fullpath + engineFileName + ".xml" << underoff << fgdef << endl;
\r
283 } else if (token == "AC_TANK") { // ============== READING TANKS
\r
285 if (debug_lvl > 0) cout << "\n Reading tank definition" << endl;
\r
286 Tanks.push_back(new FGTank(AC_cfg));
\r
287 switch(Tanks[numTanks]->GetType()) {
\r
288 case FGTank::ttFUEL:
\r
289 numSelectedFuelTanks++;
\r
292 case FGTank::ttOXIDIZER:
\r
293 numSelectedOxiTanks++;
\r
300 } else if (token == "AC_THRUSTER") { // ========== READING THRUSTERS
\r
302 thrusterFileName = AC_cfg->GetValue("FILE");
\r
304 if (debug_lvl > 0) cout << "\n Reading thruster from file: " <<
\r
305 fullpath + thrusterFileName + ".xml" << endl;
\r
306 FGConfigFile Thruster_cfg(fullpath + thrusterFileName + ".xml");
\r
308 if (Thruster_cfg.IsOpen()) {
\r
309 Thruster_cfg.GetNextConfigLine();
\r
310 thrType = Thruster_cfg.GetValue();
\r
312 if (thrType == "FG_PROPELLER") {
\r
313 Thrusters.push_back(new FGPropeller(FDMExec, &Thruster_cfg));
\r
314 } else if (thrType == "FG_NOZZLE") {
\r
315 Thrusters.push_back(new FGNozzle(FDMExec, &Thruster_cfg));
\r
318 AC_cfg->GetNextConfigLine();
\r
319 while ((token = AC_cfg->GetValue()) != string("/AC_THRUSTER")) {
\r
321 if (token == "XLOC") *AC_cfg >> xLoc;
\r
322 else if (token == "YLOC") *AC_cfg >> yLoc;
\r
323 else if (token == "ZLOC") *AC_cfg >> zLoc;
\r
324 else if (token == "PITCH") *AC_cfg >> Pitch;
\r
325 else if (token == "YAW") *AC_cfg >> Yaw;
\r
326 else if (token == "P_FACTOR") *AC_cfg >> P_Factor;
\r
327 else if (token == "SENSE") *AC_cfg >> Sense;
\r
328 else cerr << "Unknown identifier: " << token << " in engine file: "
\r
329 << engineFileName << endl;
\r
332 Thrusters[numThrusters]->SetLocation(xLoc, yLoc, zLoc);
\r
333 Thrusters[numThrusters]->SetAnglesToBody(0, Pitch, Yaw);
\r
334 if (thrType == "FG_PROPELLER" && P_Factor > 0.001) {
\r
335 ((FGPropeller*)Thrusters[numThrusters])->SetPFactor(P_Factor);
\r
336 if (debug_lvl > 0) cout << " P-Factor: " << P_Factor << endl;
\r
337 ((FGPropeller*)Thrusters[numThrusters])->SetSense(fabs(Sense)/Sense);
\r
338 if (debug_lvl > 0) cout << " Sense: " << Sense << endl;
\r
340 Thrusters[numThrusters]->SetdeltaT(dt*rate);
\r
341 Thrusters[numThrusters]->SetThrusterNumber(numThrusters);
\r
345 cerr << "Could not read thruster config file: " << fullpath
\r
346 + thrusterFileName + ".xml" << endl;
\r
351 AC_cfg->GetNextConfigLine();
\r
354 if (!ThrottleAdded) FCS->AddThrottle(); // need to have at least one throttle
\r
359 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
361 string FGPropulsion::GetPropulsionStrings(void)
\r
363 string PropulsionStrings = "";
\r
364 bool firstime = true;
\r
367 for (unsigned int i=0;i<Engines.size();i++) {
\r
368 if (firstime) firstime = false;
\r
369 else PropulsionStrings += ", ";
\r
371 sprintf(buffer, "%d", i);
\r
373 switch(Engines[i]->GetType()) {
\r
374 case FGEngine::etPiston:
\r
375 PropulsionStrings += (Engines[i]->GetName() + "_PwrAvail[" + buffer + "]");
\r
377 case FGEngine::etRocket:
\r
378 PropulsionStrings += (Engines[i]->GetName() + "_ChamberPress[" + buffer + "]");
\r
380 case FGEngine::etTurboJet:
\r
381 case FGEngine::etTurboProp:
\r
382 case FGEngine::etTurboShaft:
\r
385 PropulsionStrings += "INVALID ENGINE TYPE";
\r
389 PropulsionStrings += ", ";
\r
391 FGPropeller* Propeller = (FGPropeller*)Thrusters[i];
\r
392 switch(Thrusters[i]->GetType()) {
\r
393 case FGThruster::ttNozzle:
\r
394 PropulsionStrings += (Thrusters[i]->GetName() + "_Thrust[" + buffer + "]");
\r
396 case FGThruster::ttRotor:
\r
398 case FGThruster::ttPropeller:
\r
399 PropulsionStrings += (Thrusters[i]->GetName() + "_Torque[" + buffer + "], ");
\r
400 PropulsionStrings += (Thrusters[i]->GetName() + "_PFactor_Roll[" + buffer + "], ");
\r
401 PropulsionStrings += (Thrusters[i]->GetName() + "_PFactor_Pitch[" + buffer + "], ");
\r
402 PropulsionStrings += (Thrusters[i]->GetName() + "_PFactor_Yaw[" + buffer + "], ");
\r
403 PropulsionStrings += (Thrusters[i]->GetName() + "_Thrust[" + buffer + "], ");
\r
404 if (Propeller->IsVPitch())
\r
405 PropulsionStrings += (Thrusters[i]->GetName() + "_Pitch[" + buffer + "], ");
\r
406 PropulsionStrings += (Thrusters[i]->GetName() + "_RPM[" + buffer + "]");
\r
409 PropulsionStrings += "INVALID THRUSTER TYPE";
\r
414 return PropulsionStrings;
\r
417 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
419 string FGPropulsion::GetPropulsionValues(void)
\r
422 string PropulsionValues = "";
\r
423 bool firstime = true;
\r
425 for (unsigned int i=0;i<Engines.size();i++) {
\r
426 if (firstime) firstime = false;
\r
427 else PropulsionValues += ", ";
\r
429 switch(Engines[i]->GetType()) {
\r
430 case FGEngine::etPiston:
\r
431 PropulsionValues += (string(gcvt(((FGPiston*)Engines[i])->GetPowerAvailable(), 10, buff)));
\r
433 case FGEngine::etRocket:
\r
434 PropulsionValues += (string(gcvt(((FGRocket*)Engines[i])->GetChamberPressure(), 10, buff)));
\r
436 case FGEngine::etTurboJet:
\r
437 case FGEngine::etTurboProp:
\r
438 case FGEngine::etTurboShaft:
\r
442 PropulsionValues += ", ";
\r
444 switch(Thrusters[i]->GetType()) {
\r
445 case FGThruster::ttNozzle:
\r
446 PropulsionValues += (string(gcvt(((FGNozzle*)Thrusters[i])->GetThrust(), 10, buff)));
\r
448 case FGThruster::ttRotor:
\r
450 case FGThruster::ttPropeller:
\r
451 FGPropeller* Propeller = (FGPropeller*)Thrusters[i];
\r
452 FGColumnVector3 vPFactor = Propeller->GetPFactor();
\r
453 PropulsionValues += string(gcvt(Propeller->GetTorque(), 10, buff)) + ", ";
\r
454 PropulsionValues += string(gcvt(vPFactor(eRoll), 10, buff)) + ", ";
\r
455 PropulsionValues += string(gcvt(vPFactor(ePitch), 10, buff)) + ", ";
\r
456 PropulsionValues += string(gcvt(vPFactor(eYaw), 10, buff)) + ", ";
\r
457 PropulsionValues += string(gcvt(Propeller->GetThrust(), 10, buff)) + ", ";
\r
458 if (Propeller->IsVPitch())
\r
459 PropulsionValues += string(gcvt(Propeller->GetPitch(), 10, buff)) + ", ";
\r
460 PropulsionValues += string(gcvt(Propeller->GetRPM(), 10, buff));
\r
465 return PropulsionValues;
\r
468 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
470 FGColumnVector3& FGPropulsion::GetTanksMoment(void)
\r
472 iTank = Tanks.begin();
\r
473 vXYZtank.InitMatrix();
\r
474 while (iTank < Tanks.end()) {
\r
475 vXYZtank(eX) += (*iTank)->GetX()*(*iTank)->GetContents();
\r
476 vXYZtank(eY) += (*iTank)->GetY()*(*iTank)->GetContents();
\r
477 vXYZtank(eZ) += (*iTank)->GetZ()*(*iTank)->GetContents();
\r
483 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
485 double FGPropulsion::GetTanksWeight(void)
\r
489 iTank = Tanks.begin();
\r
490 while (iTank < Tanks.end()) {
\r
491 Tw += (*iTank)->GetContents();
\r
497 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
499 double FGPropulsion::GetTanksIxx(const FGColumnVector3& vXYZcg)
\r
502 iTank = Tanks.begin();
\r
503 while (iTank < Tanks.end()) {
\r
504 I += ((*iTank)->GetX() - vXYZcg(eX))*((*iTank)->GetX() - vXYZcg(eX)) * (*iTank)->GetContents()/(144.0*Inertial->gravity());
\r
510 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
512 double FGPropulsion::GetTanksIyy(const FGColumnVector3& vXYZcg)
\r
515 iTank = Tanks.begin();
\r
516 while (iTank < Tanks.end()) {
\r
517 I += ((*iTank)->GetY() - vXYZcg(eY))*((*iTank)->GetY() - vXYZcg(eY)) * (*iTank)->GetContents()/(144.0*Inertial->gravity());
\r
523 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
525 double FGPropulsion::GetTanksIzz(const FGColumnVector3& vXYZcg)
\r
528 iTank = Tanks.begin();
\r
529 while (iTank < Tanks.end()) {
\r
530 I += ((*iTank)->GetZ() - vXYZcg(eZ))*((*iTank)->GetZ() - vXYZcg(eZ)) * (*iTank)->GetContents()/(144.0*Inertial->gravity());
\r
536 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
538 double FGPropulsion::GetTanksIxz(const FGColumnVector3& vXYZcg)
\r
541 iTank = Tanks.begin();
\r
542 while (iTank < Tanks.end()) {
\r
543 I += ((*iTank)->GetX() - vXYZcg(eX))*((*iTank)->GetZ() - vXYZcg(eZ)) * (*iTank)->GetContents()/(144.0*Inertial->gravity());
\r
549 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
551 double FGPropulsion::GetTanksIxy(const FGColumnVector3& vXYZcg)
\r
554 iTank = Tanks.begin();
\r
555 while (iTank != Tanks.end()) {
\r
556 I += ((*iTank)->GetX() - vXYZcg(eX))*((*iTank)->GetY() - vXYZcg(eY)) * (*iTank)->GetContents()/(144.0*Inertial->gravity());
\r
562 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
564 void FGPropulsion::SetMagnetos(int setting)
\r
566 if (ActiveEngine == -1) {
\r
567 for (unsigned i=0; i<Engines.size(); i++) {
\r
568 Engines[i]->SetMagnetos(setting);
\r
571 Engines[ActiveEngine]->SetMagnetos(setting);
\r
575 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
577 void FGPropulsion::SetStarter(int setting)
\r
579 if (ActiveEngine == -1) {
\r
580 for (unsigned i=0; i<Engines.size(); i++) {
\r
581 Engines[i]->SetStarter(setting);
\r
585 Engines[ActiveEngine]->SetStarter(false);
\r
587 Engines[ActiveEngine]->SetStarter(true);
\r
591 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
593 void FGPropulsion::SetActiveEngine(int engine)
\r
595 if ( unsigned(engine) > Engines.size())
\r
598 ActiveEngine = engine;
\r
601 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
603 void FGPropulsion::bind(void)
\r
605 typedef double (FGPropulsion::*PMF)(int) const;
\r
606 typedef int (FGPropulsion::*iPMF)(void) const;
\r
607 /* PropertyManager->Tie("propulsion/num-engines", this,
\r
608 &FGPropulsion::GetNumEngines);
\r
609 PropertyManager->Tie("propulsion/num-tanks", this,
\r
610 &FGPropulsion::GetNumTanks); */
\r
612 PropertyManager->Tie("propulsion/magneto_cmd", this,
\r
614 &FGPropulsion::SetMagnetos,
\r
616 PropertyManager->Tie("propulsion/starter_cmd", this,
\r
618 &FGPropulsion::SetStarter,
\r
620 PropertyManager->Tie("propulsion/active_engine", this,
\r
622 &FGPropulsion::SetActiveEngine,
\r
625 PropertyManager->Tie("propulsion/num-sel-fuel-tanks", this,
\r
626 &FGPropulsion::GetnumSelectedFuelTanks);
\r
627 PropertyManager->Tie("propulsion/num-sel-ox-tanks", this,
\r
628 &FGPropulsion::GetnumSelectedOxiTanks);
\r
629 PropertyManager->Tie("forces/fbx-prop-lbs", this,1,
\r
630 (PMF)&FGPropulsion::GetForces);
\r
631 PropertyManager->Tie("forces/fby-prop-lbs", this,2,
\r
632 (PMF)&FGPropulsion::GetForces);
\r
633 PropertyManager->Tie("forces/fbz-prop-lbs", this,3,
\r
634 (PMF)&FGPropulsion::GetForces);
\r
635 PropertyManager->Tie("moments/l-prop-lbsft", this,1,
\r
636 (PMF)&FGPropulsion::GetMoments);
\r
637 PropertyManager->Tie("moments/m-prop-lbsft", this,2,
\r
638 (PMF)&FGPropulsion::GetMoments);
\r
639 PropertyManager->Tie("moments/n-prop-lbsft", this,3,
\r
640 (PMF)&FGPropulsion::GetMoments);
\r
641 //PropertyManager->Tie("propulsion/tanks-weight-lbs", this,
\r
642 // &FGPropulsion::GetTanksWeight);
\r
645 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
647 void FGPropulsion::unbind(void)
\r
649 /* PropertyManager->Untie("propulsion/num-engines");
\r
650 PropertyManager->Untie("propulsion/num-tanks"); */
\r
651 PropertyManager->Untie("propulsion/num-sel-fuel-tanks");
\r
652 PropertyManager->Untie("propulsion/num-sel-ox-tanks");
\r
653 PropertyManager->Untie("propulsion/magneto_cmd");
\r
654 PropertyManager->Untie("propulsion/starter_cmd");
\r
655 PropertyManager->Untie("propulsion/active_engine");
\r
656 PropertyManager->Untie("forces/fbx-prop-lbs");
\r
657 PropertyManager->Untie("forces/fby-prop-lbs");
\r
658 PropertyManager->Untie("forces/fbz-prop-lbs");
\r
659 PropertyManager->Untie("moments/l-prop-lbsft");
\r
660 PropertyManager->Untie("moments/m-prop-lbsft");
\r
661 PropertyManager->Untie("moments/n-prop-lbsft");
\r
662 //PropertyManager->Untie("propulsion/tanks-weight-lbs");
\r
665 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
666 // The bitmasked value choices are as follows:
\r
667 // unset: In this case (the default) JSBSim would only print
\r
668 // out the normally expected messages, essentially echoing
\r
669 // the config files as they are read. If the environment
\r
670 // variable is not set, debug_lvl is set to 1 internally
\r
671 // 0: This requests JSBSim not to output any messages
\r
673 // 1: This value explicity requests the normal JSBSim
\r
674 // startup messages
\r
675 // 2: This value asks for a message to be printed out when
\r
676 // a class is instantiated
\r
677 // 4: When this value is set, a message is displayed when a
\r
678 // FGModel object executes its Run() method
\r
679 // 8: When this value is set, various runtime state variables
\r
680 // are printed out periodically
\r
681 // 16: When set various parameters are sanity checked and
\r
682 // a message is printed out when they go out of bounds
\r
684 void FGPropulsion::Debug(int from)
\r
686 if (debug_lvl <= 0) return;
\r
688 if (debug_lvl & 1) { // Standard console startup message output
\r
689 if (from == 0) { // Constructor
\r
693 if (debug_lvl & 2 ) { // Instantiation/Destruction notification
\r
694 if (from == 0) cout << "Instantiated: FGPropulsion" << endl;
\r
695 if (from == 1) cout << "Destroyed: FGPropulsion" << endl;
\r
697 if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
\r
699 if (debug_lvl & 8 ) { // Runtime state variables
\r
701 if (debug_lvl & 16) { // Sanity checking
\r
703 if (debug_lvl & 64) {
\r
704 if (from == 0) { // Constructor
\r
705 cout << IdSrc << endl;
\r
706 cout << IdHdr << endl;
\r