JSBSim Flight Dynamics Model  1.0 (02 March 2017)
An Open Source Flight Dynamics and Control Software Library in C++
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 (jon@jsbsim.org) -------------
9 
10  This program is free software; you can redistribute it and/or modify it under
11  the terms of the GNU Lesser 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 Lesser General Public License for more details.
18 
19  You should have received a copy of the GNU Lesser General Public License along with
20  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21  Place - Suite 330, Boston, MA 02111-1307, USA.
22 
23  Further information about the GNU Lesser General Public License can also be found on
24  the world wide web at http://www.gnu.org.
25 
26 FUNCTIONAL DESCRIPTION
27 --------------------------------------------------------------------------------
28 See header file.
29 
30 HISTORY
31 --------------------------------------------------------------------------------
32 01/21/99 JSB Created
33 09/03/99 JSB Changed Rocket thrust equation to correct -= Thrust instead of
34  += Thrust (thanks to Tony Peden)
35 
36 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
37 INCLUDES
38 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
39 
40 #include <iostream>
41 #include <fstream>
42 #include <cstdlib>
43 
44 #include "FGEngine.h"
45 #include "FGTank.h"
46 #include "FGPropeller.h"
47 #include "FGNozzle.h"
48 #include "FGRotor.h"
49 #include "input_output/FGXMLElement.h"
50 #include "math/FGColumnVector3.h"
51 
52 using namespace std;
53 
54 namespace JSBSim {
55 
56 IDENT(IdSrc,"$Id: FGEngine.cpp,v 1.67 2015/09/27 09:54:21 bcoconni Exp $");
57 IDENT(IdHdr,ID_ENGINE);
58 
59 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
60 CLASS IMPLEMENTATION
61 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
62 
63 FGEngine::FGEngine(int engine_number, struct Inputs& input)
64  : in(input), EngineNumber(engine_number)
65 {
66  Type = etUnknown;
67  X = Y = Z = 0.0;
68  EnginePitch = EngineYaw = 0.0;
69  SLFuelFlowMax = 0.0;
70  FuelExpended = 0.0;
71  MaxThrottle = 1.0;
72  MinThrottle = 0.0;
73  FuelDensity = 6.02;
74  Debug(0);
75 }
76 
77 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
78 
79 FGEngine::~FGEngine()
80 {
81  delete Thruster;
82  Debug(1);
83 }
84 
85 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
86 
88 {
89  Starter = false;
90  FuelExpended = 0.0;
91  Starved = Running = Cranking = false;
92  PctPower = 0.0;
93  FuelFlow_gph = 0.0;
94  FuelFlow_pph = 0.0;
95  FuelFlowRate = 0.0;
96  FuelFreeze = false;
97  FuelUsedLbs = 0.0;
98  Thruster->ResetToIC();
99 }
100 
101 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
102 
104 {
105  FuelFlowRate = SLFuelFlowMax*PctPower;
106  FuelExpended = FuelFlowRate*in.TotalDeltaT;
107  if (!Starved) FuelUsedLbs += FuelExpended;
108  return FuelExpended;
109 }
110 
111 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
112 
113 unsigned int FGEngine::GetSourceTank(unsigned int i) const
114 {
115  if (i < SourceTanks.size()) {
116  return SourceTanks[i];
117  } else {
118  throw("No such source tank is available for this engine");
119  }
120 }
121 
122 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
123 
125  const FGColumnVector3& orientation)
126 {
127  X = location(eX);
128  Y = location(eY);
129  Z = location(eZ);
130  EnginePitch = orientation(ePitch);
131  EngineYaw = orientation (eYaw);
132 }
133 
134 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
135 
136 double FGEngine::GetThrust(void) const
137 {
138  return Thruster->GetThrust();
139 }
140 
141 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
142 
143 const FGColumnVector3& FGEngine::GetBodyForces(void)
144 {
145  return Thruster->GetBodyForces();
146 }
147 
148 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
149 
150 const FGColumnVector3& FGEngine::GetMoments(void)
151 {
152  return Thruster->GetMoments();
153 }
154 
155 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
156 
157 void FGEngine::LoadThrusterInputs()
158 {
159  Thruster->in.TotalDeltaT = in.TotalDeltaT;
160  Thruster->in.H_agl = in.H_agl;
161  Thruster->in.PQRi = in.PQRi;
162  Thruster->in.AeroPQR = in.AeroPQR;
163  Thruster->in.AeroUVW = in.AeroUVW;
164  Thruster->in.Density = in.Density;
165  Thruster->in.Pressure = in.Pressure;
166  Thruster->in.Soundspeed = in.Soundspeed;
167  Thruster->in.Alpha = in.alpha;
168  Thruster->in.Beta = in.beta;
169  Thruster->in.Vt = in.Vt;
170 }
171 
172 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
173 
174 void FGEngine::LoadThruster(FGFDMExec* exec, Element *thruster_element)
175 {
176  if (thruster_element->FindElement("propeller")) {
177  Element *document = thruster_element->FindElement("propeller");
178  Thruster = new FGPropeller(exec, document, EngineNumber);
179  } else if (thruster_element->FindElement("nozzle")) {
180  Element *document = thruster_element->FindElement("nozzle");
181  Thruster = new FGNozzle(exec, document, EngineNumber);
182  } else if (thruster_element->FindElement("rotor")) {
183  Element *document = thruster_element->FindElement("rotor");
184  Thruster = new FGRotor(exec, document, EngineNumber);
185  } else if (thruster_element->FindElement("direct")) {
186  Element *document = thruster_element->FindElement("direct");
187  Thruster = new FGThruster(exec, document, EngineNumber);
188  } else {
189  cerr << thruster_element->ReadFrom() << " Unknown thruster type" << endl;
190  throw("Failed to load the thruster");
191  }
192 
193  Debug(2);
194 }
195 
196 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
197 
198 bool FGEngine::Load(FGFDMExec *exec, Element *engine_element)
199 {
200  Element* parent_element = engine_element->GetParent();
201  Element* local_element;
202  FGColumnVector3 location, orientation;
203 
204  FGPropertyManager* PropertyManager = exec->GetPropertyManager();
205 
206  Name = engine_element->GetAttributeValue("name");
207 
208  FGModelFunctions::Load(engine_element, PropertyManager, to_string((int)EngineNumber)); // Call ModelFunctions loader
209 
210 // Find and set engine location
211 
212  local_element = parent_element->FindElement("location");
213  if (local_element) location = local_element->FindElementTripletConvertTo("IN");
214 // else cerr << "No engine location found for this engine." << endl;
215 // Jon: The engine location is not important - the nozzle location is.
216 
217  local_element = parent_element->FindElement("orient");
218  if (local_element) orientation = local_element->FindElementTripletConvertTo("RAD");
219 // else cerr << "No engine orientation found for this engine." << endl;
220 // Jon: The engine orientation has a default and is not normally used.
221 
222  SetPlacement(location, orientation);
223 
224  // Load thruster
225  local_element = parent_element->FindElement("thruster");
226  if (local_element) {
227  try {
228  LoadThruster(exec, local_element);
229  } catch (std::string& str) {
230  throw("Error loading engine " + Name + ". " + str);
231  }
232  } else {
233  cerr << "No thruster definition supplied with engine definition." << endl;
234  }
235 
236  ResetToIC(); // initialize dynamic terms
237 
238  // Load feed tank[s] references
239  local_element = parent_element->FindElement("feed");
240  while (local_element) {
241  int tankID = (int)local_element->GetDataAsNumber();
242  SourceTanks.push_back(tankID);
243  local_element = parent_element->FindNextElement("feed");
244  }
245 
246  string property_name, base_property_name;
247  base_property_name = CreateIndexedPropertyName("propulsion/engine", EngineNumber);
248 
249  property_name = base_property_name + "/set-running";
250  PropertyManager->Tie( property_name.c_str(), this, &FGEngine::GetRunning, &FGEngine::SetRunning );
251  property_name = base_property_name + "/thrust-lbs";
252  PropertyManager->Tie( property_name.c_str(), Thruster, &FGThruster::GetThrust);
253  property_name = base_property_name + "/fuel-flow-rate-pps";
254  PropertyManager->Tie( property_name.c_str(), this, &FGEngine::GetFuelFlowRate);
255  property_name = base_property_name + "/fuel-flow-rate-gph";
256  PropertyManager->Tie( property_name.c_str(), this, &FGEngine::GetFuelFlowRateGPH);
257  property_name = base_property_name + "/fuel-used-lbs";
258  PropertyManager->Tie( property_name.c_str(), this, &FGEngine::GetFuelUsedLbs);
259 
260  PostLoad(engine_element, PropertyManager, to_string((int)EngineNumber));
261 
262  Debug(0);
263 
264  return true;
265 }
266 
267 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
268 // The bitmasked value choices are as follows:
269 // unset: In this case (the default) JSBSim would only print
270 // out the normally expected messages, essentially echoing
271 // the config files as they are read. If the environment
272 // variable is not set, debug_lvl is set to 1 internally
273 // 0: This requests JSBSim not to output any messages
274 // whatsoever.
275 // 1: This value explicity requests the normal JSBSim
276 // startup messages
277 // 2: This value asks for a message to be printed out when
278 // a class is instantiated
279 // 4: When this value is set, a message is displayed when a
280 // FGModel object executes its Run() method
281 // 8: When this value is set, various runtime state variables
282 // are printed out periodically
283 // 16: When set various parameters are sanity checked and
284 // a message is printed out when they go out of bounds
285 
286 void FGEngine::Debug(int from)
287 {
288  if (debug_lvl <= 0) return;
289 
290  if (debug_lvl & 1) { // Standard console startup message output
291  if (from == 0) { // Constructor
292 
293  }
294  if (from == 2) { // After thruster loading
295  cout << " X = " << Thruster->GetLocationX() << endl;
296  cout << " Y = " << Thruster->GetLocationY() << endl;
297  cout << " Z = " << Thruster->GetLocationZ() << endl;
298  cout << " Pitch = " << radtodeg*Thruster->GetAnglesToBody(ePitch) << " degrees" << endl;
299  cout << " Yaw = " << radtodeg*Thruster->GetAnglesToBody(eYaw) << " degrees" << endl;
300  }
301  }
302  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
303  if (from == 0) cout << "Instantiated: FGEngine" << endl;
304  if (from == 1) cout << "Destroyed: FGEngine" << endl;
305  }
306  if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
307  }
308  if (debug_lvl & 8 ) { // Runtime state variables
309  }
310  if (debug_lvl & 16) { // Sanity checking
311  }
312  if (debug_lvl & 64) {
313  if (from == 0) { // Constructor
314  cout << IdSrc << endl;
315  cout << IdHdr << endl;
316  }
317  }
318 }
319 }
Element * GetParent(void)
Returns a pointer to the parent of an element.
Definition: FGXMLElement.h:231
std::string GetAttributeValue(const std::string &key)
Retrieves an attribute.
Models a rocket nozzle.
Definition: FGNozzle.h:85
STL namespace.
FGPropeller models a propeller given the tabular data for Ct (thrust) and Cp (power), indexed by the advance ratio "J".
Definition: FGPropeller.h:170
Element * FindElement(const std::string &el="")
Searches for a specified element.
Base class for specific thrusting devices such as propellers, nozzles, etc.
Definition: FGThruster.h:84
Models a helicopter rotor.
Definition: FGRotor.h:242
virtual double CalcFuelNeed(void)
The fuel need is calculated based on power levels and flow rate for that power level.
Definition: FGEngine.cpp:103
FGPropertyManager * GetPropertyManager(void)
Returns a pointer to the property manager object.
Definition: FGFDMExec.cpp:1099
void Tie(const std::string &name, bool *pointer, bool useDefault=true)
Tie a property to an external bool variable.
double GetDataAsNumber(void)
Converts the element data to a number.
This class implements a 3 element column vector.
std::string ReadFrom(void) const
Return a string that contains a description of the location where the current XML element was read fr...
Element * FindNextElement(const std::string &el="")
Searches for the next element as specified.
virtual void SetPlacement(const FGColumnVector3 &location, const FGColumnVector3 &orientation)
Sets engine placement information.
Definition: FGEngine.cpp:124
Encapsulates the JSBSim simulation executive.
Definition: FGFDMExec.h:189
FGColumnVector3 FindElementTripletConvertTo(const std::string &target_units)
Composes a 3-element column vector for the supplied location or orientation.
virtual void ResetToIC(void)
Resets the Engine parameters to the initial conditions.
Definition: FGEngine.cpp:87