Skip to content

Commit 8aa1016

Browse files
committed
ENH: restructuring rocket class
-ENH: removed 'BaseRocket' class now 'PointMassRocket' inherits directly from 'Rocket' class
1 parent b18b241 commit 8aa1016

3 files changed

Lines changed: 118 additions & 84 deletions

File tree

rocketpy/__init__.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@
3737
Parachute,
3838
RailButtons,
3939
Rocket,
40-
BaseRocket,
4140
PointMassRocket,
4241
Tail,
4342
TrapezoidalFins,

rocketpy/rocket/__init__.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,4 @@
1515
from rocketpy.rocket.components import Components
1616
from rocketpy.rocket.parachute import Parachute
1717
from rocketpy.rocket.rocket import Rocket
18-
from rocketpy.rocket.rocket import BaseRocket
1918
from rocketpy.rocket.rocket import PointMassRocket

rocketpy/rocket/rocket.py

Lines changed: 118 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -23,89 +23,9 @@
2323
from rocketpy.rocket.components import Components
2424
from rocketpy.rocket.parachute import Parachute
2525
from rocketpy.tools import parallel_axis_theorem_from_com
26+
from functools import cached_property
27+
from rocketpy.mathutils.function import funcify_method
2628

27-
class BaseRocket:
28-
"""Base class for a rocket model with minimal attributes and methods."""
29-
def __init__(self, mass):
30-
self.mass = mass
31-
self.motor = None
32-
def add_motor(self, motor):
33-
self.motor = motor
34-
self.evaluate_total_mass()
35-
def evaluate_total_mass(self):
36-
if self.motor:
37-
return self.mass + self.motor.total_mass
38-
return self.mass
39-
40-
41-
class PointMassRocket(BaseRocket):
42-
"""Rocket modeled as a point mass for 3-DOF simulations."""
43-
44-
def __init__(self, mass, drag_coefficient=0.4, radius=0.05):
45-
super().__init__(mass)
46-
47-
# Basic configuration
48-
self.drag_coefficient = drag_coefficient
49-
self.radius = radius # in meters
50-
self.area = math.pi * self.radius**2
51-
52-
# Coordinate system configuration
53-
self.coordinate_system_orientation = "tail_to_nose"
54-
self.center_of_dry_mass_position = 0 # arbitrary for point mass
55-
self.dry_mass = mass # dry_mass = structure + dry motor, here it's same as base mass
56-
self.nozzle_position = 0 # or another reference point like -1 * length/2
57-
58-
# Components
59-
self.parachutes = []
60-
self._controllers = []
61-
self.air_brakes = []
62-
self.sensors = Components()
63-
self.aerodynamic_surfaces = Components()
64-
self.rail_buttons = Components()
65-
self.surfaces_cp_to_cdm = {}
66-
67-
# Drag models
68-
self.power_on_drag = Function(
69-
drag_coefficient,
70-
"Mach Number",
71-
"Power-On Drag Coefficient",
72-
interpolation="constant"
73-
)
74-
self.power_off_drag = Function(
75-
drag_coefficient * 1.2,
76-
"Mach Number",
77-
"Power-Off Drag Coefficient",
78-
interpolation="constant"
79-
)
80-
def add_parachute(
81-
self, name, cd_s, trigger, sampling_rate=100, lag=0, noise=(0, 0, 0)
82-
):
83-
parachute = Parachute(name, cd_s, trigger, sampling_rate, lag, noise)
84-
self.parachutes.append(parachute)
85-
self.total_mass = None
86-
self.evaluate_total_mass()
87-
return self.parachutes[-1]
88-
89-
def evaluate_total_mass(self):
90-
"""Returns Function of total mass (dry + motor)."""
91-
if self.motor is None:
92-
print("Please associate this rocket with a motor!")
93-
return False
94-
95-
motor_mass_func = (
96-
self.motor.total_mass if hasattr(self.motor.total_mass, "get_value_opt")
97-
else Function(lambda t: self.motor.total_mass)
98-
)
99-
100-
self.total_mass = Function(
101-
lambda t: self.mass + motor_mass_func(t),
102-
inputs="Time (s)",
103-
outputs="Total Mass (Rocket + Motor + Propellant) (kg)",
104-
title="Total Mass (Rocket + Motor + Propellant)"
105-
)
106-
return self.total_mass
107-
108-
10929
# pylint: disable=too-many-instance-attributes, too-many-public-methods, too-many-instance-attributes
11030
class Rocket:
11131
"""Keeps rocket information.
@@ -2085,3 +2005,119 @@ def from_dict(cls, data):
20852005
)
20862006

20872007
return rocket
2008+
2009+
class PointMassRocket(Rocket):
2010+
"""Rocket modeled as a point mass for 3-DOF simulations."""
2011+
2012+
def __init__(self, mass, radius=0.05):
2013+
self,
2014+
radius: float = 0,
2015+
mass: float = 0,
2016+
center_of_mass: float = 0,
2017+
power_off_drag = 0,
2018+
power_on_drag = 0,
2019+
super().__init__(
2020+
radius=radius,
2021+
mass=mass,
2022+
inertia=(0, 0, 0),
2023+
center_of_mass_without_motor=center_of_mass,
2024+
power_off_drag=power_off_drag,
2025+
power_on_drag=power_on_drag,
2026+
)
2027+
@cached_property
2028+
@funcify_method("Time (s)", "I_xx (kg·m²)")
2029+
def I_11(self) -> Function:
2030+
"""Returns the moment of inertia around the x-axis for a point mass (always 0)."""
2031+
return Function(0)
2032+
2033+
@cached_property
2034+
@funcify_method("Time (s)", "I_22 (kg·m²)")
2035+
def I_22(self) -> Function:
2036+
"""Returns the moment of inertia around the y-axis for a point mass (always 0)."""
2037+
return Function(0)
2038+
2039+
@cached_property
2040+
@funcify_method("Time (s)", "I_33 (kg·m²)")
2041+
def I_33(self) -> Function:
2042+
"""Returns the moment of inertia around the z-axis for a point mass (always 0)."""
2043+
return Function(0)
2044+
2045+
@cached_property
2046+
@funcify_method("Time (s)", "I_12 (kg·m²)")
2047+
def I_12(self) -> Function:
2048+
"""Returns the product of inertia I_xy for a point mass (always 0)."""
2049+
return Function(0)
2050+
2051+
@cached_property
2052+
@funcify_method("Time (s)", "I_13 (kg·m²)")
2053+
def I_13(self) -> Function:
2054+
"""Returns the product of inertia I_xz for a point mass (always 0)."""
2055+
return Function(0)
2056+
2057+
@cached_property
2058+
@funcify_method("Time (s)", "I_23 (kg·m²)")
2059+
def I_23(self) -> Function:
2060+
"""Returns the product of inertia I_yz for a point mass (always 0)."""
2061+
return Function(0)
2062+
2063+
@property
2064+
def dry_I_11(self) -> float:
2065+
"""Returns the dry moment of inertia around the x-axis for a point mass (always 0)."""
2066+
return 0.0
2067+
2068+
@property
2069+
def dry_I_22(self) -> float:
2070+
"""Returns the dry moment of inertia around the y-axis for a point mass (always 0)."""
2071+
return 0.0
2072+
2073+
@property
2074+
def dry_I_33(self) -> float:
2075+
"""Returns the dry moment of inertia around the z-axis for a point mass (always 0)."""
2076+
return 0.0
2077+
2078+
@property
2079+
def dry_I_12(self) -> float:
2080+
"""Returns the dry product of inertia I_xy for a point mass (always 0)."""
2081+
return 0.0
2082+
2083+
@property
2084+
def dry_I_13(self) -> float:
2085+
"""Returns the dry product of inertia I_xz for a point mass (always 0)."""
2086+
return 0.0
2087+
2088+
@property
2089+
def dry_I_23(self) -> float:
2090+
"""Returns the dry product of inertia I_yz for a point mass (always 0)."""
2091+
return 0.0
2092+
2093+
def evaluate_inertias(self):
2094+
"""Calculates and returns the rocket's inertias. For a PointMassRocket, these are always zero."""
2095+
self.I_11 = self.I_22 = self.I_33 = Function(0)
2096+
self.I_12 = self.I_13 = self.I_23 = Function(0)
2097+
return (0, 0, 0, 0, 0, 0)
2098+
2099+
def evaluate_dry_inertias(self):
2100+
"""Calculates and returns the rocket's dry inertias. For a PointMassRocket, these are always zero."""
2101+
self.dry_I_11 = self.dry_I_22 = self.dry_I_33 = 0.0
2102+
self.dry_I_12 = self.dry_I_13 = self.dry_I_23 = 0.0
2103+
return (0, 0, 0, 0, 0, 0)
2104+
2105+
@property
2106+
def center_of_mass(self) -> Function:
2107+
"""Returns the center of mass for a PointMassRocket.
2108+
If a motor is attached, this will be the motor's center of mass.
2109+
Otherwise, it will be the `center_of_mass_without_motor`.
2110+
"""
2111+
if self.motor and not isinstance(self.motor, EmptyMotor):
2112+
return self.motor_center_of_mass_position
2113+
return Function(self.center_of_mass_without_motor)
2114+
2115+
@property
2116+
def center_of_dry_mass_position(self) -> float:
2117+
"""Returns the center of dry mass position for a PointMassRocket.
2118+
If a motor is attached, this will be the motor's center of dry mass position.
2119+
Otherwise, it will be the `center_of_mass_without_motor`.
2120+
"""
2121+
if self.motor and not isinstance(self.motor, EmptyMotor):
2122+
return self.motor_center_of_dry_mass_position
2123+
return self.center_of_mass_without_motor

0 commit comments

Comments
 (0)