Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
9fe3a37
wind factor bug corrected
kevin-alcaniz Mar 14, 2025
f6efa81
BUG: StochasticModel visualize attributes of a uniform distribution
kevin-alcaniz Mar 15, 2025
04337ab
variable names corrections
kevin-alcaniz Mar 15, 2025
7f551c2
Merge branch 'develop' into develop
kevin-alcaniz Mar 15, 2025
18f8323
Corrections requested by the pylint test
kevin-alcaniz Mar 15, 2025
72c63b4
Merge branch 'develop' of https://github.com/kevin-alcaniz/RocketPy i…
kevin-alcaniz Mar 15, 2025
a46de46
ENH: add multiplication for 2D functions in rocketpy.function
kevin-alcaniz Mar 16, 2025
7181360
ENH: StochasticAirBrakes class created
kevin-alcaniz Mar 16, 2025
e1549e0
ENH: set_air_brakes function created
kevin-alcaniz Mar 18, 2025
89a83a6
Merge pull request #1 from kevin-alcaniz/enh/set-air-brakes-function
kevin-alcaniz Mar 18, 2025
b14ce09
Merge pull request #2 from kevin-alcaniz/enh/multiply_2D_functions
kevin-alcaniz Mar 18, 2025
2d2a0e8
ENH: add StochasticAirBrake to rocketpy.stochastic_rocket
kevin-alcaniz Mar 18, 2025
b206647
BUG: StochasticAirBrake object input in _Controller
kevin-alcaniz Mar 18, 2025
f0ebdda
Merge pull request #3 from kevin-alcaniz/bug/stochastic-airbrake-in-c…
kevin-alcaniz Mar 18, 2025
e45ae76
ENH: add time_overshoot option to rocketpy.stochastic_flight
kevin-alcaniz Mar 18, 2025
7f082d2
DOC: StochasticAirBrakes related documentation added
kevin-alcaniz Mar 18, 2025
1c4c791
ENH: pylint recommendations done
kevin-alcaniz Mar 18, 2025
85e82e6
ENH: Reformatted files to pass Ruff linting checks
kevin-alcaniz Mar 18, 2025
0eead44
Merge pull request #4 from kevin-alcaniz/enh/ruff-modifications
kevin-alcaniz Mar 18, 2025
a52ad3e
ENH: Update rocketpy/stochastic/stochastic_rocket.py
kevin-alcaniz Mar 19, 2025
91f83c8
DOC: improve drag curve factor definition in StochasticAirBrakes
kevin-alcaniz Mar 23, 2025
95a69fa
ENH: Change assert statement to if
kevin-alcaniz Mar 23, 2025
ac958d6
DOC: better explanation of __mul__ function
kevin-alcaniz Mar 23, 2025
d51f15b
ENH: delete set_air_brakes function for simplicity
kevin-alcaniz Mar 23, 2025
8e66319
Merge branch 'enh/stochastic-airbrakes-feature' of https://github.com…
kevin-alcaniz Mar 23, 2025
6d8c9b5
Merge branch 'develop' into enh/stochastic-airbrakes-feature
kevin-alcaniz Mar 23, 2025
f83bf87
DOC: CHANGELOG file updated
kevin-alcaniz Mar 23, 2025
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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ Attention: The newest changes should be on top -->

- 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

Expand All @@ -46,6 +48,7 @@ Attention: The newest changes should be on top -->
- 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
Expand Down
1 change: 1 addition & 0 deletions rocketpy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
from .sensors import Accelerometer, Barometer, GnssReceiver, Gyroscope
from .simulation import Flight, MonteCarlo
from .stochastic import (
StochasticAirBrakes,
StochasticEllipticalFins,
StochasticEnvironment,
StochasticFlight,
Expand Down
101 changes: 70 additions & 31 deletions rocketpy/mathutils/function.py
Original file line number Diff line number Diff line change
Expand Up @@ -2219,10 +2219,10 @@
"""
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
----------
Expand All @@ -2238,7 +2238,7 @@
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 = (
Expand All @@ -2250,37 +2250,76 @@
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 (

Check warning on line 2283 in rocketpy/mathutils/function.py

View check run for this annotation

Codecov / codecov/patch

rocketpy/mathutils/function.py#L2281-L2283

Added lines #L2281 - L2283 were not covered by tests
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(

Check warning on line 2289 in rocketpy/mathutils/function.py

View check run for this annotation

Codecov / codecov/patch

rocketpy/mathutils/function.py#L2289

Added line #L2289 was not covered by tests
(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(

Check warning on line 2294 in rocketpy/mathutils/function.py

View check run for this annotation

Codecov / codecov/patch

rocketpy/mathutils/function.py#L2292-L2294

Added lines #L2292 - L2294 were not covered by tests
other
):
if not self_source_is_array:
return Function(

Check warning on line 2298 in rocketpy/mathutils/function.py

View check run for this annotation

Codecov / codecov/patch

rocketpy/mathutils/function.py#L2297-L2298

Added lines #L2297 - L2298 were not covered by tests
lambda x, y: (self.get_value_opt(x, y) * other), inputs
)
source = np.column_stack(

Check warning on line 2301 in rocketpy/mathutils/function.py

View check run for this annotation

Codecov / codecov/patch

rocketpy/mathutils/function.py#L2301

Added line #L2301 was not covered by tests
(self.x_array, self.y_array, np.multiply(self.z_array, other))
)
outputs = f"({self.__outputs__[0]}*{other})"
return Function(

Check warning on line 2305 in rocketpy/mathutils/function.py

View check run for this annotation

Codecov / codecov/patch

rocketpy/mathutils/function.py#L2304-L2305

Added lines #L2304 - L2305 were not covered by tests
source,
inputs,
outputs,
interp,
extrap,
)
elif callable(other):
return Function(

Check warning on line 2313 in rocketpy/mathutils/function.py

View check run for this annotation

Codecov / codecov/patch

rocketpy/mathutils/function.py#L2312-L2313

Added lines #L2312 - L2313 were not covered by tests
lambda x, y: (self.get_value_opt(x, y) * other(x)), inputs
)
else:
raise TypeError("Unsupported type for multiplication")

Check warning on line 2317 in rocketpy/mathutils/function.py

View check run for this annotation

Codecov / codecov/patch

rocketpy/mathutils/function.py#L2317

Added line #L2317 was not covered by tests

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
----------
Expand All @@ -2290,7 +2329,7 @@
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

Expand Down
1 change: 1 addition & 0 deletions rocketpy/simulation/monte_carlo.py
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,7 @@ def __run_single_simulation(self):
heading=self.flight._randomize_heading(),
initial_solution=self.flight.initial_solution,
terminate_on_apogee=self.flight.terminate_on_apogee,
time_overshoot=self.flight.time_overshoot,
)

def __evaluate_flight_inputs(self, sim_idx):
Expand Down
1 change: 1 addition & 0 deletions rocketpy/stochastic/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"""

from .stochastic_aero_surfaces import (
StochasticAirBrakes,
StochasticEllipticalFins,
StochasticNoseCone,
StochasticRailButtons,
Expand Down
112 changes: 112 additions & 0 deletions rocketpy/stochastic/stochastic_aero_surfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
RailButtons,
Tail,
TrapezoidalFins,
AirBrakes,
)

from .stochastic_model import StochasticModel
Expand Down Expand Up @@ -432,3 +433,114 @@
"""
generated_dict = next(self.dict_generator())
return RailButtons(**generated_dict)


class StochasticAirBrakes(StochasticModel):
"""A Stochastic Air Brakes class that inherits from StochasticModel.

See Also
--------
:ref:`stochastic_model` and
:class:`AirBrakes <rocketpy.AirBrakes>`

Attributes
----------
object : AirBrakes
AirBrakes object to be used for validation.
drag_coefficient_curve : list, str
The drag coefficient curve of the air brakes can account for
either the air brakes' drag alone or the combined drag of both
the rocket and the air brakes.
drag_coefficient_curve_factor : tuple, list, int, float
The drag curve factor of the air brakes. This value scales the
drag coefficient curve to introduce stochastic variability.
reference_area : tuple, list, int, float
Reference area used to non-dimensionalize the drag coefficients.
clamp : bool
If True, the simulation will clamp the deployment level to 0 or 1 if
the deployment level is out of bounds. If False, the simulation will
not clamp the deployment level and will instead raise a warning if
the deployment level is out of bounds.
override_rocket_drag : bool
If False, the air brakes drag coefficient will be added to the
rocket's power off drag coefficient curve. If True, during the
simulation, the rocket's power off drag will be ignored and the air
brakes drag coefficient will be used for the entire rocket instead.
deployment_level : tuple, list, int, float
Initial deployment level, ranging from 0 to 1.
name : list[str]
List with the air brakes object name. This attribute can't be randomized.
"""

def __init__(
self,
air_brakes,
drag_coefficient_curve=None,
drag_coefficient_curve_factor=(1, 0),
reference_area=None,
clamp=None,
override_rocket_drag=None,
deployment_level=(0, 0),
):
"""Initializes the Stochastic AirBrakes class.

See Also
--------
:ref:`stochastic_model`

Parameters
----------
air_brakes : AirBrakes
AirBrakes object to be used for validation.
drag_coefficient_curve : list, str, optional
The drag coefficient curve of the air brakes can account for
either the air brakes' drag alone or the combined drag of both
the rocket and the air brakes.
drag_coefficient_curve_factor : tuple, list, int, float, optional
The drag curve factor of the air brakes. This value scales the
drag coefficient curve to introduce stochastic variability.
reference_area : tuple, list, int, float, optional
Reference area used to non-dimensionalize the drag coefficients.
clamp : bool, optional
If True, the simulation will clamp the deployment level to 0 or 1 if
the deployment level is out of bounds. If False, the simulation will
not clamp the deployment level and will instead raise a warning if
the deployment level is out of bounds.
override_rocket_drag : bool, optional
If False, the air brakes drag coefficient will be added to the
rocket's power off drag coefficient curve. If True, during the
simulation, the rocket's power off drag will be ignored and the air
brakes drag coefficient will be used for the entire rocket instead.
deployment_level : tuple, list, int, float, optional
Initial deployment level, ranging from 0 to 1.
"""
super().__init__(

Check warning on line 517 in rocketpy/stochastic/stochastic_aero_surfaces.py

View check run for this annotation

Codecov / codecov/patch

rocketpy/stochastic/stochastic_aero_surfaces.py#L517

Added line #L517 was not covered by tests
air_brakes,
drag_coefficient_curve=drag_coefficient_curve,
drag_coefficient_curve_factor=drag_coefficient_curve_factor,
reference_area=reference_area,
clamp=clamp,
override_rocket_drag=override_rocket_drag,
deployment_level=deployment_level,
name=None,
)

def create_object(self):
"""Creates and returns an AirBrakes object from the randomly generated
input arguments.

Returns
-------
air_brake : AirBrakes
AirBrakes object with the randomly generated input arguments.
"""
generated_dict = next(self.dict_generator())
air_brakes = AirBrakes(

Check warning on line 538 in rocketpy/stochastic/stochastic_aero_surfaces.py

View check run for this annotation

Codecov / codecov/patch

rocketpy/stochastic/stochastic_aero_surfaces.py#L537-L538

Added lines #L537 - L538 were not covered by tests
drag_coefficient_curve=generated_dict["drag_coefficient_curve"],
reference_area=generated_dict["reference_area"],
clamp=generated_dict["clamp"],
override_rocket_drag=generated_dict["override_rocket_drag"],
deployment_level=generated_dict["deployment_level"],
)
air_brakes.drag_coefficient *= generated_dict["drag_coefficient_curve_factor"]
return air_brakes

Check warning on line 546 in rocketpy/stochastic/stochastic_aero_surfaces.py

View check run for this annotation

Codecov / codecov/patch

rocketpy/stochastic/stochastic_aero_surfaces.py#L545-L546

Added lines #L545 - L546 were not covered by tests
12 changes: 12 additions & 0 deletions rocketpy/stochastic/stochastic_flight.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@
terminate_on_apogee : bool
Whether or not the flight should terminate on apogee. This attribute
can not be randomized.
time_overshoot : bool
If False, the simulation will run at the time step defined by the controller
sampling rate. Be aware that this will make the simulation run much slower.
"""

def __init__(
Expand All @@ -39,6 +42,7 @@
heading=None,
initial_solution=None,
terminate_on_apogee=None,
time_overshoot=None,
):
"""Initializes the Stochastic Flight class.

Expand All @@ -63,11 +67,17 @@
terminate_on_apogee : bool, optional
Whether or not the flight should terminate on apogee. This attribute
can not be randomized.
time_overshoot : bool
If False, the simulation will run at the time step defined by the controller
sampling rate. Be aware that this will make the simulation run much slower.
"""
if terminate_on_apogee is not None:
assert isinstance(terminate_on_apogee, bool), (
"`terminate_on_apogee` must be a boolean"
)
if time_overshoot is not None:
if not isinstance(time_overshoot, bool):
raise TypeError("`time_overshoot` must be a boolean")

Check warning on line 80 in rocketpy/stochastic/stochastic_flight.py

View check run for this annotation

Codecov / codecov/patch

rocketpy/stochastic/stochastic_flight.py#L79-L80

Added lines #L79 - L80 were not covered by tests
super().__init__(
flight,
rail_length=rail_length,
Expand All @@ -77,6 +87,7 @@

self.initial_solution = initial_solution
self.terminate_on_apogee = terminate_on_apogee
self.time_overshoot = time_overshoot

def _validate_initial_solution(self, initial_solution):
if initial_solution is not None:
Expand Down Expand Up @@ -128,4 +139,5 @@
heading=generated_dict["heading"],
initial_solution=self.initial_solution,
terminate_on_apogee=self.terminate_on_apogee,
time_overshoot=self.time_overshoot,
)
Loading