Skip to content

Commit e428604

Browse files
kevin-alcanizGui-FernandesBRMateusStanoMateusStano
authored
ENH: Add the Coriolis Force to the Flight class (#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 <[email protected]> * ENH: more intuitive uniform distribution display in StochasticModel Co-authored-by: MateusStano <[email protected]> * DOC: improve drag curve factor definition in StochasticAirBrakes * ENH: Change assert statement to if Co-authored-by: Gui-FernandesBR <[email protected]> * DOC: better explanation of __mul__ function Co-authored-by: MateusStano <[email protected]> * 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 <[email protected]> * 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 <[email protected]> Co-authored-by: MateusStano <[email protected]> Co-authored-by: MateusStano <[email protected]> Co-authored-by: MateusStano <[email protected]>
1 parent 780f724 commit e428604

File tree

5 files changed

+65
-24
lines changed

5 files changed

+65
-24
lines changed

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
@@ -1676,6 +1676,12 @@ def u_dot(self, t, u, post_processing=False): # pylint: disable=too-many-locals
16761676
ax, ay, az = K @ Vector(L)
16771677
az -= self.env.gravity.get_value_opt(z) # Include gravity
16781678

1679+
# Coriolis acceleration
1680+
_, w_earth_y, w_earth_z = self.env.earth_rotation_vector
1681+
ax -= 2 * (vz * w_earth_y - vy * w_earth_z)
1682+
ay -= 2 * (vx * w_earth_z)
1683+
az -= 2 * (-vx * w_earth_y)
1684+
16791685
# Create u_dot
16801686
u_dot = [
16811687
vx,
@@ -1742,7 +1748,7 @@ def u_dot_generalized(self, t, u, post_processing=False): # pylint: disable=too
17421748
_, _, z, vx, vy, vz, e0, e1, e2, e3, omega1, omega2, omega3 = u
17431749

17441750
# Create necessary vectors
1745-
# r = Vector([x, y, z]) # CDM position vector
1751+
# r = Vector([x, y, z]) # CDM position vector
17461752
v = Vector([vx, vy, vz]) # CDM velocity vector
17471753
e = [e0, e1, e2, e3] # Euler parameters/quaternions
17481754
w = Vector([omega1, omega2, omega3]) # Angular velocity vector
@@ -1901,9 +1907,6 @@ def u_dot_generalized(self, t, u, post_processing=False): # pylint: disable=too
19011907
# Angular velocity derivative
19021908
w_dot = I_CM.inverse @ (T21 + (T20 ^ r_CM))
19031909

1904-
# Velocity vector derivative
1905-
v_dot = K @ (T20 / total_mass - (r_CM ^ w_dot))
1906-
19071910
# Euler parameters derivative
19081911
e_dot = [
19091912
0.5 * (-omega1 * e1 - omega2 * e2 - omega3 * e3),
@@ -1912,6 +1915,10 @@ def u_dot_generalized(self, t, u, post_processing=False): # pylint: disable=too
19121915
0.5 * (omega3 * e0 + omega2 * e1 - omega1 * e2),
19131916
]
19141917

1918+
# Velocity vector derivative + Coriolis acceleration
1919+
w_earth = Vector(self.env.earth_rotation_vector)
1920+
v_dot = K @ (T20 / total_mass - (r_CM ^ w_dot)) - 2 * (w_earth ^ v)
1921+
19151922
# Position vector derivative
19161923
r_dot = [vx, vy, vz]
19171924

@@ -1991,6 +1998,12 @@ def u_dot_parachute(self, t, u, post_processing=False):
19911998
ay = Dy / (mp + ma)
19921999
az = (Dz - 9.8 * mp) / (mp + ma)
19932000

2001+
# Add coriolis acceleration
2002+
_, w_earth_y, w_earth_z = self.env.earth_rotation_vector
2003+
ax -= 2 * (vz * w_earth_y - vy * w_earth_z)
2004+
ay -= 2 * (vx * w_earth_z)
2005+
az -= 2 * (-vx * w_earth_y)
2006+
19942007
if post_processing:
19952008
self.__post_processed_variables.append(
19962009
[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)