示例#1
0
    def __call__(self, conditions):
        """ process vehicle to setup geometry, condititon and configuration
            
            Inputs:
                conditions - DataDict() of aerodynamic conditions
                results - DataDict() of 
                
            Outputs:

                
            Assumptions:

                
        """

        # unpack
        configuration = self.configuration
        geometry = self.geometry
        stability_model = self.stability_model

        q = conditions.freestream.dynamic_pressure
        Sref = geometry.reference_area
        mach = conditions.freestream.mach_number
        velocity = conditions.freestream.velocity
        density = conditions.freestream.density
        Span = geometry.wings['main_wing'].spans.projected
        mac = geometry.wings['main_wing'].chords.mean_aerodynamic
        aero = conditions.aerodynamics

        # set up data structures
        static_stability = Data()
        dynamic_stability = Data()

        # Calculate CL_alpha
        if not conditions.has_key('lift_curve_slope'):
            conditions.lift_curve_slope = datcom(geometry.wings['main_wing'],
                                                 mach)

        # Calculate change in downwash with respect to change in angle of attack
        for surf in geometry.wings:
            sref = surf.areas.reference
            span = (surf.aspect_ratio * sref)**0.5
            surf.CL_alpha = datcom(surf, mach)
            surf.ep_alpha = Supporting_Functions.ep_alpha(
                surf.CL_alpha, sref, span)

        # Static Stability Methods
        static_stability.cm_alpha = taw_cmalpha(geometry, mach, conditions,
                                                configuration)
        static_stability.cn_beta = taw_cnbeta(geometry, conditions,
                                              configuration)

        # Dynamic Stability
        if np.count_nonzero(
                configuration.mass_properties.moments_of_inertia.tensor) > 0:
            # Dynamic Stability Approximation Methods - valid for non-zero I tensor

            # Derivative of yawing moment with respect to the rate of yaw
            cDw = aero.drag_breakdown.parasite[
                'main_wing'].parasite_drag_coefficient  # Might not be the correct value
            l_v = geometry.wings['vertical_stabilizer'].origin[
                0] + geometry.wings['vertical_stabilizer'].aerodynamic_center[
                    0] - geometry.wings['main_wing'].origin[
                        0] - geometry.wings['main_wing'].aerodynamic_center[0]
            dynamic_stability.cn_r = Supporting_Functions.cn_r(
                cDw, geometry.wings['vertical_stabilizer'].areas.reference,
                Sref, l_v, span,
                geometry.wings['vertical_stabilizer'].dynamic_pressure_ratio,
                geometry.wings['vertical_stabilizer'].CL_alpha)

            # Derivative of rolling moment with respect to roll rate
            dynamic_stability.cl_p = 0  # Need to see if there is a low fidelity way to calculate cl_p

            # Derivative of roll rate with respect to sideslip (dihedral effect)
            dynamic_stability.cl_beta = 0  # Need to see if there is a low fidelity way to calculate cl_beta

            # Derivative of pitching moment with respect to pitch rate
            l_t = geometry.wings['horizontal_stabilizer'].origin[
                0] + geometry.wings['horizontal_stabilizer'].aerodynamic_center[
                    0] - geometry.wings['main_wing'].origin[
                        0] - geometry.wings['main_wing'].aerodynamic_center[
                            0]  #Need to check this is the length of the horizontal tail moment arm
            dynamic_stability.cm_q = Supporting_Functions.cm_q(
                conditions.lift_curve_slope, l_t,
                mac)  # Need to check Cm_i versus Cm_alpha

            # Derivative of pitching rate with respect to d(alpha)/d(t)
            dynamic_stability.cm_alpha_dot = Supporting_Functions.cm_alphadot(
                static_stability.cm_alpha,
                geometry.wings['horizontal_stabilizer'].ep_alpha, l_t,
                mac)  # Need to check Cm_i versus Cm_alpha

            # Derivative of Z-axis force with respect to angle of attack
            dynamic_stability.cz_alpha = Supporting_Functions.cz_alpha(
                aero.drag_coefficient, conditions.lift_curve_slope)

            stability_model.dutch_roll = Approximations.dutch_roll(
                velocity, static_stability.cn_beta, Sref, density, Span,
                configuration.mass_properties.moments_of_inertia.tensor[2][2],
                dynamic_stability.cn_r)

            if dynamic_stability.cl_p != 0:
                stability_model.roll_tau = Approximations.roll(
                    configuration.mass_properties.momen[2][2], Sref, density,
                    velocity, Span, dynamic_stability.cl_p)
                dynamic_stability.cy_phi = Supporting_Functions.cy_phi(
                    aero.lift_coefficient)
                dynamic_stability.cl_r = Supporting_Functions.cl_r(
                    aero.lift_coefficient)  # Will need to be changed
                stability_model.spiral_tau = Approximations.spiral(
                    conditions.weights.total_mass, velocity, density, Sref,
                    dynamic_stability.cl_p, static_stability.cn_beta,
                    dynamic_stability.cy_phi, dynamic_stability.cl_beta,
                    dynamic_stability.cn_r, dynamic_stability.cl_r)
            stability_model.short_period = Approximations.short_period(
                velocity, density, Sref, mac, dynamic_stability.cm_q,
                dynamic_stability.cz_alpha, conditions.weights.total_mass,
                static_stability.cm_alpha,
                configuration.mass_properties.moments_of_inertia.tensor[1][1],
                dynamic_stability.cm_alpha_dot)
            stability_model.phugoid = Approximations.phugoid(
                conditions.freestream.gravity, conditions.freestream.velocity,
                aero.drag_coefficient, aero.lift_coefficient)

            # Dynamic Stability Full Linearized Methods
            if aero.has_key(
                    'cy_beta'
            ) and dynamic_stability.cl_p != 0 and dynamic_stability.cl_beta != 0:
                theta = conditions.frames.wind.body_rotations[:, 1]
                dynamic_stability.cy_beta = aero.cy_beta
                dynamic_stability.cl_psi = Supporting_Functions.cy_psi(
                    aero.lift_coefficient, theta)
                dynamic_stability.cL_u = 0
                dynamic_stability.cz_u = Supporting_Functions.cz_u(
                    aero.lift_coefficient, velocity, dynamic_stability.cL_u)
                dynamic_stability.cz_alpha_dot = Supporting_Functions.cz_alphadot(
                    static_stability.cm_alpha,
                    geometry.wings['horizontal_stabilizer'].ep_alpha)
                dynamic_stability.cz_q = Supporting_Functions.cz_q(
                    static_stability.cm_alpha)
                dynamic_stability.cx_u = Supporting_Functions.cx_u(
                    aero.drag_coefficient)
                dynamic_stability.cx_alpha = Supporting_Functions.cx_alpha(
                    aero.lift_coefficient, conditions.lift_curve_slope)

                lateral_directional = Full_Linearized_Equations.lateral_directional(
                    velocity, static_stability.cn_beta, Sref, density, Span,
                    configuration.mass_properties.moments_of_inertia.tensor[2]
                    [2], dynamic_stability.cn_r,
                    configuration.mass_properties.Moments_Of_Inertia.tensor[0]
                    [0], dynamic_stability.cl_p,
                    configuration.mass_properties.moments_of_inertia.tensor[0]
                    [2], dynamic_stability.cl_r, dynamic_stability.cl_beta,
                    dynamic_stability.cn_p, dynamic_stability.cy_phi,
                    dynamic_stability.cy_psi, dynamic_stability.cy_beta,
                    conditions.weights.total_mass)
                longitudinal = Full_Linearized_Equations.longitudinal(
                    velocity, density, Sref, mac, dynamic_stability.cm_q,
                    dynamic_stability.cz_alpha, conditions.weights.total_mass,
                    static_stability.cm_alpha,
                    configuration.mass_properties.moments_of_inertia.tensor[1]
                    [1], dynamic_stability.cm_alpha_dot,
                    dynamic_stability.cz_u, dynamic_stability.cz_alpha_dot,
                    dynamic_stability.cz_q, -aero.lift_coefficient, theta,
                    dynamic_stability.cx_u, dynamic_stability.cx_alpha)
                stability_model.dutch_roll.natural_frequency = lateral_directional.dutch_natural_frequency
                stability_model.dutch_roll.damping_ratio = lateral_directional.dutch_damping_ratio
                stability_model.spiral_tau = lateral_directional.spiral_tau
                stability_model.roll_tau = lateral_directional.roll_tau
                stability_model.short_period.natural_frequency = longitudinal.short_natural_frequency
                stability_model.short_period.damping_ratio = longitudinal.short_damping_ratio
                stability_model.phugoid.natural_frequency = longitudinal.phugoid_natural_frequency
                stability_model.phugoid.damping_ratio = longitudinal.phugoid_damping_ratio

        # pack results
        results = Data()
        results.static = static_stability
        results.dynamic = dynamic_stability

        return results
示例#2
0
    def __call__(self,conditions):
            """ process vehicle to setup geometry, condititon and configuration
                
                Inputs:
                    conditions - DataDict() of aerodynamic conditions
                    results - DataDict() of 
                    
                Outputs:

                    
                Assumptions:

                    
            """
            
            # unpack
            configuration = self.configuration
            geometry      = self.geometry
            q             = conditions.freestream.dynamic_pressure
            Sref          = geometry.reference_area    
            mach          = conditions.freestream.mach_number
            velocity      = conditions.freestream.velocity
            density       = conditions.freestream.density
            Span          = geometry.Wings['Main Wing'].span
            mac           = geometry.Wings['Main Wing'].chord_mac
            aero          = conditions.aerodynamics
            
            # Calculate CL_alpha 
            if not conditions.has_key('lift_curve_slope'):
                conditions.lift_curve_slope = (datcom(geometry.Wings['Main Wing'],mach))
            
            # Calculate change in downwash with respect to change in angle of attack
            for surf in geometry.Wings:
                e = surf.e
                sref = surf.sref
                span = (surf.ar * sref ) ** 0.5
                surf.CL_alpha = datcom(surf,mach)
                surf.ep_alpha = Supporting_Functions.ep_alpha(surf.CL_alpha, sref, span, e)
            
            # Static Stability Methods
            aero.cm_alpha = taw_cmalpha(geometry,mach,conditions,configuration)
            aero.cn_beta = taw_cnbeta(geometry,conditions,configuration)
            
            if np.count_nonzero(configuration.mass_props.I_cg) > 0:         
                # Dynamic Stability Approximation Methods
                if not aero.has_key('cn_r'):  
                    cDw = aero.drag_breakdown.parasite['Main Wing'].parasite_drag_coefficient # Might not be the correct value
                    l_v = geometry.Wings['Vertical Stabilizer'].origin[0] + geometry.Wings['Vertical Stabilizer'].aero_center[0] - geometry.Wings['Main Wing'].origin[0] - geometry.Wings['Main Wing'].aero_center[0]
                    aero.cn_r = Supporting_Functions.cn_r(cDw, geometry.Wings['Vertical Stabilizer'].sref, Sref, l_v, span, geometry.Wings['Vertical Stabilizer'].eta, geometry.Wings['Vertical Stabilizer'].CL_alpha)
                if not aero.has_key('cl_p'):
                    aero.cl_p = 0 # Need to see if there is a low fidelity way to calculate cl_p
                    
                if not aero.has_key('cl_beta'):
                    aero.cl_beta = 0 # Need to see if there is a low fidelity way to calculate cl_beta
                
                l_t = geometry.Wings['Horizontal Stabilizer'].origin[0] + geometry.Wings['Horizontal Stabilizer'].aero_center[0] - geometry.Wings['Main Wing'].origin[0] - geometry.Wings['Main Wing'].aero_center[0] #Need to check this is the length of the horizontal tail moment arm       
                
                if not aero.has_key('cm_q'):
                    aero.cm_q = Supporting_Functions.cm_q(conditions.lift_curve_slope, l_t,mac) # Need to check Cm_i versus Cm_alpha
                
                if not aero.has_key('cm_alpha_dot'):
                    aero.cm_alpha_dot = Supporting_Functions.cm_alphadot(aero.cm_alpha, geometry.Wings['Horizontal Stabilizer'].ep_alpha, l_t, mac) # Need to check Cm_i versus Cm_alpha
                    
                if not aero.has_key('cz_alpha'):
                    aero.cz_alpha = Supporting_Functions.cz_alpha(aero.drag_coefficient,conditions.lift_curve_slope)                   
                
                conditions.dutch_roll = Approximations.dutch_roll(velocity, aero.cn_beta, Sref, density, Span, configuration.mass_props.I_cg[2][2], aero.cn_r)
                
                if aero.cl_p != 0:                 
                    roll_tau = Approximations.roll(configuration.mass_props.I_cg[2][2], Sref, density, velocity, Span, aero.cl_p)
                    if aero.cl_beta != 0:
                        aero.cy_phi = Supporting_Functions.cy_phi(aero.lift_coefficient)
                        aero.cl_r = Supporting_Functions.cl_r( aero.lift_coefficient) # Will need to be changed
                        spiral_tau = Approximations.spiral(conditions.weights.total_mass, velocity, density, Sref, aero.cl_p, aero.cn_beta, aero.cy_phi, aero.cl_beta, aero.cn_r, aero.cl_r)
                conditions.short_period = Approximations.short_period(velocity, density, Sref, mac, aero.cm_q, aero.cz_alpha, conditions.weights.total_mass, aero.cm_alpha, configuration.mass_props.I_cg[1][1], aero.cm_alpha_dot)
                conditions.phugoid = Approximations.phugoid(conditions.freestream.gravity, conditions.freestream.velocity, aero.drag_coefficient, aero.lift_coefficient)
                
                # Dynamic Stability Full Linearized Methods
                if aero.has_key('cy_beta') and aero.cl_p != 0 and aero.cl_beta != 0:
                    if not aero.has_key('cy_psi'):
                        theta = conditions.frames.wind.body_rotations[:,1]
                        aero.cl_psi = Supporting_Functions.cy_psi(aero.lift_coefficient, theta)                     
                    if not aero.has_key('cz_u'):
                        if not aero.has_key('cL_u'):
                            aero.cL_u = 0
                        aero.cz_u = Supporting_Functions.cz_u(aero.lift_coefficient,velocity,aero.cL_u)
                    if not aero.has_key('cz_alpha_dot'):
                        aero.cz_alpha_dot = Supporting_Functions.cz_alphadot(aero.cm_alpha, geometry.Wings['Horizontal Stabilizer'].ep_alpha)
                    if not aero.has_key('cz_q'):
                        aero.cz_q = Supporting_Functions.cz_q(aero.cm_alpha)
                    if not aero.has_key('cx_u'):
                        aero.cx_u = Supporting_Functions.cx_u(aero.drag_coefficient)
                    if not aero.has_key('cx_alpha'):
                        aero.cx_alpha = Supporting_Functions.cx_alpha(aero.lift_coefficient, conditions.lift_curve_slope)
                
                    lateral_directional = Full_Linearized_Equations.lateral_directional(velocity, aero.cn_beta , Sref, density, Span, configuration.mass_props.I_cg[2][2], aero.cn_r, configuration.mass_props.I_cg[0][0], aero.cl_p, configuration.mass_props.I_cg[0][2], aero.cl_r, aero.cl_beta, aero.cn_p, aero.cy_phi, aero.cy_psi, aero.cy_beta, conditions.weights.total_mass)
                    longitudinal = Full_Linearized_Equations.longitudinal(velocity, density, Sref, mac, aero.cm_q, aero.cz_alpha, conditions.weights.total_mass, aero.cm_alpha, configuration.mass_props.I_cg[1][1], aero.cm_alpha_dot, aero.cz_u, aero.cz_alpha_dot, aero.cz_q, -aero.lift_coefficient, theta, aero.cx_u, aero.cx_alpha)
            
            return 
示例#3
0
    def __call__(self, conditions):
        """ Process vehicle to setup geometry, condititon and configuration

        Assumptions:
        None

        Source:
        N/A

        Inputs:
        conditions - DataDict() of aerodynamic conditions
        results    - DataDict() of moment coeffients and stability and body axis derivatives

        Outputs:
        None

        Properties Used:
        self.geometry
        """

        # unpack
        configuration = self.configuration
        geometry = self.geometry

        q = conditions.freestream.dynamic_pressure
        Sref = geometry.reference_area
        mach = conditions.freestream.mach_number
        velocity = conditions.freestream.velocity
        density = conditions.freestream.density
        Span = geometry.wings['main_wing'].spans.projected
        mac = geometry.wings['main_wing'].chords.mean_aerodynamic
        aero = conditions.aerodynamics

        # set up data structures
        stability = Data()
        stability.static = Data()
        stability.dynamic = Data()

        # Calculate CL_alpha
        conditions.lift_curve_slope = datcom(geometry.wings['main_wing'], mach)

        # Calculate change in downwash with respect to change in angle of attack
        for surf in geometry.wings:
            sref = surf.areas.reference
            span = (surf.aspect_ratio * sref)**0.5
            surf.CL_alpha = datcom(surf, mach)
            surf.ep_alpha = Supporting_Functions.ep_alpha(
                surf.CL_alpha, sref, span)

        # Static Stability Methods
        stability.static.Cm_alpha, stability.static.Cm0, stability.static.CM = taw_cmalpha(
            geometry, mach, conditions, configuration)

        if 'vertical_stabilizer' in geometry.wings:
            stability.static.Cn_beta = taw_cnbeta(geometry, conditions,
                                                  configuration)
        else:
            stability.static.Cn_beta = np.zeros_like(mach)

        # calculate the static margin
        stability.static.static_margin = -stability.static.Cm_alpha / conditions.lift_curve_slope

        # Dynamic Stability
        if np.count_nonzero(
                configuration.mass_properties.moments_of_inertia.tensor) > 0:
            # Dynamic Stability Approximation Methods - valid for non-zero I tensor

            # Derivative of yawing moment with respect to the rate of yaw
            cDw = aero.drag_breakdown.parasite[
                'main_wing'].parasite_drag_coefficient  # Might not be the correct value
            l_v = geometry.wings['vertical_stabilizer'].origin[
                0] + geometry.wings['vertical_stabilizer'].aerodynamic_center[
                    0] - geometry.wings['main_wing'].origin[
                        0] - geometry.wings['main_wing'].aerodynamic_center[0]
            stability.static.Cn_r = Supporting_Functions.cn_r(
                cDw, geometry.wings['vertical_stabilizer'].areas.reference,
                Sref, l_v, span,
                geometry.wings['vertical_stabilizer'].dynamic_pressure_ratio,
                geometry.wings['vertical_stabilizer'].CL_alpha)

            # Derivative of rolling moment with respect to roll rate
            stability.static.Cl_p = Supporting_Functions.cl_p(
                conditions.lift_curve_slope, geometry)

            # Derivative of roll rate with respect to sideslip (dihedral effect)
            if 'dihedral' in geometry.wings['main_wing']:
                stability.static.Cl_beta = Supporting_Functions.cl_beta(
                    geometry, stability.static.Cl_p)
            else:
                stability.static.Cl_beta = np.zeros(1)

            stability.static.Cy_beta = 0

            # Derivative of pitching moment with respect to pitch rate
            l_t = geometry.wings['horizontal_stabilizer'].origin[
                0] + geometry.wings['horizontal_stabilizer'].aerodynamic_center[
                    0] - geometry.wings['main_wing'].origin[
                        0] - geometry.wings['main_wing'].aerodynamic_center[
                            0]  #Need to check this is the length of the horizontal tail moment arm
            stability.static.Cm_q = Supporting_Functions.cm_q(
                conditions.lift_curve_slope, l_t,
                mac)  # Need to check Cm_i versus Cm_alpha

            # Derivative of pitching rate with respect to d(alpha)/d(t)
            stability.static.Cm_alpha_dot = Supporting_Functions.cm_alphadot(
                stability.static.Cm_alpha,
                geometry.wings['horizontal_stabilizer'].ep_alpha, l_t,
                mac)  # Need to check Cm_i versus Cm_alpha

            # Derivative of Z-axis force with respect to angle of attack
            stability.static.Cz_alpha = Supporting_Functions.cz_alpha(
                aero.drag_coefficient, conditions.lift_curve_slope)

            dutch_roll = Approximations.dutch_roll(
                velocity, stability.static.Cn_beta, Sref, density, Span,
                configuration.mass_properties.moments_of_inertia.tensor[2][2],
                stability.static.Cn_r)
            stability.dynamic.dutchRollFreqHz = dutch_roll.natural_frequency
            stability.dynamic.dutchRollDamping = dutch_roll.damping_ratio

            if stability.static.Cl_p.all() != 0:
                stability.dynamic.rollSubsistenceTimeConstant = Approximations.roll(
                    configuration.mass_properties.moments_of_inertia.tensor[2]
                    [2], Sref, density, velocity, Span, stability.static.Cl_p)
                stability.static.Cy_phi = Supporting_Functions.cy_phi(
                    aero.lift_coefficient)
                stability.static.Cl_r = Supporting_Functions.cl_r(
                    aero.lift_coefficient)  # Will need to be changed
                stability.dynamic.spiralSubsistenceTimeConstant = Approximations.spiral(conditions.weights.total_mass, velocity, density, Sref, stability.static.Cl_p, stability.static.Cn_beta, stability.static.Cy_phi,\
                                                                            stability.static.Cl_beta, stability.static.Cn_r, stability.static.Cl_r)

            short_period_res                               = Approximations.short_period(velocity, density, Sref, mac, stability.static.Cm_q, stability.static.Cz_alpha, conditions.weights.total_mass, stability.static.Cm_alpha,\
                                                            configuration.mass_properties.moments_of_inertia.tensor[1][1], stability.static.Cm_alpha_dot)
            stability.dynamic.shortPeriodFreqHz = short_period_res.natural_frequency
            stability.dynamic.shortPeriodDamp = short_period_res.damping_ratio

            phugoid_res = Approximations.phugoid(
                conditions.freestream.gravity, conditions.freestream.velocity,
                aero.drag_coefficient, aero.lift_coefficient)
            stability.dynamic.phugoidFreqHz = phugoid_res.natural_frequency
            stability.dynamic.phugoidDamp = phugoid_res.damping_ratio

            # Dynamic Stability Full Linearized Methods
            if stability.static.Cy_beta != 0 and stability.static.Cl_p.all(
            ) != 0 and stability.static.Cl_beta.all() != 0:
                theta = conditions.frames.wind.body_rotations[:, 1]
                stability.static.Cy_psi = Supporting_Functions.cy_psi(
                    aero.lift_coefficient, theta)
                stability.static.CL_u = 0
                stability.static.Cz_u = Supporting_Functions.cz_u(
                    aero.lift_coefficient, velocity, stability.static.cL_u)
                stability.static.Cz_alpha_dot = Supporting_Functions.cz_alphadot(
                    stability.static.Cm_alpha,
                    geometry.wings['horizontal_stabilizer'].ep_alpha)
                stability.static.Cz_q = Supporting_Functions.cz_q(
                    stability.static.Cm_alpha)
                stability.static.Cx_u = Supporting_Functions.cx_u(
                    aero.drag_coefficient)
                stability.static.Cx_alpha = Supporting_Functions.cx_alpha(
                    aero.lift_coefficient, conditions.lift_curve_slope)

                lateral_directional = Full_Linearized_Equations.lateral_directional(velocity, stability.static.cn_beta , Sref, density, Span, configuration.mass_properties.moments_of_inertia.tensor[2][2], stability.static.Cn_r,\
                                    configuration.mass_properties.moments_of_inertia.tensor[0][0], stability.static.Cl_p, configuration.mass_properties.moments_of_inertia.tensor[0][2], stability.static.Cl_r, stability.static.Cl_beta,\
                                    stability.static.Cn_p, stability.static.Cy_phi, stability.static.Cy_psi, stability.static.Cy_beta, conditions.weights.total_mass)
                longitudinal        = Full_Linearized_Equations.longitudinal(velocity, density, Sref, mac, stability.static.Cm_q, stability.static.Cz_alpha, conditions.weights.total_mass, stability.static.Cm_alpha, \
                                    configuration.mass_properties.moments_of_inertia.tensor[1][1], stability.static.Cm_alpha_dot, stability.static.Cz_u, stability.static.Cz_alpha_dot, stability.static.Cz_q, -aero.lift_coefficient,\
                                    theta, stability.static.Cx_u, stability.static.Cx_alpha)
                stability.dynamic.dutchRollFreqHz = lateral_directional.dutch_natural_frequency
                stability.dynamic.dutchRollDamping = lateral_directional.dutch_damping_ratio
                stability.dynamic.spiralSubsistenceTimeConstant = lateral_directional.spiral_tau
                stability.dynamic.rollSubsistenceTimeConstant = lateral_directional.roll_tau
                stability.dynamic.shortPeriodFreqHz = longitudinal.short_natural_frequency
                stability.dynamic.shortPeriodDamp = longitudinal.short_damping_ratio
                stability.dynamic.phugoidFreqHz = longitudinal.phugoid_natural_frequency
                stability.dynamic.phugoidDamp = longitudinal.phugoid_damping_ratio

        # pack results
        results = Data()
        results = stability

        return results
    def __call__(self,conditions):
        """ process vehicle to setup geometry, condititon and configuration
            
            Inputs:
                conditions - DataDict() of aerodynamic conditions
                results - DataDict() of 
                
            Outputs:

                
            Assumptions:

                
        """
        
        # unpack
        configuration   = self.configuration
        geometry        = self.geometry
        stability_model = self.stability_model
        
        q             = conditions.freestream.dynamic_pressure
        Sref          = geometry.reference_area    
        mach          = conditions.freestream.mach_number
        velocity      = conditions.freestream.velocity
        density       = conditions.freestream.density
        Span          = geometry.wings['main_wing'].spans.projected
        mac           = geometry.wings['main_wing'].chords.mean_aerodynamic
        aero          = conditions.aerodynamics
        
        # set up data structures
        static_stability = Data()
        dynamic_stability = Data()
        
        # Calculate CL_alpha 
        if not conditions.has_key('lift_curve_slope'):
            conditions.lift_curve_slope = datcom(geometry.wings['main_wing'],mach)
        
        # Calculate change in downwash with respect to change in angle of attack
        for surf in geometry.wings:
            sref = surf.areas.reference
            span = (surf.aspect_ratio * sref ) ** 0.5
            surf.CL_alpha = datcom(surf,mach)
            surf.ep_alpha = Supporting_Functions.ep_alpha(surf.CL_alpha, sref, span)
        
        # Static Stability Methods
        static_stability.cm_alpha = taw_cmalpha(geometry,mach,conditions,configuration)
        static_stability.cn_beta = taw_cnbeta(geometry,conditions,configuration)
        
        # Dynamic Stability
        if np.count_nonzero(configuration.mass_properties.moments_of_inertia.tensor) > 0:    
            # Dynamic Stability Approximation Methods - valid for non-zero I tensor
            
            # Derivative of yawing moment with respect to the rate of yaw
            cDw = aero.drag_breakdown.parasite['main_wing'].parasite_drag_coefficient # Might not be the correct value
            l_v = geometry.wings['vertical_stabilizer'].origin[0] + geometry.wings['vertical_stabilizer'].aerodynamic_center[0] - geometry.wings['main_wing'].origin[0] - geometry.wings['main_wing'].aerodynamic_center[0]
            dynamic_stability.cn_r = Supporting_Functions.cn_r(cDw, geometry.wings['vertical_stabilizer'].areas.reference, Sref, l_v, span, geometry.wings['vertical_stabilizer'].dynamic_pressure_ratio, geometry.wings['vertical_stabilizer'].CL_alpha)
            
            # Derivative of rolling moment with respect to roll rate
            dynamic_stability.cl_p = 0 # Need to see if there is a low fidelity way to calculate cl_p
            
            # Derivative of roll rate with respect to sideslip (dihedral effect)
            dynamic_stability.cl_beta = 0 # Need to see if there is a low fidelity way to calculate cl_beta
            
            # Derivative of pitching moment with respect to pitch rate
            l_t = geometry.wings['horizontal_stabilizer'].origin[0] + geometry.wings['horizontal_stabilizer'].aerodynamic_center[0] - geometry.wings['main_wing'].origin[0] - geometry.wings['main_wing'].aerodynamic_center[0] #Need to check this is the length of the horizontal tail moment arm       
            dynamic_stability.cm_q = Supporting_Functions.cm_q(conditions.lift_curve_slope, l_t,mac) # Need to check Cm_i versus Cm_alpha
            
            # Derivative of pitching rate with respect to d(alpha)/d(t)
            dynamic_stability.cm_alpha_dot = Supporting_Functions.cm_alphadot(static_stability.cm_alpha, geometry.wings['horizontal_stabilizer'].ep_alpha, l_t, mac) # Need to check Cm_i versus Cm_alpha
              
            # Derivative of Z-axis force with respect to angle of attack  
            dynamic_stability.cz_alpha = Supporting_Functions.cz_alpha(aero.drag_coefficient,conditions.lift_curve_slope)                   
            
            
            stability_model.dutch_roll = Approximations.dutch_roll(velocity, static_stability.cn_beta, Sref, density, Span, configuration.mass_properties.moments_of_inertia.tensor[2][2], dynamic_stability.cn_r)
            
            if dynamic_stability.cl_p != 0:                 
                stability_model.roll_tau = Approximations.roll(configuration.mass_properties.momen[2][2], Sref, density, velocity, Span, dynamic_stability.cl_p)
                dynamic_stability.cy_phi = Supporting_Functions.cy_phi(aero.lift_coefficient)
                dynamic_stability.cl_r = Supporting_Functions.cl_r( aero.lift_coefficient) # Will need to be changed
                stability_model.spiral_tau = Approximations.spiral(conditions.weights.total_mass, velocity, density, Sref, dynamic_stability.cl_p, static_stability.cn_beta, dynamic_stability.cy_phi, dynamic_stability.cl_beta, dynamic_stability.cn_r, dynamic_stability.cl_r)
            stability_model.short_period = Approximations.short_period(velocity, density, Sref, mac, dynamic_stability.cm_q, dynamic_stability.cz_alpha, conditions.weights.total_mass, static_stability.cm_alpha, configuration.mass_properties.moments_of_inertia.tensor[1][1], dynamic_stability.cm_alpha_dot)
            stability_model.phugoid = Approximations.phugoid(conditions.freestream.gravity, conditions.freestream.velocity, aero.drag_coefficient, aero.lift_coefficient)
            
            # Dynamic Stability Full Linearized Methods
            if aero.has_key('cy_beta') and dynamic_stability.cl_p != 0 and dynamic_stability.cl_beta != 0:
                theta = conditions.frames.wind.body_rotations[:,1]
                dynamic_stability.cy_beta = aero.cy_beta
                dynamic_stability.cl_psi = Supporting_Functions.cy_psi(aero.lift_coefficient, theta)                     
                dynamic_stability.cL_u = 0
                dynamic_stability.cz_u = Supporting_Functions.cz_u(aero.lift_coefficient,velocity,dynamic_stability.cL_u)
                dynamic_stability.cz_alpha_dot = Supporting_Functions.cz_alphadot(static_stability.cm_alpha, geometry.wings['horizontal_stabilizer'].ep_alpha)
                dynamic_stability.cz_q = Supporting_Functions.cz_q(static_stability.cm_alpha)
                dynamic_stability.cx_u = Supporting_Functions.cx_u(aero.drag_coefficient)
                dynamic_stability.cx_alpha = Supporting_Functions.cx_alpha(aero.lift_coefficient, conditions.lift_curve_slope)
            
                lateral_directional = Full_Linearized_Equations.lateral_directional(velocity, static_stability.cn_beta , Sref, density, Span, configuration.mass_properties.moments_of_inertia.tensor[2][2], dynamic_stability.cn_r, configuration.mass_properties.Moments_Of_Inertia.tensor[0][0], dynamic_stability.cl_p, configuration.mass_properties.moments_of_inertia.tensor[0][2], dynamic_stability.cl_r, dynamic_stability.cl_beta, dynamic_stability.cn_p, dynamic_stability.cy_phi, dynamic_stability.cy_psi, dynamic_stability.cy_beta, conditions.weights.total_mass)
                longitudinal = Full_Linearized_Equations.longitudinal(velocity, density, Sref, mac, dynamic_stability.cm_q, dynamic_stability.cz_alpha, conditions.weights.total_mass, static_stability.cm_alpha, configuration.mass_properties.moments_of_inertia.tensor[1][1], dynamic_stability.cm_alpha_dot, dynamic_stability.cz_u, dynamic_stability.cz_alpha_dot, dynamic_stability.cz_q, -aero.lift_coefficient, theta, dynamic_stability.cx_u, dynamic_stability.cx_alpha)                    
                stability_model.dutch_roll.natural_frequency = lateral_directional.dutch_natural_frequency
                stability_model.dutch_roll.damping_ratio = lateral_directional.dutch_damping_ratio
                stability_model.spiral_tau = lateral_directional.spiral_tau
                stability_model.roll_tau = lateral_directional.roll_tau
                stability_model.short_period.natural_frequency = longitudinal.short_natural_frequency
                stability_model.short_period.damping_ratio = longitudinal.short_damping_ratio
                stability_model.phugoid.natural_frequency = longitudinal.phugoid_natural_frequency
                stability_model.phugoid.damping_ratio = longitudinal.phugoid_damping_ratio
        
        # pack results
        results = Data()
        results.static  = static_stability
        results.dynamic = dynamic_stability
        
        return results
def compute_dynamic_flight_modes(results, aircraft, flight_conditions, cases):
    """This function follows the stability axis EOM derivation in Blakelock
    to return the aircraft's dynamic modes and state space 
    
    Assumptions:
       Linerarized Equations are used following the reference below

    Source:
      Automatic Control of Aircraft and Missiles by J. Blakelock Pg 23 and 117 

    Inputs:
       results.aerodynamics  
       results.stability.static  
       results.stability.dynamic 

    Outputs: 
       results.dynamic_stability.LatModes
       results.dynamic_stability.LongModes 

    Properties Used:
       N/A
     """

    # unpack unit conversions
    g = flight_conditions.freestream.gravity
    mach = flight_conditions.freestream.mach_number

    # Calculate change in downwash with respect to change in angle of attack
    for surf in aircraft.wings:
        sref = surf.areas.reference
        span = (surf.aspect_ratio * sref)**0.5
        surf.CL_alpha = datcom(surf, mach)
        surf.ep_alpha = Supporting_Functions.ep_alpha(surf.CL_alpha, sref,
                                                      span)

    # Unpack aircraft Properties
    theta0 = results.aerodynamics.AoA
    AoA = results.aerodynamics.AoA
    CLtot = results.aerodynamics.lift_coefficient
    CDtot = results.aerodynamics.drag_coefficient
    e = results.aerodynamics.oswald_efficiency
    st = results.stability.static
    dy = results.stability.dynamic

    num_cases = len(AoA)

    b_ref = results.b_ref
    c_ref = results.c_ref
    S_ref = results.S_ref
    AR = (b_ref**2) / S_ref
    moments_of_inertia = aircraft.mass_properties.moments_of_inertia.tensor
    Ixx = moments_of_inertia[0][0]
    Iyy = moments_of_inertia[1][1]
    Izz = moments_of_inertia[2][2]
    if aircraft.mass_properties.mass == 0:
        m = aircraft.mass_properties.max_takeoff
    elif aircraft.mass_properties.max_takeoff == 0:
        m = aircraft.mass_properties.mass
    else:
        raise AttributeError("Specify Vehicle Mass")

    # unpack FLight Conditions
    rho = flight_conditions.freestream.density
    u0 = flight_conditions.freestream.velocity
    qDyn0 = 0.5 * rho * u0**2

    st.spiral_stability = st.Cl_beta * st.Cn_r / (st.Cl_r * st.Cn_beta)

    ## Build longitudinal EOM A Matrix (stability axis)
    ALon = np.zeros((num_cases, 4, 4))
    BLon = np.zeros((num_cases, 4, 1))
    CLon = np.zeros((num_cases, 4, 4))
    for i in range(num_cases):
        CLon[i, :, :] = np.eye(4)
    DLon = np.zeros((num_cases, 4, 1))

    Cw = m * g / (qDyn0 * S_ref)
    Cxu = st.CX_u
    Xu = rho * u0 * S_ref * Cw * np.sin(theta0) + 0.5 * rho * u0 * S_ref * Cxu
    Cxalpha = (CLtot - 2 * CLtot / (np.pi * AR * e) * st.CL_alpha)
    Xw = 0.5 * rho * u0 * S_ref * Cxalpha
    Xq = 0

    Czu = st.CZ_u
    Zu = -rho * u0 * S_ref * Cw * np.cos(theta0) + 0.5 * rho * u0 * S_ref * Czu
    Czalpha = -CDtot - st.CL_alpha
    Zw = 0.5 * rho * u0 * S_ref * Czalpha
    Czq = -st.CL_q
    Zq = 0.25 * rho * u0 * c_ref * S_ref * Czq
    Cmu = st.Cm_q
    Mu = 0.5 * rho * u0 * c_ref * S_ref * Cmu
    Mw = 0.5 * rho * u0 * c_ref * S_ref * st.Cm_alpha
    Mq = 0.25 * rho * u0 * c_ref * c_ref * S_ref * st.Cm_q

    # Derivative of pitching rate with respect to d(alpha)/d(t)
    if aircraft.wings['horizontal_stabilizer'] and aircraft.wings['main_wing']:
        l_t = aircraft.wings['horizontal_stabilizer'].origin[
            0] + aircraft.wings['horizontal_stabilizer'].aerodynamic_center[
                0] - aircraft.wings['main_wing'].origin[0] - aircraft.wings[
                    'main_wing'].aerodynamic_center[0]
        mac = aircraft.wings['main_wing'].chords.mean_aerodynamic
        st.Cm_alpha_dot = Supporting_Functions.cm_alphadot(
            st.Cm_alpha, aircraft.wings['horizontal_stabilizer'].ep_alpha, l_t,
            mac)
        st.Cz_alpha_dot = Supporting_Functions.cz_alphadot(
            st.Cm_alpha, aircraft.wings['horizontal_stabilizer'].ep_alpha)
    else:
        st.Cm_alpha_dot = 0
        st.Cz_alpha_dot = 0

    ZwDot = 0.25 * rho * c_ref * S_ref * st.Cz_alpha_dot
    MwDot = 0.25 * rho * c_ref * S_ref * st.Cm_alpha_dot

    # Elevator effectiveness
    for wing in aircraft.wings:
        if wing.control_surfaces:
            for cs in wing.control_surfaces:
                ctrl_surf = wing.control_surfaces[cs]
                if (type(ctrl_surf) == Elevator):
                    ele = st.control_surfaces_cases[
                        cases[i].tag].control_surfaces[cs]
                    Xe = 0  # Neglect
                    Ze = 0.5 * rho * u0 * u0 * S_ref * ele.CL
                    Me = 0.5 * rho * u0 * u0 * S_ref * c_ref * ele.Cm

                    BLon[:, 0, 0] = Xe / m
                    BLon[:, 1, 0] = (Ze / (m - ZwDot)).T[0]
                    BLon[:, 2,
                         0] = (Me / Iyy + MwDot / Iyy * Ze / (m - ZwDot)).T[0]
                    BLon[:, 3, 0] = 0

    ALon[:, 0, 0] = (Xu / m).T[0]
    ALon[:, 0, 1] = (Xw / m).T[0]
    ALon[:, 0, 2] = Xq / m
    ALon[:, 0, 3] = (-g * np.cos(theta0)).T[0]
    ALon[:, 1, 0] = (Zu / (m - ZwDot)).T[0]
    ALon[:, 1, 1] = (Zw / (m - ZwDot)).T[0]
    ALon[:, 1, 2] = ((Zq + (m * u0)) / (m - ZwDot)).T[0]
    ALon[:, 1, 3] = (-m * g * np.sin(theta0) / (m - ZwDot)).T[0]
    ALon[:, 2, 0] = ((Mu + MwDot * Zu / (m - ZwDot)) / Iyy).T[0]
    ALon[:, 2, 1] = ((Mw + MwDot * Zw / (m - ZwDot)) / Iyy).T[0]
    ALon[:, 2, 2] = ((Mq + MwDot * (Zq + m * u0) / (m - ZwDot)) / Iyy).T[0]
    ALon[:, 2,
         3] = (-MwDot * m * g * np.sin(theta0) / (Iyy * (m - ZwDot))).T[0]
    ALon[:, 3, 0] = 0
    ALon[:, 3, 1] = 0
    ALon[:, 3, 2] = 1
    ALon[:, 3, 3] = 0

    # Look at eigenvalues and eigenvectors
    LonModes = np.zeros((num_cases, 4), dtype=complex)
    phugoidFreqHz = np.zeros((num_cases, 1))
    phugoidDamping = np.zeros((num_cases, 1))
    phugoidTimeDoubleHalf = np.zeros((num_cases, 1))
    shortPeriodFreqHz = np.zeros((num_cases, 1))
    shortPeriodDamping = np.zeros((num_cases, 1))
    shortPeriodTimeDoubleHalf = np.zeros((num_cases, 1))

    for i in range(num_cases):
        D, V = np.linalg.eig(ALon[i, :, :])  # State order: u, w, q, theta
        LonModes[i, :] = D

        # Find phugoid
        phugoidInd = np.argmax(V[0, :])  # u is the primary state involved
        phugoidFreqHz[i] = abs(LonModes[i, phugoidInd]) / 2 / np.pi
        phugoidDamping[i] = -np.cos(np.angle(LonModes[i, phugoidInd]))
        phugoidTimeDoubleHalf[i] = np.log(2) / abs(
            2 * np.pi * phugoidFreqHz[i] * phugoidDamping[i])

        # Find short period
        shortPeriodInd = np.argmax(V[1, :])  # w is the primary state involved
        shortPeriodFreqHz[i] = abs(LonModes[i, shortPeriodInd]) / 2 / np.pi
        shortPeriodDamping[i] = -np.cos(np.angle(LonModes[i, shortPeriodInd]))
        shortPeriodTimeDoubleHalf[i] = np.log(2) / abs(
            2 * np.pi * shortPeriodFreqHz[i] * shortPeriodDamping[i])

    ## Build lateral EOM A Matrix (stability axis)
    ALat = np.zeros((num_cases, 4, 4))
    BLat = np.zeros((num_cases, 4, 1))
    CLat = np.zeros((num_cases, 4, 4))
    for i in range(num_cases):
        CLat[i, :, :] = np.eye(4)
    DLat = np.zeros((num_cases, 4, 1))

    # Need to compute Ixx, Izz, and Ixz as a function of alpha
    Ixp = np.zeros((num_cases, 1))
    Izp = np.zeros((num_cases, 1))
    Ixzp = np.zeros((num_cases, 1))

    for i in range(num_cases):
        R = np.array([[
            np.cos(AoA[i][0] * Units.degrees),
            -np.sin(AoA[i][0] * Units.degrees)
        ],
                      [
                          np.sin(AoA[i][0] * Units.degrees),
                          np.cos(AoA[i][0] * Units.degrees)
                      ]])
        modI = np.array([[moments_of_inertia[0][0], moments_of_inertia[0][2]],
                         [moments_of_inertia[2][0], moments_of_inertia[2][2]]])
        INew = R * modI * np.transpose(R)
        IxxStab = INew[0, 0]
        IxzStab = -INew[0, 1]
        IzzStab = INew[1, 1]
        Ixp[i] = (IxxStab * IzzStab - IxzStab**2) / IzzStab
        Izp[i] = (IxxStab * IzzStab - IxzStab**2) / IxxStab
        Ixzp[i] = IxzStab / (IxxStab * IzzStab - IxzStab**2)

    Yv = 0.5 * rho * u0 * S_ref * st.CY_beta
    Yp = 0.25 * rho * u0 * b_ref * S_ref * st.CY_p
    Yr = 0.25 * rho * u0 * b_ref * S_ref * st.CY_r
    Lv = 0.5 * rho * u0 * b_ref * S_ref * st.Cl_beta
    Lp = 0.25 * rho * u0 * b_ref**2 * S_ref * st.Cl_p
    Lr = 0.25 * rho * u0 * b_ref**2 * S_ref * st.Cl_r
    Nv = 0.5 * rho * u0 * b_ref * S_ref * st.Cn_beta
    Np = 0.25 * rho * u0 * b_ref**2 * S_ref * st.Cn_p
    Nr = 0.25 * rho * u0 * b_ref**2 * S_ref * st.Cn_r

    # Aileron effectiveness
    for wing in aircraft.wings:
        if wing.control_surfaces:
            for cs in wing.control_surfaces:
                ctrl_surf = wing.control_surfaces[cs]
                if (type(ctrl_surf) == Aileron):
                    ail = st.control_surfaces_cases[
                        cases[i].tag].control_surfaces[cs]
                    Ya = 0.5 * rho * u0 * u0 * S_ref * ail.CY
                    La = 0.5 * rho * u0 * u0 * S_ref * b_ref * ail.Cl
                    Na = 0.5 * rho * u0 * u0 * S_ref * b_ref * ail.Cn

                    BLat[:, 0, 0] = (Ya / m).T[0]
                    BLat[:, 1, 0] = (La / Ixp + Ixzp * Na).T[0]
                    BLat[:, 2, 0] = (Ixzp * La + Na / Izp).T[0]
                    BLat[:, 3, 0] = 0

    ALat[:, 0, 0] = (Yv / m).T[0]
    ALat[:, 0, 1] = (Yp / m).T[0]
    ALat[:, 0, 2] = (Yr / m - u0).T[0]
    ALat[:, 0, 3] = (g * np.cos(theta0)).T[0]
    ALat[:, 1, 0] = (Lv / Ixp + Ixzp * Nv).T[0]
    ALat[:, 1, 1] = (Lp / Ixp + Ixzp * Np).T[0]
    ALat[:, 1, 2] = (Lr / Ixp + Ixzp * Nr).T[0]
    ALat[:, 1, 3] = 0
    ALat[:, 2, 0] = (Ixzp * Lv + Nv / Izp).T[0]
    ALat[:, 2, 1] = (Ixzp * Lp + Np / Izp).T[0]
    ALat[:, 2, 2] = (Ixzp * Lr + Nr / Izp).T[0]
    ALat[:, 2, 3] = 0
    ALat[:, 3, 0] = 0
    ALat[:, 3, 1] = 1
    ALat[:, 3, 2] = (np.tan(theta0)).T[0]
    ALat[:, 3, 3] = 0

    LatModes = np.zeros((num_cases, 4), dtype=complex)
    dutchRollFreqHz = np.zeros((num_cases, 1))
    dutchRollDamping = np.zeros((num_cases, 1))
    dutchRollTimeDoubleHalf = np.zeros((num_cases, 1))
    rollSubsistenceFreqHz = np.zeros((num_cases, 1))
    rollSubsistenceTimeConstant = np.zeros((num_cases, 1))
    rollSubsistenceDamping = np.zeros((num_cases, 1))
    spiralFreqHz = np.zeros((num_cases, 1))
    spiralTimeDoubleHalf = np.zeros((num_cases, 1))
    spiralDamping = np.zeros((num_cases, 1))
    dutchRoll_mode_real = np.zeros((num_cases, 1))

    for i in range(num_cases):
        D, V = np.linalg.eig(ALat[i, :, :])  # State order: u, w, q, theta
        LatModes[i, :] = D

        # Find dutch roll (complex pair)
        done = 0
        for j in range(3):
            for k in range(j + 1, 4):
                if LatModes[i, j].real == LatModes[i, k].real:
                    dutchRollFreqHz[i] = abs(LatModes[i, j]) / 2 / np.pi
                    dutchRollDamping[i] = -np.cos(np.angle(LatModes[i, j]))
                    dutchRollTimeDoubleHalf[i] = np.log(2) / abs(
                        2 * np.pi * dutchRollFreqHz[i] * dutchRollDamping[i])
                    dutchRoll_mode_real[i] = LatModes[i, j].real / 2 / np.pi
                    done = 1
                    break
            if done:
                break

        # Find roll mode
        diff_vec = np.arange(0, 4)
        tmpInd = np.setdiff1d(diff_vec, [j, k])
        rollInd = np.argmax(abs(
            LatModes[i, tmpInd]))  # higher frequency than spiral
        rollInd = tmpInd[rollInd]
        rollSubsistenceFreqHz[i] = abs(LatModes[i, rollInd]) / 2 / np.pi
        rollSubsistenceDamping[i] = -np.sign(LatModes[i, rollInd].real)
        rollSubsistenceTimeConstant[i] = 1 / (
            2 * np.pi * rollSubsistenceFreqHz[i] * rollSubsistenceDamping[i])

        # Find spiral mode
        spiralInd = np.setdiff1d(diff_vec, [j, k, rollInd])
        spiralFreqHz[i] = abs(LatModes[i, spiralInd]) / 2 / np.pi
        spiralDamping[i] = -np.sign(LatModes[i, spiralInd].real)
        spiralTimeDoubleHalf[i] = np.log(2) / abs(
            2 * np.pi * spiralFreqHz[i] * spiralDamping[i])

    ## Build longitudinal and lateral state space system. Requires additional toolbox
    #from control.matlab import ss  # control toolbox needed in python. Run "pip (or pip3) install control"
    #LonSys    = {}
    #LatSys    = {}
    #for i in range(num_cases):
    #LonSys[cases[i].tag] = ss(ALon[i],BLon[i],CLon[i],DLon[i])
    #LatSys[cases[i].tag] = ss(ALat[i],BLat[i],CLat[i],DLat[i])

    # Inertial coupling susceptibility
    # See Etkin & Reid pg. 118
    results.dynamic_stability = Data()
    results.dynamic_stability.LongModes = Data()
    results.dynamic_stability.LatModes = Data()
    results.dynamic_stability.pMax = min(min(np.sqrt(-Mw * u0 / (Izz - Ixx))),
                                         min(np.sqrt(-Nv * u0 / (Iyy - Ixx))))

    # -----------------------------------------------------------------------------------------------------------------------
    # Store Results
    # ------------------------------------------------------------------------------------------------------------------------
    results.dynamic_stability.LongModes.LongModes = LonModes
    #results.dynamic_stability.LongModes.LongSys                      = LonSys
    results.dynamic_stability.LongModes.phugoidFreqHz = phugoidFreqHz
    results.dynamic_stability.LongModes.phugoidDamp = phugoidDamping
    results.dynamic_stability.LongModes.phugoidTimeDoubleHalf = phugoidTimeDoubleHalf
    results.dynamic_stability.LongModes.shortPeriodFreqHz = shortPeriodFreqHz
    results.dynamic_stability.LongModes.shortPeriodDamp = shortPeriodDamping
    results.dynamic_stability.LongModes.shortPeriodTimeDoubleHalf = shortPeriodTimeDoubleHalf

    results.dynamic_stability.LatModes.LatModes = LatModes
    #results.dynamic_stability.LatModes.Latsys                        = LatSys
    results.dynamic_stability.LatModes.dutchRollFreqHz = dutchRollFreqHz
    results.dynamic_stability.LatModes.dutchRollDamping = dutchRollDamping
    results.dynamic_stability.LatModes.dutchRollTimeDoubleHalf = dutchRollTimeDoubleHalf
    results.dynamic_stability.LatModes.dutchRoll_mode_real = dutchRoll_mode_real
    results.dynamic_stability.LatModes.rollSubsistenceFreqHz = rollSubsistenceFreqHz
    results.dynamic_stability.LatModes.rollSubsistenceTimeConstant = rollSubsistenceTimeConstant
    results.dynamic_stability.LatModes.rollSubsistenceDamping = rollSubsistenceDamping
    results.dynamic_stability.LatModes.spiralFreqHz = spiralFreqHz
    results.dynamic_stability.LatModes.spiralTimeDoubleHalf = spiralTimeDoubleHalf
    results.dynamic_stability.LatModes.spiralDamping = spiralDamping

    return results
示例#6
0
    def __call__(self, conditions):
        """ process vehicle to setup geometry, condititon and configuration
                
                Inputs:
                    conditions - DataDict() of aerodynamic conditions
                    results - DataDict() of 
                    
                Outputs:

                    
                Assumptions:

                    
            """

        # unpack
        configuration = self.configuration
        geometry = self.geometry
        stability_model = self.stability_model
        q = conditions.freestream.dynamic_pressure
        Sref = geometry.reference_area
        mach = conditions.freestream.mach_number
        velocity = conditions.freestream.velocity
        density = conditions.freestream.density
        Span = geometry.wings['Main Wing'].spans.projected
        mac = geometry.wings['Main Wing'].chords.mean_aerodynamic
        aero = conditions.aerodynamics

        # Calculate CL_alpha
        if not conditions.has_key('lift_curve_slope'):
            conditions.lift_curve_slope = datcom(geometry.wings['Main Wing'],
                                                 mach)

        # Calculate change in downwash with respect to change in angle of attack
        for surf in geometry.wings:
            e = surf.span_efficiency
            sref = surf.areas.reference
            span = (surf.aspect_ratio * sref)**0.5
            surf.CL_alpha = datcom(surf, mach)
            surf.ep_alpha = Supporting_Functions.ep_alpha(
                surf.CL_alpha, sref, span, e)

        # Static Stability Methods
        aero.cm_alpha = taw_cmalpha(geometry, mach, conditions, configuration)
        aero.cn_beta = taw_cnbeta(geometry, conditions, configuration)

        if np.count_nonzero(
                configuration.mass_properties.moments_of_inertia.tensor) > 0:
            # Dynamic Stability Approximation Methods
            if not aero.has_key('cn_r'):
                cDw = aero.drag_breakdown.parasite[
                    'Main Wing'].parasite_drag_coefficient  # Might not be the correct value
                l_v = geometry.wings['Vertical Stabilizer'].origin[
                    0] + geometry.wings[
                        'Vertical Stabilizer'].aerodynamic_center[
                            0] - geometry.wings['Main Wing'].origin[
                                0] - geometry.wings[
                                    'Main Wing'].aerodynamic_center[0]
                aero.cn_r = Supporting_Functions.cn_r(
                    cDw, geometry.wings['Vertical Stabilizer'].areas.reference,
                    Sref, l_v, span, geometry.wings['Vertical Stabilizer'].eta,
                    geometry.wings['Vertical Stabilizer'].CL_alpha)
            if not aero.has_key('cl_p'):
                aero.cl_p = 0  # Need to see if there is a low fidelity way to calculate cl_p

            if not aero.has_key('cl_beta'):
                aero.cl_beta = 0  # Need to see if there is a low fidelity way to calculate cl_beta

                l_t = geometry.wings['Horizontal Stabilizer'].origin[
                    0] + geometry.wings['Horizontal Stabilizer'].aerodynamic_center[
                        0] - geometry.wings['Main Wing'].origin[
                            0] - geometry.wings['Main Wing'].aerodynamic_center[
                                0]  #Need to check this is the length of the horizontal tail moment arm

            if not aero.has_key('cm_q'):
                aero.cm_q = Supporting_Functions.cm_q(
                    conditions.lift_curve_slope, l_t,
                    mac)  # Need to check Cm_i versus Cm_alpha

            if not aero.has_key('cm_alpha_dot'):
                aero.cm_alpha_dot = Supporting_Functions.cm_alphadot(
                    aero.cm_alpha,
                    geometry.wings['Horizontal Stabilizer'].ep_alpha, l_t,
                    mac)  # Need to check Cm_i versus Cm_alpha

            if not aero.has_key('cz_alpha'):
                aero.cz_alpha = Supporting_Functions.cz_alpha(
                    aero.drag_coefficient, conditions.lift_curve_slope)

            stability_model.dutch_roll = Approximations.dutch_roll(
                velocity, aero.cn_beta, Sref, density, Span,
                configuration.mass_properties.moments_of_inertia.tensor[2][2],
                aero.cn_r)

            if aero.cl_p != 0:
                stability_model.roll_tau = Approximations.roll(
                    configuration.mass_properties.momen[2][2], Sref, density,
                    velocity, Span, aero.cl_p)
                if aero.cl_beta != 0:
                    aero.cy_phi = Supporting_Functions.cy_phi(
                        aero.lift_coefficient)
                    aero.cl_r = Supporting_Functions.cl_r(
                        aero.lift_coefficient)  # Will need to be changed
                    stability_model.spiral_tau = Approximations.spiral(
                        conditions.weights.total_mass, velocity, density, Sref,
                        aero.cl_p, aero.cn_beta, aero.cy_phi, aero.cl_beta,
                        aero.cn_r, aero.cl_r)
            stability_model.short_period = Approximations.short_period(
                velocity, density, Sref, mac, aero.cm_q, aero.cz_alpha,
                conditions.weights.total_mass, aero.cm_alpha,
                configuration.mass_properties.moments_of_inertia.tensor[1][1],
                aero.cm_alpha_dot)
            stability_model.phugoid = Approximations.phugoid(
                conditions.freestream.gravity, conditions.freestream.velocity,
                aero.drag_coefficient, aero.lift_coefficient)

            # Dynamic Stability Full Linearized Methods
            if aero.has_key(
                    'cy_beta') and aero.cl_p != 0 and aero.cl_beta != 0:
                if not aero.has_key('cy_psi'):
                    theta = conditions.frames.wind.body_rotations[:, 1]
                    aero.cl_psi = Supporting_Functions.cy_psi(
                        aero.lift_coefficient, theta)
                if not aero.has_key('cz_u'):
                    if not aero.has_key('cL_u'):
                        aero.cL_u = 0
                    aero.cz_u = Supporting_Functions.cz_u(
                        aero.lift_coefficient, velocity, aero.cL_u)
                if not aero.has_key('cz_alpha_dot'):
                    aero.cz_alpha_dot = Supporting_Functions.cz_alphadot(
                        aero.cm_alpha,
                        geometry.wings['Horizontal Stabilizer'].ep_alpha)
                if not aero.has_key('cz_q'):
                    aero.cz_q = Supporting_Functions.cz_q(aero.cm_alpha)
                if not aero.has_key('cx_u'):
                    aero.cx_u = Supporting_Functions.cx_u(
                        aero.drag_coefficient)
                if not aero.has_key('cx_alpha'):
                    aero.cx_alpha = Supporting_Functions.cx_alpha(
                        aero.lift_coefficient, conditions.lift_curve_slope)

                lateral_directional = Full_Linearized_Equations.lateral_directional(
                    velocity, aero.cn_beta, Sref, density, Span,
                    configuration.mass_properties.moments_of_inertia.tensor[2]
                    [2], aero.cn_r,
                    configuration.mass_properties.Moments_Of_Inertia.tensor[0]
                    [0], aero.cl_p,
                    configuration.mass_properties.moments_of_inertia.tensor[0]
                    [2], aero.cl_r, aero.cl_beta, aero.cn_p, aero.cy_phi,
                    aero.cy_psi, aero.cy_beta, conditions.weights.total_mass)
                longitudinal = Full_Linearized_Equations.longitudinal(
                    velocity, density, Sref, mac, aero.cm_q, aero.cz_alpha,
                    conditions.weights.total_mass, aero.cm_alpha,
                    configuration.mass_properties.moments_of_inertia.tensor[1]
                    [1], aero.cm_alpha_dot, aero.cz_u, aero.cz_alpha_dot,
                    aero.cz_q, -aero.lift_coefficient, theta, aero.cx_u,
                    aero.cx_alpha)
                stability_model.dutch_roll.natural_frequency = lateral_directional.dutch_natural_frequency
                stability_model.dutch_roll.damping_ratio = lateral_directional.dutch_damping_ratio
                stability_model.spiral_tau = lateral_directional.spiral_tau
                stability_model.roll_tau = lateral_directional.roll_tau
                stability_model.short_period.natural_frequency = longitudinal.short_natural_frequency
                stability_model.short_period.damping_ratio = longitudinal.short_damping_ratio
                stability_model.phugoid.natural_frequency = longitudinal.phugoid_natural_frequency
                stability_model.phugoid.damping_ratio = longitudinal.phugoid_damping_ratio

        return