Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ Attention: The newest changes should be on top -->

### Added

- ENH: Add simplified opening shock force estimation [#1092](https://github.com/RocketPy-Team/RocketPy/pull/1092)
- ENH: Support for Meteomatics API in the `Environment` class [#1079](https://github.com/RocketPy-Team/RocketPy/pull/1079)
- ENH: update master with develop [#1081](https://github.com/RocketPy-Team/RocketPy/pull/1081)

Expand Down
44 changes: 44 additions & 0 deletions rocketpy/utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -780,3 +780,47 @@ def load_from_rpy(filename: str, resimulate=False):
simulation = json.dumps(data["simulation"])
flight = json.loads(simulation, cls=RocketPyDecoder, resimulate=resimulate)
return flight


def calculate_simplified_opening_shock_force(
cd_s, air_density, velocity, opening_shock_coefficient=1.5
):
"""Estimates the peak transient force experienced by the recovery
hardware during parachute inflation (the "opening shock").

The estimate follows the simplified model described in Knacke's
"Parachute Recovery Systems Design Manual" (1992, Section 5.5):

.. math::

F_0 = C_x \\cdot C_{d} S \\cdot q

where :math:`C_x` is the ``opening_shock_coefficient``,
:math:`C_{d} S` is the parachute's ``cd_s``, and :math:`q` is the
dynamic pressure (:math:`q = \\tfrac{1}{2} \\rho V^2`) at the instant
the canopy begins to inflate.

Parameters
----------
cd_s : float
Drag coefficient times reference area of the parachute.
air_density : float
Freestream air density, in kg/m^3, at the moment of parachute
deployment.
velocity : float
Freestream velocity relative to the rocket, in m/s, at the moment
of parachute deployment.
opening_shock_coefficient : float, optional
Empirical coefficient (commonly noted Cx) used to estimate the
peak transient force experienced during parachute inflation via
:meth:`calculate_opening_shock_force`. Typical values range from
1.2 to 2.0 depending on the deployment method and canopy type.
Default value is 1.5.

Returns
-------
float
Estimated peak opening shock force, in Newtons.
"""
dynamic_pressure = 0.5 * air_density * velocity**2
return opening_shock_coefficient * cd_s * dynamic_pressure
35 changes: 35 additions & 0 deletions tests/unit/test_utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,41 @@ def test_load_from_rpy(mock_show): # pylint: disable=unused-argument
assert loaded_flight.all_info() is None


def test_opening_shock_coefficient_default_is_1_5():
"""Default opening_shock_coefficient must be 1.5."""
force_default = utilities.calculate_simplified_opening_shock_force(10.0, 1.225, 10)
force_1_5 = utilities.calculate_simplified_opening_shock_force(10.0, 1.225, 10, 1.5)
assert force_default == force_1_5


def test_calculate_simplified_opening_shock_force_matches_formula():
"""calculate_simplified_opening_shock_force must return
Cx * cd_s * 0.5 * rho * V^2."""
cd_s = 10.0
cx = 1.6
air_density = 1.225
velocity = 50.0

expected_force = cx * cd_s * 0.5 * air_density * velocity**2
assert utilities.calculate_simplified_opening_shock_force(
cd_s, air_density, velocity, cx
) == pytest.approx(expected_force, rel=1e-9)


def test_calculate_simplified_opening_shock_force_scales_with_velocity_squared():
"""Doubling velocity must quadruple the opening shock force."""
force_v = utilities.calculate_simplified_opening_shock_force(10.0, 1.225, 40.0)
force_2v = utilities.calculate_simplified_opening_shock_force(10.0, 1.225, 80.0)
assert force_2v == pytest.approx(4 * force_v, rel=1e-9)


def test_calculate_simplified_opening_shock_force_zero_velocity_is_zero():
"""No dynamic pressure means no opening shock force."""
assert utilities.calculate_simplified_opening_shock_force(
10.0, 1.225, 0.0
) == pytest.approx(0.0)


# --- Logging (rocketpy.utilities.enable_logging) ------------------------------


Expand Down