Exemplo n.º 1
0
            public VelPoint(AeroPredictor vessel, CelestialBody body, float altitude, float speed)
            {
                this.altitude = altitude;
                this.speed    = speed;
                AeroPredictor.Conditions conditions = new AeroPredictor.Conditions(body, speed, altitude);
                float gravParameter, radius;

                lock (body)
                {
                    gravParameter = (float)body.gravParameter;
                    radius        = (float)body.Radius;
                }
                this.mach            = conditions.mach;
                this.dynamicPressure = 0.0005f * conditions.atmDensity * speed * speed;
                float   weight = (vessel.Mass * gravParameter / ((radius + altitude) * (radius + altitude))) - (vessel.Mass * speed * speed / (radius + altitude));
                Vector3 thrustForce = vessel.GetThrustForce(conditions);

                AoA_max          = vessel.GetMaxAoA(conditions, out Lift_max);
                AoA_level        = Mathf.Min(vessel.GetAoA(conditions, weight), AoA_max);
                pitchInput       = vessel.GetPitchInput(conditions, AoA_level);
                Thrust_available = thrustForce.magnitude;
                Vector3 force = vessel.GetAeroForce(conditions, AoA_level, pitchInput);

                drag          = AeroPredictor.GetDragForceMagnitude(force, AoA_level);
                Thrust_excess = -drag - AeroPredictor.GetDragForceMagnitude(thrustForce, AoA_level);
                Accel_excess  = Thrust_excess / vessel.Mass / WindTunnelWindow.gAccel;
                LDRatio       = Mathf.Abs(AeroPredictor.GetLiftForceMagnitude(force, AoA_level) / drag);
                dLift         = (vessel.GetLiftForceMagnitude(conditions, AoA_level + WindTunnelWindow.AoAdelta, pitchInput) -
                                 vessel.GetLiftForceMagnitude(conditions, AoA_level, pitchInput)) / (WindTunnelWindow.AoAdelta * Mathf.Rad2Deg);
            }
            public EnvelopePoint(AeroPredictor vessel, CelestialBody body, float altitude, float speed, float AoA_guess = float.NaN, float maxA_guess = float.NaN, float pitchI_guess = float.NaN)
            {
                this.altitude = altitude;
                this.speed    = speed;
                AeroPredictor.Conditions conditions = new AeroPredictor.Conditions(body, speed, altitude);
                float gravParameter, radius;

                lock (body)
                {
                    gravParameter = (float)body.gravParameter;
                    radius        = (float)body.Radius;
                }
                this.mach            = conditions.mach;
                this.dynamicPressure = 0.0005f * conditions.atmDensity * speed * speed;
                float   weight = (vessel.Mass * gravParameter / ((radius + altitude) * (radius + altitude))); // TODO: Minus centrifugal force...
                Vector3 thrustForce = vessel.GetThrustForce(conditions);

                //AoA_max = vessel.GetMaxAoA(conditions, out Lift_max, maxA_guess);
                if (float.IsNaN(maxA_guess))
                {
                    AoA_max = vessel.GetMaxAoA(conditions, out Lift_max, maxA_guess);
                }
                else
                {
                    AoA_max  = maxA_guess;
                    Lift_max = AeroPredictor.GetLiftForceMagnitude(vessel.GetAeroForce(conditions, AoA_max, 1) + thrustForce, AoA_max);
                }

                AoA_level = vessel.GetAoA(conditions, weight, guess: AoA_guess, pitchInputGuess: 0, lockPitchInput: true);
                if (AoA_level < AoA_max)
                {
                    pitchInput = vessel.GetPitchInput(conditions, AoA_level, guess: pitchI_guess);
                }
                else
                {
                    pitchInput = 1;
                }

                Thrust_available = thrustForce.magnitude;
                force            = vessel.GetAeroForce(conditions, AoA_level, pitchInput);
                liftforce        = AeroPredictor.ToFlightFrame(force, AoA_level); //vessel.GetLiftForce(body, speed, altitude, AoA_level, mach, atmDensity);
                drag             = AeroPredictor.GetDragForceMagnitude(force, AoA_level);
                float lift = AeroPredictor.GetLiftForceMagnitude(force, AoA_level);

                Thrust_excess = -drag - AeroPredictor.GetDragForceMagnitude(thrustForce, AoA_level);
                if (weight > Lift_max)// AoA_level >= AoA_max)
                {
                    Thrust_excess = Lift_max - weight;
                    AoA_level     = AoA_max;
                }
                Accel_excess = (Thrust_excess / vessel.Mass / WindTunnelWindow.gAccel);
                LDRatio      = Mathf.Abs(lift / drag);
                dLift        = (vessel.GetLiftForceMagnitude(conditions, AoA_level + WindTunnelWindow.AoAdelta, pitchInput) -
                                vessel.GetLiftForceMagnitude(conditions, AoA_level, pitchInput)) / (WindTunnelWindow.AoAdelta * Mathf.Rad2Deg);
            }
Exemplo n.º 3
0
        public virtual Vector3 GetLiftForce(Vector3 inflow, AeroPredictor.Conditions conditions, float AoA, float pitchInput, out Vector3 torque, Vector3 torquePoint)
        {
            Vector3 aeroForce = Vector3.zero;

            torque = Vector3.zero;

            for (int i = parts.Count - 1; i >= 0; i--)
            {
                if (parts[i].shieldedFromAirstream)
                {
                    continue;
                }
                aeroForce += parts[i].GetLift(inflow, conditions.mach, out Vector3 pTorque, torquePoint);
                torque    += pTorque;
            }
            for (int i = surfaces.Count - 1; i >= 0; i--)
            {
                if (surfaces[i].part.shieldedFromAirstream)
                {
                    continue;
                }
                aeroForce += surfaces[i].GetLift(inflow, conditions.mach, out Vector3 pTorque, torquePoint);
                torque    += pTorque;
            }
            for (int i = ctrls.Count - 1; i >= 0; i--)
            {
                if (ctrls[i].part.shieldedFromAirstream)
                {
                    continue;
                }
                aeroForce += ctrls[i].GetLift(inflow, conditions.mach, pitchInput, out Vector3 pTorque, torquePoint);
                torque    += pTorque;
            }
            for (int i = partCollections.Count - 1; i >= 0; i--)
            {
                aeroForce += partCollections[i].GetLiftForce(inflow, conditions, AoA, pitchInput, out Vector3 pTorque, torquePoint);
                torque    += pTorque;
            }

            //float Q = 0.0005f * conditions.atmDensity * conditions.speed * conditions.speed;
            //torque *= Q;
            return(aeroForce); // * Q;
        }
Exemplo n.º 4
0
            public AoAPoint(AeroPredictor vessel, CelestialBody body, float altitude, float speed, float AoA)
            {
                this.altitude = altitude;
                this.speed    = speed;
                AeroPredictor.Conditions conditions = new AeroPredictor.Conditions(body, speed, altitude);
                this.AoA             = AoA;
                this.mach            = conditions.mach;
                this.dynamicPressure = 0.0005f * conditions.atmDensity * speed * speed;
                this.pitchInput      = vessel.GetPitchInput(conditions, AoA);
                this.pitchInput_dry  = vessel.GetPitchInput(conditions, AoA, true);
                Vector3 force = AeroPredictor.ToFlightFrame(vessel.GetAeroForce(conditions, AoA, pitchInput), AoA);

                torque     = vessel.GetAeroTorque(conditions, AoA).x;
                torque_dry = vessel.GetAeroTorque(conditions, AoA, 0, true).x;
                Lift       = force.y;
                Drag       = -force.z;
                LDRatio    = Mathf.Abs(Lift / Drag);
                dLift      = (vessel.GetLiftForceMagnitude(conditions, AoA + WindTunnelWindow.AoAdelta, pitchInput) - Lift) /
                             (WindTunnelWindow.AoAdelta * Mathf.Rad2Deg);
            }
Exemplo n.º 5
0
        private static void GetStabilityValues(AeroPredictor vessel, AeroPredictor.Conditions conditions, float AoA_centre, out float stabilityRange, out float stabilityScore)
        {
            const int step       = 5;
            const int range      = 90;
            const int alphaSteps = range / step;

            float[] torques = new float[2 * alphaSteps + 1];
            float[] aoas = new float[2 * alphaSteps + 1];
            int     start, end;

            for (int i = 0; i <= 2 * alphaSteps; i++)
            {
                aoas[i]    = (i - alphaSteps) * step * Mathf.Deg2Rad;
                torques[i] = vessel.GetAeroTorque(conditions, aoas[i], 0).x;
            }
            int eq  = 0 + alphaSteps;
            int dir = (int)Math.Sign(torques[eq]);

            if (dir == 0)
            {
                start = eq - 1;
                end   = eq + 1;
            }
            else
            {
                while (eq > 0 && eq < 2 * alphaSteps)
                {
                    eq += dir;
                    if (Math.Sign(torques[eq]) != dir)
                    {
                        break;
                    }
                }
                if (eq == 0 || eq == 2 * alphaSteps)
                {
                    stabilityRange = 0;
                    stabilityScore = 0;
                    return;
                }
                if (dir < 0)
                {
                    start = eq;
                    end   = eq + 1;
                }
                else
                {
                    start = eq - 1;
                    end   = eq;
                }
            }
            while (torques[start] > 0 && start > 0)
            {
                start -= 1;
            }
            while (torques[end] < 0 && end < 2 * alphaSteps - 1)
            {
                end += 1;
            }
            float min = (Mathf.InverseLerp(torques[start], torques[start + 1], 0) + start) * step;
            float max = (-Mathf.InverseLerp(torques[end], torques[end - 1], 0) + end) * step;

            stabilityRange = max - min;
            stabilityScore = 0;
            for (int i = start; i < end; i++)
            {
                stabilityScore += (torques[i] + torques[i + 1]) / 2 * step;
            }
        }
Exemplo n.º 6
0
        public EnvelopePoint(AeroPredictor vessel, CelestialBody body, float altitude, float speed, float AoA_guess = float.NaN, float maxA_guess = float.NaN, float pitchI_guess = float.NaN)
        {
            this.altitude = altitude;
            this.speed    = speed;
            AeroPredictor.Conditions conditions = new AeroPredictor.Conditions(body, speed, altitude);
            float gravParameter, radius;

            gravParameter        = (float)body.gravParameter;
            radius               = (float)body.Radius;
            this.mach            = conditions.mach;
            this.dynamicPressure = 0.0005f * conditions.atmDensity * speed * speed;
            float   weight = (vessel.Mass * gravParameter / ((radius + altitude) * (radius + altitude))) - (vessel.Mass * speed * speed / (radius + altitude));
            Vector3 thrustForce = vessel.GetThrustForce(conditions);

            fuelBurnRate = vessel.GetFuelBurnRate(conditions);
            //AoA_max = vessel.GetMaxAoA(conditions, out Lift_max, maxA_guess);
            if (float.IsNaN(maxA_guess))
            {
                AoA_max = vessel.GetMaxAoA(conditions, out Lift_max, maxA_guess);
                //Lift_max = AeroPredictor.GetLiftForceMagnitude(vessel.GetAeroForce(conditions, AoA_max, 1) + thrustForce, AoA_max);
            }
            else
            {
                AoA_max  = maxA_guess;
                Lift_max = AeroPredictor.GetLiftForceMagnitude(vessel.GetAeroForce(conditions, AoA_max, 1) + thrustForce, AoA_max);
            }

            AoA_level = vessel.GetAoA(conditions, weight, guess: AoA_guess, pitchInputGuess: 0, lockPitchInput: true);
            if (AoA_level < AoA_max)
            {
                pitchInput = vessel.GetPitchInput(conditions, AoA_level, guess: pitchI_guess);
            }
            else
            {
                pitchInput = 1;
            }

            if (speed < 5 && Math.Abs(altitude) < 10)
            {
                AoA_level = 0;
            }

            Thrust_available = thrustForce.magnitude;

            //vessel.GetAeroCombined(conditions, AoA_level, pitchInput, out force, out Vector3 torque);
            force     = vessel.GetAeroForce(conditions, AoA_level, pitchInput);
            aeroforce = AeroPredictor.ToFlightFrame(force, AoA_level); //vessel.GetLiftForce(body, speed, altitude, AoA_level, mach, atmDensity);
            drag      = -aeroforce.z;
            float lift = aeroforce.y;

            Thrust_excess = -drag - AeroPredictor.GetDragForceMagnitude(thrustForce, AoA_level);
            if (weight > Lift_max)// AoA_level >= AoA_max)
            {
                Thrust_excess = Lift_max - weight;
                AoA_level     = AoA_max;
            }
            Accel_excess = (Thrust_excess / vessel.Mass / WindTunnelWindow.gAccel);
            LDRatio      = Math.Abs(lift / drag);
            dLift        = (vessel.GetLiftForceMagnitude(conditions, AoA_level + WindTunnelWindow.AoAdelta, pitchInput) - lift)
                           / (WindTunnelWindow.AoAdelta * Mathf.Rad2Deg);
            //stabilityDerivative = (vessel.GetAeroTorque(conditions, AoA_level + WindTunnelWindow.AoAdelta, pitchInput).x - torque.x)
            //    / (WindTunnelWindow.AoAdelta * Mathf.Rad2Deg);
            //GetStabilityValues(vessel, conditions, AoA_level, out stabilityRange, out stabilityScore);

            completed = true;
        }
        public override Vector3 GetLiftForce(Vector3 inflow, AeroPredictor.Conditions conditions, float pitchInput, out Vector3 torque, Vector3 torquePoint)
        {
            Vector3 aeroForce = Vector3.zero;

            torque = Vector3.zero;
            int   rotationCount = WindTunnelSettings.Instance.rotationCount;
            float Q             = 0.0005f * conditions.atmDensity;

            // The root part is the rotor hub, so since the rotating mesh is usually cylindrical we
            // only need to evaluate this part once.
            if (!parts[0].shieldedFromAirstream)
            {
                float localMach      = inflow.magnitude;
                float localVelFactor = localMach * localMach;
                float localPRDM;
                lock (PhysicsGlobals.DragCurvePseudoReynolds)
                    localPRDM = PhysicsGlobals.DragCurvePseudoReynolds.Evaluate(conditions.atmDensity * localMach);
                localMach /= conditions.speedOfSound;
                aeroForce += parts[0].GetAero(inflow.normalized, localMach, localPRDM, out Vector3 pTorque, origin) * localVelFactor * Q;
                torque    += pTorque * localVelFactor * Q;
            }

            for (int r = 0; r < rotationCount; r++)
            {
                Quaternion rotation   = Quaternion.AngleAxis(360f / rotationCount * r, axis);
                Vector3    rTorque    = Vector3.zero;
                Vector3    rAeroForce = Vector3.zero;
                // Rotate inflow
                Vector3 rotatedInflow = rotation * inflow;
                // Calculate forces
                for (int i = parts.Count - 1; i >= 1; i--)
                {
                    if (parts[i].shieldedFromAirstream)
                    {
                        continue;
                    }
                    //Vector3 partMotion = Vector3.Cross(axis, (parts[i].transformPosition - origin)) * angularVelocity + rotatedInflow;
                    Vector3 partMotion     = Vector3.Cross((parts[i].transformPosition - origin), axis) * angularVelocity + rotatedInflow;
                    Vector3 partInflow     = partMotion.normalized;
                    float   localMach      = partMotion.magnitude;
                    float   localVelFactor = localMach * localMach;
                    localMach  /= conditions.speedOfSound;
                    rAeroForce += parts[i].GetLift(partInflow, localMach, out Vector3 pTorque, torquePoint) * localVelFactor;
                    rTorque    += pTorque * localVelFactor;
                }
                for (int i = surfaces.Count - 1; i >= 0; i--)
                {
                    if (surfaces[i].part.shieldedFromAirstream)
                    {
                        continue;
                    }
                    //Vector3 partMotion = Vector3.Cross(axis, (surfaces[i].part.transformPosition + surfaces[i].velocityOffset - origin)) * angularVelocity + rotatedInflow;
                    Vector3 partMotion     = Vector3.Cross((surfaces[i].part.transformPosition + surfaces[i].velocityOffset - origin), axis) * angularVelocity + rotatedInflow;
                    Vector3 partInflow     = partMotion.normalized;
                    float   localMach      = partMotion.magnitude;
                    float   localVelFactor = localMach * localMach;
                    localMach  /= conditions.speedOfSound;
                    rAeroForce += surfaces[i].GetLift(partInflow, localMach, out Vector3 pTorque, torquePoint) * localVelFactor;
                    rTorque    += pTorque * localVelFactor;
                }
                for (int i = ctrls.Count - 1; i >= 0; i--)
                {
                    if (ctrls[i].part.shieldedFromAirstream)
                    {
                        continue;
                    }
                    //Vector3 partMotion = Vector3.Cross(axis, (ctrls[i].part.transformPosition + ctrls[i].velocityOffset - origin)) * angularVelocity + rotatedInflow;
                    Vector3 partMotion     = Vector3.Cross((ctrls[i].part.transformPosition + ctrls[i].velocityOffset - origin), axis) * angularVelocity + rotatedInflow;
                    Vector3 partInflow     = partMotion.normalized;
                    float   localMach      = partMotion.magnitude;
                    float   localVelFactor = localMach * localMach;
                    localMach  /= conditions.speedOfSound;
                    rAeroForce += ctrls[i].GetLift(partInflow, localMach, pitchInput, out Vector3 pTorque, torquePoint) * localVelFactor;
                    rTorque    += pTorque * localVelFactor;
                }

                rTorque    *= Q;
                rAeroForce *= Q;

                for (int i = partCollections.Count - 1; i >= 0; i--)
                {
                    //Vector3 partMotion = Vector3.Cross(axis, partCollections[i].origin - this.origin) * angularVelocity;
                    Vector3 partMotion = Vector3.Cross(partCollections[i].origin - this.origin, axis) * angularVelocity;
                    rAeroForce += partCollections[i].GetLiftForce(rotatedInflow + partMotion, conditions, pitchInput, out Vector3 pTorque, torquePoint);
                    rTorque    += pTorque;
                }

                // Rotate torque backwards
                rTorque = Quaternion.AngleAxis(-360f / rotationCount * r, axis) * rTorque;

                torque    += rTorque;
                aeroForce += rAeroForce;
            }
            aeroForce /= rotationCount;
            torque    /= rotationCount;
            torque    += Vector3.Cross(aeroForce, origin - torquePoint);

            return(aeroForce);
        }
        public override Vector3 GetAeroForce(Vector3 inflow, AeroPredictor.Conditions conditions, float pitchInput, out Vector3 torque, Vector3 torquePoint)
        {
            Vector3 aeroForce = Vector3.zero;

            torque = Vector3.zero;
            int   rotationCount = WindTunnelSettings.Instance.rotationCount;
            float Q             = 0.0005f * conditions.atmDensity;

            // The root part is the rotor hub, so since the rotating mesh is usually cylindrical we
            // only need to evaluate this part once.
            if (!parts[0].shieldedFromAirstream)
            {
                float localMach      = inflow.magnitude;
                float localVelFactor = localMach * localMach;
                float localPRDM;
                lock (PhysicsGlobals.DragCurvePseudoReynolds)
                    localPRDM = PhysicsGlobals.DragCurvePseudoReynolds.Evaluate(conditions.atmDensity * localMach);
                localMach /= conditions.speedOfSound;
                aeroForce += parts[0].GetAero(inflow.normalized, localMach, localPRDM, out Vector3 pTorque, origin) * localVelFactor * Q;
                torque    += pTorque * localVelFactor * Q;
            }

            for (int r = 0; r < rotationCount; r++)
            {
                Quaternion rotation   = Quaternion.AngleAxis(360f / rotationCount * r, axis);
                Vector3    rTorque    = Vector3.zero;
                Vector3    rAeroForce = Vector3.zero;
                // Rotate inflow
                Vector3 rotatedInflow = rotation * inflow;
                // Calculate forces
                for (int i = parts.Count - 1; i >= 1; i--)
                {
                    if (parts[i].shieldedFromAirstream)
                    {
                        continue;
                    }
                    Vector3 partMotion = Vector3.Cross(axis, (parts[i].transformPosition - origin)) * angularVelocity + rotatedInflow;
                    //Vector3 partMotion = Vector3.Cross((parts[i].transformPosition - origin), axis) * angularVelocity + rotatedInflow;
                    Vector3 partInflow     = partMotion.normalized;
                    float   localMach      = partMotion.magnitude;
                    float   localVelFactor = localMach * localMach;
                    float   localPRDM;
                    lock (PhysicsGlobals.DragCurvePseudoReynolds)
                        localPRDM = PhysicsGlobals.DragCurvePseudoReynolds.Evaluate(conditions.atmDensity * localMach);
                    localMach  /= conditions.speedOfSound;
                    rAeroForce += parts[i].GetAero(partInflow, localMach, localPRDM, out Vector3 pTorque, origin) * localVelFactor;
                    rTorque    += pTorque * localVelFactor;
                }
                for (int i = surfaces.Count - 1; i >= 0; i--)
                {
                    if (surfaces[i].part.shieldedFromAirstream)
                    {
                        continue;
                    }
                    Vector3 partMotion = Vector3.Cross(axis, (surfaces[i].part.transformPosition + surfaces[i].velocityOffset - origin)) * angularVelocity + rotatedInflow;
                    //Vector3 partMotion = Vector3.Cross((surfaces[i].part.transformPosition + surfaces[i].velocityOffset - origin), axis) * angularVelocity + rotatedInflow;
                    Vector3 partInflow     = partMotion.normalized;
                    float   localMach      = partMotion.magnitude;
                    float   localVelFactor = localMach * localMach;
                    localMach  /= conditions.speedOfSound;
                    rAeroForce += surfaces[i].GetForce(partInflow, localMach, out Vector3 pTorque, origin) * localVelFactor;
                    rTorque    += pTorque * localVelFactor;
                    if (conditions.altitude <= 50 && conditions.speed >= 15 && conditions.speed < 25 && Vector3.Angle(inflow, Vector3.forward) < 10)
                    {
                        if (i == surfaces.Count - 1)
                        {
                            Debug.LogFormat("\nAxis {0}\tAngularVelocity {1}\nSpeed {2}\tAltitude {3}", axis, angularVelocity, conditions.speed, conditions.altitude);
                        }
                        Debug.LogFormat("Surface {4}\tInflow {0}\tPartMotion {1}\tTorque {2}\tAeroForce{3}", rotatedInflow, partMotion, Quaternion.AngleAxis(-360f / rotationCount * r, axis) * pTorque, surfaces[i].GetForce(inflow + partMotion, conditions.mach, out _, origin), i);
                    }
                }
                for (int i = ctrls.Count - 1; i >= 0; i--)
                {
                    if (ctrls[i].part.shieldedFromAirstream)
                    {
                        continue;
                    }
                    Vector3 partMotion = Vector3.Cross(axis, (ctrls[i].part.transformPosition + ctrls[i].velocityOffset - origin)) * angularVelocity + rotatedInflow;
                    //Vector3 partMotion = Vector3.Cross((ctrls[i].part.transformPosition + ctrls[i].velocityOffset - origin), axis) * angularVelocity + rotatedInflow;
                    Vector3 partInflow     = partMotion.normalized;
                    float   localMach      = partMotion.magnitude;
                    float   localVelFactor = localMach * localMach;
                    float   localPRDM;
                    lock (PhysicsGlobals.DragCurvePseudoReynolds)
                        localPRDM = PhysicsGlobals.DragCurvePseudoReynolds.Evaluate(conditions.atmDensity * localMach);
                    localMach  /= conditions.speedOfSound;
                    rAeroForce += ctrls[i].GetForce(partInflow, localMach, pitchInput, localPRDM, out Vector3 pTorque, origin) * localVelFactor;
                    rTorque    += pTorque * localVelFactor;
                    if (conditions.altitude <= 50 && conditions.speed >= 15 && conditions.speed < 25 && Vector3.Angle(inflow, Vector3.forward) < 10)
                    {
                        if (i == ctrls.Count - 1 && surfaces.Count == 0)
                        {
                            Debug.LogFormat("\nAxis {0}\tAngularVelocity {1}\nSpeed {2}\tAltitude {3}\tRotated Inflow {4}", axis, angularVelocity, conditions.speed, conditions.altitude, rotatedInflow);

                            float surfaceInput = 0;
                            if (!ctrls[i].ignorePitch)
                            {
                                Vector3 input = ctrls[i].inputRotation * new Vector3(!ctrls[i].ignorePitch ? pitchInput : 0, 0, 0);
                                surfaceInput  = Vector3.Dot(input, ctrls[i].rotationAxis);
                                surfaceInput *= ctrls[i].authorityLimiter * 0.01f;
                                surfaceInput  = Mathf.Clamp(surfaceInput, -1, 1);
                            }
                            if (ctrls[i].deployed)
                            {
                                surfaceInput += ctrls[i].deployAngle;
                                surfaceInput  = Mathf.Clamp(surfaceInput, -1.5f, 1.5f);
                            }
                            surfaceInput *= ctrls[i].deflectionDirection;

                            Vector3 relLiftVector;
                            if (surfaceInput != 0)
                            {
                                relLiftVector = Quaternion.AngleAxis(ctrls[i].ctrlSurfaceRange * surfaceInput, ctrls[i].rotationAxis) * ctrls[i].liftVector;
                            }
                            else
                            {
                                relLiftVector = ctrls[i].liftVector;
                            }

                            float   dot    = Vector3.Dot(partInflow, relLiftVector);
                            float   absdot = ctrls[i].omnidirectional ? Math.Abs(dot) : Mathf.Clamp01(dot);
                            Vector3 lift   = Vector3.zero;
                            lock (ctrls[i].liftCurve)
                                lift = -relLiftVector *Math.Sign(dot) * ctrls[i].liftCurve.Evaluate(absdot) * ctrls[i].liftMachCurve.Evaluate(localMach) * ctrls[i].deflectionLiftCoeff * PhysicsGlobals.LiftMultiplier;
                            if (ctrls[i].perpendicularOnly)
                            {
                                lift = Vector3.ProjectOnPlane(lift, -partInflow);
                            }
                            Debug.LogFormat("Inflow vector: {3}\tBase lift vector: {0}\tCtrl lift vector: {1}\tDot: {2}\tAoA: {4}", ctrls[i].liftVector, relLiftVector, dot, partInflow, Mathf.Acos(-dot) * Mathf.Rad2Deg);
                            Debug.LogFormat("Lifting surface forces: {0} (without part drag)", lift * 1000 * Q * localVelFactor);
                        }
                        Debug.LogFormat("Ctrl {3}\tPartMotion {0}\tTorque {1}\tAeroForce{2}", partMotion, Quaternion.AngleAxis(-360f / rotationCount * r, axis) * pTorque * Q, ctrls[i].GetForce(inflow + partMotion, conditions.mach, pitchInput, conditions.pseudoReDragMult, out _, origin) * localVelFactor * Q, i);
                    }
                }

                rTorque    *= Q;
                rAeroForce *= Q;

                for (int i = partCollections.Count - 1; i >= 0; i--)
                {
                    //Vector3 partMotion = Vector3.Cross(axis, (parts[i].transformPosition - origin)) * angularVelocity;
                    Vector3 partMotion = Vector3.Cross((parts[i].transformPosition - origin), axis) * angularVelocity;
                    rAeroForce += partCollections[i].GetAeroForce(rotatedInflow + partMotion, conditions, pitchInput, out Vector3 pTorque, origin);
                    rTorque    += pTorque;
                }

                // Rotate torque backwards
                rTorque = Quaternion.AngleAxis(-360f / rotationCount * r, axis) * rTorque;

                torque    += rTorque;
                aeroForce += rAeroForce;
            }

            aeroForce /= rotationCount;
            torque    /= rotationCount;
            if (conditions.altitude <= 50 && conditions.speed >= 15 && conditions.speed < 25 && Vector3.Angle(inflow, Vector3.forward) < 10)
            {
                Debug.LogFormat("Aeroforce {0}\tTorque {1}", aeroForce, torque);
            }
            torque += Vector3.Cross(aeroForce, origin - torquePoint);

            return(aeroForce);
        }
Exemplo n.º 9
0
 public virtual void GetAeroCombined(Vector3 inflow, AeroPredictor.Conditions conditions, float AoA, float pitchInput, out Vector3 forces, out Vector3 torques, Vector3 torquePoint)
 {
     forces = GetAeroForce(inflow, conditions, AoA, pitchInput, out torques, torquePoint);
 }
Exemplo n.º 10
0
 public virtual Vector3 GetAeroTorque(Vector3 inflow, AeroPredictor.Conditions conditions, float AoA, Vector3 torquePoint, float pitchInput = 0)
 {
     GetAeroForce(inflow, conditions, AoA, pitchInput, out Vector3 torque, torquePoint);
     return(torque);
 }