]> git.mxchange.org Git - flightgear.git/blob - src/FDM/JSBSim/FGPropulsion.cpp
Latest round of JSBSim updates.
[flightgear.git] / src / FDM / JSBSim / FGPropulsion.cpp
1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2
3  Module:       FGPropulsion.cpp
4  Author:       Jon S. Berndt
5  Date started: 08/20/00
6  Purpose:      Encapsulates the set of engines, tanks, and thrusters associated
7                with this aircraft
8
9  ------------- Copyright (C) 2000  Jon S. Berndt (jsb@hal-pc.org) -------------
10
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
14  version.
15
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
19  details.
20
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.
24
25  Further information about the GNU General Public License can also be found on
26  the world wide web at http://www.gnu.org.
27
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:
35
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.
39
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.
46
47 HISTORY
48 --------------------------------------------------------------------------------
49 08/20/00   JSB   Created
50
51 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
52 INCLUDES
53 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
54
55 #include "FGPropulsion.h"
56
57 static const char *IdSrc = "$Id$";
58 static const char *IdHdr = ID_PROPULSION;
59
60 extern short debug_lvl;
61
62 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
63 CLASS IMPLEMENTATION
64 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
65
66
67 FGPropulsion::FGPropulsion(FGFDMExec* exec) : FGModel(exec)
68 {
69   Name = "FGPropulsion";
70   numSelectedFuelTanks = numSelectedOxiTanks = 0;
71   numTanks = numEngines = numThrusters = 0;
72   numOxiTanks = numFuelTanks = 0;
73   Forces  = new FGColumnVector(3);
74   Moments = new FGColumnVector(3);
75
76   if (debug_lvl & 2) cout << "Instantiated: " << Name << endl;
77 }
78
79 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
80
81 FGPropulsion::~FGPropulsion()
82 {
83   for (unsigned int i=0; i<Engines.size(); i++) delete Engines[i];
84   Engines.clear();
85   if (Forces) delete Forces;
86   if (Moments) delete Moments;
87   if (debug_lvl & 2) cout << "Destroyed:    FGPropulsion" << endl;
88 }
89
90 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
91
92 bool FGPropulsion::Run(void) {
93   float PowerAvailable;
94   dt = State->Getdt();
95
96   Forces->InitMatrix();
97   Moments->InitMatrix();
98
99   if (!FGModel::Run()) {
100     for (unsigned int i=0; i<numEngines; i++) {
101       Thrusters[i]->SetdeltaT(dt*rate);
102       PowerAvailable = Engines[i]->Calculate(Thrusters[i]->GetPowerRequired());
103       Thrusters[i]->Calculate(PowerAvailable);
104       *Forces  += Thrusters[i]->GetBodyForces();  // sum body frame forces
105       *Moments += Thrusters[i]->GetMoments();     // sum body frame moments
106     }
107
108     return false;
109   } else {
110     return true;
111   }
112 }
113
114 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
115
116 bool FGPropulsion::GetSteadyState(void) {
117   float PowerAvailable;
118   float currentThrust = 0, lastThrust=-1;
119   dt = State->Getdt();
120
121   Forces->InitMatrix();
122   Moments->InitMatrix();
123
124   if (!FGModel::Run()) {
125     for (unsigned int i=0; i<numEngines; i++) {
126       Engines[i]->SetTrimMode(true);
127       Thrusters[i]->SetdeltaT(dt*rate);
128       while (pow(currentThrust - lastThrust, 2.0) > currentThrust*0.00010) {
129         PowerAvailable = Engines[i]->Calculate(Thrusters[i]->GetPowerRequired());
130         lastThrust = currentThrust;
131         currentThrust = Thrusters[i]->Calculate(PowerAvailable);
132       }
133       *Forces  += Thrusters[i]->GetBodyForces();  // sum body frame forces
134       *Moments += Thrusters[i]->GetMoments();     // sum body frame moments
135       Engines[i]->SetTrimMode(false);
136     }
137
138     return false;
139   } else {
140     return true;
141   }
142 }
143
144 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
145
146 bool FGPropulsion::LoadPropulsion(FGConfigFile* AC_cfg)
147 {
148   string token, fullpath;
149   string engineFileName, engType;
150   string thrusterFileName, thrType;
151   string parameter;
152   string enginePath = FDMExec->GetEnginePath();
153   float xLoc, yLoc, zLoc, Pitch, Yaw;
154   int Feed;
155
156 # ifndef macintosh
157       fullpath = enginePath + "/";
158 # else
159       fullpath = enginePath + ";";
160 # endif
161
162   AC_cfg->GetNextConfigLine();
163
164   while ((token = AC_cfg->GetValue()) != "/PROPULSION") {
165
166     if (token == "AC_ENGINE") {                   // ============ READING ENGINES
167
168       engineFileName = AC_cfg->GetValue("FILE");
169
170       cout << "\n    Reading engine from file: " << fullpath
171                                                    + engineFileName + ".xml"<< endl;
172       FGConfigFile Eng_cfg(fullpath + engineFileName + ".xml");
173
174       if (Eng_cfg.IsOpen()) {
175         Eng_cfg.GetNextConfigLine();
176         engType = Eng_cfg.GetValue();
177
178         FCS->AddThrottle();
179
180         if (engType == "FG_ROCKET") {
181           Engines.push_back(new FGRocket(FDMExec, &Eng_cfg));
182         } else if (engType == "FG_PISTON") {
183           Engines.push_back(new FGPiston(FDMExec, &Eng_cfg));
184         } else if (engType == "FG_TURBOJET") {
185           Engines.push_back(new FGTurboJet(FDMExec, &Eng_cfg));
186         } else if (engType == "FG_TURBOSHAFT") {
187           Engines.push_back(new FGTurboShaft(FDMExec, &Eng_cfg));
188         } else if (engType == "FG_TURBOPROP") {
189           Engines.push_back(new FGTurboProp(FDMExec, &Eng_cfg));
190         } else {
191           cerr << "    Unrecognized engine type: " << engType << " found in config file.\n";
192         }
193
194         AC_cfg->GetNextConfigLine();
195         while ((token = AC_cfg->GetValue()) != "/AC_ENGINE") {
196           *AC_cfg >> token;
197           if (token == "XLOC") { *AC_cfg >> xLoc; cout << "      X = " << xLoc << endl;}
198           else if (token == "YLOC") { *AC_cfg >> yLoc; cout << "      Y = " << yLoc << endl;}
199           else if (token == "ZLOC") { *AC_cfg >> zLoc; cout << "      Z = " << zLoc << endl;}
200           else if (token == "PITCH") { *AC_cfg >> Pitch; cout << "      Pitch = " << Pitch << endl;}
201           else if (token == "YAW") { *AC_cfg >> Yaw; cout << "      Yaw = " << Yaw << endl;}
202           else if (token == "FEED") {
203             *AC_cfg >> Feed;
204             Engines[numEngines]->AddFeedTank(Feed);
205             cout << "      Feed tank: " << Feed << endl;
206           } else cerr << "Unknown identifier: " << token << " in engine file: "
207                                                         << engineFileName << endl;
208         }
209         
210         Engines[numEngines]->SetPlacement(xLoc, yLoc, zLoc, Pitch, Yaw);
211         numEngines++;
212
213       } else {
214       
215         cerr << "Could not read engine config file: " << fullpath
216                                                   + engineFileName + ".xml" << endl;
217         return false;
218       }
219
220     } else if (token == "AC_TANK") {              // ============== READING TANKS
221
222       cout << "\n    Reading tank definition" << endl;
223       Tanks.push_back(new FGTank(AC_cfg));
224       switch(Tanks[numTanks]->GetType()) {
225       case FGTank::ttFUEL:
226         numSelectedFuelTanks++;
227         numFuelTanks++;
228         break;
229       case FGTank::ttOXIDIZER:
230         numSelectedOxiTanks++;
231         numOxiTanks++;
232         break;
233       }
234       
235       numTanks++;
236
237     } else if (token == "AC_THRUSTER") {          // ========== READING THRUSTERS
238
239       thrusterFileName = AC_cfg->GetValue("FILE");
240
241       cout << "\n    Reading thruster from file: " <<
242                                        fullpath + thrusterFileName + ".xml" << endl;
243       FGConfigFile Thruster_cfg(fullpath + thrusterFileName + ".xml");
244
245       if (Thruster_cfg.IsOpen()) {
246         Thruster_cfg.GetNextConfigLine();
247         thrType = Thruster_cfg.GetValue();
248
249         if (thrType == "FG_PROPELLER") {
250           Thrusters.push_back(new FGPropeller(FDMExec, &Thruster_cfg));
251         } else if (thrType == "FG_NOZZLE") {
252           Thrusters.push_back(new FGNozzle(FDMExec, &Thruster_cfg));
253         }
254
255         AC_cfg->GetNextConfigLine();
256         while ((token = AC_cfg->GetValue()) != "/AC_THRUSTER") {
257           *AC_cfg >> token;
258           if (token == "XLOC") *AC_cfg >> xLoc;
259           else if (token == "YLOC") *AC_cfg >> yLoc;
260           else if (token == "ZLOC") *AC_cfg >> zLoc;
261           else if (token == "PITCH") *AC_cfg >> Pitch;
262           else if (token == "YAW") *AC_cfg >> Yaw;
263           else cerr << "Unknown identifier: " << token << " in engine file: "
264                                                         << engineFileName << endl;
265         }
266
267         Thrusters[numThrusters]->SetLocation(xLoc, yLoc, zLoc);
268         Thrusters[numThrusters]->SetAnglesToBody(0, Pitch, Yaw);
269         Thrusters[numThrusters]->SetdeltaT(dt*rate);
270
271         numThrusters++;
272
273       } else {
274         cerr << "Could not read thruster config file: " << fullpath
275                                                 + thrusterFileName + ".xml" << endl;
276         return false;
277       }
278
279     }
280     AC_cfg->GetNextConfigLine();
281   }
282
283   return true;
284 }
285
286 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
287
288 void FGPropulsion::Debug(void)
289 {
290     //TODO: Add your source code here
291 }
292