41 #include "FGFDMExec.h"
43 #include "FGThruster.h"
44 #include "input_output/FGXMLElement.h"
55 :
FGEngine(engine_number, input), isp_function(nullptr), FDMExec(exec)
60 Element* thrust_table_element =
nullptr;
61 ThrustTable =
nullptr;
63 previousFuelNeedPerTank = 0.0;
64 previousOxiNeedPerTank = 0.0;
65 PropellantFlowRate = 0.0;
66 TotalPropellantExpended = 0.0;
67 FuelFlowRate = FuelExpended = 0.0;
68 OxidizerFlowRate = OxidizerExpended = 0.0;
69 SLOxiFlowMax = SLFuelFlowMax = PropFlowMax = 0.0;
73 ThrustVariation = 0.0;
74 TotalIspVariation = 0.0;
82 std::stringstream strEngineNumber;
83 strEngineNumber << EngineNumber;
86 bindmodel(PropertyManager);
95 isp_function =
new FGFunction(exec, isp_func_el, strEngineNumber.str());
100 throw(
"Specific Impulse <isp> must be specified for a rocket engine");
115 PropFlowMax = SLOxiFlowMax + SLFuelFlowMax;
116 MxR = SLOxiFlowMax/SLFuelFlowMax;
126 if (isp_function) Isp = isp_function->
GetValue();
128 thrust_table_element = el->
FindElement(
"thrust_table");
129 if (thrust_table_element) {
130 ThrustTable =
new FGTable(PropertyManager, thrust_table_element);
132 if (variation_element) {
162 PropellantFlowRate = (FuelExpended + OxidizerExpended)/in.TotalDeltaT;
163 TotalPropellantExpended += FuelExpended + OxidizerExpended;
166 if (isp_function) Isp = isp_function->
GetValue();
172 if (ThrustTable != 0L) {
174 if ((in.ThrottlePos[EngineNumber] == 1 || BurnTime > 0.0 ) && !Starved) {
176 VacThrust = ThrustTable->GetValue(TotalPropellantExpended)
177 * (ThrustVariation + 1)
178 * (TotalIspVariation + 1);
179 if (BurnTime <= BuildupTime && BuildupTime > 0.0) {
180 VacThrust *= sin((BurnTime/BuildupTime)*M_PI/2.0);
183 BurnTime += in.TotalDeltaT;
190 if (in.ThrottlePos[EngineNumber] < MinThrottle || Starved) {
200 PctPower = in.ThrottlePos[EngineNumber];
202 VacThrust = Isp * PropellantFlowRate;
208 LoadThrusterInputs();
209 It += Thruster->Calculate(VacThrust) * in.TotalDeltaT;
210 ItVac += VacThrust * in.TotalDeltaT;
224 if (ThrustTable != 0L) {
225 FuelFlowRate = VacThrust/Isp;
226 FuelFlowRate /= (1 + TotalIspVariation);
228 SLFuelFlowMax = PropFlowMax / (1 + MxR);
229 FuelFlowRate = SLFuelFlowMax * PctPower;
232 FuelExpended = FuelFlowRate * in.TotalDeltaT;
240 SLOxiFlowMax = PropFlowMax * MxR / (1 + MxR);
241 OxidizerFlowRate = SLOxiFlowMax * PctPower;
242 OxidizerExpended = OxidizerFlowRate * in.TotalDeltaT;
243 return OxidizerExpended;
248 string FGRocket::GetEngineLabels(
const string& delimiter)
250 std::ostringstream buf;
252 buf << Name <<
" Total Impulse (engine " << EngineNumber <<
" in lbf)" << delimiter
253 << Name <<
" Total Vacuum Impulse (engine " << EngineNumber <<
" in lbf)" << delimiter
254 << Name <<
" Roll Moment (engine " << EngineNumber <<
" in ft-lbf)" << delimiter
255 << Name <<
" Pitch Moment (engine " << EngineNumber <<
" in ft-lbf)" << delimiter
256 << Name <<
" Yaw Moment (engine " << EngineNumber <<
" in ft-lbf)" << delimiter
257 << Name <<
" X Force (engine " << EngineNumber <<
" in lbf)" << delimiter
258 << Name <<
" Y Force (engine " << EngineNumber <<
" in lbf)" << delimiter
259 << Name <<
" Z Force (engine " << EngineNumber <<
" in lbf)" << delimiter
260 << Thruster->GetThrusterLabels(EngineNumber, delimiter);
267 string FGRocket::GetEngineValues(
const string& delimiter)
269 std::ostringstream buf;
271 buf << It << delimiter
272 << ItVac << delimiter
273 << GetMoments().
Dump(delimiter) << delimiter
274 << Thruster->GetBodyForces().
Dump(delimiter) << delimiter
275 << Thruster->GetThrusterValues(EngineNumber, delimiter);
284 void FGRocket::bindmodel(FGPropertyManager* PropertyManager)
286 string property_name, base_property_name;
287 base_property_name = CreateIndexedPropertyName(
"propulsion/engine", EngineNumber);
289 property_name = base_property_name +
"/total-impulse";
291 property_name = base_property_name +
"/total-vac-impulse";
293 property_name = base_property_name +
"/vacuum-thrust_lbs";
294 PropertyManager->Tie( property_name.c_str(),
this, &FGRocket::GetVacThrust);
297 property_name = base_property_name +
"/thrust-variation_pct";
300 property_name = base_property_name +
"/total-isp-variation_pct";
304 property_name = base_property_name +
"/oxi-flow-rate-pps";
305 PropertyManager->Tie( property_name.c_str(),
this, &FGRocket::GetOxiFlowRate);
306 property_name = base_property_name +
"/mixture-ratio";
307 PropertyManager->Tie( property_name.c_str(),
this, &FGRocket::GetMixtureRatio,
308 &FGRocket::SetMixtureRatio);
309 property_name = base_property_name +
"/isp";
310 PropertyManager->Tie( property_name.c_str(),
this, &FGRocket::GetIsp,
334 void FGRocket::Debug(
int from)
336 if (debug_lvl <= 0)
return;
340 cout <<
" Engine Name: " << Name << endl;
341 cout <<
" Vacuum Isp = " << Isp << endl;
342 cout <<
" Maximum Throttle = " << MaxThrottle << endl;
343 cout <<
" Minimum Throttle = " << MinThrottle << endl;
344 cout <<
" Fuel Flow (max) = " << SLFuelFlowMax << endl;
345 cout <<
" Oxidizer Flow (max) = " << SLOxiFlowMax << endl;
346 if (SLFuelFlowMax > 0)
347 cout <<
" Mixture ratio = " << SLOxiFlowMax/SLFuelFlowMax << endl;
350 if (debug_lvl & 2 ) {
351 if (from == 0) cout <<
"Instantiated: FGRocket" << endl;
352 if (from == 1) cout <<
"Destroyed: FGRocket" << endl;
354 if (debug_lvl & 4 ) {
356 if (debug_lvl & 8 ) {
358 if (debug_lvl & 16) {
360 if (debug_lvl & 64) {