示例#1
0
        void Start()
        {
            if (waterSlowDragNew < 0)
            {
                waterSlowDragNew    = PhysicsGlobals.BuoyancyWaterDragSlow;
                minVelVesselMultNew = (float)PhysicsGlobals.BuoyancyWaterDragPartVelGreaterVesselMult;
                PhysicsGlobals.BuoyancyWaterDragPartVelGreaterVesselMult = 0;
            }

            part.maximum_drag = 0;
            part.minimum_drag = 0;
            part.angularDrag  = 0;
            if (HighLogic.LoadedSceneIsFlight)
            {
                this.enabled = true;
            }
            else if (HighLogic.LoadedSceneIsEditor)
            {
                this.enabled = false;
            }

            partLocalVel    = Vector3.zero;
            partLocalForce  = Vector3.zero;
            partLocalTorque = Vector3.zero;

            //if (!part.Modules.Contains("ModuleAeroSurface"))
            //    part.dragModel = Part.DragModel.CYLINDRICAL;

            if (FARDebugValues.allowStructuralFailures)
            {
                FARPartStressTemplate template = FARAeroStress.DetermineStressTemplate(this.part);
                partStressMaxY  = template.YmaxStress;
                partStressMaxXZ = template.XZmaxStress;
            }
            partTransform = part.partTransform;

            materialColorUpdater = new MaterialColorUpdater(partTransform, PhysicsGlobals.TemperaturePropertyID);
            if (part.Modules.Contains <FARWingAerodynamicModel>())
            {
                legacyWingModel = part.Modules.GetModule <FARWingAerodynamicModel>();
            }
            else if (part.Modules.Contains <FARControllableSurface>())
            {
                legacyWingModel = part.Modules.GetModule <FARControllableSurface>();
            }
            else
            {
                legacyWingModel = null;
            }

            // For handling airbrakes aero visualization
            if (part.Modules.Contains <ModuleAeroSurface>())
            {
                stockAeroSurfaceModule = part.Modules.GetModule <ModuleAeroSurface>();
            }
            else
            {
                stockAeroSurfaceModule = null;
            }
        }
示例#2
0
        // Stock aero force calculation by NathanKell

        private static Vector3 VesselStockAeroForces(Vessel vessel)
        {
            Vector3 aeroForce = Vector3.zero;

            for (int i = 0; i < vessel.parts.Count; i++)
            {
                Part part = vessel.parts[i];
                aeroForce += -part.dragVectorDir * part.dragScalar;
                if (!part.hasLiftModule)
                {
                    Vector3 bodyLift = part.transform.rotation * (part.bodyLiftScalar * part.DragCubes.LiftForce);
                    aeroForce += Vector3.ProjectOnPlane(bodyLift, -part.dragVectorDir);
                }
                else
                {
                    for (int j = 0; j < part.Modules.Count; j++)
                    {
                        ModuleLiftingSurface module = part.Modules[j] as ModuleLiftingSurface;
                        if (module == null) continue;
                        aeroForce += module.liftForce;
                        aeroForce += module.dragForce;
                    }
                }
            }

            return aeroForce;
        }
        private void CountSurfaces()
        {
            print("Counting wings for " + vessel.GetName());

            liftingSurfaces = new List <ModuleLiftingSurface>();
            controlSurfaces = new List <ModuleControlSurface>();


            inRange = true;

            groundPlane = new Plane();

            // This will be calculated later
            wingSpan = 42 / 42;

            foreach (Part part in vessel.Parts)
            {
                ModuleControlSurface thingThatLiftsPartsAndMoves = null;
                ModuleLiftingSurface thingThatLiftsParts         = null;
                // Make sure we're actually allowed to modify that part
                if (!part.Modules.Contains("IgnoreGroundEffect"))
                {
                    // Look through the list of part modules to find anything that inherits ModuleLiftingSurface
                    foreach (PartModule module in part.Modules)
                    {
                        if (typeof(ModuleLiftingSurface).IsAssignableFrom(module.GetType()))
                        {
                            //thingThatLiftsParts = (ModuleLiftingSurface)(module);
                            //initialLift = thingThatLiftsParts.deflectionLiftCoeff;

                            thingThatLiftsParts = (ModuleLiftingSurface)(module);

                            if (module is ModuleControlSurface)
                            {
                                thingThatLiftsPartsAndMoves = (ModuleControlSurface)(module);
                            }
                        }
                    }
                }

                if (thingThatLiftsParts != null)
                {
                    if (thingThatLiftsPartsAndMoves != null)
                    {
                        // It's a control surface, add to control surface arrays
                        controlSurfaces.Add(thingThatLiftsPartsAndMoves);
                    }
                    else
                    {
                        // It's just a lifting surface, add to lifting surface arrays
                        liftingSurfaces.Add(thingThatLiftsParts);
                    }
                }

                //thingThatLiftsPartsAndMoves.OnCenterOfLiftQuery();
            }

            print("LiftingSurfaces counted for " + vessel.GetName() + ": " + liftingSurfaces.Count);
            print("ControlSurfaces counted for " + vessel.GetName() + ": " + controlSurfaces.Count);
        }
        public override void OnStart(StartState state)
        {
            if (ferramEnabled)
            {
                // Do Ferrem stuff

                // isn't legacy not even stilln't today but not used?
                //if (part.Modules.Contains("FARControllableSurface")) {
                //	ferramModule = part.Modules["FARControllableSurface"];
                //} else if (part.Modules.Contains("FARWingAerodynamicModel")) {
                //	ferramModule = part.Modules["FARWingAerodynamicModel"];
                //}

                if (part.Modules.Contains("FARAeroPartModule"))
                {
                    ferramModule = part.Modules ["FARAeroPartModule"];
                    ferramField  = ferramModule.GetType().GetField("worldSpaceAeroForce");
                }
                else
                {
                    print("FAR module not found");
                    Destroy(this);
                    return;
                }

                //foreach (PartModule pm in part.Modules) {
                //	print ("module: " + pm.ClassName);
                //}

                //print ("farrem module: " + ferramModule);

                print("Ground effect module loaded with FAR");
                return;
            }
            else
            {
                // Look through the list of part modules to find anything that inherits ModuleLiftingSurface
                foreach (PartModule module in part.Modules)
                {
                    if (typeof(ModuleLiftingSurface).IsAssignableFrom(module.GetType()))
                    {
                        thingThatLiftsParts = (ModuleLiftingSurface)(module);
                        initialLift         = thingThatLiftsParts.deflectionLiftCoeff;
                        if (module is ModuleControlSurface)
                        {
                            //print ("SURFAAAACE!");
                            thingThatAlsoLiftsPartsButMoves = (ModuleControlSurface)(module);
                            initialLiftCtrl = thingThatAlsoLiftsPartsButMoves.ctrlSurfaceArea;
                        }
                        print("Ground effect module loaded");
                        return;
                    }
                }
                // This means there's a module manager error?
            }

            print("Ground effect module loaded for non-aero part?");
            Destroy(this);
        }
示例#5
0
        public static SimulatedLiftingSurface Borrow(ModuleLiftingSurface module, SimulatedPart part)
        {
            SimulatedLiftingSurface surface = pool.Borrow();

            surface.vessel = part.vessel;
            surface.Init(module, part);
            return(surface);
        }
示例#6
0
        public override void OnStart(StartState state)
        {
            Debug.Log(string.Format("{0} ModulePebkacLesPitchControl.OnStart", _myModTag));
            _pitchEngine     = GetPitchEngine();
            _deployAnimation = GetDeployAnimation();
            _liftingSurface  = GetLiftingSurface();

            base.OnStart(state);
        }
示例#7
0
        private void Start()
        {
            shield = new DummyAirstreamShield {
                part = part
            };

            if (waterSlowDragNew < 0)
            {
                waterSlowDragNew    = PhysicsGlobals.BuoyancyWaterDragSlow;
                minVelVesselMultNew = (float)PhysicsGlobals.BuoyancyWaterDragPartVelGreaterVesselMult;
                PhysicsGlobals.BuoyancyWaterDragPartVelGreaterVesselMult = 0;
            }

            part.maximum_drag = 0;
            part.minimum_drag = 0;
            part.angularDrag  = 0;
            if (HighLogic.LoadedSceneIsFlight)
            {
                enabled = true;
            }
            else if (HighLogic.LoadedSceneIsEditor)
            {
                enabled = false;
            }

            partLocalVel    = Vector3.zero;
            partLocalForce  = Vector3.zero;
            partLocalTorque = Vector3.zero;

            if (FARDebugValues.allowStructuralFailures && !partStressOverride)
            {
                FARPartStressTemplate template = FARAeroStress.DetermineStressTemplate(part);
                partStressMaxY  = template.YMaxStress;
                partStressMaxXZ = template.XZMaxStress;
            }

            partTransform = part.partTransform;

            materialColorUpdater = new MaterialColorUpdater(partTransform, PhysicsGlobals.TemperaturePropertyID);
            if (part.Modules.Contains <FARWingAerodynamicModel>())
            {
                LegacyWingModel = part.Modules.GetModule <FARWingAerodynamicModel>();
            }
            else if (part.Modules.Contains <FARControllableSurface>())
            {
                LegacyWingModel = part.Modules.GetModule <FARControllableSurface>();
            }
            else
            {
                LegacyWingModel = null;
            }

            // For handling airbrakes aero visualization
            stockAeroSurfaceModule = part.Modules.Contains <ModuleAeroSurface>()
                                         ? part.Modules.GetModule <ModuleAeroSurface>()
                                         : null;
        }
        private void CountSurfaces()
        {
            print("Counting wings for " + vessel.GetName());

            liftingSurfaces = new List <WingEntry>();


            inRange = true;

            groundPlane = new Plane();

            // This will be calculated later
            wingSpan = 42 / 42;

            foreach (Part part in vessel.Parts)
            {
                ModuleLiftingSurface thingThatLiftsParts = null;
                float multiplyingLiftWhatever            = DefaultLiftMultiplier;

                // Look through the list of part modules to find anything that
                // inherits ModuleLiftingSurface
                foreach (PartModule module in part.Modules)
                {
                    if (typeof(ModuleLiftingSurface).IsAssignableFrom(module.GetType()))
                    {
                        thingThatLiftsParts = (ModuleLiftingSurface)(module);
                        //initialLift = thingThatLiftsParts.deflectionLiftCoeff;



                        if (module is ModuleControlSurface)
                        {
                            // maybe do specific for control surfaces
                        }
                    }
                    else if (module is ModuleGroundEffect)
                    {
                        multiplyingLiftWhatever = ((ModuleGroundEffect)module)
                                                  .groundEffectMultiplier;
                    }
                }

                if (thingThatLiftsParts != null)
                {
                    WingEntry entry = new WingEntry();
                    entry.groundEffectMultiplier = multiplyingLiftWhatever;
                    entry.surface = thingThatLiftsParts;
                    liftingSurfaces.Add(entry);
                }


                //thingThatLiftsPartsAndMoves.OnCenterOfLiftQuery();
            }

            print("LiftingSurfaces counted for " + vessel.GetName()
                  + ": " + liftingSurfaces.Count);
        }
        public override void OnStart(StartState state)
        {
            // hook up to the part attach callback

            /*
             * if (state == StartState.Editor)
             * {
             *  part.OnEditorAttach += OnEditorAttach;
             * }
             */

            List <ModuleEngines> engines = part.FindModulesImplementing <ModuleEngines>();

            foreach (ModuleEngines e in engines)
            {
                if (e.engineID == escapeEngineID)
                {
                    escapeEngine = e;
                }
                else if (e.engineID == pitchEngineID)
                {
                    pitchEngine = e;
                }
                else if (e.engineID == jettisonEngineID)
                {
                    jettisonEngine = e;
                }
                foreach (BaseAction a in e.Actions)
                {
                    a.active = false;
                }
                foreach (BaseField f in e.Fields)
                {
                    f.guiActive       = false;
                    f.guiActiveEditor = false;
                }
                foreach (BaseEvent ev in e.Events)
                {
                    ev.guiActive       = false;
                    ev.guiActiveEditor = false;
                }
            }

            // check for nulls in engines

            // set up the variables used to shift aerodynamics
            _maxFuel       = part.Resources["SolidFuel"].maxAmount;
            _origComOffset = part.CoMOffset;
            _origCopOffset = part.CoPOffset;
            _origColOffset = part.CoLOffset;

            // set up the variables used by code for simming the canards
            _deployAnimation = GetDeployAnimation();
            _liftingSurface  = GetLiftingSurface();
        }
示例#10
0
        void Start()
        {
            part.maximum_drag = 0;
            part.minimum_drag = 0;
            part.angularDrag  = 0;
            if (HighLogic.LoadedSceneIsFlight)
            {
                this.enabled = true;
            }
            else if (HighLogic.LoadedSceneIsEditor)
            {
                this.enabled = false;
            }

            partLocalVel    = Vector3.zero;
            partLocalForce  = Vector3.zero;
            partLocalTorque = Vector3.zero;

            if (!part.Modules.Contains("ModuleAeroSurface"))
            {
                part.dragModel = Part.DragModel.CYLINDRICAL;
            }

            if (FARDebugValues.allowStructuralFailures)
            {
                FARPartStressTemplate template = FARAeroStress.DetermineStressTemplate(this.part);
                partStressMaxY  = template.YmaxStress;
                partStressMaxXZ = template.XZmaxStress;
            }
            partTransform = part.partTransform;

            materialColorUpdater = new MaterialColorUpdater(partTransform, PhysicsGlobals.TemperaturePropertyID);
            if (part.Modules.Contains("FARWingAerodynamicModel"))
            {
                legacyWingModel = part.Modules["FARWingAerodynamicModel"] as FARWingAerodynamicModel;
            }
            else if (part.Modules.Contains("FARControllableSurface"))
            {
                legacyWingModel = part.Modules["FARControllableSurface"] as FARWingAerodynamicModel;
            }
            else
            {
                legacyWingModel = null;
            }

            // For handling airbrakes aero visualization
            if (part.Modules.Contains("ModuleAeroSurface"))
            {
                stockAeroSurfaceModule = part.Modules["ModuleAeroSurface"] as ModuleAeroSurface;
            }
            else
            {
                stockAeroSurfaceModule = null;
            }
        }
示例#11
0
        public override void OnStart(StartState state)
        {
            List <ModuleEngines> engines = part.FindModulesImplementing <ModuleEngines>();

            foreach (ModuleEngines e in engines)
            {
                if (e.engineID == _escapeEngineID)
                {
                    _escapeEngine = e;
                }
                else if (e.engineID == _pitchEngineID)
                {
                    _pitchEngine = e;
                }
                else if (e.engineID == _jettisonEngineID)
                {
                    _jettisonEngine = e;
                }
                foreach (BaseAction a in e.Actions)
                {
                    a.active = false;
                }
                foreach (BaseField f in e.Fields)
                {
                    f.guiActive       = false;
                    f.guiActiveEditor = false;
                }
                foreach (BaseEvent ev in e.Events)
                {
                    ev.guiActive       = false;
                    ev.guiActiveEditor = false;
                }
            }

            if (hasPitchControl)
            {
                // set up the variables used to shift aerodynamics
                _maxFuel       = part.Resources["SolidFuel"].maxAmount;
                _origComOffset = part.CoMOffset;
                _origColOffset = part.CoLOffset;

                // set up the variables used by code for simming the canards
                _deployAnimation = GetDeployAnimation();
                _liftingSurface  = GetLiftingSurface();
            }

            // get the decoupler
            _lesDecoupler = part.FindModuleImplementing <ModuleDecouple>();

            if (_lesDecoupler == null)
            {
                Debug.LogError(string.Format("{0}: {1}: {2}", _myModTag, part.name, "Did not find a decoupler on the LES!"));
            }
        }
示例#12
0
        private void OnFirstUpdate()         // Simulated event
        {
            Log.dbg("OnFirtUpdate()");

            // Fetch the needed data on craft spawn, when anything that wanted to change something already did it.
            // Yeah, TweakScale. :)
            this.module = this.part.Modules.GetModule <ModuleLiftingSurface>();
            this.defaultdDeflectionLiftCoeff = this.module.deflectionLiftCoeff;

            Log.dbg("defaultdDeflectionLiftCoeff = {0}", this.defaultdDeflectionLiftCoeff);
        }
示例#13
0
        private double FallbackEvaluateTerminalVelocity()
        {
            // Terminal velocity computation based on MechJeb 2.5.1 or one of the later snapshots
            if (altitudeASL > vessel.mainBody.RealMaxAtmosphereAltitude())
            {
                return(float.PositiveInfinity);
            }

            Vector3 pureDragV = Vector3.zero, pureLiftV = Vector3.zero;

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

                pureDragV += -p.dragVectorDir * p.dragScalar;

                if (!p.hasLiftModule)
                {
                    Vector3 bodyLift = p.transform.rotation * (p.bodyLiftScalar * p.DragCubes.LiftForce);
                    bodyLift   = Vector3.ProjectOnPlane(bodyLift, -p.dragVectorDir);
                    pureLiftV += bodyLift;

                    for (int m = 0; m < p.Modules.Count; m++)
                    {
                        PartModule pm = p.Modules[m];
                        if (!pm.isEnabled)
                        {
                            continue;
                        }

                        if (pm is ModuleLiftingSurface)
                        {
                            ModuleLiftingSurface liftingSurface = (ModuleLiftingSurface)pm;
                            if (p.ShieldedFromAirstream)
                            {
                                continue;
                            }
                            pureLiftV += liftingSurface.liftForce;
                            pureDragV += liftingSurface.dragForce;
                        }
                    }
                }
            }

            // Why?
            pureDragV = pureDragV / totalShipWetMass;
            pureLiftV = pureLiftV / totalShipWetMass;

            Vector3 force = pureDragV + pureLiftV;
            double  drag  = Vector3.Dot(force, -vessel.srf_velocity.normalized);

            return(Math.Sqrt(localGeeDirect / drag) * vessel.srfSpeed);
        }
示例#14
0
 public override void OnStart(StartState state)
 {
     try
     {
         base.OnStart(state);
         liftingSurface      = part.FindModuleImplementing <ModuleLiftingSurface>();
         deflectionLiftCoeff = liftingSurface.deflectionLiftCoeff;
         liftingSurface.deflectionLiftCoeff = deflectionLiftCoeff * oneOrZero;
     }
     catch (Exception ex)
     {
         Debug.LogError("PROBLEM.\n" + ex.Message + "\n" + ex.StackTrace);
     }
 }
示例#15
0
        private void GenerateHighlightingData(ShipConstruct ship, CelestialBody body, float altitude, float speed, float aoa)
        {
            float mach, atmDensity;

            lock (body)
            {
                atmDensity = (float)Extensions.KSPClassExtensions.GetDensity(body, altitude);
                mach       = speed / (float)body.GetSpeedOfSound(body.GetPressure(altitude), atmDensity);
            }

            int count = ship.parts.Count;

            highlightingData = new PartAeroData[count];

            Vector3 inflow = AeroPredictor.InflowVect(aoa);

            float pseudoReDragMult;

            lock (PhysicsGlobals.DragCurvePseudoReynolds)
                pseudoReDragMult = PhysicsGlobals.DragCurvePseudoReynolds.Evaluate(atmDensity * speed);

            for (int i = 0; i < count; i++)
            {
                if (WindTunnelSettings.HighlightIgnoresLiftingSurfaces && ship.parts[i].HasModuleImplementing <ModuleLiftingSurface>())
                {
                    highlightingData[i] = new PartAeroData(0, 0, ship.parts[i].mass);
                    continue;
                }

                VesselCache.SimulatedPart simPart = VesselCache.SimulatedPart.Borrow(ship.parts[i], null);
                Vector3 partForce = simPart.GetAero(inflow, mach, pseudoReDragMult);

                ModuleLiftingSurface liftingSurface = ship.parts[i].FindModuleImplementing <ModuleLiftingSurface>();
                if (liftingSurface != null)
                {
                    VesselCache.SimulatedLiftingSurface simLiftSurf = VesselCache.SimulatedLiftingSurface.Borrow(liftingSurface, simPart);
                    partForce += simLiftSurf.GetForce(inflow, mach);
                    simLiftSurf.Release();
                }
                simPart.Release();
                //Vector3 partForce = highlightingVessel.parts[i].GetAero(inflow, mach, pseudoReDragMult);
                //Vector3 partForce = StockAeroUtil.SimAeroForce(body, new ShipConstruct("test", "", new List<Part>() { EditorLogic.fetch.ship.parts[i] }), inflow * speed, altitude);
                partForce = AeroPredictor.ToFlightFrame(partForce, aoa);  // (Quaternion.AngleAxis((aoa * 180 / Mathf.PI), Vector3.left) * partForce);

                highlightingData[i] = new PartAeroData(Math.Abs(partForce.z), Math.Abs(partForce.y), ship.parts[i].mass);
            }
        }
示例#16
0
        private double FallbackEvaluateDragForce()
        {
            // Equations based on https://github.com/NathanKell/AeroGUI/blob/master/AeroGUI/AeroGUI.cs and MechJeb.
            double dragForce = 0.0;

            if (altitudeASL < vessel.mainBody.RealMaxAtmosphereAltitude())
            {
                Vector3 pureDragV = Vector3.zero, pureLiftV = Vector3.zero;

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

                    pureDragV += -p.dragVectorDir * p.dragScalar;

                    if (!p.hasLiftModule)
                    {
                        Vector3 bodyLift = p.transform.rotation * (p.bodyLiftScalar * p.DragCubes.LiftForce);
                        bodyLift   = Vector3.ProjectOnPlane(bodyLift, -p.dragVectorDir);
                        pureLiftV += bodyLift;

                        for (int m = 0; m < p.Modules.Count; m++)
                        {
                            PartModule pm = p.Modules[m];
                            if (pm.isEnabled && pm is ModuleLiftingSurface)
                            {
                                ModuleLiftingSurface liftingSurface = pm as ModuleLiftingSurface;
                                if (!p.ShieldedFromAirstream)
                                {
                                    pureLiftV += liftingSurface.liftForce;
                                    pureDragV += liftingSurface.dragForce;
                                }
                            }
                        }
                    }
                }

                // Per NathanKell here http://forum.kerbalspaceprogram.com/threads/125746-Drag-Api?p=2029514&viewfull=1#post2029514
                // drag is in kN.  Divide by wet mass to get m/s^2 acceleration
                Vector3 force = pureDragV + pureLiftV;
                dragForce = Vector3.Dot(force, -vessel.srf_velocity.normalized);
            }

            return(dragForce);
        }
示例#17
0
        protected void Init(ModuleLiftingSurface surface, SimulatedPart part)
        {
            surface.SetupCoefficients(Vector3.forward, out Vector3 nVel, out this.liftVector, out float liftDot, out float absDot);
            this.omnidirectional      = surface.omnidirectional;
            this.perpendicularOnly    = surface.perpendicularOnly;
            this.liftCurve            = surface.liftCurve.Clone();
            this.liftMachCurve        = surface.liftMachCurve.Clone();
            this.dragCurve            = surface.dragCurve.Clone();
            this.dragMachCurve        = surface.dragMachCurve.Clone();
            this.deflectionLiftCoeff  = surface.deflectionLiftCoeff;
            this.useInternalDragModel = surface.useInternalDragModel;
            this.part = part;

            if (surface is ModuleControlSurface ctrl)
            {
                this.deflectionLiftCoeff *= (1 - ctrl.ctrlSurfaceArea);
            }
        }
示例#18
0
        private double FallbackEvaluateLiftForce()
        {
            double liftForce = 0.0;

            if (altitudeASL < vessel.mainBody.RealMaxAtmosphereAltitude())
            {
                Vector3 pureDragV = Vector3.zero, pureLiftV = Vector3.zero;

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

                    pureDragV += -p.dragVectorDir * p.dragScalar;

                    if (!p.hasLiftModule)
                    {
                        Vector3 bodyLift = p.transform.rotation * (p.bodyLiftScalar * p.DragCubes.LiftForce);
                        bodyLift   = Vector3.ProjectOnPlane(bodyLift, -p.dragVectorDir);
                        pureLiftV += bodyLift;

                        for (int m = 0; m < p.Modules.Count; m++)
                        {
                            PartModule pm = p.Modules[m];
                            if (pm.isEnabled && pm is ModuleLiftingSurface)
                            {
                                ModuleLiftingSurface liftingSurface = pm as ModuleLiftingSurface;
                                if (!p.ShieldedFromAirstream)
                                {
                                    pureLiftV += liftingSurface.liftForce;
                                    pureDragV += liftingSurface.dragForce;
                                }
                            }
                        }
                    }
                }

                Vector3 force   = pureDragV + pureLiftV;
                Vector3 liftDir = -Vector3.Cross(vessel.transform.right, vessel.srf_velocity.normalized);
                liftForce = Vector3.Dot(force, liftDir);
            }

            return(liftForce);
        }
示例#19
0
        public override void OnUpdate()
        {
            base.OnUpdate();

            if (HighLogic.LoadedSceneIsFlight == false)
            {
                return;
            }
            if (watchAnimation == false)
            {
                return;
            }

            //Are we done deploying/stowing the wing?
            //If so, update the lift and the GUI.
            if (anim.aniState == ModuleAnimateGeneric.animationStates.MOVING)
            {
                ModuleLiftingSurface liftingSurface = this.part.FindModuleImplementing <ModuleLiftingSurface>();

                if (liftingSurface == null)
                {
                    return;
                }

                if (isDeploying)
                {
                    //Update dragModel & CoLOffset
                    Events["DeployWing"].active        = false;
                    Events["StowWing"].active          = true;
                    liftingSurface.deflectionLiftCoeff = deflectionLiftCoeffDeployed;
                    watchAnimation = false;
                }
                else
                {
                    //Update dragModel & CoLOffset
                    Events["DeployWing"].active        = true;
                    Events["StowWing"].active          = false;
                    liftingSurface.deflectionLiftCoeff = deflectionLiftCoeffStowed;
                    watchAnimation = false;
                }
            }
        }
 private void OnDestroy()
 {
     if (liftArrow != null)
     {
         UnityEngine.Object.Destroy(liftArrow);
         liftArrow = null;
     }
     if (dragArrow != null)
     {
         UnityEngine.Object.Destroy(dragArrow);
         dragArrow = null;
     }
     if (momentArrow != null)
     {
         UnityEngine.Object.Destroy(momentArrow);
         momentArrow = null;
     }
     legacyWingModel        = null;
     stockAeroSurfaceModule = null;
 }
示例#21
0
        public override void OnStart(StartState state)
        {
            base.OnStart(state);

            anim = this.part.FindModuleImplementing <ModuleAnimateGeneric>();
            if (anim == null)
            {
                Debug.Log("[ModuleDeployableWing] ModuleAnimateGeneric not found!");
                return;
            }
            anim.Events["Toggle"].guiActive          = false;
            anim.Events["Toggle"].guiActiveEditor    = false;
            anim.Events["Toggle"].guiActiveUnfocused = false;

            ModuleLiftingSurface liftingSurface = this.part.FindModuleImplementing <ModuleLiftingSurface>();

            if (liftingSurface == null)
            {
                Debug.Log("[ModuleDeployableWing] ModuleLiftingSurface not found!");
                return;
            }

            //If we're showing the endEventGUIName then the wing is deployed.
            if (anim.Events["Toggle"].guiName == anim.startEventGUIName)          //animation.endEventGUIName)
            {
                Events["DeployWing"].active = false;                              //true;
                Events["StowWing"].active   = true;                               //false;

                liftingSurface.deflectionLiftCoeff = deflectionLiftCoeffDeployed; //deflectionLiftCoeffStowed
            }

            else
            {
                Events["DeployWing"].active = true;                             //false;
                Events["StowWing"].active   = false;                            //true;

                liftingSurface.deflectionLiftCoeff = deflectionLiftCoeffStowed; //deflectionLiftCoeffDeployed
            }
        }
        private ModuleLiftingSurface GetLiftingSurface()
        {
            Debug.Log(string.Format("{0} ModulePebkacLesPitchControl.GetLiftingSurface", _myModTag));
            ModuleLiftingSurface myLiftingSurface = null;

            try
            {
                myLiftingSurface = part.FindModulesImplementing <ModuleLiftingSurface>().SingleOrDefault();
            }
            catch (System.Exception x)
            {
                Debug.Log(string.Format("{0} ERROR: {1}", _myModTag, x.Message));
            }

            if (!myLiftingSurface)
            {
                // this shouldn't happen under normal circumstances
                Debug.LogError("ERROR: Didn't find ModuleLiftingSurface on LES nosecone!");
            }

            return(myLiftingSurface);
        }
示例#23
0
        private void OnDestroy()
        {
            if (liftArrow != null)
            {
                Destroy(liftArrow);
                liftArrow = null;
            }

            if (dragArrow != null)
            {
                Destroy(dragArrow);
                dragArrow = null;
            }

            if (momentArrow != null)
            {
                Destroy(momentArrow);
                momentArrow = null;
            }

            LegacyWingModel        = null;
            stockAeroSurfaceModule = null;
        }
        private void FixedUpdateLateLate()
        {
            if (!vessel.loaded)
            {
                return;
            }

            // Checks to see if ground effect would have any significance
            if (((vessel.situation & LowFlying) == 0) ||
                (vessel.radarAltitude > ActivateAltitude) ||
                !vessel.mainBody.hasSolidSurface ||
                !vessel.mainBody.atmosphere)
            {
                if (inRange)
                {
                    // Previously in ground effect, just exited
                    print(vessel.GetName() + " Exited Ground Effect range");
                    inRange = false;
                    //ResetLiftValues();
                    liftingSurfaces = null;
                }

                return;
            }


            if (liftingSurfaces == null)
            {
                // Count the control surfaces if not done so
                //print(vessel.GetName() + " Entered Ground Effect range");
                CountSurfaces();
            }

            groundDir   = vessel.gravityForPos.normalized;
            oceanNormal = -groundDir;

            // Use raytrace below to set the ground plane

            if (vessel.radarAltitude < wingSpan * 2.0f)
            {
                RaycastHit ray;
                // 1 << 15 hits anything that isn't a vessel or ocean
                if (Physics.Raycast(vessel.CoM, groundDir, out ray,
                                    wingSpan * 2.0f, 1 << 15))
                {
                    groundPlane.SetNormalAndPosition(ray.normal, ray.point);
                }
                else
                {
                    groundPlane.distance = 0.0f;
                }
            }
            else
            {
                groundPlane.distance = 0.0f;
            }

            float newWingSpan = 1.0f;

            bool prevInGroundEffect = inGroundEffect;

            // Set true in AddGroundEffectForce, if any wing is close enough to the
            // ground
            inGroundEffect = false;

            // Loop trough all surfaces and change their lift
            // Also get the max wingspan


            for (int i = 0; i < liftingSurfaces.Count; i++)
            {
                ModuleLiftingSurface surface = liftingSurfaces[i].surface;
                float mul  = liftingSurfaces[i].groundEffectMultiplier;
                Part  part = surface.part;



                Vector3 newLift = AddGroundEffectForce(part, surface.liftForce,
                                                       mul);

                // set aerodynamic overlay
                if (surface.liftArrow)
                {
                    // arrow length is 2x smaller than lift force as of 1.10
                    surface.liftArrow.Length    = newLift.magnitude * 0.5f;
                    surface.liftArrow.Direction = newLift;
                }


                newWingSpan = Math.Max(newWingSpan, ApproximateWingSpan(part));
            }

            if (prevInGroundEffect && !inGroundEffect)
            {
                print(vessel.GetName() + " Exited Ground Effect");
            }
            else if (!prevInGroundEffect && inGroundEffect)
            {
                print(vessel.GetName() + " Entered Ground Effect");
            }

            //print("wingspan: " + newWingSpan);

            wingSpan = newWingSpan;
        }
示例#25
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);
        }
        //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;
                }
            }
        }
示例#27
0
        // This method will calculate various useful stats
        // That we display in the GUI.
        public void GetAeroStats(Vector3d nVel)
        {
            Vessel   v      = FlightGlobals.ActiveVessel;
            Vector3d vLift  = Vector3d.zero; // the sum of lift from all parts
            Vector3d vDrag  = Vector3d.zero; // the sum of drag from all parts
            double   sqrMag = v.srf_velocity.sqrMagnitude;

            Q   = 0.5 * v.atmDensity * sqrMag;              // dynamic pressure, aka Q
            eas = Math.Sqrt(sqrMag * v.atmDensity / 1.225); // Equivalent Air Speed
            // i.e. your airspeed at sea level with the same Q
            density    = v.atmDensity;
            pressure   = v.staticPressurekPa * 1000.0;
            mach       = v.rootPart.machNumber;
            soundSpeed = v.speedOfSound;
            double dTime = TimeWarp.fixedDeltaTime;
            double mass  = 0d;

            // Now we loop through all parts, checking the modules in each part
            // This way we get all drag, lift, and thrust.
            for (int i = 0; i < v.Parts.Count; ++i)
            {
                Part p = v.Parts[i];
                mass += p.mass + p.GetResourceMass();
                // get part drag (but not wing/surface drag)
                vDrag += -p.dragVectorDir * p.dragScalar;
                if (!p.hasLiftModule)
                {
                    Vector3 bodyLift = p.transform.rotation * (p.bodyLiftScalar * p.DragCubes.LiftForce);
                    bodyLift = Vector3.ProjectOnPlane(bodyLift, -p.dragVectorDir);
                    vLift   += bodyLift;
                }

                // get convection
                convectiveTotal += p.thermalConvectionFlux * dTime;

                // now find modules
                for (int j = 0; j < p.Modules.Count; ++j)
                {
                    var m = p.Modules[j];
                    if (m is ModuleLiftingSurface) // control surface derives from this
                    {
                        ModuleLiftingSurface wing = (ModuleLiftingSurface)m;
                        vLift += wing.liftForce;
                        vDrag += wing.dragForce;
                    }
                    // Get thrust
                    if (m is ModuleEngines) // FX derives from this
                    {
                        thrust += ((ModuleEngines)m).finalThrust;
                    }
                }
            }
            // pLift is 'pure' lift, and same for drag, i.e. just the magnitude of each
            pLift = vLift.magnitude;
            pDrag = vDrag.magnitude;
            Vector3d force   = vLift + vDrag;                            // sum of all forces on the craft
            Vector3d liftDir = -Vector3d.Cross(v.transform.right, nVel); // we need the "lift" direction, which

            // is "up" from our current velocity vector and roll angle.

            // Now we can compute the dots.
            lift        = Vector3d.Dot(force, liftDir);  // just the force in the 'lift' direction
            liftUp      = Vector3d.Dot(force, v.upAxis); // just the force in the 'up' direction (note, some of it may be drag!)
            drag        = Vector3d.Dot(force, -nVel);    // drag force, = pDrag + lift-induced drag
            lidForce    = Vector3d.Dot(vLift, -nVel);    // Lift Induced Drag
            dragUpForce = Vector3d.Dot(vDrag, v.upAxis); // any drag in the opposite direction of gravity
            ldRatio     = lift / drag;                   // Lift / Drag ratio
            terminalV   = Math.Sqrt(grav / drag) * v.speed;
            if (double.IsNaN(terminalV))
            {
                terminalV = 0d;
            }

            double qRecip = 1000d / Q; // convert kN to Newtons

            ClS            = lift * qRecip;
            CdS            = drag * qRecip;
            ballisticCoeff = 1000d * mass / CdS; // convert tonnes to kg
        }
        void Start()
        {
            part.maximum_drag = 0;
            part.minimum_drag = 0;
            part.angularDrag = 0;
            if (HighLogic.LoadedSceneIsFlight)
                this.enabled = true;
            else if (HighLogic.LoadedSceneIsEditor)
                this.enabled = false;

            partLocalVel = Vector3.zero;
            partLocalForce = Vector3.zero;
            partLocalTorque = Vector3.zero;

            if (!part.Modules.Contains("ModuleAeroSurface"))
                part.dragModel = Part.DragModel.CYLINDRICAL;

            if(FARDebugValues.allowStructuralFailures)
            {
                FARPartStressTemplate template = FARAeroStress.DetermineStressTemplate(this.part);
                partStressMaxY = template.YmaxStress;
                partStressMaxXZ = template.XZmaxStress;
            }
            partTransform = part.partTransform;

            materialColorUpdater = new MaterialColorUpdater(partTransform, PhysicsGlobals.TemperaturePropertyID);
            if (part.Modules.Contains("FARWingAerodynamicModel"))
                legacyWingModel = part.Modules["FARWingAerodynamicModel"] as FARWingAerodynamicModel;
            else if (part.Modules.Contains("FARControllableSurface"))
                legacyWingModel = part.Modules["FARControllableSurface"] as FARWingAerodynamicModel;
            else
                legacyWingModel = null;

            // For handling airbrakes aero visualization
            if (part.Modules.Contains("ModuleAeroSurface"))
                stockAeroSurfaceModule = part.Modules["ModuleAeroSurface"] as ModuleAeroSurface;
            else
                stockAeroSurfaceModule = null;
        }
 private void OnDestroy()
 {
     if (liftArrow != null)
     {
         UnityEngine.Object.Destroy(liftArrow);
         liftArrow = null;
     }
     if (dragArrow != null)
     {
         UnityEngine.Object.Destroy(dragArrow);
         dragArrow = null;
     }
     if (momentArrow != null)
     {
         UnityEngine.Object.Destroy(momentArrow);
         momentArrow = null;
     }
     legacyWingModel = null;
     stockAeroSurfaceModule = null;
 }
示例#30
0
        private void UpdateAeroForces()
        {
            if (aeroDataValid)
            {
                return;
            }

            aeroDataValid = true;

            gravForce = 1000.0 * vessel.GetTotalMass() * FlightGlobals.getGeeForceAtPosition(vessel.CoM).magnitude; // force of gravity

            // Short-circuit these computations if there's no atmosphere.
            if (vessel.atmDensity == 0.0)
            {
                liftForce        = 0.0;
                dragForce        = 0.0;
                terminalVelocity = 0.0;
                liftUpForce      = 0.0;

                return;
            }

            // Code substantially from NathanKell's AeroGUI mod,
            // https://github.com/NathanKell/AeroGUI/blob/ccfd5e2e40fdf13e6ce66517ceb1db418689a5f0/AeroGUI/AeroGUI.cs#L301

            Vector3d vLift    = Vector3d.zero; // the sum of lift from all parts
            Vector3d vDrag    = Vector3d.zero; // the sum of drag from all parts
            double   areaDrag = 0.0;

            for (int i = vessel.Parts.Count - 1; i >= 0; --i)
            {
                Part p = vessel.Parts[i];

                // get part drag (but not wing/surface drag)
                vDrag += -p.dragVectorDir * p.dragScalar;
                if (!p.hasLiftModule)
                {
                    Vector3 bodyLift = p.transform.rotation * (p.bodyLiftScalar * p.DragCubes.LiftForce);
                    bodyLift = Vector3.ProjectOnPlane(bodyLift, -p.dragVectorDir);
                    vLift   += bodyLift;
                }

                ModuleLiftingSurface wing = p.FindModuleImplementing <ModuleLiftingSurface>();
                if (wing != null)
                {
                    vLift += wing.liftForce;
                    vDrag += wing.dragForce;
                }

                areaDrag += p.DragCubes.AreaDrag * PhysicsGlobals.DragCubeMultiplier * PhysicsGlobals.DragMultiplier;
            }

            Vector3d force   = vLift + vDrag;                                 // sum of all forces on the craft
            Vector3d nVel    = vessel.srf_velocity.normalized;
            Vector3d liftDir = -Vector3d.Cross(vessel.transform.right, nVel); // we need the "lift" direction, which

            // is "up" from our current velocity vector and roll angle.

            // Now we can compute the dots.
            liftForce = Vector3d.Dot(force, liftDir); // just the force in the 'lift' direction

            dragForce = Vector3d.Dot(force, -nVel);   // drag force, = pDrag + lift-induced drag

            liftUpForce = Vector3d.Dot(force, up);

            terminalVelocity = Math.Sqrt(2.0 * gravForce / (areaDrag * vessel.atmDensity));
        }
        public override void OnStart(StartState state)
        {
            // hook up to the part attach callback
            /*
            if (state == StartState.Editor)
            {
                part.OnEditorAttach += OnEditorAttach;
            }
            */

            List<ModuleEngines> engines = part.FindModulesImplementing<ModuleEngines>();
            foreach (ModuleEngines e in engines)
            {
                if (e.engineID == escapeEngineID)
                {
                    escapeEngine = e;
                }
                else if (e.engineID == pitchEngineID)
                {
                    pitchEngine = e;
                }
                else if (e.engineID == jettisonEngineID)
                {
                    jettisonEngine = e;
                }
                foreach (BaseAction a in e.Actions)
                {
                    a.active = false;
                }
                foreach (BaseField f in e.Fields)
                {
                    f.guiActive = false;
                    f.guiActiveEditor = false;
                }
                foreach (BaseEvent ev in e.Events)
                {
                    ev.guiActive = false;
                    ev.guiActiveEditor = false;
                }
            }

            // check for nulls in engines

            // set up the variables used to shift aerodynamics
            _maxFuel = part.Resources["SolidFuel"].maxAmount;
            _origComOffset = part.CoMOffset;
            _origCopOffset = part.CoPOffset;
            _origColOffset = part.CoLOffset;

            // set up the variables used by code for simming the canards
            _deployAnimation = GetDeployAnimation();
            _liftingSurface = GetLiftingSurface();
        }
        //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);
        }
示例#33
0
        public static Vector3 get_part_torque(CenterOfLiftQuery qry, Part p, Vector3 CoM, ref float lift, ref float drag)
        {
            if (p == null || (p.Rigidbody != p.rb) && !PhysicsGlobals.ApplyDragToNonPhysicsParts)
            {
                return(Vector3.zero);
            }

            Vector3 lift_pos = Vector3.zero;
            Vector3 drag_pos = Vector3.zero;

            if (!p.ShieldedFromAirstream)
            {
                var providers = p.FindModulesImplementing <ModuleLiftingSurface>();
                if ((providers != null) && providers.Count > 0)
                {
                    p.hasLiftModule = true;
                }

                Vector3 res = Vector3.zero;

                if (p.hasLiftModule && providers[0] is ModuleControlSurface)
                {
                    p.DragCubes.SetCubeWeight("neutral", 1.5f);
                    p.DragCubes.SetCubeWeight("fullDeflectionPos", 0.0f);
                    p.DragCubes.SetCubeWeight("fullDeflectionNeg", 0.0f);
                }

                // drag from drag-cubes
                if (!p.DragCubes.None)
                {
                    Vector3 drag_force = Vector3.zero;

                    p.dragVector         = qry.refVector;
                    p.dragVectorSqrMag   = p.dragVector.sqrMagnitude;
                    p.dragVectorMag      = Mathf.Sqrt(p.dragVectorSqrMag);
                    p.dragVectorDir      = p.dragVector / p.dragVectorMag;
                    p.dragVectorDirLocal = -p.partTransform.InverseTransformDirection(p.dragVectorDir);

                    p.dynamicPressurekPa = qry.refAirDensity * 0.0005 * p.dragVectorSqrMag;

                    if (p.rb != p.Rigidbody && PhysicsGlobals.ApplyDragToNonPhysicsPartsAtParentCoM)
                    {
                        drag_pos = p.Rigidbody.worldCenterOfMass;
                        lift_pos = drag_pos;
                    }
                    else
                    {
                        lift_pos = p.partTransform.TransformPoint(p.CoLOffset);
                        drag_pos = p.partTransform.TransformPoint(p.CoPOffset);
                    }

                    p.DragCubes.SetDrag(p.dragVectorDirLocal, mach);

                    float pseudoreynolds   = (float)(density * Mathf.Abs(speed));
                    float pseudoredragmult = PhysicsGlobals.DragCurvePseudoReynolds.Evaluate(pseudoreynolds);
                    float drag_k           = p.DragCubes.AreaDrag * PhysicsGlobals.DragCubeMultiplier * pseudoredragmult;
                    p.dragScalar = (float)(p.dynamicPressurekPa * drag_k * PhysicsGlobals.DragMultiplier);

                    drag_force = p.dragScalar * -p.dragVectorDir;

                    res += Vector3.Cross(drag_force, drag_pos - CoM);

                    Vector3 sum_force = drag_force;

                    drag += Vector3.Dot(sum_force, -p.dragVectorDir);
                }

                if (!p.hasLiftModule)
                {
                    // stock aero lift
                    if (!p.DragCubes.None)
                    {
                        p.bodyLiftScalar = (float)(p.dynamicPressurekPa * p.bodyLiftMultiplier * PhysicsGlobals.BodyLiftMultiplier *
                                                   CorrectCoL.CoLMarkerFull.lift_curves.liftMachCurve.Evaluate(mach));

                        Vector3 lift_force = p.partTransform.rotation * (p.bodyLiftScalar * p.DragCubes.LiftForce);
                        lift_force = Vector3.ProjectOnPlane(lift_force, -p.dragVectorDir);

                        res += Vector3.Cross(lift_force, lift_pos - CoM);

                        Vector3 sum_force = lift_force;

                        lift += Vector3.Dot(sum_force, Vector3.Cross(p.dragVectorDir, EditorLogic.RootPart.transform.right).normalized);
                    }
                    return(res);
                }
                else
                {
                    double q = 0.5 * qry.refAirDensity * qry.refVector.sqrMagnitude;

                    for (int i = 0; i < providers.Count; i++)
                    {
                        Vector3 dragvect;
                        Vector3 liftvect;
                        Vector3 lift_force = Vector3.zero;
                        Vector3 drag_force = Vector3.zero;
                        float   abs;
                        ModuleLiftingSurface lsurf = providers[i];
                        ModuleControlSurface csurf = lsurf as ModuleControlSurface;
                        lsurf.SetupCoefficients(qry.refVector, out dragvect, out liftvect, out lsurf.liftDot, out abs);

                        lift_pos = p.partTransform.TransformPoint(p.CoLOffset);
                        drag_pos = p.partTransform.TransformPoint(p.CoPOffset);

                        lift_force = lsurf.GetLiftVector(liftvect, lsurf.liftDot, abs, q, mach);
                        if (lsurf.useInternalDragModel)
                        {
                            drag_force = lsurf.GetDragVector(dragvect, abs, q);
                        }

                        if (csurf != null)
                        {
                            float      deflection = (float)deflection_field.GetValue(csurf);
                            Quaternion incidence  = Quaternion.AngleAxis(csurf.ctrlSurfaceRange * deflection, p.partTransform.rotation * Vector3.right);
                            liftvect      = incidence * liftvect;
                            lsurf.liftDot = Vector3.Dot(dragvect, liftvect);
                            abs           = Mathf.Abs(lsurf.liftDot);
                            lift_force    = lift_force * (1.0f - csurf.ctrlSurfaceArea);
                            lift_force   += lsurf.GetLiftVector(liftvect, lsurf.liftDot, abs, q, mach) * csurf.ctrlSurfaceArea;
                            if (csurf.useInternalDragModel)
                            {
                                drag_force  = drag_force * (1.0f - csurf.ctrlSurfaceArea);
                                drag_force += csurf.GetDragVector(dragvect, abs, q) * csurf.ctrlSurfaceArea;
                            }
                        }

                        res += Vector3.Cross(lift_force, lift_pos - CoM);
                        res += Vector3.Cross(drag_force, drag_pos - CoM);

                        Vector3 result_force = lift_force + drag_force;
                        lift += Vector3.Dot(result_force, Vector3.Cross(qry.refVector, EditorLogic.RootPart.transform.right).normalized);
                        drag += Vector3.Dot(result_force, -qry.refVector.normalized);
                    }
                    return(res);
                }
            }

            return(Vector3.zero);
        }