Ejemplo n.º 1
0
        //Retreives an "apparent" diameter from a DragCube
        private float GetApparentDiameter(DragCube cube)
        {
            float area = 0;

            for (int i = 0; i < 6; i++)
            {
                area += cube.Area[i] * cube.Drag[i]
                        * PhysicsGlobals.DragCurveValue((Vector3.Dot(Vector3.up, DragCubeList.GetFaceDirection((DragCube.DragFace)i)) + 1f) * 0.5f, 0);
            }
            return((float)(Math.Max(Math.Round(Math.Sqrt((area * PhysicsGlobals.DragCubeMultiplier * PhysicsGlobals.DragMultiplier) / Math.PI) * 2d, 1, MidpointRounding.AwayFromZero), 0.1)));
        }
Ejemplo n.º 2
0
        //Retreives an "apparent" diameter from a DragCube
        private static float GetApparentDiameter(DragCube cube)
        {
            float area = 0;

            for (int i = 0; i < 6; i++)
            {
                // TODO 1.2: according to API docs this method should have only 2 arguments but it has 3
                area += cube.Area[i] * cube.Drag[i]
                        * PhysicsGlobals.DragCurveValue(PhysicsGlobals.SurfaceCurves, (Vector3.Dot(Vector3.up, DragCubeList.GetFaceDirection((DragCube.DragFace)i)) + 1) * 0.5f, 0);
            }
            return((float)Math.Max(Math.Round(Math.Sqrt((area * 0.1f * PhysicsGlobals.DragMultiplier) / Math.PI) * 2, 1, MidpointRounding.AwayFromZero), 0.1));
        }
Ejemplo n.º 3
0
        public DragCubeList.CubeData AddSurfaceDragDirection(Vector3 direction, float machNumber)
        {
            part.DragCubes.SetDrag(direction, machNumber);
            //var liftCurves = GetPrivate<PhysicsGlobals.LiftingSurfaceCurve>("liftCurves", part.DragCubes);
            var   liftCurves = part.DragCubes.BodyLiftCurve;
            float num        = 0;

            DragCubeList.CubeData result = default(DragCubeList.CubeData);
            result.dragVector = direction;
            for (int i = 0; i < 6; i++)
            {
                Vector3 faceDirection = DragCubeList.GetFaceDirection((DragCube.DragFace)i);
                float   num2          = Vector3.Dot(direction, faceDirection);
                float   dotNormalized = (num2 + 1) * 0.5f;
                float   num3          = PhysicsGlobals.DragCurveValue(PhysicsGlobals.SurfaceCurves, dotNormalized, machNumber);
                float   num4          = this.areaOccluded [i] * num3;
                float   num5          = this.weightedDrag [i];
                float   num6          = num5;
                if (num6 < 1)
                {
                    num6 = PhysicsGlobals.DragCurveCd.Evaluate(num6);
                }
                result.area               += num4;
                result.areaDrag           += num4 * num6;
                result.crossSectionalArea += this.areaOccluded [i] * Mathf.Clamp01(num2);
                if (num5 < 0.01)
                {
                    num5 = 1;
                }
                if (num5 < 1)
                {
                    num5 = 1 / num5;
                }
                result.exposedArea += num4 / PhysicsGlobals.DragCurveMultiplier.Evaluate(machNumber) * num5;
                if (num2 > 0)
                {
                    num += num2;
                    double num7 = (double)liftCurves.liftCurve.Evaluate(num2);
                    if (!double.IsNaN(num7))
                    {
                        result.liftForce += -faceDirection * (num2 * this.areaOccluded [i] * this.weightedDrag [i] * (float)num7);
                    }
                    result.depth     += num2 * this.weightedDepth [i];
                    result.dragCoeff += num2 * num6;
                }
            }
            float num8 = 1 / num;

            result.depth     *= num8;
            result.dragCoeff *= num8;
            return(result);
        }
        double drag(double s, double h, double v)
        {
            if (h > Body.atmosphereDepth)
            {
                return(0);
            }
            var atm  = Body.AtmoParamsAtAltitude(h);
            var v2   = v * v;
            var dP   = atm.Rho * v2 / 2;
            var mach = v / atm.Mach1;
            var d    = Cd *
                       PhysicsGlobals.DragCurveValue(PhysicsGlobals.SurfaceCurves, C.DragCurveK, (float)mach) *
                       PhysicsGlobals.DragCurvePseudoReynolds.Evaluate((float)(atm.Rho * Math.Abs(v)));

            return(dP * d * s);
        }
Ejemplo n.º 5
0
            public SimCurves(CelestialBody mainBody)
            {
                dragCurveMultiplier     = new FloatCurve(PhysicsGlobals.DragCurveMultiplier.Curve.keys);
                dragCurveSurface        = new FloatCurve(PhysicsGlobals.DragCurveSurface.Curve.keys);
                dragCurveTail           = new FloatCurve(PhysicsGlobals.DragCurveTail.Curve.keys);
                dragCurveTip            = new FloatCurve(PhysicsGlobals.DragCurveTip.Curve.keys);
                liftCurve               = new FloatCurve(PhysicsGlobals.GetLiftingSurfaceCurve("BodyLift").liftCurve.Curve.keys);
                liftMachCurve           = new FloatCurve(PhysicsGlobals.GetLiftingSurfaceCurve("BodyLift").liftMachCurve.Curve.keys);
                atmospherePressureCurve = new FloatCurve(mainBody.atmospherePressureCurve.Curve.keys);

                atmosphereTemperatureSunMultCurve = new FloatCurve(mainBody.atmosphereTemperatureSunMultCurve.Curve.keys);
                latitudeTemperatureBiasCurve      = new FloatCurve(mainBody.latitudeTemperatureBiasCurve.Curve.keys);
                latitudeTemperatureSunMultCurve   = new FloatCurve(mainBody.latitudeTemperatureSunMultCurve.Curve.keys);
                atmosphereTemperatureCurve        = new FloatCurve(mainBody.atmosphereTemperatureCurve.Curve.keys);
                axialTemperatureSunMultCurve      = new FloatCurve(mainBody.axialTemperatureSunMultCurve.Curve.keys);
            }
Ejemplo n.º 6
0
            public void Update()
            {
                Altitude    = pos.magnitude - Body.Radius;
                Atmosphere  = Body.atmosphere && Altitude < Body.atmosphereDepth;
                rel_pos     = Body.BodyFrame.WorldToLocal(TrajectoryCalculator.BodyRotationAtdT(Body, Path.UT0 - UT) * pos);
                srf_vel     = vel + Vector3d.Cross(Body.zUpAngularVelocity, pos);
                HorSrfSpeed = Vector3d.Exclude(rel_pos, srf_vel).magnitude;
                SrfSpeed    = srf_vel.magnitude;

                if (Atmosphere)
                {
                    Pressure = Body.GetPressure(Altitude);
                    AtmosphereTemperature = Body.GetTemperature(Altitude);
                    Density = Body.GetDensity(Pressure, AtmosphereTemperature);
                    Mach1   = Body.GetSpeedOfSound(Pressure, Density);

                    var Rho_v = Density * SrfSpeed;
                    DynamicPressure = Rho_v * SrfSpeed / 2;
                    Mach            = SrfSpeed / Mach1;
                    SpecificDrag    = AtmoSim.Cd * DynamicPressure *
                                      PhysicsGlobals.DragCurveValue(PhysicsGlobals.SurfaceCurves, VSL.OnPlanetParams.DragCurveK, (float)Mach) *
                                      PhysicsGlobals.DragCurvePseudoReynolds.Evaluate((float)(Rho_v));

                    var convectiveMachLerp = Math.Pow(UtilMath.Clamp01((Mach - PhysicsGlobals.NewtonianMachTempLerpStartMach) /
                                                                       (PhysicsGlobals.NewtonianMachTempLerpEndMach - PhysicsGlobals.NewtonianMachTempLerpStartMach)),
                                                      PhysicsGlobals.NewtonianMachTempLerpExponent);
                    ShockTemperature = SrfSpeed * PhysicsGlobals.NewtonianTemperatureFactor;
                    if (convectiveMachLerp > 0.0)
                    {
                        double b = PhysicsGlobals.MachTemperatureScalar * Math.Pow(SrfSpeed, PhysicsGlobals.MachTemperatureVelocityExponent);
                        ShockTemperature = UtilMath.LerpUnclamped(ShockTemperature, b, convectiveMachLerp);
                    }
                    ShockTemperature *= (double)HighLogic.CurrentGame.Parameters.Difficulty.ReentryHeatScale * Body.shockTemperatureMultiplier;
                    ShockTemperature  = Math.Max(AtmosphereTemperature, ShockTemperature);
                    //calculate convective coefficient for speed > Mach1; lower speed is not a concern
                    ConvectiveCoefficient  = 1E-10 * PhysicsGlobals.MachConvectionFactor;
                    ConvectiveCoefficient *= Density > 1 ? Density : Math.Pow(Density, PhysicsGlobals.MachConvectionDensityExponent);
                    ConvectiveCoefficient *= Math.Pow(SrfSpeed, PhysicsGlobals.MachConvectionVelocityExponent) * Body.convectionMultiplier;
                }
            }
Ejemplo n.º 7
0
        private void Update()
        {
            if (fairingTemperatureRenderer_1 != null && !isDeployed)
            {
                if (HighLogic.LoadedSceneIsFlight)
                {
                    if (fairingTemperatureRenderer_1 != null)
                    {
                        fairingTemperatureRenderer_1.Update(PhysicsGlobals.GetBlackBodyRadiation((float)base.part.skinTemperature, base.part), false);
                    }

                    if (fairingTemperatureRenderer_2 != null)
                    {
                        fairingTemperatureRenderer_2.Update(PhysicsGlobals.GetBlackBodyRadiation((float)base.part.skinTemperature, base.part), false);
                    }
                }
                else
                {
                    fairingTemperatureRenderer_1.Update(Color.clear, false);
                }
            }
        }
Ejemplo n.º 8
0
        //*******************************************************
        public static Vector3 SimAeroForce(Vessel _vessel, Vector3 v_wrld_vel, double altitude, double latitude = 0)
        {
            CelestialBody body     = _vessel.mainBody;
            double        pressure = body.GetPressure(altitude);
            // Lift and drag for force accumulation.
            Vector3d total_lift = Vector3d.zero;
            Vector3d total_drag = Vector3d.zero;

            // dynamic pressure for standard drag equation
            double rho          = GetDensity(altitude, body);
            double dyn_pressure = 0.0005 * rho * v_wrld_vel.sqrMagnitude;

            if (rho <= 0)
            {
                return(Vector3.zero);
            }

            double soundSpeed = body.GetSpeedOfSound(pressure, rho);
            double mach       = v_wrld_vel.magnitude / soundSpeed;

            if (mach > 25.0)
            {
                mach = 25.0;
            }

            // Loop through all parts, accumulating drag and lift.
            for (int i = 0; i < _vessel.Parts.Count; ++i)
            {
                // need checks on shielded components
                Part p = _vessel.Parts[i];
                if (p.ShieldedFromAirstream || p.Rigidbody == null)
                {
                    continue;
                }

                // Get Drag
                Vector3 sim_dragVectorDir      = v_wrld_vel.normalized;
                Vector3 sim_dragVectorDirLocal = -(p.transform.InverseTransformDirection(sim_dragVectorDir));

                Vector3  liftForce = new Vector3(0, 0, 0);
                Vector3d dragForce;

                switch (p.dragModel)
                {
                case Part.DragModel.DEFAULT:
                case Part.DragModel.CUBE:
                    DragCubeList cubes = p.DragCubes;

                    DragCubeList.CubeData p_drag_data = new DragCubeList.CubeData();

                    float drag;
                    if (cubes.None)     // since 1.0.5, some parts don't have drag cubes (for example fuel lines and struts)
                    {
                        drag = p.maximum_drag;
                    }
                    else
                    {
                        try
                        {
                            cubes.AddSurfaceDragDirection(-sim_dragVectorDirLocal, (float)mach, ref p_drag_data);
                        }
                        catch (Exception)
                        {
                            cubes.SetDrag(sim_dragVectorDirLocal, (float)mach);
                            cubes.ForceUpdate(true, true);
                            cubes.AddSurfaceDragDirection(-sim_dragVectorDirLocal, (float)mach, ref p_drag_data);
                            //Debug.Log(String.Format("Trajectories: Caught NRE on Drag Initialization.  Should be fixed now.  {0}", e));
                        }

                        float pseudoreynolds   = (float)(rho * Mathf.Abs(v_wrld_vel.magnitude));
                        float pseudoredragmult = PhysicsGlobals.DragCurvePseudoReynolds.Evaluate(pseudoreynolds);
                        drag = p_drag_data.areaDrag * PhysicsGlobals.DragCubeMultiplier * pseudoredragmult;

                        liftForce = p_drag_data.liftForce;
                    }

                    double sim_dragScalar = dyn_pressure * (double)drag * PhysicsGlobals.DragMultiplier;
                    dragForce = -(Vector3d)sim_dragVectorDir * sim_dragScalar;

                    break;

                case Part.DragModel.SPHERICAL:
                    dragForce = -(Vector3d)sim_dragVectorDir * (double)p.maximum_drag;
                    break;

                case Part.DragModel.CYLINDRICAL:
                    dragForce = -(Vector3d)sim_dragVectorDir * (double)Mathf.Lerp(p.minimum_drag, p.maximum_drag, Mathf.Abs(Vector3.Dot(p.partTransform.TransformDirection(p.dragReferenceVector), sim_dragVectorDir)));
                    break;

                case Part.DragModel.CONIC:
                    dragForce = -(Vector3d)sim_dragVectorDir * (double)Mathf.Lerp(p.minimum_drag, p.maximum_drag, Vector3.Angle(p.partTransform.TransformDirection(p.dragReferenceVector), sim_dragVectorDir) / 180f);
                    break;

                default:
                    // no drag to apply
                    dragForce = new Vector3d();
                    break;
                }

                total_drag += dragForce;

                // If it isn't a wing or lifter, get body lift.
                if (!p.hasLiftModule)
                {
                    float simbodyLiftScalar = p.bodyLiftMultiplier * PhysicsGlobals.BodyLiftMultiplier * (float)dyn_pressure;
                    simbodyLiftScalar *= PhysicsGlobals.GetLiftingSurfaceCurve("BodyLift").liftMachCurve.Evaluate((float)mach);
                    Vector3 bodyLift = p.transform.rotation * (simbodyLiftScalar * liftForce);
                    bodyLift = Vector3.ProjectOnPlane(bodyLift, sim_dragVectorDir);
                    // Only accumulate forces for non-LiftModules
                    //Debug.Log("[Trajectories] bodyLift=" + bodyLift);
                    total_lift += bodyLift;
                }

                // Find ModuleLifingSurface for wings and liftforce.
                // Should catch control surface as it is a subclass
                for (int j = 0; j < p.Modules.Count; ++j)
                {
                    var   m = p.Modules[j];
                    float mcs_mod;
                    if (m is ModuleLiftingSurface)
                    {
                        mcs_mod = 1.0f;
                        double liftQ = dyn_pressure * 1000;
                        ModuleLiftingSurface wing = (ModuleLiftingSurface)m;
                        Vector3 nVel       = Vector3.zero;
                        Vector3 liftVector = Vector3.zero;
                        float   liftdot;
                        float   absdot;
                        wing.SetupCoefficients(v_wrld_vel, out nVel, out liftVector, out liftdot, out absdot);

                        double prevMach = p.machNumber;
                        p.machNumber = mach;
                        Vector3 local_lift = mcs_mod * wing.GetLiftVector(liftVector, liftdot, absdot, liftQ, (float)mach);
                        Vector3 local_drag = mcs_mod * wing.GetDragVector(nVel, absdot, liftQ);
                        p.machNumber = prevMach;

                        total_lift += local_lift;
                        total_drag += local_drag;
                    }
                }
            }
            // RETURN STUFF
            //Debug.Log("[Trajectories] total_lift" + total_lift + " total_drag=" + total_drag);
            Vector3 force = total_lift + total_drag;

            return(force);
        }
Ejemplo n.º 9
0
        void Start()
        {
            Debug.Log("[CorrectCoL]: Starting!");

            if (!far_searched)
            {
                foreach (var a in AppDomain.CurrentDomain.GetAssemblies())
                {
                    if (a.GetName().Name.Equals("FerramAerospaceResearch"))
                    {
                        far_found = true;
                        break;
                    }
                }
                far_searched = true;
            }
            if (far_found)
            {
                Debug.Log("[CorrectCoL]: FAR found, disabling itself!");
                GameObject.Destroy(this.gameObject);
                return;
            }

            overlays = EditorVesselOverlays.fetch;
            if (overlays == null)
            {
                Debug.Log("[CorrectCoL]: overlays is null!");
                GameObject.Destroy(this.gameObject);
                return;
            }
            old_CoL_marker = overlays.CoLmarker;
            if (old_CoL_marker == null)
            {
                Debug.Log("[CorrectCoL]: CoL_marker is null!");
                GameObject.Destroy(this.gameObject);
                return;
            }
            bodylift_curves = PhysicsGlobals.GetLiftingSurfaceCurve("BodyLift");
            if (new_CoL_marker == null)
            {
                new_CoL_marker                 = this.gameObject.AddComponent <CoLMarkerFull>();
                CoLMarkerFull.lift_curves      = bodylift_curves;
                new_CoL_marker.posMarkerObject = (GameObject)GameObject.Instantiate(old_CoL_marker.dirMarkerObject);
                new_CoL_marker.posMarkerObject.transform.parent     = new_CoL_marker.transform;
                new_CoL_marker.posMarkerObject.transform.localScale = new Vector3(0.5f, 0.5f, 0.5f);
                new_CoL_marker.posMarkerObject.SetActive(false);
                new_CoL_marker.posMarkerObject.layer = 2;
                foreach (Transform child in new_CoL_marker.posMarkerObject.transform)
                {
                    child.gameObject.layer = 2;
                }
                GameEvents.onEditorRestart.Add(new EventVoid.OnEvent(TurnOffCoL));
                // should be called once, so let's deserialize graph here too
                GraphWindow.load_settings();
                GraphWindow.init_textures(true);
                GraphWindow.init_reflections();

                clickEvent = new Button.ButtonClickedEvent();
                clickEvent.AddListener(ToggleCoL);
            }
            GameEvents.onGUIApplicationLauncherReady.Add(onAppLauncherLoad);
            GameEvents.onGUIApplicationLauncherUnreadifying.Add(onAppLauncherUnload);
            onAppLauncherLoad();
            GraphWindow.shown      = false;
            new_CoL_marker.enabled = false;
            old_CoL_marker.gameObject.SetActive(false);
            overlays.toggleCoLbtn.onClick = clickEvent;
            //overlays.toggleCoLbtn.methodToInvoke = "ToggleCoL";
        }
Ejemplo n.º 10
0
        //*******************************************************
        public static Vector3d SimAeroForce(Vessel vessel, Vector3d v_wrld_vel, double altitude, double latitude = 0.0)
        {
            Profiler.Start("SimAeroForce");

            CelestialBody body     = vessel.mainBody;
            double        pressure = body.GetPressure(altitude);
            // Lift and drag for force accumulation.
            Vector3d total_lift = Vector3d.zero;
            Vector3d total_drag = Vector3d.zero;

            // dynamic pressure for standard drag equation
            double rho          = GetDensity(altitude, body);
            double dyn_pressure = 0.0005 * rho * v_wrld_vel.sqrMagnitude;

            if (rho <= 0)
            {
                return(Vector3.zero);
            }

            double soundSpeed = body.GetSpeedOfSound(pressure, rho);
            double mach       = v_wrld_vel.magnitude / soundSpeed;

            if (mach > 25.0)
            {
                mach = 25.0;
            }

            // Loop through all parts, accumulating drag and lift.
            for (int i = 0; i < vessel.Parts.Count; ++i)
            {
                // need checks on shielded components
                Part p = vessel.Parts[i];
#if DEBUG
                TrajectoriesDebug partDebug = VesselAerodynamicModel.DebugParts ? p.FindModuleImplementing <TrajectoriesDebug>() : null;
                if (partDebug != null)
                {
                    partDebug.Drag = 0;
                    partDebug.Lift = 0;
                }
#endif

                if (p.ShieldedFromAirstream || p.Rigidbody == null)
                {
                    continue;
                }

                // Get Drag
                Vector3d sim_dragVectorDir      = v_wrld_vel.normalized;
                Vector3d sim_dragVectorDirLocal = -(p.transform.InverseTransformDirection(sim_dragVectorDir));

                Vector3d liftForce = Vector3d.zero;
                Vector3d dragForce;


                Profiler.Start("SimAeroForce#drag");
                switch (p.dragModel)
                {
                case Part.DragModel.DEFAULT:
                case Part.DragModel.CUBE:
                    DragCubeList cubes = p.DragCubes;

                    DragCubeList.CubeData p_drag_data = new DragCubeList.CubeData();

                    double drag;
                    if (cubes.None)     // since 1.0.5, some parts don't have drag cubes (for example fuel lines and struts)
                    {
                        drag = p.maximum_drag;
                    }
                    else
                    {
                        try
                        {
                            cubes.AddSurfaceDragDirection(-sim_dragVectorDirLocal, (float)mach, ref p_drag_data);
                        }
                        catch (Exception e)
                        {
                            cubes.SetDrag(sim_dragVectorDirLocal, (float)mach);
                            cubes.ForceUpdate(true, true);
                            cubes.AddSurfaceDragDirection(-sim_dragVectorDirLocal, (float)mach, ref p_drag_data);
                            Util.DebugLogError("Exception {0} on drag initialization", e);
                        }

                        double pseudoreynolds   = rho * Math.Abs(v_wrld_vel.magnitude);
                        double pseudoredragmult = PhysicsGlobals.DragCurvePseudoReynolds.Evaluate((float)pseudoreynolds);
                        drag = p_drag_data.areaDrag * PhysicsGlobals.DragCubeMultiplier * pseudoredragmult;

                        liftForce = p_drag_data.liftForce;
                    }

                    double sim_dragScalar = dyn_pressure * drag * PhysicsGlobals.DragMultiplier;
                    dragForce = -sim_dragVectorDir * sim_dragScalar;

                    break;

                case Part.DragModel.SPHERICAL:
                    dragForce = -sim_dragVectorDir * p.maximum_drag;
                    break;

                case Part.DragModel.CYLINDRICAL:
                    dragForce = -sim_dragVectorDir *Mathf.Lerp(p.minimum_drag, p.maximum_drag, Mathf.Abs(Vector3.Dot(p.partTransform.TransformDirection(p.dragReferenceVector), sim_dragVectorDir)));

                    break;

                case Part.DragModel.CONIC:
                    dragForce = -sim_dragVectorDir *Mathf.Lerp(p.minimum_drag, p.maximum_drag, Vector3.Angle(p.partTransform.TransformDirection(p.dragReferenceVector), sim_dragVectorDir) / 180f);

                    break;

                default:
                    // no drag to apply
                    dragForce = Vector3d.zero;
                    break;
                }

                Profiler.Stop("SimAeroForce#drag");

#if DEBUG
                if (partDebug != null)
                {
                    partDebug.Drag += (float)dragForce.magnitude;
                }
#endif
                total_drag += dragForce;

                // If it isn't a wing or lifter, get body lift.
                if (!p.hasLiftModule)
                {
                    Profiler.Start("SimAeroForce#BodyLift");

                    float simbodyLiftScalar = p.bodyLiftMultiplier * PhysicsGlobals.BodyLiftMultiplier * (float)dyn_pressure;
                    simbodyLiftScalar *= PhysicsGlobals.GetLiftingSurfaceCurve("BodyLift").liftMachCurve.Evaluate((float)mach);
                    Vector3 bodyLift = p.transform.rotation * (simbodyLiftScalar * liftForce);
                    bodyLift = Vector3.ProjectOnPlane(bodyLift, sim_dragVectorDir);
                    // Only accumulate forces for non-LiftModules
                    total_lift += bodyLift;


                    Profiler.Stop("SimAeroForce#BodyLift");
                }


                Profiler.Start("SimAeroForce#LiftingSurface");

                // Find ModuleLifingSurface for wings and liftforce.
                // Should catch control surface as it is a subclass
                for (int j = 0; j < p.Modules.Count; ++j)
                {
                    var m = p.Modules[j];
                    if (m is ModuleLiftingSurface wing)
                    {
                        const float mcs_mod = 1.0f;
                        double      liftQ   = dyn_pressure * 1000;
                        wing.SetupCoefficients(v_wrld_vel, out var nVel, out var liftVector, out var liftdot, out var absdot);

                        double prevMach = p.machNumber;
                        p.machNumber = mach;
                        Vector3 local_lift = mcs_mod * wing.GetLiftVector(liftVector, liftdot, absdot, liftQ, (float)mach);
                        Vector3 local_drag = mcs_mod * wing.GetDragVector(nVel, absdot, liftQ);
                        p.machNumber = prevMach;

                        total_lift += local_lift;
                        total_drag += local_drag;

#if DEBUG
                        if (partDebug != null)
                        {
                            partDebug.Lift += local_lift.magnitude;
                            partDebug.Drag += local_drag.magnitude;
                        }
#endif
                    }
                }

                Profiler.Stop("SimAeroForce#LiftingSurface");
            }

            // RETURN STUFF
            Vector3 force = total_lift + total_drag;

            Profiler.Stop("SimAeroForce");
            return(force);
        }
        //Retrieve the vector sum of the lift and drag forces on the part when wind is present.
        public List <Vector3> GetDragLiftForce(ModularFI.ModularFlightIntegrator fi, Part p, Vector3d vel, Vector3d windVec, double mach, bool isgrounded)
        {
            //Initialize forces
            Vector3 total_drag = Vector3d.zero;
            Vector3 total_lift = Vector3d.zero;

            List <Vector3> total = new List <Vector3>();

            //Set Part drag based on new air velocity
            p.dragVector       = vel;
            p.dragVectorSqrMag = p.dragVector.sqrMagnitude;
            //Update dynamic pressure
            p.dynamicPressurekPa = 0.0005 * p.atmDensity * p.dragVectorSqrMag;
            //If part darg is near zero or part is shielded do not calculate force sum
            if (p.dragVectorSqrMag.NearlyEqual(0) || p.ShieldedFromAirstream)
            {
                p.dragVectorMag      = 0f;
                p.dragVectorDir      = Vector3.zero;
                p.dragVectorDirLocal = Vector3.zero;
                p.dragScalar         = 0f;
            }
            //Update drag vector
            p.dragVectorMag      = (float)Math.Sqrt(p.dragVectorSqrMag);
            p.dragVectorDir      = p.dragVector / p.dragVectorMag;
            p.dragVectorDirLocal = -p.transform.InverseTransformDirection(p.dragVectorDir);

            if (((!p.DragCubes.None) && (!p.hasLiftModule)) || (p.name.Contains("kerbalEVA")))
            {
                //Apply drag vector direction to drag cube
                Vector3 drag_force = Vector3.zero;
                //Update angular drag (adapated from FAR)
                p.DragCubes.SetDrag(p.dragVectorDirLocal, (float)mach);
                //Calculate drag force and set dragScalar (adapated from Trajectories mod)
                double pseudoreynolds   = p.atmDensity * Math.Abs(vel.magnitude);
                double pseudoReDragMult = PhysicsGlobals.DragCurvePseudoReynolds.Evaluate((float)pseudoreynolds);
                double drag             = p.DragCubes.AreaDrag * PhysicsGlobals.DragCubeMultiplier * pseudoReDragMult;
                p.dragScalar = (float)(p.dynamicPressurekPa * drag * PhysicsGlobals.DragMultiplier);
                //Add drag force to total drag
                drag_force  = -p.dragVectorDir * p.dragScalar;
                total_drag += drag_force;

                //Estimate lift force from body lift
                p.bodyLiftScalar = (float)(p.dynamicPressurekPa * p.bodyLiftMultiplier * PhysicsGlobals.BodyLiftMultiplier) * PhysicsGlobals.GetLiftingSurfaceCurve("BodyLift").liftMachCurve.Evaluate((float)mach);
                Vector3 lforce = p.transform.rotation * (p.bodyLiftScalar * p.DragCubes.LiftForce);
                lforce = Vector3.ProjectOnPlane(lforce, -p.dragVectorDir);
                //Add lift force if vessel is on the ground
                total_lift += lforce;
            }

            for (int j = 0; j < p.Modules.Count; ++j)
            {
                var m = p.Modules[j];
                if (m is ModuleLiftingSurface)
                {
                    //Initialize force vectors
                    Vector3 lforce3 = Vector3.zero;
                    Vector3 dforce3 = Vector3.zero;
                    //Convert kPa to Pa
                    double liftQ = p.dynamicPressurekPa * 1000;
                    ModuleLiftingSurface wing = (ModuleLiftingSurface)m;

                    //Get wing coefficients
                    Vector3 nVel       = Vector3.zero;
                    Vector3 liftVector = Vector3.zero;
                    float   liftdot;
                    float   absdot;
                    wing.SetupCoefficients(vel, out nVel, out liftVector, out liftdot, out absdot);

                    //Get Lift/drag force
                    lforce3 = wing.GetLiftVector(liftVector, liftdot, absdot, liftQ, (float)mach);
                    dforce3 = wing.GetDragVector(nVel, absdot, liftQ);

                    //wing.dragForce = dforce3;
                    if (p.name.Contains("kerbalEVA"))
                    {
                        continue;
                    }
                    total_drag += dforce3;
                    if (isgrounded)
                    {
                        total_lift += lforce3;
                    }
                }
            }
            total.Add(total_drag);
            total.Add(total_lift);
            return(total);
        }
        //Update aerodynamics
        //Adapted from KSP Trajectories, Kerbal Wind Tunnel, FAR, and AeroGUI
        void UpdateAerodynamics(ModularFI.ModularFlightIntegrator fi, Part part)
        {
            Vessel v = FlightGlobals.ActiveVessel;

            wx_enabled = Util.getWindBool(); //Is weather enabled?
            use_climo  = Util.useCLIM();     //Are we using the climatology
            use_point  = Util.useWX();       //Are we using MPAS point time-series

            //Get main vessel and get reference to Kerbin (i.e. celestial body)
            kerbin = Util.getbody();

            //Get wind vector (initialize to zero)
            Vector3d windVec = Vector3d.zero;

            if (use_climo)
            {
                //Retrieve wind vector from climatology
                windVec = KerbalWxClimo.getWSWind(); // .GetWind(FlightGlobals.currentMainBody, part, rb.position);
            }
            else if (use_point)
            {
                //Retrieve wind vector from point forecast
                windVec = KerbalWxPoint.getWSWind(); // .GetWind(FlightGlobals.currentMainBody, part, rb.position);
            }
            //Check to see if root part is in list. If not do not perform aero update.
            //This avoids updating aerodynamics of parts that have been decoupled and are no longer part of the active vessel.
            bool hasPart = false;

            for (int i = 0; i < fi.PartThermalDataCount; i++)
            {
                PartThermalData pttd  = fi.partThermalDataList[i];
                Part            ppart = pttd.part;
                if (ppart == v.rootPart)
                {
                    hasPart = true;
                }
            }

            if (!hasPart)
            {
                return;
            }

            //Get position of current vessel
            double vheight = v.altitude;
            double vlat    = v.latitude;
            double vlng    = v.longitude;

            double air_pressure; double air_density; double soundSpeed;
            //Define gamma (i.e. ratio between specific heat of dry air at constant pressure and specific heat of dry air at constant volume: cp/cv).
            double gamma = 1.4;
            //Util.Log("MFI wx_enabled: " + wx_enabled+", use_point: "+use_point+", use_climo: "+use_climo);
            bool inatmos = false;

            if ((FlightGlobals.ActiveVessel.mainBody == kerbin) && (v.altitude <= 70000) && (wx_enabled))
            {
                if (use_climo)
                {
                    //Retrieve air pressure/density at vessel location
                    climate_api.wx_aero ptd = _clim_api.getPTD(vlat, vlng, vheight);
                    air_density  = ptd.density;
                    air_pressure = ptd.pressure;
                }
                else
                {
                    //Retrieve air pressure/density at vessel location
                    weather_api.wx_aero ptd = _wx_api.getPTD(vheight);
                    air_density  = ptd.density;
                    air_pressure = ptd.pressure;
                }
                //Compute speed of sound based on air pressure and air density.
                soundSpeed = Math.Sqrt(gamma * (air_pressure / air_density));
                inatmos    = true;
            }
            else
            {
                soundSpeed = v.speedOfSound;
            }
            //Get height from surface
            double hsfc = v.heightFromTerrain;
            //Determine if vessel is grounded (i.e. on the ground)
            bool isgrounded = true;

            if (hsfc >= 10)
            {
                isgrounded = false;
            }

            //If FAR is present FAR will handle aerodynamic updates or if we're not on Kerbin (i.e. in a different atmosphere)
            if (part.Modules.Contains <ModuleAeroSurface>() || (part.Modules.Contains("MissileLauncher") && part.vessel.rootPart == part) || (haveFAR) || (v.mainBody != kerbin) || (!inatmos))
            {
                fi.BaseFIUpdateAerodynamics(part);

                if (((!part.DragCubes.None) && (!part.hasLiftModule)) || (part.name.Contains("kerbalEVA")))
                {
                    double drag  = part.DragCubes.AreaDrag * PhysicsGlobals.DragCubeMultiplier * fi.pseudoReDragMult;
                    float  pscal = (float)(part.dynamicPressurekPa * drag * PhysicsGlobals.DragMultiplier);

                    //Estimate lift force from body lift
                    Vector3 lforce = part.transform.rotation * (part.bodyLiftScalar * part.DragCubes.LiftForce);
                    lforce = Vector3.ProjectOnPlane(lforce, -part.dragVectorDir);
                }
                return;
            }
            else
            {
                fi.BaseFIUpdateAerodynamics(part); //Run base aerodynamic update first (fix bug where parachutes experience multiplicative acceleration)

                // Get rigid body
                Rigidbody rb = part.rb;
                if (rb)
                {
                    if (part == v.rootPart)
                    {
                        v.mach = 0;
                    }
                    //Retrieve wind vector at vessel location
                    //Vector3d windVec = KWPWind.GetWind(FlightGlobals.currentMainBody, part, rb.position);
                    //Util.Log("MFI windVec: " + windVec + ", use_point: " + use_point + ", use_climo: " + use_climo);
                    //Retrieve world velocity without wind vector
                    Vector3 velocity_nowind = rb.velocity + Krakensbane.GetFrameVelocity();
                    //Compute mach number
                    double mach_nowind = velocity_nowind.magnitude / soundSpeed;

                    Vector3 drag_sum = Vector3.zero;
                    Vector3 lift_sum = Vector3.zero;

                    if (((!part.DragCubes.None) && (!part.hasLiftModule)) || (part.name.Contains("kerbalEVA")))
                    {
                        //Estimate Drag force
                        double pseudoreynolds   = part.atmDensity * Math.Abs(velocity_nowind.magnitude);
                        double pseudoReDragMult = PhysicsGlobals.DragCurvePseudoReynolds.Evaluate((float)pseudoreynolds);
                        double drag             = part.DragCubes.AreaDrag * PhysicsGlobals.DragCubeMultiplier * pseudoReDragMult;
                        float  pscal            = (float)(part.dynamicPressurekPa * drag * PhysicsGlobals.DragMultiplier);
                        drag_sum += -part.dragVectorDir * pscal;

                        //Estimate lift force from body lift
                        float   pbodyLiftScalar = (float)(part.dynamicPressurekPa * part.bodyLiftMultiplier * PhysicsGlobals.BodyLiftMultiplier) * PhysicsGlobals.GetLiftingSurfaceCurve("BodyLift").liftMachCurve.Evaluate((float)part.machNumber);
                        Vector3 lforce2         = part.transform.rotation * (pbodyLiftScalar * part.DragCubes.LiftForce);
                        lforce2   = Vector3.ProjectOnPlane(lforce2, -part.dragVectorDir);
                        lift_sum += lforce2;
                    }

                    //Util.Log("BodyLift Default: " + part.bodyLiftScalar + ", Lift Force: " + lift_force);
                    //Loop through each part module to look for lifting surfaces
                    for (int j = 0; j < part.Modules.Count; ++j)
                    {
                        var m = part.Modules[j];
                        if (m is ModuleLiftingSurface)
                        {
                            //Initialize force vectors
                            Vector3 lforce = Vector3.zero;
                            Vector3 dforce = Vector3.zero;
                            //Convert kPa to Pa
                            double liftQ = part.dynamicPressurekPa * 1000;
                            ModuleLiftingSurface wing = (ModuleLiftingSurface)m;

                            //Get wing coefficients
                            Vector3 nVel       = Vector3.zero;
                            Vector3 liftVector = Vector3.zero;
                            float   liftdot;
                            float   absdot;
                            wing.SetupCoefficients(velocity_nowind, out nVel, out liftVector, out liftdot, out absdot);

                            //Get Lift/drag force
                            lforce = wing.GetLiftVector(liftVector, liftdot, absdot, liftQ, (float)part.machNumber);
                            dforce = wing.GetDragVector(nVel, absdot, liftQ);

                            if (part.name.Contains("kerbalEVA"))
                            {
                                continue;
                            }
                            drag_sum += dforce;
                            //lift_sum += lforce;
                            if (isgrounded)
                            {
                                lift_sum += lforce;
                            }
                        }
                    }

                    //Retrieve world velocity and subtract off wind vector
                    Vector3 velocity_wind = rb.velocity + Krakensbane.GetFrameVelocity() - windVec;
                    //Compute mach number
                    double mach_wind = velocity_wind.magnitude / soundSpeed;
                    //Set mach number
                    part.machNumber = mach_wind; // *mdiv;
                    if (part == v.rootPart)
                    {
                        fi.mach = mach_wind;
                    }
                    //Get drag and lift forces with wind
                    List <Vector3> total_forces = GetDragLiftForce(fi, part, velocity_wind, windVec, part.machNumber, isgrounded);

                    //Compute difference in drag/lift with and without wind.
                    Vector3 total_drag = total_forces[0] - drag_sum;
                    Vector3 total_lift = total_forces[1] - lift_sum;

                    //Calculate force due to wind
                    Vector3 force = total_lift + total_drag;

                    if (double.IsNaN(force.sqrMagnitude) || (((float)force.magnitude).NearlyEqual(0.0f)))
                    {
                        force = Vector3d.zero;
                    }
                    else
                    {
                        //Adapted from FAR - apply numerical control factor
                        float numericalControlFactor = (float)(part.rb.mass * velocity_wind.magnitude * 0.67 / (force.magnitude * TimeWarp.fixedDeltaTime));
                        force *= Math.Min(numericalControlFactor, 1);
                        part.AddForce(force);
                    }
                    v.mach = fi.mach;
                }
            }
        }
Ejemplo n.º 13
0
        //*******************************************************
        public static Vector3 SimLiftForce(CelestialBody body, IShipconstruct vessel, Vector3 v_wrld_vel, double altitude, double latitude = 0.0)
        {
            //Profiler.Start("SimLiftForce");
            double pressure = body.GetPressure(altitude);
            // Lift and drag for force accumulation.
            Vector3d total_lift = Vector3d.zero;

            // dynamic pressure for standard drag equation
            double rho          = GetDensity(altitude, body);
            double dyn_pressure = 0.0005 * rho * v_wrld_vel.sqrMagnitude;

            if (rho <= 0)
            {
                return(Vector3.zero);
            }

            double soundSpeed = body.GetSpeedOfSound(pressure, rho);
            double mach       = v_wrld_vel.magnitude / soundSpeed;

            if (mach > 25.0)
            {
                mach = 25.0;
            }

            // Loop through all parts, accumulating drag and lift.
            for (int i = vessel.Parts.Count - 1; i >= 0; i--)
            {
                // need checks on shielded components
                Part part = vessel.Parts[i];

                if (part.ShieldedFromAirstream || part.Rigidbody == null)
                {
                    continue;
                }

                // Get Drag
                Vector3 sim_dragVectorDir      = v_wrld_vel.normalized;
                Vector3 sim_dragVectorDirLocal = -(part.transform.InverseTransformDirection(sim_dragVectorDir));

                Vector3 liftForce = new Vector3(0, 0, 0);

                //Profiler.Start("SimLiftForce#Body");
                switch (part.dragModel)
                {
                case Part.DragModel.DEFAULT:
                case Part.DragModel.CUBE:
                    DragCubeList cubes = part.DragCubes;

                    DragCubeList.CubeData p_drag_data = new DragCubeList.CubeData();

                    if (!cubes.None)     // since 1.0.5, some parts don't have drag cubes (for example fuel lines and struts)
                    {
                        try
                        {
                            cubes.SetDragWeights();
                            cubes.SetPartOcclusion();
                            cubes.AddSurfaceDragDirection(-sim_dragVectorDirLocal, (float)mach, ref p_drag_data);
                        }
                        catch (Exception)
                        {
                            cubes.SetDrag(sim_dragVectorDirLocal, (float)mach);
                            cubes.ForceUpdate(true, true);
                            cubes.AddSurfaceDragDirection(-sim_dragVectorDirLocal, (float)mach, ref p_drag_data);
                            //Debug.Log(String.Format("Trajectories: Caught NRE on Drag Initialization.  Should be fixed now.  {0}", e));
                        }

                        float pseudoreynolds   = (float)(rho * Mathf.Abs(v_wrld_vel.magnitude));
                        float pseudoredragmult = PhysicsGlobals.DragCurvePseudoReynolds.Evaluate(pseudoreynolds);

                        liftForce = p_drag_data.liftForce;
                    }
                    break;
                }

                // If it isn't a wing or lifter, get body lift.
                if (!part.hasLiftModule)
                {
                    float simbodyLiftScalar = part.bodyLiftMultiplier * PhysicsGlobals.BodyLiftMultiplier * (float)dyn_pressure;
                    simbodyLiftScalar *= PhysicsGlobals.GetLiftingSurfaceCurve("BodyLift").liftMachCurve.Evaluate((float)mach);
                    Vector3 bodyLift = part.transform.rotation * (simbodyLiftScalar * liftForce);
                    bodyLift = Vector3.ProjectOnPlane(bodyLift, sim_dragVectorDir);
                    // Only accumulate forces for non-LiftModules
                    total_lift += bodyLift;
                }
                //Profiler.Stop("SimLiftForce#Body");

                // Find ModuleLifingSurface for wings and liftforce.
                // Should catch control surface as it is a subclass
                //Profiler.Start("SimLiftForce#LiftModule");
                for (int j = part.Modules.Count - 1; j >= 0; j--)
                {
                    if (part.Modules[j] is ModuleLiftingSurface)
                    {
                        float  mcs_mod            = 1.0f;
                        double liftQ              = dyn_pressure * 1000;
                        ModuleLiftingSurface wing = (ModuleLiftingSurface)part.Modules[j];
                        Vector3 nVel              = Vector3.zero;
                        Vector3 liftVector        = Vector3.zero;
                        float   liftdot;
                        float   absdot;
                        wing.SetupCoefficients(v_wrld_vel, out nVel, out liftVector, out liftdot, out absdot);

                        double prevMach = part.machNumber;
                        part.machNumber = mach;
                        Vector3 local_lift = mcs_mod * wing.GetLiftVector(liftVector, liftdot, absdot, liftQ, (float)mach);
                        part.machNumber = prevMach;

                        total_lift += local_lift;
                    }
                }
                //Profiler.Stop("SimLiftForce#LiftModule");
            }
            // RETURN STUFF
            //Profiler.Stop("SimLiftForce");
            return(total_lift);
        }
Ejemplo n.º 14
0
        //*******************************************************
        public static Vector3 SimAeroForce(List <Part> parts, CelestialBody body, Vector3 v_wrld_vel, double altitude, double latitude = 0.0)
        {
            double pressure = body.GetPressure(altitude);
            // Lift and drag for force accumulation.
            Vector3d total_lift = Vector3d.zero;
            Vector3d total_drag = Vector3d.zero;

            // dynamic pressure for standard drag equation
            double rho          = GetDensity(altitude, body);
            double dyn_pressure = 0.0005 * rho * v_wrld_vel.sqrMagnitude;

            if (rho <= 0)
            {
                return(Vector3.zero);
            }

            double soundSpeed = body.GetSpeedOfSound(pressure, rho);
            double mach       = v_wrld_vel.magnitude / soundSpeed;

            if (mach > 25.0)
            {
                mach = 25.0;
            }

            // Loop through all parts, accumulating drag and lift.
            foreach (Part p in parts)
            {
                // need checks on shielded components
                if (p.ShieldedFromAirstream || p.Rigidbody == null)
                {
                    continue;
                }

                // Get Drag
                Vector3 sim_dragVectorDir      = v_wrld_vel.normalized;
                Vector3 sim_dragVectorDirLocal = -(p.transform.InverseTransformDirection(sim_dragVectorDir));

                Vector3 liftForce = new Vector3(0, 0, 0);

                switch (p.dragModel)
                {
                case Part.DragModel.DEFAULT:
                case Part.DragModel.CUBE:
                    SmartDragCubeList cubes = new SmartDragCubeList(p, parts);

                    DragCubeList.CubeData p_drag_data;

                    float drag;
                    if (cubes.None)     // since 1.0.5, some parts don't have drag cubes (for example fuel lines and struts)
                    {
                        drag = p.maximum_drag;
                    }
                    else
                    {
                        p_drag_data = cubes.AddSurfaceDragDirection(-sim_dragVectorDirLocal, (float)mach);

                        drag = p_drag_data.areaDrag * PhysicsGlobals.DragCubeMultiplier;

                        liftForce = p_drag_data.liftForce;
                    }

                    double sim_dragScalar = dyn_pressure * (double)drag * PhysicsGlobals.DragMultiplier;
                    total_drag += -(Vector3d)sim_dragVectorDir * sim_dragScalar;

                    break;

                case Part.DragModel.SPHERICAL:
                    total_drag += -(Vector3d)sim_dragVectorDir * (double)p.maximum_drag;
                    break;

                case Part.DragModel.CYLINDRICAL:
                    total_drag += -(Vector3d)sim_dragVectorDir * (double)Mathf.Lerp(p.minimum_drag, p.maximum_drag, Mathf.Abs(Vector3.Dot(p.partTransform.TransformDirection(p.dragReferenceVector), sim_dragVectorDir)));
                    break;

                case Part.DragModel.CONIC:
                    total_drag += -(Vector3d)sim_dragVectorDir * (double)Mathf.Lerp(p.minimum_drag, p.maximum_drag, Vector3.Angle(p.partTransform.TransformDirection(p.dragReferenceVector), sim_dragVectorDir) / 180f);
                    break;

                default:
                    // no drag to apply
                    break;
                }

                // If it isn't a wing or lifter, get body lift.
                if (!p.hasLiftModule)
                {
                    float simbodyLiftScalar = p.bodyLiftMultiplier * PhysicsGlobals.BodyLiftMultiplier * (float)dyn_pressure;
                    simbodyLiftScalar *= PhysicsGlobals.GetLiftingSurfaceCurve("BodyLift").liftMachCurve.Evaluate((float)mach);
                    Vector3 bodyLift = p.transform.rotation * (simbodyLiftScalar * liftForce);
                    bodyLift = Vector3.ProjectOnPlane(bodyLift, sim_dragVectorDir);
                    // Only accumulate forces for non-LiftModules
                    total_lift += bodyLift;
                }

                // Find ModuleLifingSurface for wings and liftforce.
                // Should catch control surface as it is a subclass
                foreach (var m in p.Modules.OfType <ModuleLiftingSurface>())
                {
                    float  mcs_mod            = 1.0f;
                    double liftQ              = dyn_pressure * 1000;
                    ModuleLiftingSurface wing = (ModuleLiftingSurface)m;
                    Vector3 nVel              = Vector3.zero;
                    Vector3 liftVector        = Vector3.zero;
                    float   liftdot;
                    float   absdot;
                    wing.SetupCoefficients(v_wrld_vel, out nVel, out liftVector, out liftdot, out absdot);

                    float simLiftScalar = Mathf.Sign(liftdot) * wing.liftCurve.Evaluate(absdot) * wing.liftMachCurve.Evaluate((float)mach);
                    simLiftScalar *= wing.deflectionLiftCoeff;
                    simLiftScalar  = (float)(liftQ * (double)(PhysicsGlobals.LiftMultiplier * simLiftScalar));

                    float simdragScalar = wing.dragCurve.Evaluate(absdot) * wing.dragMachCurve.Evaluate((float)mach);
                    simdragScalar *= wing.deflectionLiftCoeff;
                    simdragScalar  = (float)(liftQ * (double)(simdragScalar * PhysicsGlobals.LiftDragMultiplier));

                    Vector3 local_lift = mcs_mod * wing.GetLiftVector(liftVector, liftdot, absdot, liftQ, (float)mach);
                    Vector3 local_drag = mcs_mod * wing.GetDragVector(nVel, absdot, liftQ);

                    total_lift += local_lift;
                    total_drag += local_drag;
                }
            }
            // RETURN STUFF
            Vector3 force = total_lift + total_drag;

            return(1000 * force);
        }