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