Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ENH: Add Eccentricity to Stochastic Simulations #792

Merged
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
28 changes: 13 additions & 15 deletions rocketpy/rocket/rocket.py
Original file line number Diff line number Diff line change
Expand Up @@ -1744,8 +1744,8 @@ def set_rail_buttons(
def add_cm_eccentricity(self, x, y):
"""Moves line of action of aerodynamic and thrust forces by
equal translation amount to simulate an eccentricity in the
position of the center of mass of the rocket relative to its
geometrical center line.
position of the center of dry mass of the rocket relative to
its geometrical center line.

Parameters
----------
Expand Down Expand Up @@ -1781,20 +1781,18 @@ def add_cm_eccentricity(self, x, y):
def add_cp_eccentricity(self, x, y):
"""Moves line of action of aerodynamic forces to simulate an
eccentricity in the position of the center of pressure relative
to the center of mass of the rocket.
to the center of dry mass of the rocket.

Parameters
----------
x : float
Distance in meters by which the CP is to be translated in
the x direction relative to the center of mass axial line.
The x axis is defined according to the body axes coordinate
system.
the x direction relative to the center of dry mass axial line.
The x axis is defined according to the body axes coordinate system.
y : float
Distance in meters by which the CP is to be translated in
the y direction relative to the center of mass axial line.
The y axis is defined according to the body axes coordinate
system.
the y direction relative to the center of dry mass axial line.
The y axis is defined according to the body axes coordinate system.

Returns
-------
Expand All @@ -1811,19 +1809,19 @@ def add_cp_eccentricity(self, x, y):

def add_thrust_eccentricity(self, x, y):
"""Moves line of action of thrust forces to simulate a
misalignment of the thrust vector and the center of mass.
misalignment of the thrust vector and the center of dry mass.

Parameters
----------
x : float
Distance in meters by which the line of action of the
thrust force is to be translated in the x direction
relative to the center of mass axial line. The x axis
relative to the center of dry mass axial line. The x axis
is defined according to the body axes coordinate system.
y : float
Distance in meters by which the line of action of the
thrust force is to be translated in the x direction
relative to the center of mass axial line. The y axis
thrust force is to be translated in the y direction
relative to the center of dry mass axial line. The y axis
is defined according to the body axes coordinate system.

Returns
Expand All @@ -1835,8 +1833,8 @@ def add_thrust_eccentricity(self, x, y):
--------
:ref:`rocket_axes`
"""
self.thrust_eccentricity_y = x
self.thrust_eccentricity_x = y
self.thrust_eccentricity_x = x
self.thrust_eccentricity_y = y
return self

def draw(self, vis_args=None, plane="xz", *, filename=None):
Expand Down
8 changes: 4 additions & 4 deletions rocketpy/simulation/flight.py
Original file line number Diff line number Diff line change
Expand Up @@ -1469,8 +1469,8 @@ def u_dot(self, t, u, post_processing=False): # pylint: disable=too-many-locals
# Thrust
thrust = self.rocket.motor.thrust.get_value_opt(t)
# Off center moment
M1 += self.rocket.thrust_eccentricity_x * thrust
M2 -= self.rocket.thrust_eccentricity_y * thrust
M1 += self.rocket.thrust_eccentricity_y * thrust
M2 -= self.rocket.thrust_eccentricity_x * thrust
else:
# Motor stopped
# Inertias
Expand Down Expand Up @@ -1856,11 +1856,11 @@ def u_dot_generalized(self, t, u, post_processing=False): # pylint: disable=too
thrust = self.rocket.motor.thrust.get_value_opt(t)
M1 += (
self.rocket.cp_eccentricity_y * R3
+ self.rocket.thrust_eccentricity_x * thrust
+ self.rocket.thrust_eccentricity_y * thrust
)
M2 -= (
self.rocket.cp_eccentricity_x * R3
- self.rocket.thrust_eccentricity_y * thrust
+ self.rocket.thrust_eccentricity_x * thrust
)
M3 += self.rocket.cp_eccentricity_x * R2 - self.rocket.cp_eccentricity_y * R1

Expand Down
123 changes: 123 additions & 0 deletions rocketpy/stochastic/stochastic_rocket.py
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,105 @@ def set_rail_buttons(
rail_buttons, self._validate_position(rail_buttons, lower_button_position)
)

def add_cp_eccentricity(self, x=None, y=None):
"""Moves line of action of aerodynamic forces to simulate an
eccentricity in the position of the center of pressure relative
to the center of dry mass of the rocket.

Parameters
----------
x : tuple, list, int, float, optional
Distance in meters by which the CP is to be translated in
the x direction relative to the center of dry mass axial line.
The x axis is defined according to the body axes coordinate system.
y : tuple, list, int, float, optional
Distance in meters by which the CP is to be translated in
the y direction relative to the center of dry mass axial line.
The y axis is defined according to the body axes coordinate system.

Returns
-------
self : StochasticRocket
Object of the StochasticRocket class.
"""
self.cp_eccentricity_x = self._validate_eccentricity("cp_eccentricity_x", x)
self.cp_eccentricity_y = self._validate_eccentricity("cp_eccentricity_y", y)
return self

def add_thrust_eccentricity(self, x=None, y=None):
"""Moves line of action of thrust forces to simulate a
misalignment of the thrust vector and the center of dry mass.

Parameters
----------
x : tuple, list, int, float, optional
Distance in meters by which the line of action of the
thrust force is to be translated in the x direction
relative to the center of dry mass axial line. The x axis
is defined according to the body axes coordinate system.
y : tuple, list, int, float, optional
Distance in meters by which the line of action of the
thrust force is to be translated in the y direction
relative to the center of dry mass axial line. The y axis
is defined according to the body axes coordinate system.

Returns
-------
self : StochasticRocket
Object of the StochasticRocket class.
"""
self.thrust_eccentricity_x = self._validate_eccentricity(
"thrust_eccentricity_x", x
)
self.thrust_eccentricity_y = self._validate_eccentricity(
"thrust_eccentricity_y", y
)
return self

def _validate_eccentricity(self, eccentricity, position):
"""Validate the eccentricity argument.

Parameters
----------
eccentricity : str
The eccentricity to which the position argument refers to.
position : tuple, list, int, float
The position argument to be validated.

Returns
-------
tuple or list
Validated position argument.

Raises
------
ValueError
If the position argument does not conform to the specified formats.
"""
if isinstance(position, tuple):
return self._validate_tuple(
eccentricity,
position,
)
elif isinstance(position, (int, float)):
return self._validate_scalar(
eccentricity,
position,
)
elif isinstance(position, list):
return self._validate_list(
eccentricity,
position,
)
elif position is None:
position = []
return self._validate_list(
eccentricity,
position,
)
else:
raise AssertionError("`position` must be a tuple, list, int, or float")

def _validate_position(self, validated_object, position):
"""Validate the position argument.

Expand Down Expand Up @@ -578,6 +677,13 @@ def _create_parachute(self, stochastic_parachute):
self.last_rnd_dict["parachutes"].append(stochastic_parachute.last_rnd_dict)
return parachute

def _create_eccentricities(self, stochastic_x, stochastic_y, eccentricity):
x_rnd = self._randomize_position(stochastic_x)
self.last_rnd_dict[eccentricity + "_x"] = x_rnd
y_rnd = self._randomize_position(stochastic_y)
self.last_rnd_dict[eccentricity + "_y"] = y_rnd
return x_rnd, y_rnd

def create_object(self):
"""Creates and returns a Rocket object from the randomly generated input
arguments.
Expand Down Expand Up @@ -609,6 +715,23 @@ def create_object(self):
rocket.power_off_drag *= generated_dict["power_off_drag_factor"]
rocket.power_on_drag *= generated_dict["power_on_drag_factor"]

if hasattr(self, "cp_eccentricity_x") and hasattr(self, "cp_eccentricity_y"):
cp_ecc_x, cp_ecc_y = self._create_eccentricities(
self.cp_eccentricity_x,
self.cp_eccentricity_y,
"cp_eccentricity",
)
rocket.add_cp_eccentricity(cp_ecc_x, cp_ecc_y)
if hasattr(self, "thrust_eccentricity_x") and hasattr(
self, "thrust_eccentricity_y"
):
thrust_ecc_x, thrust_ecc_y = self._create_eccentricities(
self.thrust_eccentricity_x,
self.thrust_eccentricity_y,
"thrust_eccentricity",
)
rocket.add_thrust_eccentricity(thrust_ecc_x, thrust_ecc_y)

for component_motor in self.motors:
motor, position_rnd = self._create_motor(component_motor)
rocket.add_motor(motor, position_rnd)
Expand Down
8 changes: 4 additions & 4 deletions tests/unit/test_rocket.py
Original file line number Diff line number Diff line change
Expand Up @@ -331,15 +331,15 @@ def test_add_cm_eccentricity_assert_properties_set(calisto):
assert calisto.cp_eccentricity_x == -4
assert calisto.cp_eccentricity_y == -5

assert calisto.thrust_eccentricity_y == -4
assert calisto.thrust_eccentricity_x == -5
assert calisto.thrust_eccentricity_x == -4
assert calisto.thrust_eccentricity_y == -5


def test_add_thrust_eccentricity_assert_properties_set(calisto):
calisto.add_thrust_eccentricity(x=4, y=5)

assert calisto.thrust_eccentricity_y == 4
assert calisto.thrust_eccentricity_x == 5
assert calisto.thrust_eccentricity_x == 4
assert calisto.thrust_eccentricity_y == 5


def test_add_cp_eccentricity_assert_properties_set(calisto):
Expand Down