diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f0ffb99f..fd4f9c9cf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -52,6 +52,7 @@ Attention: The newest changes should be on top --> ### Fixed +- BUG: correct encoding for trapezoidal sweep length and angle. [#861](https://github.com/RocketPy-Team/RocketPy/pull/861) - BUG: Fix no time initialization when passing initial_solution as array to Flight object [#844](https://github.com/RocketPy-Team/RocketPy/pull/844) diff --git a/rocketpy/plots/monte_carlo_plots.py b/rocketpy/plots/monte_carlo_plots.py index d602b3a46..22d320b6b 100644 --- a/rocketpy/plots/monte_carlo_plots.py +++ b/rocketpy/plots/monte_carlo_plots.py @@ -1,6 +1,6 @@ import matplotlib.pyplot as plt -from matplotlib.transforms import offset_copy import numpy as np +from matplotlib.transforms import offset_copy from ..tools import generate_monte_carlo_ellipses, import_optional_dependency diff --git a/rocketpy/rocket/aero_surface/fins/trapezoidal_fins.py b/rocketpy/rocket/aero_surface/fins/trapezoidal_fins.py index 58b68799f..c6b4ea633 100644 --- a/rocketpy/rocket/aero_surface/fins/trapezoidal_fins.py +++ b/rocketpy/rocket/aero_surface/fins/trapezoidal_fins.py @@ -176,9 +176,6 @@ def __init__( sweep_length = np.tan(sweep_angle * np.pi / 180) * span elif sweep_length is None: sweep_length = root_chord - tip_chord - else: - # Sweep length is given - pass self._tip_chord = tip_chord self._sweep_length = sweep_length @@ -351,12 +348,12 @@ def all_info(self): def to_dict(self, **kwargs): data = super().to_dict(**kwargs) data["tip_chord"] = self.tip_chord + data["sweep_length"] = self.sweep_length + data["sweep_angle"] = self.sweep_angle if kwargs.get("include_outputs", False): data.update( { - "sweep_length": self.sweep_length, - "sweep_angle": self.sweep_angle, "shape_vec": self.shape_vec, "Af": self.Af, "AR": self.AR, @@ -382,4 +379,5 @@ def from_dict(cls, data): cant_angle=data["cant_angle"], airfoil=data["airfoil"], name=data["name"], + sweep_length=data.get("sweep_length"), ) diff --git a/tests/fixtures/surfaces/surface_fixtures.py b/tests/fixtures/surfaces/surface_fixtures.py index bf6e384c4..c48627478 100644 --- a/tests/fixtures/surfaces/surface_fixtures.py +++ b/tests/fixtures/surfaces/surface_fixtures.py @@ -69,6 +69,50 @@ def calisto_trapezoidal_fins(): ) +@pytest.fixture +def calisto_trapezoidal_fins_custom_sweep_length(): + """The trapezoidal fins of the Calisto rocket with + a custom sweep length. + + Returns + ------- + rocketpy.TrapezoidalFins + The trapezoidal fins of the Calisto rocket. + """ + return TrapezoidalFins( + n=4, + span=0.100, + root_chord=0.120, + tip_chord=0.040, + rocket_radius=0.0635, + name="calisto_trapezoidal_fins_custom_sweep_length", + cant_angle=0, + sweep_length=0.1, + ) + + +@pytest.fixture +def calisto_trapezoidal_fins_custom_sweep_angle(): + """The trapezoidal fins of the Calisto rocket with + a custom sweep angle. + + Returns + ------- + rocketpy.TrapezoidalFins + The trapezoidal fins of the Calisto rocket. + """ + return TrapezoidalFins( + n=4, + span=0.100, + root_chord=0.120, + tip_chord=0.040, + rocket_radius=0.0635, + name="calisto_trapezoidal_fins_custom_sweep_angle", + cant_angle=0, + sweep_angle=30, + ) + + @pytest.fixture def calisto_free_form_fins(): """The free form fins of the Calisto rocket. diff --git a/tests/integration/test_encoding.py b/tests/integration/test_encoding.py index 90e454af1..38d5aef41 100644 --- a/tests/integration/test_encoding.py +++ b/tests/integration/test_encoding.py @@ -242,6 +242,41 @@ def test_rocket_encoder(rocket_name, request): ) +@pytest.mark.parametrize( + "fin_name", + [ + "calisto_trapezoidal_fins", + "calisto_trapezoidal_fins_custom_sweep_length", + "calisto_trapezoidal_fins_custom_sweep_angle", + ], +) +def test_trapezoidal_fins_encoder(fin_name, request): + """Test encoding a ``rocketpy.TrapezoidalFins``. + + Parameters + ---------- + fin_name : str + Name of the fin fixture to encode. + request : pytest.FixtureRequest + Pytest request object. + """ + fin_to_encode = request.getfixturevalue(fin_name) + + json_encoded = json.dumps(fin_to_encode, cls=RocketPyEncoder) + + fin_loaded = json.loads(json_encoded, cls=RocketPyDecoder) + + assert isinstance(fin_loaded, type(fin_to_encode)) + assert fin_to_encode.n == fin_loaded.n + assert np.isclose(fin_to_encode.span, fin_loaded.span) + assert np.isclose(fin_to_encode.root_chord, fin_loaded.root_chord) + assert np.isclose(fin_to_encode.tip_chord, fin_loaded.tip_chord) + assert np.isclose(fin_to_encode.rocket_radius, fin_loaded.rocket_radius) + assert np.isclose(fin_to_encode.sweep_length, fin_loaded.sweep_length) + if fin_to_encode._sweep_angle is not None and fin_loaded._sweep_angle is not None: + assert np.isclose(fin_to_encode.sweep_angle, fin_loaded.sweep_angle) + + @pytest.mark.parametrize("rocket_name", ["calisto_robust", "calisto_hybrid_modded"]) def test_encoder_discretize(rocket_name, request): """Test encoding the total mass of ``rocketpy.Rocket`` with