]> git.mxchange.org Git - flightgear.git/blob - src/FDM/JSBSim/FGPropulsion.cpp
Latest JSBSim updates.
[flightgear.git] / src / FDM / JSBSim / FGPropulsion.cpp
1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
2 \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
7                with this aircraft\r
8 \r
9  ------------- Copyright (C) 2000  Jon S. Berndt (jsb@hal-pc.org) -------------\r
10 \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
14  version.\r
15 \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
19  details.\r
20 \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
24 \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
27 \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
35 \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
39 \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
46 \r
47 HISTORY\r
48 --------------------------------------------------------------------------------\r
49 08/20/00   JSB   Created\r
50 \r
51 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
52 INCLUDES\r
53 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
54 \r
55 #include "FGPropulsion.h"\r
56 #include "FGPropertyManager.h"\r
57 \r
58 \r
59 static const char *IdSrc = "$Id$";\r
60 static const char *IdHdr = ID_PROPULSION;\r
61 \r
62 extern short debug_lvl;\r
63 \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
69     return buf;\r
70 }\r
71 #endif\r
72 \r
73 \r
74 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
75 CLASS IMPLEMENTATION\r
76 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
77 \r
78 FGPropulsion::FGPropulsion(FGFDMExec* exec) : FGModel(exec)\r
79 {\r
80   Name = "FGPropulsion";\r
81   numSelectedFuelTanks = numSelectedOxiTanks = 0;\r
82   numTanks = numEngines = numThrusters = 0;\r
83   numOxiTanks = numFuelTanks = 0;\r
84   dt = 0.0;\r
85   ActiveEngine = -1; // -1: ALL, 0: Engine 1, 1: Engine 2 ...\r
86   bind();\r
87   Debug(0);\r
88 }\r
89 \r
90 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
91 \r
92 FGPropulsion::~FGPropulsion()\r
93 {\r
94   for (unsigned int i=0; i<Engines.size(); i++) delete Engines[i];\r
95   Engines.clear();\r
96   unbind();\r
97   Debug(1);\r
98 }\r
99 \r
100 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
101 \r
102 bool FGPropulsion::Run(void)\r
103 {\r
104   double PowerAvailable;\r
105   dt = State->Getdt();\r
106 \r
107   vForces.InitMatrix();\r
108   vMoments.InitMatrix();\r
109 \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
117     }\r
118     return false;\r
119   } else {\r
120     return true;\r
121   }\r
122 }\r
123 \r
124 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
125 \r
126 bool FGPropulsion::GetSteadyState(void)\r
127 {\r
128   double PowerAvailable;\r
129   double currentThrust = 0, lastThrust=-1;\r
130   dt = State->Getdt();\r
131   int steady_count,j=0;\r
132   bool steady=false;\r
133 \r
134   vForces.InitMatrix();\r
135   vMoments.InitMatrix();\r
136 \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
141       steady=false;\r
142       steady_count=0;\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
148           steady_count++;\r
149           if (steady_count > 120) { steady=true; }\r
150         } else {\r
151           steady_count=0;\r
152         }\r
153         j++;    \r
154       }\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
158     }\r
159 \r
160     return false;\r
161   } else {\r
162     return true;\r
163   }\r
164 }\r
165 \r
166 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
167 \r
168 bool FGPropulsion::ICEngineStart(void)\r
169 {\r
170   double PowerAvailable;\r
171   int j;\r
172   dt = State->Getdt();\r
173 \r
174   vForces.InitMatrix();\r
175   vMoments.InitMatrix();\r
176     \r
177   for (unsigned int i=0; i<numEngines; i++) {\r
178     Engines[i]->SetTrimMode(true);\r
179     Thrusters[i]->SetdeltaT(dt*rate);\r
180     j=0;\r
181     while (!Engines[i]->GetRunning() && j < 2000) {\r
182       PowerAvailable = Engines[i]->Calculate(Thrusters[i]->GetPowerRequired());\r
183       Thrusters[i]->Calculate(PowerAvailable);\r
184       j++;    \r
185     }\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
189   }\r
190   return true;\r
191 }\r
192 \r
193 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
194 \r
195 bool FGPropulsion::Load(FGConfigFile* AC_cfg)\r
196 {\r
197   string token, fullpath;\r
198   string engineFileName, engType;\r
199   string thrusterFileName, thrType;\r
200   string parameter;\r
201   string enginePath = FDMExec->GetEnginePath();\r
202   double xLoc, yLoc, zLoc, Pitch, Yaw;\r
203   double P_Factor = 0, Sense = 0.0;\r
204   int Feed;\r
205   bool ThrottleAdded = false;\r
206 \r
207 # ifndef macintosh\r
208       fullpath = enginePath + "/";\r
209 # else\r
210       fullpath = enginePath + ";";\r
211 # endif\r
212 \r
213   AC_cfg->GetNextConfigLine();\r
214 \r
215   while ((token = AC_cfg->GetValue()) != string("/PROPULSION")) {\r
216 \r
217     if (token == "AC_ENGINE") {                   // ============ READING ENGINES\r
218 \r
219       engineFileName = AC_cfg->GetValue("FILE");\r
220 \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
224 \r
225       if (Eng_cfg.IsOpen()) {\r
226         Eng_cfg.GetNextConfigLine();\r
227         engType = Eng_cfg.GetValue();\r
228 \r
229         FCS->AddThrottle();\r
230         ThrottleAdded = true;\r
231 \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
242         } else {\r
243           cerr << fgred << "    Unrecognized engine type: " << underon << engType\r
244                     << underoff << " found in config file." << fgdef << endl;\r
245           return false;\r
246         }\r
247 \r
248         AC_cfg->GetNextConfigLine();\r
249         while ((token = AC_cfg->GetValue()) != string("/AC_ENGINE")) {\r
250           *AC_cfg >> token;\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
257             *AC_cfg >> 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
262         }\r
263 \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
270         }\r
271 \r
272         Engines[numEngines]->SetPlacement(xLoc, yLoc, zLoc, Pitch, Yaw);\r
273         Engines[numEngines]->SetEngineNumber(numEngines);\r
274         numEngines++;\r
275 \r
276       } else {\r
277 \r
278         cerr << fgred << "\n  Could not read engine config file: " << underon <<\r
279                     fullpath + engineFileName + ".xml" << underoff << fgdef << endl;\r
280         return false;\r
281       }\r
282 \r
283     } else if (token == "AC_TANK") {              // ============== READING TANKS\r
284 \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
290         numFuelTanks++;\r
291         break;\r
292       case FGTank::ttOXIDIZER:\r
293         numSelectedOxiTanks++;\r
294         numOxiTanks++;\r
295         break;\r
296       }\r
297 \r
298       numTanks++;\r
299 \r
300     } else if (token == "AC_THRUSTER") {          // ========== READING THRUSTERS\r
301 \r
302       thrusterFileName = AC_cfg->GetValue("FILE");\r
303 \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
307 \r
308       if (Thruster_cfg.IsOpen()) {\r
309         Thruster_cfg.GetNextConfigLine();\r
310         thrType = Thruster_cfg.GetValue();\r
311 \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
316         }\r
317 \r
318         AC_cfg->GetNextConfigLine();\r
319         while ((token = AC_cfg->GetValue()) != string("/AC_THRUSTER")) {\r
320           *AC_cfg >> token;\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
330         }\r
331 \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
339         }\r
340         Thrusters[numThrusters]->SetdeltaT(dt*rate);\r
341         Thrusters[numThrusters]->SetThrusterNumber(numThrusters);\r
342         numThrusters++;\r
343 \r
344       } else {\r
345         cerr << "Could not read thruster config file: " << fullpath\r
346                                                 + thrusterFileName + ".xml" << endl;\r
347         return false;\r
348       }\r
349 \r
350     }\r
351     AC_cfg->GetNextConfigLine();\r
352   }\r
353 \r
354   if (!ThrottleAdded) FCS->AddThrottle(); // need to have at least one throttle\r
355 \r
356   return true;\r
357 }\r
358 \r
359 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
360 \r
361 string FGPropulsion::GetPropulsionStrings(void)\r
362 {\r
363   string PropulsionStrings = "";\r
364   bool firstime = true;\r
365   char buffer[5];\r
366 \r
367   for (unsigned int i=0;i<Engines.size();i++) {\r
368     if (firstime)  firstime = false;\r
369     else           PropulsionStrings += ", ";\r
370 \r
371     sprintf(buffer, "%d", i);\r
372 \r
373     switch(Engines[i]->GetType()) {\r
374     case FGEngine::etPiston:\r
375       PropulsionStrings += (Engines[i]->GetName() + "_PwrAvail[" + buffer + "]");\r
376       break;\r
377     case FGEngine::etRocket:\r
378       PropulsionStrings += (Engines[i]->GetName() + "_ChamberPress[" + buffer + "]");\r
379       break;\r
380     case FGEngine::etTurboJet:\r
381     case FGEngine::etTurboProp:\r
382     case FGEngine::etTurboShaft:\r
383       break;\r
384     default:\r
385       PropulsionStrings += "INVALID ENGINE TYPE";\r
386       break;\r
387     }\r
388 \r
389     PropulsionStrings += ", ";\r
390 \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
395       break;\r
396     case FGThruster::ttRotor:\r
397       break;\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
407       break;\r
408     default:\r
409       PropulsionStrings += "INVALID THRUSTER TYPE";\r
410       break;\r
411     }    \r
412   }\r
413 \r
414   return PropulsionStrings;\r
415 }\r
416 \r
417 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
418 \r
419 string FGPropulsion::GetPropulsionValues(void)\r
420 {\r
421   char buff[20];\r
422   string PropulsionValues = "";\r
423   bool firstime = true;\r
424 \r
425   for (unsigned int i=0;i<Engines.size();i++) {\r
426     if (firstime)  firstime = false;\r
427     else           PropulsionValues += ", ";\r
428 \r
429     switch(Engines[i]->GetType()) {\r
430     case FGEngine::etPiston:\r
431       PropulsionValues += (string(gcvt(((FGPiston*)Engines[i])->GetPowerAvailable(), 10, buff)));\r
432       break;\r
433     case FGEngine::etRocket:\r
434       PropulsionValues += (string(gcvt(((FGRocket*)Engines[i])->GetChamberPressure(), 10, buff)));\r
435       break;\r
436     case FGEngine::etTurboJet:\r
437     case FGEngine::etTurboProp:\r
438     case FGEngine::etTurboShaft:\r
439       break;\r
440     }\r
441 \r
442     PropulsionValues += ", ";\r
443 \r
444     switch(Thrusters[i]->GetType()) {\r
445     case FGThruster::ttNozzle:\r
446       PropulsionValues += (string(gcvt(((FGNozzle*)Thrusters[i])->GetThrust(), 10, buff)));\r
447       break;\r
448     case FGThruster::ttRotor:\r
449       break;\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
461       break;\r
462     }\r
463   }\r
464 \r
465   return PropulsionValues;\r
466 }\r
467 \r
468 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
469 \r
470 FGColumnVector3& FGPropulsion::GetTanksMoment(void)\r
471 {\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
478     iTank++;\r
479   }\r
480   return vXYZtank;\r
481 }\r
482 \r
483 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
484 \r
485 double FGPropulsion::GetTanksWeight(void)\r
486 {\r
487   double Tw = 0.0;\r
488 \r
489   iTank = Tanks.begin();\r
490   while (iTank < Tanks.end()) {\r
491     Tw += (*iTank)->GetContents();\r
492     iTank++;\r
493   }\r
494   return Tw;\r
495 }\r
496 \r
497 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
498 \r
499 double FGPropulsion::GetTanksIxx(const FGColumnVector3& vXYZcg)\r
500 {\r
501   double I = 0.0;\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
505     iTank++;\r
506   }\r
507   return I;\r
508 }\r
509 \r
510 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
511 \r
512 double FGPropulsion::GetTanksIyy(const FGColumnVector3& vXYZcg)\r
513 {\r
514   double I = 0.0;\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
518     iTank++;\r
519   }\r
520   return I;\r
521 }\r
522 \r
523 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
524 \r
525 double FGPropulsion::GetTanksIzz(const FGColumnVector3& vXYZcg)\r
526 {\r
527   double I = 0.0;\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
531     iTank++;\r
532   }\r
533   return I;\r
534 }\r
535 \r
536 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
537 \r
538 double FGPropulsion::GetTanksIxz(const FGColumnVector3& vXYZcg)\r
539 {\r
540   double I = 0.0;\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
544     iTank++;\r
545   }\r
546   return I;\r
547 }\r
548 \r
549 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
550 \r
551 double FGPropulsion::GetTanksIxy(const FGColumnVector3& vXYZcg)\r
552 {\r
553   double I = 0.0;\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
557     iTank++;\r
558   }\r
559   return I;\r
560 }\r
561 \r
562 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
563 \r
564 void FGPropulsion::SetMagnetos(int setting)\r
565 {\r
566   if (ActiveEngine == -1) {\r
567     for (unsigned i=0; i<Engines.size(); i++) {\r
568       Engines[i]->SetMagnetos(setting);\r
569     }\r
570   } else {\r
571     Engines[ActiveEngine]->SetMagnetos(setting);\r
572   }\r
573 }\r
574 \r
575 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
576 \r
577 void FGPropulsion::SetStarter(int setting)\r
578 {\r
579   if (ActiveEngine == -1) {\r
580     for (unsigned i=0; i<Engines.size(); i++) {\r
581       Engines[i]->SetStarter(setting);\r
582     }\r
583   } else {\r
584     if (setting == 0)\r
585       Engines[ActiveEngine]->SetStarter(false);\r
586     else\r
587       Engines[ActiveEngine]->SetStarter(true);\r
588   }\r
589 }\r
590 \r
591 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
592 \r
593 void FGPropulsion::SetActiveEngine(int engine)\r
594 {\r
595   if ( unsigned(engine) > Engines.size())\r
596     ActiveEngine = -1;\r
597   else\r
598     ActiveEngine = engine;\r
599 }\r
600 \r
601 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
602 \r
603 void FGPropulsion::bind(void)\r
604 {\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
611 \r
612   PropertyManager->Tie("propulsion/magneto_cmd", this,\r
613                        (iPMF)0,\r
614                        &FGPropulsion::SetMagnetos,\r
615                        true);\r
616   PropertyManager->Tie("propulsion/starter_cmd", this,\r
617                        (iPMF)0,\r
618                        &FGPropulsion::SetStarter,\r
619                        true);\r
620   PropertyManager->Tie("propulsion/active_engine", this,\r
621                        (iPMF)0,\r
622                        &FGPropulsion::SetActiveEngine,\r
623                        true);\r
624 \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
643 }\r
644 \r
645 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
646 \r
647 void FGPropulsion::unbind(void)\r
648 {\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
663 }\r
664 \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
672 //       whatsoever.\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
683 \r
684 void FGPropulsion::Debug(int from)\r
685 {\r
686   if (debug_lvl <= 0) return;\r
687 \r
688   if (debug_lvl & 1) { // Standard console startup message output\r
689     if (from == 0) { // Constructor\r
690 \r
691     }\r
692   }\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
696   }\r
697   if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects\r
698   }\r
699   if (debug_lvl & 8 ) { // Runtime state variables\r
700   }\r
701   if (debug_lvl & 16) { // Sanity checking\r
702   }\r
703   if (debug_lvl & 64) {\r
704     if (from == 0) { // Constructor\r
705       cout << IdSrc << endl;\r
706       cout << IdHdr << endl;\r
707     }\r
708   }\r
709 }\r
710 \r