From 3a41c22480ef050f2978b5de9ab20fd65c077de1 Mon Sep 17 00:00:00 2001 From: hugo bentata Date: Sat, 29 Nov 2025 16:05:13 +0100 Subject: [PATCH 1/5] feat: add axial_acceleration with tests --- CHANGELOG.md | 1 + rocketpy/simulation/flight.py | 9 ++++++++ tests/conftest.py | 2 +- tests/unit/simulation/test_flight.py | 31 ++++++++++++++++++++++++++++ 4 files changed, 42 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c3aa2373..493448988 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,7 @@ Attention: The newest changes should be on top --> ### Added +- ENH: Add axial_acceleration attribute to the Flight class [#876](https://github.com/RocketPy-Team/RocketPy/pull/876) - ENH: Add save functionality to `_MonteCarloPlots.all` method [#848](https://github.com/RocketPy-Team/RocketPy/pull/848) - ENH: Add persistent caching for ThrustCurve API [#881](https://github.com/RocketPy-Team/RocketPy/pull/881) - ENH: Compatibility with MERRA-2 atmosphere reanalysis files [#825](https://github.com/RocketPy-Team/RocketPy/pull/825) diff --git a/rocketpy/simulation/flight.py b/rocketpy/simulation/flight.py index 30ea66466..76f5b0907 100644 --- a/rocketpy/simulation/flight.py +++ b/rocketpy/simulation/flight.py @@ -2620,6 +2620,15 @@ def max_acceleration(self): max_acceleration_time_index = np.argmax(self.acceleration[:, 1]) return self.acceleration[max_acceleration_time_index, 1] + @cached_property + def axial_acceleration(self): + """Axial acceleration magnitude as a function of time.""" + return ( + self.ax * self.attitude_vector_x + + self.ay * self.attitude_vector_y + + self.az * self.attitude_vector_z + ) + @funcify_method("Time (s)", "Horizontal Speed (m/s)") def horizontal_speed(self): """Rocket horizontal speed as a Function of time.""" diff --git a/tests/conftest.py b/tests/conftest.py index 12d07c334..456de43ca 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,6 +1,6 @@ +import matplotlib import netCDF4 import numpy as np -import matplotlib import pytest # Configure matplotlib to use non-interactive backend for tests diff --git a/tests/unit/simulation/test_flight.py b/tests/unit/simulation/test_flight.py index 1bd9384e2..a54c5afdb 100644 --- a/tests/unit/simulation/test_flight.py +++ b/tests/unit/simulation/test_flight.py @@ -413,6 +413,37 @@ def test_max_values(flight_calisto_robust): assert pytest.approx(285.94948, rel=rtol) == test.max_speed +@pytest.mark.parametrize( + "flight_time_attr", + ["t_initial", "out_of_rail_time", "apogee_time", "t_final"], +) +def test_axial_acceleration(flight_calisto_custom_wind, flight_time_attr): + """Tests the axial_acceleration property by manually calculating the + dot product of the acceleration vector and the attitude vector at + specific time steps. + + Parameters + ---------- + flight_calisto_custom_wind : rocketpy.Flight + Flight object to be tested. + flight_time_attr : str + The name of the attribute of the flight object that contains the time + of the point to be tested. + """ + flight = flight_calisto_custom_wind + t = getattr(flight, flight_time_attr) + + calculated_axial_acc = flight.axial_acceleration(t) + + expected_axial_acc = ( + flight.ax(t) * flight.attitude_vector_x(t) + + flight.ay(t) * flight.attitude_vector_y(t) + + flight.az(t) * flight.attitude_vector_z(t) + ) + + assert pytest.approx(expected_axial_acc, abs=1e-9) == calculated_axial_acc + + def test_effective_rail_length(flight_calisto_robust, flight_calisto_nose_to_tail): """Tests the effective rail length of the flight simulation. The expected values are calculated by hand, and should be valid as long as the rail From e54da413afeb005ffb67bc620e1d0288bf613580 Mon Sep 17 00:00:00 2001 From: hugo bentata Date: Tue, 2 Dec 2025 15:53:23 +0100 Subject: [PATCH 2/5] Update axial_acceleration. --- rocketpy/simulation/flight.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/rocketpy/simulation/flight.py b/rocketpy/simulation/flight.py index 76f5b0907..dfd9996df 100644 --- a/rocketpy/simulation/flight.py +++ b/rocketpy/simulation/flight.py @@ -2571,6 +2571,15 @@ def acceleration(self): """Rocket acceleration magnitude as a Function of time.""" return (self.ax**2 + self.ay**2 + self.az**2) ** 0.5 + @funcify_method("Time (s)", "Axial Acceleration (m/s²)", "spline", "zero") + def axial_acceleration(self): + """Axial acceleration magnitude as a function of time, in m/s².""" + return ( + self.ax * self.attitude_vector_x + + self.ay * self.attitude_vector_y + + self.az * self.attitude_vector_z + ) + @cached_property def max_acceleration_power_on_time(self): """Time at which the rocket reaches its maximum acceleration during @@ -2620,15 +2629,6 @@ def max_acceleration(self): max_acceleration_time_index = np.argmax(self.acceleration[:, 1]) return self.acceleration[max_acceleration_time_index, 1] - @cached_property - def axial_acceleration(self): - """Axial acceleration magnitude as a function of time.""" - return ( - self.ax * self.attitude_vector_x - + self.ay * self.attitude_vector_y - + self.az * self.attitude_vector_z - ) - @funcify_method("Time (s)", "Horizontal Speed (m/s)") def horizontal_speed(self): """Rocket horizontal speed as a Function of time.""" From 5c73e6d55515a8d9354e9808c4fe68610b2a1397 Mon Sep 17 00:00:00 2001 From: hogatata <98260741+hogatata@users.noreply.github.com> Date: Tue, 2 Dec 2025 16:13:14 +0100 Subject: [PATCH 3/5] Update CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c9e64bc58..06993d669 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,6 +33,7 @@ Attention: The newest changes should be on top --> ### Added - ENH: Add axial_acceleration attribute to the Flight class [#876](https://github.com/RocketPy-Team/RocketPy/pull/876) +- ENH: Built-in flight comparison tool (`FlightComparator`) to validate simulations against external data [#888](https://github.com/RocketPy-Team/RocketPy/pull/888) - ENH: Add save functionality to `_MonteCarloPlots.all` method [#848](https://github.com/RocketPy-Team/RocketPy/pull/848) - ENH: Add persistent caching for ThrustCurve API [#881](https://github.com/RocketPy-Team/RocketPy/pull/881) - ENH: Compatibility with MERRA-2 atmosphere reanalysis files [#825](https://github.com/RocketPy-Team/RocketPy/pull/825) From ff1ce0fa157c1efbe59c9e3b175aa1e8b45d26dc Mon Sep 17 00:00:00 2001 From: hogatata <98260741+hogatata@users.noreply.github.com> Date: Tue, 2 Dec 2025 16:15:54 +0100 Subject: [PATCH 4/5] Update CHANGELOG --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 06993d669..3eb416938 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,7 +34,6 @@ Attention: The newest changes should be on top --> - ENH: Add axial_acceleration attribute to the Flight class [#876](https://github.com/RocketPy-Team/RocketPy/pull/876) - ENH: Built-in flight comparison tool (`FlightComparator`) to validate simulations against external data [#888](https://github.com/RocketPy-Team/RocketPy/pull/888) -- ENH: Add save functionality to `_MonteCarloPlots.all` method [#848](https://github.com/RocketPy-Team/RocketPy/pull/848) - ENH: Add persistent caching for ThrustCurve API [#881](https://github.com/RocketPy-Team/RocketPy/pull/881) - ENH: Compatibility with MERRA-2 atmosphere reanalysis files [#825](https://github.com/RocketPy-Team/RocketPy/pull/825) - ENH: Enable only radial burning [#815](https://github.com/RocketPy-Team/RocketPy/pull/815) From 3099277d5ca336223d344466fd89b9f36a2a0389 Mon Sep 17 00:00:00 2001 From: hogatata <98260741+hogatata@users.noreply.github.com> Date: Tue, 2 Dec 2025 16:20:44 +0100 Subject: [PATCH 5/5] Refine docstring for axial_acceleration method Updated docstring for axial_acceleration method to improve clarity. --- rocketpy/simulation/flight.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rocketpy/simulation/flight.py b/rocketpy/simulation/flight.py index dfd9996df..70199a29f 100644 --- a/rocketpy/simulation/flight.py +++ b/rocketpy/simulation/flight.py @@ -2573,7 +2573,7 @@ def acceleration(self): @funcify_method("Time (s)", "Axial Acceleration (m/s²)", "spline", "zero") def axial_acceleration(self): - """Axial acceleration magnitude as a function of time, in m/s².""" + """Axial acceleration magnitude as a Function of time.""" return ( self.ax * self.attitude_vector_x + self.ay * self.attitude_vector_y