diff --git a/rocketpy/rocket/parachute.py b/rocketpy/rocket/parachute.py index f0bf86f67..a9224a3c8 100644 --- a/rocketpy/rocket/parachute.py +++ b/rocketpy/rocket/parachute.py @@ -209,7 +209,6 @@ def __init__( - 0.25975 * self.porosity**2 + 1.2626 * self.porosity**3 ) - alpha, beta = self.noise_corr self.noise_function = lambda: alpha * self.noise_signal[-1][ 1 diff --git a/rocketpy/simulation/flight.py b/rocketpy/simulation/flight.py index a7e0374b2..b8e65a481 100644 --- a/rocketpy/simulation/flight.py +++ b/rocketpy/simulation/flight.py @@ -765,6 +765,21 @@ def __simulate(self, verbose): "parachute_added_mass_coefficient", added_mass_coefficient, ), + lambda self: setattr( + self, + "parachute_volume", + (4 / 3) + * math.pi + * (self.parachute_height / self.parachute_radius) + * ( + min( + self.parachute_radius, + self.rocket.radius, + ) + ) + * 3, + ), + lambda self: delattr(self, "t0"), ] self.flight_phases.add_phase( node.t + parachute.lag, @@ -987,6 +1002,21 @@ def __check_and_handle_parachute_triggers( "parachute_added_mass_coefficient", added_mass_coefficient, ), + lambda self: setattr( + self, + "parachute_volume", + (4 / 3) + * math.pi + * (self.parachute_height / self.parachute_radius) + * ( + min( + self.parachute_radius, + self.rocket.radius, + ) + ) + * 3, + ), + lambda self: delattr(self, "t0"), ] self.flight_phases.add_phase( node.t + parachute.lag, @@ -2702,31 +2732,58 @@ def u_dot_parachute(self, t, u, post_processing=False): # Get the mass of the rocket mp = self.rocket.dry_mass - # to = 1.2 - # eta = 1 - # Rdot = (6 * R * (1 - eta) / (1.2**6)) * ( - # (1 - eta) * t**5 + eta * (to**3) * (t**2) - # ) - # Rdot = 0 - - # tf = 8 * nominal diameter / velocity at line stretch - - # Calculate added mass - ma = ( - self.parachute_added_mass_coefficient - * rho - * (2 / 3) - * np.pi - * self.parachute_radius**2 - * self.parachute_height - ) - # Calculate freestream speed freestream_x = vx - wind_velocity_x freestream_y = vy - wind_velocity_y freestream_z = vz free_stream_speed = (freestream_x**2 + freestream_y**2 + freestream_z**2) ** 0.5 + # Initialize parachute geometrical parameters + radius = self.parachute_radius + height = self.parachute_height + inflated_radius = ( + (3 * self.parachute_volume * radius) / (4 * math.pi * height) + ) ** (1 / 3) + inflated_height = inflated_radius * height / radius + + # Calculate the surface area of the parachute + if radius > height: + e = math.sqrt(1 - (inflated_height**2) / (inflated_radius**2)) + surface_area = ( + math.pi * inflated_radius**2 * (1 + (1 - e**2) / e * math.atanh(e)) + ) + else: + e = math.sqrt(1 - (inflated_radius**2) / (inflated_height**2)) + surface_area = ( + math.pi + * inflated_radius**2 + * (1 + inflated_height / (e * inflated_radius) * math.asin(e)) + ) + + # Calculate volume flow of air into parachute + volume_flow = ( + rho + * freestream_z # considering parachute as vertical + * ( + (math.pi * inflated_radius**2) + - (self.parachute_porosity * surface_area) + ) + ) + + # Getting time step + self.t0 = getattr(self, "t0", t) + t1 = t + dt = t1 - self.t0 + + # Integrating parachute volume + self.parachute_volume += volume_flow * dt + + # Dragged air mass + ma = self.parachute_volume * rho + + # Moving time step + self.t0 = t1 + # Determine drag force pseudo_drag = -0.5 * rho * self.parachute_cd_s * free_stream_speed # pseudo_drag = pseudo_drag - ka * rho * 4 * np.pi * (R**2) * Rdot