From 89c36c026a4a8423264c1e3d99b6381ef394e258 Mon Sep 17 00:00:00 2001 From: Giovani Hidalgo Ceotto Date: Wed, 12 Oct 2022 00:09:54 -0300 Subject: [PATCH 1/4] ENH: add sweep length to trapezoidal fins --- rocketpy/Rocket.py | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/rocketpy/Rocket.py b/rocketpy/Rocket.py index f47ab610e..60bb43afe 100644 --- a/rocketpy/Rocket.py +++ b/rocketpy/Rocket.py @@ -482,6 +482,7 @@ def addTrapezoidalFins( span, distanceToCM, cantAngle=0, + sweepLength=None, radius=None, airfoil=None, ): @@ -507,6 +508,12 @@ def addTrapezoidalFins( cantAngle : int, float, optional Fins cant angle with respect to the rocket centerline. Must be given in degrees. + sweepLength : int, float, optional + Fins sweep length in meters. By sweep length, understand the axial distance + between the fin root leading edge and the fin tip leading edge measured + parallel to the rocket centerline. If not given, the sweep length is + assumed to be equal the root chord minus the tip chord, in which case the + fin is a right trapezoid with its base perpendicular to the rocket's axis. radius : int, float, optional Reference radius to calculate lift coefficient. If None, which is default, use rocket radius. Otherwise, enter the radius @@ -538,6 +545,7 @@ def addTrapezoidalFins( """ # Retrieves and convert basic geometrical parameters Cr, Ct = rootChord, tipChord + sweepLength = Cr - Ct if sweepLength is None else sweepLength s = span radius = self.radius if radius is None else radius cantAngleRad = np.radians(cantAngle) @@ -548,8 +556,11 @@ def addTrapezoidalFins( Yr = Cr + Ct Af = Yr * s / 2 # Fin area AR = 2 * s**2 / Af # Fin aspect ratio - gamac = np.arctan((Cr - Ct) / (2 * s)) # Mid chord angle + gamma_c = np.arctan( + (sweepLength + 0.5 * Ct - 0.5 * Cr) / (span) + ) # Mid chord angle Yma = (s / 3) * (Cr + 2 * Ct) / Yr # Span wise coord of mean aero chord + rollGeometricalConstant = ( (Cr + 3 * Ct) * s**3 + 4 * (Cr + 2 * Ct) * radius * s**2 @@ -558,7 +569,7 @@ def addTrapezoidalFins( # Center of pressure position relative to CDM (center of dry mass) cpz = distanceToCM + np.sign(distanceToCM) * ( - ((Cr - Ct) / 3) * ((Cr + 2 * Ct) / (Cr + Ct)) + (sweepLength / 3) * ((Cr + 2 * Ct) / (Cr + Ct)) + (1 / 6) * (Cr + Ct - Cr * Ct / (Cr + Ct)) ) @@ -636,11 +647,11 @@ def finNumCorrection(n): clalpha2D = Function(lambda mach: clalpha2D_Mach0 / beta(mach)) # Diederich's Planform Correlation Parameter - FD = 2 * np.pi * AR / (clalpha2D * np.cos(gamac)) + FD = 2 * np.pi * AR / (clalpha2D * np.cos(gamma_c)) # Lift coefficient derivative for a single fin clalphaSingleFin = Function( - lambda mach: (clalpha2D(mach) * FD(mach) * (Af / Aref) * np.cos(gamac)) + lambda mach: (clalpha2D(mach) * FD(mach) * (Af / Aref) * np.cos(gamma_c)) / (2 + FD(mach) * np.sqrt(1 + (2 / FD(mach)) ** 2)) ) From 909b38e339d3cf1174c19af09514824b32cccd9e Mon Sep 17 00:00:00 2001 From: Giovani Hidalgo Ceotto Date: Wed, 12 Oct 2022 00:21:14 -0300 Subject: [PATCH 2/4] ENH: add option to enter sweep angle in Rocket.addTrapezoidalFins --- rocketpy/Rocket.py | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/rocketpy/Rocket.py b/rocketpy/Rocket.py index 60bb43afe..b3de21c7c 100644 --- a/rocketpy/Rocket.py +++ b/rocketpy/Rocket.py @@ -483,6 +483,7 @@ def addTrapezoidalFins( distanceToCM, cantAngle=0, sweepLength=None, + sweepAngle=None, radius=None, airfoil=None, ): @@ -514,6 +515,13 @@ def addTrapezoidalFins( parallel to the rocket centerline. If not given, the sweep length is assumed to be equal the root chord minus the tip chord, in which case the fin is a right trapezoid with its base perpendicular to the rocket's axis. + Cannot be used in conjunction with sweepAngle. + sweepAngle : int, float, optional + Fins sweep angle with respect to the rocket centerline. Must + be given in degrees. If not given, the sweep angle is automatically + calculated, in which case the fin is assumed to be a right trapezoid with + its base perpendicular to the rocket's axis. + Cannot be used in conjunction with sweepLength. radius : int, float, optional Reference radius to calculate lift coefficient. If None, which is default, use rocket radius. Otherwise, enter the radius @@ -545,11 +553,21 @@ def addTrapezoidalFins( """ # Retrieves and convert basic geometrical parameters Cr, Ct = rootChord, tipChord - sweepLength = Cr - Ct if sweepLength is None else sweepLength s = span radius = self.radius if radius is None else radius cantAngleRad = np.radians(cantAngle) + # Check if sweep angle or sweep length is given + if sweepLength is not None and sweepAngle is not None: + raise ValueError("Cannot use sweepLength and sweepAngle together") + elif sweepAngle is not None: + sweepLength = np.tan(sweepAngle * np.pi / 180) * span + elif sweepLength is None: + sweepLength = Cr - Ct + else: + # Sweep length is given + pass + # Compute auxiliary geometrical parameters d = 2 * radius Aref = np.pi * radius**2 From af2de0ca341493b3764dbed74d44ab6e78ea21de Mon Sep 17 00:00:00 2001 From: Giovani Hidalgo Ceotto Date: Wed, 12 Oct 2022 01:17:40 -0300 Subject: [PATCH 3/4] TST: implement tests related to trapezoidal fin sweep --- tests/test_rocket.py | 64 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/tests/test_rocket.py b/tests/test_rocket.py index c44687796..4ece55172 100644 --- a/tests/test_rocket.py +++ b/tests/test_rocket.py @@ -340,6 +340,70 @@ def test_add_tail_assert_cp_cm_plus_tail(rocket, dimensionless_rocket, m): ) +@pytest.mark.parametrize( + "sweep_angle, expected_fin_cpz, expected_clalpha, expected_cpz_cm", + [(39.8, 2.51, 3.16, 1.65), (-10, 2.47, 3.21, 1.63), (29.1, 2.50, 3.28, 1.66)], +) +def test_add_trapezoidal_fins_sweep_angle( + rocket, sweep_angle, expected_fin_cpz, expected_clalpha, expected_cpz_cm +): + # Reference values from OpenRocket + Nose = rocket.addNose(length=0.55829, kind="vonKarman", distanceToCM=0.71971) + + FinSet = rocket.addTrapezoidalFins( + n=3, + span=0.090, + rootChord=0.100, + tipChord=0.050, + sweepAngle=sweep_angle, + distanceToCM=-1.182, + ) + + # Check center of pressure + translate = 0.55829 + 0.71971 + cpz = FinSet["cp"][2] + assert translate - cpz == pytest.approx(expected_fin_cpz, 0.01) + + # Check lift coefficient derivative + cl_alpha = FinSet["cl"](1, 0.0) + assert cl_alpha == pytest.approx(expected_clalpha, 0.01) + + # Check rocket's center of pressure (just double checking) + assert translate - rocket.cpPosition == pytest.approx(expected_cpz_cm, 0.01) + + +@pytest.mark.parametrize( + "sweep_length, expected_fin_cpz, expected_clalpha, expected_cpz_cm", + [(0.075, 2.51, 3.16, 1.65), (-0.0159, 2.47, 3.21, 1.63), (0.05, 2.50, 3.28, 1.66)], +) +def test_add_trapezoidal_fins_sweep_length( + rocket, sweep_length, expected_fin_cpz, expected_clalpha, expected_cpz_cm +): + # Reference values from OpenRocket + Nose = rocket.addNose(length=0.55829, kind="vonKarman", distanceToCM=0.71971) + + FinSet = rocket.addTrapezoidalFins( + n=3, + span=0.090, + rootChord=0.100, + tipChord=0.050, + sweepLength=sweep_length, + distanceToCM=-1.182, + ) + + # Check center of pressure + translate = 0.55829 + 0.71971 + cpz = FinSet["cp"][2] + assert translate - cpz == pytest.approx(expected_fin_cpz, 0.01) + + # Check lift coefficient derivative + cl_alpha = FinSet["cl"](1, 0.0) + assert cl_alpha == pytest.approx(expected_clalpha, 0.01) + + # Check rocket's center of pressure (just double checking) + assert translate - rocket.cpPosition == pytest.approx(expected_cpz_cm, 0.01) + + def test_add_fins_assert_cp_cm_plus_fins(rocket, dimensionless_rocket, m): rocket.addTrapezoidalFins( 4, From 2834b5f4bccf87f709722a55d93be720f6ef6504 Mon Sep 17 00:00:00 2001 From: Giovani Hidalgo Ceotto Date: Wed, 12 Oct 2022 01:18:07 -0300 Subject: [PATCH 4/4] FIX: addFins returns created fin set once again --- rocketpy/Rocket.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rocketpy/Rocket.py b/rocketpy/Rocket.py index b3de21c7c..7a7fb3441 100644 --- a/rocketpy/Rocket.py +++ b/rocketpy/Rocket.py @@ -472,7 +472,7 @@ def addFins(self, *args, **kwargs): "removed by version 2.0.0. Use Rocket.addTrapezoidalFins instead", PendingDeprecationWarning, ) - self.addTrapezoidalFins(*args, **kwargs) + return self.addTrapezoidalFins(*args, **kwargs) def addTrapezoidalFins( self,