]> git.mxchange.org Git - flightgear.git/blob - src/FDM/YASim/Jet.cpp
edd364bee2867cbe48c9ea7006a65313a2e72ed8
[flightgear.git] / src / FDM / YASim / Jet.cpp
1 #include "Atmosphere.hpp"
2 #include "Math.hpp"
3 #include "Jet.hpp"
4 namespace yasim {
5
6 Jet::Jet()
7 {
8     _maxThrust = 0;
9     _abFactor = 1;
10     _reheat = 0;
11     _rotControl = 0;
12     _maxRot = 0;
13
14     // Initialize parameters for an early-ish subsonic turbojet.  More
15     // recent turbofans will typically have a lower vMax, epr0, and
16     // tsfc.
17     _vMax = 800;
18     _epr0 = 3.0;
19     _tsfc = 0.8f;
20     _egt0 = 1050;
21     _n1Min = 55;
22     _n1Max = 102;
23     _n2Min = 73;
24     _n2Max = 103;
25     setSpooling(4); // 4 second spool time? s'bout right.
26
27     // And initialize to an engine that is idling
28     _n1 = _n1Min;
29     _n2 = _n2Min;
30
31     // And sanify the remaining junk, just in case.
32     _running = true;
33     _cranking = false;
34     _fuel = true;
35     _epr = 1;
36     _fuelFlow = 0;
37     _egt = 273;
38     _tempCorrect = 1;
39     _pressureCorrect = 1;
40 }
41
42 void Jet::stabilize()
43 {
44     // Just run it for an hour, there's no need to iterate given the
45     // algorithms used.
46     integrate(3600);
47 }
48
49 void Jet::setMaxThrust(float thrust, float afterburner)
50 {
51     _maxThrust = thrust;
52     if(afterburner == 0) _abFactor = 1;
53     else                 _abFactor = afterburner/thrust;
54 }
55
56 void Jet::setVMax(float spd)
57 {
58     _vMax = spd;
59 }
60
61 void Jet::setTSFC(float tsfc)
62 {
63     _tsfc = tsfc;
64 }
65
66 void Jet::setRPMs(float idleN1, float maxN1, float idleN2, float maxN2)
67 {
68     _n1Min = idleN1;
69     _n1Max = maxN1;
70     _n2Min = idleN2;
71     _n2Max = maxN2;
72 }
73
74 void Jet::setEGT(float takeoffEGT)
75 {
76     _egt0 = takeoffEGT;
77 }
78
79 void Jet::setEPR(float takeoffEPR)
80 {
81     _epr0 = takeoffEPR;
82 }
83
84 void Jet::setSpooling(float time)
85 {
86     // 2.3 = -ln(0.1), i.e. x=2.3 is the 90% point we're defining
87     // The extra fudge factor is there because the N1 speed (which
88     // determines thrust) lags the N2 speed.
89     _decay = 1.5f * 2.3f / time;
90 }
91
92 void Jet::setVectorAngle(float angle)
93 {
94     _maxRot = angle;
95 }
96
97 void Jet::setReheat(float reheat)
98 {
99     _reheat = Math::clamp(reheat, 0, 1);
100 }
101
102 void Jet::setRotation(float rot)
103 {
104     if(rot < 0) rot = 0;
105     if(rot > 1) rot = 1;
106     _rotControl = rot;
107 }
108
109 float Jet::getN1()
110 {
111     return _n1 * _tempCorrect;
112 }
113
114 float Jet::getN2()
115 {
116     return _n2 * _tempCorrect;
117 }
118
119 float Jet::getEPR()
120 {
121     return _epr;
122 }
123
124 float Jet::getEGT()
125 {
126     // Exactly zero means "off" -- return the ambient temperature
127     if(_egt == 0) return _temp;
128
129     return _egt * _tempCorrect * _tempCorrect;
130 }
131
132 float Jet::getFuelFlow()
133 {
134     return _fuelFlow * _pressureCorrect;
135 }
136
137 void Jet::integrate(float dt)
138 {
139     // Sea-level values
140     const static float P0 = Atmosphere::getStdPressure(0);
141     const static float T0 = Atmosphere::getStdTemperature(0);
142     const static float D0 = Atmosphere::getStdDensity(0);
143
144     float speed = -Math::dot3(_wind, _dir);
145
146     float statT, statP, statD;
147     Atmosphere::calcStaticAir(_pressure, _temp, _rho, speed,
148                               &statP, &statT, &statD);
149     _pressureCorrect = statP/P0;
150     _tempCorrect = Math::sqrt(statT/T0);
151
152     // Handle running out of fuel.  This is a hack.  What should
153     // really happen is a simulation of ram air torque on the
154     // turbine.  This just forces the engine into ground idle.
155     if(_fuel == false)
156         _throttle = 0;
157
158     // Linearly taper maxThrust to zero at vMax
159     float vCorr = 1 - (speed/_vMax);
160
161     float maxThrust = _maxThrust * vCorr * (statD/D0);
162     float setThrust = maxThrust * _throttle;
163
164     // Now get a "beta" (i.e. EPR - 1) value.  The output values are
165     // expressed as functions of beta.
166     float ibeta0 = 1/(_epr0 - 1);
167     float betaTarget = (_epr0 - 1) * (setThrust/_maxThrust) * (P0/_pressure)
168         * (_temp/statT);
169     float n2Target = _n2Min + (betaTarget*ibeta0) * (_n2Max - _n2Min);
170
171     // Note that this "first" beta value is used to compute a target
172     // for N2 only Integrate the N2 speed and back-calculate a beta1
173     // target.  The N1 speed will seek to this.
174     _n2 = (_n2 + dt*_decay * n2Target) / (1 + dt*_decay);
175
176     float betaN2 = (_epr0-1) * (_n2 - _n2Min) / (_n2Max - _n2Min);
177     float n1Target = _n1Min + betaN2*ibeta0 * (_n1Max - _n1Min);
178     _n1 = (_n1 + dt*_decay * n1Target) / (1 + dt*_decay);
179
180     // The actual thrust produced is keyed to the N1 speed.  Add the
181     // afterburners in at the end.
182     float betaN1 =  (_epr0-1) * (_n1 - _n1Min) / (_n1Max - _n1Min);
183     _thrust = _maxThrust * betaN1/((_epr0-1)*(P0/_pressure)*(_temp/statT));
184     _thrust *= 1 + _reheat*(_abFactor-1);
185
186     // Finally, calculate the output variables.   Use a 80/20 mix of
187     // the N2/N1 speeds as the key.
188     float beta = 0.8f*betaN2 + 0.2f*betaN1;
189     _epr = beta + 1;
190     float ff0 = _maxThrust*_tsfc*(1/(3600.0f*9.8f)); // takeoff fuel flow, kg/s
191     _fuelFlow = ff0 * beta*ibeta0;
192     _fuelFlow *= 1 + (3.5f * _reheat * _abFactor); // Afterburners take
193                                                   // 3.5 times as much
194                                                   // fuel per thrust unit
195     _egt = T0 + beta*ibeta0 * (_egt0 - T0);
196 }
197
198 bool Jet::isRunning()
199 {
200     return _running;
201 }
202
203 bool Jet::isCranking()
204 {
205     return _cranking;
206 }
207
208 void Jet::getThrust(float* out)
209 {
210     Math::mul3(_thrust, _dir, out);
211
212     // Rotate about the Y axis for thrust vectoring
213     float angle = _rotControl * _maxRot;
214     float s = Math::sin(angle);
215     float c = Math::cos(angle);
216     float o0 = out[0];
217     out[0] =  c * o0 + s * out[2];
218     out[2] = -s * o0 + c * out[2];
219 }
220
221 void Jet::getTorque(float* out)
222 {
223     out[0] = out[1] = out[2] = 0;
224     return;
225 }
226
227 void Jet::getGyro(float* out)
228 {
229     out[0] = out[1] = out[2] = 0;
230     return;
231 }
232
233 }; // namespace yasim