2#include "yasim-common.hpp"
7int Surface::s_idGenerator = 0;
9Surface::Surface(Version* version,
const float* pos,
float c0 = 1 ) :
13 _id = s_idGenerator++;
15 _orient[0] = 1; _orient[1] = 0; _orient[2] = 0;
16 _orient[3] = 0; _orient[4] = 1; _orient[5] = 0;
17 _orient[6] = 0; _orient[7] = 0; _orient[8] = 1;
19 Math::set3(pos, _pos);
21 _surfN =
fgGetNode(
"/fdm/yasim/debug/surfaces",
true);
23 _surfN = _surfN->getChild(
"surface", _id,
true);
24 _fxN = _surfN->getNode(
"f-x",
true);
25 _fyN = _surfN->getNode(
"f-y",
true);
26 _fzN = _surfN->getNode(
"f-z",
true);
27 _fabsN = _surfN->getNode(
"f-abs",
true);
28 _alphaN = _surfN->getNode(
"alpha",
true);
29 _stallAlphaN = _surfN->getNode(
"stall-alpha",
true);
30 _flapN = _surfN->getNode(
"flap-pos",
true);
31 _slatN = _surfN->getNode(
"slat-pos",
true);
32 _spoilerN = _surfN->getNode(
"spoiler-pos",
true);
33 _incidenceN = _surfN->getNode(
"incidence-deg",
true);
34 _incidenceN->setFloatValue(0);
35 _twistN = _surfN->getNode(
"twist-deg",
true);
36 _twistN->setFloatValue(0);
37 _pgCorrectionN = _surfN->getNode(
"pg-correction",
true);
38 _pgCorrectionN->setFloatValue(1);
39 _dcdwaveN = _surfN->getNode(
"wavedrag",
true);
40 _dcdwaveN->setFloatValue(1);
41 _surfN->getNode(
"pos-x",
true)->setFloatValue(pos[0]);
42 _surfN->getNode(
"pos-y",
true)->setFloatValue(pos[1]);
43 _surfN->getNode(
"pos-z",
true)->setFloatValue(pos[2]);
44 _surfN->getNode(
"chord",
true)->setFloatValue(0);
45 _surfN->getNode(
"axis-x",
true)->setFloatValue(0);
46 _surfN->getNode(
"axis-y",
true)->setFloatValue(0);
47 _surfN->getNode(
"axis-z",
true)->setFloatValue(0);
52void Surface::setPosition(
const float* pos)
54 Math::set3(pos, _pos);
56 _surfN->getNode(
"pos-x",
true)->setFloatValue(pos[0]);
57 _surfN->getNode(
"pos-y",
true)->setFloatValue(pos[1]);
58 _surfN->getNode(
"pos-z",
true)->setFloatValue(pos[2]);
62void Surface::setChord(
float chord)
66 _surfN->getNode(
"chord",
true)->setFloatValue(_chord);
70void Surface::setOrientation(
const float* o)
72 for(
int i=0;
i<9;
i++) _orient[
i] = o[
i];
75 float xaxis[3] {1,0,0};
76 Math::tmul33(_orient,xaxis, xaxis);
77 _surfN->getNode(
"axis-x",
true)->setFloatValue(xaxis[0]);
78 _surfN->getNode(
"axis-y",
true)->setFloatValue(xaxis[1]);
79 _surfN->getNode(
"axis-z",
true)->setFloatValue(xaxis[2]);
84void Surface::setSlatParams(
float stallDelta,
float dragPenalty)
86 _slatAlpha = stallDelta;
87 _slatDrag = dragPenalty;
90void Surface::setFlapParams(
float liftAdd,
float dragPenalty)
93 _flapDrag = dragPenalty;
96void Surface::setSpoilerParams(
float liftPenalty,
float dragPenalty)
98 _spoilerLift = liftPenalty;
99 _spoilerDrag = dragPenalty;
102void Surface::setFlapPos(
float pos)
104 if (_flapPos != pos) {
107 _flapN->setFloatValue(pos);
112void Surface::setSlatPos(
float pos)
114 if (_slatPos != pos) {
117 _slatN->setFloatValue(pos);
122void Surface::setSpoilerPos(
float pos)
124 if (_spoilerPos != pos) {
126 if (_surfN != 0) _spoilerN->setFloatValue(pos);
135void Surface::calcForce(
const float* v,
const float rho,
float mach,
float* out,
float* torque)
142 float vel = Math::mag3(v);
151 if(_cx == 0. && _cy == 0. && _cz == 0.) {
156 Math::mul3(1/vel, v, out);
157 Math::vmul33(_orient, out, out);
162 float incidence = _incidence + _twist;
163 out[2] += incidence * out[0];
168 Math::set3(out, lwind);
171 float stallMul = stallFunc(out);
172 stallMul *= 1 + _spoilerPos * (_spoilerLift - 1);
173 float stallLift = (stallMul - 1) * _cz * out[2];
174 float flaplift = flapLift(out[2]);
182 float pg_correction {1};
184 if (_flow == FLOW_TRANSONIC) {
186 pg_correction = 1.0f/sqrt(1.0f-(mach*mach));
188 if ((mach >= 0.8f) && (mach < 1.2f)) {
189 pg_correction = Math::polynomial(pg_coefficients, mach);
192 pg_correction = 2.0f/(((mach*mach)-1.0f)*YASIM_PI);
194 out[2] *= pg_correction;
198 wavedrag = 9.5f * Math::pow((mach > 1.0f ? 1.0f : mach)-_Mcrit, 2.8f) + 0.00193f;
210 torque[1] = 0.1667f * _chord * (flaplift - (_cz*_cz0 + stallLift));
212 Math::tmul33(_orient, torque, torque);
215 out[0] = controlDrag(out[2], _cx * out[0]);
221 Math::mul3(-1*_inducedDrag*out[2]*lwind[2], lwind, lwind);
222 Math::add3(lwind, out, out);
231 if( _version->isVersionOrNewer( YASIM_VERSION::V_32 )) {
232 out[0] += incidence * out[2];
234 out[2] -= incidence * out[0];
238 Math::tmul33(_orient, out, out);
241 float scale = 0.5f*rho*vel*vel*_c0;
242 Math::mul3(
scale, out, out);
243 Math::mul3(
scale, torque, torque);
246 _fabsN->setFloatValue(Math::mag3(out));
247 _fxN->setFloatValue(out[0]);
248 _fyN->setFloatValue(out[1]);
249 _fzN->setFloatValue(out[2]);
250 _alphaN->setFloatValue(_alpha);
251 _stallAlphaN->setFloatValue(_stallAlpha);
252 _pgCorrectionN->setFloatValue(pg_correction);
253 _dcdwaveN->setFloatValue(wavedrag);
260 static const float DEG2RAD = 0.0174532925199;
261 float v[3], force[3], torque[3];
262 float rho = Atmosphere::getStdDensity(0);
269 for(
float angle = -90; angle<90; angle += 0.01) {
270 float rad = angle * DEG2RAD;
271 v[0] = spd * -Math::cos(rad);
273 v[2] = spd * Math::sin(rad);
274 calcForce(v, rho, force, torque);
275 float lift = force[2] * Math::cos(rad) + force[0] * Math::sin(rad);
277 __builtin_printf(
"%f %f\n", angle, torque[2]);
284float Surface::stallFunc(
float* v)
287 if(v[0] == 0)
return 1;
289 _alpha = Math::abs(v[2]/v[0]);
292 int fwdBak = v[0] > 0;
293 int posNeg = v[2] < 0;
294 int i = (fwdBak<<1) | posNeg;
296 _stallAlpha = _stalls[
i];
302 if( _version->isVersionOrNewer( YASIM_VERSION::V_32 )) {
303 _stallAlpha += _slatPos * _slatAlpha;
305 _stallAlpha += _slatAlpha;
310 if(_alpha > _stallAlpha+_widths[
i])
314 float scale = 0.5f*_peaks[fwdBak]/_stalls[
i&2];
317 if(_alpha <= _stallAlpha)
322 float frac = (_alpha - _stallAlpha) / _widths[
i];
323 frac = frac*frac*(3-2*frac);
325 return scale*(1-frac) + frac;
330float Surface::flapLift(
float alpha)
332 float flapLift = _cz * _flapPos * (_flapLift-1) * _flapEffectiveness;
338 if(alpha < _stalls[0])
340 else if(alpha > _stalls[0] + _widths[0])
343 float frac = (
alpha - _stalls[0]) / _widths[0];
344 frac = frac*frac*(3-2*frac);
345 return flapLift * (1-frac);
348float Surface::controlDrag(
float lift,
float drag)
356 fp -= _cz0/(_flapLift-1);
362 float flapDragAoA = (_flapLift - 1 - _cz0) * _stalls[0];
363 float fd = Math::abs(lift * flapDragAoA * fp);
364 if(drag < 0) fd = -fd;
368 drag *= 1 + fp * (_flapDrag - 1);
369 drag *= 1 + _spoilerPos * (_spoilerDrag - 1);
370 drag *= 1 + _slatPos * (_slatDrag - 1);
376void Surface::setIncidence(
float angle) {
377 _incidence = angle * -1;
379 _incidenceN->setFloatValue(angle * RAD2DEG);
384void Surface::setTwist(
float angle) {
387 _twistN->setFloatValue(angle * RAD2DEG);
SGPropertyNode * fgGetNode(const char *path, bool create)
Get a property node.