Ejemplo n.º 1
0
def forceFromCoefficients(rocketState, environment, Cd, Cl, CMx, CMy, CMz,
                          CPLocation, refArea, refLength):
    ''' Initialize ForceMomentSystem from all aerodynamic coefficients '''
    q = AeroParameters.getDynamicPressure(rocketState, environment)
    if q == 0.0:
        # No force without dynamic pressure
        return ForceMomentSystem(Vector(0, 0, 0))
    nonDimConstant = q * refArea

    #### Drag ####
    localFrameAirVel = AeroParameters.getLocalFrameAirVel(
        rocketState, environment)
    dragDirection = localFrameAirVel.normalize()
    dragForce = dragDirection * Cd

    #### Lift ####
    # Find the lift force direction
    # Lift force will be in the same plane as the normalForceDirection & rocketFrameAirVel vectors
    # But, the lift force will be perpendicular to rocketFraeAirVel, whereas the normalForceDirection might form an acute angle with it
    # Rotate the normal force direction vector until it's perpendicular with rocketFrameAirVel
    normalForceDir = AeroParameters.getNormalAeroForceDirection(
        rocketState, environment)
    rotAxis = localFrameAirVel.crossProduct(normalForceDir)
    angle = math.pi / 2 - localFrameAirVel.angle(normalForceDir)
    rotatorQuat = Quaternion(rotAxis, angle)
    liftDirection = rotatorQuat.rotate(normalForceDir)
    liftForce = liftDirection * Cl

    # Combine and redimensionalize
    totalForce = (dragForce + liftForce) * nonDimConstant

    #### Moments ####
    moments = Vector(CMx, CMy, CMz) * nonDimConstant * refLength

    return ForceMomentSystem(totalForce, CPLocation, moments)
Ejemplo n.º 2
0
    def getAppliedForce(self, state, time, environment, rocketCG):
        airspeed = max(
            AeroParameters.getLocalFrameAirVel(state, environment).length(),
            0.0000001)
        redimConst = self.Lref / (2 * airspeed)
        # Calculate moment coefficients from damping coefficients
        localFrameAngularVelocity = Vector(*state.angularVelocity)
        zMomentCoeff = self.zDampingCoeffs * localFrameAngularVelocity * redimConst
        yMomentCoeff = self.yDampingCoeffs * localFrameAngularVelocity * redimConst
        xMomentCoeff = self.xDampingCoeffs * localFrameAngularVelocity * redimConst
        momentCoeffs = [xMomentCoeff, yMomentCoeff, zMomentCoeff]

        return AeroFunctions.forceFromCoefficients(state, environment, 0, 0,
                                                   *momentCoeffs,
                                                   self.position, self.Aref,
                                                   self.Lref)
Ejemplo n.º 3
0
    def getFinSliceArgs(self, vel, orientation, angVel, fin1, finSlicePosition=0):
        rocketState = RigidBodyState(Vector(0,0,0), vel, orientation, angVel)
        CG = self.rocket2.getCG(0, rocketState)

        rocketVelocity = AeroParameters.getLocalFrameAirVel(rocketState, self.currentConditions)

        # Add fin velocities due to motion of the rocket
        velocityDueToRocketPitchYaw = rocketState.angularVelocity.crossProduct(fin1.position - CG)*(-1) #The negative puts it in the wind frame

        #We need to find the angle between the rocket velocity vector and the plane described by the fin deflection angle 
        #and the shaft normal
        finNormal = fin1.spanwiseDirection.crossProduct(Vector(0, 0, 1))
        finDeflectionAngle = fin1.finAngle # Adjusted by parent finset during each timestep
        if(finDeflectionAngle != 0):
            rotation = Quaternion(axisOfRotation = fin1.spanwiseDirection, angle=math.radians(finDeflectionAngle))
            finNormal = rotation.rotate(finNormal)

        finUnitSpanTangentialVelocity = rocketState.angularVelocity.crossProduct(fin1.spanwiseDirection)*(-1)
        finVelWithoutRoll = rocketVelocity + velocityDueToRocketPitchYaw

        return finSlicePosition, finVelWithoutRoll, finUnitSpanTangentialVelocity, finNormal, fin1.spanwiseDirection, fin1.stallAngle
Ejemplo n.º 4
0
def getCylindricalSkinFrictionDragCoefficientAndRollDampingMoment(
        state,
        environment,
        length,
        Mach,
        surfaceRoughness,
        wettedArea,
        Aref,
        finenessRatio,
        assumeFullyTurbulent=True):
    ''' Equations from Barrowman section 4.0, Niskanen section 3.4 '''
    # Get a compressiblity-corrected flat plate skin friction drag coefficient, normalized by wetted area
    skinFrictionDragCoefficient = getSkinFrictionCoefficient(
        state, environment, length, Mach, surfaceRoughness,
        assumeFullyTurbulent)
    # Account for the fact that the rocket is cylindrical, and not a flat plate (Barrowman Eqn 4-16)
    skinFrictionDragCoefficient *= (1 + (0.5 / finenessRatio))
    # Rebase coefficient to the reference area
    skinFrictionDragCoefficient *= (wettedArea / Aref)

    # Approximate avg radius as the radius of a cylinder which would have the same wetted area + length
    avgRadius = (wettedArea / length) / (2 * math.pi)
    rollingSurfaceVel = avgRadius * state.angularVelocity.Z
    # Assume velocities are perpendicular
    airVel = AeroParameters.getLocalFrameAirVel(state, environment).length()
    # Use total velocity to redimensionalize coefficient
    totalVelSquared = airVel**2 + rollingSurfaceVel**2

    if totalVelSquared == 0:
        return skinFrictionDragCoefficient, Vector(0, 0, 0)
    else:
        totalSurfaceForce = skinFrictionDragCoefficient * 0.5 * totalVelSquared * environment.Density * Aref
        # Calculate roll damping component of total friction force using similar triangles
        rollDampingForce = totalSurfaceForce * (rollingSurfaceVel /
                                                math.sqrt(totalVelSquared))
        # Calculate resulting moment
        rollDampingMoment = Vector(0, 0, -rollDampingForce * avgRadius)

    return skinFrictionDragCoefficient, rollDampingMoment
Ejemplo n.º 5
0
    def _getPreComputedFinAeroData(self, rocketState, environment, CG):
        #General Info ---------------------------------------------------------------------------------------------------------------------
        Aref = self.rocket.Aref
        Mach = AeroParameters.getMachNumber(rocketState, environment)
        dynamicPressure = AeroParameters.getDynamicPressure(
            rocketState, environment)

        # Skin Friction Drag -------------------------------------------------------------------------------------------------------------

        skinFrictionCoefficient = AeroFunctions.getSkinFrictionCoefficient(
            rocketState, environment, self.MACLength, Mach,
            self.surfaceRoughness, self.rocket.fullyTurbulentBL)
        # Adjust to the rocket reference area (skinFrictionCoefficient is based on wetted area)
        skinFrictionDragCoefficient = skinFrictionCoefficient * (
            self.wettedArea / Aref)
        # Correct for additional surface area due to fin thickness - Niskanen Eqn 3.85
        skinFrictionDragCoefficient *= (1 +
                                        2 * self.thickness / self.MACLength)

        # Pressure Drag ------------------------------------------------------------------------------------------------------------------

        # Leading edge drag coefficient
        if self.leadingEdgeShape == "Round":
            leadingEdgeCd = AeroFunctions.getCylinderCrossFlowCd_ZeroBaseDrag(
                Mach)
            LEthickness = self.leadingEdgeRadius * 2
        elif self.leadingEdgeShape == "Blunt":
            leadingEdgeCd = AeroFunctions.getBluntBodyCd_ZeroBaseDrag(Mach)
            LEthickness = self.leadingEdgeThickness

        # Adjust for leading edge angle and convert reference area to rocket reference area - Barrowman Eqn 4-22
        leadingEdgeCdAdjustmentFactor = LEthickness * self.span * cos(
            self.sweepAngle)**2 / Aref
        leadingEdgeCd *= leadingEdgeCdAdjustmentFactor

        # Trailing edge drag coefficient - simpler method from Niskanen section 3.4.4. Corrected to use only the trailing edge area, not the full fin frontal area
        # more intricate method available in Barrowman
        baseDragCd = AeroFunctions.getBaseDragCoefficient(Mach)
        if self.trailingEdgeShape == "Tapered":
            TEthickness = 0  # Zero base drag
        elif self.trailingEdgeShape == "Round":
            TEthickness = self.trailingEdgeRadius  # 0.5 base drag
        elif self.trailingEdgeShape == "Blunt":
            TEthickness = self.trailingEdgeThickness  # Full base drag

        # Convert to standard rocket reference Area
        trailingEdgeCd = baseDragCd * self.span * TEthickness / Aref

        # Thickness / Wave Drag
        #TODO: This section doesn't seem to be working quite right
        if Mach <= 1:
            # Thickness drag, subsonic
            thicknessDrag = 4*skinFrictionCoefficient*((self.thickness/self.rootChord)*cos(self.midChordSweep) + \
                (30 * (self.thickness/self.rootChord)**4 * cos(self.midChordSweep)**2) /  \
                    (self.subsonicFinThicknessK - Mach**2 * cos(self.midChordSweep)**2)**(3/2))
        else:
            # Supersonic wave drag
            # Using simplistic method from Hoerner - assumes diamond profile (pg 17-12, Eqn 29)
            # TODO: Implement method from Barrowman's FIN program
            thicknessDrag = 2.3 * self.aspectRatio * (self.thickness /
                                                      self.MACLength)**2

        thicknessDrag *= self.planformArea / Aref

        pressureDragCoefficient = leadingEdgeCd + trailingEdgeCd + thicknessDrag

        # Total Drag --------------------------------------------------------------------------------------------------------------------

        totalDragCoefficient = pressureDragCoefficient + skinFrictionDragCoefficient

        localFrameRocketVelocity = AeroParameters.getLocalFrameAirVel(
            rocketState, environment)
        axialPositionRelCG = self.position - CG
        finVelocityDueToRocketPitchYaw = rocketState.angularVelocity.crossProduct(
            axialPositionRelCG)
        airVelRelativeToFin = localFrameRocketVelocity - finVelocityDueToRocketPitchYaw  # The negative puts it in the wind frame
        CPXPos = self._getCPXPos(Mach)

        #### Transfer info to fins ####
        return PreComputedFinAeroData(airVelRelativeToFin, CPXPos,
                                      totalDragCoefficient)