コード例 #1
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);
        }
コード例 #2
0
        private void Init(IShipconstruct v)
        {
            totalMass        = 0;
            dryMass          = 0;
            CoM              = Vector3.zero;
            CoM_dry          = Vector3.zero;
            relativeWingArea = 0;
            stage            = 0;

            List <Part>          oParts = v.Parts;
            List <SimulatedPart> variableDragParts_ctrls = new List <SimulatedPart>();

            count = oParts.Count;

            if (HighLogic.LoadedSceneIsEditor)
            {
                for (int i = 0; i < v.Parts.Count; i++)
                {
                    Part p = v.Parts[i];
                    if (p.dragModel == Part.DragModel.CUBE && !p.DragCubes.None)
                    {
                        DragCubeList cubes = p.DragCubes;
                        lock (cubes)
                        {
                            DragCubeList.CubeData p_drag_data = new DragCubeList.CubeData();

                            try
                            {
                                cubes.SetDragWeights();
                                cubes.SetPartOcclusion();
                                cubes.AddSurfaceDragDirection(-Vector3.forward, 0, ref p_drag_data);
                            }
                            catch (Exception)
                            {
                                cubes.SetDrag(Vector3.forward, 0);
                                cubes.ForceUpdate(true, true);
                                cubes.SetDragWeights();
                                cubes.SetPartOcclusion();
                                cubes.AddSurfaceDragDirection(-Vector3.forward, 0, ref p_drag_data);
                                //Debug.Log(String.Format("Trajectories: Caught NRE on Drag Initialization.  Should be fixed now.  {0}", e));
                            }
                        }
                    }
                }
            }

            bool lgWarning = false;

            for (int i = 0; i < count; i++)
            {
                if (!lgWarning)
                {
                    ModuleWheels.ModuleWheelDeployment gear = oParts[i].FindModuleImplementing <ModuleWheels.ModuleWheelDeployment>();
                    bool forcedRetract = !oParts[i].ShieldedFromAirstream && gear != null && gear.Position > 0;

                    if (forcedRetract)
                    {
                        lgWarning = true;
                    }
                }
            }

            // Recursively add all parts to collections
            // What a crazy change to make just to accomodate rotating parts!
            partCollection = PartCollection.Borrow(this, oParts[0]);

            CoM     /= totalMass;
            CoM_dry /= dryMass;

            partCollection.origin = CoM;

            if (relativeWingArea == 0)
            {
                // I'm not sure what effect calling ScreenMessages from a background thread will be.
                // Fortunately, anyone using this mod probably has at least one wing.
                ScreenMessages.PostScreenMessage("No wings found, using a reference area of 1.", 5, ScreenMessageStyle.UPPER_CENTER);
                relativeWingArea = 1;
            }

            //if (lgWarning)
            //ScreenMessages.PostScreenMessage("Landing gear deployed, results may not be accurate.", 5, ScreenMessageStyle.UPPER_CENTER);
        }
コード例 #3
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);
        }
コード例 #4
0
        //*******************************************************
        public static Vector3 SimDragForce(CelestialBody body, IShipconstruct vessel, Vector3 v_wrld_vel, double altitude, double latitude = 0.0)
        {
            double pressure = body.GetPressure(altitude);
            // Lift and drag for force accumulation.
            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 = 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));

                Vector3d dragForce;

                switch (part.dragModel)
                {
                case Part.DragModel.DEFAULT:
                case Part.DragModel.CUBE:
                    DragCubeList cubes = part.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 = part.maximum_drag;
                    }
                    else
                    {
                        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);
                        drag = p_drag_data.areaDrag * PhysicsGlobals.DragCubeMultiplier * pseudoredragmult;
                    }

                    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)part.maximum_drag;
                    break;

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

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

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

                total_drag += dragForce;


                // Find ModuleLifingSurface for wings and liftforce.
                // Should catch control surface as it is a subclass
                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_drag = mcs_mod * wing.GetDragVector(nVel, absdot, liftQ);
                        part.machNumber = prevMach;

                        total_drag += local_drag;
                    }
                }
            }
            // RETURN STUFF
            return(total_drag);
        }
コード例 #5
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);
        }
コード例 #6
0
        private void Init(IShipconstruct v, SimCurves _simCurves)
        {
            totalMass = 0;
            dryMass = 0;
            CoM = Vector3.zero;
            CoM_dry = Vector3.zero;

            List<Part> oParts = v.Parts;
            List<SimulatedPart> variableDragParts_ctrls = new List<SimulatedPart>();
            count = oParts.Count;

            if (HighLogic.LoadedSceneIsEditor)
            {
                for (int i = 0; i < v.Parts.Count; i++)
                {
                    Part p = v.Parts[i];
                    if (p.dragModel == Part.DragModel.CUBE && !p.DragCubes.None)
                    {
                        DragCubeList cubes = p.DragCubes;
                        DragCubeList.CubeData p_drag_data = new DragCubeList.CubeData();

                        try
                        {
                            cubes.SetDragWeights();
                            cubes.SetPartOcclusion();
                            cubes.AddSurfaceDragDirection(-Vector3.forward, 0, ref p_drag_data);
                        }
                        catch (Exception)
                        {
                            cubes.SetDrag(Vector3.forward, 0);
                            cubes.ForceUpdate(true, true);
                            cubes.SetDragWeights();
                            cubes.SetPartOcclusion();
                            cubes.AddSurfaceDragDirection(-Vector3.forward, 0, ref p_drag_data);
                            //Debug.Log(String.Format("Trajectories: Caught NRE on Drag Initialization.  Should be fixed now.  {0}", e));
                        }
                    }
                }
            }

            simCurves = _simCurves;

            if (parts.Capacity < count)
                parts.Capacity = count;

            bool lgWarning = false;
            int stage = 0;
            for (int i = 0; i < count; i++)
            {
                if (!lgWarning)
                {
                    ModuleWheels.ModuleWheelDeployment gear = oParts[i].FindModuleImplementing<ModuleWheels.ModuleWheelDeployment>();
                    bool forcedRetract = !oParts[i].ShieldedFromAirstream && gear != null && gear.Position > 0;

                    if (forcedRetract)
                        lgWarning = true;
                }

                SimulatedPart simulatedPart = SimulatedPart.Borrow(oParts[i], this);
                parts.Add(simulatedPart);

                totalMass += simulatedPart.totalMass;
                dryMass += simulatedPart.dryMass;
                CoM += simulatedPart.totalMass * simulatedPart.CoM;
                CoM_dry += simulatedPart.dryMass * simulatedPart.CoM;
                
                ModuleLiftingSurface liftingSurface = oParts[i].FindModuleImplementing<ModuleLiftingSurface>();
                if (liftingSurface != null)
                {
                    parts[i].hasLiftModule = true;
                    if (liftingSurface is ModuleControlSurface ctrlSurface)
                    {
                        ctrls.Add(SimulatedControlSurface.Borrow(ctrlSurface, simulatedPart));
                        variableDragParts_ctrls.Add(simulatedPart);
                        if (ctrlSurface.ctrlSurfaceArea < 1)
                            surfaces.Add(SimulatedLiftingSurface.Borrow(ctrlSurface, simulatedPart));
                    }
                    else
                        surfaces.Add(SimulatedLiftingSurface.Borrow(liftingSurface, simulatedPart));
                }

                List<ITorqueProvider> torqueProviders = oParts[i].FindModulesImplementing<ITorqueProvider>();
                // TODO: Add them to a list.

                if(oParts[i].inverseStage > stage)
                {
                    SimulatedEngine.Release(engines);
                    engines.Clear();
                    stage = oParts[i].inverseStage;
                }
                if (oParts[i].inverseStage >= stage)
                {
                    MultiModeEngine multiMode = oParts[i].FindModuleImplementing<MultiModeEngine>();
                    if (multiMode != null)
                    {
                        engines.Add(SimulatedEngine.Borrow(oParts[i].FindModulesImplementing<ModuleEngines>().Find(engine => engine.engineID == multiMode.mode), simulatedPart));
                    }
                    else
                    {
                        ModuleEngines engine = oParts[i].FindModulesImplementing<ModuleEngines>().FirstOrDefault();
                        if (engine != null)
                            engines.Add(SimulatedEngine.Borrow(engine, simulatedPart));
                    }
                }
            }
            CoM /= totalMass;
            CoM_dry /= dryMass;

            if (lgWarning)
                ScreenMessages.PostScreenMessage("Landing gear deployed, results may not be accurate.", 5, ScreenMessageStyle.UPPER_CENTER);

            /*for (int i = 0; i < count; i++)
            {
                parts[i].CoM -= this.CoM;
                parts[i].CoL -= this.CoM;
                parts[i].CoP -= this.CoM;
            }*/

            parts.RemoveAll(part => variableDragParts_ctrls.Contains(part));
        }
コード例 #7
0
                public void update(double curSpeed, double curDensity)
                {
                    maxSpeed      = 0;
                    breakDistance = 0;
                    curDensity    = Math.Max(curDensity, 0.2 * vesselState.mainBody.atmDensityASL);
                    double curSpeedOfSound = Math.Max(vesselState.speedOfSound, vesselState.mainBody.GetSpeedOfSound(0.2 * vesselState.mainBody.atmPressureASL, 0.2 * vesselState.mainBody.atmDensityASL));
                    //create List by descending order of maxSpeed with drag and max chute reaction time
                    SortedList <double, (float, float)> parachuteTypes = new SortedList <double, (float, float)>(Comparer <double> .Create((a, b) => Math.Sign(b - a)));

                    foreach (var p in vesselState.parachutes)
                    {
                        if (p.deploymentState == ModuleParachute.deploymentStates.STOWED)
                        {
                            p.refDensity = curDensity;
                            p.CalcBaseStats();
                            DragCubeList simParachute = new DragCubeList();
                            simParachute.LoadCube(p.part.DragCubes, "DEPLOYED");
                            simParachute.SetPart(p.part);
                            simParachute.SetOcclusionMultiplier(0f);
                            simParachute.ResetCubeWeights();
                            simParachute.SetDragWeights();
                            simParachute.SetPartOcclusion();
                            //Debug.Log(String.Format("ParachuteInfo.update Parchute {0} has up Cube area={1:F1} drag={2:F1} weight={3:F1} AreaOccluded={4:F1}",
                            //    p.part.name, simParachute.Cubes[0].Area[(int) DragCube.DragFace.YP], simParachute.Cubes[0].Drag[(int) DragCube.DragFace.YP],
                            //    simParachute.Cubes[0].Weight, simParachute.AreaOccluded[(int)DragCube.DragFace.YP]));
                            DragCubeList.CubeData simDrag = new DragCubeList.CubeData();
                            simParachute.AddSurfaceDragDirection(Vector3.up, (float)(p.maxSafeSpeedAtRef / curSpeedOfSound), ref simDrag);
                            //Debug.Log(String.Format("ParachuteInfo.update Parchute {0} has areaDrag={1:F1}, crossSectionalArea={2:F1}, exposedArea={3:F1}",
                            //          p.part.name, simDrag.areaDrag, simDrag.crossSectionalArea, simDrag.exposedArea));
                            if (parachuteTypes.ContainsKey(p.maxSafeSpeedAtRef))
                            {
                                parachuteTypes[p.maxSafeSpeedAtRef] = (parachuteTypes[p.maxSafeSpeedAtRef].Item1 + simDrag.areaDrag,
                                                                       Mathf.Max(parachuteTypes[p.maxSafeSpeedAtRef].Item2, p.Anim[p.semiDeployedAnimation].length / p.semiDeploymentSpeed + p.Anim[p.fullyDeployedAnimation].length / p.deploymentSpeed));
                            }
                            else
                            {
                                parachuteTypes.Add(p.maxSafeSpeedAtRef, (simDrag.areaDrag, p.Anim[p.semiDeployedAnimation].length / p.semiDeploymentSpeed + p.Anim[p.fullyDeployedAnimation].length / p.deploymentSpeed));
                            }
                        }
                    }
                    float  totalFriction = 0;
                    double lastSpeed     = 0;

                    foreach (var pt in parachuteTypes)
                    {
                        double effSpeed = Math.Min(curSpeed, pt.Key);
                        // base equation deceleration term + chute reaction term with deceleration taken from moving equations with netwon friction
                        // during reaction time we hardly break, so assume
                        float friction_const = pt.Value.Item1 * 0.0005f * (float)curDensity * PhysicsGlobals.DragMultiplier
                                               * PhysicsGlobals.DragCubeMultiplier * PhysicsGlobals.DragCurvePseudoReynolds.Evaluate((float)(effSpeed * curDensity));
                        if (breakDistance == 0) // first term for highest speed
                        {
                            breakDistance      = (float)vesselState.mass / friction_const * Math.Log(effSpeed) + effSpeed * pt.Value.Item2;
                            undeployedDistance = effSpeed * pt.Value.Item2;// - vesselState.mass / friction_const  ;
                            maxSpeed           = lastSpeed = effSpeed;
                            totalFriction      = friction_const;
                            //Debug.Log(String.Format("ParachuteInfo.update has first chute type with friction={0:F4} and effSpeed={1:F0}, delay={3:F1} results break dist={2:F0}", friction_const, effSpeed, breakDistance, pt.Value.Item2));
                        }
                        else
                        {
                            // calculate slowdown during parachute opening using old friction
                            effSpeed           *= (float)vesselState.mass / (totalFriction * pt.Value.Item2 * effSpeed + vesselState.mass);
                            breakDistance      -= (float)vesselState.mass / (totalFriction + friction_const) * friction_const / totalFriction * Math.Log(effSpeed);
                            undeployedDistance += pt.Value.Item2 * effSpeed;// + vesselState.mass * lastSpeed / (totalFriction * effSpeed) - vesselState.mass / (totalFriction + friction_const);
                            lastSpeed           = effSpeed;
                            totalFriction      += friction_const;
                            //Debug.Log(String.Format("ParachuteInfo.update has next chute type with friction={0:F4} and effSpeed={1:F0}, delay={3:F1} results break dist={2:F0}", friction_const, effSpeed, breakDistance, pt.Value.Item2));
                        }
                    }
                    if (totalFriction > 0)
                    {
                        double terminalSpeed = Math.Sqrt((float)vesselState.mass / totalFriction * vesselState.mainBody.GeeASL * PhysicsGlobals.GravitationalAcceleration);
                        //we are not getting slower than terminal velocity, so substract this as best guess for integration constant v
                        breakDistance -= (float)vesselState.mass / totalFriction * Math.Log(terminalSpeed);
                        //undeployedDistance += vesselState.mass * lastSpeed / (totalFriction * terminalSpeed);
                        //Debug.Log(String.Format("ParachuteInfo.update has terminal velocity term with friction={0:F4} and terminalSpeed={1:F0} results break dist={2:F0}", totalFriction, terminalSpeed, breakDistance));
                    }
                    Debug.Log(String.Format("ParachuteInfo.update for speed={0:F0} gives maxSpeed={1:F0} break dist={2:F0} undeployedDistance={3:F0}", curSpeed, maxSpeed, breakDistance, undeployedDistance));
                }