예제 #1
0
    def __init__(self, name,
                 relative_pos=Vector2D(0, 0),
                 chord_length=1,
                 angle=Angle(0),
                 area=1,
                 lift_curve=None,
                 drag_curve=None,
                 atmosphere=Atmosphere()):

        self._point = Point(relative_pos)

        self.name = name
        self.angle = angle
        self.area = area
        self._atmosphere = atmosphere

        self.lift_curve = lift_curve
        self.drag_curve = drag_curve

        if lift_curve is not None:
            stall_angle = lift_curve.stall_angle()
        else:
            stall_angle = None

        self.cp = CP(relative_pos, chord_length, stall_angle)

        self.velocity = Vector2D(0, 0)
        self.current_cp = Vector2D(0, 0)
예제 #2
0
 def test_0_length(self):
     cp = CP(Vector2D(1, 0), 0, Angle(10))
     calculated = cp.calculate(Angle(1))
     self.assertEqual(1, calculated.x)
예제 #3
0
 def test_backward_upsidedown(self):
     cp = CP(Vector2D(1, 0), 12, Angle(10))
     calculated = cp.calculate(Angle(-175))
     self.assertEqual(-8, calculated.x)
예제 #4
0
 def test_backward_upsidedown_stalled(self):
     cp = CP(Vector2D(1, 0), 12, Angle(10))
     calculated = cp.calculate(Angle(-130))
     self.assertEqual(-6.5, calculated.x)
예제 #5
0
 def test_down_vertical(self):
     cp = CP(Vector2D(1, 0), 12, Angle(10))
     calculated = cp.calculate(Angle(-90))
     self.assertEqual(-5, calculated.x)
예제 #6
0
 def test_down_stalled(self):
     cp = CP(Vector2D(1, 0), 12, Angle(10))
     calculated = cp.calculate(Angle(-50))
     self.assertEqual(-3.5, calculated.x)
예제 #7
0
 def test_just_past_vertical(self):
     cp = CP(Vector2D(1, 0), 12, Angle(10))
     calculated = cp.calculate(Angle(91))
     self.assertEqual(-5.0375, calculated.x)
예제 #8
0
 def test_normal(self):
     cp = CP(Vector2D(1, 0), 12, Angle(10))
     calculated = cp.calculate(Angle(1))
     self.assertEqual(-2, calculated.x)
예제 #9
0
 def test_null_angle(self):
     cp = CP(Vector2D(1, 0), 12, None)
     calculated = cp.calculate(Angle(1))
     self.assertEqual(1, calculated.x)
예제 #10
0
class Surface:
    ''' A plane has multiple services that generate lift
    and drag forces'''

    def __init__(self, name,
                 relative_pos=Vector2D(0, 0),
                 chord_length=1,
                 angle=Angle(0),
                 area=1,
                 lift_curve=None,
                 drag_curve=None,
                 atmosphere=Atmosphere()):

        self._point = Point(relative_pos)

        self.name = name
        self.angle = angle
        self.area = area
        self._atmosphere = atmosphere

        self.lift_curve = lift_curve
        self.drag_curve = drag_curve

        if lift_curve is not None:
            stall_angle = lift_curve.stall_angle()
        else:
            stall_angle = None

        self.cp = CP(relative_pos, chord_length, stall_angle)

        self.velocity = Vector2D(0, 0)
        self.current_cp = Vector2D(0, 0)

    def aoa(self, velocity):
        vel_angle = velocity.angle()
        return self.angle.minus(vel_angle)

    def calculate_forces(self, translation_velocity,
                         angular_velocity, altitude):

        surface_velocity = self._point.total_velocity(
            translation_velocity,
            angular_velocity)

        self.velocity = surface_velocity
        air_density = self._atmosphere.get_air_density(altitude)

        velocity_magnitude = surface_velocity.magnitude()
        aoa = self.aoa(surface_velocity)

        forces = []

        current_cp = self.cp.calculate(aoa)
        self.current_cp = current_cp

        CL = 0
        if self.lift_curve is not None:
            CL = self.lift_curve.calculate_lift_coefficient(aoa)
            lift_mag = self.calculate_lift(CL, velocity_magnitude, air_density)
            lift_dir = Surface.get_lift_unit(aoa, surface_velocity)
            lift_force = lift_dir.scale(lift_mag)
            forces.append(Force("lift", Force.LIFT,
                                current_cp, lift_force))

        CD = 0
        if self.drag_curve is not None:
            CD = self.drag_curve.calculate_drag_coefficient(aoa, CL)
            drag_mag = self.calculate_drag(
                CD, velocity_magnitude, air_density)
            drag_dir = surface_velocity.reverse().unit()
            drag_vector = drag_dir.scale(drag_mag)
            drag_force = Force("drag", Force.DRAG,
                               current_cp, drag_vector)
            forces.append(drag_force)

        return forces

    def get_lift_unit(aoa, surface_velocity):
        if abs(aoa.relative_degrees()) <= 90:
            return surface_velocity.rotate(Angle(90)).unit()
        else:
            # trailing edge is leading so velocity vector is reversed
            return surface_velocity.rotate(Angle(-90)).unit()

    def calculate_lift(self, CL, velocity_magnitude, air_density):
        return (air_density * velocity_magnitude**2 * self.area * CL) \
            / 2

    def calculate_drag(self, CD, velocity_magnitude, air_density):
        return CD * self.area * (air_density * velocity_magnitude**2) \
            / 2