X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FFDM%2FYASim%2FSurface.cpp;h=77349b7683d562432e4d95c7e74cdb037898d782;hb=ce91286e19d6d66b316811d04b5b66b8b768827b;hp=536caf680d611eddbb8e71a063171a4feb9a2a45;hpb=47b230735620a285783566ace5e6cfd9ad08f664;p=flightgear.git diff --git a/src/FDM/YASim/Surface.cpp b/src/FDM/YASim/Surface.cpp index 536caf680..77349b768 100644 --- a/src/FDM/YASim/Surface.cpp +++ b/src/FDM/YASim/Surface.cpp @@ -10,18 +10,24 @@ Surface::Surface() _cz0 = 0; _peaks[0] = _peaks[1] = 1; int i; - for(i=0; i<4; i++) - _stalls[i] = _widths[i] = 0; + for(i=0; i<4; i++) { + _stalls[i] = 0; + _widths[i] = 0.01; // half a degree + } _orient[0] = 1; _orient[1] = 0; _orient[2] = 0; _orient[3] = 0; _orient[4] = 1; _orient[5] = 0; _orient[6] = 0; _orient[7] = 0; _orient[8] = 1; + _chord = 0; _incidence = 0; + _twist = 0; _slatPos = _spoilerPos = _flapPos = 0; _slatDrag = _spoilerDrag = _flapDrag = 1; + _flapLift = 0; _slatAlpha = 0; _spoilerLift = 1; + _inducedDrag = 1; } void Surface::setPosition(float* p) @@ -98,6 +104,11 @@ void Surface::setIncidence(float angle) _incidence = angle; } +void Surface::setTwist(float angle) +{ + _twist = angle; +} + void Surface::setSlatParams(float stallDelta, float dragPenalty) { _slatAlpha = stallDelta; @@ -142,7 +153,7 @@ void Surface::calcForce(float* v, float rho, float* out, float* torque) // Handle the blowup condition. Zero velocity means zero force by // definition. if(vel == 0) { - int i; + int i; for(i=0; i<3; i++) out[i] = torque[i] = 0; return; } @@ -155,18 +166,24 @@ void Surface::calcForce(float* v, float rho, float* out, float* torque) // "Rotate" by the incidence angle. Assume small angles, so we // need to diddle only the Z component, X is relatively unchanged // by small rotations. - out[2] += _incidence * out[0]; // z' = z + incidence * x + float incidence = _incidence + _twist; + out[2] += incidence * out[0]; // z' = z + incidence * x + // Hold onto the local wind vector so we can multiply the induced + // drag at the end. + float lwind[3]; + Math::set3(out, lwind); + // Diddle the Z force according to our configuration float stallMul = stallFunc(out); stallMul *= 1 + _spoilerPos * (_spoilerLift - 1); float stallLift = (stallMul - 1) * _cz * out[2]; - float flapLift = _cz * _flapPos * (_flapLift-1); + float flaplift = flapLift(out[2]); out[2] *= _cz; // scaling factor out[2] += _cz*_cz0; // zero-alpha lift out[2] += stallLift; - out[2] += flapLift; + out[2] += flaplift; // Airfoil lift (pre-stall and zero-alpha) torques "up" (negative // torque) around the Y axis, while flap lift pushes down. Both @@ -174,23 +191,29 @@ void Surface::calcForce(float* v, float rho, float* out, float* torque) // edge. Convert to local (i.e. airplane) coordiantes and store // into "torque". torque[0] = 0; - torque[1] = 0.1667 * _chord * (flapLift - (_cz*_cz0 + stallLift)); + torque[1] = 0.1667f * _chord * (flaplift - (_cz*_cz0 + stallLift)); torque[2] = 0; Math::tmul33(_orient, torque, torque); - // Diddle X (drag) and Y (side force) in the same manner - out[0] *= _cx * controlDrag(); + // The X (drag) force gets diddled for control deflection + out[0] = controlDrag(out[2], _cx * out[0]); + + // Add in any specific Y (side force) coefficient. out[1] *= _cy; + // Diddle the induced drag + Math::mul3(-1*_inducedDrag*out[2]*lwind[2], lwind, lwind); + Math::add3(lwind, out, out); + // Reverse the incidence rotation to get back to surface // coordinates. - out[2] -= _incidence * out[0]; + out[2] -= incidence * out[0]; // Convert back to external coordinates Math::tmul33(_orient, out, out); // Add in the units to make a real force: - float scale = 0.5*rho*vel*vel*_c0; + float scale = 0.5f*rho*vel*vel*_c0; Math::mul3(scale, out, out); Math::mul3(scale, torque, torque); } @@ -221,7 +244,7 @@ float Surface::stallFunc(float* v) return 1; // (note mask: we want to use the "positive" stall angle here) - float scale = 0.5*_peaks[fwdBak]/_stalls[i&2]; + float scale = 0.5f*_peaks[fwdBak]/_stalls[i&2]; // Before the stall if(alpha <= stallAlpha) @@ -235,24 +258,48 @@ float Surface::stallFunc(float* v) return scale*(1-frac) + frac; } -float Surface::controlDrag() +// Similar to the above -- interpolates out the flap lift past the +// stall alpha +float Surface::flapLift(float alpha) { - float d = 1; - d *= 1 + _spoilerPos * (_spoilerDrag - 1); - d *= 1 + _slatPos * (_slatDrag - 1); + float flapLift = _cz * _flapPos * (_flapLift-1); + if(alpha < 0) alpha = -alpha; + if(alpha < _stalls[0]) + return flapLift; + else if(alpha > _stalls[0] + _widths[0]) + return 1; + + float frac = (alpha - _stalls[0]) / _widths[0]; + frac = frac*frac*(3-2*frac); + return flapLift * (1-frac) + frac; +} + +float Surface::controlDrag(float lift, float drag) +{ // Negative flap deflections don't affect drag until their lift - // multiplier exceeds the "camber" (cz0) of the surface. + // multiplier exceeds the "camber" (cz0) of the surface. Use a + // synthesized "fp" number instead of the actual flap position. float fp = _flapPos; if(fp < 0) { fp = -fp; fp -= _cz0/(_flapLift-1); if(fp < 0) fp = 0; } - - d *= 1 + fp * (_flapDrag - 1); - - return d; + + // Calculate an "effective" drag -- this is the drag that would + // have been produced by an unflapped surface at the same lift. + float flapDragAoA = (_flapLift - 1 - _cz0) * _stalls[0]; + float fd = Math::abs(lift * flapDragAoA * fp); + if(drag < 0) fd = -fd; + drag += fd; + + // Now multiply by the various control factors + drag *= 1 + fp * (_flapDrag - 1); + drag *= 1 + _spoilerPos * (_spoilerDrag - 1); + drag *= 1 + _slatPos * (_slatDrag - 1); + + return drag; } }; // namespace yasim