diff --git a/CHANGELOG.md b/CHANGELOG.md index 75e20416e..abca56e18 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,7 @@ Attention: The newest changes should be on top --> ### Added +- MNT: net thrust addition to 3 dof in flight class [#907] (https://github.com/RocketPy-Team/RocketPy/pull/907) - ENH: 3-dof lateral motion improvement [#883](https://github.com/RocketPy-Team/RocketPy/pull/883) - ENH: Add multi-dimensional drag coefficient support (Cd as function of M, Re, α) [#875](https://github.com/RocketPy-Team/RocketPy/pull/875) - ENH: Add save functionality to `_MonteCarloPlots.all` method [#848](https://github.com/RocketPy-Team/RocketPy/pull/848) @@ -52,6 +53,7 @@ Attention: The newest changes should be on top --> ### Fixed +- BUG: energy_data plot not working for 3 dof sims [[#906](https://github.com/RocketPy-Team/RocketPy/issues/906)] - BUG: Fix CSV column header spacing in FlightDataExporter [#864](https://github.com/RocketPy-Team/RocketPy/issues/864) - BUG: Fix parallel Monte Carlo simulation showing incorrect iteration count [#806](https://github.com/RocketPy-Team/RocketPy/pull/806) diff --git a/rocketpy/simulation/flight.py b/rocketpy/simulation/flight.py index 84ab880dc..3e0204ece 100644 --- a/rocketpy/simulation/flight.py +++ b/rocketpy/simulation/flight.py @@ -2041,11 +2041,20 @@ def u_dot_generalized_3dof(self, t, u, post_processing=False): R3 += fz # Thrust and weight - thrust = self.rocket.motor.thrust.get_value_opt(t) + # Calculate net thrust including pressure thrust correction if motor is burning + if self.rocket.motor.burn_start_time < t < self.rocket.motor.burn_out_time: + pressure = self.env.pressure.get_value_opt(z) + net_thrust = max( + self.rocket.motor.thrust.get_value_opt(t) + + self.rocket.motor.pressure_thrust(pressure), + 0, + ) + else: + net_thrust = 0 gravity = self.env.gravity.get_value_opt(z) weight_body = Kt @ Vector([0, 0, -total_mass * gravity]) - total_force = Vector([0, 0, thrust]) + weight_body + Vector([R1, R2, R3]) + total_force = Vector([0, 0, net_thrust]) + weight_body + Vector([R1, R2, R3]) # Dynamics v_dot = K @ (total_force / total_mass) @@ -2133,7 +2142,7 @@ def u_dot_generalized_3dof(self, t, u, post_processing=False): if post_processing: self.__post_processed_variables.append( - [t, *v_dot, *w_dot, R1, R2, R3, 0, 0, 0] + [t, *v_dot, *w_dot, R1, R2, R3, 0, 0, 0, net_thrust] ) return u_dot diff --git a/tests/integration/simulation/test_flight_3dof.py b/tests/integration/simulation/test_flight_3dof.py index ef4c35c14..94a4e33eb 100644 --- a/tests/integration/simulation/test_flight_3dof.py +++ b/tests/integration/simulation/test_flight_3dof.py @@ -301,3 +301,26 @@ def test_weathercock_anti_aligned_uses_perp_axis_and_evolves(flight_weathercock_ assert e_dot_magnitude > 1e-6, ( "Quaternion derivatives should be non-zero for anti-aligned" ) + + +def test_3dof_net_thrust_available(flight_3dof): + """Tests that net_thrust property is available in 3 DOF mode. + The net_thrust property is required for energy plots and should be + available in both 3 DOF and 6 DOF modes. + + Parameters + ---------- + flight_3dof : rocketpy.simulation.flight.Flight + A Flight object configured for 3-DOF simulation. + """ + # Check that net_thrust can be accessed + assert hasattr(flight_3dof, "net_thrust"), "net_thrust attribute not found" + + # Check that it returns a Function object with data + net_thrust = flight_3dof.net_thrust + assert len(net_thrust) > 0, "net_thrust should have data points" + + # Verify that thrust_power can be computed (uses net_thrust internally) + assert hasattr(flight_3dof, "thrust_power"), "thrust_power attribute not found" + thrust_power = flight_3dof.thrust_power + assert len(thrust_power) > 0, "thrust_power should have data points"