def test_elevator_deflection(): control_input = ControlInput() elevator_deflection = 0.2 control_input.elevator_deflection = elevator_deflection assert control_input.elevator_deflection == pytest.approx( elevator_deflection) assert np.allclose(control_input.control_input, [elevator_deflection, 0.0, 0.0, 0.0])
def test_dynamics_forces(): control_input = ControlInput() prop = SimpleTestAircraftNoMoments(control_input) t = 0 for i in range(-50, 101, 50): control_input.throttle = 0.8 control_input.elevator_deflection = i control_input.aileron_deflection = i control_input.rudder_deflection = i state = State() state.vx = 20.0 state.vy = 1 state.vz = 0 params = {"prop": prop, "wind": no_wind()} update = dynamics_kinetmatics_update(t=t, x=state.state, u=control_input.control_input, params=params) V_a = np.sqrt(np.sum(calc_airspeed(state, params['wind'].get(0.0))**2)) forces_aero_wind_frame = np.array([ -np.abs(control_input.elevator_deflection), control_input.aileron_deflection, -control_input.rudder_deflection ]) forces_aero_body_frame = wind2body(forces_aero_wind_frame, state, params['wind'].get(0)) force_propulsion = np.array([(2 * control_input.throttle)**2 - V_a**2, 0, 0]) force_gravity = inertial2body( np.array([0, 0, prop.mass() * GRAVITY_CONST]), state) forces_body = forces_aero_body_frame + force_propulsion + force_gravity vx_update_expect = (1 / prop.mass()) * forces_body[0] vy_update_expect = (1 / prop.mass()) * forces_body[1] vz_update_expect = (1 / prop.mass()) * forces_body[2] # No moments ang_rate_x_update_expect = 0 ang_rate_y_update_expect = 0 ang_rate_z_update_expect = 0 assert np.allclose(vx_update_expect, update[6]) assert np.allclose(vy_update_expect, update[7]) assert np.allclose(vz_update_expect, update[8]) assert np.allclose(ang_rate_x_update_expect, update[9]) assert np.allclose(ang_rate_y_update_expect, update[10]) assert np.allclose(ang_rate_z_update_expect, update[11])
def test_dynamics_moments(): control_input = ControlInput() t = 0 for i in range(-50, 51, 50): control_input.throttle = i control_input.elevator_deflection = i control_input.aileron_deflection = i control_input.rudder_deflection = i prop = SimpleTestAircraftNoForces(control_input) state = State() state.vx = 20.0 state.vy = 1 state.vz = 0 state.ang_rate_x = 0.157079633 state.ang_rate_y = 0.157079633 state.ang_rate_z = 0.157079633 params = {"prop": prop, "wind": no_wind()} update = dynamics_kinetmatics_update(t=t, x=state.state, u=control_input.control_input, params=params) moments_aero = np.array([ control_input.elevator_deflection, control_input.aileron_deflection, control_input.rudder_deflection ]) omega = np.array( [state.ang_rate_x, state.ang_rate_y, state.ang_rate_z]) coreolis_term = prop.inv_inertia_matrix().dot( np.cross(omega, prop.inertia_matrix().dot(omega))) ang_rate_x_update_expect = (2 / 3) * moments_aero[0] - ( 1 / 3) * moments_aero[2] - coreolis_term[0] ang_rate_y_update_expect = (1 / 2) * moments_aero[1] - coreolis_term[1] ang_rate_z_update_expect = (2 / 3) * moments_aero[2] - ( 1 / 3) * moments_aero[0] - coreolis_term[2] assert np.allclose(ang_rate_x_update_expect, update[9]) assert np.allclose(ang_rate_y_update_expect, update[10]) assert np.allclose(ang_rate_z_update_expect, update[11])
def drag_coeff_test_cases(): state1 = State() state1.vx = 20.0 state1.vz = 0.0 wind1 = np.zeros(6) wind2 = np.zeros(6) wind2[0] = 1.0 wind2[2] = -19.0 * np.tan(6 * np.pi / 180.0) zero_input = ControlInput() elevator_input = ControlInput() elevator_input.elevator_deflection = 2.0 * np.pi / 180.0 return [(state1, wind1, 0.0, zero_input, 0.015039166436721), (state1, wind1, 1.0, zero_input, 0.043224285541117), (state1, wind2, 0.0, zero_input, 0.027939336576642), (state1, wind2, 1.0, zero_input, 0.082879203470842), (state1, wind1, 0.0, elevator_input, 0.015039166436721 + 0.0633 * elevator_input.elevator_deflection), (state1, wind1, 1.0, elevator_input, 0.043224285541117 + 0.0633 * elevator_input.elevator_deflection)]
def pitch_moment_coeff_test_cases(): state1 = State() state1.vx = 20.0 state1.vz = 0.0 wind1 = np.zeros(6) wind2 = np.zeros(6) wind2[0] = 1.0 wind2[2] = -19.0 * np.tan(6 * np.pi / 180.0) zero_input = ControlInput() elevator_input = ControlInput() elevator_input.elevator_deflection = 2.0 * np.pi / 180.0 return [(state1, wind1, 0.0, zero_input, 0.001161535578433), (state1, wind1, 1.0, zero_input, -0.004297270367523), (state1, wind2, 0.0, zero_input, -0.064477317568596), (state1, wind2, 1.0, zero_input, -0.01808304889307), (state1, wind1, 0.0, elevator_input, 0.001161535578433 - 0.206 * elevator_input.elevator_deflection), (state1, wind1, 1.0, elevator_input, -0.004297270367523 - 0.206 * elevator_input.elevator_deflection)]
def lift_coeff_test_cases(): constants = SkywalkerX8Constants() c = constants.mean_chord state1 = State() state1.vx = 20.0 state1.vz = 0.0 state2 = State() state2.vx = 20.0 state2.vz = 0.0 state2.ang_rate_y = 5 * np.pi / 180 wind1 = np.zeros(6) wind2 = np.zeros(6) wind3 = np.zeros(6) wind2[0] = 1.0 wind2[2] = -19.0 * np.tan(8 * np.pi / 180.0) wind3[0] = 1.0 wind3[2] = -19.0 * np.tan(8 * np.pi / 180.0) wind3[4] = 3 * np.pi / 180 ang_rate_y2 = state2.ang_rate_y - wind3[4] airspeed2 = np.sqrt(np.sum(calc_airspeed(state2, wind2)**2)) zero_input = ControlInput() elevator_input = ControlInput() elevator_input.elevator_deflection = 2.0 * np.pi / 180.0 return [(state1, wind1, 0.0, zero_input, 0.030075562375465), (state1, wind1, 1.0, zero_input, 0.018798581619545), (state1, wind2, 0.0, zero_input, 0.609296679062686), (state1, wind2, 1.0, zero_input, 0.454153721254944), (state1, wind1, 0.0, elevator_input, 0.030075562375465 + 0.278 * elevator_input.elevator_deflection), (state1, wind1, 1.0, elevator_input, 0.018798581619545 + 0.278 * elevator_input.elevator_deflection), (state2, wind3, 0.0, elevator_input, 0.609296679062686 + 4.60 * c / (2 * airspeed2) * ang_rate_y2 + 0.278 * elevator_input.elevator_deflection), (state2, wind3, 1.0, elevator_input, 0.454153721254944 - 3.51 * c / (2 * airspeed2) * ang_rate_y2 + 0.278 * elevator_input.elevator_deflection)]