Exemplo n.º 1
0
        /** Calculates and returns the thrust produced by this propeller.
         *  Given the excess power available from the engine (in watts), the thrust is
         *  calculated, as well as the current RPM. The RPM is calculated by integrating
         *  the torque provided by the engine over what the propeller "absorbs"
         *  (essentially the "drag" of the propeller).
         *  @param PowerAvailable this is the excess power provided by the engine to
         *  accelerate the prop. It could be negative, dictating that the propeller
         *  would be slowed.
         *  @return the thrust in newtons */
        public double Calculate(double EnginePower, double rho, double Vel, double speedOfSound, double deltaTime)
        {
            deltaT = deltaTime;
            double omega, PowerAvailable;
            double RPS     = RPM * (1d / 60d);
            double machInv = 1d / speedOfSound;
            // Calculate helical tip Mach
            double Area = 0.25d * Diameter * Diameter * Math.PI;
            double Vtip = RPS * Diameter * Math.PI;

            HelicalTipMach = Math.Sqrt(Vtip * Vtip + Vel * Vel) * machInv;

            PowerAvailable = EnginePower - GetPowerRequired(rho, Vel);

            if (RPS > 0d)
            {
                J = Vel / (Diameter * RPS); // Calculate J normally
            }
            else
            {
                J = Vel / Diameter;
            }

            if (MaxPitch == MinPitch)     // Fixed pitch prop
            {
                ThrustCoeff = cThrustFP.Evaluate((float)J);
            }
            else                       // Variable pitch prop
            {
                ThrustCoeff = cThrust.GetValue(J, Pitch);
            }

            // Apply optional scaling factor to Ct (default value = 1)
            ThrustCoeff *= CtFactor * CtTweak;

            // Apply optional Mach effects from CT_MACH table
            double CtMachFactor = 1;

            if (CtMach != null)
            {
                CtMachFactor = Math.Pow(CtMach.Evaluate((float)HelicalTipMach), MachPowTweak);
                ThrustCoeff *= CtMachFactor;
            }

            Thrust = ThrustCoeff * RPS * RPS * D4 * rho;

            //Debug.Log("CT = " + ThrustCoeff + " CtFactor = " + CtFactor + "\n\rCtTweak = " + CtTweak + " CtMachFactor = " + CtMachFactor + "\n\rJ = " + J + "\n\rHelicalTipMach = " + HelicalTipMach + " SoundSpeed = " + speedOfSound);

            /*// Induced velocity in the propeller disk area. This formula is obtained
             * // from momentum theory - see B. W. McCormick, "Aerodynamics, Aeronautics,
             * // and Flight Mechanics" 1st edition, eqn. 6.15 (propeller analysis chapter).
             * // Since Thrust and Vel can both be negative we need to adjust this formula
             * // To handle sign (direction) separately from magnitude.
             * double Vel2sum = Vel*Math.Abs(Vel) + 2.0*Thrust/(rho*Area);
             *
             * if( Vel2sum > 0.0)
             *  Vinduced = 0.5 * (-Vel + Math.Sqrt(Vel2sum));
             * else
             *  Vinduced = 0.5 * (-Vel - Math.Sqrt(-Vel2sum));
             *
             * // We need to drop the case where the downstream velocity is opposite in
             * // direction to the aircraft velocity. For example, in such a case, the
             * // direction of the airflow on the tail would be opposite to the airflow on
             * // the wing tips. When such complicated airflows occur, the momentum theory
             * // breaks down and the formulas above are no longer applicable
             * // (see H. Glauert, "The Elements of Airfoil and Airscrew Theory",
             * // 2nd edition, ?6.3, pp. 219-221)
             *
             * if ((Vel+2.0*Vinduced)*Vel < 0.0)
             * // The momentum theory is no longer applicable so let's assume the induced
             * // saturates to -0.5*Vel so that the total velocity Vel+2*Vinduced equals 0.
             *  Vinduced = -0.5*Vel;
             *
             * // P-factor is simulated by a shift of the acting location of the thrust.
             * // The shift is a multiple of the angle between the propeller shaft axis
             * // and the relative wind that goes through the propeller disk.
             * if (P_Factor > 0.0001) {
             * double tangentialVel = localAeroVel.Magnitude(eV, eW);
             *
             * if (tangentialVel > 0.0001) {
             *  double angle = atan2(tangentialVel, localAeroVel(eU));
             *  double factor = Sense * P_Factor * angle / tangentialVel;
             *  SetActingLocationY( GetLocationY() + factor * localAeroVel(eW));
             *  SetActingLocationZ( GetLocationZ() + factor * localAeroVel(eV));
             * }
             * }*/

            omega = RPS * 2d * Math.PI;

            // The Ixx value and rotation speed given below are for rotation about the
            // natural axis of the engine. The transform takes place in the base class
            // FGForce::GetBodyForces() function.

            /*vH(eX) = Ixx*omega*Sense;
             * vH(eY) = 0.0;
             * vH(eZ) = 0.0;*/

            if (omega > 0d)
            {
                ExcessTorque = PowerAvailable / omega;
            }
            else
            {
                ExcessTorque = PowerAvailable;
            }

            RPM = (RPS + (ExcessTorque / (Ixx * 2.0 * Math.PI) * deltaT)) * 60d;

            if (RPM < 0d)
            {
                RPM = 0d;           // Engine won't turn backwards
            }
            // Transform Torque and momentum first, as PQR is used in this
            // equation and cannot be transformed itself.
            //vMn = in.PQR*(Transform()*vH) + Transform()*vTorque;

            // hacky mach drag -- should not be needed with nuFAR

            /*if (MachDrag != null)
             * {
             *  double machDrag = MachDrag.Evaluate((float)(Vel * machInv));
             *  machDrag *= machDrag * D4 * RPS * RPS * rho * 0.00004d;
             *  Thrust -= machDrag;
             * }*/

            //MonoBehaviour.print("Prop running: thrust " + Thrust + ", Ct " + ThrustCoeff + ", RPM " + RPM + ", PAvail " + PowerAvailable + ", J " + J + ", delta RPM " + (RPM - RPS * 60d));

            return(Thrust);
        }
Exemplo n.º 2
0
        /*public Vector3 GetPFactor()
         * {
         *  double px = 0.0, py, pz;
         *
         *  py = Thrust * Sense * (ActingLocation.y - GetLocationY()) / 12.0;
         *  pz = Thrust * Sense * (ActingLocation.z - GetLocationZ()) / 12.0;
         *
         *  return Vector3(px, py, pz);
         * }*/

        /** Retrieves the power required (or "absorbed") by the propeller -
         *  i.e. the power required to keep spinning the propeller at the current
         *  velocity, air density,  and rotational rate. */
        public double GetPowerRequired(double rho, double Vel)
        {
            double cPReq, J;
            double RPS = RPM * (1d / 60d);

            if (RPS != 0d)
            {
                J = Vel / (Diameter * RPS);
            }
            else
            {
                J = Vel / Diameter;
            }

            if (MaxPitch == MinPitch)   // Fixed pitch prop
            {
                cPReq = cPowerFP.Evaluate((float)J);
            }
            else
            {                           // Variable pitch prop
                if (ConstantSpeed != 0) // Constant Speed Mode
                {
                    // do normal calculation when propeller is neither feathered nor reversed
                    // Note:  This method of feathering and reversing was added to support the
                    //        turboprop model.  It's left here for backward compatablity, but
                    //        now feathering and reversing should be done in Manual Pitch Mode.
                    if (!Feathered)
                    {
                        if (!Reversed)
                        {
                            double rpmReq = MinRPM + (MaxRPM - MinRPM) * Advance;
                            double dRPM   = rpmReq - RPM;
                            // The pitch of a variable propeller cannot be changed when the RPMs are
                            // too low - the oil pump does not work.
                            if (RPM > 200d)
                            {
                                Pitch -= dRPM * deltaT;
                            }
                            if (Pitch < MinPitch)
                            {
                                Pitch = MinPitch;
                            }
                            else if (Pitch > MaxPitch)
                            {
                                Pitch = MaxPitch;
                            }
                        }
                        else // Reversed propeller
                        {
                            // when reversed calculate propeller pitch depending on throttle lever position
                            // (beta range for taxing full reverse for braking)
                            double PitchReq = MinPitch - (MinPitch - ReversePitch) * Reverse_coef;
                            // The pitch of a variable propeller cannot be changed when the RPMs are
                            // too low - the oil pump does not work.
                            if (RPM > 200d)
                            {
                                Pitch += (PitchReq - Pitch) * (1d / 200d);
                            }
                            if (RPM > MaxRPM)
                            {
                                Pitch += (MaxRPM - RPM) / 50;
                                if (Pitch < ReversePitch)
                                {
                                    Pitch = ReversePitch;
                                }
                                else if (Pitch > MaxPitch)
                                {
                                    Pitch = MaxPitch;
                                }
                            }
                        }
                    }
                    else  // Feathered propeller
                    {
                        // ToDo: Make feathered and reverse settings done via FGKinemat
                        Pitch += (MaxPitch - Pitch) * (1d / 300d); // just a guess (about 5 sec to fully feathered)
                        if (Pitch > MaxPitch)
                        {
                            Pitch = MaxPitch;
                        }
                    }
                }
                else // Manual Pitch Mode, pitch is controlled externally
                {
                }
                cPReq = cPower.GetValue(J, Pitch);
            }

            // Apply optional scaling factor to Cp (default value = 1)
            cPReq *= CpFactor * CpTweak;

            // Apply optional Mach effects from CP_MACH table
            if (CpMach != null)
            {
                cPReq *= Math.Pow(CpMach.Evaluate((float)HelicalTipMach), MachPowTweak);
            }

            double local_RPS = RPS < 0.01d ? 0.01d : RPS;

            PowerRequired = cPReq * local_RPS * local_RPS * local_RPS * D5 * rho;
            vTorque.x     = (-Sense * PowerRequired / (local_RPS * 2.0 * Math.PI));

            //Debug.Log("Cp = " + cPReq);

            return(PowerRequired);
        }