]> git.mxchange.org Git - flightgear.git/blob - src/FDM/YASim/PropEngine.cpp
First cut at a turbulence model for YASim. It's a
[flightgear.git] / src / FDM / YASim / PropEngine.cpp
1 #include "Math.hpp"
2 #include "Propeller.hpp"
3 #include "PistonEngine.hpp"
4 #include "PropEngine.hpp"
5 namespace yasim {
6
7 PropEngine::PropEngine(Propeller* prop, PistonEngine* eng, float moment)
8 {
9     // Start off at 500rpm, because the start code doesn't exist yet
10     _omega = 52.3f;
11     _dir[0] = 1; _dir[1] = 0; _dir[2] = 0;
12
13     _variable = false;
14
15     _prop = prop;
16     _eng = eng;
17     _moment = moment;
18     _fuel = true;
19 }
20
21 PropEngine::~PropEngine()
22 {
23     delete _prop;
24     delete _eng;
25 }
26
27 void PropEngine::setMagnetos(int pos)
28 {
29     _magnetos = pos;
30 }
31
32 void PropEngine::setAdvance(float advance)
33 {
34     _advance = Math::clamp(advance, 0, 1);
35 }
36
37 void PropEngine::setPropPitch(float proppitch)
38 {
39     // update Propeller property
40     _prop->setPropPitch(proppitch);
41 }
42
43 void PropEngine::setVariableProp(float min, float max)
44 {
45     _variable = true;
46     _minOmega = min;
47     _maxOmega = max;
48 }
49
50 bool PropEngine::isRunning()
51 {
52     return _eng->isRunning();
53 }
54
55 bool PropEngine::isCranking()
56 {
57     return _eng->isCranking();
58 }
59
60 float PropEngine::getOmega()
61 {
62     return _omega;
63 }
64
65 void PropEngine::setOmega (float omega)
66 {
67     _omega = omega;
68 }
69
70 void PropEngine::getThrust(float* out)
71 {
72     int i;
73     for(i=0; i<3; i++) out[i] = _thrust[i];    
74 }
75
76 void PropEngine::getTorque(float* out)
77 {
78     int i;
79     for(i=0; i<3; i++) out[i] = _torque[i];
80 }
81
82 void PropEngine::getGyro(float* out)
83 {
84     int i;
85     for(i=0; i<3; i++) out[i] = _gyro[i];
86 }
87
88 float PropEngine::getFuelFlow()
89 {
90     return _fuelFlow;
91 }
92
93 void PropEngine::stabilize()
94 {
95     float speed = -Math::dot3(_wind, _dir);
96     _eng->setThrottle(_throttle);
97     _eng->setMixture(_mixture);
98
99     _eng->setMagnetos(3);
100     _eng->setRunning(true);
101
102     if(_variable) {
103         _omega = _minOmega + _advance * (_maxOmega - _minOmega);
104         _prop->modPitch(1e6); // Start at maximum pitch and move down
105     } else {
106         _omega = 52;
107     }
108
109     bool goingUp = false;
110     float step = 10;
111     while(true) {
112         float ptau, dummy;
113         _prop->calc(_rho, speed, _omega, &dummy, &ptau);
114         _eng->calc(_pressure, _temp, _omega);
115         float etau = _eng->getTorque();
116         float tdiff = etau - ptau;
117
118         if(Math::abs(tdiff/_moment) < 0.1)
119             break;
120
121         if(tdiff > 0) {
122             if(!goingUp) step *= 0.5f;
123             goingUp = true;
124             if(!_variable)  _omega += step;
125             else            _prop->modPitch(1+(step*0.005f));
126         } else {
127             if(goingUp) step *= 0.5f;
128             goingUp = false;
129             if(!_variable)  _omega -= step;
130             else            _prop->modPitch(1-(step*0.005f));
131         }
132     }
133
134     // ...and back off
135     _eng->setRunning(false);
136 }
137
138 void PropEngine::init()
139 {
140     _omega = 0.01f;
141     _eng->setStarter(false);
142     _eng->setMagnetos(0);
143 }
144
145 void PropEngine::integrate(float dt)
146 {
147     float speed = -Math::dot3(_wind, _dir);
148
149     float propTorque, engTorque, thrust;
150
151     _eng->setThrottle(_throttle);
152     _eng->setStarter(_starter);
153     _eng->setMagnetos(_magnetos);
154     _eng->setMixture(_mixture);
155     _eng->setFuelState(_fuel);
156     
157     _prop->calc(_rho, speed, _omega, &thrust, &propTorque);
158     _eng->calc(_pressure, _temp, _omega);
159     engTorque = _eng->getTorque();
160     _fuelFlow = _eng->getFuelFlow();
161
162     // Turn the thrust into a vector and save it
163     Math::mul3(thrust, _dir, _thrust);
164
165     // Euler-integrate the RPM.  This doesn't need the full-on
166     // Runge-Kutta stuff.
167     float rotacc = (engTorque-propTorque)/Math::abs(_moment);
168     _omega += dt * rotacc;
169     if (_omega < 0)
170         _omega = 0 - _omega;    // don't allow negative RPM
171                                 // FIXME: introduce proper windmilling
172
173     // Store the total angular momentum into _gyro
174     Math::mul3(_omega*_moment, _dir, _gyro);
175
176     // Accumulate the engine torque, it acts on the body as a whole.
177     // (Note: engine torque, not propeller torque.  They can be
178     // different, but the difference goes to accelerating the
179     // rotation.  It is the engine torque that is felt at the shaft
180     // and works on the body.)
181     float tau = _moment < 0 ? engTorque : -engTorque;
182     Math::mul3(tau, _dir, _torque);
183
184     // Iterate the propeller governor, if we have one.  Since engine
185     // torque is basically constant with RPM, we want to make the
186     // propeller torque at the target RPM equal to the engine by
187     // varying the pitch.  Assume the the torque goes as the square of
188     // the RPM (roughly correct) and compute a "target" torque for the
189     // _current_ RPM.  Seek to that.  This is sort of a continuous
190     // Newton-Raphson, basically.
191     if(_variable) {
192         float targetOmega = _minOmega + _advance*(_maxOmega-_minOmega);
193         float ratio2 = (_omega*_omega)/(targetOmega*targetOmega);
194         float targetTorque = engTorque * ratio2;
195
196         float mod = propTorque < targetTorque ? 1.04f : (1.0f/1.04f);
197
198         // Convert to an acceleration here, so that big propellers
199         // don't seek faster than small ones.
200         float diff = Math::abs((propTorque - targetTorque) / _moment);
201         if(diff < 10) mod = 1 + (mod-1)*(0.1f*diff);
202
203         _prop->modPitch(mod);
204     }
205 }
206
207 }; // namespace yasim