Branch data Line data Source code
1 : : /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2 : :
3 : : Module: FGPropulsion.cpp
4 : : Author: Jon S. Berndt
5 : : Date started: 08/20/00
6 : : Purpose: Encapsulates the set of engines and tanks associated
7 : : with this aircraft
8 : :
9 : : ------------- Copyright (C) 2000 Jon S. Berndt (jon@jsbsim.org) -------------
10 : :
11 : : This program is free software; you can redistribute it and/or modify it under
12 : : the terms of the GNU Lesser 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 Lesser General Public License for more
19 : : details.
20 : :
21 : : You should have received a copy of the GNU Lesser 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 Lesser 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 and tanks. Once the Propulsion class gets the config file,
32 : : it reads in information which is specific to a type of engine. Then:
33 : :
34 : : 1) The appropriate engine type instance is created
35 : : 2) At least one tank object is created, and is linked to an engine.
36 : :
37 : : At Run time each engines Calculate() method is called.
38 : :
39 : : HISTORY
40 : : --------------------------------------------------------------------------------
41 : : 08/20/00 JSB Created
42 : :
43 : : %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
44 : : INCLUDES
45 : : %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
46 : :
47 : : #include "FGPropulsion.h"
48 : : #include "models/FGFCS.h"
49 : : #include "models/FGMassBalance.h"
50 : : #include "models/propulsion/FGThruster.h"
51 : : #include "models/propulsion/FGRocket.h"
52 : : #include "models/propulsion/FGTurbine.h"
53 : : #include "models/propulsion/FGPiston.h"
54 : : #include "models/propulsion/FGElectric.h"
55 : : #include "models/propulsion/FGTurboProp.h"
56 : : #include "models/propulsion/FGTank.h"
57 : : #include "input_output/FGPropertyManager.h"
58 : : #include "input_output/FGXMLParse.h"
59 : : #include "math/FGColumnVector3.h"
60 : : #include <iostream>
61 : : #include <sstream>
62 : : #include <cstdlib>
63 : :
64 : : using namespace std;
65 : :
66 : : namespace JSBSim {
67 : :
68 : : static const char *IdSrc = "$Id: FGPropulsion.cpp,v 1.39 2010/02/25 05:21:36 jberndt Exp $";
69 : : static const char *IdHdr = ID_PROPULSION;
70 : :
71 : : extern short debug_lvl;
72 : :
73 : :
74 : : /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
75 : : CLASS IMPLEMENTATION
76 : : %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
77 : :
78 : 2 : FGPropulsion::FGPropulsion(FGFDMExec* exec) : FGModel(exec)
79 : : {
80 : 1 : Name = "FGPropulsion";
81 : :
82 : 1 : InitializedEngines = 0;
83 : 1 : numSelectedFuelTanks = numSelectedOxiTanks = 0;
84 : 1 : numTanks = numEngines = 0;
85 : 1 : numOxiTanks = numFuelTanks = 0;
86 : 1 : ActiveEngine = -1; // -1: ALL, 0: Engine 1, 1: Engine 2 ...
87 : 1 : tankJ.InitMatrix();
88 : 1 : refuel = dump = false;
89 : 1 : DumpRate = 0.0;
90 : 1 : fuel_freeze = false;
91 : 1 : TotalFuelQuantity = 0.0;
92 : : IsBound =
93 : : HavePistonEngine =
94 : : HaveTurbineEngine =
95 : : HaveRocketEngine =
96 : : HaveTurboPropEngine =
97 : 1 : HaveElectricEngine = false;
98 : 1 : HasInitializedEngines = false;
99 : :
100 : 1 : Debug(0);
101 : 1 : }
102 : :
103 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
104 : :
105 : 1 : FGPropulsion::~FGPropulsion()
106 : : {
107 [ + - ][ + + ]: 13 : for (unsigned int i=0; i<Engines.size(); i++) delete Engines[i];
[ # # ][ # # ]
108 : 1 : Engines.clear();
109 [ + - ][ + + ]: 7 : for (unsigned int i=0; i<Tanks.size(); i++) delete Tanks[i];
[ # # ][ # # ]
110 : 1 : Tanks.clear();
111 : 1 : Debug(1);
112 : 2 : }
113 : :
114 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
115 : :
116 : 1 : bool FGPropulsion::InitModel(void)
117 : : {
118 [ - + ]: 1 : if (!FGModel::InitModel()) return false;
119 : :
120 [ - + ]: 1 : for (unsigned int i=0; i<numTanks; i++) Tanks[i]->ResetToIC();
121 : :
122 [ - + ]: 1 : for (unsigned int i=0; i<numEngines; i++) {
123 [ # # # ]: 0 : switch (Engines[i]->GetType()) {
124 : : case FGEngine::etPiston:
125 : 0 : ((FGPiston*)Engines[i])->ResetToIC();
126 [ # # ][ # # ]: 0 : if (HasInitializedEngines && (InitializedEngines & i)) InitRunning(i);
127 : : break;
128 : : case FGEngine::etTurbine:
129 : 0 : ((FGTurbine*)Engines[i])->ResetToIC();
130 [ # # ][ # # ]: 0 : if (HasInitializedEngines && (InitializedEngines & i)) InitRunning(i);
131 : : break;
132 : : default:
133 : : break;
134 : : }
135 : : }
136 : :
137 : 1 : return true;
138 : : }
139 : :
140 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
141 : :
142 : 54005 : bool FGPropulsion::Run(void)
143 : : {
144 : : unsigned int i;
145 : :
146 [ - + ]: 54005 : if (FGModel::Run()) return true;
147 [ - + ]: 54005 : if (FDMExec->Holding()) return false;
148 : :
149 : 54005 : RunPreFunctions();
150 : :
151 : 108010 : double dt = FDMExec->GetDeltaT();
152 : :
153 : 54005 : vForces.InitMatrix();
154 : 54005 : vMoments.InitMatrix();
155 : :
156 [ + + ]: 702065 : for (i=0; i<numEngines; i++) {
157 : 648060 : Engines[i]->Calculate();
158 : 648060 : vForces += Engines[i]->GetBodyForces(); // sum body frame forces
159 : 648060 : vMoments += Engines[i]->GetMoments(); // sum body frame moments
160 : : }
161 : :
162 : 54005 : TotalFuelQuantity = 0.0;
163 [ + + ]: 378035 : for (i=0; i<numTanks; i++) {
164 : 324030 : Tanks[i]->Calculate( dt * rate );
165 [ + + ]: 324030 : if (Tanks[i]->GetType() == FGTank::ttFUEL) {
166 : 216020 : TotalFuelQuantity += Tanks[i]->GetContents();
167 : : }
168 : : }
169 : :
170 [ - + ]: 54005 : if (refuel) DoRefuel( dt * rate );
171 [ - + ]: 54005 : if (dump) DumpFuel( dt * rate );
172 : :
173 : 54005 : RunPostFunctions();
174 : :
175 : 54005 : return false;
176 : : }
177 : :
178 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
179 : :
180 : 0 : bool FGPropulsion::GetSteadyState(void)
181 : : {
182 : 0 : double currentThrust = 0, lastThrust = -1;
183 : 0 : int steady_count = 0, j = 0;
184 : 0 : bool steady = false;
185 : :
186 : 0 : vForces.InitMatrix();
187 : 0 : vMoments.InitMatrix();
188 : :
189 [ # # ]: 0 : if (!FGModel::Run()) {
190 [ # # ]: 0 : for (unsigned int i=0; i<numEngines; i++) {
191 : : // cout << " Finding steady state for engine " << i << endl;
192 : 0 : Engines[i]->SetTrimMode(true);
193 : 0 : steady=false;
194 : 0 : steady_count=0;
195 : 0 : j=0;
196 [ # # ][ # # ]: 0 : while (!steady && j < 6000) {
197 : 0 : Engines[i]->Calculate();
198 : 0 : lastThrust = currentThrust;
199 : 0 : currentThrust = Engines[i]->GetThruster()->GetThrust();
200 [ # # ]: 0 : if (fabs(lastThrust-currentThrust) < 0.0001) {
201 : 0 : steady_count++;
202 [ # # ]: 0 : if (steady_count > 120) {
203 : 0 : steady=true;
204 : : // cout << " Steady state found at thrust: " << currentThrust << " lbs." << endl;
205 : : }
206 : : } else {
207 : 0 : steady_count=0;
208 : : }
209 : 0 : j++;
210 : : }
211 : : // if (j >= 6000) {
212 : : // cout << " Could not find a steady state for this engine." << endl;
213 : : // }
214 : 0 : vForces += Engines[i]->GetBodyForces(); // sum body frame forces
215 : 0 : vMoments += Engines[i]->GetMoments(); // sum body frame moments
216 : 0 : Engines[i]->SetTrimMode(false);
217 : : }
218 : :
219 : 0 : return false;
220 : : } else {
221 : 0 : return true;
222 : : }
223 : : }
224 : :
225 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
226 : :
227 : 0 : void FGPropulsion::InitRunning(int n)
228 : : {
229 [ # # ]: 0 : if (n > 0) { // A specific engine is supposed to be initialized
230 : :
231 [ # # ]: 0 : if (n >= (int)GetNumEngines() ) {
232 : 0 : cerr << "Tried to initialize a non-existent engine!" << endl;
233 : 0 : throw;
234 : : }
235 : 0 : FCS->SetThrottleCmd(n,1);
236 : 0 : FCS->SetMixtureCmd(n,1);
237 : 0 : GetEngine(n)->InitRunning();
238 : 0 : GetSteadyState();
239 : :
240 : 0 : InitializedEngines = 1 << n;
241 : 0 : HasInitializedEngines = true;
242 : :
243 [ # # ]: 0 : } else if (n < 0) { // -1 refers to "All Engines"
244 : :
245 [ # # ]: 0 : for (unsigned int i=0; i<GetNumEngines(); i++) {
246 : 0 : FCS->SetThrottleCmd(i,1);
247 : 0 : FCS->SetMixtureCmd(i,1);
248 : 0 : GetEngine(i)->InitRunning();
249 : : }
250 : 0 : GetSteadyState();
251 : 0 : InitializedEngines = -1;
252 : 0 : HasInitializedEngines = true;
253 : :
254 : : } else if (n == 0) { // No engines are to be initialized
255 : : // Do nothing
256 : : }
257 : 0 : }
258 : :
259 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
260 : :
261 : 1 : bool FGPropulsion::Load(Element* el)
262 : : {
263 : 1 : string type, engine_filename;
264 : 1 : bool ThrottleAdded = false;
265 : :
266 : 1 : Debug(2);
267 : :
268 : 1 : FGModel::Load(el); // Perform base class Load.
269 : :
270 : : // Process tank definitions first to establish the number of fuel tanks
271 : :
272 : 1 : Element* tank_element = el->FindElement("tank");
273 [ + + ]: 7 : while (tank_element) {
274 : 6 : Tanks.push_back(new FGTank(FDMExec, tank_element, numTanks));
275 [ + + ]: 6 : if (Tanks.back()->GetType() == FGTank::ttFUEL) numFuelTanks++;
276 [ + - ]: 2 : else if (Tanks.back()->GetType() == FGTank::ttOXIDIZER) numOxiTanks++;
277 : 0 : else {cerr << "Unknown tank type specified." << endl; return false;}
278 : 6 : numTanks++;
279 : 6 : tank_element = el->FindNextElement("tank");
280 : : }
281 : 1 : numSelectedFuelTanks = numFuelTanks;
282 : 1 : numSelectedOxiTanks = numOxiTanks;
283 : :
284 : 1 : Element* engine_element = el->FindElement("engine");
285 [ + + ]: 13 : while (engine_element) {
286 : 24 : engine_filename = engine_element->GetAttributeValue("file");
287 : :
288 [ - + ]: 12 : if (engine_filename.empty()) {
289 : 0 : cerr << "Engine definition did not supply an engine file." << endl;
290 : 0 : return false;
291 : : }
292 : :
293 : 24 : engine_filename = FindEngineFullPathname(engine_filename);
294 : 24 : document = LoadXMLDocument(engine_filename);
295 : 12 : document->SetParent(engine_element);
296 : :
297 : 12 : type = document->GetName();
298 [ - + ]: 12 : if (type == "piston_engine") {
299 : 0 : HavePistonEngine = true;
300 [ # # ]: 0 : if (!IsBound) bind();
301 : 0 : Engines.push_back(new FGPiston(FDMExec, document, numEngines));
302 [ - + ]: 12 : } else if (type == "turbine_engine") {
303 : 0 : HaveTurbineEngine = true;
304 [ # # ]: 0 : if (!IsBound) bind();
305 : 0 : Engines.push_back(new FGTurbine(FDMExec, document, numEngines));
306 [ - + ]: 12 : } else if (type == "turboprop_engine") {
307 : 0 : HaveTurboPropEngine = true;
308 [ # # ]: 0 : if (!IsBound) bind();
309 : 0 : Engines.push_back(new FGTurboProp(FDMExec, document, numEngines));
310 [ + - ]: 12 : } else if (type == "rocket_engine") {
311 : 12 : HaveRocketEngine = true;
312 [ + + ]: 12 : if (!IsBound) bind();
313 : 12 : Engines.push_back(new FGRocket(FDMExec, document, numEngines));
314 [ # # ]: 0 : } else if (type == "electric_engine") {
315 : 0 : HaveElectricEngine = true;
316 [ # # ]: 0 : if (!IsBound) bind();
317 : 0 : Engines.push_back(new FGElectric(FDMExec, document, numEngines));
318 : : } else {
319 : 0 : cerr << "Unknown engine type: " << type << endl;
320 : 0 : exit(-5);
321 : : }
322 : :
323 : 12 : FCS->AddThrottle();
324 : 12 : ThrottleAdded = true;
325 : :
326 : 12 : numEngines++;
327 : :
328 : 12 : engine_element = el->FindNextElement("engine");
329 : 12 : ResetParser();
330 : : }
331 : :
332 : 1 : CalculateTankInertias();
333 [ - + ]: 1 : if (!ThrottleAdded) FCS->AddThrottle(); // need to have at least one throttle
334 : :
335 : : // Process fuel dump rate
336 [ - + ]: 1 : if (el->FindElement("dump-rate"))
337 : 0 : DumpRate = el->FindElementValueAsNumberConvertTo("dump-rate", "LBS/MIN");
338 : :
339 : 1 : PostLoad(el, PropertyManager);
340 : :
341 : 1 : return true;
342 : : }
343 : :
344 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
345 : :
346 : 12 : string FGPropulsion::FindEngineFullPathname(const string& engine_filename)
347 : : {
348 : 12 : string fullpath, localpath;
349 : 12 : string enginePath = FDMExec->GetEnginePath();
350 : 12 : string aircraftPath = FDMExec->GetFullAircraftPath();
351 : 12 : ifstream engine_file;
352 : :
353 : 12 : string separator = "/";
354 : :
355 : 24 : fullpath = enginePath + separator;
356 : 24 : localpath = aircraftPath + separator + "Engines" + separator;
357 : :
358 : 12 : engine_file.open(string(fullpath + engine_filename + ".xml").c_str());
359 [ - + ]: 12 : if ( !engine_file.is_open()) {
360 : 0 : engine_file.open(string(localpath + engine_filename + ".xml").c_str());
361 [ # # ]: 0 : if ( !engine_file.is_open()) {
362 : : cerr << " Could not open engine file: " << engine_filename << " in path "
363 : 0 : << fullpath << " or " << localpath << endl;
364 : 0 : return string("");
365 : : } else {
366 : 0 : return string(localpath + engine_filename + ".xml");
367 : : }
368 : : }
369 : 12 : return string(fullpath + engine_filename + ".xml");
370 : : }
371 : :
372 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
373 : :
374 : 0 : ifstream* FGPropulsion::FindEngineFile(const string& engine_filename)
375 : : {
376 : 0 : string fullpath, localpath;
377 : 0 : string enginePath = FDMExec->GetEnginePath();
378 : 0 : string aircraftPath = FDMExec->GetFullAircraftPath();
379 : 0 : ifstream* engine_file = new ifstream();
380 : :
381 : 0 : string separator = "/";
382 : :
383 : 0 : fullpath = enginePath + separator;
384 : 0 : localpath = aircraftPath + separator + "Engines" + separator;
385 : :
386 : 0 : engine_file->open(string(fullpath + engine_filename + ".xml").c_str());
387 [ # # ]: 0 : if ( !engine_file->is_open()) {
388 : 0 : engine_file->open(string(localpath + engine_filename + ".xml").c_str());
389 [ # # ]: 0 : if ( !engine_file->is_open()) {
390 : : cerr << " Could not open engine file: " << engine_filename << " in path "
391 : 0 : << fullpath << " or " << localpath << endl;
392 : : }
393 : : }
394 : 0 : return engine_file;
395 : : }
396 : :
397 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
398 : :
399 : 1 : string FGPropulsion::GetPropulsionStrings(const string& delimiter)
400 : : {
401 : : unsigned int i;
402 : :
403 : 1 : string PropulsionStrings = "";
404 : 1 : bool firstime = true;
405 : 1 : stringstream buf;
406 : :
407 [ + + ]: 13 : for (i=0; i<Engines.size(); i++) {
408 [ + + ]: 12 : if (firstime) firstime = false;
409 : 11 : else PropulsionStrings += delimiter;
410 : :
411 : 24 : PropulsionStrings += Engines[i]->GetEngineLabels(delimiter);
412 : : }
413 [ + + ]: 7 : for (i=0; i<Tanks.size(); i++) {
414 [ + + ]: 6 : if (Tanks[i]->GetType() == FGTank::ttFUEL) buf << delimiter << "Fuel Tank " << i;
415 [ + - ]: 2 : else if (Tanks[i]->GetType() == FGTank::ttOXIDIZER) buf << delimiter << "Oxidizer Tank " << i;
416 : : }
417 : :
418 : 1 : return PropulsionStrings;
419 : : }
420 : :
421 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
422 : :
423 : 4909 : string FGPropulsion::GetPropulsionValues(const string& delimiter)
424 : : {
425 : : unsigned int i;
426 : :
427 : 4909 : string PropulsionValues = "";
428 : 4909 : bool firstime = true;
429 : 4909 : stringstream buf;
430 : :
431 [ + + ]: 63817 : for (i=0; i<Engines.size(); i++) {
432 [ + + ]: 58908 : if (firstime) firstime = false;
433 : 53999 : else PropulsionValues += delimiter;
434 : :
435 : 117816 : PropulsionValues += Engines[i]->GetEngineValues(delimiter);
436 : : }
437 [ + + ]: 34363 : for (i=0; i<Tanks.size(); i++) {
438 : 29454 : buf << delimiter;
439 : 58908 : buf << Tanks[i]->GetContents();
440 : : }
441 : :
442 : 4909 : return PropulsionValues;
443 : : }
444 : :
445 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
446 : :
447 : 54006 : FGColumnVector3& FGPropulsion::GetTanksMoment(void)
448 : : {
449 : 54006 : vXYZtank_arm.InitMatrix();
450 [ + + ]: 378042 : for (unsigned int i=0; i<Tanks.size(); i++) {
451 : 324036 : vXYZtank_arm(eX) += Tanks[i]->GetXYZ(eX) * Tanks[i]->GetContents();
452 : 324036 : vXYZtank_arm(eY) += Tanks[i]->GetXYZ(eY) * Tanks[i]->GetContents();
453 : 324036 : vXYZtank_arm(eZ) += Tanks[i]->GetXYZ(eZ) * Tanks[i]->GetContents();
454 : : }
455 : 54006 : return vXYZtank_arm;
456 : : }
457 : :
458 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
459 : :
460 : 54007 : double FGPropulsion::GetTanksWeight(void)
461 : : {
462 : 54007 : double Tw = 0.0;
463 : :
464 [ + + ]: 378043 : for (unsigned int i=0; i<Tanks.size(); i++) Tw += Tanks[i]->GetContents();
465 : :
466 : 54007 : return Tw;
467 : : }
468 : :
469 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
470 : :
471 : 54007 : FGMatrix33& FGPropulsion::CalculateTankInertias(void)
472 : : {
473 : : unsigned int size;
474 : :
475 : 108014 : size = Tanks.size();
476 [ - + ]: 54007 : if (size == 0) return tankJ;
477 : :
478 : 54007 : tankJ = FGMatrix33();
479 : :
480 [ + + ]: 378049 : for (unsigned int i=0; i<size; i++) {
481 : : tankJ += MassBalance->GetPointmassInertia( lbtoslug * Tanks[i]->GetContents(),
482 : 648084 : Tanks[i]->GetXYZ() );
483 : 1296168 : tankJ(1,1) += Tanks[i]->GetIxx();
484 : 1296168 : tankJ(2,2) += Tanks[i]->GetIyy();
485 : 1296168 : tankJ(3,3) += Tanks[i]->GetIzz();
486 : : }
487 : :
488 : 54007 : return tankJ;
489 : : }
490 : :
491 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
492 : :
493 : 0 : void FGPropulsion::SetMagnetos(int setting)
494 : : {
495 [ # # ]: 0 : if (ActiveEngine < 0) {
496 [ # # ]: 0 : for (unsigned i=0; i<Engines.size(); i++) {
497 : : // ToDo: first need to make sure the engine Type is really appropriate:
498 : : // do a check to see if it is of type Piston. This should be done for
499 : : // all of this kind of possibly across-the-board settings.
500 : 0 : ((FGPiston*)Engines[i])->SetMagnetos(setting);
501 : : }
502 : : } else {
503 : 0 : ((FGPiston*)Engines[ActiveEngine])->SetMagnetos(setting);
504 : : }
505 : 0 : }
506 : :
507 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
508 : :
509 : 0 : void FGPropulsion::SetStarter(int setting)
510 : : {
511 [ # # ]: 0 : if (ActiveEngine < 0) {
512 [ # # ]: 0 : for (unsigned i=0; i<Engines.size(); i++) {
513 [ # # ]: 0 : if (setting == 0)
514 : 0 : Engines[i]->SetStarter(false);
515 : : else
516 : 0 : Engines[i]->SetStarter(true);
517 : : }
518 : : } else {
519 [ # # ]: 0 : if (setting == 0)
520 : 0 : Engines[ActiveEngine]->SetStarter(false);
521 : : else
522 : 0 : Engines[ActiveEngine]->SetStarter(true);
523 : : }
524 : 0 : }
525 : :
526 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
527 : :
528 : 0 : void FGPropulsion::SetCutoff(int setting)
529 : : {
530 [ # # ]: 0 : if (ActiveEngine < 0) {
531 [ # # ]: 0 : for (unsigned i=0; i<Engines.size(); i++) {
532 [ # # ]: 0 : if (setting == 0)
533 : 0 : ((FGTurbine*)Engines[i])->SetCutoff(false);
534 : : else
535 : 0 : ((FGTurbine*)Engines[i])->SetCutoff(true);
536 : : }
537 : : } else {
538 [ # # ]: 0 : if (setting == 0)
539 : 0 : ((FGTurbine*)Engines[ActiveEngine])->SetCutoff(false);
540 : : else
541 : 0 : ((FGTurbine*)Engines[ActiveEngine])->SetCutoff(true);
542 : : }
543 : 0 : }
544 : :
545 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
546 : :
547 : 0 : void FGPropulsion::SetActiveEngine(int engine)
548 : : {
549 [ # # ][ # # ]: 0 : if (engine >= (int)Engines.size() || engine < 0)
[ # # ]
550 : 0 : ActiveEngine = -1;
551 : : else
552 : 0 : ActiveEngine = engine;
553 : 0 : }
554 : :
555 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
556 : :
557 : 0 : double FGPropulsion::Transfer(int source, int target, double amount)
558 : : {
559 : : double shortage, overage;
560 : :
561 [ # # ]: 0 : if (source == -1) {
562 : 0 : shortage = 0.0;
563 : : } else {
564 : 0 : shortage = Tanks[source]->Drain(amount);
565 : : }
566 [ # # ]: 0 : if (target == -1) {
567 : 0 : overage = 0.0;
568 : : } else {
569 : 0 : overage = Tanks[target]->Fill(amount - shortage);
570 : : }
571 : 0 : return overage;
572 : : }
573 : :
574 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
575 : :
576 : 0 : void FGPropulsion::DoRefuel(double time_slice)
577 : : {
578 : : unsigned int i;
579 : :
580 : 0 : double fillrate = 100 * time_slice; // 100 lbs/sec = 6000 lbs/min
581 : 0 : int TanksNotFull = 0;
582 : :
583 [ # # ]: 0 : for (i=0; i<numTanks; i++) {
584 [ # # ]: 0 : if (Tanks[i]->GetPctFull() < 99.99) ++TanksNotFull;
585 : : }
586 : :
587 [ # # ]: 0 : if (TanksNotFull) {
588 [ # # ]: 0 : for (i=0; i<numTanks; i++) {
589 [ # # ]: 0 : if (Tanks[i]->GetPctFull() < 99.99)
590 : 0 : Transfer(-1, i, fillrate/TanksNotFull);
591 : : }
592 : : }
593 : 0 : }
594 : :
595 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
596 : :
597 : 0 : void FGPropulsion::DumpFuel(double time_slice)
598 : : {
599 : : unsigned int i;
600 : 0 : int TanksDumping = 0;
601 : :
602 [ # # ]: 0 : for (i=0; i<numTanks; i++) {
603 [ # # ]: 0 : if (Tanks[i]->GetContents() > Tanks[i]->GetStandpipe()) ++TanksDumping;
604 : : }
605 : :
606 [ # # ]: 0 : if (TanksDumping == 0) return;
607 : :
608 : 0 : double dump_rate_per_tank = DumpRate / 60.0 * time_slice / TanksDumping;
609 : :
610 [ # # ]: 0 : for (i=0; i<numTanks; i++) {
611 [ # # ]: 0 : if (Tanks[i]->GetContents() > Tanks[i]->GetStandpipe()) {
612 : 0 : Transfer(i, -1, dump_rate_per_tank);
613 : : }
614 : : }
615 : : }
616 : :
617 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
618 : :
619 : 0 : void FGPropulsion::SetFuelFreeze(bool f)
620 : : {
621 : 0 : fuel_freeze = f;
622 [ # # ]: 0 : for (unsigned int i=0; i<numEngines; i++) {
623 : 0 : Engines[i]->SetFuelFreeze(f);
624 : : }
625 : 0 : }
626 : :
627 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
628 : :
629 : 1 : void FGPropulsion::bind(void)
630 : : {
631 : : typedef double (FGPropulsion::*PMF)(int) const;
632 : : typedef int (FGPropulsion::*iPMF)(void) const;
633 : :
634 : 1 : IsBound = true;
635 : 1 : PropertyManager->Tie("propulsion/set-running", this, (iPMF)0, &FGPropulsion::InitRunning, true);
636 [ - + ]: 1 : if (HaveTurbineEngine) {
637 : 0 : PropertyManager->Tie("propulsion/starter_cmd", this, (iPMF)0, &FGPropulsion::SetStarter, true);
638 : 0 : PropertyManager->Tie("propulsion/cutoff_cmd", this, (iPMF)0, &FGPropulsion::SetCutoff, true);
639 : : }
640 : :
641 [ - + ]: 1 : if (HavePistonEngine) {
642 : 0 : PropertyManager->Tie("propulsion/starter_cmd", this, (iPMF)0, &FGPropulsion::SetStarter, true);
643 : 0 : PropertyManager->Tie("propulsion/magneto_cmd", this, (iPMF)0, &FGPropulsion::SetMagnetos, true);
644 : : }
645 : :
646 : : PropertyManager->Tie("propulsion/active_engine", this, (iPMF)&FGPropulsion::GetActiveEngine,
647 : 1 : &FGPropulsion::SetActiveEngine, true);
648 : 2 : PropertyManager->Tie("propulsion/total-fuel-lbs", this, &FGPropulsion::GetTotalFuelQuantity);
649 : : PropertyManager->Tie("propulsion/refuel", this, &FGPropulsion::GetRefuel,
650 : 1 : &FGPropulsion::SetRefuel, true);
651 : : PropertyManager->Tie("propulsion/fuel_dump", this, &FGPropulsion::GetFuelDump,
652 : 1 : &FGPropulsion::SetFuelDump, true);
653 : : PropertyManager->Tie("forces/fbx-prop-lbs", this,1,
654 : 1 : (PMF)&FGPropulsion::GetForces);
655 : : PropertyManager->Tie("forces/fby-prop-lbs", this,2,
656 : 1 : (PMF)&FGPropulsion::GetForces);
657 : : PropertyManager->Tie("forces/fbz-prop-lbs", this,3,
658 : 1 : (PMF)&FGPropulsion::GetForces);
659 : : PropertyManager->Tie("moments/l-prop-lbsft", this,1,
660 : 1 : (PMF)&FGPropulsion::GetMoments);
661 : : PropertyManager->Tie("moments/m-prop-lbsft", this,2,
662 : 1 : (PMF)&FGPropulsion::GetMoments);
663 : : PropertyManager->Tie("moments/n-prop-lbsft", this,3,
664 : 1 : (PMF)&FGPropulsion::GetMoments);
665 : :
666 : 1 : }
667 : :
668 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
669 : : // The bitmasked value choices are as follows:
670 : : // unset: In this case (the default) JSBSim would only print
671 : : // out the normally expected messages, essentially echoing
672 : : // the config files as they are read. If the environment
673 : : // variable is not set, debug_lvl is set to 1 internally
674 : : // 0: This requests JSBSim not to output any messages
675 : : // whatsoever.
676 : : // 1: This value explicity requests the normal JSBSim
677 : : // startup messages
678 : : // 2: This value asks for a message to be printed out when
679 : : // a class is instantiated
680 : : // 4: When this value is set, a message is displayed when a
681 : : // FGModel object executes its Run() method
682 : : // 8: When this value is set, various runtime state variables
683 : : // are printed out periodically
684 : : // 16: When set various parameters are sanity checked and
685 : : // a message is printed out when they go out of bounds
686 : :
687 : 3 : void FGPropulsion::Debug(int from)
688 : : {
689 [ + - ]: 3 : if (debug_lvl <= 0) return;
690 : :
691 [ + - ]: 3 : if (debug_lvl & 1) { // Standard console startup message output
692 [ + + ]: 3 : if (from == 2) { // Loader
693 : 1 : cout << endl << " Propulsion:" << endl;
694 : : }
695 : : }
696 [ - + ]: 3 : if (debug_lvl & 2 ) { // Instantiation/Destruction notification
697 [ # # ]: 0 : if (from == 0) cout << "Instantiated: FGPropulsion" << endl;
698 [ # # ]: 0 : if (from == 1) cout << "Destroyed: FGPropulsion" << endl;
699 : : }
700 : 3 : if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
701 : : }
702 : 3 : if (debug_lvl & 8 ) { // Runtime state variables
703 : : }
704 : 3 : if (debug_lvl & 16) { // Sanity checking
705 : : }
706 [ - + ]: 3 : if (debug_lvl & 64) {
707 [ # # ]: 0 : if (from == 0) { // Constructor
708 : 0 : cout << IdSrc << endl;
709 : 0 : cout << IdHdr << endl;
710 : : }
711 : : }
712 : : }
713 [ + + ][ + - ]: 12 : }
|