Skip to content

Commit 0cb0994

Browse files
kevin-alcanizGui-FernandesBRMateusStanoMateusStano
authored andcommitted
ENH: Add the Coriolis Force to the Flight class (RocketPy-Team#799)
* wind factor bug corrected the wind factor wasn't applied to the env.wind_velocity properties * BUG: StochasticModel visualize attributes of a uniform distribution It showed the nominal and the standard deviation values and it doesn't make sense in a uniform distribution. In a np.random.uniform the 'nominal value' is the lower bound of the distribution, and the 'standard deviation' value is the upper bound. Now, a new condition has been added for the uniform distributions where the mean and semi range are calculated and showed. This way the visualize_attribute function will show the whole range where the random values are uniformly taken in * variable names corrections * Corrections requested by the pylint test * ENH: add multiplication for 2D functions in rocketpy.function Added the ability to multiply functions with 2D domains in the __mul__ function * ENH: StochasticAirBrakes class created The StochasticAirBrakes class has been created. The __init__.py files in the stochastic and rocketpy folders have also been modified accordingly to incorporate this new class * ENH: set_air_brakes function created This functions appends an airbrake and controller objects previuosly created to the rocket * ENH: add StochasticAirBrake to rocketpy.stochastic_rocket Some functions has been modified and other has been created in order to include the new StochasticAirBrakes feature into the StochasticRocket class. A new function named 'add_air_brakes' has been created to append a StochasticAirBrakes and Controller objects to the StochasticRocket object. A new function '_create_air_brake' has been introduced to create a sample of an AirBrake object through a StochasticAirBrake object. Enventually, the 'create_object' function has been modified to add the sampled AirBrakes to the sampled Rocket * BUG: StochasticAirBrake object input in _Controller When defining the _Controller object a StochasticAirBrake was input. This is already corrected and a AirBrake object is now introduced * ENH: add time_overshoot option to rocketpy.stochastic_flight Since the new StochasticAirBrake class is defined, we need the 'time_overshoot' option in the Flight class to ensure that the time step defined in the simulation is the controller sampling rate. The MonteCarlo class has had to be modified as well to include this option. * DOC: StochasticAirBrakes related documentation added Documentation related to the StochasticAirBrakes implementation has been added in StochasticAirBrakes, StochasticRocket and Rocket classes. * ENH: pylint recommendations done * ENH: Reformatted files to pass Ruff linting checks * ENH: Update rocketpy/stochastic/stochastic_rocket.py Unnecessary comment Co-authored-by: Gui-FernandesBR <63590233+Gui-FernandesBR@users.noreply.github.com> * ENH: more intuitive uniform distribution display in StochasticModel Co-authored-by: MateusStano <69485049+MateusStano@users.noreply.github.com> * DOC: improve drag curve factor definition in StochasticAirBrakes * ENH: Change assert statement to if Co-authored-by: Gui-FernandesBR <63590233+Gui-FernandesBR@users.noreply.github.com> * DOC: better explanation of __mul__ function Co-authored-by: MateusStano <69485049+MateusStano@users.noreply.github.com> * ENH: delete set_air_brakes function for simplicity * ENH: inertial foreces added to u_dot_generalized * ENH: define Earth's angular velocity vector in Environment * ENH: some corrections to the Flight class * ENH: modifications in the Flight class * DOC: improving Environment documentation * DOC: more improvements in the Environment class * ENH: format changes done * DOC: env.earth_rotation_vector improved Co-authored-by: Gui-FernandesBR <63590233+Gui-FernandesBR@users.noreply.github.com> * ENH: Coriolis acceleration added to u_dot * BUG: print left * ENH: ruff changes * ENH: CHANGELOG updated * ENH: remove unecessary frame rotation * ENH: remove rotation from solid prop udot * ENH: add coriolis to parachute * TST: fix tests values * MNT: remove debug functions * DEV: changelog --------- Co-authored-by: Gui-FernandesBR <63590233+Gui-FernandesBR@users.noreply.github.com> Co-authored-by: MateusStano <69485049+MateusStano@users.noreply.github.com> Co-authored-by: MateusStano <go34lap@mytum.de> Co-authored-by: MateusStano <mateusstano@usp.br>
1 parent 70f24ee commit 0cb0994

5 files changed

Lines changed: 65 additions & 24 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,11 @@ Attention: The newest changes should be on top -->
3232

3333
### Added
3434

35+
- ENH: Add the Coriolis Force to the Flight class [#799](https://github.com/RocketPy-Team/RocketPy/pull/799)
3536

3637
### Changed
3738

3839
- ENH: _MotorPrints inheritance - issue #460 [#828](https://github.com/RocketPy-Team/RocketPy/pull/828)
39-
4040
- MNT: fix deprecations and warnings [#829](https://github.com/RocketPy-Team/RocketPy/pull/829)
4141

4242
### Fixed

rocketpy/environment/environment.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,8 @@ class Environment:
247247
Number of ensemble members. Only defined when using Ensembles.
248248
Environment.ensemble_member : int
249249
Current selected ensemble member. Only defined when using Ensembles.
250+
Environment.earth_rotation_vector : list[float]
251+
Earth's angular velocity vector in the Flight Coordinate System.
250252
251253
Notes
252254
-----
@@ -352,6 +354,7 @@ def __init__(
352354
self.set_location(latitude, longitude)
353355
self.__initialize_earth_geometry(datum)
354356
self.__initialize_utm_coordinates()
357+
self.__set_earth_rotation_vector()
355358

356359
# Set the gravity model
357360
self.gravity = self.set_gravity_model(gravity)
@@ -583,6 +586,23 @@ def __reset_wind_direction_function(self):
583586
self.wind_direction.set_outputs("Wind Direction (Deg True)")
584587
self.wind_direction.set_title("Wind Direction Profile")
585588

589+
def __set_earth_rotation_vector(self):
590+
"""Calculates and stores the Earth's angular velocity vector in the Flight
591+
Coordinate System, which is essential for evaluating inertial forces.
592+
"""
593+
# Sidereal day
594+
T = 86164.1 # seconds
595+
596+
# Earth's angular velocity magnitude
597+
w_earth = 2 * np.pi / T
598+
599+
# Vector in the Flight Coordinate System
600+
lat = np.radians(self.latitude)
601+
w_local = [0, w_earth * np.cos(lat), w_earth * np.sin(lat)]
602+
603+
# Store the attribute
604+
self.earth_rotation_vector = w_local
605+
586606
# Validators (used to verify an attribute is being set correctly.)
587607

588608
def __validate_dictionary(self, file, dictionary):

rocketpy/simulation/flight.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1579,6 +1579,12 @@ def u_dot(self, t, u, post_processing=False): # pylint: disable=too-many-locals
15791579
ax, ay, az = K @ Vector(L)
15801580
az -= self.env.gravity.get_value_opt(z) # Include gravity
15811581

1582+
# Coriolis acceleration
1583+
_, w_earth_y, w_earth_z = self.env.earth_rotation_vector
1584+
ax -= 2 * (vz * w_earth_y - vy * w_earth_z)
1585+
ay -= 2 * (vx * w_earth_z)
1586+
az -= 2 * (-vx * w_earth_y)
1587+
15821588
# Create u_dot
15831589
u_dot = [
15841590
vx,
@@ -1767,7 +1773,7 @@ def u_dot_generalized(self, t, u, post_processing=False): # pylint: disable=too
17671773
_, _, z, vx, vy, vz, e0, e1, e2, e3, omega1, omega2, omega3 = u
17681774

17691775
# Create necessary vectors
1770-
# r = Vector([x, y, z]) # CDM position vector
1776+
# r = Vector([x, y, z]) # CDM position vector
17711777
v = Vector([vx, vy, vz]) # CDM velocity vector
17721778
e = [e0, e1, e2, e3] # Euler parameters/quaternions
17731779
w = Vector([omega1, omega2, omega3]) # Angular velocity vector
@@ -1926,9 +1932,6 @@ def u_dot_generalized(self, t, u, post_processing=False): # pylint: disable=too
19261932
# Angular velocity derivative
19271933
w_dot = I_CM.inverse @ (T21 + (T20 ^ r_CM))
19281934

1929-
# Velocity vector derivative
1930-
v_dot = K @ (T20 / total_mass - (r_CM ^ w_dot))
1931-
19321935
# Euler parameters derivative
19331936
e_dot = [
19341937
0.5 * (-omega1 * e1 - omega2 * e2 - omega3 * e3),
@@ -1937,6 +1940,10 @@ def u_dot_generalized(self, t, u, post_processing=False): # pylint: disable=too
19371940
0.5 * (omega3 * e0 + omega2 * e1 - omega1 * e2),
19381941
]
19391942

1943+
# Velocity vector derivative + Coriolis acceleration
1944+
w_earth = Vector(self.env.earth_rotation_vector)
1945+
v_dot = K @ (T20 / total_mass - (r_CM ^ w_dot)) - 2 * (w_earth ^ v)
1946+
19401947
# Position vector derivative
19411948
r_dot = [vx, vy, vz]
19421949

@@ -2016,6 +2023,12 @@ def u_dot_parachute(self, t, u, post_processing=False):
20162023
ay = Dy / (mp + ma)
20172024
az = (Dz - 9.8 * mp) / (mp + ma)
20182025

2026+
# Add coriolis acceleration
2027+
_, w_earth_y, w_earth_z = self.env.earth_rotation_vector
2028+
ax -= 2 * (vz * w_earth_y - vy * w_earth_z)
2029+
ay -= 2 * (vx * w_earth_z)
2030+
az -= 2 * (-vx * w_earth_y)
2031+
20192032
if post_processing:
20202033
self.__post_processed_variables.append(
20212034
[t, ax, ay, az, 0, 0, 0, Dx, Dy, Dz, 0, 0, 0, 0]

tests/integration/test_flight.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -491,8 +491,9 @@ def test_empty_motor_flight(mock_show, example_plain_env, calisto_motorless): #
491491

492492
def test_freestream_speed_at_apogee(example_plain_env, calisto):
493493
"""
494-
Asserts that a rocket at apogee has a free stream speed of 0.0 m/s in all
495-
directions given that the environment doesn't have any wind.
494+
Asserts that a rocket at apogee has a free stream speed of near 0.0 m/s
495+
in all directions given that the environment doesn't have any wind. Any
496+
speed values comes from coriolis effect.
496497
"""
497498
# NOTE: this rocket doesn't move in x or z direction. There's no wind.
498499
hard_atol = 1e-12
@@ -508,7 +509,9 @@ def test_freestream_speed_at_apogee(example_plain_env, calisto):
508509
)
509510

510511
assert np.isclose(
511-
test_flight.stream_velocity_x(test_flight.apogee_time), 0.0, atol=hard_atol
512+
test_flight.stream_velocity_x(test_flight.apogee_time),
513+
0.4641492104717301,
514+
atol=hard_atol,
512515
)
513516
assert np.isclose(
514517
test_flight.stream_velocity_y(test_flight.apogee_time), 0.0, atol=hard_atol
@@ -518,9 +521,13 @@ def test_freestream_speed_at_apogee(example_plain_env, calisto):
518521
test_flight.stream_velocity_z(test_flight.apogee_time), 0.0, atol=soft_atol
519522
)
520523
assert np.isclose(
521-
test_flight.free_stream_speed(test_flight.apogee_time), 0.0, atol=soft_atol
524+
test_flight.free_stream_speed(test_flight.apogee_time),
525+
0.4641492104717798,
526+
atol=hard_atol,
527+
)
528+
assert np.isclose(
529+
test_flight.apogee_freestream_speed, 0.4641492104717798, atol=hard_atol
522530
)
523-
assert np.isclose(test_flight.apogee_freestream_speed, 0.0, atol=soft_atol)
524531

525532

526533
def test_rocket_csys_equivalence(
@@ -546,6 +553,7 @@ def test_rocket_csys_equivalence(
546553
assert np.isclose(
547554
flight_calisto_robust.x_impact,
548555
flight_calisto_nose_to_tail_robust.x_impact,
556+
atol=1e-3,
549557
)
550558
assert np.isclose(
551559
flight_calisto_robust.y_impact,

tests/unit/test_flight.py

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -109,15 +109,15 @@ def test_get_solution_at_time(flight_calisto):
109109
flight_calisto.get_solution_at_time(flight_calisto.t_final),
110110
np.array(
111111
[
112-
48.4313533,
113-
0.0,
114-
985.7665845,
115-
-0.00000229951048,
116-
0.0,
117-
11.2223284,
118-
-341.028803,
119-
0.999048222,
120-
-0.0436193874,
112+
48.43719482805657,
113+
-14.836008075478597,
114+
985.9858934483618,
115+
-3.4415459237894554e-05,
116+
0.0007572309307800201,
117+
11.21695000766671,
118+
-341.1460775169661,
119+
0.9990482215818578,
120+
-0.043619387365336,
121121
0.0,
122122
0.0,
123123
0.0,
@@ -212,7 +212,7 @@ def test_export_sensor_data(flight_calisto_with_sensors):
212212
[
213213
("t_initial", (0.25886, -0.649623, 0)),
214214
("out_of_rail_time", (0.792028, -1.987634, 0)),
215-
("apogee_time", (-0.522875, -0.741825, 0)),
215+
("apogee_time", (-0.509420, -0.732933, -2.089120e-14)),
216216
("t_final", (0, 0, 0)),
217217
],
218218
)
@@ -251,8 +251,8 @@ def test_aerodynamic_moments(flight_calisto_custom_wind, flight_time, expected_v
251251
[
252252
("t_initial", (1.654150, 0.659142, -0.067103)),
253253
("out_of_rail_time", (5.052628, 2.013361, -1.75370)),
254-
("apogee_time", (2.339424, -1.648934, -0.938867)),
255-
("t_final", (0, 0, 159.2210)),
254+
("apogee_time", (2.321838, -1.613641, -0.962108)),
255+
("t_final", (-0.025792, 0.012030, 159.202481)),
256256
],
257257
)
258258
def test_aerodynamic_forces(flight_calisto_custom_wind, flight_time, expected_values):
@@ -292,7 +292,7 @@ def test_aerodynamic_forces(flight_calisto_custom_wind, flight_time, expected_va
292292
("out_of_rail_time", (0, 2.248540, 25.700928)),
293293
(
294294
"apogee_time",
295-
(-14.488364, 15.638049, -0.000191),
295+
(-14.826350, 15.670022, -0.000264),
296296
),
297297
("t_final", (5, 2, -5.660155)),
298298
],
@@ -540,7 +540,7 @@ def test_lat_lon_conversion_from_origin(mock_show, example_plain_env, calisto_ro
540540
heading=0,
541541
)
542542

543-
assert abs(test_flight.longitude(test_flight.t_final) - 0) < 1e-12
543+
assert abs(test_flight.longitude(test_flight.t_final)) < 1e-4
544544
assert test_flight.latitude(test_flight.t_final) > 0
545545

546546

0 commit comments

Comments
 (0)