Skip to content

Commit d36947c

Browse files
Merge pull request #408 from RocketPy-Team/tst/flight-class-protection
TST: new set of tests to the Flight class
2 parents 46725b9 + 81118ea commit d36947c

File tree

2 files changed

+363
-0
lines changed

2 files changed

+363
-0
lines changed

tests/conftest.py

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,43 @@ def calisto(calisto_motorless, cesaroni_m1670): # old name: rocket
157157
return calisto
158158

159159

160+
@pytest.fixture
161+
def calisto_nose_to_tail(cesaroni_m1670):
162+
"""Create a simple object of the Rocket class to be used in the tests. This
163+
is the same as the calisto fixture, but with the coordinate system
164+
orientation set to "nose_to_tail" instead of "tail_to_nose". This allows to
165+
check if the coordinate system orientation is being handled correctly in
166+
the code.
167+
168+
Parameters
169+
----------
170+
cesaroni_m1670 : rocketpy.SolidMotor
171+
An object of the SolidMotor class. This is a pytest fixture too.
172+
173+
Returns
174+
-------
175+
rocketpy.Rocket
176+
The Calisto rocket with the coordinate system orientation set to
177+
"nose_to_tail". Rail buttons are already set, as well as the motor.
178+
"""
179+
calisto = Rocket(
180+
radius=0.0635,
181+
mass=14.426,
182+
inertia=(6.321, 6.321, 0.034),
183+
power_off_drag="data/calisto/powerOffDragCurve.csv",
184+
power_on_drag="data/calisto/powerOnDragCurve.csv",
185+
center_of_mass_without_motor=0,
186+
coordinate_system_orientation="nose_to_tail",
187+
)
188+
calisto.add_motor(cesaroni_m1670, position=1.373)
189+
calisto.set_rail_buttons(
190+
upper_button_position=-0.082,
191+
lower_button_position=0.618,
192+
angular_position=45,
193+
)
194+
return calisto
195+
196+
160197
@pytest.fixture
161198
def calisto_liquid_modded(calisto_motorless, liquid_motor):
162199
"""Create a simple object of the Rocket class to be used in the tests. This
@@ -735,6 +772,35 @@ def flight_calisto(calisto, example_env): # old name: flight
735772
)
736773

737774

775+
@pytest.fixture
776+
def flight_calisto_nose_to_tail(calisto_nose_to_tail, example_env):
777+
"""A rocketpy.Flight object of the Calisto rocket. This uses the calisto
778+
with "nose_to_tail" coordinate system orientation, just as described in the
779+
calisto_nose_to_tail fixture.
780+
781+
Parameters
782+
----------
783+
calisto_nose_to_tail : rocketpy.Rocket
784+
An object of the Rocket class. This is a pytest fixture too.
785+
example_env : rocketpy.Environment
786+
An object of the Environment class. This is a pytest fixture too.
787+
788+
Returns
789+
-------
790+
rocketpy.Flight
791+
The Calisto rocket with the coordinate system orientation set to
792+
"nose_to_tail".
793+
"""
794+
return Flight(
795+
environment=example_env,
796+
rocket=calisto_nose_to_tail,
797+
rail_length=5.2,
798+
inclination=85,
799+
heading=0,
800+
terminate_on_apogee=False,
801+
)
802+
803+
738804
@pytest.fixture
739805
def flight_calisto_robust(calisto_robust, example_env_robust):
740806
"""A rocketpy.Flight object of the Calisto rocket. This uses the calisto
@@ -767,6 +833,42 @@ def flight_calisto_robust(calisto_robust, example_env_robust):
767833
)
768834

769835

836+
@pytest.fixture
837+
def flight_calisto_custom_wind(calisto_robust, example_env_robust):
838+
"""A rocketpy.Flight object of the Calisto rocket. This uses the calisto
839+
with the aerodynamic surfaces and parachutes. The environment is a bit more
840+
complex than the one in the flight_calisto_robust fixture. Now the wind is
841+
set to 5m/s (x direction) and 2m/s (y direction), constant with altitude.
842+
843+
Parameters
844+
----------
845+
calisto_robust : rocketpy.Rocket
846+
An object of the Rocket class. This is a pytest fixture too.
847+
example_env_robust : rocketpy.Environment
848+
An object of the Environment class. This is a pytest fixture too.
849+
850+
Returns
851+
-------
852+
rocketpy.Flight
853+
854+
"""
855+
env = example_env_robust
856+
env.set_atmospheric_model(
857+
type="custom_atmosphere",
858+
temperature=300,
859+
wind_u=[(0, 5), (4000, 5)],
860+
wind_v=[(0, 2), (4000, 2)],
861+
)
862+
return Flight(
863+
environment=env,
864+
rocket=calisto_robust,
865+
rail_length=5.2,
866+
inclination=85,
867+
heading=0,
868+
terminate_on_apogee=False,
869+
)
870+
871+
770872
## Dimensionless motors and rockets
771873

772874

tests/test_flight.py

Lines changed: 261 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ def compute_static_margin_error_given_distance(position, static_margin, rocket):
7979
return rocket
8080

8181

82+
# Tests
83+
84+
8285
@patch("matplotlib.pyplot.show")
8386
def test_all_info(mock_show, flight_calisto_robust):
8487
"""Test that the flight class is working as intended. This basically calls
@@ -656,3 +659,261 @@ def test_hybrid_motor_flight(mock_show, calisto_hybrid_modded):
656659
)
657660

658661
assert test_flight.all_info() == None
662+
663+
664+
def test_surface_wind(flight_calisto_custom_wind):
665+
"""Tests the surface wind of the flight simulation. The expected values
666+
are provided by the definition of the 'light_calisto_custom_wind' fixture.
667+
If the fixture changes, this test must be updated.
668+
669+
Parameters
670+
----------
671+
flight_calisto_custom_wind : rocketpy.Flight
672+
Flight object to be tested. See the conftest.py file for more info
673+
regarding this pytest fixture.
674+
"""
675+
test = flight_calisto_custom_wind
676+
atol = 1e-8
677+
assert pytest.approx(2.0, abs=atol) == test.frontal_surface_wind
678+
assert pytest.approx(-5.0, abs=atol) == test.lateral_surface_wind
679+
680+
681+
def test_effective_rail_length(flight_calisto_robust, flight_calisto_nose_to_tail):
682+
"""Tests the effective rail length of the flight simulation. The expected
683+
values are calculated by hand, and should be valid as long as the rail
684+
length and the position of the buttons and nozzle do not change in the
685+
fixtures. If the fixtures change, this test must be updated. It is important
686+
to keep
687+
688+
Parameters
689+
----------
690+
flight_calisto_robust : rocketpy.Flight
691+
Flight object to be tested. See the conftest.py file for more info
692+
regarding this pytest fixture.
693+
flight_calisto_nose_to_tail : rocketpy.Flight
694+
Flight object to be tested. The difference here is that the rocket is
695+
defined with the "nose_to_tail" orientation instead of the
696+
"tail_to_nose" orientation. See the conftest.py file for more info
697+
regarding this pytest fixture.
698+
"""
699+
test1 = flight_calisto_robust
700+
test2 = flight_calisto_nose_to_tail
701+
atol = 1e-8
702+
703+
rail_length = 5.2
704+
upper_button_position = 0.082
705+
lower_button_position = -0.618
706+
nozzle_position = -1.373
707+
708+
effective_1rl = rail_length - abs(upper_button_position - nozzle_position)
709+
effective_2rl = rail_length - abs(lower_button_position - nozzle_position)
710+
711+
# test 1: Rocket with "tail_to_nose" orientation
712+
assert pytest.approx(test1.effective_1rl, abs=atol) == effective_1rl
713+
assert pytest.approx(test1.effective_2rl, abs=atol) == effective_2rl
714+
# test 2: Rocket with "nose_to_tail" orientation
715+
assert pytest.approx(test2.effective_1rl, abs=atol) == effective_1rl
716+
assert pytest.approx(test2.effective_2rl, abs=atol) == effective_2rl
717+
718+
719+
def test_max_values(flight_calisto_robust):
720+
"""Test the max values of the flight. This tests if the max values are
721+
close to the expected values. However, the expected values were NOT
722+
calculated by hand, it was just copied from the test results. This is
723+
because the expected values are not easy to calculate by hand, and the
724+
results are not expected to change. If the results change, the test will
725+
fail, and the expected values must be updated. If if want to update the
726+
values, always double check if the results are really correct. Acceptable
727+
reasons for changes in the results are: 1) changes in the code that
728+
improve the accuracy of the simulation, 2) a bug was found and fixed. Keep
729+
in mind that other tests may be more accurate than this one, for example,
730+
the acceptance tests, which are based on the results of real flights.
731+
732+
Parameters
733+
----------
734+
flight_calisto_robust : rocketpy.Flight
735+
Flight object to be tested. See the conftest.py file for more info
736+
regarding this pytest fixture.
737+
"""
738+
test = flight_calisto_robust
739+
atol = 5e-3
740+
assert pytest.approx(105.2774, abs=atol) == test.max_acceleration_power_on
741+
assert pytest.approx(105.2774, abs=atol) == test.max_acceleration
742+
assert pytest.approx(0.85999, abs=atol) == test.max_mach_number
743+
assert pytest.approx(285.90240, abs=atol) == test.max_speed
744+
745+
746+
def test_rail_buttons_forces(flight_calisto_custom_wind):
747+
"""Test the rail buttons forces. This tests if the rail buttons forces are
748+
close to the expected values. However, the expected values were NOT
749+
calculated by hand, it was just copied from the test results. The results
750+
are not expected to change, unless the code is changed for bug fixes or
751+
accuracy improvements.
752+
753+
Parameters
754+
----------
755+
flight_calisto_custom_wind : rocketpy.Flight
756+
Flight object to be tested. See the conftest.py file for more info
757+
regarding this pytest fixture.
758+
"""
759+
test = flight_calisto_custom_wind
760+
atol = 5e-3
761+
assert pytest.approx(3.80358, abs=atol) == test.max_rail_button1_normal_force
762+
assert pytest.approx(1.63602, abs=atol) == test.max_rail_button1_shear_force
763+
assert pytest.approx(1.19353, abs=atol) == test.max_rail_button2_normal_force
764+
assert pytest.approx(0.51337, abs=atol) == test.max_rail_button2_shear_force
765+
766+
767+
@pytest.mark.parametrize(
768+
"flight_time, expected_values",
769+
[
770+
("t_initial", (0, 0, 0)),
771+
("out_of_rail_time", (0, 7.8068, 89.2325)),
772+
("apogee_time", (0.07534, -0.058127, -9.614386)),
773+
("t_final", (0, 0, 0.0017346294117130806)),
774+
],
775+
)
776+
def test_accelerations(flight_calisto_custom_wind, flight_time, expected_values):
777+
"""Tests if the acceleration in some particular points of the trajectory is
778+
correct. The expected values were NOT calculated by hand, it was just
779+
copied from the test results. The results are not expected to change,
780+
unless the code is changed for bug fixes or accuracy improvements.
781+
782+
Parameters
783+
----------
784+
flight_calisto_custom_wind : rocketpy.Flight
785+
Flight object to be tested. See the conftest.py file for more info.
786+
flight_time : str
787+
The name of the attribute of the flight object that contains the time
788+
of the point to be tested.
789+
expected_values : tuple
790+
The expected values of the acceleration vector at the point to be
791+
tested.
792+
"""
793+
expected_attr, expected_acc = flight_time, expected_values
794+
795+
test = flight_calisto_custom_wind
796+
t = getattr(test, expected_attr)
797+
atol = 5e-3
798+
799+
assert pytest.approx(expected_acc, abs=atol) == (
800+
test.ax(t),
801+
test.ay(t),
802+
test.az(t),
803+
), f"Assertion error for acceleration vector at {expected_attr}."
804+
805+
806+
@pytest.mark.parametrize(
807+
"flight_time, expected_values",
808+
[
809+
("t_initial", (0, 0, 0)),
810+
("out_of_rail_time", (0, 2.248727, 25.703072)),
811+
("apogee_time", (-13.209436, 16.05115, -0.000257)),
812+
("t_final", (5, 2, -5.334289)),
813+
],
814+
)
815+
def test_velocities(flight_calisto_custom_wind, flight_time, expected_values):
816+
"""Tests if the velocity in some particular points of the trajectory is
817+
correct. The expected values were NOT calculated by hand, it was just
818+
copied from the test results. The results are not expected to change,
819+
unless the code is changed for bug fixes or accuracy improvements.
820+
821+
Parameters
822+
----------
823+
flight_calisto_custom_wind : rocketpy.Flight
824+
Flight object to be tested. See the conftest.py file for more info.
825+
flight_time : str
826+
The name of the attribute of the flight object that contains the time
827+
of the point to be tested.
828+
expected_values : tuple
829+
The expected values of the velocity vector at the point to be tested.
830+
"""
831+
expected_attr, expected_vel = flight_time, expected_values
832+
833+
test = flight_calisto_custom_wind
834+
t = getattr(test, expected_attr)
835+
atol = 5e-3
836+
837+
assert pytest.approx(expected_vel, abs=atol) == (
838+
test.vx(t),
839+
test.vy(t),
840+
test.vz(t),
841+
), f"Assertion error for velocity vector at {expected_attr}."
842+
843+
844+
@pytest.mark.parametrize(
845+
"flight_time, expected_values",
846+
[
847+
("t_initial", (1.6542528, 0.65918, -0.067107)),
848+
("out_of_rail_time", (5.05334, 2.01364, -1.7541)),
849+
("apogee_time", (2.35291, -1.8275, -0.87851)),
850+
("t_final", (0, 0, 141.42421)),
851+
],
852+
)
853+
def test_aerodynamic_forces(flight_calisto_custom_wind, flight_time, expected_values):
854+
"""Tests if the aerodynamic forces in some particular points of the
855+
trajectory is correct. The expected values were NOT calculated by hand, it
856+
was just copied from the test results. The results are not expected to
857+
change, unless the code is changed for bug fixes or accuracy improvements.
858+
859+
Parameters
860+
----------
861+
flight_calisto_custom_wind : rocketpy.Flight
862+
Flight object to be tested. See the conftest.py file for more info.
863+
flight_time : str
864+
The name of the attribute of the flight object that contains the time
865+
of the point to be tested.
866+
expected_values : tuple
867+
The expected values of the aerodynamic forces vector at the point to be
868+
tested.
869+
"""
870+
expected_attr, expected_R = flight_time, expected_values
871+
872+
test = flight_calisto_custom_wind
873+
t = getattr(test, expected_attr)
874+
atol = 5e-3
875+
876+
assert pytest.approx(expected_R, abs=atol) == (
877+
test.R1(t),
878+
test.R2(t),
879+
test.R3(t),
880+
), f"Assertion error for aerodynamic forces vector at {expected_attr}."
881+
882+
883+
@pytest.mark.parametrize(
884+
"flight_time, expected_values",
885+
[
886+
("t_initial", (0.17179073815516033, -0.431117, 0)),
887+
("out_of_rail_time", (0.547026, -1.3727895, 0)),
888+
("apogee_time", (-0.5874848151271623, -0.7563596, 0)),
889+
("t_final", (0, 0, 0)),
890+
],
891+
)
892+
def test_aerodynamic_moments(flight_calisto_custom_wind, flight_time, expected_values):
893+
"""Tests if the aerodynamic moments in some particular points of the
894+
trajectory is correct. The expected values were NOT calculated by hand, it
895+
was just copied from the test results. The results are not expected to
896+
change, unless the code is changed for bug fixes or accuracy improvements.
897+
898+
Parameters
899+
----------
900+
flight_calisto_custom_wind : rocketpy.Flight
901+
Flight object to be tested. See the conftest.py file for more info.
902+
flight_time : str
903+
The name of the attribute of the flight object that contains the time
904+
of the point to be tested.
905+
expected_values : tuple
906+
The expected values of the aerodynamic moments vector at the point to
907+
be tested.
908+
"""
909+
expected_attr, expected_M = flight_time, expected_values
910+
911+
test = flight_calisto_custom_wind
912+
t = getattr(test, expected_attr)
913+
atol = 5e-3
914+
915+
assert pytest.approx(expected_M, abs=atol) == (
916+
test.M1(t),
917+
test.M2(t),
918+
test.M3(t),
919+
), f"Assertion error for moment vector at {expected_attr}."

0 commit comments

Comments
 (0)