예제 #1
0
        public void GetClCdCmSteady(InstantConditionSimInput input, out InstantConditionSimOutput output, bool clear, bool reset_stall = false)
        {
            output = new InstantConditionSimOutput();

            double area = 0;
            double MAC  = 0;
            double b_2  = 0;

            Vector3d forward = Vector3.forward;
            Vector3d up      = Vector3.up;
            Vector3d right   = Vector3.right;

            Vector3d    CoM       = Vector3d.zero;
            double      mass      = 0;
            List <Part> partsList = EditorLogic.SortedShipList;

            for (int i = 0; i < partsList.Count; i++)
            {
                Part p = partsList[i];

                if (FARAeroUtil.IsNonphysical(p))
                {
                    continue;
                }

                double partMass = p.mass;
                if (p.Resources.Count > 0)
                {
                    partMass += p.GetResourceMass();
                }

                //partMass += p.GetModuleMass(p.mass);
                // If you want to use GetModuleMass, you need to start from p.partInfo.mass, not p.mass
                CoM  += partMass * (Vector3d)p.transform.TransformPoint(p.CoMOffset);
                mass += partMass;
            }
            CoM /= mass;

            if (EditorDriver.editorFacility == EditorFacility.VAB)
            {
                forward = Vector3.up;
                up      = -Vector3.forward;
            }

            double sinAlpha = Math.Sin(input.alpha * Math.PI / 180);
            double cosAlpha = Math.Sqrt(Math.Max(1 - sinAlpha * sinAlpha, 0));

            double sinBeta = Math.Sin(input.beta * Math.PI / 180);
            double cosBeta = Math.Sqrt(Math.Max(1 - sinBeta * sinBeta, 0));

            double sinPhi = Math.Sin(input.phi * Math.PI / 180);
            double cosPhi = Math.Sqrt(Math.Max(1 - sinPhi * sinPhi, 0));

            double alphaDot = input.alphaDot * Math.PI / 180;
            double betaDot  = input.betaDot * Math.PI / 180;
            double phiDot   = input.phiDot * Math.PI / 180;

            Vector3d AngVel = (phiDot - sinAlpha * betaDot) * forward;

            AngVel += (cosPhi * alphaDot + cosAlpha * sinPhi * betaDot) * right;
            AngVel += (sinPhi * alphaDot - cosAlpha * cosPhi * betaDot) * up;

            Vector3d velocity = forward * cosAlpha * cosBeta;

            velocity += right * (sinPhi * cosAlpha * cosBeta + cosPhi * sinBeta);
            velocity += -up * cosPhi * (sinAlpha * cosBeta + sinBeta);

            velocity.Normalize();

            //this is negative wrt the ground
            Vector3d liftVector = -forward * sinAlpha + right * sinPhi * cosAlpha - up * cosPhi * cosAlpha;

            Vector3d sideways = Vector3.Cross(velocity, liftVector).normalized;


            for (int i = 0; i < _wingAerodynamicModel.Count; i++)
            {
                FARWingAerodynamicModel w = _wingAerodynamicModel[i];
                if (!(w && w.part))
                {
                    continue;
                }

                w.ComputeForceEditor(velocity.normalized, input.machNumber, 2);

                if (clear)
                {
                    w.EditorClClear(reset_stall);
                }

                Vector3d relPos = w.GetAerodynamicCenter() - CoM;

                Vector3d vel = velocity + Vector3d.Cross(AngVel, relPos);

                if (w is FARControllableSurface)
                {
                    (w as FARControllableSurface).SetControlStateEditor(CoM, vel, (float)input.pitchValue, 0, 0, input.flaps, input.spoilers);
                }
                else if (w.isShielded)
                {
                    continue;
                }


                //w.ComputeForceEditor(velocity, input.machNumber);     //do this just to get the AC right

                Vector3d force = w.ComputeForceEditor(vel.normalized, input.machNumber, 2) * 1000;

                output.Cl += -Vector3d.Dot(force, liftVector);
                output.Cy += Vector3d.Dot(force, sideways);
                output.Cd += -Vector3d.Dot(force, velocity);

                Vector3d moment = -Vector3d.Cross(relPos, force);

                output.Cm     += Vector3d.Dot(moment, sideways);
                output.Cn     += Vector3d.Dot(moment, liftVector);
                output.C_roll += Vector3d.Dot(moment, velocity);

                //w.ComputeClCdEditor(vel.normalized, input.machNumber);

                /*double tmpCl = w.GetCl() * w.S;
                 * output.Cl += tmpCl * -Vector3d.Dot(w.GetLiftDirection(), liftVector);
                 * output.Cy += tmpCl * -Vector3d.Dot(w.GetLiftDirection(), sideways);
                 * double tmpCd = w.GetCd() * w.S;
                 * output.Cd += tmpCd;
                 * output.Cm += tmpCl * Vector3d.Dot((relPos), velocity) * -Vector3d.Dot(w.GetLiftDirection(), liftVector) + tmpCd * -Vector3d.Dot((relPos), liftVector);
                 * output.Cn += tmpCd * Vector3d.Dot((relPos), sideways) + tmpCl * Vector3d.Dot((relPos), velocity) * -Vector3d.Dot(w.GetLiftDirection(), sideways);
                 * output.C_roll += tmpCl * Vector3d.Dot((relPos), sideways) * -Vector3d.Dot(w.GetLiftDirection(), liftVector);*/
                area += w.S;
                MAC  += w.GetMAC() * w.S;
                b_2  += w.Getb_2() * w.S;
            }
            FARCenterQuery center = new FARCenterQuery();

            for (int i = 0; i < _currentAeroSections.Count; i++)
            {
                _currentAeroSections[i].PredictionCalculateAeroForces(2, (float)input.machNumber, 10000, 0, 0.005f, velocity.normalized, center);
            }

            Vector3d centerForce = center.force * 1000;

            output.Cl += -Vector3d.Dot(centerForce, liftVector);
            output.Cy += Vector3d.Dot(centerForce, sideways);
            output.Cd += -Vector3d.Dot(centerForce, velocity);

            Vector3d centerMoment = -center.TorqueAt(CoM) * 1000;

            output.Cm     += Vector3d.Dot(centerMoment, sideways);
            output.Cn     += Vector3d.Dot(centerMoment, liftVector);
            output.C_roll += Vector3d.Dot(centerMoment, velocity);


            /*for (int i = 0; i < FARAeroUtil.CurEditorParts.Count; i++)
             * {
             *  Part p = FARAeroUtil.CurEditorParts[i];
             *  if (FARAeroUtil.IsNonphysical(p))
             *      continue;
             *
             *  Vector3 part_pos = p.transform.TransformPoint(p.CoMOffset) - CoM;
             *  double partMass = p.mass;
             *  if (p.Resources.Count > 0)
             *      partMass += p.GetResourceMass();
             *
             *  double stock_drag = partMass * p.maximum_drag * FlightGlobals.DragMultiplier * 1000;
             *  output.Cd += stock_drag;
             *  output.Cm += stock_drag * -Vector3d.Dot(part_pos, liftVector);
             *  output.Cn += stock_drag * Vector3d.Dot(part_pos, sideways);
             * }*/

            if (area == 0)
            {
                area = _maxCrossSectionFromBody;
                b_2  = 1;
                MAC  = _bodyLength;
            }

            double recipArea = 1 / area;

            MAC           *= recipArea;
            b_2           *= recipArea;
            output.Cl     *= recipArea;
            output.Cd     *= recipArea;
            output.Cm     *= recipArea / MAC;
            output.Cy     *= recipArea;
            output.Cn     *= recipArea / b_2;
            output.C_roll *= recipArea / b_2;
        }
예제 #2
0
        public void GetClCdCmSteady(Vector3d CoM, double alpha, double beta, double phi, double alphaDot, double betaDot, double phiDot, double M, double pitch, out double Cl, out double Cd, out double Cm, out double Cy, out double Cn, out double C_roll, bool clear, bool reset_stall = false, int flap_setting = 0, bool spoilersDeployed = false, bool vehicleFueled = true)
        {
            Cl     = 0;
            Cd     = 0;
            Cm     = 0;
            Cy     = 0;
            Cn     = 0;
            C_roll = 0;
            double area = 0;
            double MAC  = 0;
            double b_2  = 0;

            alpha *= FARMathUtil.deg2rad;
            beta  *= FARMathUtil.deg2rad;
            phi   *= FARMathUtil.deg2rad;

            Vector3d forward = Vector3.forward;
            Vector3d up      = Vector3.up;
            Vector3d right   = Vector3.right;

            if (EditorDriver.editorFacility == EditorFacility.VAB)
            {
                forward = Vector3.up;
                up      = -Vector3.forward;
            }

            Vector3d AngVel = (phiDot - Math.Sin(alpha) * betaDot) * forward + (Math.Cos(phi) * alphaDot + Math.Cos(alpha) * Math.Sin(phi) * betaDot) * right + (Math.Sin(phi) * alphaDot - Math.Cos(alpha) * Math.Cos(phi) * betaDot) * up;


            Vector3d velocity = forward * Math.Cos(alpha) * Math.Cos(beta) + right * (Math.Sin(phi) * Math.Sin(alpha) * Math.Cos(beta) - Math.Cos(phi) * Math.Sin(beta)) - up * (Math.Cos(phi) * Math.Sin(alpha) * Math.Cos(beta) - Math.Cos(phi) * Math.Sin(beta));

            velocity.Normalize();

            Vector3d liftVector = -forward *Math.Sin(alpha) + right * Math.Sin(phi) * Math.Cos(alpha) - up * Math.Cos(phi) * Math.Cos(alpha);

            Vector3d sideways = Vector3.Cross(velocity, liftVector);


            for (int i = 0; i < FARAeroUtil.CurEditorWings.Count; i++)
            {
                FARWingAerodynamicModel w = FARAeroUtil.CurEditorWings[i];
                if (w.isShielded)
                {
                    continue;
                }

                if (clear)
                {
                    w.EditorClClear(reset_stall);
                }

                Vector3d relPos = w.GetAerodynamicCenter() - CoM;

                Vector3d vel = velocity + Vector3d.Cross(AngVel, relPos);

                if (w is FARControllableSurface)
                {
                    (w as FARControllableSurface).SetControlStateEditor(CoM, vel, (float)pitch, 0, 0, flap_setting, spoilersDeployed);
                }

                w.ComputeClCdEditor(vel, M);

                double tmpCl = w.GetCl() * w.S;
                Cl += tmpCl * -Vector3d.Dot(w.GetLiftDirection(), liftVector);
                Cy += tmpCl * -Vector3d.Dot(w.GetLiftDirection(), sideways);
                double tmpCd = w.GetCd() * w.S;
                Cd     += tmpCd;
                Cm     += tmpCl * Vector3d.Dot((relPos), velocity) * -Vector3d.Dot(w.GetLiftDirection(), liftVector) + tmpCd * -Vector3d.Dot((relPos), liftVector);
                Cn     += tmpCd * Vector3d.Dot((relPos), sideways) + tmpCl * Vector3d.Dot((relPos), velocity) * -Vector3d.Dot(w.GetLiftDirection(), sideways);
                C_roll += tmpCl * Vector3d.Dot((relPos), sideways) * -Vector3d.Dot(w.GetLiftDirection(), liftVector);
                area   += w.S;
                MAC    += w.GetMAC() * w.S;
                b_2    += w.Getb_2() * w.S;
            }
            for (int i = 0; i < FARAeroUtil.CurEditorOtherDrag.Count; i++)
            {
                FARBasicDragModel d = FARAeroUtil.CurEditorOtherDrag[i];
                if (d.isShielded)
                {
                    continue;
                }

                Vector3d relPos = d.part.transform.position - CoM;

                Vector3d vel = velocity + Vector3d.Cross(AngVel, relPos);

                double tmpCd = d.GetDragEditor(vel, M);
                Cd += tmpCd;
                double tmpCl = d.GetLiftEditor();
                Cl     += tmpCl * -Vector3d.Dot(d.GetLiftDirection(), liftVector);
                Cy     += tmpCl * -Vector3d.Dot(d.GetLiftDirection(), sideways);
                relPos  = d.GetCoDWithoutMomentShift() - CoM;
                Cm     += d.GetMomentEditor() + tmpCl * Vector3d.Dot((relPos), velocity) * -Vector3d.Dot(d.GetLiftDirection(), liftVector) + tmpCd * -Vector3d.Dot((relPos), liftVector);
                Cn     += tmpCd * Vector3d.Dot((relPos), sideways) + tmpCl * Vector3d.Dot((relPos), velocity) * -Vector3d.Dot(d.GetLiftDirection(), sideways);
                C_roll += tmpCl * Vector3d.Dot((relPos), sideways) * -Vector3d.Dot(d.GetLiftDirection(), liftVector);
            }
            for (int i = 0; i < FARAeroUtil.CurEditorParts.Count; i++)
            {
                Part p = FARAeroUtil.CurEditorParts[i];
                if (FARAeroUtil.IsNonphysical(p))
                {
                    continue;
                }

                Vector3 part_pos = p.transform.TransformPoint(p.CoMOffset) - CoM;
                double  partMass = p.mass;
                if (vehicleFueled && p.Resources.Count > 0)
                {
                    partMass += p.GetResourceMass();
                }

                double stock_drag = partMass * p.maximum_drag * FlightGlobals.DragMultiplier * 1000;
                Cd += stock_drag;
                Cm += stock_drag * -Vector3d.Dot(part_pos, liftVector);
                Cn += stock_drag * Vector3d.Dot(part_pos, sideways);
            }
            if (area == 0)
            {
                area = 1;
                b_2  = 1;
                MAC  = 1;
            }

            double recipArea = 1 / area;

            MAC    *= recipArea;
            b_2    *= recipArea;
            Cl     *= recipArea;
            Cd     *= recipArea;
            Cm     *= recipArea / MAC;
            Cy     *= recipArea;
            Cn     *= recipArea / b_2;
            C_roll *= recipArea / b_2;
        }
예제 #3
0
        public void ResetClCdCmSteady(Vector3d CoM, InstantConditionSimInput input, out FARCenterQuery center, bool reset_cossweep, bool clear_clcd, bool reset_stall)
        {
            Vector3d velocity, liftDown, sideways, angVel, velVector;

            GetAxisVectors(CoM, input, out velocity, out liftDown, out sideways, out angVel);
            velVector = input.fltenv.VelocityVector(velocity);

            if (reset_cossweep)
            {
                for (int i = 0; i < _wingAerodynamicModel.Count; i++)
                {
                    FARWingAerodynamicModel w = _wingAerodynamicModel[i];
                    if (w == null)
                    {
                        continue;
                    }

                    w.ResetCosSweepAngle();
                }
            }

            for (int i = 0; i < _wingAerodynamicModel.Count; i++)
            {
                FARWingAerodynamicModel w = _wingAerodynamicModel[i];
                if (!(w && w.part))
                {
                    continue;
                }

                w.ComputeForceEditor(velVector, input.fltenv);
            }

            if (clear_clcd)
            {
                for (int i = 0; i < _wingAerodynamicModel.Count; i++)
                {
                    FARWingAerodynamicModel w = _wingAerodynamicModel[i];
                    if (!(w && w.part))
                    {
                        continue;
                    }

                    w.EditorClClear(reset_stall);
                }
            }

            for (int i = 0; i < _wingAerodynamicModel.Count; i++)
            {
                FARWingAerodynamicModel w = _wingAerodynamicModel[i];
                if (!(w && w.part))
                {
                    continue;
                }

                Vector3d relPos = w.GetAerodynamicCenter() - CoM;
                Vector3d vel    = velVector + Vector3d.Cross(angVel, relPos);

                if (w is FARControllableSurface)
                {
                    (w as FARControllableSurface).SetControlStateEditor(CoM, vel, (float)input.pitchValue, 0, 0, input.flaps, input.spoilers);
                }
                else if (w.isShielded)
                {
                    continue;
                }

                w.ComputeForceEditor(vel, input.fltenv);
            }

            center = new FARCenterQuery();
            for (int i = 0; i < _currentAeroSections.Count; i++)
            {
                // Rodhern: The hardcoded 2 for density is replaced, but some other parameters are still rough editor approximations.
                float  reynoldsPerUnitLength = 10000;
                float  pseudoKnudsenNumber   = 0;
                double pseudoLengthScale     = 1;
                float  skinFrictionDrag      = (float)input.fltenv.SkinFrictionDrag(pseudoLengthScale);
                _currentAeroSections[i].PredictionCalculateAeroForces((float)input.fltenv.Rho, (float)input.fltenv.MachNumber,
                                                                      reynoldsPerUnitLength, pseudoKnudsenNumber, skinFrictionDrag,
                                                                      velVector, center);
            }
        }
        public void GetClCdCmSteady(InstantConditionSimInput input, out InstantConditionSimOutput output, bool clear, bool reset_stall = false)
        {
            output = new InstantConditionSimOutput();

            double area = 0;
            double MAC  = 0;
            double b_2  = 0;

            Vector3d forward = Vector3.forward;
            Vector3d up      = Vector3.up;
            Vector3d right   = Vector3.right;

            Vector3d CoM = Vector3d.zero;

            if (EditorDriver.editorFacility == EditorFacility.VAB)
            {
                forward = Vector3.up;
                up      = -Vector3.forward;
            }

            double      mass      = 0;
            List <Part> partsList = EditorLogic.SortedShipList;

            for (int i = 0; i < partsList.Count; i++)
            {
                Part p = partsList[i];

                if (FARAeroUtil.IsNonphysical(p))
                {
                    continue;
                }

                double partMass = p.mass;
                if (p.Resources.Count > 0)
                {
                    partMass += p.GetResourceMass();
                }

                //partMass += p.GetModuleMass(p.mass);
                // If you want to use GetModuleMass, you need to start from p.partInfo.mass, not p.mass
                CoM  += partMass * (Vector3d)p.transform.TransformPoint(p.CoMOffset);
                mass += partMass;
            }
            CoM /= mass;

            // Rodhern: The original reference directions (velocity, liftVector, sideways) did not form an orthonormal
            //  basis. That in turn produced some counterintuitive calculation results, such as coupled yaw and pitch
            //  derivatives. A more thorough discussion of the topic can be found on the KSP forums:
            //  https://forum.kerbalspaceprogram.com/index.php?/topic/19321-131-ferram-aerospace-research-v01591-liepmann-4218/&do=findComment&comment=2781270
            //  The reference directions have been replaced by new ones that are orthonormal by construction.
            //  In dkavolis branch Vector3.Cross() and Vector3d.Normalize() are used explicitly. There is no apparent
            //  benefit to this other than possibly improved readability.

            double sinAlpha = Math.Sin(input.alpha * Math.PI / 180);
            double cosAlpha = Math.Sqrt(Math.Max(1 - sinAlpha * sinAlpha, 0));

            double sinBeta = Math.Sin(input.beta * Math.PI / 180);
            double cosBeta = Math.Sqrt(Math.Max(1 - sinBeta * sinBeta, 0));

            double sinPhi = Math.Sin(input.phi * Math.PI / 180);
            double cosPhi = Math.Sqrt(Math.Max(1 - sinPhi * sinPhi, 0));

            double alphaDot = input.alphaDot * Math.PI / 180;
            double betaDot  = input.betaDot * Math.PI / 180;
            double phiDot   = input.phiDot * Math.PI / 180;

            Vector3d velocity = forward * cosAlpha * cosBeta;

            velocity += right * (sinPhi * sinAlpha * cosBeta + cosPhi * sinBeta);
            velocity += -up * (cosPhi * sinAlpha * cosBeta - sinPhi * sinBeta);
            velocity.Normalize();

            Vector3d liftDown = -forward * sinAlpha;

            liftDown += right * sinPhi * cosAlpha;
            liftDown += -up * cosPhi * cosAlpha;
            liftDown.Normalize();

            //Vector3d sideways = -forward * cosAlpha * sinBeta;
            //sideways += right * (cosPhi * cosBeta - sinPhi * sinAlpha * sinBeta);
            //sideways += up * (cosPhi * sinAlpha * sinBeta + sinPhi * cosBeta);
            Vector3d sideways = Vector3.Cross(velocity, liftDown);

            sideways.Normalize();

            Vector3d angVel = forward * (phiDot - sinAlpha * betaDot);

            angVel += right * (cosPhi * alphaDot + cosAlpha * sinPhi * betaDot);
            angVel += up * (sinPhi * alphaDot - cosAlpha * cosPhi * betaDot);


            for (int i = 0; i < _wingAerodynamicModel.Count; i++)
            {
                FARWingAerodynamicModel w = _wingAerodynamicModel[i];
                if (!(w && w.part))
                {
                    continue;
                }

                w.ComputeForceEditor(velocity, input.machNumber, 2);

                if (clear)
                {
                    w.EditorClClear(reset_stall);
                }

                Vector3d relPos = w.GetAerodynamicCenter() - CoM;

                Vector3d vel = velocity + Vector3d.Cross(angVel, relPos);

                if (w is FARControllableSurface)
                {
                    (w as FARControllableSurface).SetControlStateEditor(CoM, vel, (float)input.pitchValue, 0, 0, input.flaps, input.spoilers);
                }
                else if (w.isShielded)
                {
                    continue;
                }


                //w.ComputeForceEditor(velocity, input.machNumber);     //do this just to get the AC right

                Vector3d force = w.ComputeForceEditor(vel.normalized, input.machNumber, 2) * 1000;

                output.Cl += -Vector3d.Dot(force, liftDown);
                output.Cy += Vector3d.Dot(force, sideways);
                output.Cd += -Vector3d.Dot(force, velocity);

                Vector3d moment = -Vector3d.Cross(relPos, force);

                output.Cm     += Vector3d.Dot(moment, sideways);
                output.Cn     += Vector3d.Dot(moment, liftDown);
                output.C_roll += Vector3d.Dot(moment, velocity);

                //w.ComputeClCdEditor(vel.normalized, input.machNumber);

                /*double tmpCl = w.GetCl() * w.S;
                 * output.Cl += tmpCl * -Vector3d.Dot(w.GetLiftDirection(), liftVector);
                 * output.Cy += tmpCl * -Vector3d.Dot(w.GetLiftDirection(), sideways);
                 * double tmpCd = w.GetCd() * w.S;
                 * output.Cd += tmpCd;
                 * output.Cm += tmpCl * Vector3d.Dot((relPos), velocity) * -Vector3d.Dot(w.GetLiftDirection(), liftVector) + tmpCd * -Vector3d.Dot((relPos), liftVector);
                 * output.Cn += tmpCd * Vector3d.Dot((relPos), sideways) + tmpCl * Vector3d.Dot((relPos), velocity) * -Vector3d.Dot(w.GetLiftDirection(), sideways);
                 * output.C_roll += tmpCl * Vector3d.Dot((relPos), sideways) * -Vector3d.Dot(w.GetLiftDirection(), liftVector);*/
                area += w.S;
                MAC  += w.GetMAC() * w.S;
                b_2  += w.Getb_2() * w.S;
            }

            FARCenterQuery center = new FARCenterQuery();

            for (int i = 0; i < _currentAeroSections.Count; i++)
            {
                _currentAeroSections[i].PredictionCalculateAeroForces(2, (float)input.machNumber, 10000, 0, 0.005f, velocity.normalized, center);
            }

            Vector3d centerForce = center.force * 1000;

            output.Cl += -Vector3d.Dot(centerForce, liftDown);
            output.Cy += Vector3d.Dot(centerForce, sideways);
            output.Cd += -Vector3d.Dot(centerForce, velocity);

            Vector3d centerMoment = -center.TorqueAt(CoM) * 1000;

            output.Cm     += Vector3d.Dot(centerMoment, sideways);
            output.Cn     += Vector3d.Dot(centerMoment, liftDown);
            output.C_roll += Vector3d.Dot(centerMoment, velocity);


            /*for (int i = 0; i < FARAeroUtil.CurEditorParts.Count; i++)
             * {
             *  Part p = FARAeroUtil.CurEditorParts[i];
             *  if (FARAeroUtil.IsNonphysical(p))
             *      continue;
             *
             *  Vector3 part_pos = p.transform.TransformPoint(p.CoMOffset) - CoM;
             *  double partMass = p.mass;
             *  if (p.Resources.Count > 0)
             *      partMass += p.GetResourceMass();
             *
             *  double stock_drag = partMass * p.maximum_drag * FlightGlobals.DragMultiplier * 1000;
             *  output.Cd += stock_drag;
             *  output.Cm += stock_drag * -Vector3d.Dot(part_pos, liftVector);
             *  output.Cn += stock_drag * Vector3d.Dot(part_pos, sideways);
             * }*/

            if (area.NearlyEqual(0))
            {
                area = _maxCrossSectionFromBody;
                b_2  = 1;
                MAC  = _bodyLength;
            }

            double recipArea = 1 / area;

            MAC           *= recipArea;
            b_2           *= recipArea;
            output.Cl     *= recipArea;
            output.Cd     *= recipArea;
            output.Cm     *= recipArea / MAC;
            output.Cy     *= recipArea;
            output.Cn     *= recipArea / b_2;
            output.C_roll *= recipArea / b_2;
        }
예제 #5
0
        public void GetClCdCmSteady(InstantConditionSimInput input, out InstantConditionSimOutput output, bool clear, bool reset_stall)
        {
            Vector3d CoM;
            double   mass, area, MAC, b; // mass not actually used in these calculations

            GetCoMAndSize(out CoM, out mass, out area, out MAC, out b);

            FARCenterQuery center;

            ResetClCdCmSteady(CoM, input, out center, false, clear, reset_stall);

            Vector3d velocity, liftDown, sideways, angVel, velVector;

            GetAxisVectors(CoM, input, out velocity, out liftDown, out sideways, out angVel);
            velVector = input.fltenv.VelocityVector(velocity);

            output = new InstantConditionSimOutput();

            for (int i = 0; i < _wingAerodynamicModel.Count; i++)
            {
                FARWingAerodynamicModel w = _wingAerodynamicModel[i];
                if (!(w && w.part) || w.isShielded)
                {
                    continue;
                }

                Vector3d relPos = w.GetAerodynamicCenter() - CoM;
                Vector3d vel    = velVector + Vector3d.Cross(angVel, relPos);
                Vector3d force  = w.ComputeForceEditor(vel, input.fltenv);

                output.Cl += -Vector3d.Dot(force, liftDown);
                output.Cd += -Vector3d.Dot(force, velocity);
                output.Cy += Vector3d.Dot(force, sideways);

                Vector3d moment = -Vector3d.Cross(relPos, force);

                output.Cm     += Vector3d.Dot(moment, sideways);
                output.Cn     += Vector3d.Dot(moment, liftDown);
                output.C_roll += Vector3d.Dot(moment, velocity);
            }

            Vector3d centerForce = center.force;

            output.Cl += -Vector3d.Dot(centerForce, liftDown);
            output.Cd += -Vector3d.Dot(centerForce, velocity);
            output.Cy += Vector3d.Dot(centerForce, sideways);

            Vector3d centerMoment = -center.TorqueAt(CoM);

            output.Cm     += Vector3d.Dot(centerMoment, sideways);
            output.Cn     += Vector3d.Dot(centerMoment, liftDown);
            output.C_roll += Vector3d.Dot(centerMoment, velocity);

            double q     = input.fltenv.DynamicPressure();
            double recip = 1 / (q * area); // reciprocal value to area and dynamic pressure

            output.Cl     *= recip;
            output.Cd     *= recip;
            output.Cy     *= recip;
            output.Cm     *= recip / MAC;
            output.Cn     *= recip / b;
            output.C_roll *= recip / b;
        }