Beispiel #1
0
    def _barrowmanAeroFunc(self,
                           rocketState,
                           time,
                           environment,
                           precomputedData,
                           CG=Vector(0, 0, 0),
                           finDeflectionAngle=None):
        '''
            Precomputed Data is a named tuple (PreComputedFinAeroData) which contains data/results from the parts of the fin aerodynamics calculation
                that are common to all fins in a FinSet (drag calculations mostly). These calculations are performed at the FinSet level.
            Only the parts of the Fin Aero Computation that change from fin to fin (normal force mostly, since different fins can have different angles of attack) are computed here
        '''
        Mach = AeroParameters.getMachNumber(rocketState, environment)
        dynamicPressure = AeroParameters.getDynamicPressure(
            rocketState, environment)

        if finDeflectionAngle == None:
            finDeflectionAngle = self.finAngle  # Adjusted by parent finset during each timestep, when the FinSet is controlled

        # Unpack precomputedData
        airVelRelativeToFin, CPXPos, totalDragCoefficient = precomputedData

        #### Compute normal force-----------------------------------------------------------------------------------------------------------------

        # Find fin normal vector after fin deflection
        finDeflectionRotation = Quaternion(
            axisOfRotation=self.spanwiseDirection,
            angle=radians(finDeflectionAngle))
        finNormal = finDeflectionRotation.rotate(self.undeflectedFinNormal)
        # Get the tangential velocity component vector, per unit radial distance from the rocket centerline
        rollAngVel = AngularVelocity(0, 0, rocketState.angularVelocity.Z)
        unitSpanTangentialAirVelocity = rollAngVel.crossProduct(
            self.spanwiseDirection) * (-1)

        def subsonicNormalForce(Mach):  # Subsonic linear method
            tempBeta = AeroParameters.getBeta(Mach)
            CnAlpha = getFinCnAlpha_Subsonic_Barrowman(self.span,
                                                       self.planformArea,
                                                       tempBeta,
                                                       self.midChordSweep)
            return getSubsonicFinNormalForce(airVelRelativeToFin,
                                             unitSpanTangentialAirVelocity,
                                             finNormal, self.spanwiseDirection,
                                             self.CPSpanWisePosition.length(),
                                             CnAlpha, self)

        def supersonicNormalForce(Mach):  # Supersonic Busemann method
            gamma = AeroFunctions.getGamma()
            tempBeta = AeroParameters.getBeta(Mach)
            K1, K2, K3, Kstar = getBusemannCoefficients(Mach, tempBeta, gamma)

            # Mach Cone coords
            machAngle = asin(1 / Mach)
            machCone_negZPerRadius = 1 / tan(machAngle)
            machConeEdgeZPos = []
            outerRadius = self.spanSliceRadii[-1]
            for i in range(len(self.spanSliceRadii)):
                machConeAtCurrentRadius = (
                    outerRadius - self.spanSliceRadii[i]
                ) * machCone_negZPerRadius + self.tipPosition
                machConeEdgeZPos.append(machConeAtCurrentRadius)

            return getSupersonicFinNormalForce(
                airVelRelativeToFin, unitSpanTangentialAirVelocity, finNormal,
                machConeEdgeZPos, self.spanwiseDirection,
                self.CPSpanWisePosition.length(), K1, K2, K3, Kstar, self)

        if Mach <= 0.8:
            normalForceMagnitude, finMoment = subsonicNormalForce(Mach)

        elif Mach < 1.4:
            # Interpolate in transonic region
            # TODO: Do this with less function evaluations? Perhaps precompute AOA and Mach combinations and simply interpolate? Lazy precompute? Cython?
            x1, x2 = 0.8, 1.4  # Start, end pts of interpolated region
            dx = 0.001

            # Find normal force and derivative at start of interpolation interval
            f_x1, m_x1 = subsonicNormalForce(x1)
            f_x12, m_x12 = subsonicNormalForce(x1 + dx)

            # Find normal force and derivative at end of interpolation interval
            f_x2, m_x2 = supersonicNormalForce(x2)
            f_x22, m_x22 = supersonicNormalForce(x2 + dx)

            normalForceMagnitude = Interpolation.cubicInterp(
                Mach, x1, x2, f_x1, f_x2, f_x12, f_x22, dx)
            finMoment = Interpolation.cubicInterp(Mach, x1, x2, m_x1, m_x2,
                                                  m_x12, m_x22, dx)
        else:
            normalForceMagnitude, finMoment = supersonicNormalForce(Mach)

        # Complete redimensionalization of normal force coefficients by multiplying by dynamic pressure
        # Direct the normal force along the fin's normal direction
        normalForce = normalForceMagnitude * dynamicPressure * finNormal
        finMoment *= dynamicPressure

        #### Get axial force-----------------------------------------------------------------------------------------------------------------------

        avgAOA = getFinSliceAngleOfAttack(
            self.spanSliceRadii[round(len(self.spanSliceAreas) / 2)],
            airVelRelativeToFin, unitSpanTangentialAirVelocity, finNormal,
            self.spanwiseDirection,
            self.stallAngle)  # Approximate average fin AOA
        totalAxialForceCoefficient = AeroFunctions.getDragToAxialForceFactor(
            avgAOA) * totalDragCoefficient
        axialForceMagnitude = totalAxialForceCoefficient * self.rocket.Aref * dynamicPressure
        axialForceDirection = self.spanwiseDirection.crossProduct(finNormal)
        axialForce = axialForceDirection * axialForceMagnitude

        #### Get CP Location ----------------------------------------------------------------------------------------------------------------------

        CPChordWisePosition = self.position - Vector(
            0, 0, CPXPos
        )  # Ignoring the change in CP position due to fin deflection for now
        globalCP = self.CPSpanWisePosition + CPChordWisePosition

        #### Assemble total force moment system objects--------------------------------------------------------------------------------------------

        totalForce = normalForce + axialForce
        return ForceMomentSystem(totalForce,
                                 globalCP,
                                 moment=Vector(0, 0, finMoment)), globalCP
Beispiel #2
0
 def getVelocity(self, time):
     pos = self.getPosition(time)
     angVel = AngularVelocity(0, 0, self.earthAngVel)
     return angVel.crossProduct(pos)