]> git.mxchange.org Git - flightgear.git/blob - src/FDM/JSBSim/FGEngine.cpp
Expose the strut compression.
[flightgear.git] / src / FDM / JSBSim / FGEngine.cpp
1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2
3  Module:       FGEngine.cpp
4  Author:       Jon Berndt
5  Date started: 01/21/99
6  Called by:    FGAircraft
7
8  ------------- Copyright (C) 1999  Jon S. Berndt (jsb@hal-pc.org) -------------
9
10  This program is free software; you can redistribute it and/or modify it under
11  the terms of the GNU General Public License as published by the Free Software
12  Foundation; either version 2 of the License, or (at your option) any later
13  version.
14
15  This program is distributed in the hope that it will be useful, but WITHOUT
16  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
18  details.
19
20  You should have received a copy of the GNU General Public License along with
21  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
22  Place - Suite 330, Boston, MA  02111-1307, USA.
23
24  Further information about the GNU General Public License can also be found on
25  the world wide web at http://www.gnu.org.
26
27 FUNCTIONAL DESCRIPTION
28 --------------------------------------------------------------------------------
29 See header file.
30
31 HISTORY
32 --------------------------------------------------------------------------------
33 01/21/99   JSB   Created
34 09/03/99   JSB   Changed Rocket thrust equation to correct -= Thrust instead of
35                  += Thrust (thanks to Tony Peden)
36
37 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
38 INCLUDES
39 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
40
41 #ifdef FGFS
42 #  include <simgear/compiler.h>
43 #  ifdef SG_HAVE_STD_INCLUDES
44 #    include <fstream>
45 #  else
46 #    include <fstream.h>
47 #  endif
48 #else
49 #  if defined(sgi) && !defined(__GNUC__) && (_COMPILER_VERSION < 740)
50 #    include <fstream.h>
51 #  else
52 #    include <fstream>
53 #  endif
54 #endif
55
56 #include "FGEngine.h"
57 #include "FGTank.h"
58 #include "FGPropeller.h"
59 #include "FGNozzle.h"
60
61 namespace JSBSim {
62
63 static const char *IdSrc = "$Id$";
64 static const char *IdHdr = ID_ENGINE;
65
66 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
67 CLASS IMPLEMENTATION
68 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
69
70
71 FGEngine::FGEngine(FGFDMExec* exec, int engine_number) : EngineNumber(engine_number)
72 {
73   Name = "";
74   Type = etUnknown;
75   X = Y = Z = 0.0;
76   EnginePitch = EngineYaw = 0.0;
77   SLFuelFlowMax = SLOxiFlowMax = 0.0;
78   MaxThrottle = 1.0;
79   MinThrottle = 0.0;
80   Thrust = 0.0;
81   Throttle = 0.0;
82   Mixture = 1.0;
83   Starter = false;
84   FuelNeed = OxidizerNeed = 0.0;
85   Starved = Running = Cranking = false;
86   PctPower = 0.0;
87   TrimMode = false;
88   FuelFlow_gph = 0.0;
89   FuelFlow_pph = 0.0;
90   FuelFreeze = false;
91
92   FDMExec = exec;
93   State = FDMExec->GetState();
94   Atmosphere = FDMExec->GetAtmosphere();
95   FCS = FDMExec->GetFCS();
96   Propulsion = FDMExec->GetPropulsion();
97   Aircraft = FDMExec->GetAircraft();
98   Propagate = FDMExec->GetPropagate();
99   Auxiliary = FDMExec->GetAuxiliary();
100   Output = FDMExec->GetOutput();
101
102   PropertyManager = FDMExec->GetPropertyManager();
103   
104   char property_name[80];
105   snprintf(property_name, 80, "propulsion/engine[%u]/thrust", EngineNumber);
106   PropertyManager->Tie( property_name, &Thrust);
107   
108   Debug(0);
109 }
110
111 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
112
113 FGEngine::~FGEngine()
114 {
115   if (Thruster) delete Thruster;
116
117   char property_name[80];
118   snprintf(property_name, 80, "propulsion/engine[%u]/thrust", EngineNumber);
119   PropertyManager->Untie( property_name);
120   
121   Debug(1);
122 }
123
124 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
125 // This base class function should be called from within the
126 // derived class' Calculate() function before any other calculations are done.
127 // This base class method removes fuel from the fuel tanks as appropriate,
128 // and sets the starved flag if necessary.
129
130 void FGEngine::ConsumeFuel(void)
131 {
132   if (FuelFreeze) return;
133   unsigned int i;
134   double Fshortage, Oshortage, TanksWithFuel, TanksWithOxidizer;
135   FGTank* Tank;
136   bool haveOxTanks = false;
137
138   if (TrimMode) return;
139   Fshortage = Oshortage = TanksWithFuel = TanksWithOxidizer = 0.0;
140
141   // count how many assigned tanks have fuel or oxidizer
142   for (i=0; i<SourceTanks.size(); i++) {
143     Tank = Propulsion->GetTank(SourceTanks[i]);
144     if (Tank->GetType() == FGTank::ttFUEL){
145       if (Tank->GetContents() > 0.0) {
146         ++TanksWithFuel;
147       }
148     } else if (Tank->GetType() == FGTank::ttOXIDIZER) {
149       haveOxTanks = true;
150       if (Tank->GetContents() > 0.0) {
151         ++TanksWithOxidizer;
152       }
153     }
154   }
155   if (!TanksWithFuel || (haveOxTanks && !TanksWithOxidizer)) return;
156
157   for (i=0; i<SourceTanks.size(); i++) {
158     Tank = Propulsion->GetTank(SourceTanks[i]);
159     if (Tank->GetType() == FGTank::ttFUEL) {
160        Fshortage += Tank->Drain(CalcFuelNeed()/TanksWithFuel);
161     } else if (Tank->GetType() == FGTank::ttOXIDIZER) {
162        Oshortage += Tank->Drain(CalcOxidizerNeed()/TanksWithOxidizer);
163     }
164   }
165
166   if (Fshortage < 0.00 || Oshortage < 0.00) Starved = true;
167   else Starved = false;
168 }
169
170 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
171
172 double FGEngine::CalcFuelNeed(void)
173 {
174   FuelNeed = SLFuelFlowMax*PctPower*State->Getdt()*Propulsion->GetRate();
175   return FuelNeed;
176 }
177
178 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
179
180 double FGEngine::CalcOxidizerNeed(void)
181 {
182   OxidizerNeed = SLOxiFlowMax*PctPower*State->Getdt()*Propulsion->GetRate();
183   return OxidizerNeed;
184 }
185
186 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
187
188 void FGEngine::SetPlacement(double x, double y, double z, double pitch, double yaw)
189 {
190   X = x;
191   Y = y;
192   Z = z;
193   EnginePitch = pitch;
194   EngineYaw = yaw;
195 }
196
197 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
198
199 void FGEngine::AddFeedTank(int tkID)
200 {
201   SourceTanks.push_back(tkID);
202 }
203
204 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
205
206 FGColumnVector3& FGEngine::GetBodyForces(void)
207 {
208   return Thruster->GetBodyForces();
209 }
210
211 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
212
213 FGColumnVector3& FGEngine::GetMoments(void)
214 {
215   return Thruster->GetMoments();
216 }
217
218 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
219
220 bool FGEngine::LoadThruster(FGConfigFile* AC_cfg)
221 {
222   string token, fullpath, localpath;
223   string thrType, engineFileName;
224   FGConfigFile* Cfg_ptr = 0;
225   double xLoc, yLoc, zLoc, Pitch, Yaw;
226   double P_Factor = 0, Sense = 0.0;
227   string enginePath = FDMExec->GetEnginePath();
228   string aircraftPath = FDMExec->GetAircraftPath();
229   thrusterFileName = AC_cfg->GetValue("FILE");
230
231 # ifndef macintosh
232       fullpath = enginePath + "/";
233       localpath = aircraftPath + "/"  + "/Engines/";
234 # else
235       fullpath = enginePath + ";";
236       localpath = aircraftPath + ";" + ";Engines;";
237 # endif
238
239   // Look in the Aircraft/Engines directory first
240   FGConfigFile Local_Thruster_cfg(localpath + thrusterFileName + ".xml");
241   FGConfigFile Thruster_cfg(fullpath + thrusterFileName + ".xml");
242
243   if (Local_Thruster_cfg.IsOpen()) {
244     Cfg_ptr = &Local_Thruster_cfg;
245     if (debug_lvl > 0) cout << "\n    Reading thruster from file: " << localpath
246                                       + thrusterFileName + ".xml"<< endl;
247   } else {
248     if (Thruster_cfg.IsOpen()) {
249       Cfg_ptr = &Thruster_cfg;
250       if (debug_lvl > 0) cout << "\n    Reading thruster from file: " << fullpath
251                                         + thrusterFileName + ".xml"<< endl;
252     }
253   }
254
255   if (Cfg_ptr) {
256     Cfg_ptr->GetNextConfigLine();
257     thrType = Cfg_ptr->GetValue();
258
259     if (thrType == "FG_PROPELLER") {
260       Thruster = new FGPropeller(FDMExec, Cfg_ptr, EngineNumber);
261     } else if (thrType == "FG_NOZZLE") {
262       Thruster = new FGNozzle(FDMExec, Cfg_ptr, EngineNumber);
263     } else if (thrType == "FG_DIRECT") {
264       Thruster = new FGThruster( FDMExec, Cfg_ptr, EngineNumber);
265     }
266
267     AC_cfg->GetNextConfigLine();
268     while ((token = AC_cfg->GetValue()) != string("/AC_THRUSTER")) {
269       *AC_cfg >> token;
270       if (token == "XLOC") *AC_cfg >> xLoc;
271       else if (token == "YLOC") *AC_cfg >> yLoc;
272       else if (token == "ZLOC") *AC_cfg >> zLoc;
273       else if (token == "PITCH") *AC_cfg >> Pitch;
274       else if (token == "YAW") *AC_cfg >> Yaw;
275       else if (token == "P_FACTOR") *AC_cfg >> P_Factor;
276       else if (token == "SENSE")   *AC_cfg >> Sense;
277       else cerr << "Unknown identifier: " << token << " in engine file: "
278                 << engineFileName << endl;
279     }
280
281     Thruster->SetLocation(xLoc, yLoc, zLoc);
282     Thruster->SetAnglesToBody(0, Pitch, Yaw);
283     if (thrType == "FG_PROPELLER" && P_Factor > 0.001) {
284       ((FGPropeller*)Thruster)->SetPFactor(P_Factor);
285       if (debug_lvl > 0) cout << "      P-Factor: " << P_Factor << endl;
286       ((FGPropeller*)Thruster)->SetSense(fabs(Sense)/Sense);
287       if (debug_lvl > 0) cout << "      Sense: " << Sense <<  endl;
288     }
289     Thruster->SetdeltaT(State->Getdt() * Propulsion->GetRate());
290     return true;
291   } else {
292
293     cerr << "Could not read thruster config file: " << fullpath
294               + thrusterFileName + ".xml" << endl;
295     return false;
296   }
297
298 }
299
300 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
301 //    The bitmasked value choices are as follows:
302 //    unset: In this case (the default) JSBSim would only print
303 //       out the normally expected messages, essentially echoing
304 //       the config files as they are read. If the environment
305 //       variable is not set, debug_lvl is set to 1 internally
306 //    0: This requests JSBSim not to output any messages
307 //       whatsoever.
308 //    1: This value explicity requests the normal JSBSim
309 //       startup messages
310 //    2: This value asks for a message to be printed out when
311 //       a class is instantiated
312 //    4: When this value is set, a message is displayed when a
313 //       FGModel object executes its Run() method
314 //    8: When this value is set, various runtime state variables
315 //       are printed out periodically
316 //    16: When set various parameters are sanity checked and
317 //       a message is printed out when they go out of bounds
318
319 void FGEngine::Debug(int from)
320 {
321   if (debug_lvl <= 0) return;
322
323   if (debug_lvl & 1) { // Standard console startup message output
324     if (from == 0) { // Constructor
325
326     }
327   }
328   if (debug_lvl & 2 ) { // Instantiation/Destruction notification
329     if (from == 0) cout << "Instantiated: FGEngine" << endl;
330     if (from == 1) cout << "Destroyed:    FGEngine" << endl;
331   }
332   if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
333   }
334   if (debug_lvl & 8 ) { // Runtime state variables
335   }
336   if (debug_lvl & 16) { // Sanity checking
337   }
338   if (debug_lvl & 64) {
339     if (from == 0) { // Constructor
340       cout << IdSrc << endl;
341       cout << IdHdr << endl;
342     }
343   }
344 }
345 }