From 193d005b8a42039d47528d344a05a3f7774d1c9a Mon Sep 17 00:00:00 2001 From: MateusStano Date: Sat, 7 Sep 2024 22:52:23 +0200 Subject: [PATCH 01/32] ENH: add individual fin class Co-authored-by: kevin-alcaniz --- rocketpy/rocket/aero_surface/fins/fin.py | 459 +++++++++++++++++++++++ 1 file changed, 459 insertions(+) create mode 100644 rocketpy/rocket/aero_surface/fins/fin.py diff --git a/rocketpy/rocket/aero_surface/fins/fin.py b/rocketpy/rocket/aero_surface/fins/fin.py new file mode 100644 index 000000000..b1ccacf5b --- /dev/null +++ b/rocketpy/rocket/aero_surface/fins/fin.py @@ -0,0 +1,459 @@ +import math +from abc import abstractmethod + +import numpy as np + +from rocketpy.mathutils.function import Function +from rocketpy.mathutils.vector_matrix import Matrix, Vector + +from ..aero_surface import AeroSurface + + +class Fin(AeroSurface): + """Abstract class that holds common methods for the individual fin classes. + Cannot be instantiated. + + Note + ---- + Local coordinate system: + - Origin located at the top of the root chord. + - Z axis along the longitudinal axis of symmetry, positive downwards (top -> bottom). + - Y axis perpendicular to the Z axis, in the span direction, positive upwards. + - X axis completes the right-handed coordinate system. + + Attributes + ---------- + Fins.rocket_radius : float + The reference rocket radius used for lift coefficient normalization, + in meters. + Fins.airfoil : tuple + Tuple of two items. First is the airfoil lift curve. + Second is the unit of the curve (radians or degrees). + Fins.cant_angle : float + Fins cant angle with respect to the rocket centerline, in degrees. + Fins.changing_attribute_dict : dict + Dictionary that stores the name and the values of the attributes that + may be changed during a simulation. Useful for control systems. + Fins.cant_angle_rad : float + Fins cant angle with respect to the rocket centerline, in radians. + Fins.root_chord : float + Fin root chord in meters. + Fins.tip_chord : float + Fin tip chord in meters. + Fins.span : float + Fin span in meters. + Fins.name : string + Name of fin set. + Fins.sweep_length : float + 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. + Fins.sweep_angle : float + Fins sweep angle with respect to the rocket centerline. Must + be given in degrees. + Fins.d : float + Reference diameter of the rocket. Has units of length and is given + in meters. + Fins.ref_area : float + Reference area of the rocket. + Fins.Af : float + Area of the longitudinal section of each fin in the set. + Fins.AR : float + Aspect ratio of each fin in the set. + Fins.gamma_c : float + Fin mid-chord sweep angle. + Fins.Yma : float + Span wise position of the mean aerodynamic chord. + Fins.roll_geometrical_constant : float + Geometrical constant used in roll calculations. + Fins.tau : float + Geometrical relation used to simplify lift and roll calculations. + Fins.lift_interference_factor : float + Factor of Fin-Body interference in the lift coefficient. + Fins.cp : tuple + Tuple with the x, y and z local coordinates of the fin set center of + pressure. Has units of length and is given in meters. + Fins.cpx : float + Fin set local center of pressure x coordinate. Has units of length and + is given in meters. + Fins.cpy : float + Fin set local center of pressure y coordinate. Has units of length and + is given in meters. + Fins.cpz : float + Fin set local center of pressure z coordinate. Has units of length and + is given in meters. + Fins.cl : Function + Function which defines the lift coefficient as a function of the angle + of attack and the Mach number. Takes as input the angle of attack in + radians and the Mach number. Returns the lift coefficient. + Fins.clalpha : float + Lift coefficient slope. Has units of 1/rad. + Fins.roll_parameters : list + List containing the roll moment lift coefficient, the roll moment + damping coefficient and the cant angle in radians. + """ + + def __init__( + self, + angular_position, + root_chord, + span, + rocket_radius, + cant_angle=0, + airfoil=None, + name="Fin", + ): + """Initialize Fin class. + + Parameters + ---------- + angular_position : int, float + Angular position of the fin in degrees. + root_chord : int, float + Fin root chord in meters. + span : int, float + Fin span in meters. + rocket_radius : int, float + Reference rocket radius used for lift coefficient normalization. + cant_angle : int, float, optional + Fin cant angle with respect to the rocket centerline. Must + be given in degrees. + airfoil : tuple, optional + Default is null, in which case fins will be treated as flat plates. + Otherwise, if tuple, fins will be considered as airfoils. The + tuple's first item specifies the airfoil's lift coefficient + by angle of attack and must be either a .csv, .txt, ndarray + or callable. The .csv and .txt files can contain a single line + header and the first column must specify the angle of attack, while + the second column must specify the lift coefficient. The + ndarray should be as [(x0, y0), (x1, y1), (x2, y2), ...] + where x0 is the angle of attack and y0 is the lift coefficient. + If callable, it should take an angle of attack as input and + return the lift coefficient at that angle of attack. + The tuple's second item is the unit of the angle of attack, + accepting either "radians" or "degrees". + name : str + Name of fin. + + Returns + ------- + None + """ + # Compute auxiliary geometrical parameters + d = 2 * rocket_radius + ref_area = np.pi * rocket_radius**2 # Reference area + + super().__init__(name, ref_area, d) + + # Store values + self.name = name + self.d = d + self.ref_area = ref_area + self._rocket_radius = rocket_radius + self._airfoil = airfoil + self._root_chord = root_chord + self._span = span + self._cant_angle = -cant_angle + self._cant_angle_rad = math.radians(-cant_angle) + self._angular_position = angular_position + self._angular_position_rad = math.radians(angular_position) + + @property + def angular_position(self): + return self._angular_position + + @angular_position.setter + def angular_position(self, value): + self._angular_position = value + self.angular_position_rad = math.radians(value) + + @property + def angular_position_rad(self): + return self._angular_position_rad + + @angular_position_rad.setter + def angular_position_rad(self, value): + self._angular_position_rad = value + self.evaluate_rotation_matrix() + + @property + def root_chord(self): + return self._root_chord + + @root_chord.setter + def root_chord(self, value): + self._root_chord = value + self.evaluate_geometrical_parameters() + self.evaluate_center_of_pressure() + self.evaluate_lift_coefficient() + self.evaluate_roll_parameters() + + @property + def span(self): + return self._span + + @span.setter + def span(self, value): + self._span = value + self.evaluate_geometrical_parameters() + self.evaluate_center_of_pressure() + self.evaluate_lift_coefficient() + self.evaluate_roll_parameters() + + @property + def rocket_radius(self): + return self._rocket_radius + + @rocket_radius.setter + def rocket_radius(self, value): + self._rocket_radius = value + self.evaluate_geometrical_parameters() + self.evaluate_center_of_pressure() + self.evaluate_lift_coefficient() + self.evaluate_roll_parameters() + + @property + def cant_angle(self): + return -self._cant_angle + + @cant_angle.setter + def cant_angle(self, value): + self._cant_angle = -value + self.cant_angle_rad = math.radians(-value) + + @property + def cant_angle_rad(self): + return self._cant_angle_rad + + @cant_angle_rad.setter + def cant_angle_rad(self, value): + self._cant_angle_rad = value + self.evaluate_geometrical_parameters() + self.evaluate_center_of_pressure() + self.evaluate_lift_coefficient() + self.evaluate_roll_parameters() + self.evaluate_rotation_matrix() + + @property + def airfoil(self): + return self._airfoil + + @airfoil.setter + def airfoil(self, value): + self._airfoil = value + self.evaluate_geometrical_parameters() + self.evaluate_center_of_pressure() + self.evaluate_lift_coefficient() + self.evaluate_roll_parameters() + + def evaluate_lift_coefficient(self): + """Calculates and returns the fin set's lift coefficient. + The lift coefficient is saved and returned. This function + also calculates and saves the lift coefficient derivative + for a single fin and the lift coefficient derivative for + a number of n fins corrected for Fin-Body interference. + + Returns + ------- + None + """ + if not self.airfoil: + # Defines clalpha2D as 2*pi for planar fins + clalpha2D_incompressible = 2 * np.pi + else: + # Defines clalpha2D as the derivative of the lift coefficient curve + # for the specific airfoil + self.airfoil_cl = Function( + self.airfoil[0], + interpolation="linear", + ) + + # Differentiating at alpha = 0 to get cl_alpha + clalpha2D_incompressible = self.airfoil_cl.differentiate_complex_step( + x=1e-3, dx=1e-3 + ) + + # Convert to radians if needed + if self.airfoil[1] == "degrees": + clalpha2D_incompressible *= 180 / np.pi + + # Correcting for compressible flow (apply Prandtl-Glauert correction) + clalpha2D = Function(lambda mach: clalpha2D_incompressible / self._beta(mach)) + + # Diederich's Planform Correlation Parameter + planform_correlation_parameter = ( + 2 * np.pi * self.AR / (clalpha2D * np.cos(self.gamma_c)) + ) + + # Lift coefficient derivative for a single fin + def lift_source(mach): + return ( + clalpha2D(mach) + * self.lift_interference_factor + * planform_correlation_parameter(mach) + * (self.Af / self.ref_area) + * np.cos(self.gamma_c) + ) / ( + 2 + + planform_correlation_parameter(mach) + * np.sqrt(1 + (2 / planform_correlation_parameter(mach)) ** 2) + ) + + self.clalpha_single_fin = Function( + lift_source, + "Mach", + "Lift coefficient derivative for a single fin", + ) + + self.clalpha = self.clalpha_single_fin + + # Cl = clalpha * alpha + self.cl = Function( + lambda alpha, mach: alpha * self.clalpha_single_fin(mach), + ["Alpha (rad)", "Mach"], + "Lift coefficient", + ) + + return self.cl + + def evaluate_roll_parameters(self): + """Calculates and returns the fin set's roll coefficients. + The roll coefficients are saved in a list. + + Returns + ------- + self.roll_parameters : list + List containing the roll moment lift coefficient, the + roll moment damping coefficient and the cant angle in + radians + """ + clf_delta = Function(lambda mach: 0) + clf_delta.set_inputs("Mach") + clf_delta.set_outputs("Roll moment forcing coefficient derivative") + cld_omega = -( + 2 + * self.roll_damping_interference_factor + * self.clalpha_single_fin + * np.cos(self.cant_angle_rad) + * self.roll_geometrical_constant + / (self.ref_area * self.d**2) + ) # Function of mach number + cld_omega.set_inputs("Mach") + cld_omega.set_outputs("Roll moment damping coefficient derivative") + self.roll_parameters = [clf_delta, cld_omega, self.cant_angle_rad] + return self.roll_parameters + + def evaluate_rotation_matrix(self): + """Calculates and returns the rotation matrix from the rocket body frame + to the fin frame. + + TODO: paste this description where it is relevant + Note + ---- + Local coordinate system: + - Origin located at the leading edge of the root chord. + - Z axis along the longitudinal axis of the fin, positive downwards + (leading edge -> trailing edge). + - Y axis perpendicular to the Z axis, in the span direction, + positive upwards (root chord -> tip chord). + - X axis completes the right-handed coordinate system. + + + Returns + ------- + None + + References + ---------- + [1] TODO link to docs + """ + phi = self.angular_position_rad + delta = self.cant_angle_rad + # TODO check rotation for nose_to_tail csystems + # Body to fin rotation matrix + R = Matrix( + [ + [ + -np.cos(delta) * np.cos(phi), + -np.cos(delta) * np.sin(phi), + np.sin(delta), + ], + [-np.sin(phi), np.cos(phi), 0], + [ + np.sin(delta) * np.cos(phi), + np.sin(delta) * np.sin(phi), + -np.cos(delta), + ], + ] + ) + self._body_to_fin = R + self._fin_to_body = R.transpose + + # Body to fin aerodynamic frame rotation matrix, need only invert the x and z axis + R = Matrix([[-1, 0, 0], [0, 1, 0], [0, 0, -1]]) @ R + self._body_to_fin_aero = R + self._fin_aero_to_body = R.transpose + + def compute_forces_and_moments( + self, + stream_velocity, + stream_speed, + stream_mach, + rho, + cp, + _, + omega1, + omega2, + omega3, + *args, + **kwargs, + ): + """Computes the forces and moments acting on the aerodynamic surface. + + Parameters + ---------- + stream_speed : int, float + Speed of the flow stream in the body frame. + + """ + R1, R2, R3, M1, M2, M3 = 0, 0, 0, 0, 0, 0 + # stream velocity in fin frame + stream_vx_f, _, stream_vz_f = self._body_to_fin_aero @ stream_velocity + if stream_vx_f != 0: + attack_angle = np.arctan(-stream_vx_f / stream_vz_f) + # Force in the X direction of the fin + X = ( + 0.5 + * rho + * stream_speed**2 + * self.reference_area + * self.cl(attack_angle, stream_mach) + ) + M = cp.z * X + N = -(self.cp[1] + self.rocket_radius) * X + # Forces and moments in body frame + R1, R2, R3 = self._fin_aero_to_body @ Vector([X, 0, 0]) + M1, M2, M3 = self._fin_aero_to_body @ Vector([0, M, N]) + + # Roll damping + _, cld_omega, _ = self.roll_parameters + M3_damping = ( + (1 / 2 * rho * stream_speed) + * self.reference_area + * (self.reference_length) ** 2 + * cld_omega.get_value_opt(stream_mach) + * omega3 + / 2 + ) + M3 += M3_damping + return R1, R2, R3, M1, M2, M3 + + def draw(self): + """Draw the fin shape along with some important information, including + the center line, the quarter line and the center of pressure position. + + Returns + ------- + None + """ + self.plots.draw() From 9c54679c8c72bfcc9af6146d23b2fdc3543e3bd9 Mon Sep 17 00:00:00 2001 From: MateusStano Date: Sat, 7 Sep 2024 22:54:09 +0200 Subject: [PATCH 02/32] ENH: add trapezoidal fin and elliptical fin Co-authored-by: kevin-alcaniz --- .../aero_surface/fins/elliptical_fin.py | 307 ++++++++++++++++++ .../aero_surface/fins/trapezoidal_fin.py | 205 ++++++++++++ 2 files changed, 512 insertions(+) create mode 100644 rocketpy/rocket/aero_surface/fins/elliptical_fin.py create mode 100644 rocketpy/rocket/aero_surface/fins/trapezoidal_fin.py diff --git a/rocketpy/rocket/aero_surface/fins/elliptical_fin.py b/rocketpy/rocket/aero_surface/fins/elliptical_fin.py new file mode 100644 index 000000000..46cf50ed4 --- /dev/null +++ b/rocketpy/rocket/aero_surface/fins/elliptical_fin.py @@ -0,0 +1,307 @@ +import numpy as np + +from .fin import Fin + + +class EllipticalFin(Fin): + """Class that defines and holds information for an elliptical fin. + + Note + ---- + Local coordinate system: + - Origin located at the top of the root chord. + - Z axis along the longitudinal axis of symmetry, positive downwards (top -> bottom). + - Y axis perpendicular to the Z axis, in the span direction, positive upwards. + - X axis completes the right-handed coordinate system. + + See Also + -------- + Fin + + Attributes + ---------- + EllipticalFin.rocket_radius : float + The reference rocket radius used for lift coefficient normalization, in + meters. + EllipticalFin.airfoil : tuple + Tuple of two items. First is the airfoil lift curve. + Second is the unit of the curve (radians or degrees) + EllipticalFin.cant_angle : float + Fin cant angle with respect to the rocket centerline, in degrees. + EllipticalFin.changing_attribute_dict : dict + Dictionary that stores the name and the values of the attributes that + may be changed during a simulation. Useful for control systems. + EllipticalFin.cant_angle_rad : float + Fin cant angle with respect to the rocket centerline, in radians. + EllipticalFin.root_chord : float + Fin root chord in meters. + EllipticalFin.span : float + Fin span in meters. + EllipticalFin.name : string + Name of fin set. + EllipticalFin.sweep_length : float + Fin 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. + EllipticalFin.sweep_angle : float + Fin sweep angle with respect to the rocket centerline. Must + be given in degrees. + EllipticalFin.d : float + Reference diameter of the rocket, in meters. + EllipticalFin.ref_area : float + Reference area of the rocket. + EllipticalFin.Af : float + Area of the longitudinal section of each fin in the set. + EllipticalFin.AR : float + Aspect ratio of each fin in the set. + EllipticalFin.gamma_c : float + Fin mid-chord sweep angle. + EllipticalFin.Yma : float + Span wise position of the mean aerodynamic chord. + EllipticalFin.roll_geometrical_constant : float + Geometrical constant used in roll calculations. + EllipticalFin.tau : float + Geometrical relation used to simplify lift and roll calculations. + EllipticalFin.lift_interference_factor : float + Factor of Fin-Body interference in the lift coefficient. + EllipticalFin.cp : tuple + Tuple with the x, y and z local coordinates of the fin set center of + pressure. Has units of length and is given in meters. + EllipticalFin.cpx : float + Fin set local center of pressure x coordinate. Has units of length and + is given in meters. + EllipticalFin.cpy : float + Fin set local center of pressure y coordinate. Has units of length and + is given in meters. + EllipticalFin.cpz : float + Fin set local center of pressure z coordinate. Has units of length and + is given in meters. + EllipticalFin.cl : Function + Function which defines the lift coefficient as a function of the angle + of attack and the Mach number. Takes as input the angle of attack in + radians and the Mach number. Returns the lift coefficient. + EllipticalFin.clalpha : float + Lift coefficient slope. Has units of 1/rad. + """ + + def __init__( + self, + angular_position, + root_chord, + span, + rocket_radius, + cant_angle=0, + airfoil=None, + name="Fin", + ): + """Initialize EllipticalFin class. + + Parameters + ---------- + root_chord : int, float + Fin root chord in meters. + span : int, float + Fin span in meters. + rocket_radius : int, float + Reference radius to calculate lift coefficient, in meters. + cant_angle : int, float, optional + Fin cant angle with respect to the rocket centerline. Must + be given in degrees. + sweep_length : int, float, optional + Fin 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. Cannot be used in conjunction + with sweep_angle. + sweep_angle : int, float, optional + Fin 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 sweep_length. + airfoil : tuple, optional + Default is null, in which case fin will be treated as flat plates. + Otherwise, if tuple, fin will be considered as airfoils. The + tuple's first item specifies the airfoil's lift coefficient + by angle of attack and must be either a .csv, .txt, ndarray + or callable. The .csv and .txt files can contain a single line + header and the first column must specify the angle of attack, while + the second column must specify the lift coefficient. The + ndarray should be as [(x0, y0), (x1, y1), (x2, y2), ...] + where x0 is the angle of attack and y0 is the lift coefficient. + If callable, it should take an angle of attack as input and + return the lift coefficient at that angle of attack. + The tuple's second item is the unit of the angle of attack, + accepting either "radians" or "degrees". + name : str + Name of fin set. + + Returns + ------- + None + """ + + super().__init__( + angular_position, + root_chord, + span, + rocket_radius, + cant_angle, + airfoil, + name, + ) + + self.evaluate_geometrical_parameters() + self.evaluate_center_of_pressure() + self.evaluate_lift_coefficient() + self.evaluate_roll_parameters() + self.evaluate_rotation_matrix() + + def evaluate_center_of_pressure(self): + """Calculates and returns the center of pressure of the fin set in local + coordinates. The center of pressure position is saved and stored as a + tuple. + + Returns + ------- + None + """ + # Center of pressure position in local coordinates + cpz = 0.288 * self.root_chord + self.cpx = 0 + self.cpy = 0 + self.cpz = cpz + self.cp = (self.cpx, self.cpy, self.cpz) + + def evaluate_geometrical_parameters(self): # pylint: disable=too-many-statements + """Calculates and saves fin set's geometrical parameters such as the + fin' area, aspect ratio and parameters for roll movement. + + Returns + ------- + None + """ + + # Compute auxiliary geometrical parameters + # pylint: disable=invalid-name + Af = (np.pi * self.root_chord / 2 * self.span) / 2 # Fin area + gamma_c = 0 # Zero for elliptical fin + AR = 2 * self.span**2 / Af # Fin aspect ratio + Yma = ( + self.span / (3 * np.pi) * np.sqrt(9 * np.pi**2 - 64) + ) # Span wise coord of mean aero chord + roll_geometrical_constant = ( + self.root_chord + * self.span + * ( + 3 * np.pi * self.span**2 + + 32 * self.rocket_radius * self.span + + 12 * np.pi * self.rocket_radius**2 + ) + / 48 + ) + + # Fin–body interference correction parameters + tau = (self.span + self.rocket_radius) / self.rocket_radius + lift_interference_factor = 1 + 1 / tau + if self.span > self.rocket_radius: + roll_damping_interference_factor = 1 + ( + (self.rocket_radius**2) + * ( + 2 + * (self.rocket_radius**2) + * np.sqrt(self.span**2 - self.rocket_radius**2) + * np.log( + ( + 2 + * self.span + * np.sqrt(self.span**2 - self.rocket_radius**2) + + 2 * self.span**2 + ) + / self.rocket_radius + ) + - 2 + * (self.rocket_radius**2) + * np.sqrt(self.span**2 - self.rocket_radius**2) + * np.log(2 * self.span) + + 2 * self.span**3 + - np.pi * self.rocket_radius * self.span**2 + - 2 * (self.rocket_radius**2) * self.span + + np.pi * self.rocket_radius**3 + ) + ) / ( + 2 + * (self.span**2) + * (self.span / 3 + np.pi * self.rocket_radius / 4) + * (self.span**2 - self.rocket_radius**2) + ) + elif self.span < self.rocket_radius: + roll_damping_interference_factor = 1 - ( + self.rocket_radius**2 + * ( + 2 * self.span**3 + - np.pi * self.span**2 * self.rocket_radius + - 2 * self.span * self.rocket_radius**2 + + np.pi * self.rocket_radius**3 + + 2 + * self.rocket_radius**2 + * np.sqrt(-self.span**2 + self.rocket_radius**2) + * np.arctan( + (self.span) / (np.sqrt(-self.span**2 + self.rocket_radius**2)) + ) + - np.pi + * self.rocket_radius**2 + * np.sqrt(-self.span**2 + self.rocket_radius**2) + ) + ) / ( + 2 + * self.span + * (-self.span**2 + self.rocket_radius**2) + * (self.span**2 / 3 + np.pi * self.span * self.rocket_radius / 4) + ) + else: + roll_damping_interference_factor = (28 - 3 * np.pi) / (4 + 3 * np.pi) + + roll_forcing_interference_factor = (1 / np.pi**2) * ( + (np.pi**2 / 4) * ((tau + 1) ** 2 / tau**2) + + ((np.pi * (tau**2 + 1) ** 2) / (tau**2 * (tau - 1) ** 2)) + * np.arcsin((tau**2 - 1) / (tau**2 + 1)) + - (2 * np.pi * (tau + 1)) / (tau * (tau - 1)) + + ((tau**2 + 1) ** 2) + / (tau**2 * (tau - 1) ** 2) + * (np.arcsin((tau**2 - 1) / (tau**2 + 1))) ** 2 + - (4 * (tau + 1)) + / (tau * (tau - 1)) + * np.arcsin((tau**2 - 1) / (tau**2 + 1)) + + (8 / (tau - 1) ** 2) * np.log((tau**2 + 1) / (2 * tau)) + ) + + # Store values + # pylint: disable=invalid-name + self.Af = Af # Fin area + self.AR = AR # Fin aspect ratio + self.gamma_c = gamma_c # Mid chord angle + self.Yma = Yma # Span wise coord of mean aero chord + self.roll_geometrical_constant = roll_geometrical_constant + self.tau = tau + self.lift_interference_factor = lift_interference_factor + self.roll_damping_interference_factor = roll_damping_interference_factor + self.roll_forcing_interference_factor = roll_forcing_interference_factor + + self.evaluate_shape() + + def evaluate_shape(self): + angles = np.arange(0, 180, 5) + x_array = self.root_chord / 2 + self.root_chord / 2 * np.cos(np.radians(angles)) + y_array = self.span * np.sin(np.radians(angles)) + self.shape_vec = [x_array, y_array] + + def info(self): + self.prints.geometry() + self.prints.lift() + + def all_info(self): + self.prints.all() + self.plots.all() diff --git a/rocketpy/rocket/aero_surface/fins/trapezoidal_fin.py b/rocketpy/rocket/aero_surface/fins/trapezoidal_fin.py new file mode 100644 index 000000000..1e4402195 --- /dev/null +++ b/rocketpy/rocket/aero_surface/fins/trapezoidal_fin.py @@ -0,0 +1,205 @@ +import math + +import numpy as np + +from .fin import Fin + + +class TrapezoidalFin(Fin): + def __init__( + self, + angular_position, + root_chord, + tip_chord, + span, + rocket_radius, + cant_angle=0, + sweep_length=None, + sweep_angle=None, + airfoil=None, + name="Fins", + ): + super().__init__( + angular_position, + root_chord, + span, + rocket_radius, + cant_angle, + airfoil, + name, + ) + + # Check if sweep angle or sweep length is given + if sweep_length is not None and sweep_angle is not None: + raise ValueError("Cannot use sweep_length and sweep_angle together") + elif sweep_angle is not None: + sweep_length = math.tan(sweep_angle * math.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 + self._sweep_angle = sweep_angle + + self.evaluate_geometrical_parameters() + self.evaluate_center_of_pressure() + self.evaluate_lift_coefficient() + self.evaluate_roll_parameters() + self.evaluate_rotation_matrix() + + @property + def tip_chord(self): + return self._tip_chord + + @tip_chord.setter + def tip_chord(self, value): + self._tip_chord = value + self.evaluate_geometrical_parameters() + self.evaluate_center_of_pressure() + self.evaluate_lift_coefficient() + self.evaluate_roll_parameters() + + @property + def sweep_angle(self): + return self._sweep_angle + + @sweep_angle.setter + def sweep_angle(self, value): + self._sweep_angle = value + self._sweep_length = math.tan(value * math.pi / 180) * self.span + self.evaluate_geometrical_parameters() + self.evaluate_center_of_pressure() + self.evaluate_lift_coefficient() + self.evaluate_roll_parameters() + + @property + def sweep_length(self): + return self._sweep_length + + @sweep_length.setter + def sweep_length(self, value): + self._sweep_length = value + self.evaluate_geometrical_parameters() + self.evaluate_center_of_pressure() + self.evaluate_lift_coefficient() + self.evaluate_roll_parameters() + + def evaluate_center_of_pressure(self): + """Calculates and returns the center of pressure of the fin set in local + coordinates. The center of pressure position is saved and stored as a + tuple. + + Returns + ------- + None + """ + # Center of pressure position in local coordinates + cpz = (self.sweep_length / 3) * ( + (self.root_chord + 2 * self.tip_chord) / (self.root_chord + self.tip_chord) + ) + (1 / 6) * ( + self.root_chord + + self.tip_chord + - self.root_chord * self.tip_chord / (self.root_chord + self.tip_chord) + ) + self.cpx = 0 + self.cpy = self.Yma + self.cpz = cpz + self.cp = (self.cpx, self.cpy, self.cpz) + + def evaluate_geometrical_parameters(self): + """Calculates and saves fin set's geometrical parameters such as the + fins' area, aspect ratio and parameters for roll movement. + + Returns + ------- + None + """ + + Yr = self.root_chord + self.tip_chord + Af = Yr * self.span / 2 # Fin area + AR = 2 * self.span**2 / Af # Fin aspect ratio + gamma_c = math.atan( + (self.sweep_length + 0.5 * self.tip_chord - 0.5 * self.root_chord) + / (self.span) + ) + Yma = ( + (self.span / 3) * (self.root_chord + 2 * self.tip_chord) / Yr + ) # Span wise coord of mean aero chord + + # Fin–body interference correction parameters + tau = (self.span + self.rocket_radius) / self.rocket_radius + lift_interference_factor = 1 + 1 / tau + λ = self.tip_chord / self.root_chord + + # Parameters for Roll Moment. + # Documented at: https://github.com/RocketPy-Team/RocketPy/blob/master/docs/technical/aerodynamics/Roll_Equations.pdf + roll_geometrical_constant = ( + (self.root_chord + 3 * self.tip_chord) * self.span**3 + + 4 + * (self.root_chord + 2 * self.tip_chord) + * self.rocket_radius + * self.span**2 + + 6 * (self.root_chord + self.tip_chord) * self.span * self.rocket_radius**2 + ) / 12 + roll_damping_interference_factor = 1 + ( + ((tau - λ) / (tau)) - ((1 - λ) / (tau - 1)) * math.log(tau) + ) / ( + ((tau + 1) * (tau - λ)) / (2) - ((1 - λ) * (tau**3 - 1)) / (3 * (tau - 1)) + ) + roll_forcing_interference_factor = (1 / math.pi**2) * ( + (math.pi**2 / 4) * ((tau + 1) ** 2 / tau**2) + + ((math.pi * (tau**2 + 1) ** 2) / (tau**2 * (tau - 1) ** 2)) + * math.asin((tau**2 - 1) / (tau**2 + 1)) + - (2 * math.pi * (tau + 1)) / (tau * (tau - 1)) + + ((tau**2 + 1) ** 2) + / (tau**2 * (tau - 1) ** 2) + * (math.asin((tau**2 - 1) / (tau**2 + 1))) ** 2 + - (4 * (tau + 1)) + / (tau * (tau - 1)) + * math.asin((tau**2 - 1) / (tau**2 + 1)) + + (8 / (tau - 1) ** 2) * math.log((tau**2 + 1) / (2 * tau)) + ) + + # Store values + self.Yr = Yr + self.Af = Af # Fin area + self.AR = AR # Aspect Ratio + self.gamma_c = gamma_c # Mid chord angle + self.Yma = Yma # Span wise coord of mean aero chord + self.roll_geometrical_constant = roll_geometrical_constant + self.tau = tau + self.lift_interference_factor = lift_interference_factor + self.λ = λ + self.roll_damping_interference_factor = roll_damping_interference_factor + self.roll_forcing_interference_factor = roll_forcing_interference_factor + + self.evaluate_shape() + + def evaluate_shape(self): + if self.sweep_length: + points = [ + (0, 0), + (self.sweep_length, self.span), + (self.sweep_length + self.tip_chord, self.span), + (self.root_chord, 0), + ] + else: + points = [ + (0, 0), + (self.root_chord - self.tip_chord, self.span), + (self.root_chord, self.span), + (self.root_chord, 0), + ] + + x_array, y_array = zip(*points) + self.shape_vec = [np.array(x_array), np.array(y_array)] + + def info(self): + self.prints.geometry() + self.prints.lift() + + def all_info(self): + self.prints.all() + self.plots.all() From 9e7d708d6d3b41c1550636eac04d5d3823e521d3 Mon Sep 17 00:00:00 2001 From: MateusStano Date: Wed, 11 Sep 2024 14:02:14 +0200 Subject: [PATCH 03/32] ENH: add fin method to rocket class --- rocketpy/__init__.py | 7 +- rocketpy/rocket/__init__.py | 7 +- rocketpy/rocket/aero_surface/__init__.py | 13 +- rocketpy/rocket/aero_surface/fins/__init__.py | 3 + rocketpy/rocket/aero_surface/fins/fins.py | 4 +- rocketpy/rocket/rocket.py | 218 +++++++++++++++++- 6 files changed, 235 insertions(+), 17 deletions(-) diff --git a/rocketpy/__init__.py b/rocketpy/__init__.py index 8585f5c95..8a11793bf 100644 --- a/rocketpy/__init__.py +++ b/rocketpy/__init__.py @@ -28,16 +28,19 @@ AeroSurface, AirBrakes, Components, + EllipticalFin, EllipticalFins, + Fin, Fins, + GenericSurface, + LinearGenericSurface, NoseCone, Parachute, RailButtons, Rocket, Tail, + TrapezoidalFin, TrapezoidalFins, - GenericSurface, - LinearGenericSurface, ) from .simulation import Flight, MonteCarlo from .stochastic import ( diff --git a/rocketpy/rocket/__init__.py b/rocketpy/rocket/__init__.py index db7c4f6ce..2d38286c3 100644 --- a/rocketpy/rocket/__init__.py +++ b/rocketpy/rocket/__init__.py @@ -2,14 +2,17 @@ from rocketpy.rocket.aero_surface import ( AeroSurface, AirBrakes, + EllipticalFin, EllipticalFins, + Fin, Fins, + GenericSurface, + LinearGenericSurface, NoseCone, RailButtons, Tail, + TrapezoidalFin, TrapezoidalFins, - GenericSurface, - LinearGenericSurface, ) from rocketpy.rocket.components import Components from rocketpy.rocket.parachute import Parachute diff --git a/rocketpy/rocket/aero_surface/__init__.py b/rocketpy/rocket/aero_surface/__init__.py index 58192513c..f31663bec 100644 --- a/rocketpy/rocket/aero_surface/__init__.py +++ b/rocketpy/rocket/aero_surface/__init__.py @@ -1,8 +1,15 @@ from rocketpy.rocket.aero_surface.aero_surface import AeroSurface from rocketpy.rocket.aero_surface.air_brakes import AirBrakes -from rocketpy.rocket.aero_surface.fins import EllipticalFins, Fins, TrapezoidalFins +from rocketpy.rocket.aero_surface.fins import ( + EllipticalFin, + EllipticalFins, + Fin, + Fins, + TrapezoidalFin, + TrapezoidalFins, +) +from rocketpy.rocket.aero_surface.generic_surface import GenericSurface +from rocketpy.rocket.aero_surface.linear_generic_surface import LinearGenericSurface from rocketpy.rocket.aero_surface.nose_cone import NoseCone from rocketpy.rocket.aero_surface.rail_buttons import RailButtons from rocketpy.rocket.aero_surface.tail import Tail -from rocketpy.rocket.aero_surface.generic_surface import GenericSurface -from rocketpy.rocket.aero_surface.linear_generic_surface import LinearGenericSurface diff --git a/rocketpy/rocket/aero_surface/fins/__init__.py b/rocketpy/rocket/aero_surface/fins/__init__.py index f1efc603a..88e1ce978 100644 --- a/rocketpy/rocket/aero_surface/fins/__init__.py +++ b/rocketpy/rocket/aero_surface/fins/__init__.py @@ -1,3 +1,6 @@ +from rocketpy.rocket.aero_surface.fins.elliptical_fin import EllipticalFin from rocketpy.rocket.aero_surface.fins.elliptical_fins import EllipticalFins +from rocketpy.rocket.aero_surface.fins.fin import Fin from rocketpy.rocket.aero_surface.fins.fins import Fins +from rocketpy.rocket.aero_surface.fins.trapezoidal_fin import TrapezoidalFin from rocketpy.rocket.aero_surface.fins.trapezoidal_fins import TrapezoidalFins diff --git a/rocketpy/rocket/aero_surface/fins/fins.py b/rocketpy/rocket/aero_surface/fins/fins.py index b4aa2f790..38614eb47 100644 --- a/rocketpy/rocket/aero_surface/fins/fins.py +++ b/rocketpy/rocket/aero_surface/fins/fins.py @@ -328,7 +328,7 @@ def evaluate_roll_parameters(self): ) # Function of mach number clf_delta.set_inputs("Mach") clf_delta.set_outputs("Roll moment forcing coefficient derivative") - cld_omega = ( + cld_omega = -( 2 * self.roll_damping_interference_factor * self.n @@ -411,7 +411,7 @@ def compute_forces_and_moments( * omega3 / 2 ) - M3 = M3_forcing - M3_damping + M3 = M3_forcing + M3_damping return R1, R2, R3, M1, M2, M3 def draw(self): diff --git a/rocketpy/rocket/rocket.py b/rocketpy/rocket/rocket.py index e1dc7c6fc..fa4415238 100644 --- a/rocketpy/rocket/rocket.py +++ b/rocketpy/rocket/rocket.py @@ -18,6 +18,9 @@ Tail, TrapezoidalFins, ) +from rocketpy.rocket.aero_surface.fins.elliptical_fin import EllipticalFin +from rocketpy.rocket.aero_surface.fins.fin import Fin +from rocketpy.rocket.aero_surface.fins.trapezoidal_fin import TrapezoidalFin from rocketpy.rocket.aero_surface.generic_surface import GenericSurface from rocketpy.rocket.components import Components from rocketpy.rocket.parachute import Parachute @@ -574,14 +577,29 @@ def evaluate_single_surface_cp_to_cdm(self, surface, position): """Calculates the relative position of each aerodynamic surface center of pressure to the rocket's center of dry mass in Body Axes Coordinate System.""" - pos = Vector( - [ - (position.x - self.cm_eccentricity_x) * self._csys - surface.cpx, - (position.y - self.cm_eccentricity_y) - surface.cpy, - (position.z - self.center_of_dry_mass_position) * self._csys - - surface.cpz, - ] - ) + # try for individual fin + if isinstance(surface, Fin): + # TODO: include cm_eccentricity_x and cm_eccentricity_y for Fin + pos = Vector( + [ + -(surface.rocket_radius + surface.cpy) + * -np.sin(surface.angular_position_rad) + * self._csys, + (surface.rocket_radius + surface.cpy) + * np.cos(surface.angular_position_rad), + (position.z - self.center_of_dry_mass_position) * self._csys + - surface.cpz, + ] + ) + else: + pos = Vector( + [ + (position.x - self.cm_eccentricity_x) * self._csys - surface.cpx, + (position.y - self.cm_eccentricity_y) + surface.cpy, + (position.z - self.center_of_dry_mass_position) * self._csys + - surface.cpz, + ] + ) self.surfaces_cp_to_cdm[surface] = pos def evaluate_stability_margin(self): @@ -1323,6 +1341,190 @@ def add_elliptical_fins( self.add_surfaces(fin_set, position) return fin_set + def add_trapezoidal_fin( + self, + root_chord, + tip_chord, + span, + position, + angular_position, + cant_angle=0.0, + sweep_length=None, + sweep_angle=None, + radius=None, + airfoil=None, + name="Fin", + ): + """Adds a single fin to the rocket. This method is useful when the user + wants to add a single fin with a specific shape and position. + + See Also + -------- + :ref:`positions` + + Parameters + ---------- + root_chord : int, float + Fin root chord in meters. + tip_chord : int, float + Fin tip chord in meters. + span : int, float + Fin span in meters. + position : int, float + Fin position relative to the rocket's user defined coordinate system. + By fin position, understand the point belonging to the root chord + which is highest in the rocket coordinate system (i.e. the point + closest to the nose cone tip). + angular_position : int, float + The angular orientation of the fin. This is the angle measured + from the positive y-axis, with positive values corresponding to a + positive rotation about the z-axis. + cant_angle : int, float, optional + Fins cant angle with respect to the rocket centerline. Must be given + in degrees. Default is 0. + sweep_length : 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. Cannot be used in conjunction + with sweep_angle. Default is None. + sweep_angle : 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 sweep_length. Default is None. + radius : int, float, optional + Radius of the rocket at the fin position. If not given, the rocket + radius will be used. Default is None. + airfoil : tuple, optional + Default is null, in which case fins will be treated as flat plates. + Otherwise, if tuple, fins will be considered as airfoils. The + tuple's first item specifies the airfoil's lift coefficient + by angle of attack and must be either a .csv, .txt, ndarray + or callable. The .csv and .txt files can contain a single line + header and the first column must specify the angle of attack, while + the second column must specify the lift coefficient. The + ndarray should be as [(x0, y0), (x1, y1), (x2, y2), ...] + where x0 is the angle of attack and y0 is the lift coefficient. + If callable, it should take an angle of attack as input and + return the lift coefficient at that angle of attack. + The tuple's second item is the unit of the angle of attack, + accepting either "radians" or "degrees". Default is None. + name : string, optional + Fin name. Default is "Fin". + + Returns + ------- + fin : Fin + Fin object created. + """ + radius = radius or self.radius + fin = TrapezoidalFin( + angular_position=angular_position, + root_chord=root_chord, + tip_chord=tip_chord, + span=span, + rocket_radius=radius, + cant_angle=cant_angle, + sweep_length=sweep_length, + sweep_angle=sweep_angle, + airfoil=airfoil, + name=name, + ) + position = Vector( + [ + radius * -math.sin(math.radians(angular_position)), + radius * math.cos(math.radians(angular_position)), + position, + ] + ) + self.add_surfaces(fin, position) + return fin + + def add_elliptical_fin( + self, + root_chord, + span, + position, + angular_position, + cant_angle=0.0, + radius=None, + airfoil=None, + name="Fin", + ): + """Adds a single fin to the rocket. This method is useful when the user + wants to add a single fin with a specific shape and position. + + See Also + -------- + :ref:`positions` + + Parameters + ---------- + root_chord : int, float + Fin root chord in meters. + span : int, float + Fin span in meters. + position : int, float + Fin position relative to the rocket's user defined coordinate system. + By fin position, understand the point belonging to the root chord + which is highest in the rocket coordinate system (i.e. the point + closest to the nose cone tip). + angular_position : int, float + The angular orientation of the fin. This is the angle measured + from the positive y-axis, with positive values corresponding to a + positive rotation about the z-axis. + cant_angle : int, float, optional + Fins cant angle with respect to the rocket centerline. Must be given + in degrees. Default is 0. + radius : int, float, optional + Radius of the rocket at the fin position. If not given, the rocket + radius will be used. Default is None. + airfoil : tuple, optional + Default is null, in which case fins will be treated as flat plates. + Otherwise, if tuple, fins will be considered as airfoils. The + tuple's first item specifies the airfoil's lift coefficient + by angle of attack and must be either a .csv, .txt, ndarray + or callable. The .csv and .txt files can contain a single line + header and the first column must specify the angle of attack, while + the second column must specify the lift coefficient. The + ndarray should be as [(x0, y0), (x1, y1), (x2, y2), ...] + where x0 is the angle of attack and y0 is the lift coefficient. + If callable, it should take an angle of attack as input and + return the lift coefficient at that angle of attack. + The tuple's second item is the unit of the angle of attack, + accepting either "radians" or "degrees". Default is None. + name : string, optional + Fin name. Default is "Fin". + + Returns + ------- + fin : Fin + Fin object created. + """ + radius = radius or self.radius + fin = EllipticalFin( + angular_position=angular_position, + root_chord=root_chord, + span=span, + rocket_radius=radius, + cant_angle=cant_angle, + airfoil=airfoil, + name=name, + ) + position = Vector( + [ + radius * -math.sin(math.radians(angular_position)), + radius * math.cos(math.radians(angular_position)), + position, + ] + ) + self.add_surfaces(fin, position) + return fin + def add_generic_surface( self, generic_surface, From 6a63b4d239a4e7f6b47d5b8ac7088bb612e6a381 Mon Sep 17 00:00:00 2001 From: Julio Machado Date: Thu, 12 Sep 2024 15:27:54 -0300 Subject: [PATCH 04/32] ENH: add print and plots to individual fins classes. --- rocketpy/plots/aero_surface_plots.py | 253 ++++++++++++++++++ rocketpy/plots/rocket_plots.py | 33 ++- rocketpy/prints/aero_surface_prints.py | 108 +++++++- .../aero_surface/fins/elliptical_fin.py | 6 + .../aero_surface/fins/trapezoidal_fin.py | 6 + 5 files changed, 403 insertions(+), 3 deletions(-) diff --git a/rocketpy/plots/aero_surface_plots.py b/rocketpy/plots/aero_surface_plots.py index c242973b3..174f94b3b 100644 --- a/rocketpy/plots/aero_surface_plots.py +++ b/rocketpy/plots/aero_surface_plots.py @@ -188,6 +188,67 @@ def all(self): self.lift() +class _FinPlots(_AeroSurfacePlots): + """Abstract class that contains all fin plots. This class inherits from the + _AeroSurfacePlots class.""" + + @abstractmethod + def draw(self): + pass + + def airfoil(self): + """Plots the airfoil information when the fin has an airfoil shape. If + the fin does not have an airfoil shape, this method does nothing. + + Returns + ------- + None + """ + + if self.aero_surface.airfoil: + print("Airfoil lift curve:") + self.aero_surface.airfoil_cl.plot_1d(force_data=True) + + def roll(self): + """Plots the roll parameters of the fin set. + + Returns + ------- + None + """ + print("Roll parameters:") + # TODO: lacks a title in the plots + self.aero_surface.roll_parameters[0]() + self.aero_surface.roll_parameters[1]() + + def lift(self): + """Plots the lift coefficient of the aero surface as a function of Mach + and the angle of attack. A 3D plot is expected. See the rocketpy.Function + class for more information on how this plot is made. Also, this method + plots the lift coefficient considering a single fin and the lift + coefficient considering all fins. + + Returns + ------- + None + """ + print("Lift coefficient:") + self.aero_surface.cl() + self.aero_surface.clalpha_single_fin() + + def all(self): + """Plots all available fin plots. + + Returns + ------- + None + """ + self.draw() + self.airfoil() + self.roll() + self.lift() + + class _TrapezoidalFinsPlots(_FinsPlots): """Class that contains all trapezoidal fin plots.""" @@ -309,6 +370,127 @@ def draw(self): plt.show() +class _TrapezoidalFinPlots(_FinPlots): + """Class that contains all trapezoidal fin plots.""" + + # pylint: disable=too-many-statements + def draw(self): + """Draw the fin shape along with some important information, including + the center line, the quarter line and the center of pressure position. + + Returns + ------- + None + """ + # Color cycle [#348ABD, #A60628, #7A68A6, #467821, #D55E00, #CC79A7, + # #56B4E9, #009E73, #F0E442, #0072B2] + # Fin + leading_edge = plt.Line2D( + (0, self.aero_surface.sweep_length), + (0, self.aero_surface.span), + color="#A60628", + ) + tip = plt.Line2D( + ( + self.aero_surface.sweep_length, + self.aero_surface.sweep_length + self.aero_surface.tip_chord, + ), + (self.aero_surface.span, self.aero_surface.span), + color="#A60628", + ) + back_edge = plt.Line2D( + ( + self.aero_surface.sweep_length + self.aero_surface.tip_chord, + self.aero_surface.root_chord, + ), + (self.aero_surface.span, 0), + color="#A60628", + ) + root = plt.Line2D((self.aero_surface.root_chord, 0), (0, 0), color="#A60628") + + # Center and Quarter line + center_line = plt.Line2D( + ( + self.aero_surface.root_chord / 2, + self.aero_surface.sweep_length + self.aero_surface.tip_chord / 2, + ), + (0, self.aero_surface.span), + color="#7A68A6", + alpha=0.35, + linestyle="--", + label="Center Line", + ) + quarter_line = plt.Line2D( + ( + self.aero_surface.root_chord / 4, + self.aero_surface.sweep_length + self.aero_surface.tip_chord / 4, + ), + (0, self.aero_surface.span), + color="#7A68A6", + alpha=1, + linestyle="--", + label="Quarter Line", + ) + + # Center of pressure + cp_point = [self.aero_surface.cpz, self.aero_surface.Yma] + + # Mean Aerodynamic Chord + yma_start = ( + self.aero_surface.sweep_length + * (self.aero_surface.root_chord + 2 * self.aero_surface.tip_chord) + / (3 * (self.aero_surface.root_chord + self.aero_surface.tip_chord)) + ) + yma_end = ( + 2 * self.aero_surface.root_chord**2 + + self.aero_surface.root_chord * self.aero_surface.sweep_length + + 2 * self.aero_surface.root_chord * self.aero_surface.tip_chord + + 2 * self.aero_surface.sweep_length * self.aero_surface.tip_chord + + 2 * self.aero_surface.tip_chord**2 + ) / (3 * (self.aero_surface.root_chord + self.aero_surface.tip_chord)) + yma_line = plt.Line2D( + (yma_start, yma_end), + (self.aero_surface.Yma, self.aero_surface.Yma), + color="#467821", + linestyle="--", + label="Mean Aerodynamic Chord", + ) + + # Plotting + fig = plt.figure(figsize=(7, 4)) + with plt.style.context("bmh"): + ax = fig.add_subplot(111) + + # Fin + ax.add_line(leading_edge) + ax.add_line(tip) + ax.add_line(back_edge) + ax.add_line(root) + + ax.add_line(center_line) + ax.add_line(quarter_line) + ax.add_line(yma_line) + ax.scatter(*cp_point, label="Center of Pressure", color="red", s=100, zorder=10) + ax.scatter(*cp_point, facecolors="none", edgecolors="red", s=500, zorder=10) + + # Plot settings + xlim = ( + self.aero_surface.root_chord + if self.aero_surface.sweep_length + self.aero_surface.tip_chord + < self.aero_surface.root_chord + else self.aero_surface.sweep_length + self.aero_surface.tip_chord + ) + ax.set_xlim(0, xlim * 1.1) + ax.set_ylim(0, self.aero_surface.span * 1.1) + ax.set_xlabel("Root chord (m)") + ax.set_ylabel("Span (m)") + ax.set_title("Trapezoidal Fin Cross Section") + ax.legend(bbox_to_anchor=(1.05, 1.0), loc="upper left") + + plt.tight_layout() + plt.show() + + class _EllipticalFinsPlots(_FinsPlots): """Class that contains all elliptical fin plots.""" @@ -380,6 +562,77 @@ def draw(self): plt.show() +class _EllipticalFinPlots(_FinPlots): + """Class that contains all elliptical fin plots.""" + + # pylint: disable=too-many-statements + def draw(self): + """Draw the fin shape along with some important information. + These being: the center line and the center of pressure position. + + Returns + ------- + None + """ + # Ellipse + ellipse = Ellipse( + (self.aero_surface.root_chord / 2, 0), + self.aero_surface.root_chord, + self.aero_surface.span * 2, + fill=False, + edgecolor="#A60628", + linewidth=2, + ) + + # Mean Aerodynamic Chord # From Barrowman's theory + yma_length = 8 * self.aero_surface.root_chord / (3 * np.pi) + yma_start = (self.aero_surface.root_chord - yma_length) / 2 + yma_end = ( + self.aero_surface.root_chord + - (self.aero_surface.root_chord - yma_length) / 2 + ) + yma_line = plt.Line2D( + (yma_start, yma_end), + (self.aero_surface.Yma, self.aero_surface.Yma), + label="Mean Aerodynamic Chord", + color="#467821", + ) + + # Center Line + center_line = plt.Line2D( + (self.aero_surface.root_chord / 2, self.aero_surface.root_chord / 2), + (0, self.aero_surface.span), + color="#7A68A6", + alpha=0.35, + linestyle="--", + label="Center Line", + ) + + # Center of pressure + cp_point = [self.aero_surface.cpz, self.aero_surface.Yma] + + # Plotting + fig = plt.figure(figsize=(7, 4)) + with plt.style.context("bmh"): + ax = fig.add_subplot(111) + ax.add_patch(ellipse) + ax.add_line(yma_line) + ax.add_line(center_line) + ax.scatter(*cp_point, label="Center of Pressure", color="red", s=100, zorder=10) + ax.scatter(*cp_point, facecolors="none", edgecolors="red", s=500, zorder=10) + + # Plot settings + ax.set_xlim(0, self.aero_surface.root_chord) + ax.set_ylim(0, self.aero_surface.span * 1.1) + ax.set_xlabel("Root chord (m)") + ax.set_ylabel("Span (m)") + ax.set_title("Elliptical Fin Cross Section") + ax.legend(bbox_to_anchor=(1.05, 1.0), loc="upper left") + + plt.tight_layout() + plt.show() + + class _TailPlots(_AeroSurfacePlots): """Class that contains all tail plots.""" diff --git a/rocketpy/plots/rocket_plots.py b/rocketpy/plots/rocket_plots.py index 9581619c0..e4d363939 100644 --- a/rocketpy/plots/rocket_plots.py +++ b/rocketpy/plots/rocket_plots.py @@ -4,7 +4,7 @@ import numpy as np from rocketpy.motors import EmptyMotor, HybridMotor, LiquidMotor, SolidMotor -from rocketpy.rocket.aero_surface import Fins, NoseCone, Tail +from rocketpy.rocket.aero_surface import Fins, Fin, NoseCone, Tail class _RocketPlots: @@ -242,6 +242,8 @@ def _draw_aerodynamic_surfaces(self, ax, vis_args): self._draw_tail(ax, surface, position.z, drawn_surfaces, vis_args) elif isinstance(surface, Fins): self._draw_fins(ax, surface, position.z, drawn_surfaces, vis_args) + elif isinstance(surface, Fin): + self._draw_fin(ax, surface, position.z, drawn_surfaces, vis_args) return drawn_surfaces def _draw_nose_cone(self, ax, surface, position, drawn_surfaces, vis_args): @@ -334,6 +336,35 @@ def _draw_fins(self, ax, surface, position, drawn_surfaces, vis_args): drawn_surfaces.append((surface, position, surface.rocket_radius, x_rotated[-1])) + def _draw_fin(self, ax, surface, position, drawn_surfaces, vis_args): + """Draws the fins and saves the position of the points of interest + for the tubes.""" + + x_fin = -self.rocket._csys * surface.shape_vec[0] + position + y_fin = surface.shape_vec[1] + surface.rocket_radius + angle = surface.angular_position + + # Create a rotation matrix for the angle around the x-axis + rotation_matrix = np.array([[1, 0], [0, np.cos(angle)]]) + + # Apply the rotation to the original fin points + rotated_points_2d = np.dot(rotation_matrix, np.vstack((x_fin, y_fin))) + + # Extract x and y coordinates of the rotated points + x_rotated, y_rotated = rotated_points_2d + + # Project points above the XY plane back into the XY plane (set z-coordinate to 0) + x_rotated = np.where(rotated_points_2d[1] > 0, rotated_points_2d[0], x_rotated) + y_rotated = np.where(rotated_points_2d[1] > 0, rotated_points_2d[1], y_rotated) + ax.plot( + x_rotated, + y_rotated, + color=vis_args["fins"], + linewidth=vis_args["line_width"], + ) + + drawn_surfaces.append((surface, position, surface.rocket_radius, x_rotated[-1])) + def _draw_tubes(self, ax, drawn_surfaces, vis_args): """Draws the tubes between the aerodynamic surfaces.""" for i, d_surface in enumerate(drawn_surfaces): diff --git a/rocketpy/prints/aero_surface_prints.py b/rocketpy/prints/aero_surface_prints.py index 7cc87c28f..8229fc072 100644 --- a/rocketpy/prints/aero_surface_prints.py +++ b/rocketpy/prints/aero_surface_prints.py @@ -157,9 +157,105 @@ def lift(self): "Lift Coefficient derivative (single fin) at Mach 0 and AoA 0: " f"{self.aero_surface.clalpha_single_fin(0):.3f}" ) + + def all(self): + """Prints all information of the fin set. + + Returns + ------- + None + """ + self.identity() + self.geometry() + self.airfoil() + self.roll() + self.lift() + + +class _FinPrints(_AeroSurfacePrints): + + def geometry(self): + print("Geometric information of the fin set:") + print("-------------------------------------") + print(f"Reference rocket radius: {self.aero_surface.rocket_radius:.3f} m") + try: + print(f"Tip chord: {self.aero_surface.tip_chord:.3f} m") + except AttributeError: + pass # it isn't a trapezoidal fin, just don't worry about tip chord + print(f"Root chord: {self.aero_surface.root_chord:.3f} m") + print(f"Span: {self.aero_surface.span:.3f} m") print( - "Lift Coefficient derivative (fin set) at Mach 0 and AoA 0: " - f"{self.aero_surface.clalpha_multiple_fins(0):.3f}" + f"Cant angle: {self.aero_surface.cant_angle:.3f} ° or " + f"{self.aero_surface.cant_angle_rad:.3f} rad" + ) + print(f"Longitudinal section area: {self.aero_surface.Af:.3f} m²") + print(f"Aspect ratio: {self.aero_surface.AR:.3f} ") + print(f"Gamma_c: {self.aero_surface.gamma_c:.3f} m") + print(f"Mean aerodynamic chord: {self.aero_surface.Yma:.3f} m\n") + + def airfoil(self): + """Prints out airfoil related information of the fin set. + + Returns + ------- + None + """ + if self.aero_surface.airfoil: + print("Airfoil information:") + print("--------------------") + print( + "Number of points defining the lift curve: " + f"{len(self.aero_surface.airfoil_cl.x_array)}" + ) + print( + "Lift coefficient derivative at Mach 0 and AoA 0: " + f"{self.aero_surface.clalpha(0):.5f} 1/rad\n" + ) + + def roll(self): + """Prints out information about roll parameters + of the fin set. + + Returns + ------- + None + """ + print("Roll information of the fin set:") + print("--------------------------------") + print( + f"Geometric constant: {self.aero_surface.roll_geometrical_constant:.3f} m" + ) + print( + "Damping interference factor: " + f"{self.aero_surface.roll_damping_interference_factor:.3f} rad" + ) + print( + "Forcing interference factor: " + f"{self.aero_surface.roll_forcing_interference_factor:.3f} rad\n" + ) + + def lift(self): + """Prints out information about lift parameters + of the fin set. + + Returns + ------- + None + """ + print("Lift information of the fin set:") + print("--------------------------------") + print( + "Lift interference factor: " + f"{self.aero_surface.lift_interference_factor:.3f} m" + ) + print( + "Center of Pressure position in local coordinates: " + f"({self.aero_surface.cpx:.3f}, {self.aero_surface.cpy:.3f}, " + f"{self.aero_surface.cpz:.3f})" + ) + print( + "Lift Coefficient derivative (single fin) at Mach 0 and AoA 0: " + f"{self.aero_surface.clalpha_single_fin(0):.3f}" ) def all(self): @@ -180,10 +276,18 @@ class _TrapezoidalFinsPrints(_FinsPrints): """Class that contains all trapezoidal fins prints.""" +class _TrapezoidalFinPrints(_FinPrints): + """Class that contains all trapezoidal fin prints.""" + + class _EllipticalFinsPrints(_FinsPrints): """Class that contains all elliptical fins prints.""" +class _EllipticalFinPrints(_FinPrints): + """Class that contains all elliptical fin prints.""" + + class _TailPrints(_AeroSurfacePrints): """Class that contains all tail prints.""" diff --git a/rocketpy/rocket/aero_surface/fins/elliptical_fin.py b/rocketpy/rocket/aero_surface/fins/elliptical_fin.py index 46cf50ed4..06def168b 100644 --- a/rocketpy/rocket/aero_surface/fins/elliptical_fin.py +++ b/rocketpy/rocket/aero_surface/fins/elliptical_fin.py @@ -2,6 +2,9 @@ from .fin import Fin +from rocketpy.plots.aero_surface_plots import _EllipticalFinPlots +from rocketpy.prints.aero_surface_prints import _EllipticalFinPrints + class EllipticalFin(Fin): """Class that defines and holds information for an elliptical fin. @@ -159,6 +162,9 @@ def __init__( self.evaluate_roll_parameters() self.evaluate_rotation_matrix() + self.prints = _EllipticalFinPrints(self) + self.plots = _EllipticalFinPlots(self) + def evaluate_center_of_pressure(self): """Calculates and returns the center of pressure of the fin set in local coordinates. The center of pressure position is saved and stored as a diff --git a/rocketpy/rocket/aero_surface/fins/trapezoidal_fin.py b/rocketpy/rocket/aero_surface/fins/trapezoidal_fin.py index 1e4402195..67db3860a 100644 --- a/rocketpy/rocket/aero_surface/fins/trapezoidal_fin.py +++ b/rocketpy/rocket/aero_surface/fins/trapezoidal_fin.py @@ -2,6 +2,9 @@ import numpy as np +from rocketpy.plots.aero_surface_plots import _TrapezoidalFinPlots +from rocketpy.prints.aero_surface_prints import _TrapezoidalFinPrints + from .fin import Fin @@ -49,6 +52,9 @@ def __init__( self.evaluate_roll_parameters() self.evaluate_rotation_matrix() + self.prints = _TrapezoidalFinPrints(self) + self.plots = _TrapezoidalFinPlots(self) + @property def tip_chord(self): return self._tip_chord From ce70197cc9cf89f899242c6d01e3282b91f0ecda Mon Sep 17 00:00:00 2001 From: Julio Machado Date: Fri, 20 Sep 2024 23:39:47 -0300 Subject: [PATCH 05/32] ENH: Lint corrections, mainly attribute names. --- docs/notebooks/coeff_testing.ipynb | 311 +++++++++++------- rocketpy/plots/rocket_plots.py | 2 +- .../aero_surface/fins/elliptical_fin.py | 4 +- rocketpy/rocket/aero_surface/fins/fin.py | 6 +- .../aero_surface/fins/trapezoidal_fin.py | 109 +++++- .../rocket/aero_surface/generic_surface.py | 31 +- .../aero_surface/linear_generic_surface.py | 146 ++++---- 7 files changed, 390 insertions(+), 219 deletions(-) diff --git a/docs/notebooks/coeff_testing.ipynb b/docs/notebooks/coeff_testing.ipynb index 26e5f77c1..80ea83b55 100644 --- a/docs/notebooks/coeff_testing.ipynb +++ b/docs/notebooks/coeff_testing.ipynb @@ -380,7 +380,7 @@ " position=-1.04956,\n", " cant_angle=0.5,\n", " airfoil=(\"../../data/calisto/NACA0012-radians.csv\", \"radians\"),\n", - " name=\"FinSet\"\n", + " name=\"FinSet\",\n", ")\n", "\n", "\n", @@ -444,7 +444,7 @@ " position=-1.04956,\n", " cant_angle=0.5,\n", " airfoil=(\"../../data/calisto/NACA0012-radians.csv\", \"radians\"),\n", - " name=\"FinSet\"\n", + " name=\"FinSet\",\n", ")\n", "\n", "\n", @@ -455,30 +455,38 @@ "from rocketpy import GenericSurface, Function\n", "import numpy as np\n", "\n", - "gennose=GenericSurface(reference_area=np.pi*calisto.radius**2,\n", - " reference_length=2*calisto.radius,\n", - " cL=\"nose_cL.csv\",\n", - " cQ=\"nose_cQ.csv\",\n", - " center_of_pressure=(0,0,0),\n", - " name=\"nose\")\n", - "genfin=GenericSurface(reference_area=np.pi*calisto.radius**2,\n", - " reference_length=2*calisto.radius,\n", - " cL=\"fins_cL.csv\",\n", - " cQ=\"fins_cQ.csv\",\n", - " cl=\"fins_roll.csv\",\n", - " center_of_pressure=(0,0,0),\n", - " name=\"fins\")\n", - "gentail=GenericSurface(reference_area=np.pi*calisto.radius**2,\n", - " reference_length=2*calisto.radius,\n", - " cL=\"tail_cL.csv\",\n", - " cQ=\"tail_cQ.csv\",\n", - " center_of_pressure=(0,0,0),\n", - " name=\"tail\")\n", - "\n", - "posnose=1.278-nose_cone.cpz\n", - "posfin=-1.04956-fin_set.cpz\n", - "postail=-1.194656-tail.cpz\n", - "calisto.aerodynamic_surfaces.pop(); calisto.aerodynamic_surfaces.pop(); calisto.aerodynamic_surfaces.pop() \n", + "gennose = GenericSurface(\n", + " reference_area=np.pi * calisto.radius**2,\n", + " reference_length=2 * calisto.radius,\n", + " cL=\"nose_cL.csv\",\n", + " cQ=\"nose_cQ.csv\",\n", + " center_of_pressure=(0, 0, 0),\n", + " name=\"nose\",\n", + ")\n", + "genfin = GenericSurface(\n", + " reference_area=np.pi * calisto.radius**2,\n", + " reference_length=2 * calisto.radius,\n", + " cL=\"fins_cL.csv\",\n", + " cQ=\"fins_cQ.csv\",\n", + " cl=\"fins_roll.csv\",\n", + " center_of_pressure=(0, 0, 0),\n", + " name=\"fins\",\n", + ")\n", + "gentail = GenericSurface(\n", + " reference_area=np.pi * calisto.radius**2,\n", + " reference_length=2 * calisto.radius,\n", + " cL=\"tail_cL.csv\",\n", + " cQ=\"tail_cQ.csv\",\n", + " center_of_pressure=(0, 0, 0),\n", + " name=\"tail\",\n", + ")\n", + "\n", + "posnose = 1.278 - nose_cone.cpz\n", + "posfin = -1.04956 - fin_set.cpz\n", + "postail = -1.194656 - tail.cpz\n", + "calisto.aerodynamic_surfaces.pop()\n", + "calisto.aerodynamic_surfaces.pop()\n", + "calisto.aerodynamic_surfaces.pop()\n", "calisto.add_generic_surface(gennose, position=posnose, angular_position=0, radius=0)\n", "calisto.add_generic_surface(genfin, position=posfin, angular_position=0, radius=0)\n", "calisto.add_generic_surface(gentail, position=postail, angular_position=0, radius=0)" @@ -523,7 +531,7 @@ } ], "source": [ - "Function(lambda mach: genfin.cl(0,0,mach,0,0,0,0)).plot(0,2) " + "Function(lambda mach: genfin.cl(0, 0, mach, 0, 0, 0, 0)).plot(0, 2)" ] }, { @@ -533,6 +541,8 @@ "outputs": [], "source": [ "import numpy as np\n", + "\n", + "\n", "def std():\n", " \"\"\"Function to extract the coefficients from standard aerosurfaces\"\"\"\n", " # call nose_cone.cl at several mach and alpha and save it to a csv file\n", @@ -551,21 +561,21 @@ " for mach in machs:\n", " cL = nose_cone.cl(alpha, mach)\n", " f.write(f\"{alpha},{mach},{cL}\\n\")\n", - " \n", + "\n", " with open(\"nose_cQ.csv\", \"w\") as f:\n", " f.write(\"beta,mach,cL\\n\")\n", " for alpha in alphas:\n", " for mach in machs:\n", " cL = nose_cone.cl(alpha, mach)\n", " f.write(f\"{alpha},{mach},{cL}\\n\")\n", - " \n", + "\n", " with open(\"fins_cL.csv\", \"w\") as f:\n", " f.write(\"alpha,mach,cL\\n\")\n", " for alpha in alphas:\n", " for mach in machs:\n", " cL = fin_set.cl(alpha, mach)\n", " f.write(f\"{alpha},{mach},{cL}\\n\")\n", - " \n", + "\n", " with open(\"fins_cQ.csv\", \"w\") as f:\n", " f.write(\"beta,mach,cL\\n\")\n", " for alpha in alphas:\n", @@ -574,10 +584,15 @@ " f.write(f\"{alpha},{mach},{cL}\\n\")\n", "\n", " clf_delta, cld_omega, _ = fin_set.roll_parameters\n", + "\n", " def cll(mach, roll_rate):\n", " if mach == 0:\n", " return clf_delta(mach) * fin_set.cant_angle_rad\n", - " return clf_delta(mach) * fin_set.cant_angle_rad - fin_set.reference_length / (2*mach*343) * cld_omega(mach) * roll_rate\n", + " return (\n", + " clf_delta(mach) * fin_set.cant_angle_rad\n", + " - fin_set.reference_length / (2 * mach * 343) * cld_omega(mach) * roll_rate\n", + " )\n", + "\n", " cl = Function(lambda mach, roll_rate: cll(mach, roll_rate))\n", " with open(\"fins_roll.csv\", \"w\") as f:\n", " f.write(\"mach,roll_rate,cl\\n\")\n", @@ -585,22 +600,22 @@ " for roll_rate in np.linspace(-30, 30, 1000):\n", " cL = cl(mach, roll_rate)\n", " f.write(f\"{mach},{roll_rate},{cL}\\n\")\n", - " \n", - " \n", + "\n", " with open(\"tail_cL.csv\", \"w\") as f:\n", " f.write(\"alpha,mach,cL\\n\")\n", " for alpha in alphas:\n", " for mach in machs:\n", " cL = tail.cl(alpha, mach)\n", " f.write(f\"{alpha},{mach},{cL}\\n\")\n", - " \n", + "\n", " with open(\"tail_cQ.csv\", \"w\") as f:\n", " f.write(\"beta,mach,cL\\n\")\n", " for alpha in alphas:\n", " for mach in machs:\n", " cL = tail.cl(alpha, mach)\n", " f.write(f\"{alpha},{mach},{cL}\\n\")\n", - " \n", + "\n", + "\n", "# std()" ] }, @@ -638,10 +653,23 @@ "outputs": [], "source": [ "test_flight_std = Flight(\n", - " rocket=calisto_std, environment=env, rail_length=5.2, inclination=85, heading=0, terminate_on_apogee=True, time_overshoot=False\n", + " rocket=calisto_std,\n", + " environment=env,\n", + " rail_length=5.2,\n", + " inclination=85,\n", + " heading=0,\n", + " terminate_on_apogee=True,\n", + " time_overshoot=False,\n", ")\n", "test_flight = Flight(\n", - " rocket=calisto, environment=env, rail_length=5.2, inclination=85, heading=0, max_time=6, max_time_step=0.1, time_overshoot=False\n", + " rocket=calisto,\n", + " environment=env,\n", + " rail_length=5.2,\n", + " inclination=85,\n", + " heading=0,\n", + " max_time=6,\n", + " max_time_step=0.1,\n", + " time_overshoot=False,\n", ")" ] }, @@ -663,7 +691,7 @@ ], "source": [ "%matplotlib inline\n", - "test_flight_std.R1.plot(0,6)\n" + "test_flight_std.R1.plot(0, 6)" ] }, { @@ -683,7 +711,7 @@ } ], "source": [ - "test_flight.R1.plot(0,6)\n" + "test_flight.R1.plot(0, 6)" ] }, { @@ -703,7 +731,7 @@ } ], "source": [ - "test_flight_std.R2.plot(0,6)\n" + "test_flight_std.R2.plot(0, 6)" ] }, { @@ -723,7 +751,7 @@ } ], "source": [ - "test_flight.R2.plot(0,6)\n" + "test_flight.R2.plot(0, 6)" ] }, { @@ -743,7 +771,7 @@ } ], "source": [ - "test_flight_std.R3.plot(0,6)\n" + "test_flight_std.R3.plot(0, 6)" ] }, { @@ -763,7 +791,7 @@ } ], "source": [ - "test_flight.R3.plot(0,6)\n" + "test_flight.R3.plot(0, 6)" ] }, { @@ -783,7 +811,7 @@ } ], "source": [ - "test_flight_std.M1.plot(0,6)\n" + "test_flight_std.M1.plot(0, 6)" ] }, { @@ -803,7 +831,7 @@ } ], "source": [ - "test_flight.M1.plot(0,5)\n" + "test_flight.M1.plot(0, 5)" ] }, { @@ -823,7 +851,7 @@ } ], "source": [ - "test_flight_std.M2.plot(0,6)\n" + "test_flight_std.M2.plot(0, 6)" ] }, { @@ -843,7 +871,7 @@ } ], "source": [ - "test_flight.M2.plot(0,6)\n" + "test_flight.M2.plot(0, 6)" ] }, { @@ -863,7 +891,7 @@ } ], "source": [ - "test_flight_std.M3.plot(0,6)\n" + "test_flight_std.M3.plot(0, 6)" ] }, { @@ -883,7 +911,7 @@ } ], "source": [ - "test_flight.M3.plot(0,6)" + "test_flight.M3.plot(0, 6)" ] }, { @@ -903,7 +931,7 @@ } ], "source": [ - "test_flight_std.w3.plot(0,12)" + "test_flight_std.w3.plot(0, 12)" ] }, { @@ -923,7 +951,7 @@ } ], "source": [ - "test_flight.w3.plot(0,12)" + "test_flight.w3.plot(0, 12)" ] }, { @@ -953,8 +981,8 @@ } ], "source": [ - "test_flight_std.w1.plot(0,12)\n", - "test_flight.w1.plot(0,12)" + "test_flight_std.w1.plot(0, 12)\n", + "test_flight.w1.plot(0, 12)" ] }, { @@ -979,7 +1007,9 @@ } ], "source": [ - "test_flight_std.z(6), test_flight.z.y_array[-1], test_flight_std.x(6), test_flight.x.y_array[-1], test_flight_std.y(6), test_flight.y.y_array[-1]" + "test_flight_std.z(6), test_flight.z.y_array[-1], test_flight_std.x(\n", + " 6\n", + "), test_flight.x.y_array[-1], test_flight_std.y(6), test_flight.y.y_array[-1]" ] }, { @@ -1064,11 +1094,11 @@ } ], "source": [ - "test_flight.partial_angle_of_attack.plot(test_flight.out_of_rail_time,5)\n", - "test_flight.angle_of_sideslip.plot(test_flight.out_of_rail_time,5)\n", - "test_flight.angle_of_sideslip2.plot(test_flight.out_of_rail_time,5)\n", - "test_flight.angle_of_attack.plot(test_flight.out_of_rail_time,5)\n", - "test_flight.angle_of_attack2.plot(test_flight.out_of_rail_time,5)" + "test_flight.partial_angle_of_attack.plot(test_flight.out_of_rail_time, 5)\n", + "test_flight.angle_of_sideslip.plot(test_flight.out_of_rail_time, 5)\n", + "test_flight.angle_of_sideslip2.plot(test_flight.out_of_rail_time, 5)\n", + "test_flight.angle_of_attack.plot(test_flight.out_of_rail_time, 5)\n", + "test_flight.angle_of_attack2.plot(test_flight.out_of_rail_time, 5)" ] }, { @@ -1109,9 +1139,9 @@ ], "source": [ "%matplotlib inline\n", - "test_flight.M1.plot(0,6)\n", - "test_flight.M2.plot(0,6)\n", - "test_flight.M3.plot(0,6)" + "test_flight.M1.plot(0, 6)\n", + "test_flight.M2.plot(0, 6)\n", + "test_flight.M3.plot(0, 6)" ] }, { @@ -1152,9 +1182,9 @@ ], "source": [ "%matplotlib inline\n", - "test_flight.M1.plot(0,6)\n", - "test_flight.M2.plot(0,6)\n", - "test_flight.M3.plot(0,6)" + "test_flight.M1.plot(0, 6)\n", + "test_flight.M2.plot(0, 6)\n", + "test_flight.M3.plot(0, 6)" ] }, { @@ -1195,9 +1225,9 @@ ], "source": [ "%matplotlib inline\n", - "test_flight.M1.plot(0,15)\n", - "test_flight.M2.plot(0,15)\n", - "test_flight.M3.plot(0,15)" + "test_flight.M1.plot(0, 15)\n", + "test_flight.M2.plot(0, 15)\n", + "test_flight.M3.plot(0, 15)" ] }, { @@ -1656,13 +1686,13 @@ } ], "source": [ - "test_flight.M1.plot(test_flight.out_of_rail_time,4)\n", - "test_flight.partial_angle_of_attack.plot(test_flight.out_of_rail_time,4)\n", + "test_flight.M1.plot(test_flight.out_of_rail_time, 4)\n", + "test_flight.partial_angle_of_attack.plot(test_flight.out_of_rail_time, 4)\n", "# test_flight.partial_angle_of_attack2.plot(test_flight.out_of_rail_time,4)\n", - "test_flight.M2.plot(test_flight.out_of_rail_time,4)\n", - "test_flight.angle_of_sideslip.plot(test_flight.out_of_rail_time,4)\n", + "test_flight.M2.plot(test_flight.out_of_rail_time, 4)\n", + "test_flight.angle_of_sideslip.plot(test_flight.out_of_rail_time, 4)\n", "# test_flight.beta2.plot(test_flight.out_of_rail_time,4)\n", - "# test_flight.angle_of_attack2.plot(test_flight.out_of_rail_time,4)\n" + "# test_flight.angle_of_attack2.plot(test_flight.out_of_rail_time,4)" ] }, { @@ -1671,9 +1701,9 @@ "metadata": {}, "outputs": [], "source": [ - "a = -1 #y\n", - "b = 2 #z\n", - "np.arctan(a/b),np.arctan2(a,b),np.arctan2(a,b)-np.pi,np.arctan2(a,b)+np.pi" + "a = -1 # y\n", + "b = 2 # z\n", + "np.arctan(a / b), np.arctan2(a, b), np.arctan2(a, b) - np.pi, np.arctan2(a, b) + np.pi" ] }, { @@ -1682,9 +1712,9 @@ "metadata": {}, "outputs": [], "source": [ - "a = -1 #x\n", - "b = -2 #z\n", - "np.arctan(-a/b),np.arctan2(-a,b),np.arctan2(a,b)-np.pi,np.arctan2(a,b)+np.pi" + "a = -1 # x\n", + "b = -2 # z\n", + "np.arctan(-a / b), np.arctan2(-a, b), np.arctan2(a, b) - np.pi, np.arctan2(a, b) + np.pi" ] }, { @@ -1693,7 +1723,7 @@ "metadata": {}, "outputs": [], "source": [ - "test_flight.angle_of_attack.plot(test_flight.out_of_rail_time,4)\n" + "test_flight.angle_of_attack.plot(test_flight.out_of_rail_time, 4)" ] }, { @@ -1702,10 +1732,10 @@ "metadata": {}, "outputs": [], "source": [ - "test_flight.angle_of_attack.plot(test_flight.out_of_rail_time,0)\n", - "test_flight.angle_of_attack2.plot(0,0.2)\n", - "test_flight.partial_angle_of_attack.plot(0,3)\n", - "test_flight.beta.plot(0,0.2)" + "test_flight.angle_of_attack.plot(test_flight.out_of_rail_time, 0)\n", + "test_flight.angle_of_attack2.plot(0, 0.2)\n", + "test_flight.partial_angle_of_attack.plot(0, 3)\n", + "test_flight.beta.plot(0, 0.2)" ] }, { @@ -1726,19 +1756,37 @@ "from rocketpy import Function\n", "from rocketpy.mathutils import Matrix\n", "import numpy as np\n", + "\n", "Kt = []\n", "for i, t in enumerate(test_flight.time):\n", - " Kt.append(Matrix.transformation([test_flight.e0.y_array[i], test_flight.e1.y_array[i], test_flight.e2.y_array[i], test_flight.e3.y_array[i]]).transpose)\n", + " Kt.append(\n", + " Matrix.transformation(\n", + " [\n", + " test_flight.e0.y_array[i],\n", + " test_flight.e1.y_array[i],\n", + " test_flight.e2.y_array[i],\n", + " test_flight.e3.y_array[i],\n", + " ]\n", + " ).transpose\n", + " )\n", "Kt = np.array(Kt)\n", - "free_stream_speed = np.array([test_flight.stream_velocity_x.y_array, test_flight.stream_velocity_y.y_array, test_flight.stream_velocity_z.y_array]).transpose()\n", + "free_stream_speed = np.array(\n", + " [\n", + " test_flight.stream_velocity_x.y_array,\n", + " test_flight.stream_velocity_y.y_array,\n", + " test_flight.stream_velocity_z.y_array,\n", + " ]\n", + ").transpose()\n", "free_stream_speed_body = np.squeeze(np.matmul(Kt, free_stream_speed[:, :, np.newaxis]))\n", - "free_stream_speed_body_x = free_stream_speed_body[:,0]\n", + "free_stream_speed_body_x = free_stream_speed_body[:, 0]\n", "\n", "alpha = np.arctan(\n", - " free_stream_speed_body[:,0] / free_stream_speed_body[:,2]\n", + " free_stream_speed_body[:, 0] / free_stream_speed_body[:, 2]\n", ") # X-Z plane\n", "# alpha = np.nan_to_num(alpha)\n", - "Function(np.column_stack([test_flight.time, np.rad2deg(alpha)])).plot(test_flight.out_of_rail_time,10)" + "Function(np.column_stack([test_flight.time, np.rad2deg(alpha)])).plot(\n", + " test_flight.out_of_rail_time, 10\n", + ")" ] }, { @@ -1750,18 +1798,36 @@ "from rocketpy import Function\n", "from rocketpy.mathutils import Matrix\n", "import numpy as np\n", + "\n", "Kt = []\n", "for i, t in enumerate(test_flight.time):\n", - " Kt.append(Matrix.transformation([test_flight.e0.y_array[i], test_flight.e1.y_array[i], test_flight.e2.y_array[i], test_flight.e3.y_array[i]]).transpose)\n", + " Kt.append(\n", + " Matrix.transformation(\n", + " [\n", + " test_flight.e0.y_array[i],\n", + " test_flight.e1.y_array[i],\n", + " test_flight.e2.y_array[i],\n", + " test_flight.e3.y_array[i],\n", + " ]\n", + " ).transpose\n", + " )\n", "Kt = np.array(Kt)\n", - "free_stream_speed = np.array([test_flight.stream_velocity_x.y_array, test_flight.stream_velocity_y.y_array, test_flight.stream_velocity_z.y_array]).transpose()\n", + "free_stream_speed = np.array(\n", + " [\n", + " test_flight.stream_velocity_x.y_array,\n", + " test_flight.stream_velocity_y.y_array,\n", + " test_flight.stream_velocity_z.y_array,\n", + " ]\n", + ").transpose()\n", "free_stream_speed_body = np.squeeze(np.matmul(Kt, free_stream_speed[:, :, np.newaxis]))\n", "\n", "alpha = np.arctan(\n", - " free_stream_speed_body[:,0] / free_stream_speed_body[:,2]\n", + " free_stream_speed_body[:, 0] / free_stream_speed_body[:, 2]\n", ") # X-Z plane\n", "# alpha = np.nan_to_num(alpha)\n", - "Function(np.column_stack([test_flight.time, np.rad2deg(alpha)])).plot(test_flight.out_of_rail_time,10)" + "Function(np.column_stack([test_flight.time, np.rad2deg(alpha)])).plot(\n", + " test_flight.out_of_rail_time, 10\n", + ")" ] }, { @@ -1772,7 +1838,7 @@ "source": [ "# Example arrays (you would replace these with your actual data)\n", "matrices = np.random.rand(707, 3, 3) # Shape (707, 3, 3)\n", - "vectors = np.random.rand(707, 3) # Shape (707, 3)\n", + "vectors = np.random.rand(707, 3) # Shape (707, 3)\n", "\n", "# Multiply each 3x3 matrix with its corresponding 3x1 vector\n", "result = np.matmul(matrices, vectors[:, :, np.newaxis])\n", @@ -1787,27 +1853,32 @@ "metadata": {}, "outputs": [], "source": [ - "dot_product = - (\n", + "dot_product = -(\n", " test_flight.attitude_vector_x.y_array * test_flight.stream_velocity_x.y_array\n", " + test_flight.attitude_vector_y.y_array * test_flight.stream_velocity_y.y_array\n", " + test_flight.attitude_vector_z.y_array * test_flight.stream_velocity_z.y_array\n", - " )\n", + ")\n", "\n", "# Define freestream speed list\n", "free_stream_speed = test_flight.free_stream_speed.y_array\n", "# free_stream_speed = np.nan_to_num(test_flight.free_stream_speed.y_array)\n", "\n", "# Normalize dot product\n", - "dot_product_normalized = np.divide(dot_product, free_stream_speed, \n", - " out=np.zeros_like(dot_product), \n", - " where=free_stream_speed > 1e-6)\n", + "dot_product_normalized = np.divide(\n", + " dot_product,\n", + " free_stream_speed,\n", + " out=np.zeros_like(dot_product),\n", + " where=free_stream_speed > 1e-6,\n", + ")\n", "# dot_product_normalized = np.nan_to_num(dot_product_normalized)\n", "dot_product_normalized = np.clip(dot_product_normalized, -1, 1)\n", "\n", "# Calculate angle of attack and convert to degrees\n", "angle_of_attack = np.rad2deg(np.arccos(dot_product_normalized))\n", "\n", - "Function(np.column_stack([test_flight.time, angle_of_attack])).plot(test_flight.out_of_rail_time, 10)\n" + "Function(np.column_stack([test_flight.time, angle_of_attack])).plot(\n", + " test_flight.out_of_rail_time, 10\n", + ")" ] }, { @@ -1816,9 +1887,14 @@ "metadata": {}, "outputs": [], "source": [ - "alpha = np.arccos(-test_flight.stream_velocity_z.source[:,1]/test_flight.free_stream_speed.source[:,1])\n", - "Function(np.column_stack([test_flight.time, np.rad2deg(alpha)])).plot(test_flight.out_of_rail_time, 10)\n", - "test_flight.angle_of_attack.plot(test_flight.out_of_rail_time, 10)\n" + "alpha = np.arccos(\n", + " -test_flight.stream_velocity_z.source[:, 1]\n", + " / test_flight.free_stream_speed.source[:, 1]\n", + ")\n", + "Function(np.column_stack([test_flight.time, np.rad2deg(alpha)])).plot(\n", + " test_flight.out_of_rail_time, 10\n", + ")\n", + "test_flight.angle_of_attack.plot(test_flight.out_of_rail_time, 10)" ] }, { @@ -1865,7 +1941,7 @@ "outputs": [], "source": [ "test_flight.angle_of_attack3.plot(test_flight.out_of_rail_time, 10)\n", - "test_flight.angle_of_attack2.plot(test_flight.out_of_rail_time, 10)\n" + "test_flight.angle_of_attack2.plot(test_flight.out_of_rail_time, 10)" ] }, { @@ -1904,7 +1980,7 @@ "%matplotlib inline\n", "calisto.static_margin.plot(0, 10)\n", "test_flight.stability_margin.plot(0, 10)\n", - "test_flight.speed.plot(0, 10)\n" + "test_flight.speed.plot(0, 10)" ] }, { @@ -1937,6 +2013,7 @@ "import csv\n", "from rocketpy import Function\n", "\n", + "\n", "def __load_csv(file_path, coeff_name):\n", " \"\"\"Load CSV data, validate it, and create an interpolation function for varying parameters.\"\"\"\n", " try:\n", @@ -1975,7 +2052,7 @@ " lambda alpha, beta, mach, height: csv_func(alpha),\n", " [\"alpha\", \"beta\", \"mach\", \"height\"],\n", " [coeff_name],\n", - " extrapolation=\"natural\"\n", + " extrapolation=\"natural\",\n", " )\n", " elif mask == [1, 1, 0, 0]:\n", " func = Function(\n", @@ -2036,8 +2113,9 @@ "\n", " return func\n", "\n", - "f=__load_csv(\"a.csv\",\"CCCXXX\")\n", - "f(5,10,10,10)\n" + "\n", + "f = __load_csv(\"a.csv\", \"CCCXXX\")\n", + "f(5, 10, 10, 10)" ] }, { @@ -2049,6 +2127,7 @@ "import csv\n", "from rocketpy import Function\n", "\n", + "\n", "def __load_csv(file_path, coeff_name):\n", " \"\"\"Load CSV data, validate it, and create an interpolation function for varying parameters.\"\"\"\n", " try:\n", @@ -2067,7 +2146,9 @@ "\n", " # Check that the last column is not an independent variable\n", " if header[-1] in independent_vars:\n", - " raise ValueError(f\"Last column in {coeff_name} CSV must be the coefficient value, not an independent variable.\")\n", + " raise ValueError(\n", + " f\"Last column in {coeff_name} CSV must be the coefficient value, not an independent variable.\"\n", + " )\n", "\n", " # Ensure that at least one independent variable is present\n", " if not present_columns:\n", @@ -2091,8 +2172,9 @@ "\n", " return func\n", "\n", - "f=__load_csv(\"a.csv\",\"cx\")\n", - "f(3,100,10,1000)" + "\n", + "f = __load_csv(\"a.csv\", \"cx\")\n", + "f(3, 100, 10, 1000)" ] }, { @@ -2104,16 +2186,17 @@ "from inspect import signature, Parameter\n", "\n", "\n", - "def a(bb,cc,*args):\n", + "def a(bb, cc, *args):\n", " return 0\n", "\n", + "\n", "# Get the signature of the function\n", "sig = signature(a)\n", "\n", "# Check if any of the parameters are VAR_POSITIONAL, which corresponds to *args\n", "for param in sig.parameters.values():\n", " if param.kind == Parameter.VAR_POSITIONAL:\n", - " r= True\n", + " r = True\n", "r" ] }, @@ -2123,7 +2206,7 @@ "metadata": {}, "outputs": [], "source": [ - "a = [1,0,1,0]\n", + "a = [1, 0, 1, 0]\n", "b = ['alpha', 'beta', 'mach', 'height']\n", "# apply the mask to the list of variables\n", "selected_args = [arg for arg, m in zip(b, a) if m]\n", diff --git a/rocketpy/plots/rocket_plots.py b/rocketpy/plots/rocket_plots.py index e4d363939..4ec4110ca 100644 --- a/rocketpy/plots/rocket_plots.py +++ b/rocketpy/plots/rocket_plots.py @@ -4,7 +4,7 @@ import numpy as np from rocketpy.motors import EmptyMotor, HybridMotor, LiquidMotor, SolidMotor -from rocketpy.rocket.aero_surface import Fins, Fin, NoseCone, Tail +from rocketpy.rocket.aero_surface import Fin, Fins, NoseCone, Tail class _RocketPlots: diff --git a/rocketpy/rocket/aero_surface/fins/elliptical_fin.py b/rocketpy/rocket/aero_surface/fins/elliptical_fin.py index 06def168b..6395b60d8 100644 --- a/rocketpy/rocket/aero_surface/fins/elliptical_fin.py +++ b/rocketpy/rocket/aero_surface/fins/elliptical_fin.py @@ -1,10 +1,10 @@ import numpy as np -from .fin import Fin - from rocketpy.plots.aero_surface_plots import _EllipticalFinPlots from rocketpy.prints.aero_surface_prints import _EllipticalFinPrints +from .fin import Fin + class EllipticalFin(Fin): """Class that defines and holds information for an elliptical fin. diff --git a/rocketpy/rocket/aero_surface/fins/fin.py b/rocketpy/rocket/aero_surface/fins/fin.py index b1ccacf5b..fb03783f4 100644 --- a/rocketpy/rocket/aero_surface/fins/fin.py +++ b/rocketpy/rocket/aero_surface/fins/fin.py @@ -1,5 +1,4 @@ import math -from abc import abstractmethod import numpy as np @@ -405,8 +404,6 @@ def compute_forces_and_moments( omega1, omega2, omega3, - *args, - **kwargs, ): """Computes the forces and moments acting on the aerodynamic surface. @@ -416,6 +413,9 @@ def compute_forces_and_moments( Speed of the flow stream in the body frame. """ + self.omega1 = omega1 + self.omega2 = omega2 + self.omega3 = omega3 R1, R2, R3, M1, M2, M3 = 0, 0, 0, 0, 0, 0 # stream velocity in fin frame stream_vx_f, _, stream_vz_f = self._body_to_fin_aero @ stream_velocity diff --git a/rocketpy/rocket/aero_surface/fins/trapezoidal_fin.py b/rocketpy/rocket/aero_surface/fins/trapezoidal_fin.py index 67db3860a..710afb965 100644 --- a/rocketpy/rocket/aero_surface/fins/trapezoidal_fin.py +++ b/rocketpy/rocket/aero_surface/fins/trapezoidal_fin.py @@ -9,6 +9,85 @@ class TrapezoidalFin(Fin): + """A class used to represent a single trapezoidal fin. + + This class inherits from the Fin class. + + Note + ---- + Local coordinate system: + - Origin located at the top of the root chord. + - Z axis along the longitudinal axis of symmetry, positive downwards (top -> bottom). + - Y axis perpendicular to the Z axis, in the span direction, positive upwards. + - X axis completes the right-handed coordinate system. + + See Also + -------- + Fin : Parent class + + Attributes + ---------- + TrapezoidalFin.angular_position : float + Angular position of the fin set with respect to the rocket centerline, in + degrees. + TrapezoidalFin.rocket_radius : float + The reference rocket radius used for lift coefficient normalization, in + meters. + TrapezoidalFin.airfoil : tuple + Tuple of two items. First is the airfoil lift curve. + Second is the unit of the curve (radians or degrees). + TrapezoidalFin.cant_angle : float + Fins cant angle with respect to the rocket centerline, in degrees. + TrapezoidalFin.changing_attribute_dict : dict + Dictionary that stores the name and the values of the attributes that + may be changed during a simulation. Useful for control systems. + TrapezoidalFin.cant_angle_rad : float + Fins cant angle with respect to the rocket centerline, in radians. + TrapezoidalFin.root_chord : float + Fin root chord in meters. + TrapezoidalFin.tip_chord : float + Fin tip chord in meters. + TrapezoidalFin.span : float + Fin span in meters. + TrapezoidalFin.name : string + Name of fin set. + TrapezoidalFin.sweep_length : float + 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. + TrapezoidalFin.sweep_angle : float + Fins sweep angle with respect to the rocket centerline. Must + be given in degrees. + TrapezoidalFin.d : float + Reference diameter of the rocket, in meters. + TrapezoidalFins.fin_area : float + Area of the longitudinal section of each fin in the set. + TrapezoidalFins.f_ar : float + Aspect ratio of each fin in the set + TrapezoidalFin.gamma_c : float + Fin mid-chord sweep angle. + TrapezoidalFin.yma : float + Span wise position of the mean aerodynamic chord. + TrapezoidalFin.roll_geometrical_constant : float + Geometrical constant used in roll calculations. + TrapezoidalFin.tau : float + Geometrical relation used to simplify lift and roll calculations. + TrapezoidalFin.lift_interference_factor : float + Factor of Fin-Body interference in the lift coefficient. + TrapezoidalFin.cp : tuple + Tuple with the x, y and z local coordinates of the fin set center of + pressure. Has units of length and is given in meters. + TrapezoidalFin.cpx : float + Fin set local center of pressure x coordinate. Has units of length and + is given in meters. + TrapezoidalFin.cpy : float + Fin set local center of pressure y coordinate. Has units of length and + is given in meters. + TrapezoidalFin.cpz : float + Fin set local center of pressure z coordinate. Has units of length and + is given in meters. + """ + def __init__( self, angular_position, @@ -110,7 +189,7 @@ def evaluate_center_of_pressure(self): - self.root_chord * self.tip_chord / (self.root_chord + self.tip_chord) ) self.cpx = 0 - self.cpy = self.Yma + self.cpy = self.yma self.cpz = cpz self.cp = (self.cpx, self.cpy, self.cpz) @@ -123,21 +202,21 @@ def evaluate_geometrical_parameters(self): None """ - Yr = self.root_chord + self.tip_chord - Af = Yr * self.span / 2 # Fin area - AR = 2 * self.span**2 / Af # Fin aspect ratio + yr = self.root_chord + self.tip_chord + fin_area = yr * self.span / 2 # Fin area + f_ar = 2 * self.span**2 / fin_area # Fin aspect ratio gamma_c = math.atan( (self.sweep_length + 0.5 * self.tip_chord - 0.5 * self.root_chord) / (self.span) ) - Yma = ( - (self.span / 3) * (self.root_chord + 2 * self.tip_chord) / Yr + yma = ( + (self.span / 3) * (self.root_chord + 2 * self.tip_chord) / yr ) # Span wise coord of mean aero chord # Fin–body interference correction parameters tau = (self.span + self.rocket_radius) / self.rocket_radius lift_interference_factor = 1 + 1 / tau - λ = self.tip_chord / self.root_chord + chord_ratio_tr = self.tip_chord / self.root_chord # Parameters for Roll Moment. # Documented at: https://github.com/RocketPy-Team/RocketPy/blob/master/docs/technical/aerodynamics/Roll_Equations.pdf @@ -150,9 +229,11 @@ def evaluate_geometrical_parameters(self): + 6 * (self.root_chord + self.tip_chord) * self.span * self.rocket_radius**2 ) / 12 roll_damping_interference_factor = 1 + ( - ((tau - λ) / (tau)) - ((1 - λ) / (tau - 1)) * math.log(tau) + ((tau - chord_ratio_tr) / (tau)) + - ((1 - chord_ratio_tr) / (tau - 1)) * math.log(tau) ) / ( - ((tau + 1) * (tau - λ)) / (2) - ((1 - λ) * (tau**3 - 1)) / (3 * (tau - 1)) + ((tau + 1) * (tau - chord_ratio_tr)) / (2) + - ((1 - chord_ratio_tr) * (tau**3 - 1)) / (3 * (tau - 1)) ) roll_forcing_interference_factor = (1 / math.pi**2) * ( (math.pi**2 / 4) * ((tau + 1) ** 2 / tau**2) @@ -169,15 +250,15 @@ def evaluate_geometrical_parameters(self): ) # Store values - self.Yr = Yr - self.Af = Af # Fin area - self.AR = AR # Aspect Ratio + self.yr = yr + self.fin_area = fin_area # Fin area + self.f_ar = f_ar # Aspect Ratio self.gamma_c = gamma_c # Mid chord angle - self.Yma = Yma # Span wise coord of mean aero chord + self.yma = yma # Span wise coord of mean aero chord self.roll_geometrical_constant = roll_geometrical_constant self.tau = tau self.lift_interference_factor = lift_interference_factor - self.λ = λ + self.chord_ratio_tr = chord_ratio_tr self.roll_damping_interference_factor = roll_damping_interference_factor self.roll_forcing_interference_factor = roll_forcing_interference_factor diff --git a/rocketpy/rocket/aero_surface/generic_surface.py b/rocketpy/rocket/aero_surface/generic_surface.py index c67495bf5..749d5478a 100644 --- a/rocketpy/rocket/aero_surface/generic_surface.py +++ b/rocketpy/rocket/aero_surface/generic_surface.py @@ -1,10 +1,11 @@ import csv import math -from rocketpy.mathutils.vector_matrix import Matrix, Vector -from rocketpy.mathutils import Function import numpy as np +from rocketpy.mathutils import Function +from rocketpy.mathutils.vector_matrix import Matrix, Vector + class GenericSurface: """Defines a generic aerodynamic surface with custom force and moment @@ -16,9 +17,9 @@ def __init__( self, reference_area, reference_length, - cL=0, - cQ=0, - cD=0, + cl_lift=0, + cq_side_force=0, + cd_drag=0, cm=0, cn=0, cl=0, @@ -50,13 +51,13 @@ def __init__( reference_length : int, float Reference length of the aerodynamic surface. Has the unit of meters. Commonly defined as the rocket's diameter. - cL : str, callable, optional + cl_lift : str, callable, optional Lift coefficient. Can be a path to a CSV file or a callable. Default is 0. - cQ : str, callable, optional + cq_side_force : str, callable, optional Side force coefficient. Can be a path to a CSV file or a callable. Default is 0. - cD : str, callable, optional + cd_drag : str, callable, optional Drag coefficient. Can be a path to a CSV file or a callable. Default is 0. cm : str, callable, optional @@ -84,9 +85,9 @@ def __init__( self.cpz = center_of_pressure[2] self.name = name - self.cL = self._process_input(cL, "cL") - self.cD = self._process_input(cD, "cD") - self.cQ = self._process_input(cQ, "cQ") + self.cl_lift = self._process_input(cl_lift, "cL") + self.cd_drag = self._process_input(cd_drag, "cD") + self.cq_side_force = self._process_input(cq_side_force, "cQ") self.cm = self._process_input(cm, "cm") self.cn = self._process_input(cn, "cn") self.cl = self._process_input(cl, "cl") @@ -138,13 +139,13 @@ def _compute_from_coefficients( dyn_pressure_area_length = dyn_pressure_area * self.reference_length # Compute aerodynamic forces - lift = dyn_pressure_area * self.cL( + lift = dyn_pressure_area * self.cl_lift( alpha, beta, mach, reynolds, pitch_rate, yaw_rate, roll_rate ) - side = dyn_pressure_area * self.cQ( + side = dyn_pressure_area * self.cq_side_force( alpha, beta, mach, reynolds, pitch_rate, yaw_rate, roll_rate ) - drag = dyn_pressure_area * self.cD( + drag = dyn_pressure_area * self.cd_drag( alpha, beta, mach, reynolds, pitch_rate, yaw_rate, roll_rate ) @@ -319,7 +320,7 @@ def __load_csv(self, file_path, coeff_name): reader = csv.reader(file) header = next(reader) except (FileNotFoundError, IOError) as e: - raise ValueError(f"Error reading {coeff_name} CSV file: {e}") + raise ValueError(f"Error reading {coeff_name} CSV file: {e}") from e if not header: raise ValueError(f"Invalid or empty CSV file for {coeff_name}.") diff --git a/rocketpy/rocket/aero_surface/linear_generic_surface.py b/rocketpy/rocket/aero_surface/linear_generic_surface.py index 259bf08c2..65cbad595 100644 --- a/rocketpy/rocket/aero_surface/linear_generic_surface.py +++ b/rocketpy/rocket/aero_surface/linear_generic_surface.py @@ -1,5 +1,5 @@ -from rocketpy.rocket.aero_surface.generic_surface import GenericSurface from rocketpy.mathutils import Function +from rocketpy.rocket.aero_surface.generic_surface import GenericSurface class LinearGenericSurface(GenericSurface): @@ -11,24 +11,24 @@ def __init__( self, reference_area, reference_length, - cL_0=0, - cL_alpha=0, - cL_beta=0, - cL_p=0, - cL_q=0, - cL_r=0, - cQ_0=0, - cQ_alpha=0, - cQ_beta=0, - cQ_p=0, - cQ_q=0, - cQ_r=0, - cD_0=0, - cD_alpha=0, - cD_beta=0, - cD_p=0, - cD_q=0, - cD_r=0, + cl_lift_0=0, + cl_lift_alpha=0, + cl_lift_beta=0, + cl_lift_p=0, + cl_lift_q=0, + cl_lift_r=0, + cq_pitch_0=0, + cq_pitch_alpha=0, + cq_pitch_beta=0, + cq_pitch_p=0, + cq_pitch_q=0, + cq_pitch_r=0, + cd_drag_0=0, + cd_drag_alpha=0, + cd_drag_beta=0, + cd_drag_p=0, + cd_drag_q=0, + cd_drag_r=0, cm_0=0, cm_alpha=0, cm_beta=0, @@ -75,56 +75,56 @@ def __init__( reference_length : int, float Reference length of the aerodynamic surface. Has the unit of meters. Commonly defined as the rocket's diameter. - cL_0 : callable, str, optional + cl_lift_0 : callable, str, optional Coefficient of lift at zero angle of attack. Default is 0. - cL_alpha : callable, str, optional + cl_lift_alpha : callable, str, optional Coefficient of lift derivative with respect to angle of attack. Default is 0. - cL_beta : callable, str, optional + cl_lift_beta : callable, str, optional Coefficient of lift derivative with respect to sideslip angle. Default is 0. - cL_p : callable, str, optional + cl_lift_p : callable, str, optional Coefficient of lift derivative with respect to roll rate. Default is 0. - cL_q : callable, str, optional + cl_lift_q : callable, str, optional Coefficient of lift derivative with respect to pitch rate. Default is 0. - cL_r : callable, str, optional + cl_lift_r : callable, str, optional Coefficient of lift derivative with respect to yaw rate. Default is 0. - cQ_0 : callable, str, optional + cq_pitch_0 : callable, str, optional Coefficient of pitch moment at zero angle of attack. Default is 0. - cQ_alpha : callable, str, optional + cq_pitch_alpha : callable, str, optional Coefficient of pitch moment derivative with respect to angle of attack. Default is 0. - cQ_beta : callable, str, optional + cq_pitch_beta : callable, str, optional Coefficient of pitch moment derivative with respect to sideslip angle. Default is 0. - cQ_p : callable, str, optional + cq_pitch_p : callable, str, optional Coefficient of pitch moment derivative with respect to roll rate. Default is 0. - cQ_q : callable, str, optional + cq_pitch_q : callable, str, optional Coefficient of pitch moment derivative with respect to pitch rate. Default is 0. - cQ_r : callable, str, optional + cq_pitch_r : callable, str, optional Coefficient of pitch moment derivative with respect to yaw rate. Default is 0. - cD_0 : callable, str, optional + cd_drag_0 : callable, str, optional Coefficient of drag at zero angle of attack. Default is 0. - cD_alpha : callable, str, optional + cd_drag_alpha : callable, str, optional Coefficient of drag derivative with respect to angle of attack. Default is 0. - cD_beta : callable, str, optional + cd_drag_beta : callable, str, optional Coefficient of drag derivative with respect to sideslip angle. Default is 0. - cD_p : callable, str, optional + cd_drag_p : callable, str, optional Coefficient of drag derivative with respect to roll rate. Default is 0. - cD_q : callable, str, optional + cd_drag_q : callable, str, optional Coefficient of drag derivative with respect to pitch rate. Default is 0. - cD_r : callable, str, optional + cd_drag_r : callable, str, optional Coefficient of drag derivative with respect to yaw rate. Default is 0. cm_0 : callable, str, optional @@ -197,24 +197,24 @@ def __init__( self.cpz = center_of_pressure[2] self.name = name - self.cL_0 = self._process_input(cL_0, "cL_0") - self.cL_alpha = self._process_input(cL_alpha, "cL_alpha") - self.cL_beta = self._process_input(cL_beta, "cL_beta") - self.cL_p = self._process_input(cL_p, "cL_p") - self.cL_q = self._process_input(cL_q, "cL_q") - self.cL_r = self._process_input(cL_r, "cL_r") - self.cQ_0 = self._process_input(cQ_0, "cQ_0") - self.cQ_alpha = self._process_input(cQ_alpha, "cQ_alpha") - self.cQ_beta = self._process_input(cQ_beta, "cQ_beta") - self.cQ_p = self._process_input(cQ_p, "cQ_p") - self.cQ_q = self._process_input(cQ_q, "cQ_q") - self.cQ_r = self._process_input(cQ_r, "cQ_r") - self.cD_0 = self._process_input(cD_0, "cD_0") - self.cD_alpha = self._process_input(cD_alpha, "cD_alpha") - self.cD_beta = self._process_input(cD_beta, "cD_beta") - self.cD_p = self._process_input(cD_p, "cD_p") - self.cD_q = self._process_input(cD_q, "cD_q") - self.cD_r = self._process_input(cD_r, "cD_r") + self.cl_lift_0 = self._process_input(cl_lift_0, "cl_lift_0") + self.cl_lift_alpha = self._process_input(cl_lift_alpha, "cl_lift_alpha") + self.cl_lift_beta = self._process_input(cl_lift_beta, "cl_lift_beta") + self.cl_lift_p = self._process_input(cl_lift_p, "cl_lift_p") + self.cl_lift_q = self._process_input(cl_lift_q, "cl_lift_q") + self.cl_lift_r = self._process_input(cl_lift_r, "cl_lift_r") + self.cq_pitch_0 = self._process_input(cq_pitch_0, "cq_pitch_0") + self.cq_pitch_alpha = self._process_input(cq_pitch_alpha, "cq_pitch_alpha") + self.cq_pitch_beta = self._process_input(cq_pitch_beta, "cq_pitch_beta") + self.cq_pitch_p = self._process_input(cq_pitch_p, "cq_pitch_p") + self.cq_pitch_q = self._process_input(cq_pitch_q, "cq_pitch_q") + self.cq_pitch_r = self._process_input(cq_pitch_r, "cq_pitch_r") + self.cd_drag_0 = self._process_input(cd_drag_0, "cd_drag_0") + self.cd_drag_alpha = self._process_input(cd_drag_alpha, "cd_drag_alpha") + self.cd_drag_beta = self._process_input(cd_drag_beta, "cd_drag_beta") + self.cd_drag_p = self._process_input(cd_drag_p, "cd_drag_p") + self.cd_drag_q = self._process_input(cd_drag_q, "cd_drag_q") + self.cd_drag_r = self._process_input(cd_drag_r, "cd_drag_r") self.cl_0 = self._process_input(cl_0, "cl_0") self.cl_alpha = self._process_input(cl_alpha, "cl_alpha") self.cl_beta = self._process_input(cl_beta, "cl_beta") @@ -297,20 +297,26 @@ def total_coefficient( def compute_all_coefficients(self): """Compute all the aerodynamic coefficients from the derivatives.""" - self.cLf = self.compute_forcing_coefficient( - self.cL_0, self.cL_alpha, self.cL_beta + self.c_l_lift_f = self.compute_forcing_coefficient( + self.cl_lift_0, self.cl_lift_alpha, self.cl_lift_beta + ) + self.c_l_lift_d = self.compute_damping_coefficient( + self.cl_lift_p, self.cl_lift_q, self.cl_lift_r ) - self.cLd = self.compute_damping_coefficient(self.cL_p, self.cL_q, self.cL_r) - self.cQf = self.compute_forcing_coefficient( - self.cQ_0, self.cQ_alpha, self.cQ_beta + self.c_q_pitch_f = self.compute_forcing_coefficient( + self.cq_pitch_0, self.cq_pitch_alpha, self.cq_pitch_beta + ) + self.c_q_pitch_d = self.compute_damping_coefficient( + self.cq_pitch_p, self.cq_pitch_q, self.cq_pitch_r ) - self.cQd = self.compute_damping_coefficient(self.cQ_p, self.cQ_q, self.cQ_r) - self.cDf = self.compute_forcing_coefficient( - self.cD_0, self.cD_alpha, self.cD_beta + self.c_d_drag_f = self.compute_forcing_coefficient( + self.cd_drag_0, self.cd_drag_alpha, self.cd_drag_beta + ) + self.c_d_drag_d = self.compute_damping_coefficient( + self.cd_drag_p, self.cd_drag_q, self.cd_drag_r ) - self.cDd = self.compute_damping_coefficient(self.cD_p, self.cD_q, self.cD_r) self.cmf = self.compute_forcing_coefficient( self.cm_0, self.cm_alpha, self.cm_beta @@ -380,21 +386,21 @@ def _compute_from_coefficients( ) # Compute aerodynamic forces - lift = dyn_pressure_area * self.cLf( + lift = dyn_pressure_area * self.c_l_lift_f( alpha, beta, mach, reynolds, pitch_rate, yaw_rate, roll_rate - ) - dyn_pressure_area_damping * self.cLd( + ) - dyn_pressure_area_damping * self.c_l_lift_d( alpha, beta, mach, reynolds, pitch_rate, yaw_rate, roll_rate ) - side = dyn_pressure_area * self.cQf( + side = dyn_pressure_area * self.c_q_pitch_f( alpha, beta, mach, reynolds, pitch_rate, yaw_rate, roll_rate - ) - dyn_pressure_area_damping * self.cQd( + ) - dyn_pressure_area_damping * self.c_q_pitch_d( alpha, beta, mach, reynolds, pitch_rate, yaw_rate, roll_rate ) - drag = dyn_pressure_area * self.cDf( + drag = dyn_pressure_area * self.c_d_drag_f( alpha, beta, mach, reynolds, pitch_rate, yaw_rate, roll_rate - ) - dyn_pressure_area_damping * self.cDd( + ) - dyn_pressure_area_damping * self.c_d_drag_d( alpha, beta, mach, reynolds, pitch_rate, yaw_rate, roll_rate ) From c1d948348286c06e50b26b28fc6fe816c66dbb9c Mon Sep 17 00:00:00 2001 From: MateusStano Date: Mon, 31 Mar 2025 22:27:41 +0200 Subject: [PATCH 06/32] ENH: reorder imports for fins module --- rocketpy/rocket/aero_surface/__init__.py | 4 ++-- rocketpy/rocket/aero_surface/fins/__init__.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/rocketpy/rocket/aero_surface/__init__.py b/rocketpy/rocket/aero_surface/__init__.py index 4b67090c8..b3538b1ef 100644 --- a/rocketpy/rocket/aero_surface/__init__.py +++ b/rocketpy/rocket/aero_surface/__init__.py @@ -2,11 +2,11 @@ from rocketpy.rocket.aero_surface.air_brakes import AirBrakes from rocketpy.rocket.aero_surface.fins import ( EllipticalFin, - Fin, - TrapezoidalFin, EllipticalFins, + Fin, Fins, FreeFormFins, + TrapezoidalFin, TrapezoidalFins, ) from rocketpy.rocket.aero_surface.generic_surface import GenericSurface diff --git a/rocketpy/rocket/aero_surface/fins/__init__.py b/rocketpy/rocket/aero_surface/fins/__init__.py index ee201755f..bf1beef37 100644 --- a/rocketpy/rocket/aero_surface/fins/__init__.py +++ b/rocketpy/rocket/aero_surface/fins/__init__.py @@ -2,6 +2,6 @@ from rocketpy.rocket.aero_surface.fins.elliptical_fins import EllipticalFins from rocketpy.rocket.aero_surface.fins.fin import Fin from rocketpy.rocket.aero_surface.fins.fins import Fins -from rocketpy.rocket.aero_surface.fins.trapezoidal_fin import TrapezoidalFin from rocketpy.rocket.aero_surface.fins.free_form_fins import FreeFormFins +from rocketpy.rocket.aero_surface.fins.trapezoidal_fin import TrapezoidalFin from rocketpy.rocket.aero_surface.fins.trapezoidal_fins import TrapezoidalFins From 8bbac15f6c5cfa8ff86857882c997547c209c634 Mon Sep 17 00:00:00 2001 From: MateusStano Date: Thu, 17 Apr 2025 16:58:39 +0200 Subject: [PATCH 07/32] ENH: fix rotation matrixes --- rocketpy/rocket/aero_surface/fins/fin.py | 32 +++++++++++++----------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/rocketpy/rocket/aero_surface/fins/fin.py b/rocketpy/rocket/aero_surface/fins/fin.py index fb03783f4..1f9f9ea77 100644 --- a/rocketpy/rocket/aero_surface/fins/fin.py +++ b/rocketpy/rocket/aero_surface/fins/fin.py @@ -370,26 +370,30 @@ def evaluate_rotation_matrix(self): delta = self.cant_angle_rad # TODO check rotation for nose_to_tail csystems # Body to fin rotation matrix - R = Matrix( + R_phi = Matrix( + [[np.cos(phi), -np.sin(phi), 0], [np.sin(phi), np.cos(phi), 0], [0, 0, 1]] + ) + self._fin_to_body_no_cant_angle = R_phi.transpose + + R_delta = Matrix( [ - [ - -np.cos(delta) * np.cos(phi), - -np.cos(delta) * np.sin(phi), - np.sin(delta), - ], - [-np.sin(phi), np.cos(phi), 0], - [ - np.sin(delta) * np.cos(phi), - np.sin(delta) * np.sin(phi), - -np.cos(delta), - ], + [np.cos(delta), 0, -np.sin(delta)], + [0, 1, 0], + [np.sin(delta), 0, np.cos(delta)], ] ) + + # self._body_to_fin = R + # self._fin_to_body = R.transpose + + # Body to fin aerodynamic frame rotation matrix, need only invert the x and z axis # TODO aerodynamic frame??? + self.Rr = Matrix([[-1, 0, 0], [0, 1, 0], [0, 0, -1]]) + R = (R_delta @ R_phi @ self.Rr).round(10) + self._body_to_fin = R self._fin_to_body = R.transpose - # Body to fin aerodynamic frame rotation matrix, need only invert the x and z axis - R = Matrix([[-1, 0, 0], [0, 1, 0], [0, 0, -1]]) @ R + # R = R @ Rr self._body_to_fin_aero = R self._fin_aero_to_body = R.transpose From b4b369e7aea031f56d0b271de73c4fe794bce90e Mon Sep 17 00:00:00 2001 From: MateusStano Date: Thu, 17 Apr 2025 16:59:11 +0200 Subject: [PATCH 08/32] ENH: create _BaseFin class --- rocketpy/rocket/aero_surface/fins/base_fin.py | 200 ++++++++++++ rocketpy/rocket/aero_surface/fins/fin.py | 301 ++++++++---------- rocketpy/rocket/aero_surface/fins/fins.py | 156 +-------- 3 files changed, 354 insertions(+), 303 deletions(-) create mode 100644 rocketpy/rocket/aero_surface/fins/base_fin.py diff --git a/rocketpy/rocket/aero_surface/fins/base_fin.py b/rocketpy/rocket/aero_surface/fins/base_fin.py new file mode 100644 index 000000000..c97683edf --- /dev/null +++ b/rocketpy/rocket/aero_surface/fins/base_fin.py @@ -0,0 +1,200 @@ +import math +from abc import ABC, abstractmethod + +import numpy as np + +from rocketpy.mathutils.function import Function + +from ..aero_surface import AeroSurface + + +class _BaseFin(AeroSurface): + """ + Base class for fins, shared by both Fin and Fins classes. + Inherits from AeroSurface. + + Handles shared initialization logic and common properties. + """ + + def __init__( + self, name, rocket_radius, root_chord, span, airfoil=None, cant_angle=0 + ): + """ + Initialize the base fin class. + + Parameters + ---------- + name : str + Name of the fin or fin set. + rocket_radius : float + Rocket radius in meters. + root_chord : float + Root chord of the fin in meters. + span : float + Span of the fin in meters. + airfoil : tuple, optional + Tuple containing airfoil data and unit ('degrees' or 'radians'). + cant_angle : float, optional + Cant angle in degrees. + """ + self.name = name + self._rocket_radius = rocket_radius + self._root_chord = root_chord + self._span = span + self._airfoil = airfoil + self._cant_angle = cant_angle + self._cant_angle_rad = math.radians(cant_angle) + + self.d = 2 * rocket_radius + self.ref_area = np.pi * rocket_radius**2 + + super().__init__(name, self.ref_area, self.d) + + @property + def rocket_radius(self): + return self._rocket_radius + + @rocket_radius.setter + def rocket_radius(self, value): + self._rocket_radius = value + self.evaluate_geometrical_parameters() + self.evaluate_center_of_pressure() + self.evaluate_lift_coefficient() + self.evaluate_roll_parameters() + + @property + def root_chord(self): + return self._root_chord + + @root_chord.setter + def root_chord(self, value): + self._root_chord = value + self.evaluate_geometrical_parameters() + self.evaluate_center_of_pressure() + self.evaluate_lift_coefficient() + self.evaluate_roll_parameters() + + @property + def span(self): + return self._span + + @span.setter + def span(self, value): + self._span = value + self.evaluate_geometrical_parameters() + self.evaluate_center_of_pressure() + self.evaluate_lift_coefficient() + self.evaluate_roll_parameters() + + @property + def cant_angle(self): + return self._cant_angle + + @cant_angle.setter + def cant_angle(self, value): + self._cant_angle = value + self.cant_angle_rad = math.radians(value) + + @property + def cant_angle_rad(self): + return self._cant_angle_rad # TODO check this sign and why??? + + @cant_angle_rad.setter + def cant_angle_rad(self, value): + self._cant_angle_rad = value + self.evaluate_geometrical_parameters() + self.evaluate_center_of_pressure() + self.evaluate_lift_coefficient() + self.evaluate_roll_parameters() + self.evaluate_rotation_matrix() + + @property + def airfoil(self): + return self._airfoil + + @airfoil.setter + def airfoil(self, value): + self._airfoil = value + self.evaluate_geometrical_parameters() + self.evaluate_center_of_pressure() + self.evaluate_lift_coefficient() + self.evaluate_roll_parameters() + self.evaluate_roll_parameters() + self.evaluate_roll_parameters() + + def evaluate_single_fin_lift_coefficient(self): + if not self.airfoil: + # Defines clalpha2D as 2*pi for planar fins + clalpha2D_incompressible = 2 * np.pi + else: + # Defines clalpha2D as the derivative of the lift coefficient curve + # for the specific airfoil + self.airfoil_cl = Function( + self.airfoil[0], + interpolation="linear", + ) + + # Differentiating at alpha = 0 to get cl_alpha + clalpha2D_incompressible = self.airfoil_cl.differentiate_complex_step( + x=1e-3, dx=1e-3 + ) + + # Convert to radians if needed + if self.airfoil[1] == "degrees": + clalpha2D_incompressible *= 180 / np.pi + + # Correcting for compressible flow (apply Prandtl-Glauert correction) + clalpha2D = Function(lambda mach: clalpha2D_incompressible / self._beta(mach)) + + # Diederich's Planform Correlation Parameter + planform_correlation_parameter = ( + 2 * np.pi * self.AR / (clalpha2D * np.cos(self.gamma_c)) + ) + + # Lift coefficient derivative for a single fin + def lift_source(mach): + return ( + clalpha2D(mach) + * self.lift_interference_factor + * planform_correlation_parameter(mach) + * (self.Af / self.ref_area) + * np.cos(self.gamma_c) + ) / ( + 2 + + planform_correlation_parameter(mach) + * np.sqrt(1 + (2 / planform_correlation_parameter(mach)) ** 2) + ) + + self.clalpha_single_fin = Function( + lift_source, + "Mach", + "Lift coefficient derivative for a single fin", + ) + + @abstractmethod + def evaluate_lift_coefficient(self): + pass + + @abstractmethod + def evaluate_roll_parameters(self): + pass + + @abstractmethod + def compute_forces_and_moments(self): + pass + + @abstractmethod + def evaluate_center_of_pressure(self): + pass + + @abstractmethod + def evaluate_geometrical_parameters(self): + pass + + @abstractmethod + def evaluate_shape(self): + pass + + @abstractmethod + def draw(self): + pass diff --git a/rocketpy/rocket/aero_surface/fins/fin.py b/rocketpy/rocket/aero_surface/fins/fin.py index 1f9f9ea77..8229d661d 100644 --- a/rocketpy/rocket/aero_surface/fins/fin.py +++ b/rocketpy/rocket/aero_surface/fins/fin.py @@ -4,11 +4,12 @@ from rocketpy.mathutils.function import Function from rocketpy.mathutils.vector_matrix import Matrix, Vector +from rocketpy.rocket.aero_surface.fins.base_fin import _BaseFin from ..aero_surface import AeroSurface -class Fin(AeroSurface): +class Fin(_BaseFin): """Abstract class that holds common methods for the individual fin classes. Cannot be instantiated. @@ -133,30 +134,23 @@ def __init__( accepting either "radians" or "degrees". name : str Name of fin. - - Returns - ------- - None """ - # Compute auxiliary geometrical parameters - d = 2 * rocket_radius - ref_area = np.pi * rocket_radius**2 # Reference area - - super().__init__(name, ref_area, d) + super().__init__( + name=name, + rocket_radius=rocket_radius, + root_chord=root_chord, + span=span, + airfoil=airfoil, + cant_angle=cant_angle, + ) # Store values - self.name = name - self.d = d - self.ref_area = ref_area - self._rocket_radius = rocket_radius - self._airfoil = airfoil - self._root_chord = root_chord - self._span = span - self._cant_angle = -cant_angle - self._cant_angle_rad = math.radians(-cant_angle) self._angular_position = angular_position self._angular_position_rad = math.radians(angular_position) + self.M3dh = [] # Roll moment damping + self.cldwh = [] # Roll moment lift coefficient derivative + @property def angular_position(self): return self._angular_position @@ -175,76 +169,6 @@ def angular_position_rad(self, value): self._angular_position_rad = value self.evaluate_rotation_matrix() - @property - def root_chord(self): - return self._root_chord - - @root_chord.setter - def root_chord(self, value): - self._root_chord = value - self.evaluate_geometrical_parameters() - self.evaluate_center_of_pressure() - self.evaluate_lift_coefficient() - self.evaluate_roll_parameters() - - @property - def span(self): - return self._span - - @span.setter - def span(self, value): - self._span = value - self.evaluate_geometrical_parameters() - self.evaluate_center_of_pressure() - self.evaluate_lift_coefficient() - self.evaluate_roll_parameters() - - @property - def rocket_radius(self): - return self._rocket_radius - - @rocket_radius.setter - def rocket_radius(self, value): - self._rocket_radius = value - self.evaluate_geometrical_parameters() - self.evaluate_center_of_pressure() - self.evaluate_lift_coefficient() - self.evaluate_roll_parameters() - - @property - def cant_angle(self): - return -self._cant_angle - - @cant_angle.setter - def cant_angle(self, value): - self._cant_angle = -value - self.cant_angle_rad = math.radians(-value) - - @property - def cant_angle_rad(self): - return self._cant_angle_rad - - @cant_angle_rad.setter - def cant_angle_rad(self, value): - self._cant_angle_rad = value - self.evaluate_geometrical_parameters() - self.evaluate_center_of_pressure() - self.evaluate_lift_coefficient() - self.evaluate_roll_parameters() - self.evaluate_rotation_matrix() - - @property - def airfoil(self): - return self._airfoil - - @airfoil.setter - def airfoil(self, value): - self._airfoil = value - self.evaluate_geometrical_parameters() - self.evaluate_center_of_pressure() - self.evaluate_lift_coefficient() - self.evaluate_roll_parameters() - def evaluate_lift_coefficient(self): """Calculates and returns the fin set's lift coefficient. The lift coefficient is saved and returned. This function @@ -256,53 +180,7 @@ def evaluate_lift_coefficient(self): ------- None """ - if not self.airfoil: - # Defines clalpha2D as 2*pi for planar fins - clalpha2D_incompressible = 2 * np.pi - else: - # Defines clalpha2D as the derivative of the lift coefficient curve - # for the specific airfoil - self.airfoil_cl = Function( - self.airfoil[0], - interpolation="linear", - ) - - # Differentiating at alpha = 0 to get cl_alpha - clalpha2D_incompressible = self.airfoil_cl.differentiate_complex_step( - x=1e-3, dx=1e-3 - ) - - # Convert to radians if needed - if self.airfoil[1] == "degrees": - clalpha2D_incompressible *= 180 / np.pi - - # Correcting for compressible flow (apply Prandtl-Glauert correction) - clalpha2D = Function(lambda mach: clalpha2D_incompressible / self._beta(mach)) - - # Diederich's Planform Correlation Parameter - planform_correlation_parameter = ( - 2 * np.pi * self.AR / (clalpha2D * np.cos(self.gamma_c)) - ) - - # Lift coefficient derivative for a single fin - def lift_source(mach): - return ( - clalpha2D(mach) - * self.lift_interference_factor - * planform_correlation_parameter(mach) - * (self.Af / self.ref_area) - * np.cos(self.gamma_c) - ) / ( - 2 - + planform_correlation_parameter(mach) - * np.sqrt(1 + (2 / planform_correlation_parameter(mach)) ** 2) - ) - - self.clalpha_single_fin = Function( - lift_source, - "Mach", - "Lift coefficient derivative for a single fin", - ) + self.evaluate_single_fin_lift_coefficient() self.clalpha = self.clalpha_single_fin @@ -326,7 +204,12 @@ def evaluate_roll_parameters(self): roll moment damping coefficient and the cant angle in radians """ - clf_delta = Function(lambda mach: 0) + clf_delta = ( + self.roll_forcing_interference_factor + * (self.Yma + self.rocket_radius) + * self.clalpha_single_fin + / self.reference_length + ) # TODO: should calculate this as well, should be same formula as fins clf_delta.set_inputs("Mach") clf_delta.set_outputs("Roll moment forcing coefficient derivative") cld_omega = -( @@ -404,40 +287,50 @@ def compute_forces_and_moments( stream_mach, rho, cp, - _, - omega1, - omega2, - omega3, - ): + omega, + *args, + ): # pylint: disable=arguments-differ """Computes the forces and moments acting on the aerodynamic surface. Parameters ---------- - stream_speed : int, float - Speed of the flow stream in the body frame. + stream_velocity : tuple of float + The velocity of the airflow relative to the surface. + stream_speed : float + The magnitude of the airflow speed. + stream_mach : float + The Mach number of the airflow. + rho : float + Air density. + cp : Vector + Center of pressure coordinates in the body frame. + omega: tuple[float, float, float] + Tuple containing angular velocities around the x, y, z axes. + Returns + ------- + tuple of float + The aerodynamic forces (lift, side_force, drag) and moments + (pitch, yaw, roll) in the body frame. """ - self.omega1 = omega1 - self.omega2 = omega2 - self.omega3 = omega3 R1, R2, R3, M1, M2, M3 = 0, 0, 0, 0, 0, 0 + # stream velocity in fin frame - stream_vx_f, _, stream_vz_f = self._body_to_fin_aero @ stream_velocity - if stream_vx_f != 0: - attack_angle = np.arctan(-stream_vx_f / stream_vz_f) - # Force in the X direction of the fin - X = ( - 0.5 - * rho - * stream_speed**2 - * self.reference_area - * self.cl(attack_angle, stream_mach) - ) - M = cp.z * X - N = -(self.cp[1] + self.rocket_radius) * X - # Forces and moments in body frame - R1, R2, R3 = self._fin_aero_to_body @ Vector([X, 0, 0]) - M1, M2, M3 = self._fin_aero_to_body @ Vector([0, M, N]) + stream_velocity_f = self._body_to_fin_aero @ stream_velocity + + attack_angle = np.arctan2(stream_velocity_f[0], stream_velocity_f[2]) + # Force in the X direction of the fin + X = ( + 0.5 + * rho + * stream_speed**2 + * self.reference_area + * self.cl.get_value_opt(attack_angle, stream_mach) + ) + # Force in body frame + R1, R2, R3 = self._fin_aero_to_body @ Vector([X, 0, 0]) + # Moments + M1, M2, M3 = cp ^ Vector([R1, R2, R3]) # Roll damping _, cld_omega, _ = self.roll_parameters @@ -446,12 +339,92 @@ def compute_forces_and_moments( * self.reference_area * (self.reference_length) ** 2 * cld_omega.get_value_opt(stream_mach) - * omega3 + * omega[2] # omega3 / 2 ) M3 += M3_damping return R1, R2, R3, M1, M2, M3 + def compute_forces_and_moments2( + self, + stream_velocity, + stream_speed, + stream_mach, + rho, + cp, + omega, + *args, + ): # pylint: disable=arguments-differ + """Computes the forces and moments acting on the aerodynamic surface. + + Parameters + ---------- + stream_velocity : tuple of float + The velocity of the airflow relative to the surface. + stream_speed : float + The magnitude of the airflow speed. + stream_mach : float + The Mach number of the airflow. + rho : float + Air density. + cp : Vector + Center of pressure coordinates in the body frame. + omega: tuple[float, float, float] + Tuple containing angular velocities around the x, y, z axes. + + Returns + ------- + tuple of float + The aerodynamic forces (lift, side_force, drag) and moments + (pitch, yaw, roll) in the body frame. + """ + R1, R2, R3, M1, M2, M3 = 0, 0, 0, 0, 0, 0 + + # stream velocity in fin frame + stream_velocity_f = self._body_to_fin_aero @ stream_velocity + + attack_angle = np.arctan2(stream_velocity_f[0], stream_velocity_f[2]) + # Force in the X direction of the fin + X = ( + 0.5 + * rho + * stream_speed**2 + * self.reference_area + * self.cl.get_value_opt(attack_angle, stream_mach) # TODO getvalueopt + ) + # Force in body frame + R1, R2, R3 = self._fin_aero_to_body @ Vector([X, 0, 0]) + + # Moments + M1, M2, M3 = cp ^ Vector([R1, R2, R3]) + + # Exclude M3 for + M3 = 0 + + # Roll + clf_delta, cld_omega, cant_angle_rad = self.roll_parameters + cant_angle_rad = -cant_angle_rad + M3_forcing = ( + (1 / 2 * rho * stream_speed**2) + * self.reference_area + * self.reference_length + * clf_delta.get_value_opt(stream_mach) + * cant_angle_rad + ) + M3_damping = ( + (1 / 2 * rho * stream_speed) + * self.reference_area + * (self.reference_length) ** 2 + * cld_omega.get_value_opt(stream_mach) + * omega[2] # omega3 + / 2 + ) + M3 = M3_forcing + M3_damping + return R1, R2, R3, M1, M2, M3 + + def to_dict(self): + pass # TODO + def draw(self): """Draw the fin shape along with some important information, including the center line, the quarter line and the center of pressure position. diff --git a/rocketpy/rocket/aero_surface/fins/fins.py b/rocketpy/rocket/aero_surface/fins/fins.py index 8990eb958..3092ad120 100644 --- a/rocketpy/rocket/aero_surface/fins/fins.py +++ b/rocketpy/rocket/aero_surface/fins/fins.py @@ -1,11 +1,12 @@ import numpy as np from rocketpy.mathutils.function import Function +from rocketpy.rocket.aero_surface.fins.base_fin import _BaseFin from ..aero_surface import AeroSurface -class Fins(AeroSurface): +class Fins(_BaseFin): """Abstract class that holds common methods for the fin classes. Cannot be instantiated. @@ -132,27 +133,18 @@ def __init__( accepting either "radians" or "degrees". name : str Name of fin set. - - Returns - ------- - None """ - # Compute auxiliary geometrical parameters - d = 2 * rocket_radius - ref_area = np.pi * rocket_radius**2 # Reference area - - super().__init__(name, ref_area, d) + super().__init__( + name=name, + rocket_radius=rocket_radius, + root_chord=root_chord, + span=span, + airfoil=airfoil, + cant_angle=-cant_angle, + ) # Store values self._n = n - self._rocket_radius = rocket_radius - self._airfoil = airfoil - self._cant_angle = cant_angle - self._root_chord = root_chord - self._span = span - self.name = name - self.d = d - self.ref_area = ref_area # Reference area @property def n(self): @@ -166,134 +158,24 @@ def n(self, value): self.evaluate_lift_coefficient() self.evaluate_roll_parameters() - @property - def root_chord(self): - return self._root_chord - - @root_chord.setter - def root_chord(self, value): - self._root_chord = value - self.evaluate_geometrical_parameters() - self.evaluate_center_of_pressure() - self.evaluate_lift_coefficient() - self.evaluate_roll_parameters() - - @property - def span(self): - return self._span - - @span.setter - def span(self, value): - self._span = value - self.evaluate_geometrical_parameters() - self.evaluate_center_of_pressure() - self.evaluate_lift_coefficient() - self.evaluate_roll_parameters() - - @property - def rocket_radius(self): - return self._rocket_radius - - @rocket_radius.setter - def rocket_radius(self, value): - self._rocket_radius = value - self.evaluate_geometrical_parameters() - self.evaluate_center_of_pressure() - self.evaluate_lift_coefficient() - self.evaluate_roll_parameters() - - @property - def cant_angle(self): - return self._cant_angle - - @cant_angle.setter - def cant_angle(self, value): - self._cant_angle = value - self.evaluate_geometrical_parameters() - self.evaluate_center_of_pressure() - self.evaluate_lift_coefficient() - self.evaluate_roll_parameters() - - @property - def airfoil(self): - return self._airfoil - - @airfoil.setter - def airfoil(self, value): - self._airfoil = value - self.evaluate_geometrical_parameters() - self.evaluate_center_of_pressure() - self.evaluate_lift_coefficient() - self.evaluate_roll_parameters() - def evaluate_lift_coefficient(self): """Calculates and returns the fin set's lift coefficient. The lift coefficient is saved and returned. This function also calculates and saves the lift coefficient derivative for a single fin and the lift coefficient derivative for a number of n fins corrected for Fin-Body interference. - - Returns - ------- - None """ - if not self.airfoil: - # Defines clalpha2D as 2*pi for planar fins - clalpha2D_incompressible = 2 * np.pi - else: - # Defines clalpha2D as the derivative of the lift coefficient curve - # for the specific airfoil - self.airfoil_cl = Function( - self.airfoil[0], - interpolation="linear", - ) - - # Differentiating at alpha = 0 to get cl_alpha - clalpha2D_incompressible = self.airfoil_cl.differentiate_complex_step( - x=1e-3, dx=1e-3 - ) - - # Convert to radians if needed - if self.airfoil[1] == "degrees": - clalpha2D_incompressible *= 180 / np.pi - - # Correcting for compressible flow (apply Prandtl-Glauert correction) - clalpha2D = Function(lambda mach: clalpha2D_incompressible / self._beta(mach)) - - # Diederich's Planform Correlation Parameter - planform_correlation_parameter = ( - 2 * np.pi * self.AR / (clalpha2D * np.cos(self.gamma_c)) - ) - - # Lift coefficient derivative for a single fin - def lift_source(mach): - return ( - clalpha2D(mach) - * planform_correlation_parameter(mach) - * (self.Af / self.ref_area) - * np.cos(self.gamma_c) - ) / ( - 2 - + planform_correlation_parameter(mach) - * np.sqrt(1 + (2 / planform_correlation_parameter(mach)) ** 2) - ) - - self.clalpha_single_fin = Function( - lift_source, - "Mach", - "Lift coefficient derivative for a single fin", - ) + self.evaluate_single_fin_lift_coefficient() # Lift coefficient derivative for n fins corrected with Fin-Body interference self.clalpha_multiple_fins = ( - self.lift_interference_factor - * self.fin_num_correction(self.n) - * self.clalpha_single_fin + self.fin_num_correction(self.n) * self.clalpha_single_fin ) # Function of mach number self.clalpha_multiple_fins.set_inputs("Mach") self.clalpha_multiple_fins.set_outputs( f"Lift coefficient derivative for {self.n:.0f} fins" ) + self.clalpha = self.clalpha_multiple_fins # Cl = clalpha * alpha @@ -316,15 +198,13 @@ def evaluate_roll_parameters(self): roll moment damping coefficient and the cant angle in radians """ - - self.cant_angle_rad = np.radians(self.cant_angle) - clf_delta = ( self.roll_forcing_interference_factor * self.n * (self.Yma + self.rocket_radius) * self.clalpha_single_fin - / self.d + / self.reference_length + / 2 # TODO: explaing this / 2 in docs ) # Function of mach number clf_delta.set_inputs("Mach") clf_delta.set_outputs("Roll moment forcing coefficient derivative") @@ -423,6 +303,8 @@ def compute_forces_and_moments( * omega[2] / 2 ) + self.M3dh.append(M3_damping) + self.cldwh.append(clf_delta.get_value_opt(stream_mach)) M3 = M3_forcing + M3_damping return R1, R2, R3, M1, M2, M3 @@ -461,9 +343,5 @@ def draw(self, *, filename=None): the plot will be shown instead of saved. Supported file endings are: eps, jpg, jpeg, pdf, pgf, png, ps, raw, rgba, svg, svgz, tif, tiff and webp (these are the formats supported by matplotlib). - - Returns - ------- - None """ self.plots.draw(filename=filename) From f4d32714edb3d41f85335c1aaf9a8d94a72d9b77 Mon Sep 17 00:00:00 2001 From: MateusStano Date: Fri, 18 Apr 2025 15:43:10 +0200 Subject: [PATCH 09/32] MNT: fix variable names in Fin --- .../aero_surface/fins/trapezoidal_fin.py | 55 +++++++++---------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/rocketpy/rocket/aero_surface/fins/trapezoidal_fin.py b/rocketpy/rocket/aero_surface/fins/trapezoidal_fin.py index 710afb965..20114b54f 100644 --- a/rocketpy/rocket/aero_surface/fins/trapezoidal_fin.py +++ b/rocketpy/rocket/aero_surface/fins/trapezoidal_fin.py @@ -189,11 +189,11 @@ def evaluate_center_of_pressure(self): - self.root_chord * self.tip_chord / (self.root_chord + self.tip_chord) ) self.cpx = 0 - self.cpy = self.yma + self.cpy = self.Yma self.cpz = cpz self.cp = (self.cpx, self.cpy, self.cpz) - def evaluate_geometrical_parameters(self): + def evaluate_geometrical_parameters(self): # pylint: disable=too-many-statements """Calculates and saves fin set's geometrical parameters such as the fins' area, aspect ratio and parameters for roll movement. @@ -201,25 +201,25 @@ def evaluate_geometrical_parameters(self): ------- None """ - - yr = self.root_chord + self.tip_chord - fin_area = yr * self.span / 2 # Fin area - f_ar = 2 * self.span**2 / fin_area # Fin aspect ratio - gamma_c = math.atan( + # pylint: disable=invalid-name + Yr = self.root_chord + self.tip_chord + Af = Yr * self.span / 2 # Fin area + AR = 2 * self.span**2 / Af # Fin aspect ratio + gamma_c = np.arctan( (self.sweep_length + 0.5 * self.tip_chord - 0.5 * self.root_chord) / (self.span) ) - yma = ( - (self.span / 3) * (self.root_chord + 2 * self.tip_chord) / yr + Yma = ( + (self.span / 3) * (self.root_chord + 2 * self.tip_chord) / Yr ) # Span wise coord of mean aero chord # Fin–body interference correction parameters tau = (self.span + self.rocket_radius) / self.rocket_radius lift_interference_factor = 1 + 1 / tau - chord_ratio_tr = self.tip_chord / self.root_chord + lambda_ = self.tip_chord / self.root_chord # Parameters for Roll Moment. - # Documented at: https://github.com/RocketPy-Team/RocketPy/blob/master/docs/technical/aerodynamics/Roll_Equations.pdf + # Documented at: https://docs.rocketpy.org/en/latest/technical/ roll_geometrical_constant = ( (self.root_chord + 3 * self.tip_chord) * self.span**3 + 4 @@ -229,36 +229,35 @@ def evaluate_geometrical_parameters(self): + 6 * (self.root_chord + self.tip_chord) * self.span * self.rocket_radius**2 ) / 12 roll_damping_interference_factor = 1 + ( - ((tau - chord_ratio_tr) / (tau)) - - ((1 - chord_ratio_tr) / (tau - 1)) * math.log(tau) + ((tau - lambda_) / (tau)) - ((1 - lambda_) / (tau - 1)) * np.log(tau) ) / ( - ((tau + 1) * (tau - chord_ratio_tr)) / (2) - - ((1 - chord_ratio_tr) * (tau**3 - 1)) / (3 * (tau - 1)) + ((tau + 1) * (tau - lambda_)) / (2) + - ((1 - lambda_) * (tau**3 - 1)) / (3 * (tau - 1)) ) - roll_forcing_interference_factor = (1 / math.pi**2) * ( - (math.pi**2 / 4) * ((tau + 1) ** 2 / tau**2) - + ((math.pi * (tau**2 + 1) ** 2) / (tau**2 * (tau - 1) ** 2)) - * math.asin((tau**2 - 1) / (tau**2 + 1)) - - (2 * math.pi * (tau + 1)) / (tau * (tau - 1)) + roll_forcing_interference_factor = (1 / np.pi**2) * ( + (np.pi**2 / 4) * ((tau + 1) ** 2 / tau**2) + + ((np.pi * (tau**2 + 1) ** 2) / (tau**2 * (tau - 1) ** 2)) + * np.arcsin((tau**2 - 1) / (tau**2 + 1)) + - (2 * np.pi * (tau + 1)) / (tau * (tau - 1)) + ((tau**2 + 1) ** 2) / (tau**2 * (tau - 1) ** 2) - * (math.asin((tau**2 - 1) / (tau**2 + 1))) ** 2 + * (np.arcsin((tau**2 - 1) / (tau**2 + 1))) ** 2 - (4 * (tau + 1)) / (tau * (tau - 1)) - * math.asin((tau**2 - 1) / (tau**2 + 1)) - + (8 / (tau - 1) ** 2) * math.log((tau**2 + 1) / (2 * tau)) + * np.arcsin((tau**2 - 1) / (tau**2 + 1)) + + (8 / (tau - 1) ** 2) * np.log((tau**2 + 1) / (2 * tau)) ) # Store values - self.yr = yr - self.fin_area = fin_area # Fin area - self.f_ar = f_ar # Aspect Ratio + self.Yr = Yr + self.Af = Af # Fin area + self.AR = AR # Aspect Ratio self.gamma_c = gamma_c # Mid chord angle - self.yma = yma # Span wise coord of mean aero chord + self.Yma = Yma # Span wise coord of mean aero chord self.roll_geometrical_constant = roll_geometrical_constant self.tau = tau self.lift_interference_factor = lift_interference_factor - self.chord_ratio_tr = chord_ratio_tr + self.λ = lambda_ # pylint: disable=non-ascii-name self.roll_damping_interference_factor = roll_damping_interference_factor self.roll_forcing_interference_factor = roll_forcing_interference_factor From 8103fd813ee2f0f20ed1b74b585b9925ec5acc15 Mon Sep 17 00:00:00 2001 From: MateusStano Date: Fri, 18 Apr 2025 20:18:04 +0200 Subject: [PATCH 10/32] BUG: correct interference factors --- rocketpy/rocket/aero_surface/fins/fin.py | 2 +- rocketpy/rocket/aero_surface/fins/fins.py | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/rocketpy/rocket/aero_surface/fins/fin.py b/rocketpy/rocket/aero_surface/fins/fin.py index 8229d661d..729514af3 100644 --- a/rocketpy/rocket/aero_surface/fins/fin.py +++ b/rocketpy/rocket/aero_surface/fins/fin.py @@ -182,7 +182,7 @@ def evaluate_lift_coefficient(self): """ self.evaluate_single_fin_lift_coefficient() - self.clalpha = self.clalpha_single_fin + self.clalpha = self.clalpha_single_fin * self.lift_interference_factor # Cl = clalpha * alpha self.cl = Function( diff --git a/rocketpy/rocket/aero_surface/fins/fins.py b/rocketpy/rocket/aero_surface/fins/fins.py index 3092ad120..e463ad1a2 100644 --- a/rocketpy/rocket/aero_surface/fins/fins.py +++ b/rocketpy/rocket/aero_surface/fins/fins.py @@ -169,7 +169,9 @@ def evaluate_lift_coefficient(self): # Lift coefficient derivative for n fins corrected with Fin-Body interference self.clalpha_multiple_fins = ( - self.fin_num_correction(self.n) * self.clalpha_single_fin + self.fin_num_correction(self.n) + * self.lift_interference_factor + * self.clalpha_single_fin ) # Function of mach number self.clalpha_multiple_fins.set_inputs("Mach") self.clalpha_multiple_fins.set_outputs( @@ -200,11 +202,10 @@ def evaluate_roll_parameters(self): """ clf_delta = ( self.roll_forcing_interference_factor - * self.n + * self.fin_num_correction(self.n) * (self.Yma + self.rocket_radius) * self.clalpha_single_fin / self.reference_length - / 2 # TODO: explaing this / 2 in docs ) # Function of mach number clf_delta.set_inputs("Mach") clf_delta.set_outputs("Roll moment forcing coefficient derivative") From c0d57d9f648694c6760528e557810188608f17f4 Mon Sep 17 00:00:00 2001 From: MateusStano Date: Fri, 18 Apr 2025 20:18:47 +0200 Subject: [PATCH 11/32] ENH: create _TrapezoidalMixin --- .../aero_surface/fins/_trapezoidal_mixin.py | 185 ++++++++++++++++++ .../aero_surface/fins/trapezoidal_fin.py | 181 +---------------- .../aero_surface/fins/trapezoidal_fins.py | 180 +---------------- 3 files changed, 194 insertions(+), 352 deletions(-) create mode 100644 rocketpy/rocket/aero_surface/fins/_trapezoidal_mixin.py diff --git a/rocketpy/rocket/aero_surface/fins/_trapezoidal_mixin.py b/rocketpy/rocket/aero_surface/fins/_trapezoidal_mixin.py new file mode 100644 index 000000000..9cca4186e --- /dev/null +++ b/rocketpy/rocket/aero_surface/fins/_trapezoidal_mixin.py @@ -0,0 +1,185 @@ +import numpy as np + + +class _TrapezoidalMixin: + """Mixin class for trapezoidal fins. + This class contains methods and properties specific to trapezoidal fin shapes. + It is designed to be used in conjunction with other classes that define the + overall behavior of the fins. + """ + + @property + def tip_chord(self): + return self._tip_chord + + @tip_chord.setter + def tip_chord(self, value): + self._tip_chord = value + self.evaluate_geometrical_parameters() + self.evaluate_center_of_pressure() + self.evaluate_lift_coefficient() + self.evaluate_roll_parameters() + + @property + def sweep_angle(self): + return self._sweep_angle + + @sweep_angle.setter + def sweep_angle(self, value): + self._sweep_angle = value + self._sweep_length = np.tan(value * np.pi / 180) * self.span + self.evaluate_geometrical_parameters() + self.evaluate_center_of_pressure() + self.evaluate_lift_coefficient() + self.evaluate_roll_parameters() + + @property + def sweep_length(self): + return self._sweep_length + + @sweep_length.setter + def sweep_length(self, value): + self._sweep_length = value + self.evaluate_geometrical_parameters() + self.evaluate_center_of_pressure() + self.evaluate_lift_coefficient() + self.evaluate_roll_parameters() + + def initialize(self, sweep_length, sweep_angle, root_chord, tip_chord, span): + # Check if sweep angle or sweep length is given + if sweep_length is not None and sweep_angle is not None: + raise ValueError("Cannot use sweep_length and sweep_angle together") + elif sweep_angle is not None: + 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 + self._sweep_angle = sweep_angle + + self.evaluate_geometrical_parameters() + self.evaluate_center_of_pressure() + self.evaluate_lift_coefficient() + self.evaluate_roll_parameters() + + def evaluate_center_of_pressure(self): + """Calculates and returns the center of pressure of the fin set in local + coordinates. The center of pressure position is saved and stored as a + tuple. + + Returns + ------- + None + """ + # Center of pressure position in local coordinates + cpz = (self.sweep_length / 3) * ( + (self.root_chord + 2 * self.tip_chord) / (self.root_chord + self.tip_chord) + ) + (1 / 6) * ( + self.root_chord + + self.tip_chord + - self.root_chord * self.tip_chord / (self.root_chord + self.tip_chord) + ) + self.cpx = 0 + self.cpy = 0 + self.cpz = cpz + self.cp = (self.cpx, self.cpy, self.cpz) + + def evaluate_geometrical_parameters(self): + """Calculates and saves fin set's geometrical parameters such as the + fins' area, aspect ratio and parameters for roll movement. + + Returns + ------- + None + """ + # pylint: disable=invalid-name + Yr = self.root_chord + self.tip_chord + Af = Yr * self.span / 2 # Fin area + AR = 2 * self.span**2 / Af # Fin aspect ratio + gamma_c = np.arctan( + (self.sweep_length + 0.5 * self.tip_chord - 0.5 * self.root_chord) + / (self.span) + ) + Yma = ( + (self.span / 3) * (self.root_chord + 2 * self.tip_chord) / Yr + ) # Span wise coord of mean aero chord + + # Fin–body interference correction parameters + tau = (self.span + self.rocket_radius) / self.rocket_radius + lift_interference_factor = 1 + 1 / tau + lambda_ = self.tip_chord / self.root_chord + + # Parameters for Roll Moment. + # Documented at: https://docs.rocketpy.org/en/latest/technical/ + roll_geometrical_constant = ( + (self.root_chord + 3 * self.tip_chord) * self.span**3 + + 4 + * (self.root_chord + 2 * self.tip_chord) + * self.rocket_radius + * self.span**2 + + 6 * (self.root_chord + self.tip_chord) * self.span * self.rocket_radius**2 + ) / 12 + roll_damping_interference_factor = 1 + ( + ((tau - lambda_) / (tau)) - ((1 - lambda_) / (tau - 1)) * np.log(tau) + ) / ( + ((tau + 1) * (tau - lambda_)) / (2) + - ((1 - lambda_) * (tau**3 - 1)) / (3 * (tau - 1)) + ) + roll_forcing_interference_factor = (1 / np.pi**2) * ( + (np.pi**2 / 4) * ((tau + 1) ** 2 / tau**2) + + ((np.pi * (tau**2 + 1) ** 2) / (tau**2 * (tau - 1) ** 2)) + * np.arcsin((tau**2 - 1) / (tau**2 + 1)) + - (2 * np.pi * (tau + 1)) / (tau * (tau - 1)) + + ((tau**2 + 1) ** 2) + / (tau**2 * (tau - 1) ** 2) + * (np.arcsin((tau**2 - 1) / (tau**2 + 1))) ** 2 + - (4 * (tau + 1)) + / (tau * (tau - 1)) + * np.arcsin((tau**2 - 1) / (tau**2 + 1)) + + (8 / (tau - 1) ** 2) * np.log((tau**2 + 1) / (2 * tau)) + ) + + # Store values + self.Yr = Yr + self.Af = Af # Fin area + self.AR = AR # Aspect Ratio + self.gamma_c = gamma_c # Mid chord angle + self.Yma = Yma # Span wise coord of mean aero chord + self.roll_geometrical_constant = roll_geometrical_constant + self.tau = tau + self.lift_interference_factor = lift_interference_factor + self.λ = lambda_ # pylint: disable=non-ascii-name + self.roll_damping_interference_factor = roll_damping_interference_factor + self.roll_forcing_interference_factor = roll_forcing_interference_factor + + self.evaluate_shape() + + def evaluate_shape(self): + if self.sweep_length: + points = [ + (0, 0), + (self.sweep_length, self.span), + (self.sweep_length + self.tip_chord, self.span), + (self.root_chord, 0), + ] + else: + points = [ + (0, 0), + (self.root_chord - self.tip_chord, self.span), + (self.root_chord, self.span), + (self.root_chord, 0), + ] + + x_array, y_array = zip(*points) + self.shape_vec = [np.array(x_array), np.array(y_array)] + + def info(self): + self.prints.geometry() + self.prints.lift() + + def all_info(self): + self.prints.all() + self.plots.all() diff --git a/rocketpy/rocket/aero_surface/fins/trapezoidal_fin.py b/rocketpy/rocket/aero_surface/fins/trapezoidal_fin.py index 20114b54f..64a176d92 100644 --- a/rocketpy/rocket/aero_surface/fins/trapezoidal_fin.py +++ b/rocketpy/rocket/aero_surface/fins/trapezoidal_fin.py @@ -4,12 +4,14 @@ from rocketpy.plots.aero_surface_plots import _TrapezoidalFinPlots from rocketpy.prints.aero_surface_prints import _TrapezoidalFinPrints +from rocketpy.rocket.aero_surface.fins._trapezoidal_mixin import _TrapezoidalMixin from .fin import Fin +from .geometry_utils import compute_sweep_length -class TrapezoidalFin(Fin): - """A class used to represent a single trapezoidal fin. +class TrapezoidalFin(_TrapezoidalMixin, Fin): + """A class used to represent a single trapezoidal fin. TODO: review this This class inherits from the Fin class. @@ -111,181 +113,8 @@ def __init__( name, ) - # Check if sweep angle or sweep length is given - if sweep_length is not None and sweep_angle is not None: - raise ValueError("Cannot use sweep_length and sweep_angle together") - elif sweep_angle is not None: - sweep_length = math.tan(sweep_angle * math.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 - self._sweep_angle = sweep_angle - - self.evaluate_geometrical_parameters() - self.evaluate_center_of_pressure() - self.evaluate_lift_coefficient() - self.evaluate_roll_parameters() + self.initialize(sweep_length, sweep_angle, root_chord, tip_chord, span) self.evaluate_rotation_matrix() self.prints = _TrapezoidalFinPrints(self) self.plots = _TrapezoidalFinPlots(self) - - @property - def tip_chord(self): - return self._tip_chord - - @tip_chord.setter - def tip_chord(self, value): - self._tip_chord = value - self.evaluate_geometrical_parameters() - self.evaluate_center_of_pressure() - self.evaluate_lift_coefficient() - self.evaluate_roll_parameters() - - @property - def sweep_angle(self): - return self._sweep_angle - - @sweep_angle.setter - def sweep_angle(self, value): - self._sweep_angle = value - self._sweep_length = math.tan(value * math.pi / 180) * self.span - self.evaluate_geometrical_parameters() - self.evaluate_center_of_pressure() - self.evaluate_lift_coefficient() - self.evaluate_roll_parameters() - - @property - def sweep_length(self): - return self._sweep_length - - @sweep_length.setter - def sweep_length(self, value): - self._sweep_length = value - self.evaluate_geometrical_parameters() - self.evaluate_center_of_pressure() - self.evaluate_lift_coefficient() - self.evaluate_roll_parameters() - - def evaluate_center_of_pressure(self): - """Calculates and returns the center of pressure of the fin set in local - coordinates. The center of pressure position is saved and stored as a - tuple. - - Returns - ------- - None - """ - # Center of pressure position in local coordinates - cpz = (self.sweep_length / 3) * ( - (self.root_chord + 2 * self.tip_chord) / (self.root_chord + self.tip_chord) - ) + (1 / 6) * ( - self.root_chord - + self.tip_chord - - self.root_chord * self.tip_chord / (self.root_chord + self.tip_chord) - ) - self.cpx = 0 - self.cpy = self.Yma - self.cpz = cpz - self.cp = (self.cpx, self.cpy, self.cpz) - - def evaluate_geometrical_parameters(self): # pylint: disable=too-many-statements - """Calculates and saves fin set's geometrical parameters such as the - fins' area, aspect ratio and parameters for roll movement. - - Returns - ------- - None - """ - # pylint: disable=invalid-name - Yr = self.root_chord + self.tip_chord - Af = Yr * self.span / 2 # Fin area - AR = 2 * self.span**2 / Af # Fin aspect ratio - gamma_c = np.arctan( - (self.sweep_length + 0.5 * self.tip_chord - 0.5 * self.root_chord) - / (self.span) - ) - Yma = ( - (self.span / 3) * (self.root_chord + 2 * self.tip_chord) / Yr - ) # Span wise coord of mean aero chord - - # Fin–body interference correction parameters - tau = (self.span + self.rocket_radius) / self.rocket_radius - lift_interference_factor = 1 + 1 / tau - lambda_ = self.tip_chord / self.root_chord - - # Parameters for Roll Moment. - # Documented at: https://docs.rocketpy.org/en/latest/technical/ - roll_geometrical_constant = ( - (self.root_chord + 3 * self.tip_chord) * self.span**3 - + 4 - * (self.root_chord + 2 * self.tip_chord) - * self.rocket_radius - * self.span**2 - + 6 * (self.root_chord + self.tip_chord) * self.span * self.rocket_radius**2 - ) / 12 - roll_damping_interference_factor = 1 + ( - ((tau - lambda_) / (tau)) - ((1 - lambda_) / (tau - 1)) * np.log(tau) - ) / ( - ((tau + 1) * (tau - lambda_)) / (2) - - ((1 - lambda_) * (tau**3 - 1)) / (3 * (tau - 1)) - ) - roll_forcing_interference_factor = (1 / np.pi**2) * ( - (np.pi**2 / 4) * ((tau + 1) ** 2 / tau**2) - + ((np.pi * (tau**2 + 1) ** 2) / (tau**2 * (tau - 1) ** 2)) - * np.arcsin((tau**2 - 1) / (tau**2 + 1)) - - (2 * np.pi * (tau + 1)) / (tau * (tau - 1)) - + ((tau**2 + 1) ** 2) - / (tau**2 * (tau - 1) ** 2) - * (np.arcsin((tau**2 - 1) / (tau**2 + 1))) ** 2 - - (4 * (tau + 1)) - / (tau * (tau - 1)) - * np.arcsin((tau**2 - 1) / (tau**2 + 1)) - + (8 / (tau - 1) ** 2) * np.log((tau**2 + 1) / (2 * tau)) - ) - - # Store values - self.Yr = Yr - self.Af = Af # Fin area - self.AR = AR # Aspect Ratio - self.gamma_c = gamma_c # Mid chord angle - self.Yma = Yma # Span wise coord of mean aero chord - self.roll_geometrical_constant = roll_geometrical_constant - self.tau = tau - self.lift_interference_factor = lift_interference_factor - self.λ = lambda_ # pylint: disable=non-ascii-name - self.roll_damping_interference_factor = roll_damping_interference_factor - self.roll_forcing_interference_factor = roll_forcing_interference_factor - - self.evaluate_shape() - - def evaluate_shape(self): - if self.sweep_length: - points = [ - (0, 0), - (self.sweep_length, self.span), - (self.sweep_length + self.tip_chord, self.span), - (self.root_chord, 0), - ] - else: - points = [ - (0, 0), - (self.root_chord - self.tip_chord, self.span), - (self.root_chord, self.span), - (self.root_chord, 0), - ] - - x_array, y_array = zip(*points) - self.shape_vec = [np.array(x_array), np.array(y_array)] - - def info(self): - self.prints.geometry() - self.prints.lift() - - def all_info(self): - self.prints.all() - self.plots.all() diff --git a/rocketpy/rocket/aero_surface/fins/trapezoidal_fins.py b/rocketpy/rocket/aero_surface/fins/trapezoidal_fins.py index 61e2b78fc..efafe9c87 100644 --- a/rocketpy/rocket/aero_surface/fins/trapezoidal_fins.py +++ b/rocketpy/rocket/aero_surface/fins/trapezoidal_fins.py @@ -2,11 +2,13 @@ from rocketpy.plots.aero_surface_plots import _TrapezoidalFinsPlots from rocketpy.prints.aero_surface_prints import _TrapezoidalFinsPrints +from rocketpy.rocket.aero_surface.fins._trapezoidal_mixin import _TrapezoidalMixin from .fins import Fins +from .geometry_utils import compute_sweep_length -class TrapezoidalFins(Fins): +class TrapezoidalFins(_TrapezoidalMixin, Fins): """Class that defines and holds information for a trapezoidal fin set. This class inherits from the Fins class. @@ -169,185 +171,11 @@ def __init__( name, ) - # Check if sweep angle or sweep length is given - if sweep_length is not None and sweep_angle is not None: - raise ValueError("Cannot use sweep_length and sweep_angle together") - elif sweep_angle is not None: - 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 - self._sweep_angle = sweep_angle - - self.evaluate_geometrical_parameters() - self.evaluate_center_of_pressure() - self.evaluate_lift_coefficient() - self.evaluate_roll_parameters() + self.initialize(sweep_length, sweep_angle, root_chord, tip_chord, span) self.prints = _TrapezoidalFinsPrints(self) self.plots = _TrapezoidalFinsPlots(self) - @property - def tip_chord(self): - return self._tip_chord - - @tip_chord.setter - def tip_chord(self, value): - self._tip_chord = value - self.evaluate_geometrical_parameters() - self.evaluate_center_of_pressure() - self.evaluate_lift_coefficient() - self.evaluate_roll_parameters() - - @property - def sweep_angle(self): - return self._sweep_angle - - @sweep_angle.setter - def sweep_angle(self, value): - self._sweep_angle = value - self._sweep_length = np.tan(value * np.pi / 180) * self.span - self.evaluate_geometrical_parameters() - self.evaluate_center_of_pressure() - self.evaluate_lift_coefficient() - self.evaluate_roll_parameters() - - @property - def sweep_length(self): - return self._sweep_length - - @sweep_length.setter - def sweep_length(self, value): - self._sweep_length = value - self.evaluate_geometrical_parameters() - self.evaluate_center_of_pressure() - self.evaluate_lift_coefficient() - self.evaluate_roll_parameters() - - def evaluate_center_of_pressure(self): - """Calculates and returns the center of pressure of the fin set in local - coordinates. The center of pressure position is saved and stored as a - tuple. - - Returns - ------- - None - """ - # Center of pressure position in local coordinates - cpz = (self.sweep_length / 3) * ( - (self.root_chord + 2 * self.tip_chord) / (self.root_chord + self.tip_chord) - ) + (1 / 6) * ( - self.root_chord - + self.tip_chord - - self.root_chord * self.tip_chord / (self.root_chord + self.tip_chord) - ) - self.cpx = 0 - self.cpy = 0 - self.cpz = cpz - self.cp = (self.cpx, self.cpy, self.cpz) - - def evaluate_geometrical_parameters(self): # pylint: disable=too-many-statements - """Calculates and saves fin set's geometrical parameters such as the - fins' area, aspect ratio and parameters for roll movement. - - Returns - ------- - None - """ - # pylint: disable=invalid-name - Yr = self.root_chord + self.tip_chord - Af = Yr * self.span / 2 # Fin area - AR = 2 * self.span**2 / Af # Fin aspect ratio - gamma_c = np.arctan( - (self.sweep_length + 0.5 * self.tip_chord - 0.5 * self.root_chord) - / (self.span) - ) - Yma = ( - (self.span / 3) * (self.root_chord + 2 * self.tip_chord) / Yr - ) # Span wise coord of mean aero chord - - # Fin–body interference correction parameters - tau = (self.span + self.rocket_radius) / self.rocket_radius - lift_interference_factor = 1 + 1 / tau - lambda_ = self.tip_chord / self.root_chord - - # Parameters for Roll Moment. - # Documented at: https://docs.rocketpy.org/en/latest/technical/ - roll_geometrical_constant = ( - (self.root_chord + 3 * self.tip_chord) * self.span**3 - + 4 - * (self.root_chord + 2 * self.tip_chord) - * self.rocket_radius - * self.span**2 - + 6 * (self.root_chord + self.tip_chord) * self.span * self.rocket_radius**2 - ) / 12 - roll_damping_interference_factor = 1 + ( - ((tau - lambda_) / (tau)) - ((1 - lambda_) / (tau - 1)) * np.log(tau) - ) / ( - ((tau + 1) * (tau - lambda_)) / (2) - - ((1 - lambda_) * (tau**3 - 1)) / (3 * (tau - 1)) - ) - roll_forcing_interference_factor = (1 / np.pi**2) * ( - (np.pi**2 / 4) * ((tau + 1) ** 2 / tau**2) - + ((np.pi * (tau**2 + 1) ** 2) / (tau**2 * (tau - 1) ** 2)) - * np.arcsin((tau**2 - 1) / (tau**2 + 1)) - - (2 * np.pi * (tau + 1)) / (tau * (tau - 1)) - + ((tau**2 + 1) ** 2) - / (tau**2 * (tau - 1) ** 2) - * (np.arcsin((tau**2 - 1) / (tau**2 + 1))) ** 2 - - (4 * (tau + 1)) - / (tau * (tau - 1)) - * np.arcsin((tau**2 - 1) / (tau**2 + 1)) - + (8 / (tau - 1) ** 2) * np.log((tau**2 + 1) / (2 * tau)) - ) - - # Store values - self.Yr = Yr - self.Af = Af # Fin area - self.AR = AR # Aspect Ratio - self.gamma_c = gamma_c # Mid chord angle - self.Yma = Yma # Span wise coord of mean aero chord - self.roll_geometrical_constant = roll_geometrical_constant - self.tau = tau - self.lift_interference_factor = lift_interference_factor - self.λ = lambda_ # pylint: disable=non-ascii-name - self.roll_damping_interference_factor = roll_damping_interference_factor - self.roll_forcing_interference_factor = roll_forcing_interference_factor - - self.evaluate_shape() - - def evaluate_shape(self): - if self.sweep_length: - points = [ - (0, 0), - (self.sweep_length, self.span), - (self.sweep_length + self.tip_chord, self.span), - (self.root_chord, 0), - ] - else: - points = [ - (0, 0), - (self.root_chord - self.tip_chord, self.span), - (self.root_chord, self.span), - (self.root_chord, 0), - ] - - x_array, y_array = zip(*points) - self.shape_vec = [np.array(x_array), np.array(y_array)] - - def info(self): - self.prints.geometry() - self.prints.lift() - - def all_info(self): - self.prints.all() - self.plots.all() - def to_dict(self, include_outputs=False): data = super().to_dict(include_outputs) data["tip_chord"] = self.tip_chord From 5ebc901c8fc381a4b7b979d5fcbd6390ec46158d Mon Sep 17 00:00:00 2001 From: MateusStano Date: Fri, 18 Apr 2025 21:11:06 +0200 Subject: [PATCH 12/32] MNT: remove unused methods and variables in fin classes --- rocketpy/rocket/aero_surface/fins/base_fin.py | 6 - rocketpy/rocket/aero_surface/fins/fin.py | 171 +++++++----------- rocketpy/rocket/aero_surface/fins/fins.py | 2 - .../aero_surface/fins/trapezoidal_fin.py | 1 - .../aero_surface/fins/trapezoidal_fins.py | 1 - rocketpy/rocket/rocket.py | 3 +- 6 files changed, 64 insertions(+), 120 deletions(-) diff --git a/rocketpy/rocket/aero_surface/fins/base_fin.py b/rocketpy/rocket/aero_surface/fins/base_fin.py index c97683edf..f8a365d7f 100644 --- a/rocketpy/rocket/aero_surface/fins/base_fin.py +++ b/rocketpy/rocket/aero_surface/fins/base_fin.py @@ -106,7 +106,6 @@ def cant_angle_rad(self, value): self.evaluate_center_of_pressure() self.evaluate_lift_coefficient() self.evaluate_roll_parameters() - self.evaluate_rotation_matrix() @property def airfoil(self): @@ -155,7 +154,6 @@ def evaluate_single_fin_lift_coefficient(self): def lift_source(mach): return ( clalpha2D(mach) - * self.lift_interference_factor * planform_correlation_parameter(mach) * (self.Af / self.ref_area) * np.cos(self.gamma_c) @@ -179,10 +177,6 @@ def evaluate_lift_coefficient(self): def evaluate_roll_parameters(self): pass - @abstractmethod - def compute_forces_and_moments(self): - pass - @abstractmethod def evaluate_center_of_pressure(self): pass diff --git a/rocketpy/rocket/aero_surface/fins/fin.py b/rocketpy/rocket/aero_surface/fins/fin.py index 729514af3..eea8ec0b0 100644 --- a/rocketpy/rocket/aero_surface/fins/fin.py +++ b/rocketpy/rocket/aero_surface/fins/fin.py @@ -151,6 +151,28 @@ def __init__( self.M3dh = [] # Roll moment damping self.cldwh = [] # Roll moment lift coefficient derivative + @property + def cant_angle(self): + return self._cant_angle + + @cant_angle.setter + def cant_angle(self, value): + self._cant_angle = value + self.cant_angle_rad = math.radians(value) + + @property + def cant_angle_rad(self): + return self._cant_angle_rad + + @cant_angle_rad.setter + def cant_angle_rad(self, value): + self._cant_angle_rad = value + self.evaluate_geometrical_parameters() + self.evaluate_center_of_pressure() + self.evaluate_lift_coefficient() + self.evaluate_roll_parameters() + self.evaluate_rotation_matrix() + @property def angular_position(self): return self._angular_position @@ -186,7 +208,7 @@ def evaluate_lift_coefficient(self): # Cl = clalpha * alpha self.cl = Function( - lambda alpha, mach: alpha * self.clalpha_single_fin(mach), + lambda alpha, mach: alpha * self.clalpha(mach), ["Alpha (rad)", "Mach"], "Lift coefficient", ) @@ -205,13 +227,10 @@ def evaluate_roll_parameters(self): radians """ clf_delta = ( - self.roll_forcing_interference_factor - * (self.Yma + self.rocket_radius) - * self.clalpha_single_fin - / self.reference_length - ) # TODO: should calculate this as well, should be same formula as fins - clf_delta.set_inputs("Mach") - clf_delta.set_outputs("Roll moment forcing coefficient derivative") + 0 # TODO: should calculate this as well, should be same formula as fins + ) + # clf_delta.set_inputs("Mach") + # clf_delta.set_outputs("Roll moment forcing coefficient derivative") cld_omega = -( 2 * self.roll_damping_interference_factor @@ -229,7 +248,6 @@ def evaluate_rotation_matrix(self): """Calculates and returns the rotation matrix from the rocket body frame to the fin frame. - TODO: paste this description where it is relevant Note ---- Local coordinate system: @@ -251,13 +269,17 @@ def evaluate_rotation_matrix(self): """ phi = self.angular_position_rad delta = self.cant_angle_rad - # TODO check rotation for nose_to_tail csystems - # Body to fin rotation matrix + + # Rotation about body Z by angular position R_phi = Matrix( - [[np.cos(phi), -np.sin(phi), 0], [np.sin(phi), np.cos(phi), 0], [0, 0, 1]] + [ + [np.cos(phi), -np.sin(phi), 0], + [np.sin(phi), np.cos(phi), 0], + [0, 0, 1], + ] ) - self._fin_to_body_no_cant_angle = R_phi.transpose + # Cant rotation about body Y R_delta = Matrix( [ [np.cos(delta), 0, -np.sin(delta)], @@ -266,19 +288,23 @@ def evaluate_rotation_matrix(self): ] ) - # self._body_to_fin = R - # self._fin_to_body = R.transpose - - # Body to fin aerodynamic frame rotation matrix, need only invert the x and z axis # TODO aerodynamic frame??? - self.Rr = Matrix([[-1, 0, 0], [0, 1, 0], [0, 0, -1]]) - R = (R_delta @ R_phi @ self.Rr).round(10) + # 180 flip about Y to align fin leading/trailing edge + R_pi = Matrix( + [ + [-1, 0, 0], + [0, 1, 0], + [0, 0, -1], + ] + ) - self._body_to_fin = R - self._fin_to_body = R.transpose + # Uncanted body to fin, then apply cant + R_uncanted = R_phi @ R_pi + R_body_to_fin = R_delta @ R_uncanted - # R = R @ Rr - self._body_to_fin_aero = R - self._fin_aero_to_body = R.transpose + # Store for downstream transforms + self._rotation_fin_to_body_uncanted = R_uncanted.transpose + self._rotation_body_to_fin = R_body_to_fin + self._rotation_fin_to_body = R_body_to_fin.transpose def compute_forces_and_moments( self, @@ -316,7 +342,7 @@ def compute_forces_and_moments( R1, R2, R3, M1, M2, M3 = 0, 0, 0, 0, 0, 0 # stream velocity in fin frame - stream_velocity_f = self._body_to_fin_aero @ stream_velocity + stream_velocity_f = self._rotation_body_to_fin @ stream_velocity attack_angle = np.arctan2(stream_velocity_f[0], stream_velocity_f[2]) # Force in the X direction of the fin @@ -328,9 +354,11 @@ def compute_forces_and_moments( * self.cl.get_value_opt(attack_angle, stream_mach) ) # Force in body frame - R1, R2, R3 = self._fin_aero_to_body @ Vector([X, 0, 0]) + R1, R2, R3 = self._rotation_fin_to_body @ Vector([X, 0, 0]) # Moments M1, M2, M3 = cp ^ Vector([R1, R2, R3]) + # Apply roll interference factor, disregarding lift interference factor + M3 *= self.roll_forcing_interference_factor / self.lift_interference_factor # Roll damping _, cld_omega, _ = self.roll_parameters @@ -345,92 +373,19 @@ def compute_forces_and_moments( M3 += M3_damping return R1, R2, R3, M1, M2, M3 - def compute_forces_and_moments2( - self, - stream_velocity, - stream_speed, - stream_mach, - rho, - cp, - omega, - *args, - ): # pylint: disable=arguments-differ - """Computes the forces and moments acting on the aerodynamic surface. - - Parameters - ---------- - stream_velocity : tuple of float - The velocity of the airflow relative to the surface. - stream_speed : float - The magnitude of the airflow speed. - stream_mach : float - The Mach number of the airflow. - rho : float - Air density. - cp : Vector - Center of pressure coordinates in the body frame. - omega: tuple[float, float, float] - Tuple containing angular velocities around the x, y, z axes. - - Returns - ------- - tuple of float - The aerodynamic forces (lift, side_force, drag) and moments - (pitch, yaw, roll) in the body frame. - """ - R1, R2, R3, M1, M2, M3 = 0, 0, 0, 0, 0, 0 - - # stream velocity in fin frame - stream_velocity_f = self._body_to_fin_aero @ stream_velocity - - attack_angle = np.arctan2(stream_velocity_f[0], stream_velocity_f[2]) - # Force in the X direction of the fin - X = ( - 0.5 - * rho - * stream_speed**2 - * self.reference_area - * self.cl.get_value_opt(attack_angle, stream_mach) # TODO getvalueopt - ) - # Force in body frame - R1, R2, R3 = self._fin_aero_to_body @ Vector([X, 0, 0]) - - # Moments - M1, M2, M3 = cp ^ Vector([R1, R2, R3]) - - # Exclude M3 for - M3 = 0 - - # Roll - clf_delta, cld_omega, cant_angle_rad = self.roll_parameters - cant_angle_rad = -cant_angle_rad - M3_forcing = ( - (1 / 2 * rho * stream_speed**2) - * self.reference_area - * self.reference_length - * clf_delta.get_value_opt(stream_mach) - * cant_angle_rad - ) - M3_damping = ( - (1 / 2 * rho * stream_speed) - * self.reference_area - * (self.reference_length) ** 2 - * cld_omega.get_value_opt(stream_mach) - * omega[2] # omega3 - / 2 - ) - M3 = M3_forcing + M3_damping - return R1, R2, R3, M1, M2, M3 - def to_dict(self): pass # TODO - def draw(self): + def draw(self, *, filename=None): """Draw the fin shape along with some important information, including the center line, the quarter line and the center of pressure position. - Returns - ------- - None + Parameters + ---------- + filename : str | None, optional + The path the plot should be saved to. By default None, in which case + the plot will be shown instead of saved. Supported file endings are: + eps, jpg, jpeg, pdf, pgf, png, ps, raw, rgba, svg, svgz, tif, tiff + and webp (these are the formats supported by matplotlib). """ - self.plots.draw() + self.plots.draw(filename=filename) diff --git a/rocketpy/rocket/aero_surface/fins/fins.py b/rocketpy/rocket/aero_surface/fins/fins.py index e463ad1a2..0f1c0fd6d 100644 --- a/rocketpy/rocket/aero_surface/fins/fins.py +++ b/rocketpy/rocket/aero_surface/fins/fins.py @@ -304,8 +304,6 @@ def compute_forces_and_moments( * omega[2] / 2 ) - self.M3dh.append(M3_damping) - self.cldwh.append(clf_delta.get_value_opt(stream_mach)) M3 = M3_forcing + M3_damping return R1, R2, R3, M1, M2, M3 diff --git a/rocketpy/rocket/aero_surface/fins/trapezoidal_fin.py b/rocketpy/rocket/aero_surface/fins/trapezoidal_fin.py index 64a176d92..ea77d4244 100644 --- a/rocketpy/rocket/aero_surface/fins/trapezoidal_fin.py +++ b/rocketpy/rocket/aero_surface/fins/trapezoidal_fin.py @@ -7,7 +7,6 @@ from rocketpy.rocket.aero_surface.fins._trapezoidal_mixin import _TrapezoidalMixin from .fin import Fin -from .geometry_utils import compute_sweep_length class TrapezoidalFin(_TrapezoidalMixin, Fin): diff --git a/rocketpy/rocket/aero_surface/fins/trapezoidal_fins.py b/rocketpy/rocket/aero_surface/fins/trapezoidal_fins.py index efafe9c87..efd082a30 100644 --- a/rocketpy/rocket/aero_surface/fins/trapezoidal_fins.py +++ b/rocketpy/rocket/aero_surface/fins/trapezoidal_fins.py @@ -5,7 +5,6 @@ from rocketpy.rocket.aero_surface.fins._trapezoidal_mixin import _TrapezoidalMixin from .fins import Fins -from .geometry_utils import compute_sweep_length class TrapezoidalFins(_TrapezoidalMixin, Fins): diff --git a/rocketpy/rocket/rocket.py b/rocketpy/rocket/rocket.py index fa8a124ea..6712cd81d 100644 --- a/rocketpy/rocket/rocket.py +++ b/rocketpy/rocket/rocket.py @@ -19,9 +19,8 @@ TrapezoidalFins, ) from rocketpy.rocket.aero_surface.fins.elliptical_fin import EllipticalFin -from rocketpy.rocket.aero_surface.fins.fin import Fin -from rocketpy.rocket.aero_surface.fins.trapezoidal_fin import TrapezoidalFin from rocketpy.rocket.aero_surface.fins.free_form_fins import FreeFormFins +from rocketpy.rocket.aero_surface.fins.trapezoidal_fin import TrapezoidalFin from rocketpy.rocket.aero_surface.generic_surface import GenericSurface from rocketpy.rocket.components import Components from rocketpy.rocket.parachute import Parachute From 6bce627a9ae253560312f3d6a072d98393daf88e Mon Sep 17 00:00:00 2001 From: MateusStano Date: Sat, 19 Apr 2025 22:18:23 +0200 Subject: [PATCH 13/32] ENH: move evaluate cp out of mixin and include to/from_dict --- .../aero_surface/fins/_trapezoidal_mixin.py | 62 ++++++++++++------- .../aero_surface/fins/trapezoidal_fin.py | 24 ++++++- .../aero_surface/fins/trapezoidal_fins.py | 56 +++++++---------- 3 files changed, 82 insertions(+), 60 deletions(-) diff --git a/rocketpy/rocket/aero_surface/fins/_trapezoidal_mixin.py b/rocketpy/rocket/aero_surface/fins/_trapezoidal_mixin.py index 9cca4186e..3bc2d243d 100644 --- a/rocketpy/rocket/aero_surface/fins/_trapezoidal_mixin.py +++ b/rocketpy/rocket/aero_surface/fins/_trapezoidal_mixin.py @@ -3,7 +3,7 @@ class _TrapezoidalMixin: """Mixin class for trapezoidal fins. - This class contains methods and properties specific to trapezoidal fin shapes. + This class holds methods and properties specific to trapezoidal fin shapes. It is designed to be used in conjunction with other classes that define the overall behavior of the fins. """ @@ -45,7 +45,7 @@ def sweep_length(self, value): self.evaluate_lift_coefficient() self.evaluate_roll_parameters() - def initialize(self, sweep_length, sweep_angle, root_chord, tip_chord, span): + def _initialize(self, sweep_length, sweep_angle, root_chord, tip_chord, span): # Check if sweep angle or sweep length is given if sweep_length is not None and sweep_angle is not None: raise ValueError("Cannot use sweep_length and sweep_angle together") @@ -65,28 +65,6 @@ def initialize(self, sweep_length, sweep_angle, root_chord, tip_chord, span): self.evaluate_lift_coefficient() self.evaluate_roll_parameters() - def evaluate_center_of_pressure(self): - """Calculates and returns the center of pressure of the fin set in local - coordinates. The center of pressure position is saved and stored as a - tuple. - - Returns - ------- - None - """ - # Center of pressure position in local coordinates - cpz = (self.sweep_length / 3) * ( - (self.root_chord + 2 * self.tip_chord) / (self.root_chord + self.tip_chord) - ) + (1 / 6) * ( - self.root_chord - + self.tip_chord - - self.root_chord * self.tip_chord / (self.root_chord + self.tip_chord) - ) - self.cpx = 0 - self.cpy = 0 - self.cpz = cpz - self.cp = (self.cpx, self.cpy, self.cpz) - def evaluate_geometrical_parameters(self): """Calculates and saves fin set's geometrical parameters such as the fins' area, aspect ratio and parameters for roll movement. @@ -183,3 +161,39 @@ def info(self): def all_info(self): self.prints.all() self.plots.all() + + def to_dict(self, include_outputs=False): + data = super().to_dict(include_outputs) + data["tip_chord"] = self.tip_chord + + if include_outputs: + data.update( + { + "sweep_length": self.sweep_length, + "sweep_angle": self.sweep_angle, + "shape_vec": self.shape_vec, + "Af": self.Af, + "AR": self.AR, + "gamma_c": self.gamma_c, + "Yma": self.Yma, + "roll_geometrical_constant": self.roll_geometrical_constant, + "tau": self.tau, + "lift_interference_factor": self.lift_interference_factor, + "roll_damping_interference_factor": self.roll_damping_interference_factor, + "roll_forcing_interference_factor": self.roll_forcing_interference_factor, + } + ) + return data + + @classmethod + def from_dict(cls, data): + return cls( + n=data["n"], + root_chord=data["root_chord"], + tip_chord=data["tip_chord"], + span=data["span"], + rocket_radius=data["rocket_radius"], + cant_angle=data["cant_angle"], + airfoil=data["airfoil"], + name=data["name"], + ) diff --git a/rocketpy/rocket/aero_surface/fins/trapezoidal_fin.py b/rocketpy/rocket/aero_surface/fins/trapezoidal_fin.py index ea77d4244..4140b3933 100644 --- a/rocketpy/rocket/aero_surface/fins/trapezoidal_fin.py +++ b/rocketpy/rocket/aero_surface/fins/trapezoidal_fin.py @@ -112,8 +112,30 @@ def __init__( name, ) - self.initialize(sweep_length, sweep_angle, root_chord, tip_chord, span) + self._initialize(sweep_length, sweep_angle, root_chord, tip_chord, span) self.evaluate_rotation_matrix() self.prints = _TrapezoidalFinPrints(self) self.plots = _TrapezoidalFinPlots(self) + + def evaluate_center_of_pressure(self): + """Calculates and returns the center of pressure of the fin set in local + coordinates. The center of pressure position is saved and stored as a + tuple. + + Returns + ------- + None + """ + # Center of pressure position in local coordinates + cpz = (self.sweep_length / 3) * ( + (self.root_chord + 2 * self.tip_chord) / (self.root_chord + self.tip_chord) + ) + (1 / 6) * ( + self.root_chord + + self.tip_chord + - self.root_chord * self.tip_chord / (self.root_chord + self.tip_chord) + ) + self.cpx = 0 + self.cpy = self.Yma + self.cpz = cpz + self.cp = (self.cpx, self.cpy, self.cpz) diff --git a/rocketpy/rocket/aero_surface/fins/trapezoidal_fins.py b/rocketpy/rocket/aero_surface/fins/trapezoidal_fins.py index efd082a30..7e12eea10 100644 --- a/rocketpy/rocket/aero_surface/fins/trapezoidal_fins.py +++ b/rocketpy/rocket/aero_surface/fins/trapezoidal_fins.py @@ -170,43 +170,29 @@ def __init__( name, ) - self.initialize(sweep_length, sweep_angle, root_chord, tip_chord, span) + self._initialize(sweep_length, sweep_angle, root_chord, tip_chord, span) self.prints = _TrapezoidalFinsPrints(self) self.plots = _TrapezoidalFinsPlots(self) - def to_dict(self, include_outputs=False): - data = super().to_dict(include_outputs) - data["tip_chord"] = self.tip_chord - - if include_outputs: - data.update( - { - "sweep_length": self.sweep_length, - "sweep_angle": self.sweep_angle, - "shape_vec": self.shape_vec, - "Af": self.Af, - "AR": self.AR, - "gamma_c": self.gamma_c, - "Yma": self.Yma, - "roll_geometrical_constant": self.roll_geometrical_constant, - "tau": self.tau, - "lift_interference_factor": self.lift_interference_factor, - "roll_damping_interference_factor": self.roll_damping_interference_factor, - "roll_forcing_interference_factor": self.roll_forcing_interference_factor, - } - ) - return data - - @classmethod - def from_dict(cls, data): - return cls( - n=data["n"], - root_chord=data["root_chord"], - tip_chord=data["tip_chord"], - span=data["span"], - rocket_radius=data["rocket_radius"], - cant_angle=data["cant_angle"], - airfoil=data["airfoil"], - name=data["name"], + def evaluate_center_of_pressure(self): + """Calculates and returns the center of pressure of the fin set in local + coordinates. The center of pressure position is saved and stored as a + tuple. + + Returns + ------- + None + """ + # Center of pressure position in local coordinates + cpz = (self.sweep_length / 3) * ( + (self.root_chord + 2 * self.tip_chord) / (self.root_chord + self.tip_chord) + ) + (1 / 6) * ( + self.root_chord + + self.tip_chord + - self.root_chord * self.tip_chord / (self.root_chord + self.tip_chord) ) + self.cpx = 0 + self.cpy = 0 + self.cpz = cpz + self.cp = (self.cpx, self.cpy, self.cpz) From 46853189c3596c8dd9abc5ebf35f0004a1406242 Mon Sep 17 00:00:00 2001 From: MateusStano Date: Sat, 19 Apr 2025 22:18:42 +0200 Subject: [PATCH 14/32] ENH: free form mixin --- .../aero_surface/fins/_free_form_mixin.py | 247 ++++++++++++++++++ .../rocket/aero_surface/fins/free_form_fin.py | 173 ++++++++++++ .../aero_surface/fins/free_form_fins.py | 234 +---------------- 3 files changed, 423 insertions(+), 231 deletions(-) create mode 100644 rocketpy/rocket/aero_surface/fins/_free_form_mixin.py create mode 100644 rocketpy/rocket/aero_surface/fins/free_form_fin.py diff --git a/rocketpy/rocket/aero_surface/fins/_free_form_mixin.py b/rocketpy/rocket/aero_surface/fins/_free_form_mixin.py new file mode 100644 index 000000000..0282aca1f --- /dev/null +++ b/rocketpy/rocket/aero_surface/fins/_free_form_mixin.py @@ -0,0 +1,247 @@ +import warnings + +import numpy as np + + +class _FreeFormMixin: + """Mixin class for free form fins. + This class holds methods and properties specific to free form fin shapes. + It is designed to be used in conjunction with other classes that define the + overall behavior of the fins. + """ + + def _initialize(self, shape_points): + self.shape_points = shape_points + + down = False + for i in range(1, len(shape_points)): + if shape_points[i][1] > shape_points[i - 1][1] and down: + warnings.warn( + "Jagged fin shape detected. This may cause small inaccuracies " + "center of pressure and pitch moment calculations." + ) + break + if shape_points[i][1] < shape_points[i - 1][1]: + down = True + i += 1 + + root_chord = abs(shape_points[0][0] - shape_points[-1][0]) + ys = [point[1] for point in shape_points] + span = max(ys) - min(ys) + return ( + root_chord, + span, + ) + + def evaluate_geometrical_parameters(self): # pylint: disable=too-many-statements + """ + Calculates and saves the fin set's geometrical parameters such as the + fin area, aspect ratio, and parameters related to roll movement. This + method uses the same calculations to those in OpenRocket for free-form + fin shapes. + + Returns + ------- + None + """ + # pylint: disable=invalid-name + # pylint: disable=too-many-locals + # Calculate the fin area (Af) using the Shoelace theorem (polygon area formula) + Af = 0 + for i in range(len(self.shape_points) - 1): + x1, y1 = self.shape_points[i] + x2, y2 = self.shape_points[i + 1] + Af += (y1 + y2) * (x1 - x2) + Af = abs(Af) / 2 + if Af < 1e-6: + raise ValueError("Fin area is too small. Check the shape_points.") + + # Calculate aspect ratio (AR) and lift interference factors + AR = 2 * self.span**2 / Af # Aspect ratio + tau = (self.span + self.rocket_radius) / self.rocket_radius + lift_interference_factor = 1 + 1 / tau + + # Calculate roll forcing interference factor using OpenRocket's approach + roll_forcing_interference_factor = (1 / np.pi**2) * ( + (np.pi**2 / 4) * ((tau + 1) ** 2 / tau**2) + + ((np.pi * (tau**2 + 1) ** 2) / (tau**2 * (tau - 1) ** 2)) + * np.arcsin((tau**2 - 1) / (tau**2 + 1)) + - (2 * np.pi * (tau + 1)) / (tau * (tau - 1)) + + ((tau**2 + 1) ** 2 / (tau**2 * (tau - 1) ** 2)) + * (np.arcsin((tau**2 - 1) / (tau**2 + 1))) ** 2 + - (4 * (tau + 1)) + / (tau * (tau - 1)) + * np.arcsin((tau**2 - 1) / (tau**2 + 1)) + + (8 / (tau - 1) ** 2) * np.log((tau**2 + 1) / (2 * tau)) + ) + + # Define number of interpolation points along the span of the fin + points_per_line = 40 # Same as OpenRocket + + # Initialize arrays for leading/trailing edge and chord lengths + chord_lead = np.ones(points_per_line) * np.inf # Leading edge x coordinates + chord_trail = np.ones(points_per_line) * -np.inf # Trailing edge x coordinates + chord_length = np.zeros( + points_per_line + ) # Chord length for each spanwise section + + # Discretize fin shape and calculate chord length, leading, and trailing edges + for p in range(1, len(self.shape_points)): + x1, y1 = self.shape_points[p - 1] + x2, y2 = self.shape_points[p] + + # Compute corresponding points along the fin span (clamp to valid range) + prev_idx = int(y1 / self.span * (points_per_line - 1)) + curr_idx = int(y2 / self.span * (points_per_line - 1)) + prev_idx = np.clip(prev_idx, 0, points_per_line - 1) + curr_idx = np.clip(curr_idx, 0, points_per_line - 1) + + if prev_idx > curr_idx: + prev_idx, curr_idx = curr_idx, prev_idx + + # Compute intersection of fin edge with each spanwise section + for i in range(prev_idx, curr_idx + 1): + y = i * self.span / (points_per_line - 1) + if y1 != y2: + x = np.clip( + (y - y2) / (y1 - y2) * x1 + (y1 - y) / (y1 - y2) * x2, + min(x1, x2), + max(x1, x2), + ) + else: + x = x1 # Handle horizontal segments + + # Update leading and trailing edge positions + chord_lead[i] = min(chord_lead[i], x) + chord_trail[i] = max(chord_trail[i], x) + + # Update chord length + if y1 < y2: + chord_length[i] -= x + else: + chord_length[i] += x + + # Replace infinities and handle invalid values in chord_lead and chord_trail + for i in range(points_per_line): + if ( + np.isinf(chord_lead[i]) + or np.isinf(chord_trail[i]) + or np.isnan(chord_lead[i]) + or np.isnan(chord_trail[i]) + ): + chord_lead[i] = 0 + chord_trail[i] = 0 + if chord_length[i] < 0 or np.isnan(chord_length[i]): + chord_length[i] = 0 + if chord_length[i] > chord_trail[i] - chord_lead[i]: + chord_length[i] = chord_trail[i] - chord_lead[i] + + # Initialize integration variables for various aerodynamic and roll properties + radius = self.rocket_radius + total_area = 0 + mac_length = 0 # Mean aerodynamic chord length + mac_lead = 0 # Mean aerodynamic chord leading edge + mac_span = 0 # Mean aerodynamic chord spanwise position (Yma) + cos_gamma_sum = 0 # Sum of cosine of the sweep angle + roll_geometrical_constant = 0 + roll_damping_numerator = 0 + roll_damping_denominator = 0 + + # Perform integration over spanwise sections + dy = self.span / (points_per_line - 1) + for i in range(points_per_line): + chord = chord_trail[i] - chord_lead[i] + y = i * dy + + # Update integration variables + mac_length += chord * chord + mac_span += y * chord + mac_lead += chord_lead[i] * chord + total_area += chord + roll_geometrical_constant += chord_length[i] * (radius + y) ** 2 + roll_damping_numerator += radius**3 * chord / (radius + y) ** 2 + roll_damping_denominator += (radius + y) * chord + + # Update cosine of sweep angle (cos_gamma) + if i > 0: + dx = (chord_trail[i] + chord_lead[i]) / 2 - ( + chord_trail[i - 1] + chord_lead[i - 1] + ) / 2 + cos_gamma_sum += dy / np.hypot(dx, dy) + + # Finalize mean aerodynamic chord properties + mac_length *= dy + mac_span *= dy + mac_lead *= dy + total_area *= dy + roll_geometrical_constant *= dy + roll_damping_numerator *= dy + roll_damping_denominator *= dy + + mac_length /= total_area + mac_span /= total_area + mac_lead /= total_area + cos_gamma = cos_gamma_sum / (points_per_line - 1) + + # Store computed values + self.Af = Af # Fin area + self.AR = AR # Aspect ratio + self.gamma_c = np.arccos(cos_gamma) # Sweep angle + self.Yma = mac_span # Mean aerodynamic chord spanwise position + self.mac_length = mac_length + self.mac_lead = mac_lead + self.tau = tau + self.roll_geometrical_constant = roll_geometrical_constant + self.lift_interference_factor = lift_interference_factor + self.roll_forcing_interference_factor = roll_forcing_interference_factor + self.roll_damping_interference_factor = 1 + ( + roll_damping_numerator / roll_damping_denominator + ) + + # Evaluate the shape and finalize geometry + self.evaluate_shape() + + def evaluate_shape(self): + x_array, y_array = zip(*self.shape_points) + self.shape_vec = [np.array(x_array), np.array(y_array)] + + def to_dict(self, include_outputs=False): + data = super().to_dict(include_outputs) + data["shape_points"] = self.shape_points + + if include_outputs: + data.update( + { + "Af": self.Af, + "AR": self.AR, + "gamma_c": self.gamma_c, + "Yma": self.Yma, + "mac_length": self.mac_length, + "mac_lead": self.mac_lead, + "roll_geometrical_constant": self.roll_geometrical_constant, + "tau": self.tau, + "lift_interference_factor": self.lift_interference_factor, + "roll_forcing_interference_factor": self.roll_forcing_interference_factor, + "roll_damping_interference_factor": self.roll_damping_interference_factor, + } + ) + return data + + @classmethod + def from_dict(cls, data): + return cls( + data["n"], + data["shape_points"], + data["rocket_radius"], + data["cant_angle"], + data["airfoil"], + data["name"], + ) + + def info(self): + self.prints.geometry() + self.prints.lift() + + def all_info(self): + self.prints.all() + self.plots.all() diff --git a/rocketpy/rocket/aero_surface/fins/free_form_fin.py b/rocketpy/rocket/aero_surface/fins/free_form_fin.py new file mode 100644 index 000000000..5df5d306e --- /dev/null +++ b/rocketpy/rocket/aero_surface/fins/free_form_fin.py @@ -0,0 +1,173 @@ +import warnings + +import numpy as np + +from rocketpy.plots.aero_surface_plots import _FreeFormFinsPlots +from rocketpy.prints.aero_surface_prints import _FreeFormFinsPrints +from rocketpy.rocket.aero_surface.fins._free_form_mixin import _FreeFormMixin + +from .fins import Fins + + +class FreeFormFins(_FreeFormMixin, Fins): + """Class that defines and holds information for a free form fin set. + + This class inherits from the Fins class. + + Note + ---- + Local coordinate system: + - Origin located at the top of the root chord. + - Z axis along the longitudinal axis of symmetry, positive downwards (top -> bottom). + - Y axis perpendicular to the Z axis, in the span direction, positive upwards. + - X axis completes the right-handed coordinate system. + + See Also + -------- + Fins + + Attributes + ---------- + FreeFormFins.n : int + Number of fins in fin set. + FreeFormFins.rocket_radius : float + The reference rocket radius used for lift coefficient normalization, in + meters. + FreeFormFins.airfoil : tuple + Tuple of two items. First is the airfoil lift curve. + Second is the unit of the curve (radians or degrees). + FreeFormFins.cant_angle : float + Fins cant angle with respect to the rocket centerline, in degrees. + FreeFormFins.cant_angle_rad : float + Fins cant angle with respect to the rocket centerline, in radians. + FreeFormFins.root_chord : float + Fin root chord in meters. + FreeFormFins.span : float + Fin span in meters. + FreeFormFins.name : string + Name of fin set. + FreeFormFins.d : float + Reference diameter of the rocket, in meters. + FreeFormFins.ref_area : float + Reference area of the rocket, in m². + FreeFormFins.Af : float + Area of the longitudinal section of each fin in the set. + FreeFormFins.AR : float + Aspect ratio of each fin in the set + FreeFormFins.gamma_c : float + Fin mid-chord sweep angle. + FreeFormFins.Yma : float + Span wise position of the mean aerodynamic chord. + FreeFormFins.roll_geometrical_constant : float + Geometrical constant used in roll calculations. + FreeFormFins.tau : float + Geometrical relation used to simplify lift and roll calculations. + FreeFormFins.lift_interference_factor : float + Factor of Fin-Body interference in the lift coefficient. + FreeFormFins.cp : tuple + Tuple with the x, y and z local coordinates of the fin set center of + pressure. Has units of length and is given in meters. + FreeFormFins.cpx : float + Fin set local center of pressure x coordinate. Has units of length and + is given in meters. + FreeFormFins.cpy : float + Fin set local center of pressure y coordinate. Has units of length and + is given in meters. + FreeFormFins.cpz : float + Fin set local center of pressure z coordinate. Has units of length and + is given in meters. + FreeFormFins.cl : Function + Function which defines the lift coefficient as a function of the angle + of attack and the Mach number. Takes as input the angle of attack in + radians and the Mach number. Returns the lift coefficient. + FreeFormFins.clalpha : float + Lift coefficient slope. Has units of 1/rad. + FreeFormFins.mac_length : float + Mean aerodynamic chord length of the fin set. + FreeFormFins.mac_lead : float + Mean aerodynamic chord leading edge x coordinate. + """ + + def __init__( + self, + n, + shape_points, + rocket_radius, + cant_angle=0, + airfoil=None, + name="Fins", + ): + """Initialize FreeFormFins class. + + Parameters + ---------- + n : int + Number of fins, must be larger than 2. + shape_points : list + List of tuples (x, y) containing the coordinates of the fin's + geometry defining points. The point (0, 0) is the root leading edge. + Positive x is rearwards, positive y is upwards (span direction). + The shape will be interpolated between the points, in the order + they are given. The last point connects to the first point, and + represents the trailing edge. + rocket_radius : int, float + Reference radius to calculate lift coefficient, in meters. + cant_angle : int, float, optional + Fins cant angle with respect to the rocket centerline. Must + be given in degrees. + airfoil : tuple, optional + Default is null, in which case fins will be treated as flat plates. + Otherwise, if tuple, fins will be considered as airfoils. The + tuple's first item specifies the airfoil's lift coefficient + by angle of attack and must be either a .csv, .txt, ndarray + or callable. The .csv and .txt files can contain a single line + header and the first column must specify the angle of attack, while + the second column must specify the lift coefficient. The + ndarray should be as [(x0, y0), (x1, y1), (x2, y2), ...] + where x0 is the angle of attack and y0 is the lift coefficient. + If callable, it should take an angle of attack as input and + return the lift coefficient at that angle of attack. + The tuple's second item is the unit of the angle of attack, + accepting either "radians" or "degrees". + name : str + Name of fin set. + + Returns + ------- + None + """ + root_chord, span = self._initialize(shape_points) + + super().__init__( + n, + root_chord, + span, + rocket_radius, + cant_angle, + airfoil, + name, + ) + + self.evaluate_geometrical_parameters() + self.evaluate_center_of_pressure() + self.evaluate_lift_coefficient() + self.evaluate_roll_parameters() + + self.prints = _FreeFormFinsPrints(self) + self.plots = _FreeFormFinsPlots(self) + + def evaluate_center_of_pressure(self): + """Calculates and returns the center of pressure of the fin set in local + coordinates. The center of pressure position is saved and stored as a + tuple. + + Returns + ------- + None + """ + # Center of pressure position in local coordinates + cpz = self.mac_lead + 0.25 * self.mac_length + self.cpx = 0 + self.cpy = self.Yma + self.cpz = cpz + self.cp = (self.cpx, self.cpy, self.cpz) diff --git a/rocketpy/rocket/aero_surface/fins/free_form_fins.py b/rocketpy/rocket/aero_surface/fins/free_form_fins.py index 7cae4e556..2974d058d 100644 --- a/rocketpy/rocket/aero_surface/fins/free_form_fins.py +++ b/rocketpy/rocket/aero_surface/fins/free_form_fins.py @@ -4,11 +4,12 @@ from rocketpy.plots.aero_surface_plots import _FreeFormFinsPlots from rocketpy.prints.aero_surface_prints import _FreeFormFinsPrints +from rocketpy.rocket.aero_surface.fins._free_form_mixin import _FreeFormMixin from .fins import Fins -class FreeFormFins(Fins): +class FreeFormFins(_FreeFormMixin, Fins): """Class that defines and holds information for a free form fin set. This class inherits from the Fins class. @@ -135,23 +136,7 @@ def __init__( ------- None """ - self.shape_points = shape_points - - down = False - for i in range(1, len(shape_points)): - if shape_points[i][1] > shape_points[i - 1][1] and down: - warnings.warn( - "Jagged fin shape detected. This may cause small inaccuracies " - "center of pressure and pitch moment calculations." - ) - break - if shape_points[i][1] < shape_points[i - 1][1]: - down = True - i += 1 - - root_chord = abs(shape_points[0][0] - shape_points[-1][0]) - ys = [point[1] for point in shape_points] - span = max(ys) - min(ys) + root_chord, span = self._initialize(shape_points) super().__init__( n, @@ -186,216 +171,3 @@ def evaluate_center_of_pressure(self): self.cpy = 0 self.cpz = cpz self.cp = (self.cpx, self.cpy, self.cpz) - - def evaluate_geometrical_parameters(self): # pylint: disable=too-many-statements - """ - Calculates and saves the fin set's geometrical parameters such as the - fin area, aspect ratio, and parameters related to roll movement. This - method uses the same calculations to those in OpenRocket for free-form - fin shapes. - - Returns - ------- - None - """ - # pylint: disable=invalid-name - # pylint: disable=too-many-locals - # Calculate the fin area (Af) using the Shoelace theorem (polygon area formula) - Af = 0 - for i in range(len(self.shape_points) - 1): - x1, y1 = self.shape_points[i] - x2, y2 = self.shape_points[i + 1] - Af += (y1 + y2) * (x1 - x2) - Af = abs(Af) / 2 - if Af < 1e-6: - raise ValueError("Fin area is too small. Check the shape_points.") - - # Calculate aspect ratio (AR) and lift interference factors - AR = 2 * self.span**2 / Af # Aspect ratio - tau = (self.span + self.rocket_radius) / self.rocket_radius - lift_interference_factor = 1 + 1 / tau - - # Calculate roll forcing interference factor using OpenRocket's approach - roll_forcing_interference_factor = (1 / np.pi**2) * ( - (np.pi**2 / 4) * ((tau + 1) ** 2 / tau**2) - + ((np.pi * (tau**2 + 1) ** 2) / (tau**2 * (tau - 1) ** 2)) - * np.arcsin((tau**2 - 1) / (tau**2 + 1)) - - (2 * np.pi * (tau + 1)) / (tau * (tau - 1)) - + ((tau**2 + 1) ** 2 / (tau**2 * (tau - 1) ** 2)) - * (np.arcsin((tau**2 - 1) / (tau**2 + 1))) ** 2 - - (4 * (tau + 1)) - / (tau * (tau - 1)) - * np.arcsin((tau**2 - 1) / (tau**2 + 1)) - + (8 / (tau - 1) ** 2) * np.log((tau**2 + 1) / (2 * tau)) - ) - - # Define number of interpolation points along the span of the fin - points_per_line = 40 # Same as OpenRocket - - # Initialize arrays for leading/trailing edge and chord lengths - chord_lead = np.ones(points_per_line) * np.inf # Leading edge x coordinates - chord_trail = np.ones(points_per_line) * -np.inf # Trailing edge x coordinates - chord_length = np.zeros( - points_per_line - ) # Chord length for each spanwise section - - # Discretize fin shape and calculate chord length, leading, and trailing edges - for p in range(1, len(self.shape_points)): - x1, y1 = self.shape_points[p - 1] - x2, y2 = self.shape_points[p] - - # Compute corresponding points along the fin span (clamp to valid range) - prev_idx = int(y1 / self.span * (points_per_line - 1)) - curr_idx = int(y2 / self.span * (points_per_line - 1)) - prev_idx = np.clip(prev_idx, 0, points_per_line - 1) - curr_idx = np.clip(curr_idx, 0, points_per_line - 1) - - if prev_idx > curr_idx: - prev_idx, curr_idx = curr_idx, prev_idx - - # Compute intersection of fin edge with each spanwise section - for i in range(prev_idx, curr_idx + 1): - y = i * self.span / (points_per_line - 1) - if y1 != y2: - x = np.clip( - (y - y2) / (y1 - y2) * x1 + (y1 - y) / (y1 - y2) * x2, - min(x1, x2), - max(x1, x2), - ) - else: - x = x1 # Handle horizontal segments - - # Update leading and trailing edge positions - chord_lead[i] = min(chord_lead[i], x) - chord_trail[i] = max(chord_trail[i], x) - - # Update chord length - if y1 < y2: - chord_length[i] -= x - else: - chord_length[i] += x - - # Replace infinities and handle invalid values in chord_lead and chord_trail - for i in range(points_per_line): - if ( - np.isinf(chord_lead[i]) - or np.isinf(chord_trail[i]) - or np.isnan(chord_lead[i]) - or np.isnan(chord_trail[i]) - ): - chord_lead[i] = 0 - chord_trail[i] = 0 - if chord_length[i] < 0 or np.isnan(chord_length[i]): - chord_length[i] = 0 - if chord_length[i] > chord_trail[i] - chord_lead[i]: - chord_length[i] = chord_trail[i] - chord_lead[i] - - # Initialize integration variables for various aerodynamic and roll properties - radius = self.rocket_radius - total_area = 0 - mac_length = 0 # Mean aerodynamic chord length - mac_lead = 0 # Mean aerodynamic chord leading edge - mac_span = 0 # Mean aerodynamic chord spanwise position (Yma) - cos_gamma_sum = 0 # Sum of cosine of the sweep angle - roll_geometrical_constant = 0 - roll_damping_numerator = 0 - roll_damping_denominator = 0 - - # Perform integration over spanwise sections - dy = self.span / (points_per_line - 1) - for i in range(points_per_line): - chord = chord_trail[i] - chord_lead[i] - y = i * dy - - # Update integration variables - mac_length += chord * chord - mac_span += y * chord - mac_lead += chord_lead[i] * chord - total_area += chord - roll_geometrical_constant += chord_length[i] * (radius + y) ** 2 - roll_damping_numerator += radius**3 * chord / (radius + y) ** 2 - roll_damping_denominator += (radius + y) * chord - - # Update cosine of sweep angle (cos_gamma) - if i > 0: - dx = (chord_trail[i] + chord_lead[i]) / 2 - ( - chord_trail[i - 1] + chord_lead[i - 1] - ) / 2 - cos_gamma_sum += dy / np.hypot(dx, dy) - - # Finalize mean aerodynamic chord properties - mac_length *= dy - mac_span *= dy - mac_lead *= dy - total_area *= dy - roll_geometrical_constant *= dy - roll_damping_numerator *= dy - roll_damping_denominator *= dy - - mac_length /= total_area - mac_span /= total_area - mac_lead /= total_area - cos_gamma = cos_gamma_sum / (points_per_line - 1) - - # Store computed values - self.Af = Af # Fin area - self.AR = AR # Aspect ratio - self.gamma_c = np.arccos(cos_gamma) # Sweep angle - self.Yma = mac_span # Mean aerodynamic chord spanwise position - self.mac_length = mac_length - self.mac_lead = mac_lead - self.tau = tau - self.roll_geometrical_constant = roll_geometrical_constant - self.lift_interference_factor = lift_interference_factor - self.roll_forcing_interference_factor = roll_forcing_interference_factor - self.roll_damping_interference_factor = 1 + ( - roll_damping_numerator / roll_damping_denominator - ) - - # Evaluate the shape and finalize geometry - self.evaluate_shape() - - def evaluate_shape(self): - x_array, y_array = zip(*self.shape_points) - self.shape_vec = [np.array(x_array), np.array(y_array)] - - def to_dict(self, include_outputs=False): - data = super().to_dict(include_outputs) - data["shape_points"] = self.shape_points - - if include_outputs: - data.update( - { - "Af": self.Af, - "AR": self.AR, - "gamma_c": self.gamma_c, - "Yma": self.Yma, - "mac_length": self.mac_length, - "mac_lead": self.mac_lead, - "roll_geometrical_constant": self.roll_geometrical_constant, - "tau": self.tau, - "lift_interference_factor": self.lift_interference_factor, - "roll_forcing_interference_factor": self.roll_forcing_interference_factor, - "roll_damping_interference_factor": self.roll_damping_interference_factor, - } - ) - return data - - @classmethod - def from_dict(cls, data): - return cls( - data["n"], - data["shape_points"], - data["rocket_radius"], - data["cant_angle"], - data["airfoil"], - data["name"], - ) - - def info(self): - self.prints.geometry() - self.prints.lift() - - def all_info(self): - self.prints.all() - self.plots.all() From d1236bbcdbb4bde2a0110a5f06f7c7a4ccf2faf4 Mon Sep 17 00:00:00 2001 From: MateusStano Date: Sat, 19 Apr 2025 22:18:55 +0200 Subject: [PATCH 15/32] ENH: elliptical mixin --- .../aero_surface/fins/_elliptical_mixin.py | 140 +++++++++++++ .../aero_surface/fins/elliptical_fin.py | 196 +++++------------- .../aero_surface/fins/elliptical_fins.py | 134 +----------- 3 files changed, 192 insertions(+), 278 deletions(-) create mode 100644 rocketpy/rocket/aero_surface/fins/_elliptical_mixin.py diff --git a/rocketpy/rocket/aero_surface/fins/_elliptical_mixin.py b/rocketpy/rocket/aero_surface/fins/_elliptical_mixin.py new file mode 100644 index 000000000..b63135bd9 --- /dev/null +++ b/rocketpy/rocket/aero_surface/fins/_elliptical_mixin.py @@ -0,0 +1,140 @@ +import numpy as np + + +class _EllipticalMixin: + """Mixin class for elliptical fins. + This class holds methods and properties specific to elliptical fin shapes. + It is designed to be used in conjunction with other classes that define the + overall behavior of the fins. + """ + + def evaluate_geometrical_parameters(self): # pylint: disable=too-many-statements + """Calculates and saves fin set's geometrical parameters such as the + fins' area, aspect ratio and parameters for roll movement. + + Returns + ------- + None + """ + + # Compute auxiliary geometrical parameters + # pylint: disable=invalid-name + Af = (np.pi * self.root_chord / 2 * self.span) / 2 # Fin area + gamma_c = 0 # Zero for elliptical fins + AR = 2 * self.span**2 / Af # Fin aspect ratio + Yma = ( + self.span / (3 * np.pi) * np.sqrt(9 * np.pi**2 - 64) + ) # Span wise coord of mean aero chord + roll_geometrical_constant = ( + self.root_chord + * self.span + * ( + 3 * np.pi * self.span**2 + + 32 * self.rocket_radius * self.span + + 12 * np.pi * self.rocket_radius**2 + ) + / 48 + ) + + # Fin–body interference correction parameters + tau = (self.span + self.rocket_radius) / self.rocket_radius + lift_interference_factor = 1 + 1 / tau + if self.span > self.rocket_radius: + roll_damping_interference_factor = 1 + ( + (self.rocket_radius**2) + * ( + 2 + * (self.rocket_radius**2) + * np.sqrt(self.span**2 - self.rocket_radius**2) + * np.log( + ( + 2 + * self.span + * np.sqrt(self.span**2 - self.rocket_radius**2) + + 2 * self.span**2 + ) + / self.rocket_radius + ) + - 2 + * (self.rocket_radius**2) + * np.sqrt(self.span**2 - self.rocket_radius**2) + * np.log(2 * self.span) + + 2 * self.span**3 + - np.pi * self.rocket_radius * self.span**2 + - 2 * (self.rocket_radius**2) * self.span + + np.pi * self.rocket_radius**3 + ) + ) / ( + 2 + * (self.span**2) + * (self.span / 3 + np.pi * self.rocket_radius / 4) + * (self.span**2 - self.rocket_radius**2) + ) + elif self.span < self.rocket_radius: + roll_damping_interference_factor = 1 - ( + self.rocket_radius**2 + * ( + 2 * self.span**3 + - np.pi * self.span**2 * self.rocket_radius + - 2 * self.span * self.rocket_radius**2 + + np.pi * self.rocket_radius**3 + + 2 + * self.rocket_radius**2 + * np.sqrt(-(self.span**2) + self.rocket_radius**2) + * np.arctan( + (self.span) / (np.sqrt(-(self.span**2) + self.rocket_radius**2)) + ) + - np.pi + * self.rocket_radius**2 + * np.sqrt(-(self.span**2) + self.rocket_radius**2) + ) + ) / ( + 2 + * self.span + * (-(self.span**2) + self.rocket_radius**2) + * (self.span**2 / 3 + np.pi * self.span * self.rocket_radius / 4) + ) + else: + roll_damping_interference_factor = (28 - 3 * np.pi) / (4 + 3 * np.pi) + + roll_forcing_interference_factor = (1 / np.pi**2) * ( + (np.pi**2 / 4) * ((tau + 1) ** 2 / tau**2) + + ((np.pi * (tau**2 + 1) ** 2) / (tau**2 * (tau - 1) ** 2)) + * np.arcsin((tau**2 - 1) / (tau**2 + 1)) + - (2 * np.pi * (tau + 1)) / (tau * (tau - 1)) + + ((tau**2 + 1) ** 2) + / (tau**2 * (tau - 1) ** 2) + * (np.arcsin((tau**2 - 1) / (tau**2 + 1))) ** 2 + - (4 * (tau + 1)) + / (tau * (tau - 1)) + * np.arcsin((tau**2 - 1) / (tau**2 + 1)) + + (8 / (tau - 1) ** 2) * np.log((tau**2 + 1) / (2 * tau)) + ) + + # Store values + # pylint: disable=invalid-name + self.Af = Af # Fin area + self.AR = AR # Fin aspect ratio + self.gamma_c = gamma_c # Mid chord angle + self.Yma = Yma # Span wise coord of mean aero chord + self.roll_geometrical_constant = roll_geometrical_constant + self.tau = tau + self.lift_interference_factor = lift_interference_factor + self.roll_damping_interference_factor = roll_damping_interference_factor + self.roll_forcing_interference_factor = roll_forcing_interference_factor + + self.evaluate_shape() + + def evaluate_shape(self): + angles = np.arange(0, 180, 5) + x_array = self.root_chord / 2 + self.root_chord / 2 * np.cos(np.radians(angles)) + y_array = self.span * np.sin(np.radians(angles)) + self.shape_vec = [x_array, y_array] + + def info(self): + self.prints.geometry() + self.prints.lift() + + def all_info(self): + self.prints.all() + self.plots.all() diff --git a/rocketpy/rocket/aero_surface/fins/elliptical_fin.py b/rocketpy/rocket/aero_surface/fins/elliptical_fin.py index 6395b60d8..ac52a82ad 100644 --- a/rocketpy/rocket/aero_surface/fins/elliptical_fin.py +++ b/rocketpy/rocket/aero_surface/fins/elliptical_fin.py @@ -2,12 +2,14 @@ from rocketpy.plots.aero_surface_plots import _EllipticalFinPlots from rocketpy.prints.aero_surface_prints import _EllipticalFinPrints +from rocketpy.rocket.aero_surface.fins._elliptical_mixin import _EllipticalMixin +from rocketpy.rocket.aero_surface.fins.fin import Fin -from .fin import Fin +class EllipticalFin(_EllipticalMixin, Fin): + """Class that defines and holds information for an elliptical fin set. -class EllipticalFin(Fin): - """Class that defines and holds information for an elliptical fin. + This class inherits from the Fins class. Note ---- @@ -19,10 +21,12 @@ class EllipticalFin(Fin): See Also -------- - Fin + Fins Attributes ---------- + EllipticalFin.n : int + Number of fins in fin set. EllipticalFin.rocket_radius : float The reference rocket radius used for lift coefficient normalization, in meters. @@ -30,12 +34,12 @@ class EllipticalFin(Fin): Tuple of two items. First is the airfoil lift curve. Second is the unit of the curve (radians or degrees) EllipticalFin.cant_angle : float - Fin cant angle with respect to the rocket centerline, in degrees. + Fins cant angle with respect to the rocket centerline, in degrees. EllipticalFin.changing_attribute_dict : dict Dictionary that stores the name and the values of the attributes that may be changed during a simulation. Useful for control systems. EllipticalFin.cant_angle_rad : float - Fin cant angle with respect to the rocket centerline, in radians. + Fins cant angle with respect to the rocket centerline, in radians. EllipticalFin.root_chord : float Fin root chord in meters. EllipticalFin.span : float @@ -43,11 +47,11 @@ class EllipticalFin(Fin): EllipticalFin.name : string Name of fin set. EllipticalFin.sweep_length : float - Fin sweep length in meters. By sweep length, understand the axial + 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. EllipticalFin.sweep_angle : float - Fin sweep angle with respect to the rocket centerline. Must + Fins sweep angle with respect to the rocket centerline. Must be given in degrees. EllipticalFin.d : float Reference diameter of the rocket, in meters. @@ -89,18 +93,20 @@ class EllipticalFin(Fin): def __init__( self, - angular_position, + n, root_chord, span, rocket_radius, cant_angle=0, airfoil=None, - name="Fin", + name="Fins", ): """Initialize EllipticalFin class. Parameters ---------- + n : int + Number of fins, must be larger than 2. root_chord : int, float Fin root chord in meters. span : int, float @@ -108,10 +114,10 @@ def __init__( rocket_radius : int, float Reference radius to calculate lift coefficient, in meters. cant_angle : int, float, optional - Fin cant angle with respect to the rocket centerline. Must + Fins cant angle with respect to the rocket centerline. Must be given in degrees. sweep_length : int, float, optional - Fin sweep length in meters. By sweep length, understand the axial + 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 @@ -119,14 +125,14 @@ def __init__( perpendicular to the rocket's axis. Cannot be used in conjunction with sweep_angle. sweep_angle : int, float, optional - Fin sweep angle with respect to the rocket centerline. Must + 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 sweep_length. airfoil : tuple, optional - Default is null, in which case fin will be treated as flat plates. - Otherwise, if tuple, fin will be considered as airfoils. The + Default is null, in which case fins will be treated as flat plates. + Otherwise, if tuple, fins will be considered as airfoils. The tuple's first item specifies the airfoil's lift coefficient by angle of attack and must be either a .csv, .txt, ndarray or callable. The .csv and .txt files can contain a single line @@ -147,7 +153,7 @@ def __init__( """ super().__init__( - angular_position, + n, root_chord, span, rocket_radius, @@ -160,7 +166,6 @@ def __init__( self.evaluate_center_of_pressure() self.evaluate_lift_coefficient() self.evaluate_roll_parameters() - self.evaluate_rotation_matrix() self.prints = _EllipticalFinPrints(self) self.plots = _EllipticalFinPlots(self) @@ -177,137 +182,36 @@ def evaluate_center_of_pressure(self): # Center of pressure position in local coordinates cpz = 0.288 * self.root_chord self.cpx = 0 - self.cpy = 0 + self.cpy = self.Yma self.cpz = cpz self.cp = (self.cpx, self.cpy, self.cpz) - def evaluate_geometrical_parameters(self): # pylint: disable=too-many-statements - """Calculates and saves fin set's geometrical parameters such as the - fin' area, aspect ratio and parameters for roll movement. - - Returns - ------- - None - """ - - # Compute auxiliary geometrical parameters - # pylint: disable=invalid-name - Af = (np.pi * self.root_chord / 2 * self.span) / 2 # Fin area - gamma_c = 0 # Zero for elliptical fin - AR = 2 * self.span**2 / Af # Fin aspect ratio - Yma = ( - self.span / (3 * np.pi) * np.sqrt(9 * np.pi**2 - 64) - ) # Span wise coord of mean aero chord - roll_geometrical_constant = ( - self.root_chord - * self.span - * ( - 3 * np.pi * self.span**2 - + 32 * self.rocket_radius * self.span - + 12 * np.pi * self.rocket_radius**2 - ) - / 48 - ) - - # Fin–body interference correction parameters - tau = (self.span + self.rocket_radius) / self.rocket_radius - lift_interference_factor = 1 + 1 / tau - if self.span > self.rocket_radius: - roll_damping_interference_factor = 1 + ( - (self.rocket_radius**2) - * ( - 2 - * (self.rocket_radius**2) - * np.sqrt(self.span**2 - self.rocket_radius**2) - * np.log( - ( - 2 - * self.span - * np.sqrt(self.span**2 - self.rocket_radius**2) - + 2 * self.span**2 - ) - / self.rocket_radius - ) - - 2 - * (self.rocket_radius**2) - * np.sqrt(self.span**2 - self.rocket_radius**2) - * np.log(2 * self.span) - + 2 * self.span**3 - - np.pi * self.rocket_radius * self.span**2 - - 2 * (self.rocket_radius**2) * self.span - + np.pi * self.rocket_radius**3 - ) - ) / ( - 2 - * (self.span**2) - * (self.span / 3 + np.pi * self.rocket_radius / 4) - * (self.span**2 - self.rocket_radius**2) - ) - elif self.span < self.rocket_radius: - roll_damping_interference_factor = 1 - ( - self.rocket_radius**2 - * ( - 2 * self.span**3 - - np.pi * self.span**2 * self.rocket_radius - - 2 * self.span * self.rocket_radius**2 - + np.pi * self.rocket_radius**3 - + 2 - * self.rocket_radius**2 - * np.sqrt(-self.span**2 + self.rocket_radius**2) - * np.arctan( - (self.span) / (np.sqrt(-self.span**2 + self.rocket_radius**2)) - ) - - np.pi - * self.rocket_radius**2 - * np.sqrt(-self.span**2 + self.rocket_radius**2) - ) - ) / ( - 2 - * self.span - * (-self.span**2 + self.rocket_radius**2) - * (self.span**2 / 3 + np.pi * self.span * self.rocket_radius / 4) + def to_dict(self, include_outputs=False): + data = super().to_dict(include_outputs) + if include_outputs: + data.update( + { + "Af": self.Af, + "AR": self.AR, + "gamma_c": self.gamma_c, + "Yma": self.Yma, + "roll_geometrical_constant": self.roll_geometrical_constant, + "tau": self.tau, + "lift_interference_factor": self.lift_interference_factor, + "roll_damping_interference_factor": self.roll_damping_interference_factor, + "roll_forcing_interference_factor": self.roll_forcing_interference_factor, + } ) - else: - roll_damping_interference_factor = (28 - 3 * np.pi) / (4 + 3 * np.pi) - - roll_forcing_interference_factor = (1 / np.pi**2) * ( - (np.pi**2 / 4) * ((tau + 1) ** 2 / tau**2) - + ((np.pi * (tau**2 + 1) ** 2) / (tau**2 * (tau - 1) ** 2)) - * np.arcsin((tau**2 - 1) / (tau**2 + 1)) - - (2 * np.pi * (tau + 1)) / (tau * (tau - 1)) - + ((tau**2 + 1) ** 2) - / (tau**2 * (tau - 1) ** 2) - * (np.arcsin((tau**2 - 1) / (tau**2 + 1))) ** 2 - - (4 * (tau + 1)) - / (tau * (tau - 1)) - * np.arcsin((tau**2 - 1) / (tau**2 + 1)) - + (8 / (tau - 1) ** 2) * np.log((tau**2 + 1) / (2 * tau)) + return data + + @classmethod + def from_dict(cls, data): + return cls( + n=data["n"], + root_chord=data["root_chord"], + span=data["span"], + rocket_radius=data["rocket_radius"], + cant_angle=data["cant_angle"], + airfoil=data["airfoil"], + name=data["name"], ) - - # Store values - # pylint: disable=invalid-name - self.Af = Af # Fin area - self.AR = AR # Fin aspect ratio - self.gamma_c = gamma_c # Mid chord angle - self.Yma = Yma # Span wise coord of mean aero chord - self.roll_geometrical_constant = roll_geometrical_constant - self.tau = tau - self.lift_interference_factor = lift_interference_factor - self.roll_damping_interference_factor = roll_damping_interference_factor - self.roll_forcing_interference_factor = roll_forcing_interference_factor - - self.evaluate_shape() - - def evaluate_shape(self): - angles = np.arange(0, 180, 5) - x_array = self.root_chord / 2 + self.root_chord / 2 * np.cos(np.radians(angles)) - y_array = self.span * np.sin(np.radians(angles)) - self.shape_vec = [x_array, y_array] - - def info(self): - self.prints.geometry() - self.prints.lift() - - def all_info(self): - self.prints.all() - self.plots.all() diff --git a/rocketpy/rocket/aero_surface/fins/elliptical_fins.py b/rocketpy/rocket/aero_surface/fins/elliptical_fins.py index 08c51ab64..c1f41b471 100644 --- a/rocketpy/rocket/aero_surface/fins/elliptical_fins.py +++ b/rocketpy/rocket/aero_surface/fins/elliptical_fins.py @@ -2,11 +2,12 @@ from rocketpy.plots.aero_surface_plots import _EllipticalFinsPlots from rocketpy.prints.aero_surface_prints import _EllipticalFinsPrints +from rocketpy.rocket.aero_surface.fins._elliptical_mixin import _EllipticalMixin from .fins import Fins -class EllipticalFins(Fins): +class EllipticalFins(_EllipticalMixin, Fins): """Class that defines and holds information for an elliptical fin set. This class inherits from the Fins class. @@ -186,137 +187,6 @@ def evaluate_center_of_pressure(self): self.cpz = cpz self.cp = (self.cpx, self.cpy, self.cpz) - def evaluate_geometrical_parameters(self): # pylint: disable=too-many-statements - """Calculates and saves fin set's geometrical parameters such as the - fins' area, aspect ratio and parameters for roll movement. - - Returns - ------- - None - """ - - # Compute auxiliary geometrical parameters - # pylint: disable=invalid-name - Af = (np.pi * self.root_chord / 2 * self.span) / 2 # Fin area - gamma_c = 0 # Zero for elliptical fins - AR = 2 * self.span**2 / Af # Fin aspect ratio - Yma = ( - self.span / (3 * np.pi) * np.sqrt(9 * np.pi**2 - 64) - ) # Span wise coord of mean aero chord - roll_geometrical_constant = ( - self.root_chord - * self.span - * ( - 3 * np.pi * self.span**2 - + 32 * self.rocket_radius * self.span - + 12 * np.pi * self.rocket_radius**2 - ) - / 48 - ) - - # Fin–body interference correction parameters - tau = (self.span + self.rocket_radius) / self.rocket_radius - lift_interference_factor = 1 + 1 / tau - if self.span > self.rocket_radius: - roll_damping_interference_factor = 1 + ( - (self.rocket_radius**2) - * ( - 2 - * (self.rocket_radius**2) - * np.sqrt(self.span**2 - self.rocket_radius**2) - * np.log( - ( - 2 - * self.span - * np.sqrt(self.span**2 - self.rocket_radius**2) - + 2 * self.span**2 - ) - / self.rocket_radius - ) - - 2 - * (self.rocket_radius**2) - * np.sqrt(self.span**2 - self.rocket_radius**2) - * np.log(2 * self.span) - + 2 * self.span**3 - - np.pi * self.rocket_radius * self.span**2 - - 2 * (self.rocket_radius**2) * self.span - + np.pi * self.rocket_radius**3 - ) - ) / ( - 2 - * (self.span**2) - * (self.span / 3 + np.pi * self.rocket_radius / 4) - * (self.span**2 - self.rocket_radius**2) - ) - elif self.span < self.rocket_radius: - roll_damping_interference_factor = 1 - ( - self.rocket_radius**2 - * ( - 2 * self.span**3 - - np.pi * self.span**2 * self.rocket_radius - - 2 * self.span * self.rocket_radius**2 - + np.pi * self.rocket_radius**3 - + 2 - * self.rocket_radius**2 - * np.sqrt(-(self.span**2) + self.rocket_radius**2) - * np.arctan( - (self.span) / (np.sqrt(-(self.span**2) + self.rocket_radius**2)) - ) - - np.pi - * self.rocket_radius**2 - * np.sqrt(-(self.span**2) + self.rocket_radius**2) - ) - ) / ( - 2 - * self.span - * (-(self.span**2) + self.rocket_radius**2) - * (self.span**2 / 3 + np.pi * self.span * self.rocket_radius / 4) - ) - else: - roll_damping_interference_factor = (28 - 3 * np.pi) / (4 + 3 * np.pi) - - roll_forcing_interference_factor = (1 / np.pi**2) * ( - (np.pi**2 / 4) * ((tau + 1) ** 2 / tau**2) - + ((np.pi * (tau**2 + 1) ** 2) / (tau**2 * (tau - 1) ** 2)) - * np.arcsin((tau**2 - 1) / (tau**2 + 1)) - - (2 * np.pi * (tau + 1)) / (tau * (tau - 1)) - + ((tau**2 + 1) ** 2) - / (tau**2 * (tau - 1) ** 2) - * (np.arcsin((tau**2 - 1) / (tau**2 + 1))) ** 2 - - (4 * (tau + 1)) - / (tau * (tau - 1)) - * np.arcsin((tau**2 - 1) / (tau**2 + 1)) - + (8 / (tau - 1) ** 2) * np.log((tau**2 + 1) / (2 * tau)) - ) - - # Store values - # pylint: disable=invalid-name - self.Af = Af # Fin area - self.AR = AR # Fin aspect ratio - self.gamma_c = gamma_c # Mid chord angle - self.Yma = Yma # Span wise coord of mean aero chord - self.roll_geometrical_constant = roll_geometrical_constant - self.tau = tau - self.lift_interference_factor = lift_interference_factor - self.roll_damping_interference_factor = roll_damping_interference_factor - self.roll_forcing_interference_factor = roll_forcing_interference_factor - - self.evaluate_shape() - - def evaluate_shape(self): - angles = np.arange(0, 180, 5) - x_array = self.root_chord / 2 + self.root_chord / 2 * np.cos(np.radians(angles)) - y_array = self.span * np.sin(np.radians(angles)) - self.shape_vec = [x_array, y_array] - - def info(self): - self.prints.geometry() - self.prints.lift() - - def all_info(self): - self.prints.all() - self.plots.all() - def to_dict(self, include_outputs=False): data = super().to_dict(include_outputs) if include_outputs: From 455ce01099bb1a7b870ccb17483f82b376aeeda8 Mon Sep 17 00:00:00 2001 From: MateusStano Date: Sat, 19 Apr 2025 22:19:21 +0200 Subject: [PATCH 16/32] ENH: add to_dict in Fin --- rocketpy/rocket/aero_surface/fins/fin.py | 92 ++++++++++++++---------- 1 file changed, 54 insertions(+), 38 deletions(-) diff --git a/rocketpy/rocket/aero_surface/fins/fin.py b/rocketpy/rocket/aero_surface/fins/fin.py index eea8ec0b0..c73b36e82 100644 --- a/rocketpy/rocket/aero_surface/fins/fin.py +++ b/rocketpy/rocket/aero_surface/fins/fin.py @@ -23,72 +23,72 @@ class Fin(_BaseFin): Attributes ---------- - Fins.rocket_radius : float + Fin.rocket_radius : float The reference rocket radius used for lift coefficient normalization, in meters. - Fins.airfoil : tuple + Fin.airfoil : tuple Tuple of two items. First is the airfoil lift curve. Second is the unit of the curve (radians or degrees). - Fins.cant_angle : float - Fins cant angle with respect to the rocket centerline, in degrees. - Fins.changing_attribute_dict : dict + Fin.cant_angle : float + Fin cant angle with respect to the rocket centerline, in degrees. + Fin.changing_attribute_dict : dict Dictionary that stores the name and the values of the attributes that may be changed during a simulation. Useful for control systems. - Fins.cant_angle_rad : float - Fins cant angle with respect to the rocket centerline, in radians. - Fins.root_chord : float + Fin.cant_angle_rad : float + Fin cant angle with respect to the rocket centerline, in radians. + Fin.root_chord : float Fin root chord in meters. - Fins.tip_chord : float + Fin.tip_chord : float Fin tip chord in meters. - Fins.span : float + Fin.span : float Fin span in meters. - Fins.name : string + Fin.name : string Name of fin set. - Fins.sweep_length : float - Fins sweep length in meters. By sweep length, understand the axial + Fin.sweep_length : float + Fin 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. - Fins.sweep_angle : float - Fins sweep angle with respect to the rocket centerline. Must + Fin.sweep_angle : float + Fin sweep angle with respect to the rocket centerline. Must be given in degrees. - Fins.d : float + Fin.d : float Reference diameter of the rocket. Has units of length and is given in meters. - Fins.ref_area : float + Fin.ref_area : float Reference area of the rocket. - Fins.Af : float + Fin.Af : float Area of the longitudinal section of each fin in the set. - Fins.AR : float + Fin.AR : float Aspect ratio of each fin in the set. - Fins.gamma_c : float + Fin.gamma_c : float Fin mid-chord sweep angle. - Fins.Yma : float + Fin.Yma : float Span wise position of the mean aerodynamic chord. - Fins.roll_geometrical_constant : float + Fin.roll_geometrical_constant : float Geometrical constant used in roll calculations. - Fins.tau : float + Fin.tau : float Geometrical relation used to simplify lift and roll calculations. - Fins.lift_interference_factor : float + Fin.lift_interference_factor : float Factor of Fin-Body interference in the lift coefficient. - Fins.cp : tuple + Fin.cp : tuple Tuple with the x, y and z local coordinates of the fin set center of pressure. Has units of length and is given in meters. - Fins.cpx : float + Fin.cpx : float Fin set local center of pressure x coordinate. Has units of length and is given in meters. - Fins.cpy : float + Fin.cpy : float Fin set local center of pressure y coordinate. Has units of length and is given in meters. - Fins.cpz : float + Fin.cpz : float Fin set local center of pressure z coordinate. Has units of length and is given in meters. - Fins.cl : Function + Fin.cl : Function Function which defines the lift coefficient as a function of the angle of attack and the Mach number. Takes as input the angle of attack in radians and the Mach number. Returns the lift coefficient. - Fins.clalpha : float + Fin.clalpha : float Lift coefficient slope. Has units of 1/rad. - Fins.roll_parameters : list + Fin.roll_parameters : list List containing the roll moment lift coefficient, the roll moment damping coefficient and the cant angle in radians. """ @@ -226,11 +226,7 @@ def evaluate_roll_parameters(self): roll moment damping coefficient and the cant angle in radians """ - clf_delta = ( - 0 # TODO: should calculate this as well, should be same formula as fins - ) - # clf_delta.set_inputs("Mach") - # clf_delta.set_outputs("Roll moment forcing coefficient derivative") + clf_delta = 0 # Not used in this class cld_omega = -( 2 * self.roll_damping_interference_factor @@ -373,8 +369,28 @@ def compute_forces_and_moments( M3 += M3_damping return R1, R2, R3, M1, M2, M3 - def to_dict(self): - pass # TODO + def to_dict(self, include_outputs=False): + data = { + "angular_position": self.angular_position, + "root_chord": self.root_chord, + "span": self.span, + "rocket_radius": self.rocket_radius, + "cant_angle": self.cant_angle, + "airfoil": self.airfoil, + "name": self.name, + } + + if include_outputs: + data.update( + { + "cp": self.cp, + "cl": self.cl, + "roll_parameters": self.roll_parameters, + "d": self.d, + "ref_area": self.ref_area, + } + ) + return data def draw(self, *, filename=None): """Draw the fin shape along with some important information, including From 985268dddf02c9177861acd66728c725e6e30529 Mon Sep 17 00:00:00 2001 From: MateusStano Date: Mon, 21 Apr 2025 16:00:36 +0200 Subject: [PATCH 17/32] ENH: add FreeFormFin prints and plots --- rocketpy/__init__.py | 1 + rocketpy/plots/aero_surface_plots.py | 153 +++++++++++++----- rocketpy/prints/aero_surface_prints.py | 5 +- rocketpy/rocket/__init__.py | 1 + rocketpy/rocket/aero_surface/__init__.py | 1 + rocketpy/rocket/aero_surface/fins/__init__.py | 1 + rocketpy/rocket/aero_surface/fins/base_fin.py | 4 +- rocketpy/rocket/aero_surface/fins/fin.py | 3 - .../rocket/aero_surface/fins/free_form_fin.py | 62 +++---- 9 files changed, 154 insertions(+), 77 deletions(-) diff --git a/rocketpy/__init__.py b/rocketpy/__init__.py index cc3233b7d..9979ce3bd 100644 --- a/rocketpy/__init__.py +++ b/rocketpy/__init__.py @@ -32,6 +32,7 @@ EllipticalFins, Fin, Fins, + FreeFormFin, FreeFormFins, GenericSurface, LinearGenericSurface, diff --git a/rocketpy/plots/aero_surface_plots.py b/rocketpy/plots/aero_surface_plots.py index fd6108630..111481d29 100644 --- a/rocketpy/plots/aero_surface_plots.py +++ b/rocketpy/plots/aero_surface_plots.py @@ -587,6 +587,77 @@ def draw(self, *, filename=None): show_or_save_plot(filename) +class _EllipticalFinPlots(_FinPlots): + """Class that contains all elliptical fin plots.""" + + # pylint: disable=too-many-statements + def draw(self): + """Draw the fin shape along with some important information. + These being: the center line and the center of pressure position. + + Returns + ------- + None + """ + # Ellipse + ellipse = Ellipse( + (self.aero_surface.root_chord / 2, 0), + self.aero_surface.root_chord, + self.aero_surface.span * 2, + fill=False, + edgecolor="#A60628", + linewidth=2, + ) + + # Mean Aerodynamic Chord # From Barrowman's theory + yma_length = 8 * self.aero_surface.root_chord / (3 * np.pi) + yma_start = (self.aero_surface.root_chord - yma_length) / 2 + yma_end = ( + self.aero_surface.root_chord + - (self.aero_surface.root_chord - yma_length) / 2 + ) + yma_line = plt.Line2D( + (yma_start, yma_end), + (self.aero_surface.Yma, self.aero_surface.Yma), + label="Mean Aerodynamic Chord", + color="#467821", + ) + + # Center Line + center_line = plt.Line2D( + (self.aero_surface.root_chord / 2, self.aero_surface.root_chord / 2), + (0, self.aero_surface.span), + color="#7A68A6", + alpha=0.35, + linestyle="--", + label="Center Line", + ) + + # Center of pressure + cp_point = [self.aero_surface.cpz, self.aero_surface.Yma] + + # Plotting + fig = plt.figure(figsize=(7, 4)) + with plt.style.context("bmh"): + ax = fig.add_subplot(111) + ax.add_patch(ellipse) + ax.add_line(yma_line) + ax.add_line(center_line) + ax.scatter(*cp_point, label="Center of Pressure", color="red", s=100, zorder=10) + ax.scatter(*cp_point, facecolors="none", edgecolors="red", s=500, zorder=10) + + # Plot settings + ax.set_xlim(0, self.aero_surface.root_chord) + ax.set_ylim(0, self.aero_surface.span * 1.1) + ax.set_xlabel("Root chord (m)") + ax.set_ylabel("Span (m)") + ax.set_title("Elliptical Fin Cross Section") + ax.legend(bbox_to_anchor=(1.05, 1.0), loc="upper left") + + plt.tight_layout() + plt.show() + + class _FreeFormFinsPlots(_FinsPlots): """Class that contains all free form fin plots.""" @@ -662,75 +733,79 @@ def draw(self, *, filename=None): show_or_save_plot(filename) -class _EllipticalFinPlots(_FinPlots): - """Class that contains all elliptical fin plots.""" +class _FreeFormFinPlots(_FinPlots): + """Class that contains all free form fin plots.""" # pylint: disable=too-many-statements - def draw(self): + def draw(self, *, filename=None): """Draw the fin shape along with some important information. These being: the center line and the center of pressure position. + Parameters + ---------- + filename : str | None, optional + The path the plot should be saved to. By default None, in which case + the plot will be shown instead of saved. Supported file endings are: + eps, jpg, jpeg, pdf, pgf, png, ps, raw, rgba, svg, svgz, tif, tiff + and webp (these are the formats supported by matplotlib). + Returns ------- None """ - # Ellipse - ellipse = Ellipse( - (self.aero_surface.root_chord / 2, 0), - self.aero_surface.root_chord, - self.aero_surface.span * 2, - fill=False, - edgecolor="#A60628", - linewidth=2, - ) + # Color cycle [#348ABD, #A60628, #7A68A6, #467821, #D55E00, #CC79A7, + # #56B4E9, #009E73, #F0E442, #0072B2] - # Mean Aerodynamic Chord # From Barrowman's theory - yma_length = 8 * self.aero_surface.root_chord / (3 * np.pi) - yma_start = (self.aero_surface.root_chord - yma_length) / 2 - yma_end = ( - self.aero_surface.root_chord - - (self.aero_surface.root_chord - yma_length) / 2 - ) + # Center of pressure + cp_point = [self.aero_surface.cpz, self.aero_surface.Yma] + + # Mean Aerodynamic Chord yma_line = plt.Line2D( - (yma_start, yma_end), + ( + self.aero_surface.mac_lead, + self.aero_surface.mac_lead + self.aero_surface.mac_length, + ), (self.aero_surface.Yma, self.aero_surface.Yma), - label="Mean Aerodynamic Chord", color="#467821", - ) - - # Center Line - center_line = plt.Line2D( - (self.aero_surface.root_chord / 2, self.aero_surface.root_chord / 2), - (0, self.aero_surface.span), - color="#7A68A6", - alpha=0.35, linestyle="--", - label="Center Line", + label="Mean Aerodynamic Chord", ) - # Center of pressure - cp_point = [self.aero_surface.cpz, self.aero_surface.Yma] - # Plotting fig = plt.figure(figsize=(7, 4)) with plt.style.context("bmh"): ax = fig.add_subplot(111) - ax.add_patch(ellipse) + + # Fin + ax.scatter( + self.aero_surface.shape_vec[0], + self.aero_surface.shape_vec[1], + color="#A60628", + ) + ax.plot( + self.aero_surface.shape_vec[0], + self.aero_surface.shape_vec[1], + color="#A60628", + ) + # line from the last point to the first point + ax.plot( + [self.aero_surface.shape_vec[0][-1], self.aero_surface.shape_vec[0][0]], + [self.aero_surface.shape_vec[1][-1], self.aero_surface.shape_vec[1][0]], + color="#A60628", + ) + ax.add_line(yma_line) - ax.add_line(center_line) ax.scatter(*cp_point, label="Center of Pressure", color="red", s=100, zorder=10) ax.scatter(*cp_point, facecolors="none", edgecolors="red", s=500, zorder=10) # Plot settings - ax.set_xlim(0, self.aero_surface.root_chord) - ax.set_ylim(0, self.aero_surface.span * 1.1) ax.set_xlabel("Root chord (m)") ax.set_ylabel("Span (m)") - ax.set_title("Elliptical Fin Cross Section") + ax.set_title("Free Form Fin Cross Section") ax.legend(bbox_to_anchor=(1.05, 1.0), loc="upper left") plt.tight_layout() - plt.show() + show_or_save_plot(filename) class _TailPlots(_AeroSurfacePlots): diff --git a/rocketpy/prints/aero_surface_prints.py b/rocketpy/prints/aero_surface_prints.py index 6a4afa3cc..b2c81eaf9 100644 --- a/rocketpy/prints/aero_surface_prints.py +++ b/rocketpy/prints/aero_surface_prints.py @@ -172,7 +172,6 @@ def all(self): class _FinPrints(_AeroSurfacePrints): - def geometry(self): print("Geometric information of the fin set:") print("-------------------------------------") @@ -291,6 +290,10 @@ class _FreeFormFinsPrints(_FinsPrints): """Class that contains all free form fins prints.""" +class _FreeFormFinPrints(_FinPrints): + """Class that contains all free form fins prints.""" + + class _TailPrints(_AeroSurfacePrints): """Class that contains all tail prints.""" diff --git a/rocketpy/rocket/__init__.py b/rocketpy/rocket/__init__.py index c48646436..87ea03c47 100644 --- a/rocketpy/rocket/__init__.py +++ b/rocketpy/rocket/__init__.py @@ -6,6 +6,7 @@ EllipticalFins, Fin, Fins, + FreeFormFin, FreeFormFins, GenericSurface, LinearGenericSurface, diff --git a/rocketpy/rocket/aero_surface/__init__.py b/rocketpy/rocket/aero_surface/__init__.py index b3538b1ef..7634d3500 100644 --- a/rocketpy/rocket/aero_surface/__init__.py +++ b/rocketpy/rocket/aero_surface/__init__.py @@ -5,6 +5,7 @@ EllipticalFins, Fin, Fins, + FreeFormFin, FreeFormFins, TrapezoidalFin, TrapezoidalFins, diff --git a/rocketpy/rocket/aero_surface/fins/__init__.py b/rocketpy/rocket/aero_surface/fins/__init__.py index bf1beef37..dd678c625 100644 --- a/rocketpy/rocket/aero_surface/fins/__init__.py +++ b/rocketpy/rocket/aero_surface/fins/__init__.py @@ -2,6 +2,7 @@ from rocketpy.rocket.aero_surface.fins.elliptical_fins import EllipticalFins from rocketpy.rocket.aero_surface.fins.fin import Fin from rocketpy.rocket.aero_surface.fins.fins import Fins +from rocketpy.rocket.aero_surface.fins.free_form_fin import FreeFormFin from rocketpy.rocket.aero_surface.fins.free_form_fins import FreeFormFins from rocketpy.rocket.aero_surface.fins.trapezoidal_fin import TrapezoidalFin from rocketpy.rocket.aero_surface.fins.trapezoidal_fins import TrapezoidalFins diff --git a/rocketpy/rocket/aero_surface/fins/base_fin.py b/rocketpy/rocket/aero_surface/fins/base_fin.py index f8a365d7f..4c78180d9 100644 --- a/rocketpy/rocket/aero_surface/fins/base_fin.py +++ b/rocketpy/rocket/aero_surface/fins/base_fin.py @@ -97,7 +97,7 @@ def cant_angle(self, value): @property def cant_angle_rad(self): - return self._cant_angle_rad # TODO check this sign and why??? + return self._cant_angle_rad @cant_angle_rad.setter def cant_angle_rad(self, value): @@ -118,8 +118,6 @@ def airfoil(self, value): self.evaluate_center_of_pressure() self.evaluate_lift_coefficient() self.evaluate_roll_parameters() - self.evaluate_roll_parameters() - self.evaluate_roll_parameters() def evaluate_single_fin_lift_coefficient(self): if not self.airfoil: diff --git a/rocketpy/rocket/aero_surface/fins/fin.py b/rocketpy/rocket/aero_surface/fins/fin.py index c73b36e82..29f69d3a1 100644 --- a/rocketpy/rocket/aero_surface/fins/fin.py +++ b/rocketpy/rocket/aero_surface/fins/fin.py @@ -148,9 +148,6 @@ def __init__( self._angular_position = angular_position self._angular_position_rad = math.radians(angular_position) - self.M3dh = [] # Roll moment damping - self.cldwh = [] # Roll moment lift coefficient derivative - @property def cant_angle(self): return self._cant_angle diff --git a/rocketpy/rocket/aero_surface/fins/free_form_fin.py b/rocketpy/rocket/aero_surface/fins/free_form_fin.py index 5df5d306e..496796fa3 100644 --- a/rocketpy/rocket/aero_surface/fins/free_form_fin.py +++ b/rocketpy/rocket/aero_surface/fins/free_form_fin.py @@ -2,14 +2,14 @@ import numpy as np -from rocketpy.plots.aero_surface_plots import _FreeFormFinsPlots -from rocketpy.prints.aero_surface_prints import _FreeFormFinsPrints +from rocketpy.plots.aero_surface_plots import _FreeFormFinPlots +from rocketpy.prints.aero_surface_prints import _FreeFormFinPrints from rocketpy.rocket.aero_surface.fins._free_form_mixin import _FreeFormMixin from .fins import Fins -class FreeFormFins(_FreeFormMixin, Fins): +class FreeFormFin(_FreeFormMixin, Fins): """Class that defines and holds information for a free form fin set. This class inherits from the Fins class. @@ -28,63 +28,63 @@ class FreeFormFins(_FreeFormMixin, Fins): Attributes ---------- - FreeFormFins.n : int + FreeFormFin.n : int Number of fins in fin set. - FreeFormFins.rocket_radius : float + FreeFormFin.rocket_radius : float The reference rocket radius used for lift coefficient normalization, in meters. - FreeFormFins.airfoil : tuple + FreeFormFin.airfoil : tuple Tuple of two items. First is the airfoil lift curve. Second is the unit of the curve (radians or degrees). - FreeFormFins.cant_angle : float + FreeFormFin.cant_angle : float Fins cant angle with respect to the rocket centerline, in degrees. - FreeFormFins.cant_angle_rad : float + FreeFormFin.cant_angle_rad : float Fins cant angle with respect to the rocket centerline, in radians. - FreeFormFins.root_chord : float + FreeFormFin.root_chord : float Fin root chord in meters. - FreeFormFins.span : float + FreeFormFin.span : float Fin span in meters. - FreeFormFins.name : string + FreeFormFin.name : string Name of fin set. - FreeFormFins.d : float + FreeFormFin.d : float Reference diameter of the rocket, in meters. - FreeFormFins.ref_area : float + FreeFormFin.ref_area : float Reference area of the rocket, in m². - FreeFormFins.Af : float + FreeFormFin.Af : float Area of the longitudinal section of each fin in the set. - FreeFormFins.AR : float + FreeFormFin.AR : float Aspect ratio of each fin in the set - FreeFormFins.gamma_c : float + FreeFormFin.gamma_c : float Fin mid-chord sweep angle. - FreeFormFins.Yma : float + FreeFormFin.Yma : float Span wise position of the mean aerodynamic chord. - FreeFormFins.roll_geometrical_constant : float + FreeFormFin.roll_geometrical_constant : float Geometrical constant used in roll calculations. - FreeFormFins.tau : float + FreeFormFin.tau : float Geometrical relation used to simplify lift and roll calculations. - FreeFormFins.lift_interference_factor : float + FreeFormFin.lift_interference_factor : float Factor of Fin-Body interference in the lift coefficient. - FreeFormFins.cp : tuple + FreeFormFin.cp : tuple Tuple with the x, y and z local coordinates of the fin set center of pressure. Has units of length and is given in meters. - FreeFormFins.cpx : float + FreeFormFin.cpx : float Fin set local center of pressure x coordinate. Has units of length and is given in meters. - FreeFormFins.cpy : float + FreeFormFin.cpy : float Fin set local center of pressure y coordinate. Has units of length and is given in meters. - FreeFormFins.cpz : float + FreeFormFin.cpz : float Fin set local center of pressure z coordinate. Has units of length and is given in meters. - FreeFormFins.cl : Function + FreeFormFin.cl : Function Function which defines the lift coefficient as a function of the angle of attack and the Mach number. Takes as input the angle of attack in radians and the Mach number. Returns the lift coefficient. - FreeFormFins.clalpha : float + FreeFormFin.clalpha : float Lift coefficient slope. Has units of 1/rad. - FreeFormFins.mac_length : float + FreeFormFin.mac_length : float Mean aerodynamic chord length of the fin set. - FreeFormFins.mac_lead : float + FreeFormFin.mac_lead : float Mean aerodynamic chord leading edge x coordinate. """ @@ -97,7 +97,7 @@ def __init__( airfoil=None, name="Fins", ): - """Initialize FreeFormFins class. + """Initialize FreeFormFin class. Parameters ---------- @@ -153,8 +153,8 @@ def __init__( self.evaluate_lift_coefficient() self.evaluate_roll_parameters() - self.prints = _FreeFormFinsPrints(self) - self.plots = _FreeFormFinsPlots(self) + self.prints = _FreeFormFinPrints(self) + self.plots = _FreeFormFinPlots(self) def evaluate_center_of_pressure(self): """Calculates and returns the center of pressure of the fin set in local From 7ce8644cdbd290efab80281daa6c4fcc581f12d7 Mon Sep 17 00:00:00 2001 From: MateusStano Date: Mon, 21 Apr 2025 19:24:07 +0200 Subject: [PATCH 18/32] ENH: add aero surfaces to body rotation matrixes --- rocketpy/rocket/aero_surface/aero_surface.py | 10 ++++++++++ rocketpy/rocket/aero_surface/fins/fin.py | 1 + rocketpy/rocket/aero_surface/generic_surface.py | 2 ++ 3 files changed, 13 insertions(+) diff --git a/rocketpy/rocket/aero_surface/aero_surface.py b/rocketpy/rocket/aero_surface/aero_surface.py index 15ca14f1d..9846f1f3b 100644 --- a/rocketpy/rocket/aero_surface/aero_surface.py +++ b/rocketpy/rocket/aero_surface/aero_surface.py @@ -2,6 +2,8 @@ import numpy as np +from rocketpy.mathutils.vector_matrix import Matrix + class AeroSurface(ABC): """Abstract class used to define aerodynamic surfaces.""" @@ -15,6 +17,14 @@ def __init__(self, name, reference_area, reference_length): self.cpy = 0 self.cpz = 0 + self._rotation_surface_to_body = Matrix( + [ + [-1, 0, 0], + [0, 1, 0], + [0, 0, -1], + ] + ) + @staticmethod def _beta(mach): """Defines a parameter that is often used in aerodynamic diff --git a/rocketpy/rocket/aero_surface/fins/fin.py b/rocketpy/rocket/aero_surface/fins/fin.py index 29f69d3a1..3d228ea75 100644 --- a/rocketpy/rocket/aero_surface/fins/fin.py +++ b/rocketpy/rocket/aero_surface/fins/fin.py @@ -298,6 +298,7 @@ def evaluate_rotation_matrix(self): self._rotation_fin_to_body_uncanted = R_uncanted.transpose self._rotation_body_to_fin = R_body_to_fin self._rotation_fin_to_body = R_body_to_fin.transpose + self._rotation_surface_to_body = self._rotation_fin_to_body def compute_forces_and_moments( self, diff --git a/rocketpy/rocket/aero_surface/generic_surface.py b/rocketpy/rocket/aero_surface/generic_surface.py index 2d58257f9..31a979457 100644 --- a/rocketpy/rocket/aero_surface/generic_surface.py +++ b/rocketpy/rocket/aero_surface/generic_surface.py @@ -84,6 +84,8 @@ def __init__( self.cpz = center_of_pressure[2] self.name = name + self._rotation_surface_to_body = Matrix([[1, 0, 0], [0, 1, 0], [0, 0, 1]]) + default_coefficients = self._get_default_coefficients() self._check_coefficients(coefficients, default_coefficients) coefficients = self._complete_coefficients(coefficients, default_coefficients) From 0ddfdc17b60aea575c7e0d18a2d1efe5d27de9e5 Mon Sep 17 00:00:00 2001 From: MateusStano Date: Mon, 21 Apr 2025 19:31:59 +0200 Subject: [PATCH 19/32] ENH: adapt position related calculations --- rocketpy/rocket/aero_surface/fins/fin.py | 33 +++ rocketpy/rocket/rocket.py | 313 ++++++----------------- 2 files changed, 112 insertions(+), 234 deletions(-) diff --git a/rocketpy/rocket/aero_surface/fins/fin.py b/rocketpy/rocket/aero_surface/fins/fin.py index 3d228ea75..80d7e43c0 100644 --- a/rocketpy/rocket/aero_surface/fins/fin.py +++ b/rocketpy/rocket/aero_surface/fins/fin.py @@ -367,6 +367,39 @@ def compute_forces_and_moments( M3 += M3_damping return R1, R2, R3, M1, M2, M3 + def __compute_leading_edge_position(self, position, _csys): + """Computes the position of the fin leading edge in a rocket's user, + given its position in a rocket.""" + # Point from deflection from cant angle in the plane perpendicular to + # the fuselage where the fin is located in the fin frame + p = Vector( + [ + -self.root_chord / 2 * np.sin(self.cant_angle_rad), + 0, + self.root_chord / 2 * (1 - np.cos(self.cant_angle_rad)), + ] + ) + # Rotate the point to the body frame orientation + p = self._rotation_fin_to_body_uncanted @ p + + # Rotate the point to the user-defined coordinate system + p = Vector([p.x * _csys, p.y, p.z * _csys]) + + # Calculate the position of the fin leading edge in the user frame + # as if no cant angle was applied + position = Vector( + [ + -self.rocket_radius * math.sin(self.angular_position_rad) * _csys, + self.rocket_radius * math.cos(self.angular_position_rad), + position, + ] + ) + + # Translate the position of the fin leading edge to the position of the + # fin leading edge with cant angle + position += p + return position + def to_dict(self, include_outputs=False): data = { "angular_position": self.angular_position, diff --git a/rocketpy/rocket/rocket.py b/rocketpy/rocket/rocket.py index 6712cd81d..1b929a20c 100644 --- a/rocketpy/rocket/rocket.py +++ b/rocketpy/rocket/rocket.py @@ -19,6 +19,7 @@ TrapezoidalFins, ) from rocketpy.rocket.aero_surface.fins.elliptical_fin import EllipticalFin +from rocketpy.rocket.aero_surface.fins.free_form_fin import FreeFormFin from rocketpy.rocket.aero_surface.fins.free_form_fins import FreeFormFins from rocketpy.rocket.aero_surface.fins.trapezoidal_fin import TrapezoidalFin from rocketpy.rocket.aero_surface.generic_surface import GenericSurface @@ -597,29 +598,20 @@ def __evaluate_single_surface_cp_to_cdm(self, surface, position): """Calculates the relative position of each aerodynamic surface center of pressure to the rocket's center of dry mass in Body Axes Coordinate System.""" - # try for individual fin - if isinstance(surface, Fin): - # TODO: include cm_eccentricity_x and cm_eccentricity_y for Fin - pos = Vector( - [ - -(surface.rocket_radius + surface.cpy) - * -np.sin(surface.angular_position_rad) - * self._csys, - (surface.rocket_radius + surface.cpy) - * np.cos(surface.angular_position_rad), - (position.z - self.center_of_dry_mass_position) * self._csys - - surface.cpz, - ] - ) - else: - pos = Vector( - [ - (position.x - self.cm_eccentricity_x) * self._csys - surface.cpx, - (position.y - self.cm_eccentricity_y) + surface.cpy, - (position.z - self.center_of_dry_mass_position) * self._csys - - surface.cpz, - ] - ) + # position of the surfaces coordinate system origin in body frame + pos_origin = Vector( + [ + (position.x - self.cm_eccentricity_x) * self._csys, + (position.y - self.cm_eccentricity_y), + (position.z - self.center_of_dry_mass_position) * self._csys, + ] + ) + # position of the center of pressure in body frame + pos = ( + surface._rotation_surface_to_body + @ Vector([surface.cpx, surface.cpy, surface.cpz]) + + pos_origin + ) # TODO: this should be recomputed whenever cant angle changes for fin self.surfaces_cp_to_cdm[surface] = pos def evaluate_stability_margin(self): @@ -1013,11 +1005,17 @@ def __add_single_surface(self, surface, position): """Adds a single aerodynamic surface to the rocket. Makes checks for rail buttons case, and position type. """ - position = ( - Vector([0, 0, position]) - if not isinstance(position, (Vector, tuple, list)) - else Vector(position) - ) + if isinstance(surface, (TrapezoidalFin, EllipticalFin, FreeFormFin)): + # TODO: this depends on cant angle, so it should somehow be + # recalculated whenever the cant angle of the fin changes + position = surface._Fin__compute_leading_edge_position(position, self._csys) + else: + position = ( + Vector([0, 0, position]) + if not isinstance(position, (Vector, tuple, list)) + else Vector(position) + ) + if isinstance(surface, RailButtons): self.rail_buttons = Components() self.rail_buttons.add(surface, position) @@ -1035,14 +1033,18 @@ def add_surfaces(self, surfaces, positions): surfaces : list, AeroSurface, NoseCone, TrapezoidalFins, EllipticalFins, Tail, RailButtons Aerodynamic surface to be added to the rocket. Can be a list of AeroSurface if more than one surface is to be added. - positions : int, float, list, tuple, Vector - Position, in m, of the aerodynamic surface's center of pressure - relative to the user defined rocket coordinate system. - If a list is passed, it will correspond to the position of each item - in the surfaces list. - For NoseCone type, position is relative to the nose cone tip. - For Fins type, position is relative to the point belonging to - the root chord which is highest in the rocket coordinate system. + positions : int, float, tuple, list, Vector + Position(s) of the aerodynamic surface's reference point. Can be: + - a single number (int or float) giving the z-coordinate along + the rocket axis. + - a sequence of three numbers (x, y, z) representing the full + position in the user-defined coordinate system. + If passing multiple surfaces, provide a list of positions matching + each surface in order. + For NoseCone type, position is the tip coordinate along the axis. + For Fins type, position refers to the z-coordinate of the root + chord leading-edge point closest to the nose cone, before any + can-angle offset is considered. For Tail type, position is relative to the point belonging to the tail which is highest in the rocket coordinate system. For RailButtons type, position is relative to the lower rail button. @@ -1055,10 +1057,18 @@ def add_surfaces(self, surfaces, positions): ------- None """ - try: + if isinstance(surfaces, list): + if isinstance(positions, list): + if len(surfaces) != len(positions): + raise ValueError( + "The number of surfaces and positions must be the same." + ) + else: + positions = [positions] * len(surfaces) + for surface, position in zip(surfaces, positions): self.__add_single_surface(surface, position) - except TypeError: + else: self.__add_single_surface(surfaces, positions) self.evaluate_center_of_pressure() @@ -1232,10 +1242,10 @@ def add_trapezoidal_fins( tip_chord : int, float Fin tip chord in meters. position : int, float - Fin set position relative to the rocket's coordinate system. - By fin set position, understand the point belonging to the root - chord which is highest in the rocket coordinate system (i.e. - the point closest to the nose cone tip). + Fin set position in the z coordinate of the user defined rocket + coordinate system. By fin set position, understand the point + belonging to the root chord which is highest in the rocket + coordinate system (i.e. the point closest to the nose cone tip). See Also -------- @@ -1281,6 +1291,12 @@ def add_trapezoidal_fins( fin_set : TrapezoidalFins Fin set object created. """ + if n <= 2: + raise ValueError( + "Number of fins must be greater than 2." + "If you want to add 2 or 1 fins, create a TrapezoidalFin object " + " and add it to the rocket using the add_surfaces method." + ) # Modify radius if not given, use rocket radius, otherwise use given. radius = radius if radius is not None else self.radius @@ -1328,10 +1344,10 @@ def add_elliptical_fins( span : int, float Fin span in meters. position : int, float - Fin set position relative to the rocket's coordinate system. By fin - set position, understand the point belonging to the root chord which - is highest in the rocket coordinate system (i.e. the point - closest to the nose cone tip). + Fin set position in the z coordinate of the user defined rocket + coordinate system. By fin set position, understand the point + belonging to the root chord which is highest in the rocket + coordinate system (i.e. the point closest to the nose cone tip). See Also -------- @@ -1367,195 +1383,18 @@ def add_elliptical_fins( fin_set : EllipticalFins Fin set object created. """ + if n <= 2: + raise ValueError( + "Number of fins must be greater than 2." + "If you want to add 2 or 1 fins, create a EllipticalFin object " + " and add it to the rocket using the add_surfaces method." + ) + radius = radius if radius is not None else self.radius fin_set = EllipticalFins(n, root_chord, span, radius, cant_angle, airfoil, name) self.add_surfaces(fin_set, position) return fin_set - def add_trapezoidal_fin( - self, - root_chord, - tip_chord, - span, - position, - angular_position, - cant_angle=0.0, - sweep_length=None, - sweep_angle=None, - radius=None, - airfoil=None, - name="Fin", - ): - """Adds a single fin to the rocket. This method is useful when the user - wants to add a single fin with a specific shape and position. - - See Also - -------- - :ref:`positions` - - Parameters - ---------- - root_chord : int, float - Fin root chord in meters. - tip_chord : int, float - Fin tip chord in meters. - span : int, float - Fin span in meters. - position : int, float - Fin position relative to the rocket's user defined coordinate system. - By fin position, understand the point belonging to the root chord - which is highest in the rocket coordinate system (i.e. the point - closest to the nose cone tip). - angular_position : int, float - The angular orientation of the fin. This is the angle measured - from the positive y-axis, with positive values corresponding to a - positive rotation about the z-axis. - cant_angle : int, float, optional - Fins cant angle with respect to the rocket centerline. Must be given - in degrees. Default is 0. - sweep_length : 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. Cannot be used in conjunction - with sweep_angle. Default is None. - sweep_angle : 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 sweep_length. Default is None. - radius : int, float, optional - Radius of the rocket at the fin position. If not given, the rocket - radius will be used. Default is None. - airfoil : tuple, optional - Default is null, in which case fins will be treated as flat plates. - Otherwise, if tuple, fins will be considered as airfoils. The - tuple's first item specifies the airfoil's lift coefficient - by angle of attack and must be either a .csv, .txt, ndarray - or callable. The .csv and .txt files can contain a single line - header and the first column must specify the angle of attack, while - the second column must specify the lift coefficient. The - ndarray should be as [(x0, y0), (x1, y1), (x2, y2), ...] - where x0 is the angle of attack and y0 is the lift coefficient. - If callable, it should take an angle of attack as input and - return the lift coefficient at that angle of attack. - The tuple's second item is the unit of the angle of attack, - accepting either "radians" or "degrees". Default is None. - name : string, optional - Fin name. Default is "Fin". - - Returns - ------- - fin : Fin - Fin object created. - """ - radius = radius or self.radius - fin = TrapezoidalFin( - angular_position=angular_position, - root_chord=root_chord, - tip_chord=tip_chord, - span=span, - rocket_radius=radius, - cant_angle=cant_angle, - sweep_length=sweep_length, - sweep_angle=sweep_angle, - airfoil=airfoil, - name=name, - ) - position = Vector( - [ - radius * -math.sin(math.radians(angular_position)), - radius * math.cos(math.radians(angular_position)), - position, - ] - ) - self.add_surfaces(fin, position) - return fin - - def add_elliptical_fin( - self, - root_chord, - span, - position, - angular_position, - cant_angle=0.0, - radius=None, - airfoil=None, - name="Fin", - ): - """Adds a single fin to the rocket. This method is useful when the user - wants to add a single fin with a specific shape and position. - - See Also - -------- - :ref:`positions` - - Parameters - ---------- - root_chord : int, float - Fin root chord in meters. - span : int, float - Fin span in meters. - position : int, float - Fin position relative to the rocket's user defined coordinate system. - By fin position, understand the point belonging to the root chord - which is highest in the rocket coordinate system (i.e. the point - closest to the nose cone tip). - angular_position : int, float - The angular orientation of the fin. This is the angle measured - from the positive y-axis, with positive values corresponding to a - positive rotation about the z-axis. - cant_angle : int, float, optional - Fins cant angle with respect to the rocket centerline. Must be given - in degrees. Default is 0. - radius : int, float, optional - Radius of the rocket at the fin position. If not given, the rocket - radius will be used. Default is None. - airfoil : tuple, optional - Default is null, in which case fins will be treated as flat plates. - Otherwise, if tuple, fins will be considered as airfoils. The - tuple's first item specifies the airfoil's lift coefficient - by angle of attack and must be either a .csv, .txt, ndarray - or callable. The .csv and .txt files can contain a single line - header and the first column must specify the angle of attack, while - the second column must specify the lift coefficient. The - ndarray should be as [(x0, y0), (x1, y1), (x2, y2), ...] - where x0 is the angle of attack and y0 is the lift coefficient. - If callable, it should take an angle of attack as input and - return the lift coefficient at that angle of attack. - The tuple's second item is the unit of the angle of attack, - accepting either "radians" or "degrees". Default is None. - name : string, optional - Fin name. Default is "Fin". - - Returns - ------- - fin : Fin - Fin object created. - """ - radius = radius or self.radius - fin = EllipticalFin( - angular_position=angular_position, - root_chord=root_chord, - span=span, - rocket_radius=radius, - cant_angle=cant_angle, - airfoil=airfoil, - name=name, - ) - position = Vector( - [ - radius * -math.sin(math.radians(angular_position)), - radius * math.cos(math.radians(angular_position)), - position, - ] - ) - self.add_surfaces(fin, position) - return fin - def add_free_form_fins( self, n, @@ -1582,10 +1421,10 @@ def add_free_form_fins( The shape will be interpolated between the points, in the order they are given. The last point connects to the first point. position : int, float - Fin set position relative to the rocket's coordinate system. - By fin set position, understand the point belonging to the root - chord which is highest in the rocket coordinate system (i.e. - the point closest to the nose cone tip). + Fin set position in the z coordinate of the user defined rocket + coordinate system. By fin set position, understand the point + belonging to the root chord which is highest in the rocket + coordinate system (i.e. the point closest to the nose cone tip). See Also -------- @@ -1617,6 +1456,12 @@ def add_free_form_fins( fin_set : FreeFormFins Fin set object created. """ + if n <= 2: + raise ValueError( + "Number of fins must be greater than 2." + "If you want to add 2 or 1 fins, create a FreeFormFin object " + " and add it to the rocket using the add_surfaces method." + ) # Modify radius if not given, use rocket radius, otherwise use given. radius = radius if radius is not None else self.radius From 0a0af82670802d888a94318ccc9d46b18c98bb0f Mon Sep 17 00:00:00 2001 From: MateusStano Date: Mon, 21 Apr 2025 19:33:49 +0200 Subject: [PATCH 20/32] Squashed commit of the following: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit c67472556c4659cdfbab7a630c3906fce384af87 Author: Kevin Alcañiz Date: Sat Apr 12 13:40:25 2025 +0200 ENH: Introduce Net Thrust with pressure corrections (#789) * 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 pressure corrections for thrust in SolidMotor The thrust generated by a SolidMotor is now adjusted for the atmospheric pressure. To achieve that, a new attribute, 'vacuum_thrust', has been created. The 'net_thrust' is the result of 'vacuum_thrust' minus the atmospheric pressure multiplied by the nozzle area. * ENH: pylint recommendations done * ENH: net thrust method extended to the rest of the motor classes * BUG: __post_processed_variables inconsistent array * ENH: ruff reformatting * Update rocketpy/motors/motor.py Co-authored-by: Gui-FernandesBR <63590233+Gui-FernandesBR@users.noreply.github.com> * ENH: Avoid breaking change * ENH: Pressure Thrust method added * BUG: call to the thrust function wrong * BUG: pressure thrust evaluated when motor is turned off * ENH: CHANGELOG updated * DOC: definition of exhaust velocity improved --------- Co-authored-by: Gui-FernandesBR <63590233+Gui-FernandesBR@users.noreply.github.com> commit 9f2644a70ea420ec2e581017ed2722aa81751a6e Author: Lucas Prates <57069366+Lucas-Prates@users.noreply.github.com> Date: Sat Apr 12 11:27:53 2025 +0200 ENH: Implement Multivariate Rejection Sampling (MRS) (#738) * ENH: implementing a draft version of the Multivarite Rejectio Sampler (MRS). * MNT: quick notebook to test MRS during development * MNT: refactoring class to match review suggestions * ENH: add comparison prints, plots and ellipses to MonteCarlo and finally checks in MRS * MNT: add MultivariateRejectionSampler class to inits and apply format * DOC: writting .rst documentation for MRS * MNT: adding pylint flags to skip checks * DOC: completing missing sections in mrs.rst * DOC: add changelog and apply sugestions in MRS class * DOC: apply suggestions to the MRS.rst * MNT: use Union instead of | for type hinting since we have to support python3.9 * TST: adding unit and integration tests to MRS * MNT: use pylint flag to fix linter * TST: adding tests to MonteCarlo comparison features * MNT: applying suggestions in .rst, better handling nested variables in MRS and applying linters * MNT: removing TODO comments from monte_carlo_plots * MNT: remove useless TODO * MNT: inserting pragmas for no cover and resolving changelog conflict commit d49c40e75c1817851bacb34ac1666a4585bc4231 Author: ArthurJWH <167456467+ArthurJWH@users.noreply.github.com> Date: Fri Apr 11 16:11:20 2025 -0400 ENH: Create a rocketpy file to store flight simulations (#800) * ENH: added .rpy file functionality (see issue 668) This commit add 'save_to_rpy' and 'load_from_rpy' functions, that allows saving and loading flights. * MNT: adjusting minor changes to .rpy functions and tests. Formatted docstrings correctly. Reverted duplication of `test_encoding.py` files. Version warning will be called when loaded version is more recent. * MNT: incorporating previous comments Change file management from os to Path Adjust docstrings * DOC: Added comment about outputs in `to_dict` method * MNT: Refactoring `RocketPyDecoder` unpacking operation and other small adjustments * DOC: update changelog * STY: formatted according to ruff * MNT: changing `str | Path` operation to support Python 3.9 * MNT: fixed trailing commas on .rpy and added shield against `ruff` formatting .rpy and .json files * MNT: fixing error related to `test_flight_save_load_no_resimulate` When `include_outputs` were set to `True`, it would try to include the additional data into the flight, breaking the test * MNT: fixing a typo and adding comment on test coverage --------- Co-authored-by: Gui-FernandesBR <63590233+Gui-FernandesBR@users.noreply.github.com> commit 6bf70f3ea05b6eafc46c77eda57ce4e6b68defd6 Author: Júlio Machado <85506246+juliomachad0@users.noreply.github.com> Date: Sat Apr 5 15:08:53 2025 -0300 ENH: Support for the RSE file format has been added to the library (#798) * ENH: Support for the RSE file format has been added to the library. The import_rse method in the Abstract Motor class and the load_from_rse_file method in the GenericMotor class are now available. With this update, the library natively supports Rock Sim software data, eliminating the need for users to manually convert motor files. The implementation was based on the import_eng and load_from_eng_file methods, utilizing Python's standard XML library. * ENH: Adding tests to the methods of .rse file treatment. * ENH: fixing mistakes on the method and test file * MNT: Running ruff * MNT: Adding the PR to CHANGELOG.md commit 220bb590b0815a54844435e3d1c60ce4777fe1e1 Merge: 4a41f7ac 4df0b383 Author: Gui-FernandesBR <63590233+Gui-FernandesBR@users.noreply.github.com> Date: Thu Mar 27 06:14:22 2025 -0300 Merge pull request #797 from RocketPy-Team/master Updates develop after 1.9.0 commit 4df0b383c2886c7804b6848bbe5b9cbe612b2cd5 Author: MateusStano <69485049+MateusStano@users.noreply.github.com> Date: Mon Mar 24 17:35:03 2025 +0100 REL: Update version to 1.9.0 (#795) commit 5328d66c6869145ed6c8488b5b72f2f305b67db6 Author: MateusStano <69485049+MateusStano@users.noreply.github.com> Date: Mon Mar 24 13:07:52 2025 +0100 DEP: Remove Pending Deprecations and Add Warnings Where Needed (#794) * DEP: Add deprecation warnings for outdated methods and functions * DEP: Remove deprecated methods for NOAA RUC soundings and power drag plots * DEV: changelog * MNT: ruff * DEP: Update deprecation warning for post_process method to specify removal in v1.10 * MNT: Remove unused imports commit 76fb5ef341832450cb5e0707f0ef78ec5b61fc64 Merge: a4b42c3b 4a41f7ac Author: Gui-FernandesBR <63590233+Gui-FernandesBR@users.noreply.github.com> Date: Sun Mar 23 19:17:16 2025 -0300 Merge pull request #793 from RocketPy-Team/develop DEV: Master to v1.9.0 commit 4a41f7ac12eec669d16b9b0cb4e1659fefc116ec Author: Kevin Alcañiz Date: Sun Mar 23 21:52:51 2025 +0100 ENH: Introduce the StochasticAirBrakes class (#785) * 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 <63590233+Gui-FernandesBR@users.noreply.github.com> * DOC: improve drag curve factor definition in StochasticAirBrakes * ENH: Change assert statement to if Co-authored-by: Gui-FernandesBR <63590233+Gui-FernandesBR@users.noreply.github.com> * DOC: better explanation of __mul__ function Co-authored-by: MateusStano <69485049+MateusStano@users.noreply.github.com> * ENH: delete set_air_brakes function for simplicity * DOC: CHANGELOG file updated --------- Co-authored-by: Gui-FernandesBR <63590233+Gui-FernandesBR@users.noreply.github.com> Co-authored-by: MateusStano <69485049+MateusStano@users.noreply.github.com> commit 90553f52364231b520b9db769e3c2596176e17ac Author: Kevin Alcañiz Date: Sun Mar 23 20:31:50 2025 +0100 ENH: Add Eccentricity to Stochastic Simulations (#792) * 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: more intuitive uniform distribution display in StochasticModel Co-authored-by: MateusStano <69485049+MateusStano@users.noreply.github.com> * ENH: Eccentricities added to the StochasticRocket class A bug has been corrected in Flight class and an enhancement has been performed in the Rocket class as well * BUG: thrust eccentricity bug corrected eccentricity_y was defined by x coordinate and eccentricity_x was defined by y coordinate * BUG: Undo some Rocket class changes * ENH: add eccentricities to StochasticRocket * BUG: fix MonteCarlo eccentricity inputs * ENH: pylint and ruff recommended changes * TST: fix tests with eccentricity --------- Co-authored-by: Gui-FernandesBR commit 73480535d439b837daed397e91ff773d50c954ca Author: Kevin Alcañiz Date: Sun Mar 23 13:49:35 2025 +0100 BUG: fix the wind velocity factors usage and better visualization of uniform distributions in Stochastic Classes (#783) * 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: more intuitive uniform distribution display in StochasticModel Co-authored-by: MateusStano <69485049+MateusStano@users.noreply.github.com> --------- Co-authored-by: MateusStano <69485049+MateusStano@users.noreply.github.com> commit d2f89ba36ef5bc3afaa3d64cc7c3ca2cd5c4bbc7 Author: Leonardo Rosa Date: Fri Mar 21 18:57:49 2025 -0300 DEV: add requirements-tests.txt on make install target (#791) * DEV: adds 'pip install -r requirements-tests.txt' recipe to 'make install' target on Makefile Co-authored-by: Gui-FernandesBR <63590233+Gui-FernandesBR@users.noreply.github.com> commit 91ac567266d20bb74a7f5810f57b708a455a55d0 Author: Leonardo Rosa Date: Fri Mar 21 18:53:53 2025 -0300 BUG: fixes get_instance_attributes for Flight objects containing a Rocket object without rail buttons (#786) * DOC: fixed a typo in funcify_method() description * TST: created test for get_instante_attributes() with flight without rail buttons * BUG: fixed __calculate_rail_button_forces() by assigning a Function(0) to null_force instead of an empty array * DEV: updates CHANGELOG commit 9407470667ba98d89e30a9cc575bf56fb4dbe31d Author: Leonard <74966503+L30-stack@users.noreply.github.com> Date: Wed Mar 19 16:01:59 2025 +0100 BUG: fixed AGL altitude in _FlightPrints.events_registered (#788) * BUG: fixed AGL altitude in _FlightPrints.events_registered * updeted CHANGELOG --- .vscode/settings.json | 4 + CHANGELOG.md | 22 + Makefile | 1 + .../rse_example/rse_motor_example_file.rse | 19 + docs/conf.py | 2 +- .../mrs.errors.txt | 0 .../mrs.inputs.txt | 116 + .../mrs.outputs.txt | 116 + .../classes/MultivariateRejectionSampler.rst | 5 + docs/reference/index.rst | 1 + docs/user/index.rst | 3 +- docs/user/installation.rst | 2 +- docs/user/mrs.rst | 278 + docs/user/sensitivity.rst | 4 +- pyproject.toml | 3 +- rocketpy/__init__.py | 3 +- rocketpy/_encoders.py | 54 +- rocketpy/environment/environment.py | 62 +- rocketpy/environment/fetchers.py | 28 - rocketpy/environment/tools.py | 71 +- rocketpy/mathutils/function.py | 103 +- rocketpy/motors/empty_motor.py | 1 + rocketpy/motors/hybrid_motor.py | 28 +- rocketpy/motors/liquid_motor.py | 24 +- rocketpy/motors/motor.py | 309 +- rocketpy/motors/solid_motor.py | 26 +- rocketpy/plots/monte_carlo_plots.py | 237 + rocketpy/plots/rocket_plots.py | 36 - rocketpy/prints/flight_prints.py | 2 +- rocketpy/prints/monte_carlo_prints.py | 62 + rocketpy/rocket/rocket.py | 30 +- rocketpy/simulation/__init__.py | 1 + rocketpy/simulation/flight.py | 128 +- rocketpy/simulation/monte_carlo.py | 45 + .../multivariate_rejection_sampler.py | 290 + rocketpy/stochastic/__init__.py | 1 + .../stochastic/stochastic_aero_surfaces.py | 112 + rocketpy/stochastic/stochastic_environment.py | 1 + rocketpy/stochastic/stochastic_flight.py | 12 + rocketpy/stochastic/stochastic_model.py | 18 +- rocketpy/stochastic/stochastic_rocket.py | 164 + rocketpy/tools.py | 56 +- rocketpy/utilities.py | 76 +- .../utilities/flight_calisto_robust.rpy | 43419 ++++++++++++++++ tests/integration/test_encoding.py | 48 +- tests/integration/test_monte_carlo.py | 9 + .../test_multivariate_rejection_sampler.py | 45 + tests/unit/test_genericmotor.py | 31 + .../test_multivariate_rejection_sampler.py | 113 + tests/unit/test_rocket.py | 8 +- tests/unit/test_utilities.py | 53 +- 51 files changed, 46024 insertions(+), 258 deletions(-) create mode 100644 data/motors/rse_example/rse_motor_example_file.rse create mode 100644 docs/notebooks/monte_carlo_analysis/monte_carlo_analysis_outputs/mrs.errors.txt create mode 100644 docs/notebooks/monte_carlo_analysis/monte_carlo_analysis_outputs/mrs.inputs.txt create mode 100644 docs/notebooks/monte_carlo_analysis/monte_carlo_analysis_outputs/mrs.outputs.txt create mode 100644 docs/reference/classes/MultivariateRejectionSampler.rst create mode 100644 docs/user/mrs.rst create mode 100644 rocketpy/simulation/multivariate_rejection_sampler.py create mode 100644 tests/fixtures/utilities/flight_calisto_robust.rpy create mode 100644 tests/integration/test_multivariate_rejection_sampler.py create mode 100644 tests/unit/test_multivariate_rejection_sampler.py diff --git a/.vscode/settings.json b/.vscode/settings.json index deed16155..5cd5a878d 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -50,6 +50,8 @@ "bijective", "bmatrix", "boldsymbol", + "boxplot", + "boxplots", "brentq", "Bressan", "bysource", @@ -276,6 +278,7 @@ "savgol", "SBMT", "scilimits", + "scipy", "searchsorted", "seblm", "seealso", @@ -295,6 +298,7 @@ "statsmodels", "STFT", "subintervals", + "supremum", "suptitle", "supxlabel", "supylabel", diff --git a/CHANGELOG.md b/CHANGELOG.md index b2d8908c2..a4b7a9fd2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,11 +32,29 @@ Attention: The newest changes should be on top --> ### Added +- ENH: Implement Multivariate Rejection Sampling (MRS) [#738] (https://github.com/RocketPy-Team/RocketPy/pull/738) +- ENH: Create a rocketpy file to store flight simulations [#800](https://github.com/RocketPy-Team/RocketPy/pull/800) +- ENH: Support for the RSE file format has been added to the library [#798](https://github.com/RocketPy-Team/RocketPy/pull/798) +- ENH: Introduce Net Thrust with pressure corrections [#789](https://github.com/RocketPy-Team/RocketPy/pull/789) + +### Changed + + +### Fixed + + +## v1.9.0 - 2025-03-24 + +### Added + - ENH: Parallel mode for monte-carlo simulations 2 [#768](https://github.com/RocketPy-Team/RocketPy/pull/768) - DOC: ASTRA Flight Example [#770](https://github.com/RocketPy-Team/RocketPy/pull/770) +- ENH: Add Eccentricity to Stochastic Simulations [#792](https://github.com/RocketPy-Team/RocketPy/pull/792) +- ENH: Introduce the StochasticAirBrakes class [#785](https://github.com/RocketPy-Team/RocketPy/pull/785) ### Changed +- DEP: Remove Pending Deprecations and Add Warnings Where Needed [#794](https://github.com/RocketPy-Team/RocketPy/pull/794) - DOCS: reshape docs (closes #659) [#781](https://github.com/RocketPy-Team/RocketPy/pull/781) - MNT: EmptyMotor class inherits from Motor(ABC) [#779](https://github.com/RocketPy-Team/RocketPy/pull/779) @@ -44,6 +62,10 @@ Attention: The newest changes should be on top --> - BUG: do not allow drawing rockets with no aerodynamic surface [#774](https://github.com/RocketPy-Team/RocketPy/pull/774) - BUG: update flight simulation logic to include burn start time [#778](https://github.com/RocketPy-Team/RocketPy/pull/778) +- BUG: fixes get_instance_attributes for Flight objects containing a Rocket object without rail buttons [#786](https://github.com/RocketPy-Team/RocketPy/pull/786) +- BUG: fixed AGL altitude print for parachutes with lag [#788](https://github.com/RocketPy-Team/RocketPy/pull/788) +- BUG: fix the wind velocity factors usage and better visualization of uniform distributions in Stochastic Classes [#783](https://github.com/RocketPy-Team/RocketPy/pull/783) + ## [v1.8.0] - 2025-01-20 diff --git a/Makefile b/Makefile index 0b077d453..8557a08b5 100644 --- a/Makefile +++ b/Makefile @@ -21,6 +21,7 @@ install: $(PYTHON) -m pip install --upgrade pip pip install -r requirements.txt pip install -r requirements-optional.txt + pip install -r requirements-tests.txt pip install -e . format: diff --git a/data/motors/rse_example/rse_motor_example_file.rse b/data/motors/rse_example/rse_motor_example_file.rse new file mode 100644 index 000000000..f934b9f2e --- /dev/null +++ b/data/motors/rse_example/rse_motor_example_file.rse @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + diff --git a/docs/conf.py b/docs/conf.py index cf4d942dc..209a9c810 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -27,7 +27,7 @@ author = "RocketPy Team" # The full version, including alpha/beta/rc tags -release = "1.8.0" +release = "1.9.0" # -- General configuration --------------------------------------------------- diff --git a/docs/notebooks/monte_carlo_analysis/monte_carlo_analysis_outputs/mrs.errors.txt b/docs/notebooks/monte_carlo_analysis/monte_carlo_analysis_outputs/mrs.errors.txt new file mode 100644 index 000000000..e69de29bb diff --git a/docs/notebooks/monte_carlo_analysis/monte_carlo_analysis_outputs/mrs.inputs.txt b/docs/notebooks/monte_carlo_analysis/monte_carlo_analysis_outputs/mrs.inputs.txt new file mode 100644 index 000000000..0d68c2376 --- /dev/null +++ b/docs/notebooks/monte_carlo_analysis/monte_carlo_analysis_outputs/mrs.inputs.txt @@ -0,0 +1,116 @@ +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 6, "radius": 0.06350803185536065, "mass": 15.321391102645253, "I_11_without_motor": 6.321, "I_22_without_motor": 6.318074651079169, "I_33_without_motor": 0.02231558279750141, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.796421153818757, "trigger": 800, "sampling_rate": 105, "lag": 1.2889273678634483, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.9394597068963542, "trigger": "apogee", "sampling_rate": 105, "lag": 1.4863408840421357, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 5051.334409023799, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.032456100097439426, "grain_number": 5, "grain_density": 1791.4919156464077, "grain_outer_radius": 0.03336766084887191, "grain_initial_inner_radius": 0.015859570445466348, "grain_initial_height": 0.11833708900926163, "grain_separation": 0.005520442830446927, "grains_center_of_mass_position": 0.39720688235605084, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.00044613640497872, "throat_radius": 0.010531081211607219, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.255876687441445}], "aerodynamic_surfaces": [{"length": 0.5575481869662148, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.133894177473017]}, {"n": 4, "root_chord": 0.11988155918352632, "tip_chord": 0.05955433102562337, "span": 0.11002328692729561, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.049681091705158]}, {"top_radius": 0.06350056929758974, "bottom_radius": 0.0431795835697226, "length": 0.061288317308863575, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.7011692212916728, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6163152348259862, "upper_button_position": 0.08485398646568665}], "rail_length": 5, "inclination": 84.47045493851068, "heading": 53.19885912092882} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 4, "radius": 0.0634923426395744, "mass": 15.186541205570112, "I_11_without_motor": 6.321, "I_22_without_motor": 6.32969439703265, "I_33_without_motor": 0.031044527733126107, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.101304635322004, "trigger": 800, "sampling_rate": 105, "lag": 1.449152162843732, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.0863326011878054, "trigger": "apogee", "sampling_rate": 105, "lag": 1.5807386414953863, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 6334.120250525818, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03348962524847486, "grain_number": 5, "grain_density": 1767.1073179570512, "grain_outer_radius": 0.032394751101825256, "grain_initial_inner_radius": 0.01504361534472906, "grain_initial_height": 0.12012668656538848, "grain_separation": 0.00515318449366391, "grains_center_of_mass_position": 0.39673404428016396, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.0016859023790911862, "throat_radius": 0.011074908888687778, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.254658376991242}], "aerodynamic_surfaces": [{"length": 0.5578223347296872, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1350307518657035]}, {"n": 4, "root_chord": 0.1203679293308533, "tip_chord": 0.059800875760536006, "span": 0.1091254204553351, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0488985452032389]}, {"top_radius": 0.06453827868465159, "bottom_radius": 0.0431198447535788, "length": 0.05964898322815028, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.7012333719890909, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6173871081166957, "upper_button_position": 0.08384626387239513}], "rail_length": 5, "inclination": 85.13902756092337, "heading": 52.08505981979775} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 16, "radius": 0.0635005371350456, "mass": 15.106582026573095, "I_11_without_motor": 6.321, "I_22_without_motor": 6.314365322306628, "I_33_without_motor": 0.047195635278228606, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.96009910422362, "trigger": 800, "sampling_rate": 105, "lag": 1.5014289998461325, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.928407162356345, "trigger": "apogee", "sampling_rate": 105, "lag": 1.6001609880261682, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 6241.821063933692, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.033005608774528676, "grain_number": 5, "grain_density": 1833.9715498192554, "grain_outer_radius": 0.03303690853285959, "grain_initial_inner_radius": 0.015259991315133756, "grain_initial_height": 0.11921229192845037, "grain_separation": 0.0055318464522216, "grains_center_of_mass_position": 0.3950031401720469, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.0009725665382717565, "throat_radius": 0.011294215263843456, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2545682392417146}], "aerodynamic_surfaces": [{"length": 0.5592118508676353, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1356073437435332]}, {"n": 4, "root_chord": 0.11984775443132953, "tip_chord": 0.05936097203918026, "span": 0.11039507555701751, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0508734335083847]}, {"top_radius": 0.06287906388966444, "bottom_radius": 0.043985985652853866, "length": 0.06067611091499706, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.701079186103225, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6185283287657592, "upper_button_position": 0.0825508573374657}], "rail_length": 5, "inclination": 85.23440818045665, "heading": 54.519967259401874} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 23, "radius": 0.06350088814734572, "mass": 15.687956793335713, "I_11_without_motor": 6.321, "I_22_without_motor": 6.336839789987341, "I_33_without_motor": 0.028988646489893646, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.982092676678759, "trigger": 800, "sampling_rate": 105, "lag": 1.3051455503803195, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.0925632242929975, "trigger": "apogee", "sampling_rate": 105, "lag": 1.33808714514536, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 4726.245950715227, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03359211884417262, "grain_number": 5, "grain_density": 1814.7129649641959, "grain_outer_radius": 0.03357420928819635, "grain_initial_inner_radius": 0.014461406772901576, "grain_initial_height": 0.12103608837837558, "grain_separation": 0.005180186940637563, "grains_center_of_mass_position": 0.3957081975153179, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.002383629196510536, "throat_radius": 0.010547659147086177, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2552427433847064}], "aerodynamic_surfaces": [{"length": 0.5595193024772361, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1330576937993402]}, {"n": 4, "root_chord": 0.1200999445781866, "tip_chord": 0.06118440239649141, "span": 0.11036846785415123, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.050574513578203]}, {"top_radius": 0.06368865651996705, "bottom_radius": 0.044099377434149246, "length": 0.058451866171339795, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6997087894637934, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6195920415929042, "upper_button_position": 0.0801167478708893}], "rail_length": 5, "inclination": 84.97780983300318, "heading": 50.32009850038174} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 27, "radius": 0.06350183797455561, "mass": 15.87574952287981, "I_11_without_motor": 6.321, "I_22_without_motor": 6.303909335567725, "I_33_without_motor": 0.031204515788468067, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.20861081760533, "trigger": 800, "sampling_rate": 105, "lag": 1.4428882238217398, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.8895257753015001, "trigger": "apogee", "sampling_rate": 105, "lag": 1.7685807103946203, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 6885.639331409522, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03250370190056724, "grain_number": 5, "grain_density": 1825.884563566716, "grain_outer_radius": 0.03323824319966411, "grain_initial_inner_radius": 0.014766901006896017, "grain_initial_height": 0.11836322594823653, "grain_separation": 0.005510123299339129, "grains_center_of_mass_position": 0.39653471390971057, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.0012556198042742897, "throat_radius": 0.012334504482416634, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2545173835983094}], "aerodynamic_surfaces": [{"length": 0.5585796710933958, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1331704003460792]}, {"n": 4, "root_chord": 0.1201301284919981, "tip_chord": 0.06021996242563409, "span": 0.10888606828771016, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0471822676170683]}, {"top_radius": 0.06297340635893019, "bottom_radius": 0.04299308970247506, "length": 0.05803218708416568, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.7012526216778054, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.617361647490302, "upper_button_position": 0.08389097418750346}], "rail_length": 5, "inclination": 84.17690533552943, "heading": 53.657314304656595} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 16, "radius": 0.06350252847592282, "mass": 14.554626267873774, "I_11_without_motor": 6.321, "I_22_without_motor": 6.320014393950434, "I_33_without_motor": 0.02978318505834989, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.809099315429796, "trigger": 800, "sampling_rate": 105, "lag": 1.435172682390572, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.9661283642956846, "trigger": "apogee", "sampling_rate": 105, "lag": 1.0908194734007017, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 7627.410184249112, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03181505461373091, "grain_number": 5, "grain_density": 1809.0171892348033, "grain_outer_radius": 0.03330315693468259, "grain_initial_inner_radius": 0.014336431082618886, "grain_initial_height": 0.12006289130189998, "grain_separation": 0.004307751767983378, "grains_center_of_mass_position": 0.39565554582103846, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.00029326744719994076, "throat_radius": 0.011045581586300398, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2550074925862347}], "aerodynamic_surfaces": [{"length": 0.5587374419774356, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1346864242350938]}, {"n": 4, "root_chord": 0.11966494757566067, "tip_chord": 0.06043914775071417, "span": 0.110173410278682, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0482419734272284]}, {"top_radius": 0.06361223404913431, "bottom_radius": 0.04441213943878098, "length": 0.06031094064657681, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.7004638353292927, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.616080438488119, "upper_button_position": 0.08438339684117369}], "rail_length": 5, "inclination": 85.31564942707135, "heading": 51.731722972868745} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 18, "radius": 0.06348749078905755, "mass": 15.274027636681094, "I_11_without_motor": 6.321, "I_22_without_motor": 6.3056411973123305, "I_33_without_motor": 0.026210549348132318, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.889025425866114, "trigger": 800, "sampling_rate": 105, "lag": 1.488251498047699, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.1197674160601925, "trigger": "apogee", "sampling_rate": 105, "lag": 1.368366805211293, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 6592.2157994782465, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03308605707134015, "grain_number": 5, "grain_density": 1796.3751731100065, "grain_outer_radius": 0.03308615810558528, "grain_initial_inner_radius": 0.015317995925855062, "grain_initial_height": 0.1192577099620557, "grain_separation": 0.005308100796681196, "grains_center_of_mass_position": 0.3965821036092778, "center_of_dry_mass_position": 0.317, "nozzle_position": 3.82008057787502e-05, "throat_radius": 0.010918433237017845, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.256142053636198}], "aerodynamic_surfaces": [{"length": 0.5573179150222657, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1354945971977657]}, {"n": 4, "root_chord": 0.12009501983146434, "tip_chord": 0.059321690994762456, "span": 0.10981054208765459, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0493722444849265]}, {"top_radius": 0.0634981444039416, "bottom_radius": 0.0424284557599094, "length": 0.06078217002823246, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6997359937622002, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6167639468311972, "upper_button_position": 0.08297204693100302}], "rail_length": 5, "inclination": 83.25414857033617, "heading": 53.540889403739} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 9, "radius": 0.06349548448024785, "mass": 14.966201991043633, "I_11_without_motor": 6.321, "I_22_without_motor": 6.3326064483970335, "I_33_without_motor": 0.03150658319946799, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.923681695232858, "trigger": 800, "sampling_rate": 105, "lag": 1.5500092224506672, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.0425269447758416, "trigger": "apogee", "sampling_rate": 105, "lag": 1.5510097362665025, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 7273.673730718726, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03343837072141842, "grain_number": 5, "grain_density": 1802.9948737500492, "grain_outer_radius": 0.032391827913907975, "grain_initial_inner_radius": 0.015040686596184153, "grain_initial_height": 0.11842278684319403, "grain_separation": 0.004218582411143555, "grains_center_of_mass_position": 0.397666578233816, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.00155681239484704, "throat_radius": 0.01101023301487878, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.255162688850939}], "aerodynamic_surfaces": [{"length": 0.5586303555434702, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1355819589267528]}, {"n": 4, "root_chord": 0.12006416295694325, "tip_chord": 0.059812409475951275, "span": 0.11019422811314691, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0514202666055863]}, {"top_radius": 0.0622835603023874, "bottom_radius": 0.04417828791537684, "length": 0.05948731109850217, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6970434155886682, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6164912368242462, "upper_button_position": 0.080552178764422}], "rail_length": 5, "inclination": 83.66947889870069, "heading": 53.999814177607014} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 21, "radius": 0.06350599548545227, "mass": 14.972365965586375, "I_11_without_motor": 6.321, "I_22_without_motor": 6.308076402470525, "I_33_without_motor": 0.026971670359626596, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.951804391245139, "trigger": 800, "sampling_rate": 105, "lag": 1.529363112871357, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.0182608330687164, "trigger": "apogee", "sampling_rate": 105, "lag": 1.1716302019327678, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 6157.460989460494, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03306537899577222, "grain_number": 5, "grain_density": 1892.4765185643228, "grain_outer_radius": 0.03291729431647596, "grain_initial_inner_radius": 0.014705999588306696, "grain_initial_height": 0.11984707551286568, "grain_separation": 0.004948410892419892, "grains_center_of_mass_position": 0.39602765568237, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.0005179033351693645, "throat_radius": 0.010687761348175333, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2554098554739306}], "aerodynamic_surfaces": [{"length": 0.5581666823037278, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1356861521267771]}, {"n": 4, "root_chord": 0.120336900983012, "tip_chord": 0.05983761810204665, "span": 0.11006917945884101, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0496412951180254]}, {"top_radius": 0.06483106026898965, "bottom_radius": 0.04532023794256472, "length": 0.06085021269786268, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.7016850030652007, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6172697087884819, "upper_button_position": 0.08441529427671879}], "rail_length": 5, "inclination": 84.68308488633484, "heading": 51.77523923230421} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 21, "radius": 0.06348774454447496, "mass": 14.930117646216331, "I_11_without_motor": 6.321, "I_22_without_motor": 6.312056348648575, "I_33_without_motor": 0.029338448436193622, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.98485567249014, "trigger": 800, "sampling_rate": 105, "lag": 1.5954373224496392, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.0082915348846462, "trigger": "apogee", "sampling_rate": 105, "lag": 1.47611633347176, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 8567.306574357362, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.0327782378599868, "grain_number": 5, "grain_density": 1805.8062893436656, "grain_outer_radius": 0.032660819562014505, "grain_initial_inner_radius": 0.015203542682672516, "grain_initial_height": 0.11834508933300521, "grain_separation": 0.0036608470091045566, "grains_center_of_mass_position": 0.3958983640087799, "center_of_dry_mass_position": 0.317, "nozzle_position": 1.3285822027841874e-05, "throat_radius": 0.011243176236998718, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.254117519523832}], "aerodynamic_surfaces": [{"length": 0.5567992399357332, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1343704811170066]}, {"n": 4, "root_chord": 0.11998896503739298, "tip_chord": 0.06031327043724632, "span": 0.1094885863904161, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0476229917891087]}, {"top_radius": 0.06401958894608005, "bottom_radius": 0.04327245837001616, "length": 0.06104097633057532, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6997379913346332, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6177225623381292, "upper_button_position": 0.08201542899650405}], "rail_length": 5, "inclination": 85.30699486775356, "heading": 49.961788567748044} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 30, "radius": 0.06350385008258067, "mass": 15.233268563553258, "I_11_without_motor": 6.321, "I_22_without_motor": 6.329087167850529, "I_33_without_motor": 0.019504456718513197, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.939743618950054, "trigger": 800, "sampling_rate": 105, "lag": 1.5729841040708499, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.8653356106930932, "trigger": "apogee", "sampling_rate": 105, "lag": 1.642216557896939, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 5652.837999463443, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03378943189234374, "grain_number": 5, "grain_density": 1887.199502396904, "grain_outer_radius": 0.0326500721350551, "grain_initial_inner_radius": 0.01542876557663005, "grain_initial_height": 0.12059714963826691, "grain_separation": 0.005893156331975001, "grains_center_of_mass_position": 0.3981861148392029, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.00022746211311398492, "throat_radius": 0.011621619417894464, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2560763636152479}], "aerodynamic_surfaces": [{"length": 0.5581001546412535, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1352389410492156]}, {"n": 4, "root_chord": 0.12024836395956051, "tip_chord": 0.06039111147883963, "span": 0.10936722291036971, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0489622166018164]}, {"top_radius": 0.06383371019026948, "bottom_radius": 0.04507765530380146, "length": 0.05923486424359505, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6989261396392559, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6200765851969161, "upper_button_position": 0.07884955444233976}], "rail_length": 5, "inclination": 83.29673725804211, "heading": 52.553141024002024} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 22, "radius": 0.06349565124600759, "mass": 15.80901182717842, "I_11_without_motor": 6.321, "I_22_without_motor": 6.324189476209414, "I_33_without_motor": 0.039947492124470727, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.958221119007575, "trigger": 800, "sampling_rate": 105, "lag": 1.4744047976407515, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.9105919500153667, "trigger": "apogee", "sampling_rate": 105, "lag": 1.1715916196282805, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 6940.150669688993, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03221267379186172, "grain_number": 5, "grain_density": 1771.9392395437242, "grain_outer_radius": 0.032362581319129495, "grain_initial_inner_radius": 0.01522597419310009, "grain_initial_height": 0.12093650772482176, "grain_separation": 0.007024323054740163, "grains_center_of_mass_position": 0.3976307814506138, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.0010662703960836852, "throat_radius": 0.011254254446186175, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2558391857674298}], "aerodynamic_surfaces": [{"length": 0.5568948547525631, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1328486955355659]}, {"n": 4, "root_chord": 0.11970888327568459, "tip_chord": 0.06068066606961564, "span": 0.1095553598059544, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0486990002737873]}, {"top_radius": 0.06395363397677654, "bottom_radius": 0.044588547419253624, "length": 0.0606897880405041, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6988706406346304, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6183513975708271, "upper_button_position": 0.08051924306380331}], "rail_length": 5, "inclination": 85.68797172124307, "heading": 53.16551825136375} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 4, "radius": 0.06350899499179277, "mass": 15.547504896775179, "I_11_without_motor": 6.321, "I_22_without_motor": 6.334642042757825, "I_33_without_motor": 0.012290033228777135, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.965775818912215, "trigger": 800, "sampling_rate": 105, "lag": 1.5580775056673257, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.0076034098063498, "trigger": "apogee", "sampling_rate": 105, "lag": 1.436168301289206, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 7108.352414416814, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03408935068456883, "grain_number": 5, "grain_density": 1888.3646315038986, "grain_outer_radius": 0.03316321755418076, "grain_initial_inner_radius": 0.015345322019192812, "grain_initial_height": 0.12005373347344893, "grain_separation": 0.006309995911955411, "grains_center_of_mass_position": 0.3969962721356382, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.0002593571580503328, "throat_radius": 0.011053543382358286, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2552580607650872}], "aerodynamic_surfaces": [{"length": 0.5588978515153908, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.134669887424594]}, {"n": 4, "root_chord": 0.12063048971372142, "tip_chord": 0.06001144236474167, "span": 0.110121263663121, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0492306654166328]}, {"top_radius": 0.06375264410513082, "bottom_radius": 0.0450462087802562, "length": 0.059763517014825386, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6993198115252584, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6189976176735027, "upper_button_position": 0.08032219385175565}], "rail_length": 5, "inclination": 85.25638610051274, "heading": 52.62801172190558} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 28, "radius": 0.0635086339015458, "mass": 15.480732711974316, "I_11_without_motor": 6.321, "I_22_without_motor": 6.326942641019564, "I_33_without_motor": 0.04357144126749683, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.996944982220173, "trigger": 800, "sampling_rate": 105, "lag": 1.5573050954413707, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.9540893919482105, "trigger": "apogee", "sampling_rate": 105, "lag": 1.213746158461936, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 6762.474332967853, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03245268338710385, "grain_number": 5, "grain_density": 1810.768306695723, "grain_outer_radius": 0.0336992446005722, "grain_initial_inner_radius": 0.015133097842216219, "grain_initial_height": 0.12000029467356098, "grain_separation": 0.004548999685899851, "grains_center_of_mass_position": 0.3962068411646316, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.0009074968900681854, "throat_radius": 0.011855513711284862, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.252781428787283}], "aerodynamic_surfaces": [{"length": 0.5588954108142717, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1336391009586577]}, {"n": 4, "root_chord": 0.11999657053978631, "tip_chord": 0.060034451842632744, "span": 0.11025901792606671, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.049919254784959]}, {"top_radius": 0.06479375834815082, "bottom_radius": 0.04418326742878161, "length": 0.0598707720851098, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6996697116885842, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6190084286350575, "upper_button_position": 0.08066128305352671}], "rail_length": 5, "inclination": 85.05121453684197, "heading": 54.38937240796542} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 27, "radius": 0.0635043477159264, "mass": 15.139007646667636, "I_11_without_motor": 6.321, "I_22_without_motor": 6.313732342465589, "I_33_without_motor": 0.03401796380358941, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.971929525597327, "trigger": 800, "sampling_rate": 105, "lag": 1.3189186920948879, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.9755074105279257, "trigger": "apogee", "sampling_rate": 105, "lag": 1.7499170526601382, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 5522.339810570602, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03311023337029737, "grain_number": 5, "grain_density": 1898.1235562309237, "grain_outer_radius": 0.033377804105204134, "grain_initial_inner_radius": 0.014747469710170718, "grain_initial_height": 0.11851728927570118, "grain_separation": 0.004929695472279985, "grains_center_of_mass_position": 0.3944279741142745, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.0020560467133627883, "throat_radius": 0.010647487735169303, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2541893610577874}], "aerodynamic_surfaces": [{"length": 0.5585689307810547, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.133944556696124]}, {"n": 4, "root_chord": 0.12028386479547713, "tip_chord": 0.060567020786275454, "span": 0.11060886948473093, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0500126357605934]}, {"top_radius": 0.06301807675290487, "bottom_radius": 0.043437690975582956, "length": 0.06056615238024632, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.7018789663470041, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6182845446728478, "upper_button_position": 0.08359442167415632}], "rail_length": 5, "inclination": 84.54965927059666, "heading": 54.68977304739376} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 19, "radius": 0.06349697824549427, "mass": 15.370288799482854, "I_11_without_motor": 6.321, "I_22_without_motor": 6.322725272036979, "I_33_without_motor": 0.04013883642345122, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.985841685991362, "trigger": 800, "sampling_rate": 105, "lag": 1.6047483709920678, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.2363284422568923, "trigger": "apogee", "sampling_rate": 105, "lag": 1.2174381731651476, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 7585.868329758809, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03274203701784928, "grain_number": 5, "grain_density": 1846.9500065168859, "grain_outer_radius": 0.032759520817618175, "grain_initial_inner_radius": 0.014724342430986978, "grain_initial_height": 0.11979571660644074, "grain_separation": 0.004488310192820125, "grains_center_of_mass_position": 0.39786905699768566, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.001935999568391242, "throat_radius": 0.010891327190413334, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.254409281174013}], "aerodynamic_surfaces": [{"length": 0.5581338620871945, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1347477159672446]}, {"n": 4, "root_chord": 0.11985959432829377, "tip_chord": 0.06051170989675571, "span": 0.11025899487042218, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.049783054802366]}, {"top_radius": 0.06318094262884065, "bottom_radius": 0.04183814645871406, "length": 0.05912644320343163, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6997077298704728, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6180323749818905, "upper_button_position": 0.08167535488858235}], "rail_length": 5, "inclination": 85.6066627752705, "heading": 52.89161157926526} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 27, "radius": 0.06349651506211391, "mass": 15.891823203043772, "I_11_without_motor": 6.321, "I_22_without_motor": 6.3238260125805015, "I_33_without_motor": 0.035293084130928624, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.219655300685899, "trigger": 800, "sampling_rate": 105, "lag": 1.4474482767323453, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.8004339775665128, "trigger": "apogee", "sampling_rate": 105, "lag": 1.6624804285716261, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 7979.525343319304, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.033176768643920794, "grain_number": 5, "grain_density": 1899.8759391351418, "grain_outer_radius": 0.033089153681433045, "grain_initial_inner_radius": 0.015174750355542256, "grain_initial_height": 0.12047437435239357, "grain_separation": 0.004652308511776028, "grains_center_of_mass_position": 0.396048426735033, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.0010149846598147812, "throat_radius": 0.011634037543367528, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2558247258381754}], "aerodynamic_surfaces": [{"length": 0.5583113920523873, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1333883942224727]}, {"n": 4, "root_chord": 0.11934442433222583, "tip_chord": 0.05951060585610028, "span": 0.11019261818537261, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0503214396087488]}, {"top_radius": 0.0630028918131456, "bottom_radius": 0.044300755825062606, "length": 0.06159695512765601, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.7005190989305117, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6181094291365088, "upper_button_position": 0.08240966979400288}], "rail_length": 5, "inclination": 84.72044828192737, "heading": 53.96906321145176} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 18, "radius": 0.0634995375328335, "mass": 14.728367937532616, "I_11_without_motor": 6.321, "I_22_without_motor": 6.323884535648947, "I_33_without_motor": 0.03476117207556388, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.870703711038196, "trigger": 800, "sampling_rate": 105, "lag": 1.5776251552100067, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.0001128347930888, "trigger": "apogee", "sampling_rate": 105, "lag": 1.5995022249466047, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 6934.719382352425, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03362435858336634, "grain_number": 5, "grain_density": 1778.2421511177895, "grain_outer_radius": 0.03309817433817483, "grain_initial_inner_radius": 0.015036577986059991, "grain_initial_height": 0.12034835463206361, "grain_separation": 0.004437275813535118, "grains_center_of_mass_position": 0.3973236960584773, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.000813718399551168, "throat_radius": 0.010845799939368905, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2568280809125016}], "aerodynamic_surfaces": [{"length": 0.5587371693608433, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.133017893094876]}, {"n": 4, "root_chord": 0.11977837487750152, "tip_chord": 0.05926166484348912, "span": 0.10960434548434023, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0479480678183306]}, {"top_radius": 0.06326535201568326, "bottom_radius": 0.04400312055730409, "length": 0.06003504466296052, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6997684815744579, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6173507612335352, "upper_button_position": 0.08241772034092276}], "rail_length": 5, "inclination": 84.60164184517363, "heading": 54.26530214698211} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 3, "radius": 0.0634911464600429, "mass": 14.486440254831013, "I_11_without_motor": 6.321, "I_22_without_motor": 6.309901364586174, "I_33_without_motor": 0.03398994359036634, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.902362508377069, "trigger": 800, "sampling_rate": 105, "lag": 1.587203958670398, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.1003008274150388, "trigger": "apogee", "sampling_rate": 105, "lag": 1.3128577817989673, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 8023.1051814785305, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.032952391719729315, "grain_number": 5, "grain_density": 1868.3533909345456, "grain_outer_radius": 0.033555825658377225, "grain_initial_inner_radius": 0.015032932532847772, "grain_initial_height": 0.119961274522818, "grain_separation": 0.005646741525968341, "grains_center_of_mass_position": 0.39605226415712946, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.0007565405445721585, "throat_radius": 0.011470072863148368, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.255787232109951}], "aerodynamic_surfaces": [{"length": 0.5599156821783463, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1342425444589466]}, {"n": 4, "root_chord": 0.12029645924677836, "tip_chord": 0.06023974081776295, "span": 0.10957127506725406, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0506742265852562]}, {"top_radius": 0.062339073470403676, "bottom_radius": 0.04399047848735983, "length": 0.059587688129559446, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.7002734900030118, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6183206080184945, "upper_button_position": 0.08195288198451722}], "rail_length": 5, "inclination": 85.62306981474396, "heading": 49.24217302156982} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 1, "radius": 0.06350096760807196, "mass": 15.638435850803534, "I_11_without_motor": 6.321, "I_22_without_motor": 6.320361559471775, "I_33_without_motor": 0.03323712566807844, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.085638405165113, "trigger": 800, "sampling_rate": 105, "lag": 1.6016220198439197, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.0044325958821694, "trigger": "apogee", "sampling_rate": 105, "lag": 1.384787782299288, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 7625.778081997914, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03262183380316639, "grain_number": 5, "grain_density": 1774.7084755302512, "grain_outer_radius": 0.03311379647061855, "grain_initial_inner_radius": 0.01523856734948392, "grain_initial_height": 0.11996990552537733, "grain_separation": 0.004341848603222936, "grains_center_of_mass_position": 0.39674886189897185, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.0008441470235894177, "throat_radius": 0.011324550780740314, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2549056846208548}], "aerodynamic_surfaces": [{"length": 0.5586332641531137, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1329996400090154]}, {"n": 4, "root_chord": 0.12072203449331113, "tip_chord": 0.06099839068749964, "span": 0.11053328992356606, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0501774328973257]}, {"top_radius": 0.06363371424423879, "bottom_radius": 0.04366426886960126, "length": 0.061147693966520394, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.7009829600788254, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6172382130414615, "upper_button_position": 0.0837447470373639}], "rail_length": 5, "inclination": 84.19052469712635, "heading": 50.03677113199436} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 17, "radius": 0.06349197680662393, "mass": 15.428411257414771, "I_11_without_motor": 6.321, "I_22_without_motor": 6.32483064604844, "I_33_without_motor": 0.02723935117940278, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.155439419564885, "trigger": 800, "sampling_rate": 105, "lag": 1.3395248648567373, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.9258740205169921, "trigger": "apogee", "sampling_rate": 105, "lag": 1.145219260228675, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 6774.538140235507, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03234589541551225, "grain_number": 5, "grain_density": 1800.8846322064876, "grain_outer_radius": 0.03283234378818839, "grain_initial_inner_radius": 0.014820380559815506, "grain_initial_height": 0.11953657507627105, "grain_separation": 0.005914069343044977, "grains_center_of_mass_position": 0.3967095425406527, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.0008366960006455244, "throat_radius": 0.011333928938224705, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.254233414700003}], "aerodynamic_surfaces": [{"length": 0.5576124396090942, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1329124876166934]}, {"n": 4, "root_chord": 0.12018778583366128, "tip_chord": 0.05880483254677678, "span": 0.10986742385701066, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0488456853783297]}, {"top_radius": 0.06277404284735084, "bottom_radius": 0.043564867573667246, "length": 0.059618155707470026, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.7010212376271764, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.616915825819793, "upper_button_position": 0.0841054118073834}], "rail_length": 5, "inclination": 85.72524446775732, "heading": 53.20971553322554} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 6, "radius": 0.06348857400194761, "mass": 14.611951499242362, "I_11_without_motor": 6.321, "I_22_without_motor": 6.327748122824438, "I_33_without_motor": 0.044872656150962614, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.979455972026859, "trigger": 800, "sampling_rate": 105, "lag": 1.4259687443485651, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.0016762681530027, "trigger": "apogee", "sampling_rate": 105, "lag": 1.2599870953114656, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 5723.206261655799, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03241553176806094, "grain_number": 5, "grain_density": 1818.9573886954888, "grain_outer_radius": 0.03268732649737654, "grain_initial_inner_radius": 0.014628356892783188, "grain_initial_height": 0.11960726874545195, "grain_separation": 0.005384153215000254, "grains_center_of_mass_position": 0.39661697354289926, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.0004737538387335993, "throat_radius": 0.011461519640227765, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2555089893235123}], "aerodynamic_surfaces": [{"length": 0.5570131217094269, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1333189711244893]}, {"n": 4, "root_chord": 0.1197016097259282, "tip_chord": 0.05924772317167854, "span": 0.10929674073287446, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0480820503417594]}, {"top_radius": 0.06314511953677157, "bottom_radius": 0.044957525988095264, "length": 0.060779192455191054, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6999878117942848, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6173926643236608, "upper_button_position": 0.08259514747062402}], "rail_length": 5, "inclination": 85.81067628452577, "heading": 51.76674272786484} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 2, "radius": 0.06349747208414004, "mass": 16.12450150650205, "I_11_without_motor": 6.321, "I_22_without_motor": 6.318305741468311, "I_33_without_motor": 0.042994744781765744, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.018966993257663, "trigger": 800, "sampling_rate": 105, "lag": 1.4752410120145523, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.0322100567242984, "trigger": "apogee", "sampling_rate": 105, "lag": 1.675019930852068, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 6185.391700744513, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03306044843614433, "grain_number": 5, "grain_density": 1756.1606934870154, "grain_outer_radius": 0.0328368590658428, "grain_initial_inner_radius": 0.014947749952674096, "grain_initial_height": 0.12041452728610347, "grain_separation": 0.005752269536842135, "grains_center_of_mass_position": 0.39562678337841595, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.0012908975147282852, "throat_radius": 0.010579189149364553, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2548141108817714}], "aerodynamic_surfaces": [{"length": 0.557550329532748, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.134437002436943]}, {"n": 4, "root_chord": 0.12001041814320897, "tip_chord": 0.06004816347996898, "span": 0.11028168672799134, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0506721427266907]}, {"top_radius": 0.06505881505156542, "bottom_radius": 0.04368838713692011, "length": 0.059246089428340885, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.7000804856892673, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6175550504489563, "upper_button_position": 0.08252543524031097}], "rail_length": 5, "inclination": 87.15758192127657, "heading": 52.26119546253493} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 10, "radius": 0.06349552376377463, "mass": 15.350885147374614, "I_11_without_motor": 6.321, "I_22_without_motor": 6.320598487591626, "I_33_without_motor": 0.027179385251218935, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.023377756531493, "trigger": 800, "sampling_rate": 105, "lag": 1.5087962332491123, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.989500749130062, "trigger": "apogee", "sampling_rate": 105, "lag": 1.2132040809107247, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 5556.662759629915, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03287256576417531, "grain_number": 5, "grain_density": 1848.3895227297855, "grain_outer_radius": 0.03239593788185526, "grain_initial_inner_radius": 0.014746024060225535, "grain_initial_height": 0.12089118209590469, "grain_separation": 0.005117139105550911, "grains_center_of_mass_position": 0.3960083879734055, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.0005231988164810428, "throat_radius": 0.011339794184151857, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.253820549043234}], "aerodynamic_surfaces": [{"length": 0.5579377234017414, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1342408227410292]}, {"n": 4, "root_chord": 0.12051475985943909, "tip_chord": 0.06091681182321002, "span": 0.11029784432365072, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0502407345389377]}, {"top_radius": 0.0663001633273378, "bottom_radius": 0.04436989802317084, "length": 0.059017924090161676, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6978344181881884, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6182786393436883, "upper_button_position": 0.07955577884450005}], "rail_length": 5, "inclination": 84.977737831712, "heading": 50.69292411737485} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 28, "radius": 0.06349796843796719, "mass": 15.491905617365733, "I_11_without_motor": 6.321, "I_22_without_motor": 6.318530013451749, "I_33_without_motor": 0.015281088244617286, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.068992583007631, "trigger": 800, "sampling_rate": 105, "lag": 1.5175927398734939, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.027203409764987, "trigger": "apogee", "sampling_rate": 105, "lag": 1.6155101471429494, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 6625.549104863241, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.0329948949040469, "grain_number": 5, "grain_density": 1829.597728711299, "grain_outer_radius": 0.033284672224308864, "grain_initial_inner_radius": 0.015948902216040967, "grain_initial_height": 0.11883594776697178, "grain_separation": 0.005833559448851904, "grains_center_of_mass_position": 0.3979306534482448, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.0002829617594964633, "throat_radius": 0.010985140272938367, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2548144244413326}], "aerodynamic_surfaces": [{"length": 0.5571676937006194, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1343202243003896]}, {"n": 4, "root_chord": 0.1204072085193961, "tip_chord": 0.059907492479558164, "span": 0.10957089277071845, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0485292012470917]}, {"top_radius": 0.06345021024013636, "bottom_radius": 0.04507416542514857, "length": 0.06006196088748484, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6993967222533961, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6170001205301586, "upper_button_position": 0.08239660172323748}], "rail_length": 5, "inclination": 84.6766425128631, "heading": 54.34109899681687} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 15, "radius": 0.0634984098346836, "mass": 15.71839673894584, "I_11_without_motor": 6.321, "I_22_without_motor": 6.31976756592214, "I_33_without_motor": 0.032842114898029295, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.905706476854565, "trigger": 800, "sampling_rate": 105, "lag": 1.3616764480324317, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.040432074086954, "trigger": "apogee", "sampling_rate": 105, "lag": 1.2254733943108183, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 5194.14996115482, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.033938474135009104, "grain_number": 5, "grain_density": 1725.4074142048564, "grain_outer_radius": 0.033142562783315455, "grain_initial_inner_radius": 0.014930287960728724, "grain_initial_height": 0.11970306899743223, "grain_separation": 0.00482149925675901, "grains_center_of_mass_position": 0.39814088875732373, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.0010017713498807067, "throat_radius": 0.010435398004827488, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.256336924363288}], "aerodynamic_surfaces": [{"length": 0.5579693203961481, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1324781298725939]}, {"n": 4, "root_chord": 0.12000079489283769, "tip_chord": 0.06001557644450443, "span": 0.10857596284015132, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0476748328327194]}, {"top_radius": 0.0639354375404682, "bottom_radius": 0.043888253802334506, "length": 0.059877434458983206, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.7007992651069247, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6163671845842055, "upper_button_position": 0.08443208052271922}], "rail_length": 5, "inclination": 83.6228346823337, "heading": 54.226610976778666} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 19, "radius": 0.06350744991481777, "mass": 14.405012223816323, "I_11_without_motor": 6.321, "I_22_without_motor": 6.33904387322666, "I_33_without_motor": 0.03907642168563871, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.04220167954604, "trigger": 800, "sampling_rate": 105, "lag": 1.385065031792861, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.0141983266247385, "trigger": "apogee", "sampling_rate": 105, "lag": 1.2421452168092624, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 7534.161222384006, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03217593414103991, "grain_number": 5, "grain_density": 1765.8875058571182, "grain_outer_radius": 0.03305351920715771, "grain_initial_inner_radius": 0.014279974938862803, "grain_initial_height": 0.12164485394886902, "grain_separation": 0.0048662704197269995, "grains_center_of_mass_position": 0.39523790030746314, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.0012617347579600676, "throat_radius": 0.01026971772511827, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2544778748627048}], "aerodynamic_surfaces": [{"length": 0.5571174658949877, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.134024729870558]}, {"n": 4, "root_chord": 0.12009943831411411, "tip_chord": 0.05929962278679848, "span": 0.11008494595823437, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.051156776488256]}, {"top_radius": 0.06303461302295726, "bottom_radius": 0.04390532613115884, "length": 0.0604568423481011, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.7002313903506101, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6164664126394285, "upper_button_position": 0.08376497771118163}], "rail_length": 5, "inclination": 85.96902861263881, "heading": 50.879864425972805} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 26, "radius": 0.06349452817007356, "mass": 15.041824059989539, "I_11_without_motor": 6.321, "I_22_without_motor": 6.32654964707118, "I_33_without_motor": 0.02576756458062284, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.984470415994345, "trigger": 800, "sampling_rate": 105, "lag": 1.4333412448604037, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.0424976306619997, "trigger": "apogee", "sampling_rate": 105, "lag": 1.4390221191332053, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 7740.346298202308, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03284342015615792, "grain_number": 5, "grain_density": 1785.436442510045, "grain_outer_radius": 0.03314852143501804, "grain_initial_inner_radius": 0.015393826504827186, "grain_initial_height": 0.12097497598830302, "grain_separation": 0.0029458341255568497, "grains_center_of_mass_position": 0.39730929858318426, "center_of_dry_mass_position": 0.317, "nozzle_position": 7.120474831156798e-05, "throat_radius": 0.011649789002983097, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2536650913196674}], "aerodynamic_surfaces": [{"length": 0.5589237622313102, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.135965790384511]}, {"n": 4, "root_chord": 0.1191775614739399, "tip_chord": 0.05978513441615296, "span": 0.11001345345569484, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0508045609573164]}, {"top_radius": 0.06371634737458537, "bottom_radius": 0.0440860135655003, "length": 0.061956448273616176, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.7005999463551792, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6179054366752573, "upper_button_position": 0.08269450967992187}], "rail_length": 5, "inclination": 82.6520638353218, "heading": 55.48456084779803} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 0, "radius": 0.06350212359874853, "mass": 14.703787727470099, "I_11_without_motor": 6.321, "I_22_without_motor": 6.329468408696411, "I_33_without_motor": 0.029887243179465277, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.015770044517405, "trigger": 800, "sampling_rate": 105, "lag": 1.4538610328057946, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.043705362455051, "trigger": "apogee", "sampling_rate": 105, "lag": 1.306953523971075, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 5470.520384202627, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.0329890205403627, "grain_number": 5, "grain_density": 1922.4194471126045, "grain_outer_radius": 0.032981466844699305, "grain_initial_inner_radius": 0.014285910878932974, "grain_initial_height": 0.12191458411302673, "grain_separation": 0.003822570077215733, "grains_center_of_mass_position": 0.39598945633162497, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.0022380488266456047, "throat_radius": 0.010023639050620198, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2553889492496562}], "aerodynamic_surfaces": [{"length": 0.5593544822892821, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1366275398877876]}, {"n": 4, "root_chord": 0.12006093090519347, "tip_chord": 0.06039452509576055, "span": 0.11065664264447529, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.049504086603735]}, {"top_radius": 0.06440857181801984, "bottom_radius": 0.044409531537504, "length": 0.059597104398322276, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6999338308832991, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.617289777285979, "upper_button_position": 0.08264405359732008}], "rail_length": 5, "inclination": 83.84850385369688, "heading": 49.828245638590715} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 1, "radius": 0.06349674560284929, "mass": 14.921816347237218, "I_11_without_motor": 6.321, "I_22_without_motor": 6.330364977651946, "I_33_without_motor": 0.032619758817294744, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.058257398709138, "trigger": 800, "sampling_rate": 105, "lag": 1.5652744069822428, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.0084128327644075, "trigger": "apogee", "sampling_rate": 105, "lag": 1.461733451530952, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 4681.446973533048, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03293366287913037, "grain_number": 5, "grain_density": 1832.1473819180446, "grain_outer_radius": 0.033394850177693634, "grain_initial_inner_radius": 0.014569446636452425, "grain_initial_height": 0.12012630522788963, "grain_separation": 0.007461080867009645, "grains_center_of_mass_position": 0.39784298410036856, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.00012727371931139028, "throat_radius": 0.012577174911559772, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2537768919128724}], "aerodynamic_surfaces": [{"length": 0.5579890842749892, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1341779982779734]}, {"n": 4, "root_chord": 0.11946637495644881, "tip_chord": 0.060460413810812574, "span": 0.10980824436420111, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0489653601877569]}, {"top_radius": 0.0627489871147417, "bottom_radius": 0.04404477419356129, "length": 0.05802139383715877, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6992017032258433, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6179338816808166, "upper_button_position": 0.08126782154502665}], "rail_length": 5, "inclination": 85.06875061582517, "heading": 53.176458342516334} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 29, "radius": 0.06349516449101554, "mass": 14.833840746517417, "I_11_without_motor": 6.321, "I_22_without_motor": 6.3142703122309145, "I_33_without_motor": 0.03461941854094872, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.053710122042567, "trigger": 800, "sampling_rate": 105, "lag": 1.5197605893524615, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.062545788595652, "trigger": "apogee", "sampling_rate": 105, "lag": 1.3594285434007936, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 6088.904205195488, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03245313023588548, "grain_number": 5, "grain_density": 1854.296259474287, "grain_outer_radius": 0.03286480455403395, "grain_initial_inner_radius": 0.014503780495382514, "grain_initial_height": 0.11947357100098997, "grain_separation": 0.003133930859190696, "grains_center_of_mass_position": 0.39648364263343683, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.0001296773138576464, "throat_radius": 0.011046956113245993, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2541415291483216}], "aerodynamic_surfaces": [{"length": 0.5596273762939828, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1321710784318435]}, {"n": 4, "root_chord": 0.12013341414087628, "tip_chord": 0.05923749531249958, "span": 0.10966388837772555, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0500007070074222]}, {"top_radius": 0.0651768776139173, "bottom_radius": 0.042016219977453056, "length": 0.05805909141673695, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6995281554288816, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6171102171102731, "upper_button_position": 0.08241793831860844}], "rail_length": 5, "inclination": 83.71033709304348, "heading": 53.79686658514623} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 16, "radius": 0.06348609830297611, "mass": 15.775564448927595, "I_11_without_motor": 6.321, "I_22_without_motor": 6.311697128138629, "I_33_without_motor": 0.045649186904574694, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.094384024854044, "trigger": 800, "sampling_rate": 105, "lag": 1.489234116391569, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.8903179875269849, "trigger": "apogee", "sampling_rate": 105, "lag": 1.2553618971322373, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 6826.105778724529, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.033518227819183836, "grain_number": 5, "grain_density": 1764.8165276773004, "grain_outer_radius": 0.03234977843965594, "grain_initial_inner_radius": 0.015292612903080921, "grain_initial_height": 0.12106983248147343, "grain_separation": 0.005706491772334038, "grains_center_of_mass_position": 0.3968010685051293, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.0012496435746191673, "throat_radius": 0.01067392938637024, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2555278148744777}], "aerodynamic_surfaces": [{"length": 0.5581739741447609, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1332158666233283]}, {"n": 4, "root_chord": 0.11957048513459026, "tip_chord": 0.06012621464950515, "span": 0.1104251435782624, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0513086459368413]}, {"top_radius": 0.06472259572820216, "bottom_radius": 0.043192920721482765, "length": 0.06017554020689808, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6995774476947385, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6180401618409889, "upper_button_position": 0.08153728585374964}], "rail_length": 5, "inclination": 84.60602142368998, "heading": 52.97926948901963} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 18, "radius": 0.06349911277736629, "mass": 15.502733930846519, "I_11_without_motor": 6.321, "I_22_without_motor": 6.326651378692527, "I_33_without_motor": 0.04719271131463472, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.030032993506115, "trigger": 800, "sampling_rate": 105, "lag": 1.3409979175873636, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.8798019044434237, "trigger": "apogee", "sampling_rate": 105, "lag": 1.970590126901424, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 6181.788048396556, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03255425294956757, "grain_number": 5, "grain_density": 1775.332205041046, "grain_outer_radius": 0.0331885797221139, "grain_initial_inner_radius": 0.015686918950381632, "grain_initial_height": 0.11996923072029957, "grain_separation": 0.0060016785603118974, "grains_center_of_mass_position": 0.397186664906841, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.00010955905834264899, "throat_radius": 0.011862038142008058, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2545253016050688}], "aerodynamic_surfaces": [{"length": 0.5566816705137342, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.132347863080437]}, {"n": 4, "root_chord": 0.11961634492464189, "tip_chord": 0.06017996779860779, "span": 0.11017748689317333, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0503160764660022]}, {"top_radius": 0.06379244854711358, "bottom_radius": 0.04285932400432567, "length": 0.059823150807485334, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.701011879289094, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6182648629356197, "upper_button_position": 0.08274701635347437}], "rail_length": 5, "inclination": 84.7223994695584, "heading": 50.63343084700375} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 3, "radius": 0.06349578711094504, "mass": 14.733005311557188, "I_11_without_motor": 6.321, "I_22_without_motor": 6.32186632400748, "I_33_without_motor": 0.030005413235617225, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.84072080079831, "trigger": 800, "sampling_rate": 105, "lag": 1.6016760044719902, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.0599440405506435, "trigger": "apogee", "sampling_rate": 105, "lag": 1.3246704961118614, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 6327.116014098299, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03341605282322616, "grain_number": 5, "grain_density": 1946.843122881012, "grain_outer_radius": 0.032849748327516505, "grain_initial_inner_radius": 0.014452995102544403, "grain_initial_height": 0.1198178101325956, "grain_separation": 0.005897453340079971, "grains_center_of_mass_position": 0.3974497383545063, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.0005660175898307726, "throat_radius": 0.0107788242114465, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2539751123411864}], "aerodynamic_surfaces": [{"length": 0.5595352722966735, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1339874584239653]}, {"n": 4, "root_chord": 0.12027984681343187, "tip_chord": 0.060010911990266966, "span": 0.10994620993010913, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0479461024543613]}, {"top_radius": 0.06434838044418614, "bottom_radius": 0.044868816644973525, "length": 0.0579134168068263, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.699720106120432, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6173316485926563, "upper_button_position": 0.08238845752777568}], "rail_length": 5, "inclination": 84.27227233651884, "heading": 54.734579458852366} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 11, "radius": 0.06348978331678039, "mass": 14.530071275062346, "I_11_without_motor": 6.321, "I_22_without_motor": 6.313601515804047, "I_33_without_motor": 0.035811282864768305, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.06451765879675, "trigger": 800, "sampling_rate": 105, "lag": 1.5667731193590384, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.0629388862215743, "trigger": "apogee", "sampling_rate": 105, "lag": 1.210409830920679, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 6421.641366442464, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03302713139904139, "grain_number": 5, "grain_density": 1801.3659471351789, "grain_outer_radius": 0.032581448844778135, "grain_initial_inner_radius": 0.01566596274225949, "grain_initial_height": 0.12022367000122891, "grain_separation": 0.004163827667550902, "grains_center_of_mass_position": 0.3972738765128864, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.00023026118927236877, "throat_radius": 0.011252346882402394, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2543600038658234}], "aerodynamic_surfaces": [{"length": 0.5593454471233844, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1337584372554539]}, {"n": 4, "root_chord": 0.11983005579448518, "tip_chord": 0.06038344945789773, "span": 0.10998277607273156, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.048457046745924]}, {"top_radius": 0.06205196560076307, "bottom_radius": 0.04322908211811743, "length": 0.05975893645128083, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.7004254705935747, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.618256876505575, "upper_button_position": 0.0821685940879997}], "rail_length": 5, "inclination": 84.99725100723349, "heading": 55.37129030903806} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 20, "radius": 0.06349965671923972, "mass": 15.187653403269254, "I_11_without_motor": 6.321, "I_22_without_motor": 6.314893773590578, "I_33_without_motor": 0.031067759776396867, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.924283528979045, "trigger": 800, "sampling_rate": 105, "lag": 1.4716672756509848, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.0179154571210376, "trigger": "apogee", "sampling_rate": 105, "lag": 1.4215560721460743, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 7331.311831434599, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.033032316941278804, "grain_number": 5, "grain_density": 1805.6811676031355, "grain_outer_radius": 0.03268780803353489, "grain_initial_inner_radius": 0.01533792025006647, "grain_initial_height": 0.11889057340767889, "grain_separation": 0.004944929794747339, "grains_center_of_mass_position": 0.39730622834128204, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.0004659840793624343, "throat_radius": 0.011285767541353475, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2570814649558104}], "aerodynamic_surfaces": [{"length": 0.556492208902252, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.135266253355802]}, {"n": 4, "root_chord": 0.11965598181056666, "tip_chord": 0.05985849455847514, "span": 0.11030262925104403, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0513234617976697]}, {"top_radius": 0.06306605778844096, "bottom_radius": 0.04381822534243298, "length": 0.060974249395334336, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6995913842047234, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6186179995290487, "upper_button_position": 0.08097338467567472}], "rail_length": 5, "inclination": 84.33274551001128, "heading": 48.2533802733674} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 9, "radius": 0.06350451524598685, "mass": 14.206096706406463, "I_11_without_motor": 6.321, "I_22_without_motor": 6.302903234647802, "I_33_without_motor": 0.027289553649598498, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.10326633095759, "trigger": 800, "sampling_rate": 105, "lag": 1.6724589857307486, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.176485433527294, "trigger": "apogee", "sampling_rate": 105, "lag": 1.5587795846603474, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 7178.31446779074, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.032694635597417476, "grain_number": 5, "grain_density": 1791.4300327399603, "grain_outer_radius": 0.03260703977654995, "grain_initial_inner_radius": 0.015178454149511491, "grain_initial_height": 0.1197948700125519, "grain_separation": 0.004455244112382221, "grains_center_of_mass_position": 0.3974725503479587, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.00015499443668369188, "throat_radius": 0.01146408370053178, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.257050613454498}], "aerodynamic_surfaces": [{"length": 0.5587607868505936, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1350135134423711]}, {"n": 4, "root_chord": 0.12059540677490324, "tip_chord": 0.05911810336122107, "span": 0.11029067795008576, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0498539997583487]}, {"top_radius": 0.06326578476354046, "bottom_radius": 0.04164927112867691, "length": 0.06079821849094003, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.7010310806352795, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6182675032517331, "upper_button_position": 0.08276357738354645}], "rail_length": 5, "inclination": 85.5645567575092, "heading": 50.12029975816826} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 18, "radius": 0.06349908754612475, "mass": 15.091281944132664, "I_11_without_motor": 6.321, "I_22_without_motor": 6.304871783946793, "I_33_without_motor": 0.028929571194958655, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.181069516880273, "trigger": 800, "sampling_rate": 105, "lag": 1.4465220138957302, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.0144764716954844, "trigger": "apogee", "sampling_rate": 105, "lag": 1.4773827685037202, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 4815.692857511716, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03276328796422462, "grain_number": 5, "grain_density": 1791.3739829419535, "grain_outer_radius": 0.03279999963439643, "grain_initial_inner_radius": 0.014835688785209347, "grain_initial_height": 0.1216240133991025, "grain_separation": 0.003073911865494121, "grains_center_of_mass_position": 0.39738065353557717, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.001383031679060434, "throat_radius": 0.011371548247390562, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.254434870772941}], "aerodynamic_surfaces": [{"length": 0.5578227710459531, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1344666286817606]}, {"n": 4, "root_chord": 0.11992247200543255, "tip_chord": 0.05942046615597525, "span": 0.11112684328812697, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0518680748999483]}, {"top_radius": 0.061494913940682946, "bottom_radius": 0.0418688620143952, "length": 0.057582314581009195, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.7006283567074604, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.615974860680944, "upper_button_position": 0.0846534960265164}], "rail_length": 5, "inclination": 83.32373734403978, "heading": 55.08948249534396} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 30, "radius": 0.0634993463075142, "mass": 14.801489078859, "I_11_without_motor": 6.321, "I_22_without_motor": 6.324861099285096, "I_33_without_motor": 0.031109938973260434, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.131106978975996, "trigger": 800, "sampling_rate": 105, "lag": 1.5799744945969683, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.033735142695526, "trigger": "apogee", "sampling_rate": 105, "lag": 1.6543321946896454, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 8194.25490069113, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03358797333700211, "grain_number": 5, "grain_density": 1832.8641859651325, "grain_outer_radius": 0.03326344967206518, "grain_initial_inner_radius": 0.014098944811000932, "grain_initial_height": 0.12056686125015023, "grain_separation": 0.00570916237729603, "grains_center_of_mass_position": 0.3975068355913086, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.00023748485345140427, "throat_radius": 0.011612784529061521, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.254036338416369}], "aerodynamic_surfaces": [{"length": 0.5591181484273685, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.134779288594393]}, {"n": 4, "root_chord": 0.11988516560589539, "tip_chord": 0.05984845512026722, "span": 0.10994789943873662, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0491091332295586]}, {"top_radius": 0.06457986434114686, "bottom_radius": 0.04520688148562775, "length": 0.05982051987933152, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6996412589648757, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6166618899414311, "upper_button_position": 0.0829793690234446}], "rail_length": 5, "inclination": 83.17748614864853, "heading": 50.80850509012273} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 18, "radius": 0.06349894169482198, "mass": 14.099064560280109, "I_11_without_motor": 6.321, "I_22_without_motor": 6.325013947970892, "I_33_without_motor": 0.03359814458900968, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.11334344556086, "trigger": 800, "sampling_rate": 105, "lag": 1.3675341328282251, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.0733939042455976, "trigger": "apogee", "sampling_rate": 105, "lag": 1.6287763043908137, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 7268.554431573363, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.033697889530363546, "grain_number": 5, "grain_density": 1926.1559879046883, "grain_outer_radius": 0.03264644740351762, "grain_initial_inner_radius": 0.014555931117282516, "grain_initial_height": 0.12068404386011491, "grain_separation": 0.00587470076016869, "grains_center_of_mass_position": 0.39532087387284237, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.0012756829386657664, "throat_radius": 0.011195281240663895, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2548296364212677}], "aerodynamic_surfaces": [{"length": 0.5584698107801568, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1348748623104554]}, {"n": 4, "root_chord": 0.12008562247079292, "tip_chord": 0.05938993226103333, "span": 0.10930797507563358, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0485908426349064]}, {"top_radius": 0.06372732646101763, "bottom_radius": 0.04333300868974996, "length": 0.061564305891335415, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6995502472027316, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6177815424909302, "upper_button_position": 0.08176870471180142}], "rail_length": 5, "inclination": 84.21686114545088, "heading": 51.596048360514224} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 21, "radius": 0.06350752038759941, "mass": 14.568592009759945, "I_11_without_motor": 6.321, "I_22_without_motor": 6.315703493536244, "I_33_without_motor": 0.04874128267366165, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.130522658569157, "trigger": 800, "sampling_rate": 105, "lag": 1.539809921052573, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.0426413035746167, "trigger": "apogee", "sampling_rate": 105, "lag": 1.5273967090900389, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 6823.002889414789, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03303055807264287, "grain_number": 5, "grain_density": 1856.9222859046567, "grain_outer_radius": 0.033062772691915564, "grain_initial_inner_radius": 0.014875188201429109, "grain_initial_height": 0.1191905529449992, "grain_separation": 0.004920553384972976, "grains_center_of_mass_position": 0.3951012114148818, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.0010643224349669294, "throat_radius": 0.011214346660564973, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2547733597296076}], "aerodynamic_surfaces": [{"length": 0.5587112069523473, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1322708251074562]}, {"n": 4, "root_chord": 0.12051615333197606, "tip_chord": 0.05965719359384979, "span": 0.1096619396945581, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0479092572793969]}, {"top_radius": 0.06330154215849293, "bottom_radius": 0.04303753924479578, "length": 0.059327294653763275, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6993630621332422, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6200970979521905, "upper_button_position": 0.0792659641810517}], "rail_length": 5, "inclination": 84.06076886892694, "heading": 54.77162126651408} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 16, "radius": 0.06352316457496157, "mass": 15.728235309957261, "I_11_without_motor": 6.321, "I_22_without_motor": 6.322592435295867, "I_33_without_motor": 0.042937380941228204, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.274660216759411, "trigger": 800, "sampling_rate": 105, "lag": 1.5317353953288444, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.0302164531184763, "trigger": "apogee", "sampling_rate": 105, "lag": 1.6075514119576728, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 7080.060307716018, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03265967553888556, "grain_number": 5, "grain_density": 1819.941579898169, "grain_outer_radius": 0.03301592231597936, "grain_initial_inner_radius": 0.015656125802250925, "grain_initial_height": 0.11842622294982127, "grain_separation": 0.005657492725928914, "grains_center_of_mass_position": 0.39762298212080105, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.0004209493104482007, "throat_radius": 0.011708112046648424, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2544959176060508}], "aerodynamic_surfaces": [{"length": 0.5562321768144465, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1351132308363574]}, {"n": 4, "root_chord": 0.11933898597818884, "tip_chord": 0.05962949872173691, "span": 0.11019436958753759, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0479789377327593]}, {"top_radius": 0.06330532157130539, "bottom_radius": 0.04347520056837399, "length": 0.06062141499978299, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6984570518175143, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6165578795743236, "upper_button_position": 0.08189917224319065}], "rail_length": 5, "inclination": 83.8587565579397, "heading": 51.47542529528003} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 29, "radius": 0.06349766810532545, "mass": 14.656848343367603, "I_11_without_motor": 6.321, "I_22_without_motor": 6.307533288706822, "I_33_without_motor": 0.0318613781097265, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.08296936874009, "trigger": 800, "sampling_rate": 105, "lag": 1.5510165049063207, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.9102018275944145, "trigger": "apogee", "sampling_rate": 105, "lag": 1.5079222294473764, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 6885.096545351595, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03317257384851179, "grain_number": 5, "grain_density": 1840.3883692737118, "grain_outer_radius": 0.033348276571029255, "grain_initial_inner_radius": 0.015137371711569736, "grain_initial_height": 0.12032926296403364, "grain_separation": 0.006373605519429962, "grains_center_of_mass_position": 0.3975640018621129, "center_of_dry_mass_position": 0.317, "nozzle_position": 2.9822997766785866e-05, "throat_radius": 0.01111248000203877, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2523204155315593}], "aerodynamic_surfaces": [{"length": 0.5579542546555215, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1332210247093493]}, {"n": 4, "root_chord": 0.11974443237947338, "tip_chord": 0.059386130897948655, "span": 0.11038000090045949, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0499885287780564]}, {"top_radius": 0.06403444615056623, "bottom_radius": 0.04389711008510284, "length": 0.06032596822152251, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.7004974238294233, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6191263006870993, "upper_button_position": 0.08137112314232398}], "rail_length": 5, "inclination": 83.62062658169378, "heading": 54.86835782617894} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 14, "radius": 0.0634924870241792, "mass": 14.709676646614824, "I_11_without_motor": 6.321, "I_22_without_motor": 6.313025008452103, "I_33_without_motor": 0.02922030499870789, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.817298873906841, "trigger": 800, "sampling_rate": 105, "lag": 1.4063749299306547, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.9015042478644425, "trigger": "apogee", "sampling_rate": 105, "lag": 1.6916849380661005, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 6514.743542099575, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03247600375348105, "grain_number": 5, "grain_density": 1802.8487679718357, "grain_outer_radius": 0.03283690273976019, "grain_initial_inner_radius": 0.014254841714729672, "grain_initial_height": 0.12023205122080777, "grain_separation": 0.0064105459111511226, "grains_center_of_mass_position": 0.3967602433044211, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.00013644286796200234, "throat_radius": 0.011668582226117183, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2539494671036846}], "aerodynamic_surfaces": [{"length": 0.5596403667045493, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1353701876975828]}, {"n": 4, "root_chord": 0.12014407469739156, "tip_chord": 0.06017500886414237, "span": 0.1103389212118897, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0489606170466572]}, {"top_radius": 0.06383549807917367, "bottom_radius": 0.04290815155775744, "length": 0.058220161897975437, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.7011021489792616, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6190834841590558, "upper_button_position": 0.08201866482020581}], "rail_length": 5, "inclination": 83.7769529700423, "heading": 55.825128718842876} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 17, "radius": 0.06349375594679321, "mass": 15.199128285098368, "I_11_without_motor": 6.321, "I_22_without_motor": 6.322160088501507, "I_33_without_motor": 0.058963578092994406, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.045144262676045, "trigger": 800, "sampling_rate": 105, "lag": 1.6168084743320965, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.1678269734005617, "trigger": "apogee", "sampling_rate": 105, "lag": 1.3540077683456562, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 4563.572283518417, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03224422295261444, "grain_number": 5, "grain_density": 1821.5087968587952, "grain_outer_radius": 0.032396969255703054, "grain_initial_inner_radius": 0.014593338245721172, "grain_initial_height": 0.12015927711054189, "grain_separation": 0.005861398144002046, "grains_center_of_mass_position": 0.3977388838690814, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.0008056669713052032, "throat_radius": 0.011976001511780647, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2560299433022888}], "aerodynamic_surfaces": [{"length": 0.558177699404519, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.132822153196735]}, {"n": 4, "root_chord": 0.12011092926040404, "tip_chord": 0.06042909487228104, "span": 0.10976673821218898, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0505549564489878]}, {"top_radius": 0.06479073513488832, "bottom_radius": 0.04350881624287202, "length": 0.06136391809263359, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6997896733287025, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.616666029595402, "upper_button_position": 0.0831236437333005}], "rail_length": 5, "inclination": 85.22188930223953, "heading": 54.04282848968786} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 28, "radius": 0.06350235440727434, "mass": 15.070204779550483, "I_11_without_motor": 6.321, "I_22_without_motor": 6.342790416702579, "I_33_without_motor": 0.05023151335844672, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.950687209250601, "trigger": 800, "sampling_rate": 105, "lag": 1.6932911219652462, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.8851945285655531, "trigger": "apogee", "sampling_rate": 105, "lag": 1.7722113781686215, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 6401.280224461789, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03365695385690572, "grain_number": 5, "grain_density": 1830.7009673285118, "grain_outer_radius": 0.03281947171301496, "grain_initial_inner_radius": 0.01528588507445965, "grain_initial_height": 0.1188540284866351, "grain_separation": 0.004376926437492424, "grains_center_of_mass_position": 0.398404054740682, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.0006207325346728692, "throat_radius": 0.010632806187796618, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2558950008463732}], "aerodynamic_surfaces": [{"length": 0.5580098300026757, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.134220754837157]}, {"n": 4, "root_chord": 0.12036332820175781, "tip_chord": 0.0597001950594256, "span": 0.10976695147617442, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.049443116624482]}, {"top_radius": 0.0650339166746558, "bottom_radius": 0.04472470808674029, "length": 0.05943466505615914, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6988256613164832, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6207561546904712, "upper_button_position": 0.07806950662601198}], "rail_length": 5, "inclination": 84.03603483764553, "heading": 55.887339061338764} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 26, "radius": 0.06351167017179078, "mass": 15.611985657395229, "I_11_without_motor": 6.321, "I_22_without_motor": 6.32841482893715, "I_33_without_motor": 0.031011243422976696, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.948985022345356, "trigger": 800, "sampling_rate": 105, "lag": 1.4554028709851992, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.0182590593942014, "trigger": "apogee", "sampling_rate": 105, "lag": 1.2472473004292794, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 6338.901413423589, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03246499500970873, "grain_number": 5, "grain_density": 1787.853898821363, "grain_outer_radius": 0.03286663630863919, "grain_initial_inner_radius": 0.015643692864322222, "grain_initial_height": 0.12082644736871681, "grain_separation": 0.005610711721622439, "grains_center_of_mass_position": 0.39614881164715504, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.00010968724020596801, "throat_radius": 0.010886357471918257, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2539405124172907}], "aerodynamic_surfaces": [{"length": 0.5561785445012554, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.132630258756316]}, {"n": 4, "root_chord": 0.11930974875814616, "tip_chord": 0.060270682612888954, "span": 0.11027737478538215, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0485189363780572]}, {"top_radius": 0.06086559183894612, "bottom_radius": 0.0454375776142393, "length": 0.06030391500642561, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.7009586103175619, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6181464263296432, "upper_button_position": 0.08281218398791867}], "rail_length": 5, "inclination": 84.15609134887411, "heading": 52.45330766215803} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 11, "radius": 0.06351202525163077, "mass": 15.392504202590164, "I_11_without_motor": 6.321, "I_22_without_motor": 6.323620497138478, "I_33_without_motor": 0.029186600176251954, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.125417795253925, "trigger": 800, "sampling_rate": 105, "lag": 1.727636501137058, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.0094449809124664, "trigger": "apogee", "sampling_rate": 105, "lag": 1.4192788769322402, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 5282.801612432365, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.0330815070178224, "grain_number": 5, "grain_density": 1755.1167766932929, "grain_outer_radius": 0.03277959596453596, "grain_initial_inner_radius": 0.014984155227919729, "grain_initial_height": 0.12049032672599923, "grain_separation": 0.004437783093532051, "grains_center_of_mass_position": 0.3966445370511041, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.0002771738131394219, "throat_radius": 0.011132774552032137, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2561708441099395}], "aerodynamic_surfaces": [{"length": 0.5598532309485841, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1341045484548415]}, {"n": 4, "root_chord": 0.11862650717253713, "tip_chord": 0.0599523202030708, "span": 0.11010291683651284, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0483470778754516]}, {"top_radius": 0.06324533464958096, "bottom_radius": 0.04134060555718694, "length": 0.06058015057263284, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.698632311100594, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6212924683491421, "upper_button_position": 0.07733984275145189}], "rail_length": 5, "inclination": 86.19588906797561, "heading": 49.85601395629662} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 7, "radius": 0.06350006955536922, "mass": 15.799447870142059, "I_11_without_motor": 6.321, "I_22_without_motor": 6.332107671710035, "I_33_without_motor": 0.03153237328129834, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.001137879935596, "trigger": 800, "sampling_rate": 105, "lag": 1.3653233466638568, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.8693621432003233, "trigger": "apogee", "sampling_rate": 105, "lag": 1.48557862101658, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 7030.577307268565, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.032796257083834886, "grain_number": 5, "grain_density": 1887.5726087443666, "grain_outer_radius": 0.03219561632695956, "grain_initial_inner_radius": 0.015077281922903172, "grain_initial_height": 0.1202439739511392, "grain_separation": 0.007695059111287829, "grains_center_of_mass_position": 0.3964477803779825, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.0018830563802775702, "throat_radius": 0.01069571145826872, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2549438058658564}], "aerodynamic_surfaces": [{"length": 0.5586959945672927, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1347026583779645]}, {"n": 4, "root_chord": 0.12067841986788942, "tip_chord": 0.05980559387136491, "span": 0.1097717783830386, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0479600980127175]}, {"top_radius": 0.0629756691974217, "bottom_radius": 0.043808635977925774, "length": 0.05972379941617993, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6979147816839694, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6169507413489307, "upper_button_position": 0.08096404033503868}], "rail_length": 5, "inclination": 85.49590126163909, "heading": 52.95951498096336} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 15, "radius": 0.06349071169964288, "mass": 14.800191249080765, "I_11_without_motor": 6.321, "I_22_without_motor": 6.32463403036484, "I_33_without_motor": 0.0322176693888181, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.924572501315387, "trigger": 800, "sampling_rate": 105, "lag": 1.3522038229512596, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.9448792264908165, "trigger": "apogee", "sampling_rate": 105, "lag": 1.5068837624054492, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 7551.380253384962, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.031958148786281754, "grain_number": 5, "grain_density": 1770.6557869397002, "grain_outer_radius": 0.03299668473194588, "grain_initial_inner_radius": 0.01450476168660286, "grain_initial_height": 0.11938619567310826, "grain_separation": 0.006932306846733179, "grains_center_of_mass_position": 0.3959409043012191, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.0007341638060561093, "throat_radius": 0.010634733696663935, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2560175990878202}], "aerodynamic_surfaces": [{"length": 0.5585889505952945, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1361210450033925]}, {"n": 4, "root_chord": 0.11939622090417909, "tip_chord": 0.05991464092188379, "span": 0.11061727097661712, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0522559589916516]}, {"top_radius": 0.06454087073167931, "bottom_radius": 0.0443065780298129, "length": 0.06121319273208881, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6999664441042162, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6180540116409904, "upper_button_position": 0.08191243246322577}], "rail_length": 5, "inclination": 83.87709490035185, "heading": 55.0599492522456} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 3, "radius": 0.06349780679999119, "mass": 15.009280751461688, "I_11_without_motor": 6.321, "I_22_without_motor": 6.29887945233111, "I_33_without_motor": 0.034479816961961667, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.90172819551314, "trigger": 800, "sampling_rate": 105, "lag": 1.5163655385794343, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.875816755176137, "trigger": "apogee", "sampling_rate": 105, "lag": 1.2023748047438532, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 7385.590506427114, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03221891989261677, "grain_number": 5, "grain_density": 1790.1967260100346, "grain_outer_radius": 0.03316729556849812, "grain_initial_inner_radius": 0.014863902626421193, "grain_initial_height": 0.12065846084196745, "grain_separation": 0.0036426744285935945, "grains_center_of_mass_position": 0.3965370904480209, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.00013280584439873054, "throat_radius": 0.011210583646187327, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2548409698708773}], "aerodynamic_surfaces": [{"length": 0.5584714172410293, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1333653549924239]}, {"n": 4, "root_chord": 0.11969334297624912, "tip_chord": 0.060121232394150424, "span": 0.10971653445562919, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0490302028140186]}, {"top_radius": 0.062407313736553297, "bottom_radius": 0.04065057212257242, "length": 0.05742457460519687, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6994335939676563, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6180270862200052, "upper_button_position": 0.08140650774765101}], "rail_length": 5, "inclination": 85.46542134999915, "heading": 55.536248042226646} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 5, "radius": 0.06349413243678145, "mass": 14.743964824602733, "I_11_without_motor": 6.321, "I_22_without_motor": 6.337257411297098, "I_33_without_motor": 0.0329993761123817, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.00520642707896, "trigger": 800, "sampling_rate": 105, "lag": 1.456810861337788, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.8956931615186817, "trigger": "apogee", "sampling_rate": 105, "lag": 1.3230597114159592, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 7209.683200057362, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03279760108823367, "grain_number": 5, "grain_density": 1834.9366360707274, "grain_outer_radius": 0.032787904216677995, "grain_initial_inner_radius": 0.014970218367640686, "grain_initial_height": 0.12128795849055533, "grain_separation": 0.004719163578293065, "grains_center_of_mass_position": 0.39530647037378636, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.0022908949144089534, "throat_radius": 0.010589347376890983, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2546074628084332}], "aerodynamic_surfaces": [{"length": 0.5572291958811432, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1353683373632557]}, {"n": 4, "root_chord": 0.12050940641366253, "tip_chord": 0.05962258502919415, "span": 0.11051119243479171, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0483006211672794]}, {"top_radius": 0.06387608941136222, "bottom_radius": 0.042135664250281764, "length": 0.06221056212548488, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6999072201956247, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6171381994017947, "upper_button_position": 0.08276902079382997}], "rail_length": 5, "inclination": 85.17946214102281, "heading": 51.998550698639285} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 1, "radius": 0.06349988246736835, "mass": 15.127951044531462, "I_11_without_motor": 6.321, "I_22_without_motor": 6.304120784320496, "I_33_without_motor": 0.047270325007072705, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.125776902514774, "trigger": 800, "sampling_rate": 105, "lag": 1.4104745690639993, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.0402900695968205, "trigger": "apogee", "sampling_rate": 105, "lag": 1.7050693742503058, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 7382.714678228542, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03366868417579529, "grain_number": 5, "grain_density": 1822.1786217419121, "grain_outer_radius": 0.034093475845885395, "grain_initial_inner_radius": 0.014939083650324135, "grain_initial_height": 0.12125037765414684, "grain_separation": 0.004922597009769367, "grains_center_of_mass_position": 0.3986958463355442, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.0009764665546426117, "throat_radius": 0.010583062536681957, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2569513063011652}], "aerodynamic_surfaces": [{"length": 0.5598181143296278, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1345825464475583]}, {"n": 4, "root_chord": 0.1199812213844204, "tip_chord": 0.06007242530874172, "span": 0.11046315666132789, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0495563519149418]}, {"top_radius": 0.06557365470659852, "bottom_radius": 0.043846776979273826, "length": 0.06026413656902243, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6992183915879916, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6171854737317541, "upper_button_position": 0.08203291785623745}], "rail_length": 5, "inclination": 86.05351223387608, "heading": 54.31655922653191} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 13, "radius": 0.06350430884204616, "mass": 15.110086357337545, "I_11_without_motor": 6.321, "I_22_without_motor": 6.313196794464696, "I_33_without_motor": 0.023551995393136224, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.021930028181636, "trigger": 800, "sampling_rate": 105, "lag": 1.352065013695944, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.9537763680190132, "trigger": "apogee", "sampling_rate": 105, "lag": 1.3902969567718713, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 5378.405857272342, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.032723072652738314, "grain_number": 5, "grain_density": 1830.5648866654535, "grain_outer_radius": 0.03291049993078663, "grain_initial_inner_radius": 0.014576842219137548, "grain_initial_height": 0.12037508413096347, "grain_separation": 0.003250255271304136, "grains_center_of_mass_position": 0.39659432746007384, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.00026071784347483993, "throat_radius": 0.011194397861158844, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2547624185188067}], "aerodynamic_surfaces": [{"length": 0.5571692791716677, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1336810995436297]}, {"n": 4, "root_chord": 0.12020141034019076, "tip_chord": 0.05864438628824802, "span": 0.1103435967322336, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0486715741057797]}, {"top_radius": 0.06229932186875737, "bottom_radius": 0.04290881295541781, "length": 0.063358717393052, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.7003511393453975, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6196147243858786, "upper_button_position": 0.08073641495951889}], "rail_length": 5, "inclination": 85.01280931564365, "heading": 54.70066345505092} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 14, "radius": 0.06349869030005506, "mass": 15.516371514227249, "I_11_without_motor": 6.321, "I_22_without_motor": 6.3311270901818855, "I_33_without_motor": 0.039518484734917196, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.187056276082586, "trigger": 800, "sampling_rate": 105, "lag": 1.4862396222757985, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.960293736835046, "trigger": "apogee", "sampling_rate": 105, "lag": 1.4964934334260673, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 6438.003037636608, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03414470526835011, "grain_number": 5, "grain_density": 1800.8243668345003, "grain_outer_radius": 0.03374461059698083, "grain_initial_inner_radius": 0.013685565254489138, "grain_initial_height": 0.12022826792767276, "grain_separation": 0.0057261536814462825, "grains_center_of_mass_position": 0.3964320154434183, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.0003684550695898837, "throat_radius": 0.012026535153821825, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2564012585885642}], "aerodynamic_surfaces": [{"length": 0.5576312641519685, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1321129037097613]}, {"n": 4, "root_chord": 0.11964163249817243, "tip_chord": 0.06053330978274308, "span": 0.10957726966567305, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0504223320165638]}, {"top_radius": 0.06377627586807537, "bottom_radius": 0.04344315579923672, "length": 0.06043671965659524, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6997111517704975, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6176186103593101, "upper_button_position": 0.08209254141118738}], "rail_length": 5, "inclination": 84.85887548960986, "heading": 52.8059677474103} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 8, "radius": 0.06350780886056825, "mass": 15.713136063635455, "I_11_without_motor": 6.321, "I_22_without_motor": 6.3444643700358165, "I_33_without_motor": 0.03428915836315116, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.103834277538313, "trigger": 800, "sampling_rate": 105, "lag": 1.3639714046090532, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.8915577948691057, "trigger": "apogee", "sampling_rate": 105, "lag": 1.5088803851157955, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 7026.854294754978, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.032921717246896305, "grain_number": 5, "grain_density": 1887.0827550331205, "grain_outer_radius": 0.03276949607729857, "grain_initial_inner_radius": 0.01501597811270181, "grain_initial_height": 0.11884550439621125, "grain_separation": 0.006216505249936778, "grains_center_of_mass_position": 0.3992649907504356, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.00019146595975479876, "throat_radius": 0.011305035482275154, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2548049677302013}], "aerodynamic_surfaces": [{"length": 0.5587865751733017, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1348964369359507]}, {"n": 4, "root_chord": 0.11935120769305262, "tip_chord": 0.06046467457639855, "span": 0.10942959470112658, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0511620933471475]}, {"top_radius": 0.06274060826929713, "bottom_radius": 0.041957770541348825, "length": 0.06034069520915706, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6974625963335641, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6178153625143794, "upper_button_position": 0.0796472338191847}], "rail_length": 5, "inclination": 83.20880479645666, "heading": 50.61474897693754} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 7, "radius": 0.06348996262058414, "mass": 14.374903371657116, "I_11_without_motor": 6.321, "I_22_without_motor": 6.316094399336938, "I_33_without_motor": 0.0424350372256497, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.060660624785088, "trigger": 800, "sampling_rate": 105, "lag": 1.3567309573777342, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.0950657123179492, "trigger": "apogee", "sampling_rate": 105, "lag": 1.0724681653530452, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 6331.80104234107, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03221203446405128, "grain_number": 5, "grain_density": 1790.2040907239311, "grain_outer_radius": 0.03306105381158216, "grain_initial_inner_radius": 0.014774081637033682, "grain_initial_height": 0.12011635841882029, "grain_separation": 0.004871724671113781, "grains_center_of_mass_position": 0.3968071243970028, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.0011697908688223773, "throat_radius": 0.011307211840652049, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.255799452226066}], "aerodynamic_surfaces": [{"length": 0.5581524755227274, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1340901674031068]}, {"n": 4, "root_chord": 0.11971592814833756, "tip_chord": 0.059482899746064105, "span": 0.11054868663961716, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0491225699779931]}, {"top_radius": 0.06314832010320223, "bottom_radius": 0.04309338518286907, "length": 0.05929522206206675, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6999439405557972, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6180478714284893, "upper_button_position": 0.08189606912730796}], "rail_length": 5, "inclination": 84.7017541615836, "heading": 52.05424611611283} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 23, "radius": 0.06350110609969463, "mass": 15.27945510023428, "I_11_without_motor": 6.321, "I_22_without_motor": 6.335105899381713, "I_33_without_motor": 0.04451985557154536, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.103771217226235, "trigger": 800, "sampling_rate": 105, "lag": 1.5137413752945212, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.9719815443093841, "trigger": "apogee", "sampling_rate": 105, "lag": 1.1333745950007599, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 7350.638053689589, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03291542616008069, "grain_number": 5, "grain_density": 1751.795497563181, "grain_outer_radius": 0.032580844789046944, "grain_initial_inner_radius": 0.015386196926125821, "grain_initial_height": 0.11925007255759713, "grain_separation": 0.0036535842265723465, "grains_center_of_mass_position": 0.39702849110222205, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.0017443444494659314, "throat_radius": 0.010237030153352124, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2549235139961086}], "aerodynamic_surfaces": [{"length": 0.5580739365630819, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1332662344967228]}, {"n": 4, "root_chord": 0.12002936531818889, "tip_chord": 0.059286537455685656, "span": 0.11014486475303154, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0493736829106934]}, {"top_radius": 0.06431269005894381, "bottom_radius": 0.04397192766024827, "length": 0.061127347819634324, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.7001038615254359, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6174162796002083, "upper_button_position": 0.08268758192522763}], "rail_length": 5, "inclination": 82.85778360047398, "heading": 51.16988676664341} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 23, "radius": 0.06351235563524632, "mass": 14.63322038652452, "I_11_without_motor": 6.321, "I_22_without_motor": 6.3302254494163215, "I_33_without_motor": 0.025350749988723893, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.053096897204416, "trigger": 800, "sampling_rate": 105, "lag": 1.3635651794695702, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.9701579230024913, "trigger": "apogee", "sampling_rate": 105, "lag": 1.6372569132834822, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 6832.288212514506, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03357760600646698, "grain_number": 5, "grain_density": 1899.105846343389, "grain_outer_radius": 0.03349899343792087, "grain_initial_inner_radius": 0.015038516649391938, "grain_initial_height": 0.1196638212053437, "grain_separation": 0.00560807561256116, "grains_center_of_mass_position": 0.39719181625568056, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.0012562832448794689, "throat_radius": 0.012044905000954774, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.255696338974987}], "aerodynamic_surfaces": [{"length": 0.5593896378193238, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1339020865839886]}, {"n": 4, "root_chord": 0.12030892210238418, "tip_chord": 0.06062600929386921, "span": 0.11017272883690943, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0483048017003125]}, {"top_radius": 0.06478527852177199, "bottom_radius": 0.042073537329639345, "length": 0.060411611459264415, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.700418092723315, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6153840766118764, "upper_button_position": 0.08503401611143857}], "rail_length": 5, "inclination": 84.59254794762977, "heading": 55.9687805076979} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 0, "radius": 0.06350590619094476, "mass": 15.080485170962332, "I_11_without_motor": 6.321, "I_22_without_motor": 6.327040010827636, "I_33_without_motor": 0.042590045765280984, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.1537874988919, "trigger": 800, "sampling_rate": 105, "lag": 1.4535783866105365, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.1199840450592056, "trigger": "apogee", "sampling_rate": 105, "lag": 1.2928765553431871, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 6560.483730429797, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.033002539805288965, "grain_number": 5, "grain_density": 1753.135707019853, "grain_outer_radius": 0.03257329208233708, "grain_initial_inner_radius": 0.014644125862002266, "grain_initial_height": 0.12098127573465807, "grain_separation": 0.007023160684503705, "grains_center_of_mass_position": 0.3957751400327463, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.0007006386699787393, "throat_radius": 0.01094411075588027, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2562606838365908}], "aerodynamic_surfaces": [{"length": 0.5581466476385946, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1341610555974102]}, {"n": 4, "root_chord": 0.11932672269248384, "tip_chord": 0.06030727424750291, "span": 0.1103326149631549, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.050338978641946]}, {"top_radius": 0.06425923763319025, "bottom_radius": 0.04278974362240359, "length": 0.060061214011226924, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.7011599614929181, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.616562364935789, "upper_button_position": 0.08459759655712917}], "rail_length": 5, "inclination": 85.49450114169898, "heading": 54.39902008969704} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 3, "radius": 0.06349535545294449, "mass": 15.303293072393853, "I_11_without_motor": 6.321, "I_22_without_motor": 6.320331081926137, "I_33_without_motor": 0.03258812738472048, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.027716162274867, "trigger": 800, "sampling_rate": 105, "lag": 1.5230030817401685, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.13248367224743, "trigger": "apogee", "sampling_rate": 105, "lag": 1.5705494417288957, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 7837.4232661561955, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03206541531820579, "grain_number": 5, "grain_density": 1834.1727399069105, "grain_outer_radius": 0.033016426516149236, "grain_initial_inner_radius": 0.014720608706298632, "grain_initial_height": 0.1192598495122423, "grain_separation": 0.005158907991717304, "grains_center_of_mass_position": 0.39423900952152346, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.0006761447815294225, "throat_radius": 0.011577124841068962, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2556291911841437}], "aerodynamic_surfaces": [{"length": 0.5569380047094106, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1340252793986345]}, {"n": 4, "root_chord": 0.12057834302562266, "tip_chord": 0.05948300577613497, "span": 0.10985576754615899, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0518576729558635]}, {"top_radius": 0.06445272034031992, "bottom_radius": 0.04234109310044354, "length": 0.05917382632419316, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.7004017762281358, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.616986328570382, "upper_button_position": 0.08341544765775377}], "rail_length": 5, "inclination": 83.77920212144204, "heading": 53.03152903838162} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 19, "radius": 0.06350573537363302, "mass": 14.30805992536985, "I_11_without_motor": 6.321, "I_22_without_motor": 6.31528362122732, "I_33_without_motor": 0.03188559398428235, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.093521331465285, "trigger": 800, "sampling_rate": 105, "lag": 1.3564706409584264, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.009760896720427, "trigger": "apogee", "sampling_rate": 105, "lag": 1.7787872915821343, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 4242.052104083594, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.033389290903656256, "grain_number": 5, "grain_density": 1746.8561271388007, "grain_outer_radius": 0.03304571390182966, "grain_initial_inner_radius": 0.014782952011176501, "grain_initial_height": 0.12135739369955491, "grain_separation": 0.004190858753516596, "grains_center_of_mass_position": 0.3949441894388302, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.0003698788353958239, "throat_radius": 0.010375367704889374, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2547516322630021}], "aerodynamic_surfaces": [{"length": 0.5589418312759338, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1345455674290448]}, {"n": 4, "root_chord": 0.11955012772670659, "tip_chord": 0.059746869415886625, "span": 0.10985610336855757, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0480885307926457]}, {"top_radius": 0.06310190179238634, "bottom_radius": 0.04431718568223173, "length": 0.06132497816473511, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6992169721499453, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6171755890032975, "upper_button_position": 0.08204138314664777}], "rail_length": 5, "inclination": 84.69013994851046, "heading": 49.7799035498802} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 7, "radius": 0.06349808638580251, "mass": 15.26117984996623, "I_11_without_motor": 6.321, "I_22_without_motor": 6.313792929031072, "I_33_without_motor": 0.039028815462556654, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.019968502483774, "trigger": 800, "sampling_rate": 105, "lag": 1.293710811772124, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.9805575865785177, "trigger": "apogee", "sampling_rate": 105, "lag": 1.5983124444765036, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 5820.692744412688, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03465972691618848, "grain_number": 5, "grain_density": 1869.9112320834886, "grain_outer_radius": 0.03285971795415413, "grain_initial_inner_radius": 0.01514107450990915, "grain_initial_height": 0.11885928499113928, "grain_separation": 0.006009036129893335, "grains_center_of_mass_position": 0.3958164370610288, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.001418728843530659, "throat_radius": 0.011731075210787385, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2559732262092702}], "aerodynamic_surfaces": [{"length": 0.5568826774337932, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1330704792408508]}, {"n": 4, "root_chord": 0.12031142839982933, "tip_chord": 0.0606743409717126, "span": 0.10870074033956711, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0508477777633585]}, {"top_radius": 0.0648848329000352, "bottom_radius": 0.044880244462127794, "length": 0.059120897804609475, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.700730906083566, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6161153401468761, "upper_button_position": 0.08461556593668995}], "rail_length": 5, "inclination": 84.40677839986306, "heading": 53.26302780747085} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 21, "radius": 0.06349929575481449, "mass": 15.465615089268946, "I_11_without_motor": 6.321, "I_22_without_motor": 6.332695064901782, "I_33_without_motor": 0.02944650746931481, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.145864653234616, "trigger": 800, "sampling_rate": 105, "lag": 1.5011199536099813, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.01143032578772, "trigger": "apogee", "sampling_rate": 105, "lag": 1.9278020202292208, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 6414.157841409511, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03327788100491452, "grain_number": 5, "grain_density": 1844.8788954830204, "grain_outer_radius": 0.03301459564213143, "grain_initial_inner_radius": 0.014707825484932605, "grain_initial_height": 0.11883880719343697, "grain_separation": 0.006392721871365158, "grains_center_of_mass_position": 0.3956476448429322, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.0010332525140067288, "throat_radius": 0.011484032909955786, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.255615340545256}], "aerodynamic_surfaces": [{"length": 0.5583373706467214, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.134658469530976]}, {"n": 4, "root_chord": 0.11944691692627743, "tip_chord": 0.06032775449099784, "span": 0.1095714360351648, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0473970351578303]}, {"top_radius": 0.06262037654067643, "bottom_radius": 0.042907937122465434, "length": 0.05949146626345526, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6987322801298296, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6175012977913668, "upper_button_position": 0.08123098233846282}], "rail_length": 5, "inclination": 86.90268603158258, "heading": 54.8443485850684} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 17, "radius": 0.06349646441148747, "mass": 16.186564204679556, "I_11_without_motor": 6.321, "I_22_without_motor": 6.3285355865999335, "I_33_without_motor": 0.04373704731517958, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.048536374379845, "trigger": 800, "sampling_rate": 105, "lag": 1.5516683981538366, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.9486697251128735, "trigger": "apogee", "sampling_rate": 105, "lag": 1.6982717640872143, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 9445.646204880664, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03369883664825597, "grain_number": 5, "grain_density": 1811.0763143046966, "grain_outer_radius": 0.03305498320609093, "grain_initial_inner_radius": 0.015135428691737481, "grain_initial_height": 0.12007989129724471, "grain_separation": 0.006316667503302023, "grains_center_of_mass_position": 0.39808673559545676, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.0009150862939795672, "throat_radius": 0.011078707680095713, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2545044859372902}], "aerodynamic_surfaces": [{"length": 0.557430375793955, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1351186435980873]}, {"n": 4, "root_chord": 0.12024472011328981, "tip_chord": 0.060165768151028885, "span": 0.10986083070797623, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.04817708214022]}, {"top_radius": 0.06295886487910317, "bottom_radius": 0.043326819305221406, "length": 0.05927481229384511, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6996806367425821, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6176905446611791, "upper_button_position": 0.08199009208140295}], "rail_length": 5, "inclination": 83.00188501232762, "heading": 53.64934999825792} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 17, "radius": 0.063489511048732, "mass": 15.403246955580508, "I_11_without_motor": 6.321, "I_22_without_motor": 6.325173329854296, "I_33_without_motor": 0.03821842888885621, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.00933365776983, "trigger": 800, "sampling_rate": 105, "lag": 1.6225523343468229, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.0986084926586897, "trigger": "apogee", "sampling_rate": 105, "lag": 1.4353139582859633, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 7300.273578654727, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03376087952005415, "grain_number": 5, "grain_density": 1807.0328943697189, "grain_outer_radius": 0.03307141546035796, "grain_initial_inner_radius": 0.014598991393814006, "grain_initial_height": 0.11897725559644393, "grain_separation": 0.004816293114279538, "grains_center_of_mass_position": 0.39620109423477756, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.0026381497150537786, "throat_radius": 0.010922838556938848, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2545358511905456}], "aerodynamic_surfaces": [{"length": 0.5591978529198565, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1330538423253214]}, {"n": 4, "root_chord": 0.1207332445668151, "tip_chord": 0.05917847890503504, "span": 0.10949151058046712, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0489433894492213]}, {"top_radius": 0.06146865769749782, "bottom_radius": 0.04413891123887712, "length": 0.05921232328798554, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6989306139678094, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6169141284281716, "upper_button_position": 0.0820164855396378}], "rail_length": 5, "inclination": 82.66250941837437, "heading": 51.8163456716249} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 1, "radius": 0.06350508115972937, "mass": 14.906764030320774, "I_11_without_motor": 6.321, "I_22_without_motor": 6.332614240778358, "I_33_without_motor": 0.032548280432326035, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.1314655019296, "trigger": 800, "sampling_rate": 105, "lag": 1.585236959922436, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.00670925931133, "trigger": "apogee", "sampling_rate": 105, "lag": 1.7910842447208755, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 6835.743103882098, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03303410945587017, "grain_number": 5, "grain_density": 1816.0087082791188, "grain_outer_radius": 0.03297010098654171, "grain_initial_inner_radius": 0.015317003102830207, "grain_initial_height": 0.12182376707803726, "grain_separation": 0.0027595682653325207, "grains_center_of_mass_position": 0.39586002002451076, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.001383263015482303, "throat_radius": 0.01061604442869967, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2550563220190505}], "aerodynamic_surfaces": [{"length": 0.5582747983454609, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1338111786693938]}, {"n": 4, "root_chord": 0.12035088651766729, "tip_chord": 0.06033904263684236, "span": 0.11086711947537538, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.05056962948637]}, {"top_radius": 0.06259444074688274, "bottom_radius": 0.044304101908211255, "length": 0.06019576431179175, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.7014645175249009, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6179759213664193, "upper_button_position": 0.08348859615848159}], "rail_length": 5, "inclination": 83.54581353537868, "heading": 53.33504342574518} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 22, "radius": 0.06350279525433856, "mass": 15.079726308932507, "I_11_without_motor": 6.321, "I_22_without_motor": 6.321573596121193, "I_33_without_motor": 0.052029932619906016, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.064804018007504, "trigger": 800, "sampling_rate": 105, "lag": 1.4698430591084484, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.9232606010826354, "trigger": "apogee", "sampling_rate": 105, "lag": 1.461215042765483, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 7256.565275020275, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03340123307811307, "grain_number": 5, "grain_density": 1840.735276556465, "grain_outer_radius": 0.033143502255780416, "grain_initial_inner_radius": 0.015231953324966354, "grain_initial_height": 0.12114596568233399, "grain_separation": 0.0022352781316530702, "grains_center_of_mass_position": 0.397183479588522, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.0011295604339312609, "throat_radius": 0.011248352425675857, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2548223020777387}], "aerodynamic_surfaces": [{"length": 0.5579397744954074, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1333465577266038]}, {"n": 4, "root_chord": 0.12065492405149036, "tip_chord": 0.05978308596814549, "span": 0.11058923015763192, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0489675732803987]}, {"top_radius": 0.06345964106367127, "bottom_radius": 0.04319341747494364, "length": 0.06080431687843, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.7002895383307389, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6178316145099039, "upper_button_position": 0.08245792382083506}], "rail_length": 5, "inclination": 84.00979106853103, "heading": 52.573723153993186} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 1, "radius": 0.06349928001026219, "mass": 15.06570967650027, "I_11_without_motor": 6.321, "I_22_without_motor": 6.322092540916452, "I_33_without_motor": 0.04767145939065197, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.960365660917095, "trigger": 800, "sampling_rate": 105, "lag": 1.453237317978458, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.8565158896144405, "trigger": "apogee", "sampling_rate": 105, "lag": 1.516866089204166, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 5720.589245204529, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03345305709290904, "grain_number": 5, "grain_density": 1805.2951782313703, "grain_outer_radius": 0.03280492984174041, "grain_initial_inner_radius": 0.01470483637132756, "grain_initial_height": 0.11924581792071379, "grain_separation": 0.004585293781336399, "grains_center_of_mass_position": 0.3971015082864182, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.0006304677928403056, "throat_radius": 0.010616896410004469, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2543536853527917}], "aerodynamic_surfaces": [{"length": 0.559613843606631, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1341460039850042]}, {"n": 4, "root_chord": 0.12007717712184073, "tip_chord": 0.06014898484709693, "span": 0.11011775772637664, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.050326371994986]}, {"top_radius": 0.06513346101633884, "bottom_radius": 0.044078635819838806, "length": 0.060242702253202364, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.699959255661251, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6190222908977664, "upper_button_position": 0.08093696476348455}], "rail_length": 5, "inclination": 84.38391613878784, "heading": 52.38590767434992} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 3, "radius": 0.06349360455926858, "mass": 14.41240179186806, "I_11_without_motor": 6.321, "I_22_without_motor": 6.324893290095144, "I_33_without_motor": 0.04739462579687119, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.103904131050887, "trigger": 800, "sampling_rate": 105, "lag": 1.5464620064494783, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.9918418977153363, "trigger": "apogee", "sampling_rate": 105, "lag": 1.3994935164927669, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 8213.353251264492, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03296069774132139, "grain_number": 5, "grain_density": 1748.2042914731965, "grain_outer_radius": 0.03302778927387984, "grain_initial_inner_radius": 0.01452041803325679, "grain_initial_height": 0.11973576790235564, "grain_separation": 0.0044877209092750985, "grains_center_of_mass_position": 0.39849352236046437, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.0007448821745868224, "throat_radius": 0.010567814449118354, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.254346443947536}], "aerodynamic_surfaces": [{"length": 0.5585481856423747, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1335738768433299]}, {"n": 4, "root_chord": 0.12049144984639884, "tip_chord": 0.06009687764860615, "span": 0.11007761338967989, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0485952079037033]}, {"top_radius": 0.06406083801263061, "bottom_radius": 0.04375817740511762, "length": 0.05817060187939539, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6989525014670805, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6184542783640068, "upper_button_position": 0.08049822310307375}], "rail_length": 5, "inclination": 84.0187599565203, "heading": 52.21587371024279} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 8, "radius": 0.06351461916945023, "mass": 15.72120103134193, "I_11_without_motor": 6.321, "I_22_without_motor": 6.320270473698307, "I_33_without_motor": 0.047394256474891636, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.891406175298021, "trigger": 800, "sampling_rate": 105, "lag": 1.5187966523751615, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.0632097751866945, "trigger": "apogee", "sampling_rate": 105, "lag": 1.5986766570656645, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 7976.658907594454, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03261755272228307, "grain_number": 5, "grain_density": 1788.4452838608797, "grain_outer_radius": 0.03194703582990407, "grain_initial_inner_radius": 0.015059965954195639, "grain_initial_height": 0.12063364793118307, "grain_separation": 0.0067145174250320865, "grains_center_of_mass_position": 0.3954802866652683, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.0005801938743106314, "throat_radius": 0.011741871036135096, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.25448476882896}], "aerodynamic_surfaces": [{"length": 0.5571698904720201, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.133336706467525]}, {"n": 4, "root_chord": 0.11990929321464576, "tip_chord": 0.06019154955791368, "span": 0.10907794255102529, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0495646454906975]}, {"top_radius": 0.0633928246694875, "bottom_radius": 0.044138659080206026, "length": 0.058566554215041804, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.69884725424692, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6183020275169964, "upper_button_position": 0.08054522672992359}], "rail_length": 5, "inclination": 83.53616800104072, "heading": 51.12808649566635} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 29, "radius": 0.06349875372499889, "mass": 15.52174848568608, "I_11_without_motor": 6.321, "I_22_without_motor": 6.3144702798962555, "I_33_without_motor": 0.03155654105979724, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.150987379633719, "trigger": 800, "sampling_rate": 105, "lag": 1.5094082349627624, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.1474910908160763, "trigger": "apogee", "sampling_rate": 105, "lag": 1.5253169971490854, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 6985.1509150213515, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03406823309765977, "grain_number": 5, "grain_density": 1839.958319286012, "grain_outer_radius": 0.03305834160739747, "grain_initial_inner_radius": 0.015100562067457328, "grain_initial_height": 0.12084662100585823, "grain_separation": 0.005060721220757177, "grains_center_of_mass_position": 0.3977591987035246, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.0004644006000592094, "throat_radius": 0.011377757096306876, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2559696807706626}], "aerodynamic_surfaces": [{"length": 0.558685327635886, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1348404752858852]}, {"n": 4, "root_chord": 0.12027042591129904, "tip_chord": 0.06016555756058694, "span": 0.11034169133769682, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0499666010623931]}, {"top_radius": 0.06389615055310356, "bottom_radius": 0.044013280181217224, "length": 0.059668445057651336, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6998735921147853, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6188400044420388, "upper_button_position": 0.08103358767274649}], "rail_length": 5, "inclination": 84.06179075879434, "heading": 51.89275923627153} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 15, "radius": 0.06350285139159496, "mass": 14.879636800722132, "I_11_without_motor": 6.321, "I_22_without_motor": 6.315619551337431, "I_33_without_motor": 0.03226393124986411, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.940166960888194, "trigger": 800, "sampling_rate": 105, "lag": 1.557278756713315, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.9415985835572387, "trigger": "apogee", "sampling_rate": 105, "lag": 1.7511041459337855, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 6404.590304023814, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03338974133172039, "grain_number": 5, "grain_density": 1795.6513684627625, "grain_outer_radius": 0.0326900313594425, "grain_initial_inner_radius": 0.014820840979368548, "grain_initial_height": 0.11949501907655767, "grain_separation": 0.006741790016212349, "grains_center_of_mass_position": 0.3981427377147511, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.0013433006593573185, "throat_radius": 0.010938108096252556, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.256919570094355}], "aerodynamic_surfaces": [{"length": 0.5573690266628984, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1348639567481815]}, {"n": 4, "root_chord": 0.12001622345599351, "tip_chord": 0.06077230409397119, "span": 0.11057405256458534, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0501091619135627]}, {"top_radius": 0.06407685568245465, "bottom_radius": 0.04292621530804189, "length": 0.06105343705276093, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6993449447206226, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6180904564334666, "upper_button_position": 0.08125448828715598}], "rail_length": 5, "inclination": 85.01744980068563, "heading": 52.44370578679336} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 17, "radius": 0.06350419070653365, "mass": 14.446850423296695, "I_11_without_motor": 6.321, "I_22_without_motor": 6.340403983267, "I_33_without_motor": 0.0013035065729761763, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.950468761358355, "trigger": 800, "sampling_rate": 105, "lag": 1.4255164516946592, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.9961488765236984, "trigger": "apogee", "sampling_rate": 105, "lag": 1.2033510758496146, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 4953.890748247072, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.032321282956486355, "grain_number": 5, "grain_density": 1925.8116427829807, "grain_outer_radius": 0.033329656905461226, "grain_initial_inner_radius": 0.014786019498855552, "grain_initial_height": 0.1189396871381035, "grain_separation": 0.003515376820615912, "grains_center_of_mass_position": 0.39760726411872865, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.002134807712007253, "throat_radius": 0.010454841459959256, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2552737871007522}], "aerodynamic_surfaces": [{"length": 0.5594800415657328, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.132628812342153]}, {"n": 4, "root_chord": 0.1206214582088253, "tip_chord": 0.059568289353501225, "span": 0.11039494159657012, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0500630206489185]}, {"top_radius": 0.06400765342799139, "bottom_radius": 0.044000083851521495, "length": 0.05988332401905376, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.7000812201972062, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6190009381001828, "upper_button_position": 0.08108028209702345}], "rail_length": 5, "inclination": 84.422305378073, "heading": 52.475647171932145} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 1, "radius": 0.06350265595738074, "mass": 15.982168053307154, "I_11_without_motor": 6.321, "I_22_without_motor": 6.325056227712188, "I_33_without_motor": 0.02471340568145637, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.900811771524102, "trigger": 800, "sampling_rate": 105, "lag": 1.4715942030746079, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.9749217135547606, "trigger": "apogee", "sampling_rate": 105, "lag": 1.6502146624092577, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 5770.517332006628, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.033573040277917285, "grain_number": 5, "grain_density": 1833.9939023815473, "grain_outer_radius": 0.03289637708238185, "grain_initial_inner_radius": 0.014869179069359561, "grain_initial_height": 0.12009574200624915, "grain_separation": 0.0035856760780511032, "grains_center_of_mass_position": 0.3981955137521441, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.0017524902169512625, "throat_radius": 0.011131997828966922, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2553387420934647}], "aerodynamic_surfaces": [{"length": 0.5568354661038059, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1341715843987137]}, {"n": 4, "root_chord": 0.12083598780842864, "tip_chord": 0.05960027098068451, "span": 0.11070755986788783, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0499393341021155]}, {"top_radius": 0.06268884905086451, "bottom_radius": 0.04412858769671177, "length": 0.06102353112627221, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6997385079644506, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6183908945877536, "upper_button_position": 0.08134761337669694}], "rail_length": 5, "inclination": 85.27209407875938, "heading": 54.190666742860444} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 12, "radius": 0.06350299968737849, "mass": 15.129294772224442, "I_11_without_motor": 6.321, "I_22_without_motor": 6.325292179261114, "I_33_without_motor": 0.04030884205613722, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.896207814847713, "trigger": 800, "sampling_rate": 105, "lag": 1.5649182546152611, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.8704696755097593, "trigger": "apogee", "sampling_rate": 105, "lag": 1.4299433950094835, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 5889.20702699435, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.033477077464184754, "grain_number": 5, "grain_density": 1774.81181830841, "grain_outer_radius": 0.0328896606631102, "grain_initial_inner_radius": 0.014951437704814474, "grain_initial_height": 0.11809364556115116, "grain_separation": 0.0037159356402908833, "grains_center_of_mass_position": 0.39910621007343594, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.0008600071351897885, "throat_radius": 0.01173267448889813, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2538392065792738}], "aerodynamic_surfaces": [{"length": 0.5590018174792856, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1352701022377598]}, {"n": 4, "root_chord": 0.12017862010002704, "tip_chord": 0.05989485134507201, "span": 0.10989769336716282, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0492381151006787]}, {"top_radius": 0.06478232771104268, "bottom_radius": 0.04322299879774567, "length": 0.05947832921729899, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.7008143164103382, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6170750818837223, "upper_button_position": 0.08373923452661591}], "rail_length": 5, "inclination": 84.34437274993806, "heading": 53.93575339928429} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 8, "radius": 0.06349887901917879, "mass": 14.908900180107135, "I_11_without_motor": 6.321, "I_22_without_motor": 6.3383172725705474, "I_33_without_motor": 0.025212036043287478, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.950150753973224, "trigger": 800, "sampling_rate": 105, "lag": 1.5403363381738076, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.0344703111778326, "trigger": "apogee", "sampling_rate": 105, "lag": 1.841613070432098, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 6306.432041999074, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03339587869190484, "grain_number": 5, "grain_density": 1805.5491626907615, "grain_outer_radius": 0.03279250298769639, "grain_initial_inner_radius": 0.014846522447359487, "grain_initial_height": 0.11852118665628893, "grain_separation": 0.004863210140639914, "grains_center_of_mass_position": 0.3975713150355508, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.00043134535986236086, "throat_radius": 0.011588191496208784, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2547996887266022}], "aerodynamic_surfaces": [{"length": 0.5589046284272716, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.131665032204105]}, {"n": 4, "root_chord": 0.11976524532581982, "tip_chord": 0.060191214487939154, "span": 0.11063467862622987, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0512644707515444]}, {"top_radius": 0.06518729061669487, "bottom_radius": 0.04321760112969352, "length": 0.060661857819613994, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6984055609698314, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6177677348672254, "upper_button_position": 0.08063782610260606}], "rail_length": 5, "inclination": 83.29911765210288, "heading": 50.36919478460611} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 9, "radius": 0.06350028897313414, "mass": 15.874329757019883, "I_11_without_motor": 6.321, "I_22_without_motor": 6.325629498551334, "I_33_without_motor": 0.0330658281237145, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.113081852709353, "trigger": 800, "sampling_rate": 105, "lag": 1.5443059640260122, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.0514581386283555, "trigger": "apogee", "sampling_rate": 105, "lag": 1.2893777431690934, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 5856.250694728396, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03257323064928406, "grain_number": 5, "grain_density": 1821.2471097776988, "grain_outer_radius": 0.03307940544802427, "grain_initial_inner_radius": 0.014599262392719015, "grain_initial_height": 0.12185739034849959, "grain_separation": 0.005086332754855426, "grains_center_of_mass_position": 0.396257765860305, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.0003085527648507209, "throat_radius": 0.011025573388122541, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2548594817324203}], "aerodynamic_surfaces": [{"length": 0.5570003027061665, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1324518575478195]}, {"n": 4, "root_chord": 0.12043550822077433, "tip_chord": 0.06054714413296922, "span": 0.1093116317662277, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0510606132034135]}, {"top_radius": 0.06430330379963214, "bottom_radius": 0.042564059212328184, "length": 0.06140519639062275, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.7019880394650353, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6188909496331936, "upper_button_position": 0.08309708983184172}], "rail_length": 5, "inclination": 84.22655015135797, "heading": 50.161628032700364} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 24, "radius": 0.06350601433065407, "mass": 15.27137233655113, "I_11_without_motor": 6.321, "I_22_without_motor": 6.300798198061935, "I_33_without_motor": 0.02137004367111585, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.998862201470702, "trigger": 800, "sampling_rate": 105, "lag": 1.5519932566494046, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.0470064434345545, "trigger": "apogee", "sampling_rate": 105, "lag": 1.5016451153311843, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 7507.457954812889, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03296985470418464, "grain_number": 5, "grain_density": 1768.1816104939548, "grain_outer_radius": 0.03280639358265971, "grain_initial_inner_radius": 0.014606602717007382, "grain_initial_height": 0.12052048127614555, "grain_separation": 0.005583702001739207, "grains_center_of_mass_position": 0.3962570974679449, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.0005508659076352886, "throat_radius": 0.010562014975168682, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2556945675888942}], "aerodynamic_surfaces": [{"length": 0.5571598712095784, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1341668960182867]}, {"n": 4, "root_chord": 0.12003815798814604, "tip_chord": 0.05980345832826959, "span": 0.1098800377955311, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.049899314543478]}, {"top_radius": 0.06316720845139089, "bottom_radius": 0.04340125221267471, "length": 0.06148964911894322, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6986922365641621, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6187687187018772, "upper_button_position": 0.07992351786228491}], "rail_length": 5, "inclination": 83.54080428492915, "heading": 53.44038241307092} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 7, "radius": 0.06349856448014375, "mass": 15.358370684317368, "I_11_without_motor": 6.321, "I_22_without_motor": 6.3222345096299115, "I_33_without_motor": 0.02572546994214788, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.045187619282522, "trigger": 800, "sampling_rate": 105, "lag": 1.542490410308309, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.001272707258571, "trigger": "apogee", "sampling_rate": 105, "lag": 1.3570579711793753, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 6882.561778763908, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.032608758666212184, "grain_number": 5, "grain_density": 1786.977399493363, "grain_outer_radius": 0.032941341907205095, "grain_initial_inner_radius": 0.015192380004538944, "grain_initial_height": 0.11881765503576278, "grain_separation": 0.005330974959019586, "grains_center_of_mass_position": 0.39725339808839444, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.0010342129808944276, "throat_radius": 0.010083511038810002, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2543941278962114}], "aerodynamic_surfaces": [{"length": 0.5587810386460624, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.133501354456158]}, {"n": 4, "root_chord": 0.11976191347978447, "tip_chord": 0.06031697763020787, "span": 0.10937836909154659, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0487621165011132]}, {"top_radius": 0.0644644492465009, "bottom_radius": 0.04325154743197436, "length": 0.06164649617383124, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.700311394963643, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.617312907001044, "upper_button_position": 0.08299848796259901}], "rail_length": 5, "inclination": 83.6138857416783, "heading": 53.15058153375897} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 9, "radius": 0.0634981813899827, "mass": 14.859267428427884, "I_11_without_motor": 6.321, "I_22_without_motor": 6.316954112738651, "I_33_without_motor": 0.02765475608430546, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.12348387601264, "trigger": 800, "sampling_rate": 105, "lag": 1.586989690186621, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.0437775709689083, "trigger": "apogee", "sampling_rate": 105, "lag": 1.5919514964529435, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 6911.718333537482, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03323992749846229, "grain_number": 5, "grain_density": 1864.9016814407896, "grain_outer_radius": 0.03308728808508502, "grain_initial_inner_radius": 0.014683137425875183, "grain_initial_height": 0.1195874525594654, "grain_separation": 0.004857937649601254, "grains_center_of_mass_position": 0.3979359284543769, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.00027485770574221406, "throat_radius": 0.01096828145733743, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.254036876518058}], "aerodynamic_surfaces": [{"length": 0.5599183925022974, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1340088316484347]}, {"n": 4, "root_chord": 0.11942754487678753, "tip_chord": 0.06039599279937518, "span": 0.10984471967500362, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0509062230937016]}, {"top_radius": 0.06387595669150617, "bottom_radius": 0.04407715118801431, "length": 0.06071033247041186, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6999095056255527, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6167892445965332, "upper_button_position": 0.08312026102901948}], "rail_length": 5, "inclination": 85.93535290191042, "heading": 52.899414193888575} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 6, "radius": 0.0635109068171948, "mass": 15.633929781859923, "I_11_without_motor": 6.321, "I_22_without_motor": 6.32413616153479, "I_33_without_motor": 0.03969900263775091, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.834362560642212, "trigger": 800, "sampling_rate": 105, "lag": 1.4258336009538153, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.8912650468491736, "trigger": "apogee", "sampling_rate": 105, "lag": 1.4521038685651637, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 4974.817900447082, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.033786578735444224, "grain_number": 5, "grain_density": 1746.8336950386788, "grain_outer_radius": 0.03279394214698376, "grain_initial_inner_radius": 0.015481373324010166, "grain_initial_height": 0.12022904373395915, "grain_separation": 0.003120285333965617, "grains_center_of_mass_position": 0.39711704679850884, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.001092892933712505, "throat_radius": 0.010893978680199414, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2557822082475814}], "aerodynamic_surfaces": [{"length": 0.5576492667259434, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1332263389142034]}, {"n": 4, "root_chord": 0.12072153231188552, "tip_chord": 0.05956047058002806, "span": 0.1095930062327995, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0503483533516376]}, {"top_radius": 0.06577505427999941, "bottom_radius": 0.043057787723638406, "length": 0.06057548259168792, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.7014103970415169, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6183357107062871, "upper_button_position": 0.08307468633522974}], "rail_length": 5, "inclination": 84.18931587843701, "heading": 54.76429406471985} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 9, "radius": 0.06350739738241934, "mass": 14.970067335874123, "I_11_without_motor": 6.321, "I_22_without_motor": 6.308709317869596, "I_33_without_motor": 0.023538652012588535, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.996146328714246, "trigger": 800, "sampling_rate": 105, "lag": 1.4894377928376885, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.0637967587480892, "trigger": "apogee", "sampling_rate": 105, "lag": 1.4197552944025036, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 7489.692061936832, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03254810364795023, "grain_number": 5, "grain_density": 1774.2887765854352, "grain_outer_radius": 0.032966655945223314, "grain_initial_inner_radius": 0.014842115968309474, "grain_initial_height": 0.11967731849857424, "grain_separation": 0.0023056409013189065, "grains_center_of_mass_position": 0.3981500175385283, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.0006403021933827702, "throat_radius": 0.010817054503619824, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.254063979969307}], "aerodynamic_surfaces": [{"length": 0.5587251191242447, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1344595537953381]}, {"n": 4, "root_chord": 0.12000658315386675, "tip_chord": 0.05988368920954532, "span": 0.10882738429387277, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0512731206666894]}, {"top_radius": 0.06401157697070317, "bottom_radius": 0.04402080285541102, "length": 0.06139041685117537, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6991978745687002, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6189370304572878, "upper_button_position": 0.08026084411141243}], "rail_length": 5, "inclination": 85.37536372514, "heading": 54.60708771420984} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 0, "radius": 0.06349902716433935, "mass": 15.031764351768178, "I_11_without_motor": 6.321, "I_22_without_motor": 6.321078321139381, "I_33_without_motor": 0.02484114491816245, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.112845655490997, "trigger": 800, "sampling_rate": 105, "lag": 1.4628219883138003, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.8675669253380869, "trigger": "apogee", "sampling_rate": 105, "lag": 1.629724002234014, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 6587.835206234734, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.032715030291042065, "grain_number": 5, "grain_density": 1815.6587832894024, "grain_outer_radius": 0.03287905286539368, "grain_initial_inner_radius": 0.014992477710058136, "grain_initial_height": 0.12013537101805616, "grain_separation": 0.004504900421298859, "grains_center_of_mass_position": 0.39720090106779565, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.00022033362393753122, "throat_radius": 0.011407593804265002, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2557425030428124}], "aerodynamic_surfaces": [{"length": 0.557966236998059, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1325285545264012]}, {"n": 4, "root_chord": 0.11941284851935915, "tip_chord": 0.05964851838161797, "span": 0.10976884631153055, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0493926197471277]}, {"top_radius": 0.06540213729157832, "bottom_radius": 0.044118083682024266, "length": 0.05942680550497701, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6984584080241735, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6187396730240534, "upper_button_position": 0.07971873500012006}], "rail_length": 5, "inclination": 83.64931191625233, "heading": 52.14542323283142} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 25, "radius": 0.06349853153743018, "mass": 15.800512063015404, "I_11_without_motor": 6.321, "I_22_without_motor": 6.3230678320389195, "I_33_without_motor": 0.020632005492927256, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.064467551098277, "trigger": 800, "sampling_rate": 105, "lag": 1.42202349815714, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.0211207849600876, "trigger": "apogee", "sampling_rate": 105, "lag": 1.294859378293711, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 7327.188379174152, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03259678841686081, "grain_number": 5, "grain_density": 1770.7774641132228, "grain_outer_radius": 0.03364004279869712, "grain_initial_inner_radius": 0.0150071044594583, "grain_initial_height": 0.11978473437064659, "grain_separation": 0.004754878760393469, "grains_center_of_mass_position": 0.3948520417707456, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.00041347157387067553, "throat_radius": 0.011090102521921098, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2564463067858118}], "aerodynamic_surfaces": [{"length": 0.5558310947742208, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1352685862009912]}, {"n": 4, "root_chord": 0.11945534314868292, "tip_chord": 0.05974861261669031, "span": 0.11069627174592134, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0484052632875618]}, {"top_radius": 0.06418729299507252, "bottom_radius": 0.04200329864929718, "length": 0.06029706779320863, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.699241641625261, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6182094016700278, "upper_button_position": 0.08103223995523323}], "rail_length": 5, "inclination": 84.50692064329158, "heading": 52.74761235497692} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 24, "radius": 0.06349779245926947, "mass": 15.83040838516131, "I_11_without_motor": 6.321, "I_22_without_motor": 6.307331480924691, "I_33_without_motor": 0.049734808569556144, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.986868907743112, "trigger": 800, "sampling_rate": 105, "lag": 1.306487374733884, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.9999071401334688, "trigger": "apogee", "sampling_rate": 105, "lag": 1.6624474606486757, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 5100.176434958228, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03318709362846449, "grain_number": 5, "grain_density": 1884.3206172743958, "grain_outer_radius": 0.033229322295293955, "grain_initial_inner_radius": 0.01566407995973153, "grain_initial_height": 0.11939338823721432, "grain_separation": 0.00337919104444369, "grains_center_of_mass_position": 0.3964436415480343, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.00041657452213572963, "throat_radius": 0.010038637515811466, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2549920011394837}], "aerodynamic_surfaces": [{"length": 0.5588806667686737, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1335087302986846]}, {"n": 4, "root_chord": 0.12096911434440984, "tip_chord": 0.060579532205768616, "span": 0.10942215935242752, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0489371105203595]}, {"top_radius": 0.06479727766674391, "bottom_radius": 0.042455281436162735, "length": 0.058961199571552006, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6992568250269238, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6170209376914776, "upper_button_position": 0.08223588733544618}], "rail_length": 5, "inclination": 85.31260312126922, "heading": 54.60310557901257} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 25, "radius": 0.0635034767740691, "mass": 14.473133168807818, "I_11_without_motor": 6.321, "I_22_without_motor": 6.314157512663184, "I_33_without_motor": 0.04889696873324676, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.166180032806391, "trigger": 800, "sampling_rate": 105, "lag": 1.444443190573961, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.9222518517648833, "trigger": "apogee", "sampling_rate": 105, "lag": 1.578967793691044, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 6747.593181220529, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03339213844272024, "grain_number": 5, "grain_density": 1766.5251094854266, "grain_outer_radius": 0.033049770480977514, "grain_initial_inner_radius": 0.015072758398978614, "grain_initial_height": 0.11954237196440844, "grain_separation": 0.006747663723533158, "grains_center_of_mass_position": 0.39728163201573646, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.00040915838828450114, "throat_radius": 0.011106433784606226, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2549789089031034}], "aerodynamic_surfaces": [{"length": 0.5573615383899484, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1345157262485654]}, {"n": 4, "root_chord": 0.12000584296683708, "tip_chord": 0.06039242720272283, "span": 0.10944203375023989, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0478399658762683]}, {"top_radius": 0.06427304844014263, "bottom_radius": 0.04362518924575842, "length": 0.059429250291222945, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.7016961426113497, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6167772016982755, "upper_button_position": 0.08491894091307417}], "rail_length": 5, "inclination": 84.14429779895038, "heading": 52.00650236133977} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 3, "radius": 0.06349743451992218, "mass": 15.036209974819245, "I_11_without_motor": 6.321, "I_22_without_motor": 6.328157884606955, "I_33_without_motor": 0.020809858026901485, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.933585095155895, "trigger": 800, "sampling_rate": 105, "lag": 1.597479007780775, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.031554050082618, "trigger": "apogee", "sampling_rate": 105, "lag": 1.4940038776674385, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 5461.218409447379, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.033178989012976015, "grain_number": 5, "grain_density": 1846.1531627920788, "grain_outer_radius": 0.03343898860151159, "grain_initial_inner_radius": 0.016206673218069706, "grain_initial_height": 0.1191992730196467, "grain_separation": 0.0041334748134873155, "grains_center_of_mass_position": 0.39722733218563683, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.0009667365815448472, "throat_radius": 0.01030357376889579, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2563677102876298}], "aerodynamic_surfaces": [{"length": 0.5589870716448792, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.133722241800354]}, {"n": 4, "root_chord": 0.12083847429163766, "tip_chord": 0.060012508576741064, "span": 0.10904424651889484, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0497846202268302]}, {"top_radius": 0.06440493671436263, "bottom_radius": 0.043586877621665035, "length": 0.05953915724976317, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.698042811757638, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6172510529884843, "upper_button_position": 0.08079175876915379}], "rail_length": 5, "inclination": 83.96012019982963, "heading": 54.47657582359791} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 10, "radius": 0.06350175690119066, "mass": 14.549142208122827, "I_11_without_motor": 6.321, "I_22_without_motor": 6.326594091088183, "I_33_without_motor": 0.03710090262067121, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.918779719478051, "trigger": 800, "sampling_rate": 105, "lag": 1.5532740210965583, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.8717575472916979, "trigger": "apogee", "sampling_rate": 105, "lag": 1.6684736124636208, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 7945.843186034017, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03289418847549375, "grain_number": 5, "grain_density": 1709.241093432216, "grain_outer_radius": 0.0325544293938807, "grain_initial_inner_radius": 0.015435461971633799, "grain_initial_height": 0.11901578165042781, "grain_separation": 0.0071511540336217354, "grains_center_of_mass_position": 0.3973355496372836, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.0007628134779484506, "throat_radius": 0.010835780912748595, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2562548633384836}], "aerodynamic_surfaces": [{"length": 0.5592623692045254, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.133809753309572]}, {"n": 4, "root_chord": 0.1200839555239807, "tip_chord": 0.05994580624437321, "span": 0.11034898118263718, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0494388771403702]}, {"top_radius": 0.06462883225148824, "bottom_radius": 0.04330043979825882, "length": 0.06041294199200335, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.7000916725817011, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6175799723745381, "upper_button_position": 0.08251170020716303}], "rail_length": 5, "inclination": 84.63883968201144, "heading": 51.776176862661856} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 28, "radius": 0.06349705629815046, "mass": 14.123173705271643, "I_11_without_motor": 6.321, "I_22_without_motor": 6.321789717956909, "I_33_without_motor": 0.03757242012180704, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.933864321276971, "trigger": 800, "sampling_rate": 105, "lag": 1.3772029200894804, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.0460831129194414, "trigger": "apogee", "sampling_rate": 105, "lag": 1.7251040755779377, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 8380.428087484768, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03356381530138269, "grain_number": 5, "grain_density": 1778.8018692672638, "grain_outer_radius": 0.032601232663090625, "grain_initial_inner_radius": 0.015407918126331977, "grain_initial_height": 0.11946226618104315, "grain_separation": 0.003888874755026696, "grains_center_of_mass_position": 0.39648179816859264, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.00010676080828896992, "throat_radius": 0.011914432665832444, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2557821487789416}], "aerodynamic_surfaces": [{"length": 0.5597763110459355, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1343778835318552]}, {"n": 4, "root_chord": 0.12052811157713465, "tip_chord": 0.0589963588844005, "span": 0.10906376174051868, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0490279322785745]}, {"top_radius": 0.06256583437416038, "bottom_radius": 0.04262291865880592, "length": 0.061321036336889706, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6999880172218871, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.617865706959014, "upper_button_position": 0.08212231026287309}], "rail_length": 5, "inclination": 84.99111462213077, "heading": 55.64381195735424} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 3, "radius": 0.06350712392139016, "mass": 14.757195794026398, "I_11_without_motor": 6.321, "I_22_without_motor": 6.314946562983625, "I_33_without_motor": 0.0413199832719251, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.926631088450291, "trigger": 800, "sampling_rate": 105, "lag": 1.614295195681567, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.0614639608042675, "trigger": "apogee", "sampling_rate": 105, "lag": 0.9597354377586996, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 6018.729975018477, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03292182548393906, "grain_number": 5, "grain_density": 1773.9816977872733, "grain_outer_radius": 0.03286325894637418, "grain_initial_inner_radius": 0.015208531177743352, "grain_initial_height": 0.11803009505850094, "grain_separation": 0.006183718692156587, "grains_center_of_mass_position": 0.3984108330378667, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.0007785344345249372, "throat_radius": 0.010540839128373464, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2563649483166277}], "aerodynamic_surfaces": [{"length": 0.5592344342181025, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1342717809565317]}, {"n": 4, "root_chord": 0.12046562900988994, "tip_chord": 0.06015563965097916, "span": 0.11033953352236586, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0501540504579356]}, {"top_radius": 0.06265764135964348, "bottom_radius": 0.042796437579250356, "length": 0.05962491916009492, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6985486637619776, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6173711707734717, "upper_button_position": 0.08117749298850585}], "rail_length": 5, "inclination": 84.27972185405488, "heading": 49.11395444365379} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 5, "radius": 0.06349439034172337, "mass": 14.511828482423246, "I_11_without_motor": 6.321, "I_22_without_motor": 6.322557061399875, "I_33_without_motor": 0.023858766674600802, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.999014528868885, "trigger": 800, "sampling_rate": 105, "lag": 1.5097901210455131, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.9983767055783637, "trigger": "apogee", "sampling_rate": 105, "lag": 1.7339958538677167, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 5527.326388339707, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03319216579474029, "grain_number": 5, "grain_density": 1783.7190255339208, "grain_outer_radius": 0.032852794071041025, "grain_initial_inner_radius": 0.014970681871701585, "grain_initial_height": 0.11971804794880396, "grain_separation": 0.004879803995147723, "grains_center_of_mass_position": 0.3957458204141297, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.0004388526374906204, "throat_radius": 0.010711310012743714, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.255407265024171}], "aerodynamic_surfaces": [{"length": 0.5575487799632869, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1319916949927447]}, {"n": 4, "root_chord": 0.11976719404362368, "tip_chord": 0.0602899706761204, "span": 0.10951722560212694, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0491837633134198]}, {"top_radius": 0.06428310263768562, "bottom_radius": 0.042767384654531435, "length": 0.059757643693485386, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6981047632365266, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.619618773664377, "upper_button_position": 0.07848598957214958}], "rail_length": 5, "inclination": 85.45483499663216, "heading": 54.220028857512666} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 12, "radius": 0.06348897430717483, "mass": 15.058483311162382, "I_11_without_motor": 6.321, "I_22_without_motor": 6.3211105500983225, "I_33_without_motor": 0.04368054003578594, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.806694743300474, "trigger": 800, "sampling_rate": 105, "lag": 1.3614997181239026, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.0350322628023303, "trigger": "apogee", "sampling_rate": 105, "lag": 1.488708677510769, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 3390.0365457255234, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03329832702812169, "grain_number": 5, "grain_density": 1841.9056216115919, "grain_outer_radius": 0.03265677065908386, "grain_initial_inner_radius": 0.01496239709097564, "grain_initial_height": 0.11978120124839382, "grain_separation": 0.0046909039138377595, "grains_center_of_mass_position": 0.39652419549132584, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.0006029574954276985, "throat_radius": 0.011139811102657401, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2534928158178336}], "aerodynamic_surfaces": [{"length": 0.5575443709218424, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1350695385716087]}, {"n": 4, "root_chord": 0.11985097167345075, "tip_chord": 0.05963472860749215, "span": 0.11027111820190999, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0489780726962399]}, {"top_radius": 0.0640996813261264, "bottom_radius": 0.04402776264876148, "length": 0.0614200691076832, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.699173144094483, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6166096855093683, "upper_button_position": 0.0825634585851146}], "rail_length": 5, "inclination": 83.67686652148507, "heading": 51.54488396734047} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 30, "radius": 0.06349246838909713, "mass": 14.826204145902281, "I_11_without_motor": 6.321, "I_22_without_motor": 6.322271890140243, "I_33_without_motor": 0.030662831007392553, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.945497373877698, "trigger": 800, "sampling_rate": 105, "lag": 1.4059600010241244, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.1268054769508686, "trigger": "apogee", "sampling_rate": 105, "lag": 1.5478748618041258, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 5176.828154802068, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.033466378220068815, "grain_number": 5, "grain_density": 1781.2803700756092, "grain_outer_radius": 0.033622704626113296, "grain_initial_inner_radius": 0.014964989560786093, "grain_initial_height": 0.12112037554901918, "grain_separation": 0.004920474725492944, "grains_center_of_mass_position": 0.3969636433843197, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.00023369905186361103, "throat_radius": 0.011788475871149442, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.254266549869575}], "aerodynamic_surfaces": [{"length": 0.5576635013586334, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1339762614144924]}, {"n": 4, "root_chord": 0.11980545590277819, "tip_chord": 0.06003119121503844, "span": 0.11021512303867356, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.048162918289076]}, {"top_radius": 0.06215287024568877, "bottom_radius": 0.04353991021182836, "length": 0.059686603527171964, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6989219641076875, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6171773080284558, "upper_button_position": 0.08174465607923165}], "rail_length": 5, "inclination": 83.5604442635234, "heading": 53.39351157093405} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 7, "radius": 0.06349869140597078, "mass": 14.230120446345197, "I_11_without_motor": 6.321, "I_22_without_motor": 6.322198705483838, "I_33_without_motor": 0.0460586260595645, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.053143490032456, "trigger": 800, "sampling_rate": 105, "lag": 1.490070135913312, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.8989419773806486, "trigger": "apogee", "sampling_rate": 105, "lag": 1.5289319036937843, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 6559.024357221486, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03319730326075547, "grain_number": 5, "grain_density": 1797.8957292224316, "grain_outer_radius": 0.03287147274515818, "grain_initial_inner_radius": 0.015151281478004326, "grain_initial_height": 0.12025202990673295, "grain_separation": 0.003959309636922095, "grains_center_of_mass_position": 0.39607013080810183, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.0003962741879448741, "throat_radius": 0.010603587591186651, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.256055789328302}], "aerodynamic_surfaces": [{"length": 0.5582915458384061, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.133268803385484]}, {"n": 4, "root_chord": 0.11994098837984403, "tip_chord": 0.059422708989922794, "span": 0.1097632816777115, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.050618027453366]}, {"top_radius": 0.06464450489184448, "bottom_radius": 0.0428688581243827, "length": 0.05989946211176852, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6994439031848404, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6175279982583463, "upper_button_position": 0.08191590492649414}], "rail_length": 5, "inclination": 85.5734203936308, "heading": 54.23748109698345} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 6, "radius": 0.06350859414346947, "mass": 15.08123397592947, "I_11_without_motor": 6.321, "I_22_without_motor": 6.327146902967929, "I_33_without_motor": 0.038358653698132746, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.185227155011349, "trigger": 800, "sampling_rate": 105, "lag": 1.6151479931612402, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.9678223876898537, "trigger": "apogee", "sampling_rate": 105, "lag": 1.8070908043638352, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 6577.049220883177, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03259700097307357, "grain_number": 5, "grain_density": 1889.2181195132098, "grain_outer_radius": 0.03281267011689317, "grain_initial_inner_radius": 0.015123000456895172, "grain_initial_height": 0.11847264426720913, "grain_separation": 0.005268131423275146, "grains_center_of_mass_position": 0.3973327145739362, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.0016234323465176249, "throat_radius": 0.010835230795250126, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2548849957481993}], "aerodynamic_surfaces": [{"length": 0.5589633629929319, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1326835053032474]}, {"n": 4, "root_chord": 0.1199940157349497, "tip_chord": 0.06043123070468818, "span": 0.11000065592763485, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0496091812228723]}, {"top_radius": 0.06276768351463742, "bottom_radius": 0.044048138009539405, "length": 0.05925510722595696, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.7026253750503199, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6175662233988229, "upper_button_position": 0.08505915165149691}], "rail_length": 5, "inclination": 85.62189855249338, "heading": 53.03933606508622} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 24, "radius": 0.06349285572117794, "mass": 14.0991917627014, "I_11_without_motor": 6.321, "I_22_without_motor": 6.302578184308834, "I_33_without_motor": 0.031192526030868573, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.112652889036847, "trigger": 800, "sampling_rate": 105, "lag": 1.4544041690223417, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.110808914694972, "trigger": "apogee", "sampling_rate": 105, "lag": 1.453024616529919, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 6542.210093453685, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03215461280452752, "grain_number": 5, "grain_density": 1845.716865292814, "grain_outer_radius": 0.03337593093216716, "grain_initial_inner_radius": 0.014666509634611899, "grain_initial_height": 0.11982584607544652, "grain_separation": 0.004500199048877129, "grains_center_of_mass_position": 0.39725250572398374, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.0005178740669312953, "throat_radius": 0.011887122187614736, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.254494635467359}], "aerodynamic_surfaces": [{"length": 0.5582585865011, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1355608196819487]}, {"n": 4, "root_chord": 0.11967868525767447, "tip_chord": 0.06041915304652207, "span": 0.11067746328954345, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.050179759963341]}, {"top_radius": 0.062277315533638467, "bottom_radius": 0.04244566435902549, "length": 0.05812886068456072, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.7011179624454615, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6164622486261881, "upper_button_position": 0.08465571381927339}], "rail_length": 5, "inclination": 85.28516776655833, "heading": 54.667427025718624} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 27, "radius": 0.06348830085282056, "mass": 14.882681968696248, "I_11_without_motor": 6.321, "I_22_without_motor": 6.296919223333103, "I_33_without_motor": 0.01735262091967832, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.038949419421275, "trigger": 800, "sampling_rate": 105, "lag": 1.663550509638369, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.10711558860621, "trigger": "apogee", "sampling_rate": 105, "lag": 1.851783766727872, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 7018.328971240856, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.032893145044193245, "grain_number": 5, "grain_density": 1820.949250316846, "grain_outer_radius": 0.03317081582341839, "grain_initial_inner_radius": 0.014767684909702001, "grain_initial_height": 0.12109336437516176, "grain_separation": 0.006751065574890648, "grains_center_of_mass_position": 0.39572180895868, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.0011419891598097149, "throat_radius": 0.011470435308868307, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2538797326001356}], "aerodynamic_surfaces": [{"length": 0.5588231758083387, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.134190447767395]}, {"n": 4, "root_chord": 0.11957936472301947, "tip_chord": 0.0596012810320038, "span": 0.10945902546471149, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0501113615661428]}, {"top_radius": 0.0634549757632317, "bottom_radius": 0.04257305378268893, "length": 0.0596555921107936, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.7001154714685096, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6198215803456679, "upper_button_position": 0.08029389112284169}], "rail_length": 5, "inclination": 86.12913542246108, "heading": 54.35429031621445} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 8, "radius": 0.0635041630713396, "mass": 14.239149646523497, "I_11_without_motor": 6.321, "I_22_without_motor": 6.325401843417168, "I_33_without_motor": 0.0391906674942733, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.945290726653068, "trigger": 800, "sampling_rate": 105, "lag": 1.582706429176969, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.019018037048352, "trigger": "apogee", "sampling_rate": 105, "lag": 1.5463022098488926, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 7524.341754351671, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03302447704859476, "grain_number": 5, "grain_density": 1767.264966070118, "grain_outer_radius": 0.03273578260363594, "grain_initial_inner_radius": 0.014792063655201809, "grain_initial_height": 0.11944262930690712, "grain_separation": 0.005110137774917791, "grains_center_of_mass_position": 0.39578505089475297, "center_of_dry_mass_position": 0.317, "nozzle_position": -2.3175008766391544e-05, "throat_radius": 0.012330850972662987, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2537695068067107}], "aerodynamic_surfaces": [{"length": 0.5588215924463259, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1328834330713755]}, {"n": 4, "root_chord": 0.1199021935388457, "tip_chord": 0.06039293242532582, "span": 0.10966353700442702, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0492806676805786]}, {"top_radius": 0.06314336794599833, "bottom_radius": 0.04103506603327466, "length": 0.060918494828026845, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.7001474161717912, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6173932777304869, "upper_button_position": 0.0827541384413043}], "rail_length": 5, "inclination": 86.22967990849415, "heading": 50.53754878850209} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 30, "radius": 0.06350062494582949, "mass": 15.343970375031695, "I_11_without_motor": 6.321, "I_22_without_motor": 6.327279447330628, "I_33_without_motor": 0.026328274855093335, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.048288369115896, "trigger": 800, "sampling_rate": 105, "lag": 1.6228525387273725, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.9669438069616259, "trigger": "apogee", "sampling_rate": 105, "lag": 1.7479220198436785, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 5973.9398228687205, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03315902554805301, "grain_number": 5, "grain_density": 1764.3383194857067, "grain_outer_radius": 0.032759471322047644, "grain_initial_inner_radius": 0.014404099387120476, "grain_initial_height": 0.11931497881514237, "grain_separation": 0.004442217531142403, "grains_center_of_mass_position": 0.3982944515942796, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.00152255508622675, "throat_radius": 0.011407997384681222, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2539698024647843}], "aerodynamic_surfaces": [{"length": 0.5579938629651594, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.133090859957866]}, {"n": 4, "root_chord": 0.12051285093894681, "tip_chord": 0.06031276350597265, "span": 0.11018637183542702, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0502115726622683]}, {"top_radius": 0.06369659912199377, "bottom_radius": 0.04217611798127526, "length": 0.05970363858580814, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6971624767562781, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6195806465133274, "upper_button_position": 0.07758183024295062}], "rail_length": 5, "inclination": 86.27842755524009, "heading": 49.755545809360484} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 25, "radius": 0.06350744251137265, "mass": 15.09545405928696, "I_11_without_motor": 6.321, "I_22_without_motor": 6.30588824418657, "I_33_without_motor": 0.0331948403499901, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.96861324750267, "trigger": 800, "sampling_rate": 105, "lag": 1.573989669485147, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.005258938894275, "trigger": "apogee", "sampling_rate": 105, "lag": 1.7205390488833778, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 7045.211377396375, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.0338996615367818, "grain_number": 5, "grain_density": 1764.0493333933991, "grain_outer_radius": 0.03271829974062877, "grain_initial_inner_radius": 0.015123293050648747, "grain_initial_height": 0.12116663363820428, "grain_separation": 0.004560852609572723, "grains_center_of_mass_position": 0.3973582622803934, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.0007215085057244918, "throat_radius": 0.010784667189442848, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2556452149874053}], "aerodynamic_surfaces": [{"length": 0.5586659512479353, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1335278927889882]}, {"n": 4, "root_chord": 0.12071517883027967, "tip_chord": 0.0598883743408181, "span": 0.11061578599912787, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0504732528798342]}, {"top_radius": 0.061479208287981715, "bottom_radius": 0.04476953702172075, "length": 0.06073824962510204, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6992852406648619, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6173146074716543, "upper_button_position": 0.08197063319320752}], "rail_length": 5, "inclination": 84.68319100123406, "heading": 54.189263990975526} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 17, "radius": 0.06349455718887169, "mass": 14.887415207410035, "I_11_without_motor": 6.321, "I_22_without_motor": 6.320465572362404, "I_33_without_motor": 0.030598423962824983, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.905167071652272, "trigger": 800, "sampling_rate": 105, "lag": 1.614389587965084, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.9408958095850001, "trigger": "apogee", "sampling_rate": 105, "lag": 0.9863463094385564, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 7802.112945200826, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03246697345486257, "grain_number": 5, "grain_density": 1870.2690491251096, "grain_outer_radius": 0.03294910037970672, "grain_initial_inner_radius": 0.015090361951501109, "grain_initial_height": 0.12118352267748121, "grain_separation": 0.00440899282780096, "grains_center_of_mass_position": 0.39605818443457236, "center_of_dry_mass_position": 0.317, "nozzle_position": -5.1847338411459676e-05, "throat_radius": 0.011430172565306212, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2554609815987887}], "aerodynamic_surfaces": [{"length": 0.5578690647847413, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.134076194493176]}, {"n": 4, "root_chord": 0.11952598259491723, "tip_chord": 0.06022399994528144, "span": 0.11062233320162532, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0504490373844608]}, {"top_radius": 0.06151230069881279, "bottom_radius": 0.042968606159515886, "length": 0.05838550568561321, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.7024488641351397, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6173091818661893, "upper_button_position": 0.08513968226895041}], "rail_length": 5, "inclination": 86.45015632503704, "heading": 54.200319720269356} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 15, "radius": 0.06350488589791063, "mass": 14.430923854187728, "I_11_without_motor": 6.321, "I_22_without_motor": 6.31833401743427, "I_33_without_motor": 0.04073543950205016, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.00245743005434, "trigger": 800, "sampling_rate": 105, "lag": 1.42153396570128, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.0678326366276096, "trigger": "apogee", "sampling_rate": 105, "lag": 1.3685666231236249, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 6190.163572455009, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.0336974201355807, "grain_number": 5, "grain_density": 1737.1194229461462, "grain_outer_radius": 0.0336772460064573, "grain_initial_inner_radius": 0.015279909471779053, "grain_initial_height": 0.11939007713168291, "grain_separation": 0.0034895382643139825, "grains_center_of_mass_position": 0.3965372608832396, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.00048343945196766366, "throat_radius": 0.011484892642122496, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.255818472383435}], "aerodynamic_surfaces": [{"length": 0.559655232420582, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1342346704250672]}, {"n": 4, "root_chord": 0.12005812964672272, "tip_chord": 0.06012497141081534, "span": 0.10933218960725932, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0500228053433207]}, {"top_radius": 0.06307277956556913, "bottom_radius": 0.04460221393597581, "length": 0.06062859246228136, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.699985527922972, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6180555649715134, "upper_button_position": 0.0819299629514586}], "rail_length": 5, "inclination": 84.06735527187571, "heading": 51.627267512933734} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 21, "radius": 0.0634989618732998, "mass": 15.702657161423273, "I_11_without_motor": 6.321, "I_22_without_motor": 6.321853872089236, "I_33_without_motor": 0.04878757957731296, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.038654294373378, "trigger": 800, "sampling_rate": 105, "lag": 1.6521135153406716, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.0853817897648086, "trigger": "apogee", "sampling_rate": 105, "lag": 1.446439603373895, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 4701.825059972517, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03274441801914148, "grain_number": 5, "grain_density": 1881.0241258707003, "grain_outer_radius": 0.03278748778719712, "grain_initial_inner_radius": 0.015020305947445417, "grain_initial_height": 0.1206241846894501, "grain_separation": 0.00690279535991399, "grains_center_of_mass_position": 0.3970080431269157, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.0012816968001657285, "throat_radius": 0.01157747292064822, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2543175432856517}], "aerodynamic_surfaces": [{"length": 0.5603041465473848, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1342603000011733]}, {"n": 4, "root_chord": 0.11978367368247034, "tip_chord": 0.061056613868349846, "span": 0.11009624704310296, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0477509663619837]}, {"top_radius": 0.06364377981582196, "bottom_radius": 0.043470905879548195, "length": 0.05941117959147104, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6995487854301886, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6193455246053537, "upper_button_position": 0.08020326082483487}], "rail_length": 5, "inclination": 84.28263463738632, "heading": 48.577058211496826} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 17, "radius": 0.06349859845820183, "mass": 15.536294576361628, "I_11_without_motor": 6.321, "I_22_without_motor": 6.339231283984124, "I_33_without_motor": 0.04589513462970105, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.007892456337862, "trigger": 800, "sampling_rate": 105, "lag": 1.4906798647356387, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.9460983770926951, "trigger": "apogee", "sampling_rate": 105, "lag": 1.7556917300574049, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 4679.861920183247, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.033040577513841395, "grain_number": 5, "grain_density": 1820.7981190446603, "grain_outer_radius": 0.0330556023630006, "grain_initial_inner_radius": 0.01453721731842722, "grain_initial_height": 0.12103284131427614, "grain_separation": 0.005176620900988839, "grains_center_of_mass_position": 0.39651051320917274, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.001035708872199685, "throat_radius": 0.01176007152483679, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2556297382157324}], "aerodynamic_surfaces": [{"length": 0.5594154225887948, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1332935332532756]}, {"n": 4, "root_chord": 0.11997215034129366, "tip_chord": 0.06035915286724394, "span": 0.10994396798128367, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.050812253903163]}, {"top_radius": 0.06263867674185546, "bottom_radius": 0.044815943242650744, "length": 0.059999092900904556, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6994799009720818, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6169006818224201, "upper_button_position": 0.08257921914966171}], "rail_length": 5, "inclination": 85.60311472426292, "heading": 50.2556874828904} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 24, "radius": 0.06350961652093641, "mass": 14.856898775437942, "I_11_without_motor": 6.321, "I_22_without_motor": 6.311328047398544, "I_33_without_motor": 0.044474806771103485, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.10899521269942, "trigger": 800, "sampling_rate": 105, "lag": 1.7176773093995306, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.9740244605764622, "trigger": "apogee", "sampling_rate": 105, "lag": 1.4101895403322091, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 5824.423080857596, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.0329165804311135, "grain_number": 5, "grain_density": 1845.9886201595514, "grain_outer_radius": 0.03302902556555971, "grain_initial_inner_radius": 0.015576040053522847, "grain_initial_height": 0.11875703909590252, "grain_separation": 0.004053896559615764, "grains_center_of_mass_position": 0.3968781354080911, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.0001481365017910036, "throat_radius": 0.010284320564042104, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2549957160646676}], "aerodynamic_surfaces": [{"length": 0.5596954913249531, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1343823013328866]}, {"n": 4, "root_chord": 0.11996165305879347, "tip_chord": 0.05904905572505063, "span": 0.10994195277364488, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0488102949844715]}, {"top_radius": 0.06285616353984486, "bottom_radius": 0.043290457846543604, "length": 0.059409674067830695, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.7000914556866284, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6190780984698379, "upper_button_position": 0.0810133572167906}], "rail_length": 5, "inclination": 84.45430191304013, "heading": 53.24502927721654} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 19, "radius": 0.0635019236329062, "mass": 14.066185162053669, "I_11_without_motor": 6.321, "I_22_without_motor": 6.33023891562729, "I_33_without_motor": 0.03160067000255987, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.037375231463686, "trigger": 800, "sampling_rate": 105, "lag": 1.4654105108950752, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.0977041635896727, "trigger": "apogee", "sampling_rate": 105, "lag": 1.7576272456627253, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 5624.192436730688, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03251708588750148, "grain_number": 5, "grain_density": 1803.7522163713818, "grain_outer_radius": 0.03293303266411425, "grain_initial_inner_radius": 0.014902273644540855, "grain_initial_height": 0.12076586891362319, "grain_separation": 0.003659997951833788, "grains_center_of_mass_position": 0.39500881441197894, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.0009530994108397453, "throat_radius": 0.011702072656281122, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2559121700163038}], "aerodynamic_surfaces": [{"length": 0.5575405435326249, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1336534885661131]}, {"n": 4, "root_chord": 0.11991950398135265, "tip_chord": 0.059950432311922486, "span": 0.11003586419562267, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0493939445897476]}, {"top_radius": 0.06180851293796316, "bottom_radius": 0.04432741685915527, "length": 0.05995575269620631, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.7009476264141186, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6202947913017857, "upper_button_position": 0.0806528351123329}], "rail_length": 5, "inclination": 83.22674914284435, "heading": 52.95021700886993} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 22, "radius": 0.0634999279209893, "mass": 14.677466850170433, "I_11_without_motor": 6.321, "I_22_without_motor": 6.317240094313157, "I_33_without_motor": 0.028302190121379557, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.173383154679213, "trigger": 800, "sampling_rate": 105, "lag": 1.4070560375678367, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.1402584367530584, "trigger": "apogee", "sampling_rate": 105, "lag": 1.552687546048584, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 7683.502058289, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03304670507665597, "grain_number": 5, "grain_density": 1738.4140881564338, "grain_outer_radius": 0.033017220758382315, "grain_initial_inner_radius": 0.014889639604763406, "grain_initial_height": 0.12040472145071134, "grain_separation": 0.004800166555709796, "grains_center_of_mass_position": 0.39529420477501054, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.0007880229823142239, "throat_radius": 0.010690717026880089, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2533507712238883}], "aerodynamic_surfaces": [{"length": 0.5567767058256697, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1343240543575641]}, {"n": 4, "root_chord": 0.12047407976534229, "tip_chord": 0.06044261691821858, "span": 0.10897699951084462, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0499909383122348]}, {"top_radius": 0.06321244558310458, "bottom_radius": 0.042993573286898734, "length": 0.060690626113990294, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.7000846075661536, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6193720023400624, "upper_button_position": 0.08071260522609125}], "rail_length": 5, "inclination": 86.2655551930799, "heading": 50.74057647173047} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 28, "radius": 0.06350324333844891, "mass": 14.416376730610171, "I_11_without_motor": 6.321, "I_22_without_motor": 6.31184314956329, "I_33_without_motor": 0.029277560506418797, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.169021112212215, "trigger": 800, "sampling_rate": 105, "lag": 1.3548254650030713, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.9199799513884394, "trigger": "apogee", "sampling_rate": 105, "lag": 1.3906165186174055, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 6232.517433835797, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.032625285369376554, "grain_number": 5, "grain_density": 1851.914181639704, "grain_outer_radius": 0.03318698852189525, "grain_initial_inner_radius": 0.01568096604564223, "grain_initial_height": 0.1193343987949351, "grain_separation": 0.004615336351617327, "grains_center_of_mass_position": 0.3962425256515898, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.0011052709121461357, "throat_radius": 0.011331315854668712, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2541039435133101}], "aerodynamic_surfaces": [{"length": 0.5583313806072471, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1346373766885023]}, {"n": 4, "root_chord": 0.12023781379374296, "tip_chord": 0.0600175571620146, "span": 0.11040102427643836, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0512571597959386]}, {"top_radius": 0.06149416957866327, "bottom_radius": 0.044634560306783984, "length": 0.05965379022287309, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6982160368214974, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6181734717646546, "upper_button_position": 0.08004256505684271}], "rail_length": 5, "inclination": 84.57525310803103, "heading": 52.98174404348843} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 19, "radius": 0.0634944444617853, "mass": 14.355525240406728, "I_11_without_motor": 6.321, "I_22_without_motor": 6.312629168787949, "I_33_without_motor": 0.02850104179259591, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.141247511278797, "trigger": 800, "sampling_rate": 105, "lag": 1.546145843698987, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.9020516758614718, "trigger": "apogee", "sampling_rate": 105, "lag": 1.5452240565689404, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 7129.174501402416, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03353239534540677, "grain_number": 5, "grain_density": 1900.060608340611, "grain_outer_radius": 0.03291508504511614, "grain_initial_inner_radius": 0.014352217371430113, "grain_initial_height": 0.11953919238939101, "grain_separation": 0.0045778818379726876, "grains_center_of_mass_position": 0.3961783989048371, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.0013033964401244704, "throat_radius": 0.010891076621968561, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.254820835081322}], "aerodynamic_surfaces": [{"length": 0.5571351634791761, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1315414657736051]}, {"n": 4, "root_chord": 0.1200919892721906, "tip_chord": 0.05976820375727909, "span": 0.10947101236566135, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0510508470675448]}, {"top_radius": 0.06201059255974693, "bottom_radius": 0.043341140666026144, "length": 0.0599123412347966, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6989048217231505, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6186695958890003, "upper_button_position": 0.08023522583415021}], "rail_length": 5, "inclination": 83.51528103725204, "heading": 53.0014639854097} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 10, "radius": 0.06350106018608451, "mass": 13.924407077851685, "I_11_without_motor": 6.321, "I_22_without_motor": 6.326820881251539, "I_33_without_motor": 0.02986958528954678, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.048527966492273, "trigger": 800, "sampling_rate": 105, "lag": 1.5902006631592602, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.8892324749354281, "trigger": "apogee", "sampling_rate": 105, "lag": 1.6251834376820244, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 7508.10130715633, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.0319240281027893, "grain_number": 5, "grain_density": 1850.5926783128011, "grain_outer_radius": 0.033664223984823535, "grain_initial_inner_radius": 0.015028732842170876, "grain_initial_height": 0.11957256826203207, "grain_separation": 0.005044535978620604, "grains_center_of_mass_position": 0.3955556218664703, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.0006066331835518567, "throat_radius": 0.012125158843443479, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.253434751518294}], "aerodynamic_surfaces": [{"length": 0.5582705013968166, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1324382750401751]}, {"n": 4, "root_chord": 0.12083788079779771, "tip_chord": 0.059835733736456995, "span": 0.10986691204120996, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0501926818446154]}, {"top_radius": 0.06323998090682992, "bottom_radius": 0.04359758013450215, "length": 0.060640016015139124, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.7009313548369903, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.619162407445633, "upper_button_position": 0.08176894739135732}], "rail_length": 5, "inclination": 82.99098491530997, "heading": 53.08465759304224} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 11, "radius": 0.06349677289274533, "mass": 15.217709776706231, "I_11_without_motor": 6.321, "I_22_without_motor": 6.32175258715042, "I_33_without_motor": 0.033459201040714426, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 10.096602661490191, "trigger": 800, "sampling_rate": 105, "lag": 1.49396409511733, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.9720085551685576, "trigger": "apogee", "sampling_rate": 105, "lag": 1.3800358814129423, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 7291.859944129631, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03286255098889512, "grain_number": 5, "grain_density": 1766.3677896946615, "grain_outer_radius": 0.032734627954657224, "grain_initial_inner_radius": 0.015352246485480142, "grain_initial_height": 0.12063907289605554, "grain_separation": 0.005563805824237478, "grains_center_of_mass_position": 0.3956640642090927, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.0012330124869399171, "throat_radius": 0.010162279829192586, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2539163609254507}], "aerodynamic_surfaces": [{"length": 0.5589934632852431, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1334772004389817]}, {"n": 4, "root_chord": 0.12003103507713203, "tip_chord": 0.060007157881095584, "span": 0.10986526029259697, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0493237384065284]}, {"top_radius": 0.06277183025721901, "bottom_radius": 0.042988022665582465, "length": 0.057439786282093896, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6997446640244589, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6190247676395187, "upper_button_position": 0.08071989638494015}], "rail_length": 5, "inclination": 84.23171746111679, "heading": 49.527753617990584} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 22, "radius": 0.06349646712700412, "mass": 14.814700814397224, "I_11_without_motor": 6.321, "I_22_without_motor": 6.321544992542315, "I_33_without_motor": 0.04144368480385598, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.784322279807983, "trigger": 800, "sampling_rate": 105, "lag": 1.514681111835507, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.9913712254685946, "trigger": "apogee", "sampling_rate": 105, "lag": 1.1417382025107303, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 6961.5368868629685, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.0332900584493347, "grain_number": 5, "grain_density": 1788.2644189899684, "grain_outer_radius": 0.03308753719951774, "grain_initial_inner_radius": 0.014404582654050256, "grain_initial_height": 0.11886282772270461, "grain_separation": 0.006320449868136485, "grains_center_of_mass_position": 0.3981131019075248, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.00017776497846661547, "throat_radius": 0.010866721021756265, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2551342947682547}], "aerodynamic_surfaces": [{"length": 0.5584202748153241, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1332925035465926]}, {"n": 4, "root_chord": 0.11994623959052625, "tip_chord": 0.06053733305829076, "span": 0.11046021490057707, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0494544587721806]}, {"top_radius": 0.06257314656471137, "bottom_radius": 0.043319782433462004, "length": 0.059705173035873985, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6979990604581422, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6184120295740662, "upper_button_position": 0.07958703088407604}], "rail_length": 5, "inclination": 84.99589937631742, "heading": 51.887238286372636} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 4, "radius": 0.06350329530188674, "mass": 15.496453305544417, "I_11_without_motor": 6.321, "I_22_without_motor": 6.3186643284452035, "I_33_without_motor": 0.03950077227905335, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.88105682090641, "trigger": 800, "sampling_rate": 105, "lag": 1.3479343837879112, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.9612370302510007, "trigger": "apogee", "sampling_rate": 105, "lag": 1.3789775577365009, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 6782.298298373643, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03314152903223107, "grain_number": 5, "grain_density": 1894.1468996913864, "grain_outer_radius": 0.032694749462845674, "grain_initial_inner_radius": 0.014065073804489932, "grain_initial_height": 0.11959622509284373, "grain_separation": 0.003974991853732072, "grains_center_of_mass_position": 0.397716852247396, "center_of_dry_mass_position": 0.317, "nozzle_position": -0.0018820454638020388, "throat_radius": 0.01073279395891568, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2551170520864183}], "aerodynamic_surfaces": [{"length": 0.5597670641078055, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1348426935549736]}, {"n": 4, "root_chord": 0.12059750329274571, "tip_chord": 0.059581698346397705, "span": 0.1102813848132924, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0496196579028505]}, {"top_radius": 0.06489677704779642, "bottom_radius": 0.04318873444093642, "length": 0.05945155314026724, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6977594543350731, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6176268591659976, "upper_button_position": 0.08013259516907556}], "rail_length": 5, "inclination": 84.36696245438576, "heading": 51.29753106834522} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 10, "radius": 0.06350683275697407, "mass": 15.50203884001735, "I_11_without_motor": 6.321, "I_22_without_motor": 6.329234614352841, "I_33_without_motor": 0.03942543540618289, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.99705678394388, "trigger": 800, "sampling_rate": 105, "lag": 1.4864005383993102, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.9261335073472055, "trigger": "apogee", "sampling_rate": 105, "lag": 1.3443714064567047, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 8005.5706291441375, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03173794023037279, "grain_number": 5, "grain_density": 1832.2847409983933, "grain_outer_radius": 0.032785297874888826, "grain_initial_inner_radius": 0.014704362412556253, "grain_initial_height": 0.12077876924005805, "grain_separation": 0.0037027528553549662, "grains_center_of_mass_position": 0.39681844080092726, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.0008900775371926553, "throat_radius": 0.010678959998932978, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2561578769221484}], "aerodynamic_surfaces": [{"length": 0.557427788081872, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1344469733063216]}, {"n": 4, "root_chord": 0.11955388510819866, "tip_chord": 0.0605411069733704, "span": 0.10974109554384873, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0505154311823244]}, {"top_radius": 0.06344719682720237, "bottom_radius": 0.04316200610992135, "length": 0.058310525727021, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6996285939418921, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6194024929103658, "upper_button_position": 0.08022610103152639}], "rail_length": 5, "inclination": 85.53895274253726, "heading": 53.0149968650151} +{"elevation": 113, "gravity": "Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 26, "radius": 0.0635027211217431, "mass": 15.078500789243703, "I_11_without_motor": 6.321, "I_22_without_motor": 6.323893530066055, "I_33_without_motor": 0.03188238068989791, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)", "power_on_drag": "Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.791867275278832, "trigger": 800, "sampling_rate": 105, "lag": 1.5383774555509766, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 0.9846929514730729, "trigger": "apogee", "sampling_rate": 105, "lag": 1.6714485669192136, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 7684.489626218814, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.03363471170244506, "grain_number": 5, "grain_density": 1883.7104959971407, "grain_outer_radius": 0.032918135962112745, "grain_initial_inner_radius": 0.015256590744721637, "grain_initial_height": 0.11974726237237875, "grain_separation": 0.005701672701260577, "grains_center_of_mass_position": 0.39587480788878565, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.0007353244314329845, "throat_radius": 0.010482322779698225, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2540920606352421}], "aerodynamic_surfaces": [{"length": 0.5588416162332039, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.1348355999109105]}, {"n": 4, "root_chord": 0.11904564842863577, "tip_chord": 0.061157344766110004, "span": 0.10994040231917326, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/airfoils/NACA0012-radians.txt", "radians"], "name": "Fins", "position": [0, 0, -1.0501166747315005]}, {"top_radius": 0.06137425121555377, "bottom_radius": 0.04382040449893698, "length": 0.059674983070251444, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.700243544566463, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6167796839943969, "upper_button_position": 0.08346386057206612}], "rail_length": 5, "inclination": 84.42460213266236, "heading": 52.473469187557626} diff --git a/docs/notebooks/monte_carlo_analysis/monte_carlo_analysis_outputs/mrs.outputs.txt b/docs/notebooks/monte_carlo_analysis/monte_carlo_analysis_outputs/mrs.outputs.txt new file mode 100644 index 000000000..d299b6c68 --- /dev/null +++ b/docs/notebooks/monte_carlo_analysis/monte_carlo_analysis_outputs/mrs.outputs.txt @@ -0,0 +1,116 @@ +{"apogee": 2312.1872472947116, "frontal_surface_wind": -3.0496076096117806, "apogee_y": 792.0643463024578, "lateral_surface_wind": -4.933428593177471, "t_final": 245.8640635159601, "out_of_rail_velocity": 22.602627269750965, "initial_stability_margin": 2.5965475536989793, "out_of_rail_time": 0.3978685698191799, "y_impact": -808.8458905124497, "apogee_x": 473.2474243585599, "impact_velocity": -5.29159675326023, "max_mach_number": 0.6712121311796375, "x_impact": 414.05676153229047, "out_of_rail_stability_margin": 2.676329129911605, "apogee_time": 21.623341277710804} +{"apogee": 3234.4452475578596, "frontal_surface_wind": -4.337392440631757, "apogee_y": 914.6161005985731, "lateral_surface_wind": -4.330218954821568, "t_final": 308.6136950810929, "out_of_rail_velocity": 25.80568850560873, "initial_stability_margin": 2.5212083871217477, "out_of_rail_time": 0.3566948768302634, "y_impact": -1630.901738601504, "apogee_x": 602.5236652027419, "impact_velocity": -5.1912272264568395, "max_mach_number": 0.861332104930048, "x_impact": 104.54718624691004, "out_of_rail_stability_margin": 2.5904766702124973, "apogee_time": 24.92645235696848} +{"apogee": 3194.2919822661884, "frontal_surface_wind": -2.9590922434593336, "apogee_y": 854.6215605295408, "lateral_surface_wind": -5.500986420895066, "t_final": 295.676524528265, "out_of_rail_velocity": 25.519210213159013, "initial_stability_margin": 2.6368645237557438, "out_of_rail_time": 0.3601293622658367, "y_impact": -1824.7409214359986, "apogee_x": 401.250373504897, "impact_velocity": -5.205589117769717, "max_mach_number": 0.8486046757015585, "x_impact": 298.52792415153493, "out_of_rail_stability_margin": 2.710429230797741, "apogee_time": 24.821588922607702} +{"apogee": 2005.5355578422684, "frontal_surface_wind": -4.355137085242682, "apogee_y": 768.6167980634466, "lateral_surface_wind": -5.742328463616666, "t_final": 232.74850709159384, "out_of_rail_velocity": 21.398277969831224, "initial_stability_margin": 2.6161759295091533, "out_of_rail_time": 0.4172765756487621, "y_impact": -980.0914807790709, "apogee_x": 324.1875339535975, "impact_velocity": -5.305869194997984, "max_mach_number": 0.6068006591743482, "x_impact": 332.7869115355111, "out_of_rail_stability_margin": 2.705155629496209, "apogee_time": 20.335146326527934} +{"apogee": 3414.1326037550193, "frontal_surface_wind": -4.145622464456691, "apogee_y": 1067.5341992124293, "lateral_surface_wind": -5.070996962871586, "t_final": 300.0408912215984, "out_of_rail_velocity": 26.318761101307224, "initial_stability_margin": 2.562607630136216, "out_of_rail_time": 0.35084514654733395, "y_impact": -1330.8722645723942, "apogee_x": 699.8948582654266, "impact_velocity": -5.267158445220961, "max_mach_number": 0.8997684911744048, "x_impact": 246.0016314455594, "out_of_rail_stability_margin": 2.633413869721548, "apogee_time": 25.544778409497113} +{"apogee": 4005.43639180465, "frontal_surface_wind": -3.223183682158992, "apogee_y": 825.9614723383999, "lateral_surface_wind": -5.350529455973221, "t_final": 345.2287009395753, "out_of_rail_velocity": 28.807427900808356, "initial_stability_margin": 2.5127223551102076, "out_of_rail_time": 0.3266913066347211, "y_impact": -2783.6999083332653, "apogee_x": 304.34509604603164, "impact_velocity": -5.159243827155025, "max_mach_number": 1.0465990745418756, "x_impact": 274.508021686453, "out_of_rail_stability_margin": 2.582497802323176, "apogee_time": 27.11963324697822} +{"apogee": 3369.7430206875033, "frontal_surface_wind": -4.126067141026567, "apogee_y": 950.1893037301417, "lateral_surface_wind": -5.367758720812397, "t_final": 316.8351000294194, "out_of_rail_velocity": 26.198310409725064, "initial_stability_margin": 2.5461594160894894, "out_of_rail_time": 0.35212814103223733, "y_impact": -2102.9174668126843, "apogee_x": 528.1202151342061, "impact_velocity": -5.244655424517382, "max_mach_number": 0.8912612876513054, "x_impact": 295.44698025503527, "out_of_rail_stability_margin": 2.6169443098116285, "apogee_time": 25.361625858486242} +{"apogee": 3779.43184471028, "frontal_surface_wind": -3.839784837857332, "apogee_y": 1017.1362281915923, "lateral_surface_wind": -4.910293207964168, "t_final": 336.1199113741417, "out_of_rail_velocity": 28.007046184035932, "initial_stability_margin": 2.7079631823608246, "out_of_rail_time": 0.3342151669899769, "y_impact": -2233.606939193176, "apogee_x": 691.6998659764772, "impact_velocity": -5.204211528816122, "max_mach_number": 0.993326214818677, "x_impact": 552.5339765803068, "out_of_rail_stability_margin": 2.7732698548275985, "apogee_time": 26.50431154681348} +{"apogee": 3185.0551035062344, "frontal_surface_wind": -3.250221342604423, "apogee_y": 719.5241227445958, "lateral_surface_wind": -4.907401228617864, "t_final": 302.51757266636207, "out_of_rail_velocity": 25.323908942075047, "initial_stability_margin": 2.5235206581218628, "out_of_rail_time": 0.36237409173413077, "y_impact": -1692.6591002104685, "apogee_x": 248.44542375123808, "impact_velocity": -5.183812017743841, "max_mach_number": 0.838106938357358, "x_impact": 163.65118864302815, "out_of_rail_stability_margin": 2.6002457121681752, "apogee_time": 24.831323336189406} +{"apogee": 4360.224222438373, "frontal_surface_wind": -3.403890176664362, "apogee_y": 980.186891813364, "lateral_surface_wind": -4.802088843385686, "t_final": 364.96342175857956, "out_of_rail_velocity": 30.60334103581782, "initial_stability_margin": 2.524717905329552, "out_of_rail_time": 0.31183422104004316, "y_impact": -2498.457065905911, "apogee_x": 543.560310489271, "impact_velocity": -5.168709004091191, "max_mach_number": 1.1461922887188867, "x_impact": 723.2265098794728, "out_of_rail_stability_margin": 2.5869153993174057, "apogee_time": 28.00589933642195} +{"apogee": 2762.1274253479473, "frontal_surface_wind": -4.070528982556502, "apogee_y": 812.7838243619475, "lateral_surface_wind": -5.913753916100903, "t_final": 267.8450828614702, "out_of_rail_velocity": 24.059379341598707, "initial_stability_margin": 2.58362636006892, "out_of_rail_time": 0.3786335192192805, "y_impact": -1435.0197541939556, "apogee_x": 296.92146384538205, "impact_velocity": -5.237641896590559, "max_mach_number": 0.7585832534208544, "x_impact": 259.5001445167858, "out_of_rail_stability_margin": 2.6609143629105283, "apogee_time": 23.357549269012186} +{"apogee": 3534.9029570139965, "frontal_surface_wind": -3.556772875965321, "apogee_y": 955.189860659162, "lateral_surface_wind": -5.435875170107231, "t_final": 306.92149145825124, "out_of_rail_velocity": 26.66380763503703, "initial_stability_margin": 2.6703444503640443, "out_of_rail_time": 0.34726074279325186, "y_impact": -2042.842691963689, "apogee_x": 484.46842361899496, "impact_velocity": -5.310370168169911, "max_mach_number": 0.9166027454514214, "x_impact": 332.16529159305156, "out_of_rail_stability_margin": 2.7362632833331526, "apogee_time": 25.947382516023982} +{"apogee": 3614.108677032202, "frontal_surface_wind": -4.296163859984769, "apogee_y": 978.1209429350522, "lateral_surface_wind": -4.371126338703365, "t_final": 320.0212794065488, "out_of_rail_velocity": 26.983391051354356, "initial_stability_margin": 2.625766417156153, "out_of_rail_time": 0.34451205219065767, "y_impact": -1828.4758943841007, "apogee_x": 660.3848176093826, "impact_velocity": -5.281596964122639, "max_mach_number": 0.9406237539646314, "x_impact": 194.09444824854987, "out_of_rail_stability_margin": 2.6969536938736858, "apogee_time": 26.131961746211903} +{"apogee": 3420.125327779051, "frontal_surface_wind": -3.7147720364157335, "apogee_y": 1003.1138426347507, "lateral_surface_wind": -6.815589778246364, "t_final": 307.1071052351639, "out_of_rail_velocity": 26.305927590690537, "initial_stability_margin": 2.550302927550933, "out_of_rail_time": 0.35153480359971184, "y_impact": -2272.945648804256, "apogee_x": 395.3936923057035, "impact_velocity": -5.2613997087095825, "max_mach_number": 0.8987755788931121, "x_impact": 614.8138782700777, "out_of_rail_stability_margin": 2.623412668922972, "apogee_time": 25.537608446255753} +{"apogee": 2599.417973288354, "frontal_surface_wind": -4.053575984754723, "apogee_y": 927.8333628905247, "lateral_surface_wind": -5.144872938283375, "t_final": 266.1509698445134, "out_of_rail_velocity": 23.681316131526582, "initial_stability_margin": 2.5817014651361134, "out_of_rail_time": 0.38329336171287726, "y_impact": -985.611612000622, "apogee_x": 617.6760010948253, "impact_velocity": -5.2171482517136365, "max_mach_number": 0.7413040886536101, "x_impact": 186.92295218668716, "out_of_rail_stability_margin": 2.6642380764852502, "apogee_time": 22.693999601208716} +{"apogee": 3881.63118624118, "frontal_surface_wind": -4.280852505152617, "apogee_y": 984.2476932897227, "lateral_surface_wind": -4.987685358209447, "t_final": 353.2799308179348, "out_of_rail_velocity": 28.17678208210907, "initial_stability_margin": 2.5703527206804613, "out_of_rail_time": 0.3326944375337907, "y_impact": -2923.3277905344717, "apogee_x": 615.1102090779864, "impact_velocity": -5.24007835674783, "max_mach_number": 1.0085432606568356, "x_impact": 726.2910223190462, "out_of_rail_stability_margin": 2.6380206959954426, "apogee_time": 26.87395393578114} +{"apogee": 4031.169401620982, "frontal_surface_wind": -4.11796971326075, "apogee_y": 916.9618884321287, "lateral_surface_wind": -5.093478306219435, "t_final": 322.1276956345975, "out_of_rail_velocity": 28.449872107328087, "initial_stability_margin": 2.6498441091561453, "out_of_rail_time": 0.3299172983320498, "y_impact": -1861.991473397278, "apogee_x": 455.0624288057102, "impact_velocity": -5.266702602345353, "max_mach_number": 1.0267153764695038, "x_impact": 8.207178256443001, "out_of_rail_stability_margin": 2.7178633531523158, "apogee_time": 27.388868130772234} +{"apogee": 3630.871096962262, "frontal_surface_wind": -4.057872513219252, "apogee_y": 984.0222585072161, "lateral_surface_wind": -5.419495770233277, "t_final": 326.99993219534747, "out_of_rail_velocity": 27.326388564356307, "initial_stability_margin": 2.5362561693858328, "out_of_rail_time": 0.3403621287534829, "y_impact": -2262.674213265278, "apogee_x": 583.9293868737337, "impact_velocity": -5.165031068855398, "max_mach_number": 0.9606086083268497, "x_impact": 410.82143574367603, "out_of_rail_stability_margin": 2.6061762933856505, "apogee_time": 26.05904046583953} +{"apogee": 4130.258160463937, "frontal_surface_wind": -3.6319081395042936, "apogee_y": 943.6973762557913, "lateral_surface_wind": -4.712169364357847, "t_final": 364.8898914002856, "out_of_rail_velocity": 29.599646211168185, "initial_stability_margin": 2.522227777666711, "out_of_rail_time": 0.3198041630806601, "y_impact": -2670.5595652655275, "apogee_x": 487.6698196275945, "impact_velocity": -5.12929795011279, "max_mach_number": 1.0936557042964867, "x_impact": 534.8324912082843, "out_of_rail_stability_margin": 2.5918742492779416, "apogee_time": 27.364979590201383} +{"apogee": 3862.398160305433, "frontal_surface_wind": -3.6709131233479657, "apogee_y": 1071.7009529907107, "lateral_surface_wind": -4.546792618170283, "t_final": 332.80479874085256, "out_of_rail_velocity": 28.09435892996872, "initial_stability_margin": 2.680099639336055, "out_of_rail_time": 0.33300595820560636, "y_impact": -1909.1191815511158, "apogee_x": 655.9070469784183, "impact_velocity": -5.260306250250454, "max_mach_number": 1.003147340511129, "x_impact": 547.1331574199163, "out_of_rail_stability_margin": 2.7459316600454846, "apogee_time": 26.831604063336425} +{"apogee": 3457.1464938724657, "frontal_surface_wind": -4.301422769308096, "apogee_y": 1011.7402292625326, "lateral_surface_wind": -5.877747623929149, "t_final": 308.69588054117315, "out_of_rail_velocity": 26.473440963674634, "initial_stability_margin": 2.633346181758324, "out_of_rail_time": 0.34926778911475, "y_impact": -1955.4186993661742, "apogee_x": 500.19723883474825, "impact_velocity": -5.214710521217645, "max_mach_number": 0.9069460544703524, "x_impact": 409.81006045710393, "out_of_rail_stability_margin": 2.7030118600968995, "apogee_time": 25.65241907461697} +{"apogee": 2930.9360659665736, "frontal_surface_wind": -3.1719539568495065, "apogee_y": 803.6198681094676, "lateral_surface_wind": -4.855670123907706, "t_final": 290.12653538933733, "out_of_rail_velocity": 24.681480762767105, "initial_stability_margin": 2.546934959494983, "out_of_rail_time": 0.36987020312468777, "y_impact": -1402.321604171246, "apogee_x": 395.71997795018314, "impact_velocity": -5.133172180527211, "max_mach_number": 0.7954499920899426, "x_impact": 283.90707917187666, "out_of_rail_stability_margin": 2.6232516584976655, "apogee_time": 23.90412984599284} +{"apogee": 2947.5707444915397, "frontal_surface_wind": -4.289086579688394, "apogee_y": 994.8489167255198, "lateral_surface_wind": -5.933503287736684, "t_final": 281.6616344102024, "out_of_rail_velocity": 24.76456187349953, "initial_stability_margin": 2.635437213467015, "out_of_rail_time": 0.36887908645968137, "y_impact": -1648.86595664764, "apogee_x": 500.7151812249715, "impact_velocity": -5.3488048773179715, "max_mach_number": 0.8000757854119254, "x_impact": 440.83709190823913, "out_of_rail_stability_margin": 2.706743887934832, "apogee_time": 24.039151681641275} +{"apogee": 2666.3189863892594, "frontal_surface_wind": -4.56034313319912, "apogee_y": 821.9337762167993, "lateral_surface_wind": -5.215932086583531, "t_final": 269.71680254461467, "out_of_rail_velocity": 23.78711937617732, "initial_stability_margin": 2.5284615872968246, "out_of_rail_time": 0.3814587634779732, "y_impact": -1570.3483732328764, "apogee_x": 375.6763233482961, "impact_velocity": -5.214713521705962, "max_mach_number": 0.7437899980180568, "x_impact": -5.862120521368879, "out_of_rail_stability_margin": 2.6056045455930934, "apogee_time": 23.0091769478826} +{"apogee": 3357.987939458601, "frontal_surface_wind": -3.720513055880615, "apogee_y": 977.0754888373787, "lateral_surface_wind": -6.812457552814147, "t_final": 309.0255506832201, "out_of_rail_velocity": 26.109362392419918, "initial_stability_margin": 2.642543229387226, "out_of_rail_time": 0.3533952628420922, "y_impact": -2304.943935000412, "apogee_x": 363.9330885624899, "impact_velocity": -5.244235197847795, "max_mach_number": 0.8838008479833885, "x_impact": 572.1468404143658, "out_of_rail_stability_margin": 2.712971895624635, "apogee_time": 25.350421057412625} +{"apogee": 2404.1219938397217, "frontal_surface_wind": -3.5260176055200043, "apogee_y": 656.9723123561896, "lateral_surface_wind": -5.8763961595870375, "t_final": 253.71517269361172, "out_of_rail_velocity": 22.70334996901872, "initial_stability_margin": 2.558467947604102, "out_of_rail_time": 0.3960997678903855, "y_impact": -1556.1483110023582, "apogee_x": 183.0533533673235, "impact_velocity": -5.307949555780116, "max_mach_number": 0.6778736616975899, "x_impact": 117.66019734596827, "out_of_rail_stability_margin": 2.6361421835556467, "apogee_time": 22.072098881093225} +{"apogee": 3952.052833800142, "frontal_surface_wind": -4.4533036944613125, "apogee_y": 925.6540968870343, "lateral_surface_wind": -4.834334453496733, "t_final": 349.615364652483, "out_of_rail_velocity": 28.805563889652156, "initial_stability_margin": 2.5426670623596808, "out_of_rail_time": 0.3267600535749173, "y_impact": -2881.711345413551, "apogee_x": 523.3087855551189, "impact_velocity": -5.076481648396569, "max_mach_number": 1.0439215834105346, "x_impact": 630.7092898564006, "out_of_rail_stability_margin": 2.611595986841253, "apogee_time": 26.92035967925358} +{"apogee": 3973.8620447387616, "frontal_surface_wind": -3.898178464469943, "apogee_y": 969.5709758373266, "lateral_surface_wind": -5.055666624184464, "t_final": 346.66173824304167, "out_of_rail_velocity": 28.77043508040725, "initial_stability_margin": 2.581404743183625, "out_of_rail_time": 0.32778231384515216, "y_impact": -2478.6308286168314, "apogee_x": 656.4387380592694, "impact_velocity": -5.197424876216387, "max_mach_number": 1.0408960951124477, "x_impact": 525.2838226262455, "out_of_rail_stability_margin": 2.6479590871120484, "apogee_time": 27.051306245931386} +{"apogee": 2733.3355689226432, "frontal_surface_wind": -3.3567696866431214, "apogee_y": 611.2617358028206, "lateral_surface_wind": -4.180518341717936, "t_final": 280.9740261931954, "out_of_rail_velocity": 23.783328535407755, "initial_stability_margin": 2.479056822395557, "out_of_rail_time": 0.38115068375692, "y_impact": -1893.3855378847995, "apogee_x": 227.00424837338818, "impact_velocity": -5.127304830718285, "max_mach_number": 0.7484626323831027, "x_impact": -193.36807509239586, "out_of_rail_stability_margin": 2.563608160252232, "apogee_time": 23.253192368514256} +{"apogee": 2154.7138533370976, "frontal_surface_wind": -3.4163730615519694, "apogee_y": 564.1016895887182, "lateral_surface_wind": -4.74102535071456, "t_final": 243.32700496945614, "out_of_rail_velocity": 21.760443760462987, "initial_stability_margin": 2.5546785875832905, "out_of_rail_time": 0.41112449420754144, "y_impact": -1128.451439653816, "apogee_x": 205.72323717181982, "impact_velocity": -5.158189768113623, "max_mach_number": 0.626576463457021, "x_impact": 45.24577905206546, "out_of_rail_stability_margin": 2.6430480773625886, "apogee_time": 21.014307652107505} +{"apogee": 3094.6886877693887, "frontal_surface_wind": -3.0751601430467863, "apogee_y": 896.7251234569044, "lateral_surface_wind": -4.267045813454278, "t_final": 301.869065695616, "out_of_rail_velocity": 25.32300007683221, "initial_stability_margin": 2.3900981583100207, "out_of_rail_time": 0.36239147917626113, "y_impact": -1441.7187363216885, "apogee_x": 655.7386401546678, "impact_velocity": -5.141225793861023, "max_mach_number": 0.8374904917809063, "x_impact": 541.409562847654, "out_of_rail_stability_margin": 2.4662877485285475, "apogee_time": 24.441530653640985} +{"apogee": 3495.021413543441, "frontal_surface_wind": -3.10592753732291, "apogee_y": 882.0723039729157, "lateral_surface_wind": -5.419436561218549, "t_final": 304.53067156286255, "out_of_rail_velocity": 26.456022159808725, "initial_stability_margin": 2.648389738023834, "out_of_rail_time": 0.34943027177572705, "y_impact": -2009.9380600058453, "apogee_x": 389.16997059150265, "impact_velocity": -5.272070505576486, "max_mach_number": 0.9026524443610076, "x_impact": 315.21098296484007, "out_of_rail_stability_margin": 2.7146784985665695, "apogee_time": 25.847661518014885} +{"apogee": 3074.4779335651006, "frontal_surface_wind": -4.393024467077156, "apogee_y": 914.0920057044569, "lateral_surface_wind": -5.151562847212306, "t_final": 284.32990880948097, "out_of_rail_velocity": 25.155318164093817, "initial_stability_margin": 2.6098559313042506, "out_of_rail_time": 0.3640768821992519, "y_impact": -1548.180765723026, "apogee_x": 446.11478991976225, "impact_velocity": -5.242390661805754, "max_mach_number": 0.8257764718757326, "x_impact": 214.3605415898124, "out_of_rail_stability_margin": 2.681807137985969, "apogee_time": 24.438789660765522} +{"apogee": 3294.3432942153395, "frontal_surface_wind": -3.1642138846267103, "apogee_y": 810.3416927678776, "lateral_surface_wind": -5.038159122588897, "t_final": 312.36217703190215, "out_of_rail_velocity": 25.80505936309025, "initial_stability_margin": 2.4800068914094195, "out_of_rail_time": 0.35734280340714486, "y_impact": -1874.4535978596978, "apogee_x": 414.2720815249571, "impact_velocity": -5.184104218067938, "max_mach_number": 0.8702927281736513, "x_impact": 279.2447186310422, "out_of_rail_stability_margin": 2.5575329073556685, "apogee_time": 25.113610127925575} +{"apogee": 3446.515911289857, "frontal_surface_wind": -3.767988938372002, "apogee_y": 777.542407443025, "lateral_surface_wind": -5.096852136472286, "t_final": 324.42908588886866, "out_of_rail_velocity": 26.462381861301154, "initial_stability_margin": 2.6239481702831315, "out_of_rail_time": 0.3495758472375969, "y_impact": -2202.348907429261, "apogee_x": 367.3784992086362, "impact_velocity": -5.0948180344201095, "max_mach_number": 0.9025534698944169, "x_impact": 90.88275672944428, "out_of_rail_stability_margin": 2.693497658724476, "apogee_time": 25.580452971667732} +{"apogee": 3734.147181142318, "frontal_surface_wind": -4.53620871982169, "apogee_y": 1187.3078421082737, "lateral_surface_wind": -5.1964030665307455, "t_final": 330.15934772464266, "out_of_rail_velocity": 27.90447108064831, "initial_stability_margin": 2.66137369013365, "out_of_rail_time": 0.3349003508213809, "y_impact": -2127.9786135394183, "apogee_x": 652.2305654009101, "impact_velocity": -5.2238023374355285, "max_mach_number": 0.9920622196703343, "x_impact": 364.3085898235332, "out_of_rail_stability_margin": 2.727485036683601, "apogee_time": 26.358155165056083} +{"apogee": 3831.2292558375816, "frontal_surface_wind": -4.163209532523157, "apogee_y": 943.3214623783674, "lateral_surface_wind": -4.639247070110235, "t_final": 357.6498110976195, "out_of_rail_velocity": 28.397282042356988, "initial_stability_margin": 2.4960073222845462, "out_of_rail_time": 0.330934212847961, "y_impact": -2610.5642954020486, "apogee_x": 539.7459952157958, "impact_velocity": -5.039588069408154, "max_mach_number": 1.0144465050556348, "x_impact": 371.1693189022848, "out_of_rail_stability_margin": 2.563497455533426, "apogee_time": 26.558803730506543} +{"apogee": 2212.6151597881767, "frontal_surface_wind": -3.979497776665914, "apogee_y": 665.8265146912603, "lateral_surface_wind": -5.477304189346046, "t_final": 247.61141085223713, "out_of_rail_velocity": 22.10965783835808, "initial_stability_margin": 2.687457307968085, "out_of_rail_time": 0.405442849385351, "y_impact": -1175.3744467566391, "apogee_x": 273.6156373974603, "impact_velocity": -5.141174945303881, "max_mach_number": 0.6456054561861525, "x_impact": -7.653695436250225, "out_of_rail_stability_margin": 2.7704570066931926, "apogee_time": 21.23356361942962} +{"apogee": 4196.004830934748, "frontal_surface_wind": -4.248685930735302, "apogee_y": 914.0127583764535, "lateral_surface_wind": -5.787085573931247, "t_final": 360.89163064474855, "out_of_rail_velocity": 29.6897405802687, "initial_stability_margin": 2.495257371640936, "out_of_rail_time": 0.3190315184022593, "y_impact": -2858.4744667769824, "apogee_x": 328.16302668664935, "impact_velocity": -5.121821434053113, "max_mach_number": 1.099351846776006, "x_impact": 503.4426317665029, "out_of_rail_stability_margin": 2.5636994287079076, "apogee_time": 27.611933271547542} +{"apogee": 3839.871056547459, "frontal_surface_wind": -4.305857938220858, "apogee_y": 950.6067686547282, "lateral_surface_wind": -5.22463885383259, "t_final": 352.5677629501762, "out_of_rail_velocity": 28.416479454860152, "initial_stability_margin": 2.3736378729544096, "out_of_rail_time": 0.33044711905922214, "y_impact": -2708.337141577087, "apogee_x": 506.8596742903591, "impact_velocity": -5.004701869365347, "max_mach_number": 1.0252802820181737, "x_impact": 348.0915562013146, "out_of_rail_stability_margin": 2.445969477146272, "apogee_time": 26.5457486242275} +{"apogee": 3600.831602872863, "frontal_surface_wind": -2.9892536817490645, "apogee_y": 945.9716746291302, "lateral_surface_wind": -5.070590500199269, "t_final": 331.91518398730074, "out_of_rail_velocity": 27.15968218051427, "initial_stability_margin": 2.477432823261019, "out_of_rail_time": 0.34265320811508826, "y_impact": -1890.2053072456886, "apogee_x": 593.9814350332412, "impact_velocity": -5.075718383908191, "max_mach_number": 0.9497395392183924, "x_impact": 616.4814521472077, "out_of_rail_stability_margin": 2.549931658372853, "apogee_time": 25.982173580517717} +{"apogee": 3608.4535517618706, "frontal_surface_wind": -3.247085548160896, "apogee_y": 993.6148011155773, "lateral_surface_wind": -5.336057903649261, "t_final": 321.9637830952574, "out_of_rail_velocity": 26.942031778460183, "initial_stability_margin": 2.640840048917396, "out_of_rail_time": 0.34448750591782407, "y_impact": -2158.470973514761, "apogee_x": 496.5070103992802, "impact_velocity": -5.218579997154987, "max_mach_number": 0.9352791720701759, "x_impact": 431.72597547631636, "out_of_rail_stability_margin": 2.708196972337256, "apogee_time": 26.14787972663668} +{"apogee": 3699.179498829001, "frontal_surface_wind": -2.994828835796924, "apogee_y": 676.906234435694, "lateral_surface_wind": -4.323805051546663, "t_final": 325.05903668140917, "out_of_rail_velocity": 27.17721904561257, "initial_stability_margin": 2.513890214542699, "out_of_rail_time": 0.34298131084691397, "y_impact": -2078.8838828081516, "apogee_x": 324.5488060387155, "impact_velocity": -5.106399683993388, "max_mach_number": 0.9512842255723164, "x_impact": 240.16335428442684, "out_of_rail_stability_margin": 2.5864810894664343, "apogee_time": 26.379193832739617} +{"apogee": 3372.703326111001, "frontal_surface_wind": -3.7212389657394835, "apogee_y": 1049.2144672952288, "lateral_surface_wind": -6.718121940554428, "t_final": 305.46498142032164, "out_of_rail_velocity": 26.399113835765277, "initial_stability_margin": 2.5155917209743994, "out_of_rail_time": 0.35031305749899605, "y_impact": -2031.267616591791, "apogee_x": 536.0396034272887, "impact_velocity": -5.19274742707198, "max_mach_number": 0.9032735488427164, "x_impact": 475.93633945474, "out_of_rail_stability_margin": 2.588456144762525, "apogee_time": 25.276409276117008} +{"apogee": 1996.5910910864711, "frontal_surface_wind": -4.215505302039444, "apogee_y": 721.9195261573232, "lateral_surface_wind": -5.939669184340507, "t_final": 236.94572564648632, "out_of_rail_velocity": 21.4142545768007, "initial_stability_margin": 2.5393158505989977, "out_of_rail_time": 0.41637390844558597, "y_impact": -1160.7813774573235, "apogee_x": 333.33372010178766, "impact_velocity": -5.208284899458889, "max_mach_number": 0.605805197465291, "x_impact": 210.37061940097385, "out_of_rail_stability_margin": 2.623666808898678, "apogee_time": 20.280493152381197} +{"apogee": 3290.172718242535, "frontal_surface_wind": -3.5353329770488546, "apogee_y": 936.3597057393529, "lateral_surface_wind": -6.910370181782125, "t_final": 297.63449573658335, "out_of_rail_velocity": 25.958929036159528, "initial_stability_margin": 2.5432853961410284, "out_of_rail_time": 0.35536623037301035, "y_impact": -2137.3288794219225, "apogee_x": 354.9942722046002, "impact_velocity": -5.210652158964284, "max_mach_number": 0.8728386266898874, "x_impact": 558.7450269569289, "out_of_rail_stability_margin": 2.614752200043072, "apogee_time": 25.09580223619011} +{"apogee": 3157.2312940893435, "frontal_surface_wind": -4.160071330874623, "apogee_y": 939.018849176115, "lateral_surface_wind": -4.842454633528848, "t_final": 295.7935864035987, "out_of_rail_velocity": 25.453459305952595, "initial_stability_margin": 2.825480269116136, "out_of_rail_time": 0.36072935644105525, "y_impact": -1638.5988955979024, "apogee_x": 549.941494761061, "impact_velocity": -5.294008355867942, "max_mach_number": 0.8416531076163297, "x_impact": 294.1364900996506, "out_of_rail_stability_margin": 2.8956885860061186, "apogee_time": 24.720456384010543} +{"apogee": 2493.9454433861424, "frontal_surface_wind": -4.240409732890779, "apogee_y": 746.1934216479096, "lateral_surface_wind": -4.711111083169344, "t_final": 260.3292570390996, "out_of_rail_velocity": 23.159704943043835, "initial_stability_margin": 2.5540253949824314, "out_of_rail_time": 0.39002200146552474, "y_impact": -1273.9911414524452, "apogee_x": 347.4088823033487, "impact_velocity": -5.21175770599466, "max_mach_number": 0.7025296599913385, "x_impact": 113.6381033024814, "out_of_rail_stability_margin": 2.631200713737236, "apogee_time": 22.373681047192225} +{"apogee": 3557.747882099693, "frontal_surface_wind": -4.623378717491691, "apogee_y": 965.262903169334, "lateral_surface_wind": -4.543683948542734, "t_final": 305.3114368363578, "out_of_rail_velocity": 26.76483739740462, "initial_stability_margin": 2.6627291588601705, "out_of_rail_time": 0.3462320179878831, "y_impact": -1881.614883628933, "apogee_x": 644.5182941711633, "impact_velocity": -5.299587220499189, "max_mach_number": 0.9251428711037164, "x_impact": 342.86376061280816, "out_of_rail_stability_margin": 2.730765898062247, "apogee_time": 26.004513267230156} +{"apogee": 3943.43528053845, "frontal_surface_wind": -3.4401784498805004, "apogee_y": 922.6435625785516, "lateral_surface_wind": -5.927056960399833, "t_final": 338.89339826231975, "out_of_rail_velocity": 28.58507664778766, "initial_stability_margin": 2.5689471432326156, "out_of_rail_time": 0.3287147486142479, "y_impact": -2711.0563850004437, "apogee_x": 437.68058381938033, "impact_velocity": -5.162181281027838, "max_mach_number": 1.0313741792407516, "x_impact": 585.8356462265267, "out_of_rail_stability_margin": 2.6363993957940877, "apogee_time": 26.967275831020494} +{"apogee": 3821.343422887789, "frontal_surface_wind": -3.093413767235326, "apogee_y": 965.3381451529741, "lateral_surface_wind": -5.0819374373234, "t_final": 324.6693523369747, "out_of_rail_velocity": 28.034675119837797, "initial_stability_margin": 2.5017804284142304, "out_of_rail_time": 0.3338369852778064, "y_impact": -2005.4232892531409, "apogee_x": 644.1199953670157, "impact_velocity": -5.211072130522262, "max_mach_number": 1.0001194701237042, "x_impact": 650.0727412309059, "out_of_rail_stability_margin": 2.570678756787538, "apogee_time": 26.63956571798566} +{"apogee": 3800.2563282190454, "frontal_surface_wind": -3.5897766426965965, "apogee_y": 913.0252185829698, "lateral_surface_wind": -5.634061051015556, "t_final": 327.97940431015735, "out_of_rail_velocity": 27.874485239441828, "initial_stability_margin": 2.489445428995911, "out_of_rail_time": 0.33534656596183354, "y_impact": -2487.4862418462326, "apogee_x": 394.54647826401816, "impact_velocity": -5.145282232800751, "max_mach_number": 0.9906807832694973, "x_impact": 532.2859666863826, "out_of_rail_stability_margin": 2.5592044304993564, "apogee_time": 26.585567151738804} +{"apogee": 3827.3766632072493, "frontal_surface_wind": -3.3213635910195753, "apogee_y": 870.0771663594517, "lateral_surface_wind": -4.808063037031196, "t_final": 338.64454382350846, "out_of_rail_velocity": 27.70777175011075, "initial_stability_margin": 2.4326044651443395, "out_of_rail_time": 0.33726945289980953, "y_impact": -2172.770177831218, "apogee_x": 494.1900412989954, "impact_velocity": -5.172525145945864, "max_mach_number": 0.9879283021822753, "x_impact": 358.79810910116066, "out_of_rail_stability_margin": 2.5061160258789243, "apogee_time": 26.74134159692111} +{"apogee": 2593.790189186025, "frontal_surface_wind": -3.343741131442183, "apogee_y": 744.5945332503826, "lateral_surface_wind": -5.795843019209302, "t_final": 265.483399793382, "out_of_rail_velocity": 23.458300227756403, "initial_stability_margin": 2.5957515254069974, "out_of_rail_time": 0.38602202076969216, "y_impact": -1470.475482518165, "apogee_x": 285.8571744000988, "impact_velocity": -5.188637434774776, "max_mach_number": 0.7240348088800113, "x_impact": 237.15278123039434, "out_of_rail_stability_margin": 2.6760114611016728, "apogee_time": 22.73937200762193} +{"apogee": 3210.27484397933, "frontal_surface_wind": -4.069916724279832, "apogee_y": 945.1246899174539, "lateral_surface_wind": -6.512799682603786, "t_final": 297.2325937657837, "out_of_rail_velocity": 25.466354244505833, "initial_stability_margin": 2.506334229800042, "out_of_rail_time": 0.3604992298911771, "y_impact": -2001.782436087753, "apogee_x": 327.68097551101613, "impact_velocity": -5.220580994885573, "max_mach_number": 0.850200521083141, "x_impact": 218.9073873806011, "out_of_rail_stability_margin": 2.583761775042269, "apogee_time": 24.901185032903207} +{"apogee": 3583.580764959765, "frontal_surface_wind": -4.2444876022185225, "apogee_y": 915.307034964373, "lateral_surface_wind": -4.329489674645672, "t_final": 309.92069961145666, "out_of_rail_velocity": 26.762207188462533, "initial_stability_margin": 2.5799423349291444, "out_of_rail_time": 0.3465913420786319, "y_impact": -1765.2073399075157, "apogee_x": 524.3171653595152, "impact_velocity": -5.25845194537824, "max_mach_number": 0.9259147341300998, "x_impact": 179.79250395126752, "out_of_rail_stability_margin": 2.6497176122710435, "apogee_time": 26.10056391600474} +{"apogee": 3345.8124779656255, "frontal_surface_wind": -4.6945885115472805, "apogee_y": 892.4253267686391, "lateral_surface_wind": -4.470070838012333, "t_final": 322.8485776373996, "out_of_rail_velocity": 26.271760315344608, "initial_stability_margin": 2.5290580955817465, "out_of_rail_time": 0.3520365183109293, "y_impact": -2175.1082012663487, "apogee_x": 561.7024311427972, "impact_velocity": -5.065719217167408, "max_mach_number": 0.8945851855121686, "x_impact": 168.79355127333753, "out_of_rail_stability_margin": 2.6028367340909067, "apogee_time": 25.19997305299555} +{"apogee": 3805.9364957671173, "frontal_surface_wind": -4.269493265509526, "apogee_y": 1023.2144838475733, "lateral_surface_wind": -5.806288183606378, "t_final": 330.8906636380743, "out_of_rail_velocity": 27.964275852805418, "initial_stability_margin": 2.630100065529309, "out_of_rail_time": 0.3346852452781659, "y_impact": -2357.788114751217, "apogee_x": 467.3439871737618, "impact_velocity": -5.211917181838343, "max_mach_number": 0.9888989491113712, "x_impact": 499.7012691696042, "out_of_rail_stability_margin": 2.6941926758095676, "apogee_time": 26.63410443796493} +{"apogee": 3556.4996446554, "frontal_surface_wind": -3.7687804898163426, "apogee_y": 1016.511674284893, "lateral_surface_wind": -6.143113936343518, "t_final": 322.98777593410654, "out_of_rail_velocity": 26.97227838896609, "initial_stability_margin": 2.370115878813151, "out_of_rail_time": 0.34419742456827207, "y_impact": -2167.67362426374, "apogee_x": 581.6189563024298, "impact_velocity": -5.1253218792467345, "max_mach_number": 0.9429265721062239, "x_impact": 611.5596995158832, "out_of_rail_stability_margin": 2.445436879200688, "apogee_time": 25.827190558051953} +{"apogee": 3409.7052847965238, "frontal_surface_wind": -3.0129465150622754, "apogee_y": 837.0610287535023, "lateral_surface_wind": -4.434725429153459, "t_final": 322.500392284277, "out_of_rail_velocity": 26.315442329021504, "initial_stability_margin": 2.55979495225858, "out_of_rail_time": 0.3507165790831769, "y_impact": -2356.0730798747386, "apogee_x": 546.6951264021687, "impact_velocity": -5.1500746382995075, "max_mach_number": 0.89653332095408, "x_impact": 193.67709727246333, "out_of_rail_stability_margin": 2.629551066910328, "apogee_time": 25.491472138108733} +{"apogee": 4006.3693308079146, "frontal_surface_wind": -3.312547556767319, "apogee_y": 933.1173830105945, "lateral_surface_wind": -4.941894933762254, "t_final": 353.5670376022463, "out_of_rail_velocity": 28.700606187750708, "initial_stability_margin": 2.5001261695325248, "out_of_rail_time": 0.32760129265720017, "y_impact": -2495.951057327003, "apogee_x": 537.6308654668574, "impact_velocity": -5.22328305667093, "max_mach_number": 1.0386767507553567, "x_impact": 557.0567493023455, "out_of_rail_stability_margin": 2.567721063228973, "apogee_time": 27.196007423021438} +{"apogee": 1908.736736747123, "frontal_surface_wind": -4.545286619686612, "apogee_y": 648.041264372225, "lateral_surface_wind": -4.747954606803458, "t_final": 233.20444443661853, "out_of_rail_velocity": 21.069122874093505, "initial_stability_margin": 2.5322544867984673, "out_of_rail_time": 0.4221769465494857, "y_impact": -1252.2645037766845, "apogee_x": 309.26364651232774, "impact_velocity": -5.048403777083266, "max_mach_number": 0.5888588004289596, "x_impact": 120.75652587040271, "out_of_rail_stability_margin": 2.6212938260090497, "apogee_time": 19.837904560950438} +{"apogee": 2816.24958934864, "frontal_surface_wind": -4.599244712497397, "apogee_y": 916.2692833283882, "lateral_surface_wind": -4.568111498657266, "t_final": 278.278618609887, "out_of_rail_velocity": 24.41563466189233, "initial_stability_margin": 2.5081578541534486, "out_of_rail_time": 0.37343054388673136, "y_impact": -1447.4669917487938, "apogee_x": 648.7729999242334, "impact_velocity": -5.213080340907972, "max_mach_number": 0.7834804674380761, "x_impact": 260.5052643284308, "out_of_rail_stability_margin": 2.584780677625157, "apogee_time": 23.498051343406708} +{"apogee": 3242.308094307731, "frontal_surface_wind": -2.982815016786125, "apogee_y": 863.3914358354883, "lateral_surface_wind": -5.074380767167222, "t_final": 302.29514909868965, "out_of_rail_velocity": 25.663946255498, "initial_stability_margin": 2.5672534951318813, "out_of_rail_time": 0.3596342294935801, "y_impact": -1519.0548562419845, "apogee_x": 482.30783068580786, "impact_velocity": -5.208875195729816, "max_mach_number": 0.8543562094844714, "x_impact": 445.93029305079, "out_of_rail_stability_margin": 2.640961271331624, "apogee_time": 25.021010311952452} +{"apogee": 4529.021812840644, "frontal_surface_wind": -4.256196224614887, "apogee_y": 1236.4314798378741, "lateral_surface_wind": -5.910579385178822, "t_final": 355.9646293836877, "out_of_rail_velocity": 31.070222039907623, "initial_stability_margin": 2.666848923411547, "out_of_rail_time": 0.3080662634932985, "y_impact": -2573.9967500584225, "apogee_x": 787.1842475847562, "impact_velocity": -5.3563838058921815, "max_mach_number": 1.18389127014406, "x_impact": 866.5744313224682, "out_of_rail_stability_margin": 2.7277785809964286, "apogee_time": 28.535454890170307} +{"apogee": 3773.150567392644, "frontal_surface_wind": -4.443077102463483, "apogee_y": 955.3878061988434, "lateral_surface_wind": -5.771414110293211, "t_final": 336.68452438138434, "out_of_rail_velocity": 27.543489201429487, "initial_stability_margin": 2.680687214325261, "out_of_rail_time": 0.33825271304236876, "y_impact": -2470.578911331097, "apogee_x": 374.60359027975676, "impact_velocity": -5.248797925480753, "max_mach_number": 0.9723884661568505, "x_impact": 286.3982441102645, "out_of_rail_stability_margin": 2.749149495312333, "apogee_time": 26.60539482165162} +{"apogee": 3618.5706604048005, "frontal_surface_wind": -3.403237631128055, "apogee_y": 820.966875607905, "lateral_surface_wind": -4.750463124569014, "t_final": 326.4453795276764, "out_of_rail_velocity": 26.960221130785975, "initial_stability_margin": 2.6757165400182563, "out_of_rail_time": 0.3443601864314907, "y_impact": -2023.748086853269, "apogee_x": 405.67120832510705, "impact_velocity": -5.137208275080617, "max_mach_number": 0.9364576036351423, "x_impact": 244.10187008708647, "out_of_rail_stability_margin": 2.7464749041780943, "apogee_time": 26.137489348201218} +{"apogee": 3745.260748346642, "frontal_surface_wind": -3.6127280751665003, "apogee_y": 1013.8329895293804, "lateral_surface_wind": -5.39884876719979, "t_final": 325.209557149793, "out_of_rail_velocity": 27.653306626993537, "initial_stability_margin": 2.574773987345006, "out_of_rail_time": 0.33786722247842566, "y_impact": -2253.9683249187588, "apogee_x": 550.4025849163155, "impact_velocity": -5.171734372979518, "max_mach_number": 0.9820830297324608, "x_impact": 416.14975914680235, "out_of_rail_stability_margin": 2.645016155328838, "apogee_time": 26.44115284909391} +{"apogee": 2849.5515702274315, "frontal_surface_wind": -3.481461094626852, "apogee_y": 783.6655441264116, "lateral_surface_wind": -4.693437430968447, "t_final": 273.35612920471476, "out_of_rail_velocity": 24.36833923457661, "initial_stability_margin": 2.537844166430635, "out_of_rail_time": 0.3745168355544106, "y_impact": -1306.5434142525917, "apogee_x": 412.6320657334109, "impact_velocity": -5.205709999609996, "max_mach_number": 0.7761287203559591, "x_impact": 254.65248378462616, "out_of_rail_stability_margin": 2.613852596861419, "apogee_time": 23.66431804732875} +{"apogee": 4244.90007629161, "frontal_surface_wind": -3.382561704671427, "apogee_y": 916.5593277937767, "lateral_surface_wind": -4.894238772912546, "t_final": 363.5868360091188, "out_of_rail_velocity": 30.279273648253533, "initial_stability_margin": 2.5189426447235714, "out_of_rail_time": 0.3144256370141395, "y_impact": -2682.3329904769994, "apogee_x": 524.9600556749829, "impact_velocity": -5.066338880123744, "max_mach_number": 1.1268900672122508, "x_impact": 616.4444503905102, "out_of_rail_stability_margin": 2.5836819598716136, "apogee_time": 27.633077704250987} +{"apogee": 4054.899573045121, "frontal_surface_wind": -4.205528007722659, "apogee_y": 934.7471575139593, "lateral_surface_wind": -4.367343589015011, "t_final": 345.7786741473781, "out_of_rail_velocity": 28.8913805961019, "initial_stability_margin": 2.6686154640261965, "out_of_rail_time": 0.3261227536185324, "y_impact": -2331.329030811318, "apogee_x": 558.0860040316805, "impact_velocity": -5.315839849605289, "max_mach_number": 1.043680082095999, "x_impact": 275.8821902721137, "out_of_rail_stability_margin": 2.730004828523415, "apogee_time": 27.391547966828874} +{"apogee": 3545.488860003587, "frontal_surface_wind": -3.2152425394191293, "apogee_y": 1013.0184784048213, "lateral_surface_wind": -4.1625118969452615, "t_final": 327.68240877321387, "out_of_rail_velocity": 26.789824967974152, "initial_stability_margin": 2.6109320827169396, "out_of_rail_time": 0.34612464101828755, "y_impact": -1752.450941248235, "apogee_x": 718.2690639132277, "impact_velocity": -5.221166581805151, "max_mach_number": 0.9283507156326842, "x_impact": 646.8378274960803, "out_of_rail_stability_margin": 2.6817331421483437, "apogee_time": 25.922788778470355} +{"apogee": 3328.3997192658558, "frontal_surface_wind": -3.7071402519060186, "apogee_y": 935.7211350563983, "lateral_surface_wind": -5.763847944866734, "t_final": 305.3000842632325, "out_of_rail_velocity": 26.10333910853045, "initial_stability_margin": 2.565870156019963, "out_of_rail_time": 0.3533745766393044, "y_impact": -2065.9623287516174, "apogee_x": 430.28615710659244, "impact_velocity": -5.1704474855654965, "max_mach_number": 0.8841759138373222, "x_impact": 478.93253049872214, "out_of_rail_stability_margin": 2.6371337187400257, "apogee_time": 25.207964878918958} +{"apogee": 2338.886616953487, "frontal_surface_wind": -4.376372858015383, "apogee_y": 830.8540796300078, "lateral_surface_wind": -5.82215729593019, "t_final": 256.9173087650527, "out_of_rail_velocity": 22.73809499249894, "initial_stability_margin": 2.473186197913793, "out_of_rail_time": 0.396792128340614, "y_impact": -1303.8614482395055, "apogee_x": 401.2549084152766, "impact_velocity": -5.116007601776199, "max_mach_number": 0.6851706855274269, "x_impact": 266.450538480061, "out_of_rail_stability_margin": 2.5613958814410887, "apogee_time": 21.660664394513397} +{"apogee": 2738.311059087404, "frontal_surface_wind": -3.3319200254523706, "apogee_y": 731.1515082219289, "lateral_surface_wind": -4.800753609154044, "t_final": 267.0155122346244, "out_of_rail_velocity": 23.84740598226049, "initial_stability_margin": 2.7367606706850522, "out_of_rail_time": 0.38102566934748006, "y_impact": -1300.769537696206, "apogee_x": 358.69127693554213, "impact_velocity": -5.361203759685262, "max_mach_number": 0.7440265428791331, "x_impact": 187.07285702648986, "out_of_rail_stability_margin": 2.8129295734526423, "apogee_time": 23.356089394780767} +{"apogee": 2983.3033214669804, "frontal_surface_wind": -3.926988148972946, "apogee_y": 755.5559779225467, "lateral_surface_wind": -5.105233730777631, "t_final": 280.10869730499365, "out_of_rail_velocity": 24.76407024167618, "initial_stability_margin": 2.5338596410495233, "out_of_rail_time": 0.36868125611797464, "y_impact": -1511.1170399930472, "apogee_x": 340.1913839136258, "impact_velocity": -5.231987052944898, "max_mach_number": 0.7993570817929538, "x_impact": 175.536690674999, "out_of_rail_stability_margin": 2.6067764105884934, "apogee_time": 24.1523024031831} +{"apogee": 3260.780127526729, "frontal_surface_wind": -4.2630035853139345, "apogee_y": 886.6311569304927, "lateral_surface_wind": -4.31125924526127, "t_final": 307.80439310193793, "out_of_rail_velocity": 25.852734697985106, "initial_stability_margin": 2.537416370203071, "out_of_rail_time": 0.35689437330241547, "y_impact": -1703.6118529878502, "apogee_x": 514.6753600226418, "impact_velocity": -5.175914597788924, "max_mach_number": 0.8680333376943979, "x_impact": 103.10302250261267, "out_of_rail_stability_margin": 2.609585679317097, "apogee_time": 25.00403093742554} +{"apogee": 2790.1934063490803, "frontal_surface_wind": -4.159862093748521, "apogee_y": 795.2914273728711, "lateral_surface_wind": -4.642248846217989, "t_final": 276.27210697392076, "out_of_rail_velocity": 24.029604637736274, "initial_stability_margin": 2.5212384829272376, "out_of_rail_time": 0.3786991777261954, "y_impact": -1498.9931784508321, "apogee_x": 387.2343770129541, "impact_velocity": -5.292900750090433, "max_mach_number": 0.7582048750946261, "x_impact": 114.55272861376322, "out_of_rail_stability_margin": 2.599137339170764, "apogee_time": 23.5184849805029} +{"apogee": 3885.592796414068, "frontal_surface_wind": -3.845001652770424, "apogee_y": 939.2832017868111, "lateral_surface_wind": -5.095951483570734, "t_final": 340.0112574786761, "out_of_rail_velocity": 28.14388784661246, "initial_stability_margin": 2.606327437224062, "out_of_rail_time": 0.332753098798267, "y_impact": -2302.648270657349, "apogee_x": 523.7956119484688, "impact_velocity": -5.221534646578817, "max_mach_number": 1.0052439721609034, "x_impact": 441.2699022399714, "out_of_rail_stability_margin": 2.672958551793843, "apogee_time": 26.88999928008215} +{"apogee": 3564.4563492383436, "frontal_surface_wind": -4.608201031876451, "apogee_y": 882.333426326476, "lateral_surface_wind": -4.55907642394957, "t_final": 319.13522219234375, "out_of_rail_velocity": 26.800944604337037, "initial_stability_margin": 2.530396066518384, "out_of_rail_time": 0.3459423347194663, "y_impact": -2178.022977282653, "apogee_x": 552.4549306108088, "impact_velocity": -5.2213280583500215, "max_mach_number": 0.9259688291193067, "x_impact": 217.42824095327947, "out_of_rail_stability_margin": 2.598818935515359, "apogee_time": 26.000702523260614} +{"apogee": 3651.907452355504, "frontal_surface_wind": -3.9333760409866176, "apogee_y": 825.5161669089649, "lateral_surface_wind": -4.8356467932853135, "t_final": 331.41982941219925, "out_of_rail_velocity": 27.073411408637302, "initial_stability_margin": 2.5233441449145144, "out_of_rail_time": 0.34324101610210905, "y_impact": -2333.1995162239323, "apogee_x": 409.36768189900846, "impact_velocity": -5.136155959174707, "max_mach_number": 0.9452208351126825, "x_impact": 216.47618860118308, "out_of_rail_stability_margin": 2.59573151009158, "apogee_time": 26.22172725117455} +{"apogee": 2249.1540235541006, "frontal_surface_wind": -2.9136950906011925, "apogee_y": 699.7716240226395, "lateral_surface_wind": -5.014898321560432, "t_final": 238.28498825340301, "out_of_rail_velocity": 22.28439099039905, "initial_stability_margin": 2.527813521310565, "out_of_rail_time": 0.40284589638826984, "y_impact": -822.4378059975744, "apogee_x": 388.02812201459426, "impact_velocity": -5.329323315219495, "max_mach_number": 0.6501037701009532, "x_impact": 328.21150966566074, "out_of_rail_stability_margin": 2.605714540032568, "apogee_time": 21.4131636137213} +{"apogee": 3874.494312527984, "frontal_surface_wind": -3.7875263209969856, "apogee_y": 983.2045382650492, "lateral_surface_wind": -4.950714226954847, "t_final": 343.51295818392396, "out_of_rail_velocity": 28.3682826061037, "initial_stability_margin": 2.5217592728536595, "out_of_rail_time": 0.3311000223996021, "y_impact": -2397.8618211293274, "apogee_x": 672.4998370752937, "impact_velocity": -5.185911028390577, "max_mach_number": 1.0156905074876306, "x_impact": 540.9545644537977, "out_of_rail_stability_margin": 2.5885529479851566, "apogee_time": 26.774895572955007} +{"apogee": 3449.8346567498425, "frontal_surface_wind": -3.185000897858484, "apogee_y": 768.9851534382531, "lateral_surface_wind": -4.312818755204869, "t_final": 306.5025672415605, "out_of_rail_velocity": 26.348099248173902, "initial_stability_margin": 2.4800468023736766, "out_of_rail_time": 0.3507803011063992, "y_impact": -2157.969479083126, "apogee_x": 414.3514399195889, "impact_velocity": -5.153043230767745, "max_mach_number": 0.8994012607697047, "x_impact": 100.5590495784027, "out_of_rail_stability_margin": 2.5516705606978234, "apogee_time": 25.64186822404151} +{"apogee": 3722.6351942298065, "frontal_surface_wind": -4.092948617010215, "apogee_y": 956.8106206470087, "lateral_surface_wind": -5.0049407159077335, "t_final": 325.6275187914103, "out_of_rail_velocity": 27.28145454123011, "initial_stability_margin": 2.542817456027403, "out_of_rail_time": 0.3409615873441347, "y_impact": -2307.3013342258832, "apogee_x": 537.9814397215778, "impact_velocity": -5.287084158486216, "max_mach_number": 0.9584898196749102, "x_impact": 266.00931567919895, "out_of_rail_stability_margin": 2.612371179032066, "apogee_time": 26.502991578273285} +{"apogee": 2277.8279251643685, "frontal_surface_wind": -3.7408031391008585, "apogee_y": 715.6511412077654, "lateral_surface_wind": -5.172924811671557, "t_final": 244.40275679292427, "out_of_rail_velocity": 22.313624411226854, "initial_stability_margin": 2.497313848975666, "out_of_rail_time": 0.40250665233846283, "y_impact": -1056.5558631456481, "apogee_x": 375.4045200929709, "impact_velocity": -5.309452079953268, "max_mach_number": 0.6572080734601271, "x_impact": 218.0805008347787, "out_of_rail_stability_margin": 2.5799948802508896, "apogee_time": 21.546609308507914} +{"apogee": 3600.0404447472083, "frontal_surface_wind": -4.157342377172009, "apogee_y": 904.1350081985215, "lateral_surface_wind": -4.951582000755581, "t_final": 323.45445748891524, "out_of_rail_velocity": 27.155582787310998, "initial_stability_margin": 2.46772737893552, "out_of_rail_time": 0.3428818366320518, "y_impact": -2254.04041056412, "apogee_x": 486.3724403284261, "impact_velocity": -5.05848825119632, "max_mach_number": 0.9479950961959466, "x_impact": 202.68881016533894, "out_of_rail_stability_margin": 2.5378433027900544, "apogee_time": 25.9809185823884} +{"apogee": 2672.2906159276477, "frontal_surface_wind": -3.186868623037853, "apogee_y": 733.5752883808632, "lateral_surface_wind": -5.023859595140672, "t_final": 273.36404117590416, "out_of_rail_velocity": 23.734232106655067, "initial_stability_margin": 2.4856054039259776, "out_of_rail_time": 0.38191685632737377, "y_impact": -1291.7145656203038, "apogee_x": 368.52270000641425, "impact_velocity": -5.206871844444488, "max_mach_number": 0.739023849160982, "x_impact": 198.63258330716704, "out_of_rail_stability_margin": 2.5642766100710603, "apogee_time": 23.02446097855121} +{"apogee": 4156.82953637903, "frontal_surface_wind": -4.460919868958712, "apogee_y": 895.7224109985343, "lateral_surface_wind": -5.301214101231658, "t_final": 344.781461420436, "out_of_rail_velocity": 29.820918850726752, "initial_stability_margin": 2.5687047947566612, "out_of_rail_time": 0.31783117138513334, "y_impact": -2596.734104346081, "apogee_x": 415.9606714808651, "impact_velocity": -5.118254799315706, "max_mach_number": 1.0961997111425543, "x_impact": 174.22409328456098, "out_of_rail_stability_margin": 2.6301192403558096, "apogee_time": 27.47284202463955} +{"apogee": 4319.35127470076, "frontal_surface_wind": -3.5646724453286067, "apogee_y": 1015.2416620470644, "lateral_surface_wind": -6.895281405815689, "t_final": 374.5769417088964, "out_of_rail_velocity": 30.97651613622723, "initial_stability_margin": 2.4986531067664646, "out_of_rail_time": 0.3087971816006266, "y_impact": -3475.373873639539, "apogee_x": 491.4073472558672, "impact_velocity": -5.066705020034197, "max_mach_number": 1.1662806722540133, "x_impact": 934.2288734296422, "out_of_rail_stability_margin": 2.561112229671911, "apogee_time": 27.70788875440057} +{"apogee": 3117.5202897745644, "frontal_surface_wind": -3.642444100445455, "apogee_y": 850.8700900521549, "lateral_surface_wind": -4.70402995603985, "t_final": 302.9742978864276, "out_of_rail_velocity": 25.357281302372975, "initial_stability_margin": 2.629012571162269, "out_of_rail_time": 0.3616875084002643, "y_impact": -1668.876468541172, "apogee_x": 391.71923703465757, "impact_velocity": -5.165393736379995, "max_mach_number": 0.8350626164065601, "x_impact": 230.63939548324268, "out_of_rail_stability_margin": 2.7008942162765184, "apogee_time": 24.52718977463929} +{"apogee": 2818.1427077940757, "frontal_surface_wind": -3.368689069470279, "apogee_y": 752.4144938905489, "lateral_surface_wind": -5.768975145054103, "t_final": 284.1108641657371, "out_of_rail_velocity": 24.32497667223676, "initial_stability_margin": 2.456180748088198, "out_of_rail_time": 0.3753106482745215, "y_impact": -1821.2060762132107, "apogee_x": 291.2408747970848, "impact_velocity": -5.110671266116348, "max_mach_number": 0.7724979499238693, "x_impact": 290.4231962419677, "out_of_rail_stability_margin": 2.5332731556494004, "apogee_time": 23.50275594544416} +{"apogee": 1251.9907669359416, "frontal_surface_wind": -4.136541817657884, "apogee_y": 445.30655137353284, "lateral_surface_wind": -4.9369696331668145, "t_final": 185.89763302821504, "out_of_rail_velocity": 18.101006099009016, "initial_stability_margin": 2.570978761450612, "out_of_rail_time": 0.48182103114886543, "y_impact": -658.5022895881125, "apogee_x": 174.8691837621877, "impact_velocity": -5.244817210161781, "max_mach_number": 0.4348781221904444, "x_impact": 115.38819962268032, "out_of_rail_stability_margin": 2.6717947244161797, "apogee_time": 16.476260903585775} +{"apogee": 2453.1236796243907, "frontal_surface_wind": -3.9833558520503556, "apogee_y": 844.5044984072373, "lateral_surface_wind": -5.972819077618828, "t_final": 266.616208062199, "out_of_rail_velocity": 23.11538671075964, "initial_stability_margin": 2.5826089431113775, "out_of_rail_time": 0.39062441190212455, "y_impact": -1354.240803306685, "apogee_x": 393.51252516685867, "impact_velocity": -5.1732369894814845, "max_mach_number": 0.7054011366720542, "x_impact": 339.37420824742424, "out_of_rail_stability_margin": 2.665668651729761, "apogee_time": 22.13894593435902} +{"apogee": 3465.113615276112, "frontal_surface_wind": -4.520891519754162, "apogee_y": 999.4998254525327, "lateral_surface_wind": -4.645668354092326, "t_final": 316.0842321891448, "out_of_rail_velocity": 26.92477168201846, "initial_stability_margin": 2.425641848905976, "out_of_rail_time": 0.34467337441054396, "y_impact": -1946.2742393169792, "apogee_x": 762.5291454788326, "impact_velocity": -5.044902598976564, "max_mach_number": 0.9353244847987882, "x_impact": 438.67924863082635, "out_of_rail_stability_margin": 2.4973753591124246, "apogee_time": 25.489056730493267} +{"apogee": 3418.3852785278145, "frontal_surface_wind": -3.0633314364292485, "apogee_y": 869.7285048852802, "lateral_surface_wind": -4.924918757417978, "t_final": 311.79498773410995, "out_of_rail_velocity": 26.236231529616024, "initial_stability_margin": 2.622958870587312, "out_of_rail_time": 0.3515489136017078, "y_impact": -1672.8917649311632, "apogee_x": 454.6727847292232, "impact_velocity": -5.153121429095131, "max_mach_number": 0.89294456072223, "x_impact": 373.8573526946888, "out_of_rail_stability_margin": 2.695032630464474, "apogee_time": 25.536466047246876} +{"apogee": 3546.798523821776, "frontal_surface_wind": -3.734993548942408, "apogee_y": 794.3262604328846, "lateral_surface_wind": -5.177121055381325, "t_final": 337.89571965442036, "out_of_rail_velocity": 26.807002480610297, "initial_stability_margin": 2.5001502239916493, "out_of_rail_time": 0.34582202020705954, "y_impact": -2342.140152942799, "apogee_x": 359.4710988903438, "impact_velocity": -5.010813810830097, "max_mach_number": 0.9318367189268297, "x_impact": 187.7517997751707, "out_of_rail_stability_margin": 2.575590478258739, "apogee_time": 25.82481815262343} +{"apogee": 3693.7242784195087, "frontal_surface_wind": -4.083630988422871, "apogee_y": 888.1815980445824, "lateral_surface_wind": -5.121050064747783, "t_final": 337.2585290941917, "out_of_rail_velocity": 27.318267186543146, "initial_stability_margin": 2.469962842560619, "out_of_rail_time": 0.34105547544286274, "y_impact": -2022.9018326535802, "apogee_x": 462.16760728392904, "impact_velocity": -5.1602477165949745, "max_mach_number": 0.9587759774374282, "x_impact": -96.26878015478988, "out_of_rail_stability_margin": 2.5417551354416537, "apogee_time": 26.331254236265718} +{"apogee": 3938.3204336927083, "frontal_surface_wind": -4.250317291002822, "apogee_y": 997.4164230311022, "lateral_surface_wind": -4.323766734463443, "t_final": 350.03209091046006, "out_of_rail_velocity": 29.063746545851043, "initial_stability_margin": 2.454826702411364, "out_of_rail_time": 0.32447840548776186, "y_impact": -2262.362311186252, "apogee_x": 660.6496877451102, "impact_velocity": -5.0724533397626095, "max_mach_number": 1.054868509606987, "x_impact": 351.76354036385544, "out_of_rail_stability_margin": 2.5212239962607037, "apogee_time": 26.805109145984556} +{"apogee": 2966.668633108827, "frontal_surface_wind": -4.354315277044086, "apogee_y": 901.5963711358562, "lateral_surface_wind": -5.708032064217207, "t_final": 284.54264224209714, "out_of_rail_velocity": 24.81664542701976, "initial_stability_margin": 2.592188437801929, "out_of_rail_time": 0.3687282800981479, "y_impact": -1588.4333942328888, "apogee_x": 349.3357736486525, "impact_velocity": -5.226161437329518, "max_mach_number": 0.8020761061599956, "x_impact": 322.13188909434473, "out_of_rail_stability_margin": 2.665322282188238, "apogee_time": 24.070130901088387} +{"apogee": 3678.001390735641, "frontal_surface_wind": -3.9657341861737563, "apogee_y": 939.3189017413574, "lateral_surface_wind": -5.1063306116867935, "t_final": 326.85130211032316, "out_of_rail_velocity": 27.35565186604991, "initial_stability_margin": 2.778371415161271, "out_of_rail_time": 0.34017274856429824, "y_impact": -2306.7654211188396, "apogee_x": 538.15504028874, "impact_velocity": -5.205042094074384, "max_mach_number": 0.958934481251867, "x_impact": 262.95768838126793, "out_of_rail_stability_margin": 2.8455046554739853, "apogee_time": 26.276917356755554} +{"apogee": 4018.1104631574044, "frontal_surface_wind": -4.199162787984338, "apogee_y": 966.7046245180038, "lateral_surface_wind": -5.9512340611787815, "t_final": 341.0165109239083, "out_of_rail_velocity": 28.905420627687977, "initial_stability_margin": 2.6345583679889932, "out_of_rail_time": 0.32560744161389577, "y_impact": -2564.8304804112827, "apogee_x": 441.1334996211137, "impact_velocity": -5.196688697238588, "max_mach_number": 1.051404787744187, "x_impact": 396.49610288233254, "out_of_rail_stability_margin": 2.7029024070124295, "apogee_time": 27.160349819281755} +{"apogee": 3253.261887487919, "frontal_surface_wind": -3.7888932716434236, "apogee_y": 917.2720769776556, "lateral_surface_wind": -5.710439541308664, "t_final": 314.3732410402694, "out_of_rail_velocity": 25.888137609326044, "initial_stability_margin": 2.543539816900533, "out_of_rail_time": 0.3563582964140308, "y_impact": -2219.5493908070202, "apogee_x": 402.2140381913957, "impact_velocity": -5.084582917969193, "max_mach_number": 0.8730150477790338, "x_impact": 426.0553233367289, "out_of_rail_stability_margin": 2.61765466012798, "apogee_time": 24.921763828866855} +{"apogee": 2038.232822006892, "frontal_surface_wind": -3.518942208238076, "apogee_y": 653.4773956688691, "lateral_surface_wind": -4.7184289047989205, "t_final": 234.04198139432364, "out_of_rail_velocity": 21.395978653746337, "initial_stability_margin": 2.5974872559023465, "out_of_rail_time": 0.4170688672216163, "y_impact": -792.1437009940422, "apogee_x": 256.48475189800723, "impact_velocity": -5.272409630249596, "max_mach_number": 0.6053200795814591, "x_impact": 145.7504936268748, "out_of_rail_stability_margin": 2.6834534434988973, "apogee_time": 20.53036215576582} +{"apogee": 2004.1759361243974, "frontal_surface_wind": -4.598614889643675, "apogee_y": 766.4146526122627, "lateral_surface_wind": -5.648264872301437, "t_final": 228.10673553621373, "out_of_rail_velocity": 21.420056310920607, "initial_stability_margin": 2.6750748079769506, "out_of_rail_time": 0.4164701298009173, "y_impact": -979.5513569742493, "apogee_x": 327.51192584228306, "impact_velocity": -5.269417346199548, "max_mach_number": 0.6084108521236261, "x_impact": 229.9281584756828, "out_of_rail_stability_margin": 2.761931425056001, "apogee_time": 20.324653422718992} +{"apogee": 2986.7143578265077, "frontal_surface_wind": -3.8623541989498578, "apogee_y": 714.5165001187027, "lateral_surface_wind": -5.082812142364545, "t_final": 290.0132182906828, "out_of_rail_velocity": 24.747527166310228, "initial_stability_margin": 2.5683261868585516, "out_of_rail_time": 0.3691044052253446, "y_impact": -1708.0792258414483, "apogee_x": 268.6673432795286, "impact_velocity": -5.129642037255641, "max_mach_number": 0.7999094808186158, "x_impact": 69.22777174581883, "out_of_rail_stability_margin": 2.643846215880008, "apogee_time": 24.15198991375388} +{"apogee": 2937.3249550929563, "frontal_surface_wind": -4.275748574242886, "apogee_y": 803.3298894722698, "lateral_surface_wind": -4.992061451267228, "t_final": 300.46724144983125, "out_of_rail_velocity": 24.815877905768566, "initial_stability_margin": 2.5791803970041554, "out_of_rail_time": 0.36821693347761986, "y_impact": -2170.858784517776, "apogee_x": 429.7589058546031, "impact_velocity": -5.024386919930757, "max_mach_number": 0.8063328653054785, "x_impact": 322.9612393860442, "out_of_rail_stability_margin": 2.6571786342719514, "apogee_time": 23.859062802041187} +{"apogee": 3996.9115249905276, "frontal_surface_wind": -3.7835828616212375, "apogee_y": 959.0151271232098, "lateral_surface_wind": -5.280518240233337, "t_final": 360.8638859636712, "out_of_rail_velocity": 29.023995426731023, "initial_stability_margin": 2.515485647984805, "out_of_rail_time": 0.3251211809426393, "y_impact": -2896.402672802543, "apogee_x": 467.9078637886909, "impact_velocity": -5.082453302124562, "max_mach_number": 1.0533945930329471, "x_impact": 316.90324183202944, "out_of_rail_stability_margin": 2.581325284010274, "apogee_time": 27.06275768916107} +{"apogee": 3264.8564967002135, "frontal_surface_wind": -3.8810778817659237, "apogee_y": 965.4159411991188, "lateral_surface_wind": -6.72227861543539, "t_final": 307.0030451743203, "out_of_rail_velocity": 25.99596396029284, "initial_stability_margin": 2.6679205317439965, "out_of_rail_time": 0.35489892728200173, "y_impact": -2233.5224936504483, "apogee_x": 342.6420557007235, "impact_velocity": -5.0536322930466415, "max_mach_number": 0.8776095475993376, "x_impact": 543.254833778517, "out_of_rail_stability_margin": 2.7420404711926567, "apogee_time": 24.927219754664154} +{"apogee": 3797.5685972755605, "frontal_surface_wind": -4.271281822636469, "apogee_y": 847.03730135533, "lateral_surface_wind": -4.995883805192391, "t_final": 332.6286050088647, "out_of_rail_velocity": 27.89720179659139, "initial_stability_margin": 2.510851371297206, "out_of_rail_time": 0.33523312132374716, "y_impact": -2655.046217522149, "apogee_x": 446.4895818474621, "impact_velocity": -5.043918650427335, "max_mach_number": 0.9951307131929221, "x_impact": 503.23943346387705, "out_of_rail_stability_margin": 2.583526365506102, "apogee_time": 26.54502604807747} +{"apogee": 3931.8125014034595, "frontal_surface_wind": -4.338701763270172, "apogee_y": 995.9132686955533, "lateral_surface_wind": -5.401698254601444, "t_final": 342.1561385206134, "out_of_rail_velocity": 29.035956116422845, "initial_stability_margin": 2.4389750050322876, "out_of_rail_time": 0.32484117963911396, "y_impact": -2406.75427808376, "apogee_x": 575.337097612752, "impact_velocity": -4.987091825094103, "max_mach_number": 1.0612884839917596, "x_impact": 311.2096058484707, "out_of_rail_stability_margin": 2.51075512259, "apogee_time": 26.748632732169362} +{"apogee": 3775.519117764259, "frontal_surface_wind": -4.2673310011136385, "apogee_y": 1012.1630087253565, "lateral_surface_wind": -4.686739641551506, "t_final": 329.76719462826645, "out_of_rail_velocity": 27.813068853184667, "initial_stability_margin": 2.6358526092723222, "out_of_rail_time": 0.3367177328106602, "y_impact": -2076.0543308050433, "apogee_x": 562.7430471902774, "impact_velocity": -5.1926133757981106, "max_mach_number": 0.984126098366045, "x_impact": 357.85582522464983, "out_of_rail_stability_margin": 2.701924050490265, "apogee_time": 26.554336876622784} +{"apogee": 3680.2721850439743, "frontal_surface_wind": -3.677153100121104, "apogee_y": 880.8014996972406, "lateral_surface_wind": -5.355176676306832, "t_final": 327.6849456765257, "out_of_rail_velocity": 27.310385026108975, "initial_stability_margin": 2.6119715923106637, "out_of_rail_time": 0.34100761441326133, "y_impact": -2450.0143097047876, "apogee_x": 365.0274800258772, "impact_velocity": -5.204034122601761, "max_mach_number": 0.9585733084753566, "x_impact": 185.89141022126375, "out_of_rail_stability_margin": 2.68215369298615, "apogee_time": 26.275019429687855} +{"apogee": 3431.650190011215, "frontal_surface_wind": -4.396499582018061, "apogee_y": 956.7441573583344, "lateral_surface_wind": -4.270194469349204, "t_final": 307.2456083272591, "out_of_rail_velocity": 26.318793569073883, "initial_stability_margin": 2.510923089103543, "out_of_rail_time": 0.35106022759252603, "y_impact": -1637.1021653899293, "apogee_x": 617.2623183698954, "impact_velocity": -5.296386806224455, "max_mach_number": 0.9002908675623732, "x_impact": 151.79827164553308, "out_of_rail_stability_margin": 2.584114299407272, "apogee_time": 25.58263955885719} +{"apogee": 4048.414976487407, "frontal_surface_wind": -4.345265988631907, "apogee_y": 980.7802377662935, "lateral_surface_wind": -5.396419230601599, "t_final": 336.8046289600785, "out_of_rail_velocity": 28.896917789586105, "initial_stability_margin": 2.5787340512638015, "out_of_rail_time": 0.3260160774314721, "y_impact": -2409.6210051643197, "apogee_x": 513.199760638137, "impact_velocity": -5.244512661768816, "max_mach_number": 1.0513832163562005, "x_impact": 267.6088382839362, "out_of_rail_stability_margin": 2.6450942821085452, "apogee_time": 27.337191733480473} +{"apogee": 3966.969352562571, "frontal_surface_wind": -4.158367086202538, "apogee_y": 924.5121992216217, "lateral_surface_wind": -4.843918200397008, "t_final": 339.20911020669985, "out_of_rail_velocity": 28.560796443914143, "initial_stability_margin": 2.6601006872937387, "out_of_rail_time": 0.3289462786117325, "y_impact": -2415.254283439537, "apogee_x": 516.122510910166, "impact_velocity": -5.2539984713720935, "max_mach_number": 1.0308784546640217, "x_impact": 375.91530427578294, "out_of_rail_stability_margin": 2.7279871054629226, "apogee_time": 27.070775305932848} diff --git a/docs/reference/classes/MultivariateRejectionSampler.rst b/docs/reference/classes/MultivariateRejectionSampler.rst new file mode 100644 index 000000000..8f70b8a2d --- /dev/null +++ b/docs/reference/classes/MultivariateRejectionSampler.rst @@ -0,0 +1,5 @@ +MultivariateRejectionSampler Class +---------------------------------- + +.. autoclass:: rocketpy.MultivariateRejectionSampler + :members: diff --git a/docs/reference/index.rst b/docs/reference/index.rst index c0868c0c5..de3b36ac8 100644 --- a/docs/reference/index.rst +++ b/docs/reference/index.rst @@ -20,6 +20,7 @@ This reference manual details functions, modules, methods and attributes include classes/EnvironmentAnalysis Monte Carlo Analysis Sensitivity Analysis + Multivariate Rejection Sampler .. toctree:: :maxdepth: 2 diff --git a/docs/user/index.rst b/docs/user/index.rst index e734abe5d..f23eae25a 100644 --- a/docs/user/index.rst +++ b/docs/user/index.rst @@ -35,7 +35,8 @@ RocketPy's User Guide ../notebooks/monte_carlo_analysis/monte_carlo_class_usage.ipynb ../notebooks/monte_carlo_analysis/monte_carlo_analysis.ipynb ../notebooks/monte_carlo_analysis/parachute_drop_from_helicopter.ipynb - sensitivity.rst + Sensitivity Analysis + Multivariate Rejection Sampler .. toctree:: :maxdepth: 2 diff --git a/docs/user/installation.rst b/docs/user/installation.rst index fe5939e98..844edd2b8 100644 --- a/docs/user/installation.rst +++ b/docs/user/installation.rst @@ -19,7 +19,7 @@ If you want to choose a specific version to guarantee compatibility, you may ins .. code-block:: shell - pip install rocketpy==1.8.0 + pip install rocketpy==1.9.0 Optional Installation Method: ``conda`` diff --git a/docs/user/mrs.rst b/docs/user/mrs.rst new file mode 100644 index 000000000..ec598960e --- /dev/null +++ b/docs/user/mrs.rst @@ -0,0 +1,278 @@ +.. _MRS: + +Multivariate Rejection Sampling +=============================== + +Multivariate Rejection Sampling allows you to quickly subsample the results of a +previous Monte Carlo simulation to obtain the results when one or more variables +have a different probability distribution without having to re-run the simulation. + +We will show you how to use the :class:`rocketpy.MultivariateRejectionSampler` +class to possibly save time. It is highly recommended that you read about Monte +Carlo simulations. + +Motivation +---------- + +As discussed in :ref:`sensitivity-practical`, there are several sources of +uncertainty that can affect the flight of a rocket, notably the weather and +the measurements errors in design parameters. Still, it is desirable that the flight +accomplishes its goal, for instance reaching a certain apogee, as well as staying under +some safety restrictions, such as ensuring that the landing point is outside +of a given area. + +Monte Carlo simulation is a technique that allows us to quantify the uncertainty and +give objective answers to those types of questions in terms of probabilities and +statistics. It relies on running several simulations under different conditions +specified by probability distributions provided by the user. Hence, depending on the +inputs and number of samples, running these Monte Carlo simulations might take a while. + +Now, imagine that you ran and saved the Monte Carlo simulations. Later, you need new a +Monte Carlo simulation with different probability distributions that are somewhat close +to the original simulation. The first straightforward option is to just re-run the +monte carlo with the new arguments, but this might be time consuming. A second option +is to use a sub-sampler that leverages the existing simulation to produce a new sample +that conforms to the new probability distributions. The latter completely avoids +the necessity of re-running the simulations and is, therefore, much faster. + +The Multivariate Rejection Sampler, or just MRS, is an algorithm that sub-samples the +original results based on weights proportional to the ratio of the new and old +probability distributions that have changed. The final result has a smaller sample size, +but their distribution matches the one newly specified without having to re-run +the simulation. + +The time efficiency of the MRS is especially interesting in two scenarios: quick testing +and tight schedules. Imagine you have an initial design and ran a huge robust monte +carlo simulation but you are also interested in minor variations of the original +design. Instead of having to run an expensive monte carlo for each of these variations, +you can just re-sample the original accordingly. For tight schedules, it is not +unheard of cases where last minute changes have to be made to simulations. The MRS might +then allow you to quickly have monte carlo results for the new configuration when a +full simulation might just take more time than available. + +Importing and using the MRS +--------------------------- + +We now show how to actually use the :class:`rocketpy.MultivariateRejectionSampler` +class. We begin by importing it along with other utilities + +.. jupyter-execute:: + + from rocketpy import MultivariateRejectionSampler, MonteCarlo + import numpy as np + from scipy.stats import norm + +The reference monte carlo simulation used is the one from the +"monte_carlo_class_usage.ipynb" notebook with a 1000 samples. A +MultivariateRejectionSampler object is initialized by giving two file paths, one +for the prefix of the original monte carlo simulation, and one for the output of the +sub-samples. The code below defines these strings and initializes the MRS object + + +.. jupyter-execute:: + + monte_carlo_filepath = ( + "notebooks/monte_carlo_analysis/monte_carlo_analysis_outputs/monte_carlo_class_example" + ) + mrs_filepath = "notebooks/monte_carlo_analysis/monte_carlo_analysis_outputs/mrs" + mrs = MultivariateRejectionSampler( + monte_carlo_filepath=monte_carlo_filepath, + mrs_filepath=mrs_filepath, + ) + +Running a monte carlo simulation requires you to specify the distribution of +all parameters that have uncertainty. The MRS, however, only needs the previous and new +distributions of the parameters whose distribution changed. All other random parameters +in the original monte carlo simulation retain their original distribution. + +In the original simulation, the mass of the rocket had a normal distribution with mean +:math:`15.426` and standard deviation of :math:`0.5`. Assume that the mean of this +distribution changed to :math:`15` and the standard deviation remained the same. To +run the mrs, we create a dictionary whose keys are the name of the parameter and the +value is a 2-tuple: the first entry contains the pdf of the old distribution, and the +second entry contains the pdf of the new distribution. The code below shows how to +create these distributions and the dictionary + +.. jupyter-execute:: + + old_mass_pdf = norm(15.426, 0.5).pdf + new_mass_pdf = norm(15, 0.5).pdf + distribution_dict = { + "mass": (old_mass_pdf, new_mass_pdf), + } + +Finally, we execute the `sample` method, as shown below + +.. jupyter-execute:: + :hide-code: + :hide-output: + + np.random.seed(seed=42) + +.. jupyter-execute:: + + mrs.sample(distribution_dict=distribution_dict) + +And that is it! The MRS has saved a file that has the same structure as the results of +a monte carlo simulation but now the mass has been sampled from the newly stated +distribution. To see that it is actually the case, let us import the results of the MRS +and check the mean and standard deviation of the mass. First, we import in the same +way we import the results from a monte carlo simulation + + +.. jupyter-execute:: + + mrs_results = MonteCarlo(mrs_filepath, None, None, None) + mrs_results.import_results() + +Notice that the sample size is now smaller than 1000 samples. Albeit the sample size is +now random, we can check the expected number of samples by printing the +`expected_sample_size` attribute + +.. jupyter-execute:: + + print(mrs.expected_sample_size) + +Now we check the mean and standard deviation of the mass. + +.. jupyter-execute:: + + mrs_mass_list = [] + for single_input_dict in mrs_results.inputs_log: + mrs_mass_list.append(single_input_dict["mass"]) + + print(f"MRS mass mean after resample: {np.mean(mrs_mass_list)}") + print(f"MRS mass std after resample: {np.std(mrs_mass_list)}") + +They are very close to the specified values. + +Comparing Monte Carlo Results +----------------------------- + +Alright, now that we have the results for this new configuration, how does it compare +to the original one? Our rocket has, on average, decreased its mass in about 400 grams +while maintaining all other aspects. How do you think, for example, that the distribution +of the apogee has changed? Let us find out. + +First, we import the original results + +.. jupyter-execute:: + + original_results = MonteCarlo(monte_carlo_filepath, None, None, None) + +Prints +^^^^^^ + +We use the `compare_info` method from the `MonteCarlo` class, passing along +the MRS monte carlo object as argument, to print a summary of the comparison + +.. jupyter-execute:: + + original_results.compare_info(mrs_results) + +This summary resemble closely the printed information from one monte carlo simulation +alone, with the difference now that it has a new column, "Source", that alternates the +results between the original and the other simulation. To answer the question proposed +earlier, compare the mean and median of the apogee between both cases. Is it what you +expected? + + +Histogram and boxplots +^^^^^^^^^^^^^^^^^^^^^^ + +Besides printed comparison, we can also provide a comparison for the distributions in +the form of histograms and boxplots, using the `compare_plots` method + + +.. jupyter-execute:: + + original_results.compare_plots(mrs_results) + +Note that the histograms displays three colors. Two are from the sources, as depicted +in the legend, the third comes from the overlap of the two. + +Ellipses +^^^^^^^^ + +Finally, we can compare the ellipses for the apogees and landing points using the +`compare_ellipses` method + +.. jupyter-execute:: + + original_results.compare_ellipses(mrs_results, ylim=(-4000, 3000)) + +Note we can pass along parameters used in the usual `ellipses` method of the +`MonteCarlo` class, in this case the `ylim` argument to expand the y-axis limits. + +Time Comparison +--------------- + +Is the MRS really much faster than just re-running a Monte Carlo simulation? +Let us take a look at some numbers. All tests ran in a Dell G15 5530, with 16 +13th Gen Intel® Core™ i5-13450HX CPUs, 16GB RAM, running Ubuntu 22.04. Each function +ran 10 times, and no parallelization was used. + +To run the original monte carlo simulation with 1000 samples it took, +on average, about 644 seconds, that is, 10 minutes and 44 seconds. For the MRS described +here, it took, on average, 0.15 seconds, with an expected sample size of 117. To re-run +the monte carlo simulations with 117 samples it took, on average, 76.3 seconds. Hence, +the MRS was, on average, (76.3 / 0.15) ~ 500 times faster than re-running the monte +carlo simulations with the same sample size provided by the MRS. + + +Sampling from nested parameters +------------------------------- + +To sample from parameters that are nested in inner levels, use a key name +formed by the name of the key of the outer level concatenated with a "_" and +the key of the inner level. For instance, to change the distribution +from the "total_impulse" parameter, which is nested within the "motors" +parameter dictionary, we have to use the key name "motors_total_impulse". + + +.. jupyter-execute:: + + old_total_impulse_pdf = norm(6500, 1000).pdf + new_total_impulse_pdf = norm(5500, 1000).pdf + distribution_dict = { + "motors_total_impulse": (old_total_impulse_pdf, new_total_impulse_pdf), + } + mrs.sample(distribution_dict=distribution_dict) + +Finally, if there are multiple named nested structures, we need to use a key +name formed by outer level concatenated with "_", the structure name, "_" and the +inner parameter name. For instance, if we want to change the distribution of +the 'root_chord' of the 'Fins', we have to pass as key +'aerodynamic_surfaces_Fins_root_chord' + +.. jupyter-execute:: + + old_root_chord_pdf = norm(0.12, 0.001).pdf + new_root_chord_pdf = norm(0.119, 0.002).pdf + distribution_dict = { + "aerodynamic_surfaces_Fins_root_chord": ( + old_root_chord_pdf, new_root_chord_pdf + ), + } + mrs.sample(distribution_dict=distribution_dict) + +A word of caution +----------------- + +Albeit the MRS provides results way faster than running the simulation again, it +might reduce the sample size drastically. If several variables undergo +changes in their distribution and the more discrepant these are from the original +ones, the more pronounced will be this sample size reduction. If you need the monte +carlo simulations to have the same sample size as before or if the expected sample size +from the MRS is too low for you current application, then it might be better to +re-run the simulations. + +References +---------- + +[1] CEOTTO, Giovani H., SCHMITT, Rodrigo N., ALVES, Guilherme F., et al. RocketPy: six +degree-of-freedom rocket trajectory simulator. Journal of Aerospace Engineering, 2021, +vol. 34, no 6, p. 04021093. + +[2] CASELLA, George, ROBERT, Christian P., et WELLS, Martin T. Generalized accept-reject +sampling schemes. Lecture notes-monograph series, 2004, p. 342-347. \ No newline at end of file diff --git a/docs/user/sensitivity.rst b/docs/user/sensitivity.rst index 7cac7d980..624fe559e 100644 --- a/docs/user/sensitivity.rst +++ b/docs/user/sensitivity.rst @@ -85,8 +85,8 @@ value of that parameter, i.e. the measured value by the instrument, and the "motors_grain_initial_inner_radius": {"mean": 15 / 1000, "std": 0.375 / 1000}, "motors_grain_outer_radius": {"mean": 33 / 1000, "std": 0.375 / 1000}, # Parachutes - "parachutes_cd_s": {"mean": 10, "std": 0.1}, - "parachutes_lag": {"mean": 1.5, "std": 0.1}, + "parachutes_Main_cd_s": {"mean": 10, "std": 0.1}, + "parachutes_Main_lag": {"mean": 1.5, "std": 0.1}, # Flight "heading": {"mean": 53, "std": 2}, "inclination": {"mean": 84.7, "std": 1}, diff --git a/pyproject.toml b/pyproject.toml index e1d8474c8..842b519e9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "rocketpy" -version = "1.8.0" +version = "1.9.0" description="Advanced 6-DOF trajectory simulation for High-Power Rocketry." dynamic = ["dependencies"] readme = "README.md" @@ -101,6 +101,7 @@ skip-magic-trailing-comma = false line-ending = "auto" docstring-code-format = false docstring-code-line-length = "dynamic" +exclude = ["**/*.json", "**/*.rpy"] [tool.ruff.lint.pydocstyle] diff --git a/rocketpy/__init__.py b/rocketpy/__init__.py index 9979ce3bd..7106af46c 100644 --- a/rocketpy/__init__.py +++ b/rocketpy/__init__.py @@ -46,8 +46,9 @@ ) from .sensitivity import SensitivityModel from .sensors import Accelerometer, Barometer, GnssReceiver, Gyroscope -from .simulation import Flight, MonteCarlo +from .simulation import Flight, MonteCarlo, MultivariateRejectionSampler from .stochastic import ( + StochasticAirBrakes, StochasticEllipticalFins, StochasticEnvironment, StochasticFlight, diff --git a/rocketpy/_encoders.py b/rocketpy/_encoders.py index 48c5d049e..e24bb1a8a 100644 --- a/rocketpy/_encoders.py +++ b/rocketpy/_encoders.py @@ -7,6 +7,8 @@ import numpy as np from rocketpy.mathutils.function import Function +from rocketpy.prints.flight_prints import _FlightPrints +from rocketpy.plots.flight_plots import _FlightPlots class RocketPyEncoder(json.JSONEncoder): @@ -75,6 +77,7 @@ class RocketPyDecoder(json.JSONDecoder): different types of objects from a JSON supported format.""" def __init__(self, *args, **kwargs): + self.resimulate = kwargs.pop("resimulate", False) super().__init__(object_hook=self.object_hook, *args, **kwargs) def object_hook(self, obj): @@ -84,7 +87,56 @@ def object_hook(self, obj): try: class_ = get_class_from_signature(signature) - if hasattr(class_, "from_dict"): + if class_.__name__ == "Flight" and not self.resimulate: + new_flight = class_.__new__(class_) + new_flight.prints = _FlightPrints(new_flight) + new_flight.plots = _FlightPlots(new_flight) + attributes = ( + "rocket", + "env", + "rail_length", + "inclination", + "heading", + "initial_solution", + "terminate_on_apogee", + "max_time", + "max_time_step", + "min_time_step", + "rtol", + "atol", + "time_overshoot", + "name", + "solution", + "out_of_rail_time", + "apogee_time", + "apogee", + "parachute_events", + "impact_state", + "impact_velocity", + "x_impact", + "y_impact", + "t_final", + "flight_phases", + "ax", + "ay", + "az", + "out_of_rail_time_index", + "function_evaluations", + "alpha1", + "alpha2", + "alpha3", + "R1", + "R2", + "R3", + "M1", + "M2", + "M3", + ) + for attribute in attributes: + setattr(new_flight, attribute, obj[attribute]) + new_flight.t_initial = new_flight.initial_solution[0] + return new_flight + elif hasattr(class_, "from_dict"): return class_.from_dict(obj) else: # Filter keyword arguments diff --git a/rocketpy/environment/environment.py b/rocketpy/environment/environment.py index 1a0c044ed..a0a8c4238 100644 --- a/rocketpy/environment/environment.py +++ b/rocketpy/environment/environment.py @@ -1653,38 +1653,6 @@ def process_wyoming_sounding(self, file): # pylint: disable=too-many-statements # Save maximum expected height self._max_expected_height = data_array[-1, 1] - def process_noaaruc_sounding(self, file): # pylint: disable=too-many-statements - """Import and process the upper air sounding data from `NOAA - Ruc Soundings` database (https://rucsoundings.noaa.gov/) given as - ASCII GSD format pages passed by its url to the file parameter. Sets - pressure, temperature, wind-u, wind-v profiles and surface elevation. - - Parameters - ---------- - file : string - URL of an upper air sounding data output from `NOAA Ruc Soundings` - in ASCII GSD format. - - Example: - - https://rucsoundings.noaa.gov/get_raobs.cgi?data_source=RAOB&latest=latest&start_year=2019&start_month_name=Feb&start_mday=5&start_hour=12&start_min=0&n_hrs=1.0&fcst_len=shortest&airport=83779&text=Ascii%20text%20%28GSD%20format%29&hydrometeors=false&start=latest - - - See also - -------- - This method is deprecated and will be fully deleted in version 1.8.0. - - Returns - ------- - None - """ - warnings.warn( - "NOAA RUC models are no longer available. " - "This method is deprecated and will be fully deleted in version 1.8.0.", - DeprecationWarning, - ) - return file - def process_forecast_reanalysis(self, file, dictionary): # pylint: disable=too-many-locals,too-many-statements """Import and process atmospheric data from weather forecasts and reanalysis given as ``netCDF`` or ``OPeNDAP`` files. @@ -2259,26 +2227,6 @@ def select_ensemble_member(self, member=0): self.calculate_speed_of_sound_profile() self.calculate_dynamic_viscosity() - def load_international_standard_atmosphere(self): # pragma: no cover - """Defines the pressure and temperature profile functions set - by `ISO 2533` for the International Standard atmosphere and saves - them as ``Environment.pressure_ISA`` and ``Environment.temperature_ISA``. - - Notes - ----- - This method is **deprecated** and will be removed in version 1.6.0. You - can access :meth:`rocketpy.Environment.pressure_ISA` and - :meth:`rocketpy.Environment.temperature_ISA` directly without the need - to call this method. - """ - warnings.warn( - "load_international_standard_atmosphere() is deprecated in version " - "1.5.0 and will be removed in version 1.7.0. This method is no longer " - "needed as the International Standard Atmosphere is already calculated " - "when the Environment object is created.", - DeprecationWarning, - ) - @funcify_method("Height Above Sea Level (m)", "Pressure (Pa)", "spline", "natural") def pressure_ISA(self): """Pressure, in Pa, as a function of height above sea level as defined @@ -2619,6 +2567,11 @@ def geodesic_to_utm( EW : string Returns "W" for western hemisphere and "E" for eastern hemisphere """ + warnings.warn( + "This function is deprecated and will be removed in v1.10.0. " + "Please use the new method `tools.geodesic_to_utm` instead.", + DeprecationWarning, + ) return geodesic_to_utm_tools(lat, lon, semi_major_axis, flattening) @staticmethod @@ -2656,6 +2609,11 @@ def utm_to_geodesic( lon : float latitude of the analyzed point """ + warnings.warn( + "This function is deprecated and will be removed in v1.10.0. " + "Please use the new method `tools.utm_to_geodesic` instead.", + DeprecationWarning, + ) return utm_to_geodesic_tools(x, y, utm_zone, hemis, semi_major_axis, flattening) @staticmethod diff --git a/rocketpy/environment/fetchers.py b/rocketpy/environment/fetchers.py index baeef329c..d5ac2a1df 100644 --- a/rocketpy/environment/fetchers.py +++ b/rocketpy/environment/fetchers.py @@ -5,7 +5,6 @@ import re import time -import warnings from datetime import datetime, timedelta, timezone import netCDF4 @@ -328,33 +327,6 @@ def fetch_wyoming_sounding(file): return response -@exponential_backoff(max_attempts=5, base_delay=2, max_delay=60) -def fetch_noaaruc_sounding(file): # pragma: no cover - """Fetches sounding data from a specified file using the NOAA RUC soundings. - - Parameters - ---------- - file : str - The URL of the file to fetch. - - Returns - ------- - str - The content of the fetched file. - - Raises - ------ - ImportError - If unable to load the specified file or the file content is too short. - """ - warnings.warn( - "The NOAA RUC soundings are deprecated since September 30th, 2024. " - "This method will be removed in version 1.8.0.", - DeprecationWarning, - ) - return file - - @exponential_backoff(max_attempts=5, base_delay=2, max_delay=60) def fetch_gefs_ensemble(): """Fetches the latest GEFS (Global Ensemble Forecast System) dataset from diff --git a/rocketpy/environment/tools.py b/rocketpy/environment/tools.py index bd3bad804..1239ee6b9 100644 --- a/rocketpy/environment/tools.py +++ b/rocketpy/environment/tools.py @@ -443,9 +443,44 @@ def get_interval_date_from_time_array(time_array, units=None): def geodesic_to_utm(lat, lon, semi_major_axis=6378137.0, flattening=1 / 298.257223563): # pylint: disable=too-many-locals,too-many-statements - # NOTE: already documented in the Environment class. - # TODO: deprecated the static method from the environment class, use only this one. + """Function which converts geodetic coordinates, i.e. lat/lon, to UTM + projection coordinates. Can be used only for latitudes between -80.00° + and 84.00° + Parameters + ---------- + lat : float + The latitude coordinates of the point of analysis, must be contained + between -80.00° and 84.00° + lon : float + The longitude coordinates of the point of analysis, must be + contained between -180.00° and 180.00° + semi_major_axis : float + The semi-major axis of the ellipsoid used to represent the Earth, + must be given in meters (default is 6,378,137.0 m, which corresponds + to the WGS84 ellipsoid) + flattening : float + The flattening of the ellipsoid used to represent the Earth, usually + between 1/250 and 1/150 (default is 1/298.257223563, which + corresponds to the WGS84 ellipsoid) + + Returns + ------- + x : float + East coordinate, always positive + y : float + North coordinate, always positive + utm_zone : int + The number of the UTM zone of the point of analysis, can vary + between 1 and 60 + utm_letter : string + The letter of the UTM zone of the point of analysis, can vary + between C and X, omitting the letters "I" and "O" + hemis : string + Returns "S" for southern hemisphere and "N" for Northern hemisphere + EW : string + Returns "W" for western hemisphere and "E" for eastern hemisphere + """ # Calculate the central meridian of UTM zone if lon != 0: signal = lon / abs(lon) @@ -529,9 +564,37 @@ def geodesic_to_utm(lat, lon, semi_major_axis=6378137.0, flattening=1 / 298.2572 def utm_to_geodesic( # pylint: disable=too-many-locals,too-many-statements x, y, utm_zone, hemis, semi_major_axis=6378137.0, flattening=1 / 298.257223563 ): - # NOTE: already documented in the Environment class. - # TODO: deprecate the static method from the environment class, use only this one. + """Function to convert UTM coordinates to geodesic coordinates + (i.e. latitude and longitude). + Parameters + ---------- + x : float + East UTM coordinate in meters + y : float + North UTM coordinate in meters + utm_zone : int + The number of the UTM zone of the point of analysis, can vary + between 1 and 60 + hemis : string + Equals to "S" for southern hemisphere and "N" for Northern + hemisphere + semi_major_axis : float + The semi-major axis of the ellipsoid used to represent the Earth, + must be given in meters (default is 6,378,137.0 m, which corresponds + to the WGS84 ellipsoid) + flattening : float + The flattening of the ellipsoid used to represent the Earth, usually + between 1/250 and 1/150 (default is 1/298.257223563, which + corresponds to the WGS84 ellipsoid) + + Returns + ------- + lat : float + latitude of the analyzed point + lon : float + latitude of the analyzed point + """ if hemis == "N": y = y + 10000000 diff --git a/rocketpy/mathutils/function.py b/rocketpy/mathutils/function.py index 143912357..a20aa9a03 100644 --- a/rocketpy/mathutils/function.py +++ b/rocketpy/mathutils/function.py @@ -2219,10 +2219,10 @@ def __rsub__(self, other): """ return other + (-self) - def __mul__(self, other): + def __mul__(self, other): # pylint: disable=too-many-statements """Multiplies a Function object and returns a new Function object which gives the result of the multiplication. Only implemented for 1D - domains. + and 2D domains. Parameters ---------- @@ -2238,7 +2238,7 @@ def __mul__(self, other): Returns ------- result : Function - A Function object which gives the result of self(x)*other(x). + A Function object which gives the result of self(x)*other(x) or self(x,y)*other(x,y). """ self_source_is_array = isinstance(self.source, np.ndarray) other_source_is_array = ( @@ -2250,37 +2250,76 @@ def __mul__(self, other): interp = self.__interpolation__ extrap = self.__extrapolation__ - if ( - self_source_is_array - and other_source_is_array - and np.array_equal(self.x_array, other.x_array) - ): - source = np.column_stack((self.x_array, self.y_array * other.y_array)) - outputs = f"({self.__outputs__[0]}*{other.__outputs__[0]})" - return Function(source, inputs, outputs, interp, extrap) - elif isinstance(other, NUMERICAL_TYPES) or self.__is_single_element_array( - other - ): - if not self_source_is_array: - return Function(lambda x: (self.get_value_opt(x) * other), inputs) - source = np.column_stack((self.x_array, np.multiply(self.y_array, other))) - outputs = f"({self.__outputs__[0]}*{other})" - return Function( - source, - inputs, - outputs, - interp, - extrap, - ) - elif callable(other): - return Function(lambda x: (self.get_value_opt(x) * other(x)), inputs) - else: - raise TypeError("Unsupported type for multiplication") + if self.__dom_dim__ == 1: + if ( + self_source_is_array + and other_source_is_array + and np.array_equal(self.x_array, other.x_array) + ): + source = np.column_stack((self.x_array, self.y_array * other.y_array)) + outputs = f"({self.__outputs__[0]}*{other.__outputs__[0]})" + return Function(source, inputs, outputs, interp, extrap) + elif isinstance(other, NUMERICAL_TYPES) or self.__is_single_element_array( + other + ): + if not self_source_is_array: + return Function(lambda x: (self.get_value_opt(x) * other), inputs) + source = np.column_stack( + (self.x_array, np.multiply(self.y_array, other)) + ) + outputs = f"({self.__outputs__[0]}*{other})" + return Function( + source, + inputs, + outputs, + interp, + extrap, + ) + elif callable(other): + return Function(lambda x: (self.get_value_opt(x) * other(x)), inputs) + else: + raise TypeError("Unsupported type for multiplication") + elif self.__dom_dim__ == 2: + if ( + self_source_is_array + and other_source_is_array + and np.array_equal(self.x_array, other.x_array) + and np.array_equal(self.y_array, other.y_array) + ): + source = np.column_stack( + (self.x_array, self.y_array, self.z_array * other.z_array) + ) + outputs = f"({self.__outputs__[0]}*{other.__outputs__[0]})" + return Function(source, inputs, outputs, interp, extrap) + elif isinstance(other, NUMERICAL_TYPES) or self.__is_single_element_array( + other + ): + if not self_source_is_array: + return Function( + lambda x, y: (self.get_value_opt(x, y) * other), inputs + ) + source = np.column_stack( + (self.x_array, self.y_array, np.multiply(self.z_array, other)) + ) + outputs = f"({self.__outputs__[0]}*{other})" + return Function( + source, + inputs, + outputs, + interp, + extrap, + ) + elif callable(other): + return Function( + lambda x, y: (self.get_value_opt(x, y) * other(x)), inputs + ) + else: + raise TypeError("Unsupported type for multiplication") def __rmul__(self, other): """Multiplies 'other' by a Function object and returns a new Function object which gives the result of the multiplication. Only implemented for - 1D domains. + 1D and 2D domains. Parameters ---------- @@ -2290,7 +2329,7 @@ def __rmul__(self, other): Returns ------- result : Function - A Function object which gives the result of other(x)*self(x). + A Function object which gives the result of other(x,y)*self(x,y). """ return self * other @@ -3492,7 +3531,7 @@ def funcify_method(*args, **kwargs): # pylint: disable=too-many-statements >>> example.f 'Function from R1 to R1 : (x) → (f(x))' - In order to reset the cache, just delete de attribute from the instance: + In order to reset the cache, just delete the attribute from the instance: >>> del example.f diff --git a/rocketpy/motors/empty_motor.py b/rocketpy/motors/empty_motor.py index 4e844472b..ff7128c11 100644 --- a/rocketpy/motors/empty_motor.py +++ b/rocketpy/motors/empty_motor.py @@ -19,6 +19,7 @@ def __init__(self): reshape_thrust_curve=False, interpolation_method="linear", coordinate_system_orientation="nozzle_to_combustion_chamber", + reference_pressure=0, ) # Mass properties diff --git a/rocketpy/motors/hybrid_motor.py b/rocketpy/motors/hybrid_motor.py index ea01e686f..1de9f435c 100644 --- a/rocketpy/motors/hybrid_motor.py +++ b/rocketpy/motors/hybrid_motor.py @@ -29,6 +29,8 @@ class HybridMotor(Motor): "combustion_chamber_to_nozzle". HybridMotor.nozzle_radius : float Radius of motor nozzle outlet in meters. + HybridMotor.nozzle_area : float + Area of motor nozzle outlet in square meters. HybridMotor.nozzle_position : float Motor's nozzle outlet position in meters, specified in the motor's coordinate system. See @@ -147,7 +149,11 @@ class HybridMotor(Motor): HybridMotor.propellant_I_22 and HybridMotor.propellant_I_33 for more information. HybridMotor.thrust : Function - Motor thrust force, in Newtons, as a function of time. + Motor thrust force obtained from thrust source, in Newtons, as a + function of time. + HybridMotor.vacuum_thrust : Function + Motor thrust force when the rocket is in a vacuum. In Newtons, as a + function of time. HybridMotor.total_impulse : float Total impulse of the thrust curve in N*s. HybridMotor.max_thrust : float @@ -167,7 +173,10 @@ class HybridMotor(Motor): Total motor burn duration, in seconds. It is the difference between the ``burn_out_time`` and the ``burn_start_time``. HybridMotor.exhaust_velocity : Function - Propulsion gases exhaust velocity, assumed constant, in m/s. + Effective exhaust velocity of the propulsion gases in m/s. Computed + as the thrust divided by the mass flow rate. This corresponds to the + actual exhaust velocity only when the nozzle exit pressure equals the + atmospheric pressure. HybridMotor.burn_area : Function Total burn area considering all grains, made out of inner cylindrical burn area and grain top and bottom faces. Expressed @@ -181,6 +190,9 @@ class HybridMotor(Motor): Method of interpolation used in case thrust curve is given by data set in .csv or .eng, or as an array. Options are 'spline' 'akima' and 'linear'. Default is "linear". + HybridMotor.reference_pressure : int, float + Atmospheric pressure in Pa at which the thrust data was recorded. + It will allow to obtain the net thrust in the Flight class. """ def __init__( # pylint: disable=too-many-arguments @@ -203,6 +215,7 @@ def __init__( # pylint: disable=too-many-arguments reshape_thrust_curve=False, interpolation_method="linear", coordinate_system_orientation="nozzle_to_combustion_chamber", + reference_pressure=None, ): """Initialize Motor class, process thrust curve and geometrical parameters and store results. @@ -298,6 +311,8 @@ class Function. Thrust units are Newtons. positions specified. Options are "nozzle_to_combustion_chamber" and "combustion_chamber_to_nozzle". Default is "nozzle_to_combustion_chamber". + reference_pressure : int, float, optional + Atmospheric pressure in Pa at which the thrust data was recorded. Returns ------- @@ -314,6 +329,7 @@ class Function. Thrust units are Newtons. reshape_thrust_curve=reshape_thrust_curve, interpolation_method=interpolation_method, coordinate_system_orientation=coordinate_system_orientation, + reference_pressure=reference_pressure, ) self.liquid = LiquidMotor( thrust_source, @@ -326,6 +342,7 @@ class Function. Thrust units are Newtons. reshape_thrust_curve, interpolation_method, coordinate_system_orientation, + reference_pressure, ) self.solid = SolidMotor( thrust_source, @@ -346,6 +363,7 @@ class Function. Thrust units are Newtons. reshape_thrust_curve, interpolation_method, coordinate_system_orientation, + reference_pressure, ) self.positioned_tanks = self.liquid.positioned_tanks @@ -371,6 +389,11 @@ def exhaust_velocity(self): ------- self.exhaust_velocity : Function Gas exhaust velocity of the motor. + + Notes + ----- + This corresponds to the actual exhaust velocity only when the nozzle + exit pressure equals the atmospheric pressure. """ return Function( self.total_impulse / self.propellant_initial_mass @@ -676,6 +699,7 @@ def from_dict(cls, data): grains_center_of_mass_position=data["grains_center_of_mass_position"], nozzle_position=data["nozzle_position"], throat_radius=data["throat_radius"], + reference_pressure=data["reference_pressure"], ) for tank in data["positioned_tanks"]: diff --git a/rocketpy/motors/liquid_motor.py b/rocketpy/motors/liquid_motor.py index 7e763dd70..5edaae3b8 100644 --- a/rocketpy/motors/liquid_motor.py +++ b/rocketpy/motors/liquid_motor.py @@ -29,6 +29,8 @@ class LiquidMotor(Motor): "combustion_chamber_to_nozzle". LiquidMotor.nozzle_radius : float Radius of motor nozzle outlet in meters. + LiquidMotor.nozzle_area : float + Area of motor nozzle outlet in square meters. LiquidMotor.nozzle_position : float Motor's nozzle outlet position in meters, specified in the motor's coordinate system. See @@ -122,7 +124,11 @@ class LiquidMotor(Motor): LiquidMotor.propellant_I_22 and LiquidMotor.propellant_I_33 for more information. LiquidMotor.thrust : Function - Motor thrust force, in Newtons, as a function of time. + Motor thrust force obtained from thrust source, in Newtons, as a + function of time. + LiquidMotor.vacuum_thrust : Function + Motor thrust force when the rocket is in a vacuum. In Newtons, as a + function of time. LiquidMotor.total_impulse : float Total impulse of the thrust curve in N*s. LiquidMotor.max_thrust : float @@ -142,7 +148,13 @@ class LiquidMotor(Motor): Total motor burn duration, in seconds. It is the difference between the burn_out_time and the burn_start_time. LiquidMotor.exhaust_velocity : Function - Propulsion gases exhaust velocity in m/s. + Effective exhaust velocity of the propulsion gases in m/s. Computed + as the thrust divided by the mass flow rate. This corresponds to the + actual exhaust velocity only when the nozzle exit pressure equals the + atmospheric pressure. + LiquidMotor.reference_pressure : int, float + Atmospheric pressure in Pa at which the thrust data was recorded. + It will allow to obtain the net thrust in the Flight class. """ def __init__( @@ -157,6 +169,7 @@ def __init__( reshape_thrust_curve=False, interpolation_method="linear", coordinate_system_orientation="nozzle_to_combustion_chamber", + reference_pressure=None, ): """Initialize LiquidMotor class, process thrust curve and geometrical parameters and store results. @@ -230,6 +243,8 @@ class Function. Thrust units are Newtons. positions specified. Options are "nozzle_to_combustion_chamber" and "combustion_chamber_to_nozzle". Default is "nozzle_to_combustion_chamber". + reference_pressure : int, float, optional + Atmospheric pressure in Pa at which the thrust data was recorded. """ super().__init__( thrust_source=thrust_source, @@ -242,6 +257,7 @@ class Function. Thrust units are Newtons. reshape_thrust_curve=reshape_thrust_curve, interpolation_method=interpolation_method, coordinate_system_orientation=coordinate_system_orientation, + reference_pressure=reference_pressure, ) self.positioned_tanks = [] @@ -264,7 +280,8 @@ def exhaust_velocity(self): ----- The exhaust velocity is computed as the ratio of the thrust and the mass flow rate. Therefore, this will vary with time if the mass flow - rate varies with time. + rate varies with time. This corresponds to the actual exhaust velocity + only when the nozzle exit pressure equals the atmospheric pressure. """ times, thrusts = self.thrust.source[:, 0], self.thrust.source[:, 1] mass_flow_rates = self.mass_flow_rate(times) @@ -511,6 +528,7 @@ def from_dict(cls, data): nozzle_position=data["nozzle_position"], interpolation_method=data["interpolate"], coordinate_system_orientation=data["coordinate_system_orientation"], + reference_pressure=data["reference_pressure"], ) for tank in data["positioned_tanks"]: diff --git a/rocketpy/motors/motor.py b/rocketpy/motors/motor.py index 5f4b0dc0b..ebc39b05a 100644 --- a/rocketpy/motors/motor.py +++ b/rocketpy/motors/motor.py @@ -1,5 +1,6 @@ import re import warnings +import xml.etree.ElementTree as ET from abc import ABC, abstractmethod from functools import cached_property from os import path @@ -28,6 +29,8 @@ class Motor(ABC): "combustion_chamber_to_nozzle". Motor.nozzle_radius : float Radius of motor nozzle outlet in meters. + Motor.nozzle_area : float + Area of motor nozzle outlet in square meters. Motor.nozzle_position : float Motor's nozzle outlet position in meters, specified in the motor's coordinate system. See :ref:`positions` for more information. @@ -121,7 +124,11 @@ class Motor(ABC): e_3 axes in kg*m^2, as a function of time. See Motor.propellant_I_22 and Motor.propellant_I_33 for more information. Motor.thrust : Function - Motor thrust force, in Newtons, as a function of time. + Motor thrust force obtained from the thrust source, in Newtons, as a + function of time. + Motor.vacuum_thrust : Function + Motor thrust force when the rocket is in a vacuum. In Newtons, as a + function of time. Motor.total_impulse : float Total impulse of the thrust curve in N*s. Motor.max_thrust : float @@ -141,11 +148,17 @@ class Motor(ABC): Total motor burn duration, in seconds. It is the difference between the burn_out_time and the burn_start_time. Motor.exhaust_velocity : Function - Propulsion gases exhaust velocity in m/s. + Effective exhaust velocity of the propulsion gases in m/s. Computed + as the thrust divided by the mass flow rate. This corresponds to the + actual exhaust velocity only when the nozzle exit pressure equals the + atmospheric pressure. Motor.interpolate : string Method of interpolation used in case thrust curve is given by data set in .csv or .eng, or as an array. Options are 'spline' 'akima' and 'linear'. Default is "linear". + Motor.reference_pressure : int, float, None + Atmospheric pressure in Pa at which the thrust data was recorded. + It will allow to obtain the net thrust in the Flight class. """ # pylint: disable=too-many-statements @@ -161,6 +174,7 @@ def __init__( reshape_thrust_curve=False, interpolation_method="linear", coordinate_system_orientation="nozzle_to_combustion_chamber", + reference_pressure=None, ): """Initialize Motor class, process thrust curve and geometrical parameters and store results. @@ -236,6 +250,8 @@ class Function. Thrust units are Newtons. positions specified. Options are "nozzle_to_combustion_chamber" and "combustion_chamber_to_nozzle". Default is "nozzle_to_combustion_chamber". + reference_pressure : int, float, optional + Atmospheric pressure in Pa at which the thrust data was recorded. Returns ------- @@ -257,7 +273,9 @@ class Function. Thrust units are Newtons. self.interpolate = interpolation_method self.nozzle_position = nozzle_position self.nozzle_radius = nozzle_radius + self.nozzle_area = np.pi * nozzle_radius**2 self.center_of_dry_mass_position = center_of_dry_mass_position + self.reference_pressure = reference_pressure # Inertia tensor setup inertia = (*dry_inertia, 0, 0, 0) if len(dry_inertia) == 3 else dry_inertia @@ -268,8 +286,9 @@ class Function. Thrust units are Newtons. self.dry_I_13 = inertia[4] self.dry_I_23 = inertia[5] - # Handle .eng file inputs + # Handle .eng or .rse file inputs self.description_eng_file = None + self.rse_motor_data = None if isinstance(thrust_source, str): if ( path.exists(thrust_source) @@ -277,7 +296,12 @@ class Function. Thrust units are Newtons. ): _, self.description_eng_file, points = Motor.import_eng(thrust_source) thrust_source = points - + elif ( + path.exists(thrust_source) + and path.splitext(path.basename(thrust_source))[1] == ".rse" + ): + self.rse_motor_data, points = Motor.import_rse(thrust_source) + thrust_source = points # Evaluate raw thrust source self.thrust_source = thrust_source self.thrust = Function( @@ -307,10 +331,6 @@ class Function. Thrust units are Newtons. self.burn_out_time = self.burn_time[1] self.burn_duration = self.burn_time[1] - self.burn_time[0] - # Define motor attributes - self.nozzle_radius = nozzle_radius - self.nozzle_position = nozzle_position - # Compute thrust metrics self.max_thrust = np.amax(self.thrust.y_array) max_thrust_index = np.argmax(self.thrust.y_array) @@ -381,6 +401,10 @@ def dry_mass(self, dry_mass): self._dry_mass = float(self.description_eng_file[-2]) - float( self.description_eng_file[-3] ) + elif self.rse_motor_data: + self._dry_mass = float( + self.rse_motor_data["description"]["total_mass"] + ) - float(self.rse_motor_data["description"]["propellant_mass"]) else: raise ValueError("Dry mass must be specified.") @@ -399,7 +423,7 @@ def total_impulse(self): @property @abstractmethod def exhaust_velocity(self): - """Exhaust velocity of the motor gases. + """Effective exhaust velocity of the motor gases. Returns ------- @@ -418,6 +442,9 @@ def exhaust_velocity(self): - The ``LiquidMotor`` class favors the more accurate data from the Tanks's mass flow rates. Therefore the exhaust velocity is generally variable, being the ratio of the motor thrust by the mass flow rate. + + This corresponds to the actual exhaust velocity only when the nozzle + exit pressure equals the atmospheric pressure. """ @funcify_method("Time (s)", "Total mass (kg)") @@ -990,6 +1017,83 @@ def clip_thrust(thrust, new_burn_time): "zero", ) + @staticmethod + def import_rse(file_name): + """ + Reads motor data from a file and extracts comments, model, description, and data points. + + Parameters + ---------- + file_path : str + Path to the motor data file. + + Returns + ------- + dict + A dictionary containing the extracted data: + - comments: List of comments in the file. + - model: Dictionary with manufacturer, code, and type of the motor. + - description: Dictionary with performance data (dimensions, weights, thrust, etc.). + - data_points: List of temporal data points (time, thrust, mass, cg). + tuple + A tuple representing the thrust curve (time, thrust). + """ + + # Parse the XML file + tree = ET.parse(file_name) + root = tree.getroot() + + # Extract comments + comments = [] + for comment in root.iter(): + if comment.tag.startswith("