Example #1
0
def test_move(monkeypatch, freebody):
    freebody.mass = 2
    freebody.pitch_rot_inertia = 3
    freebody.rot_velocity = 2
    freebody.angle = 1
    freebody.velocity = Vector2(12, 3)
    freebody.position = Vector2(5, 1)

    def force_and_moment_at_cg_mock():
        return Vector2(50, 10), 1.5

    freebody.force_and_moment_at_cg = force_and_moment_at_cg_mock

    total_force, moment_z = freebody.move(0.1)

    npt.assert_almost_equal(freebody.rot_velocity, 2.05)
    npt.assert_almost_equal(freebody.angle, 1.205)
    npt.assert_almost_equal(freebody.velocity.x, 14.5)
    npt.assert_almost_equal(freebody.velocity.y, 3.5)
    npt.assert_almost_equal(freebody.position.x, 6.45)
    npt.assert_almost_equal(freebody.position.y, 1.35)

    npt.assert_almost_equal(total_force.x, 50)
    npt.assert_almost_equal(total_force.y, 10)
    npt.assert_almost_equal(moment_z, 1.5)
Example #2
0
def test_component_vector_in_absolute_frame(mocker):
    component = mocker.Mock()
    component.position = Vector2(1.4, 0.6)
    component.angle = math.radians(24)
    vector = Vector2(-0.4, 0.1)
    new_vector = component_vector_in_absolute_frame(vector, component)
    npt.assert_almost_equal(new_vector.x, 0.994, decimal=3)
    npt.assert_almost_equal(new_vector.y, 0.53, decimal=3)
Example #3
0
class FreeBody(BaseComponent):
    position_cg: Vector2 = None
    pitch_rot_inertia: float = None
    ambient: Ambient = None

    # State attributes
    position: Vector2 = Vector2(0, 0)
    angle: float = 0
    velocity: Vector2 = Vector2(0.00001, 0.00001)
    rot_velocity: float = 0

    def __attrs_post_init__(self):
        self.add_external_force_function('weight', self.get_total_weight)

    def reset_state(self):
        self.position = Vector2(0, 0)
        self.angle = 0
        self.velocity = Vector2(0.00001, 0.00001)
        self.rot_velocity = 0
        super().reset_state()

    @property
    def gravitational_center(self) -> Vector2:
        return self.position_cg

    def force_and_moment_at_cg(self):
        force_at_cg = Vector2(0, 0)
        moment_at_cg = 0

        force_at_origin, moment_at_origin = self.force_and_moment_at_component_origin(
        )

        force_at_cg += force_at_origin
        moment_at_cg += moment_at_origin
        moment_at_cg += (Vector2(0, 0) -
                         self.gravitational_center).cross(force_at_origin)
        return force_at_cg, moment_at_cg

    def get_total_weight(self):
        weight_mag = gravitational_acceleration * self.total_mass
        weight_angle = math.radians(-90) - self.angle
        weight = Vector2(r=weight_mag, theta=weight_angle)
        return weight, self.gravitational_center

    def move(self, time_step):
        total_force, moment_z = self.force_and_moment_at_cg()

        acc = total_force / self.total_mass
        ang_acc_z = moment_z / self.pitch_rot_inertia

        self.rot_velocity = self.rot_velocity + ang_acc_z * time_step
        self.angle = self.angle + self.rot_velocity * time_step

        self.velocity = self.velocity + acc * time_step
        self.position = self.position + self.velocity * time_step

        return total_force, moment_z
Example #4
0
def test_states(freebody):
    freebody.position = Vector2(15.1, 1.2)
    freebody.angle = math.radians(15)
    freebody.velocity = Vector2(12.1, 0.7)
    freebody.rot_velocity = 14
    assert (freebody.position == Vector2(15.1, 1.2))
    assert (freebody.angle == math.radians(15))
    assert (freebody.velocity == Vector2(12.1, 0.7))
    assert (freebody.rot_velocity == 14)
Example #5
0
    def force_and_moment_at_cg(self):
        force_at_cg = Vector2(0, 0)
        moment_at_cg = 0

        force_at_origin, moment_at_origin = self.force_and_moment_at_component_origin(
        )

        force_at_cg += force_at_origin
        moment_at_cg += moment_at_origin
        moment_at_cg += (Vector2(0, 0) -
                         self.gravitational_center).cross(force_at_origin)
        return force_at_cg, moment_at_cg
Example #6
0
def test_reset_state(freebody):
    freebody.position = Vector2(2, 4)
    freebody.angle = 3
    freebody.velocity = Vector2(7, 2)
    freebody.rot_velocity = 6

    freebody.reset_state()

    assert (freebody.position == Vector2(0, 0))
    assert (freebody.angle == 0)
    assert (freebody.velocity == Vector2(0.00001, 0.00001))
    assert (freebody.rot_velocity == 0)
Example #7
0
def test_component_vector_coords_in_absolute_frame(mocker):
    component = mocker.Mock()
    component.position = Vector2(1.4, 0.6)
    component.angle = math.radians(25)
    vector_origin = Vector2(-0.4, 0.1)
    vector = Vector2(0, 0.5)
    x0, y0, x, y = component_vector_coords_in_absolute_frame(
        vector_origin, vector, component)
    npt.assert_almost_equal(x0, 0.994, decimal=3)
    npt.assert_almost_equal(y0, 0.521, decimal=3)
    npt.assert_almost_equal(x, 0.784, decimal=3)
    npt.assert_almost_equal(y, 0.975, decimal=3)
Example #8
0
def test_gear_reaction(plane, main_landing_gear):
    main_landing_gear.set_parent(plane)
    plane.velocity = Vector2(6, 0.4)

    # Plane on air (position.y = 2m), so no reaction on landing gear is expected
    plane.position = Vector2(10, 2)
    reaction, contact_point = main_landing_gear.gear_reaction()
    assert(type(contact_point) is Vector2)
    npt.assert_almost_equal(reaction.y, 0)

    # Plane on ground (position.y = 0m), so reaction on landing gear is expected
    plane.position = Vector2(10, 0)
    reaction, contact_point = main_landing_gear.gear_reaction()
    npt.assert_almost_equal(reaction.y, 80.0)
Example #9
0
def test_angle_of_attack(freebody_component, attached_component):
    freebody_component.velocity = Vector2(r=12, theta=math.radians(5))
    attached_component.set_parent(freebody_component)
    npt.testing.assert_almost_equal(
        math.degrees(freebody_component.angle_of_attack), -5.0, decimal=1)
    npt.testing.assert_almost_equal(
        math.degrees(attached_component.angle_of_attack), 4.0, decimal=1)
Example #10
0
 def force_and_moment_from_external_forces(self):
     force = Vector2(0.00001, 0)
     moment = 0.0
     for force_function in self.external_forces.values():
         _force, _application_point = force_function()
         force += _force
         moment += _application_point.cross(_force)
     return force, moment
Example #11
0
def test_translate():
    v1 = Vector2(-1.4, 0.6)
    v1_trans1 = translate(v1, 0.3, 0.6)
    v1_trans2 = translate(v1, -0.3, -0.6)
    npt.assert_almost_equal(v1_trans1.x, -1.1)
    npt.assert_almost_equal(v1_trans1.y, 1.2)
    npt.assert_almost_equal(v1_trans2.x, -1.7)
    npt.assert_almost_equal(v1_trans2.y, 0.0)
Example #12
0
def attached_component():
    attached_component = AttachedComponent(name='attached_component',
                                           type='generic_attached_component',
                                           mass=1.4,
                                           relative_position=Vector2(
                                               -0.4, 0.1),
                                           relative_angle=math.radians(9))
    return attached_component
Example #13
0
def test_transform():
    v1 = Vector2(0.7, 0.1)
    v1_trans1 = transform(v1, math.radians(90), -0.2, 0.5)
    v1_trans2 = transform(v1, math.radians(-90), -0.2, 0.5)
    npt.assert_almost_equal(v1_trans1.x, -0.3)
    npt.assert_almost_equal(v1_trans1.y, 1.2)
    npt.assert_almost_equal(v1_trans2.x, -0.1)
    npt.assert_almost_equal(v1_trans2.y, -0.2)
Example #14
0
def payload():
    payload = AttachedComponent(
        name='payload_generic',
        type='payload',
        mass=3.0,
        relative_position=Vector2(-0.6, 0.08),
        relative_angle=math.radians(9)
    )
    return payload
Example #15
0
def freebody_component():
    freebody_component = FreeBody(name='component',
                                  type='generic_component',
                                  mass=3.4,
                                  angle=math.radians(5),
                                  position_cg=Vector2(-0.7, 0.2),
                                  pitch_rot_inertia=30.0,
                                  ambient=Ambient())
    return freebody_component
Example #16
0
 def gear_reaction(self):
     displacement = self.height - self.position.y
     axial_velocity = self.velocity.y
     if displacement > 0:
         reaction_mag = self.spring_coeff * displacement - self.dump_coeff * axial_velocity
     else:
         reaction_mag = 0
     reaction = Vector2(0, reaction_mag)
     return reaction, self.floor_contact_point
Example #17
0
    def get_thrust(self):
        angle_of_attack = self.angle_of_attack
        axial_velocity = self.velocity.rotated(angle_of_attack).x

        thrust_mag = get_axial_thrust_from_linear_model(
            self.ambient.air_density, axial_velocity, self.static_thrust,
            self.linear_coefficient)

        thrust = Vector2(thrust_mag, 0)
        return thrust, self.thrust_center
Example #18
0
 def get_drag(self):
     if self.inverted:
         CD = get_CD_inv(self.angle_of_attack)
     else:
         CD = get_CD(self.angle_of_attack)
     drag_mag = get_drag(self.ambient.air_density, self.velocity.r,
                         self.area, CD)
     drag_angle = math.radians(180) - self.angle_of_attack
     drag = Vector2(r=drag_mag, theta=drag_angle)
     return drag, self.aerodynamic_center
Example #19
0
 def get_lift(self):
     if self.inverted:
         CL = get_CL_inv(self.angle_of_attack)
     else:
         CL = get_CL(self.angle_of_attack)
     lift_mag = get_lift(self.ambient.air_density, self.velocity.r,
                         self.area, CL)
     lift_angle = math.radians(90) - self.angle_of_attack
     lift = Vector2(r=lift_mag, theta=lift_angle)
     return lift, self.aerodynamic_center
Example #20
0
def freebody():
    env = Ambient()
    freebody = FreeBody(
        name='freebody',
        type='generic_freebody',
        mass=23.4,
        position_cg=Vector2(-0.2, 0.02),
        pitch_rot_inertia=5.2,
        ambient=env,
    )
    return freebody
Example #21
0
def plane():
    env = Ambient()
    plane = FreeBody(
        name='plane',
        type='plane',
        mass=23.4,
        position_cg=Vector2(-0.2, 0.02),
        pitch_rot_inertia=5.2,
        ambient=env,
    )
    return plane
Example #22
0
    def force_and_moment_from_children(self):
        force = Vector2(0, 0)
        moment = 0.0

        for component in self.children.values():
            _force, _moment = component.force_and_moment_at_component_origin()
            force += _force.rotated(component.relative_angle)
            moment += _moment
            moment += component.relative_position.cross(
                _force.rotated(component.relative_angle))
        return force, moment
Example #23
0
def test_gear_friction(plane, main_landing_gear):
    main_landing_gear.set_parent(plane)
    plane.velocity = Vector2(6, 0.4)

    # Plane on air (position.y = 2m), so no friction on landing gear is expected
    plane.position = Vector2(10, 2)
    friction, contact_point = main_landing_gear.gear_friction()
    assert(type(contact_point) is Vector2)
    npt.assert_almost_equal(friction.x, 0)

    # Plane on ground (position.y = 0m), going forward, expected friction on negative x direction
    plane.position = Vector2(10, 0)
    friction, contact_point = main_landing_gear.gear_friction()
    npt.assert_almost_equal(friction.x, -4.0)

    # Plane on ground (position.y = 0m), going backwards, expected friction on positive x direction
    plane.velocity = Vector2(-6, 0.4)
    plane.position = Vector2(10, 0)
    friction, contact_point = main_landing_gear.gear_friction()
    npt.assert_almost_equal(friction.x, 4.0)
Example #24
0
    def gear_friction(self):
        normal_force, contact_point = self.gear_reaction()

        if self.velocity.x > 0:
            velocity_direction = 1
        else:
            velocity_direction = -1

        friction_mag = self.friction_coeff * normal_force.r * velocity_direction

        friction = Vector2(-friction_mag, 0)
        return friction, self.floor_contact_point
Example #25
0
def main_landing_gear():
    main_landing_gear = LandingGear(
        name='main_landing_gear',
        relative_position=Vector2(x=-0.2, y=0),
        relative_angle=math.radians(0),
        mass=0.3,
        height=0.1,
        spring_coeff=1000,
        dump_coeff=50,
        friction_coeff=0.05
    )
    return main_landing_gear
Example #26
0
def test_rotate():
    v1 = Vector2(0.7, 0.1)
    v1_rot_90 = rotate(v1, math.radians(90))
    v1_rot_n90 = rotate(v1, math.radians(-90))
    v1_rot_n135 = rotate(v1, math.radians(-135))
    npt.assert_almost_equal(v1_rot_90.x, -0.1)
    npt.assert_almost_equal(v1_rot_90.y, 0.7)
    npt.assert_almost_equal(v1_rot_n90.x, 0.1)
    npt.assert_almost_equal(v1_rot_n90.y, -0.7)
    npt.assert_almost_equal(v1_rot_n135.x, -0.424, decimal=3)
    npt.assert_almost_equal(v1_rot_n135.y, -0.565, decimal=3)

    v2 = Vector2(-1.4, 0.6)
    v2_rot_90 = rotate(v2, math.radians(90))
    v2_rot_n90 = rotate(v2, math.radians(-90))
    v2_rot_n135 = rotate(v2, math.radians(-135))
    npt.assert_almost_equal(v2_rot_90.x, -0.6)
    npt.assert_almost_equal(v2_rot_90.y, -1.4)
    npt.assert_almost_equal(v2_rot_n90.x, 0.6)
    npt.assert_almost_equal(v2_rot_n90.y, 1.4)
    npt.assert_almost_equal(v2_rot_n135.x, 1.414, decimal=3)
    npt.assert_almost_equal(v2_rot_n135.y, 0.565, decimal=3)
Example #27
0
def test_velocity(attached_component, freebody_component):
    attached_component.set_parent(freebody_component)
    freebody_component.velocity = Vector2(20, 10)
    assert (attached_component.velocity == Vector2(20, 10))
    freebody_component.velocity = Vector2(-5, 0)
    assert (attached_component.velocity == Vector2(-5, 0))
    freebody_component.velocity = Vector2(-15, -20)
    assert (attached_component.velocity == Vector2(-15, -20))
Example #28
0
    def force_and_moment_at_component_origin(self):
        force = Vector2(0, 0)
        moment = 0.0

        _force, _moment = self.force_and_moment_from_external_forces()
        force += _force
        moment += _moment

        _moment = self.moment_from_external_moments()
        moment += _moment

        _force, _moment = self.force_and_moment_from_children()
        force += _force
        moment += _moment

        return force, moment
Example #29
0
def test_position(freebody_component, attached_component):
    attached_component.set_parent(freebody_component)
    freebody_component.angle = math.radians(0)
    freebody_component.position = Vector2(0, 0)
    assert (attached_component.position == Vector2(-0.4, 0.1))
    freebody_component.angle = math.radians(2)
    freebody_component.position = Vector2(-0.5, 0.2)
    assert (attached_component.position == Vector2(-0.9032462804778885,
                                                   0.2859792840209092))
    freebody_component.angle = math.radians(-2)
    freebody_component.position = Vector2(0.3, -0.5)
    assert (attached_component.position == Vector2(-0.09626638113738828,
                                                   -0.38610111861709))
Example #30
0
 def aerodynamic_center(self):
     return Vector2(-0.25 * self.mean_aerodynamic_chord, 0)