Skip to content

Commit b18b241

Browse files
committed
MNT: point mass motor cleanup
-MNT: removing the parameters not needed for point mass kind of motors -MNT: removing extra parameter thrust_curve -MNT: fixing problems with motor class inheritance
1 parent fe21271 commit b18b241

1 file changed

Lines changed: 178 additions & 77 deletions

File tree

rocketpy/motors/PointMassMotor.py

Lines changed: 178 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,121 +1,222 @@
11
from functools import cached_property
22
import numpy as np
3-
from ..mathutils.function import Function, funcify_method
4-
from .motor import Motor
3+
import csv
4+
import math
5+
from typing import Callable # Import Callable from the typing module
56

6-
class PointMassMotor(Motor):
7+
from rocketpy.mathutils.function import Function, funcify_method
8+
from .motor import Motor
9+
10+
class PointMassMotor(Motor):
711
"""Class representing a motor modeled as a point mass.
12+
813
Inherits from the Motor class and simplifies the model to a thrust-producing
9-
object without detailed structural components."""
14+
object without detailed structural components. The total mass of the motor
15+
will vary with propellant consumption, similar to a standard motor. However,
16+
its inertia components and the center of propellant mass are considered zero
17+
and fixed at the motor's reference point, respectively.
18+
"""
1019

1120
def __init__(
1221
self,
1322
thrust_source,
14-
dry_mass,
15-
thrust_curve=None,
16-
propellant_initial_mass=None,
17-
propellant_final_mass=None,
18-
burn_time=None,
19-
center_of_dry_mass_position=0,
20-
reshape_thrust_curve=False,
21-
interpolation_method="linear",
22-
coordinate_system_orientation="nozzle_to_combustion_chamber",
23+
dry_mass: float,
24+
propellant_initial_mass: float, # Now explicitly required
25+
burn_time: float = None,
26+
propellant_final_mass: float = None,
27+
reshape_thrust_curve: bool = False,
28+
interpolation_method: str = "linear",
2329
):
2430
"""Initialize the PointMassMotor class.
25-
31+
32+
This motor simplifies the physical model by considering its mass to be
33+
concentrated at a single point, effectively setting all its inertia
34+
components to zero. Propellant mass variation and exhaust velocity
35+
are still simulated and derived from the thrust and propellant consumption
36+
characteristics, similar to the base Motor class.
37+
2638
Parameters
2739
----------
28-
thrust_source : int, float, callable, string, array, Function
29-
Thrust source similar to the Motor class.
40+
thrust_source : int, float, callable, str, numpy.ndarray, Function
41+
Thrust source. Can be a constant value (int, float), a callable
42+
function of time, a path to a CSV file, a NumPy array, or a
43+
RocketPy `Function` object.
3044
dry_mass : float
3145
Total dry mass of the motor in kg.
32-
thrust_curve : Function, np.array, or str (csv file), optional
33-
Required if thrust_source is a csv file, Function, or np.array.
34-
propellant_initial_mass : float, optional
35-
Required if thrust_source is a csv file, Function, or np.array.
46+
propellant_initial_mass : float
47+
Initial mass of the propellant in kg. This is a required parameter
48+
as the point mass motor will still simulate propellant consumption.
49+
burn_time : float, optional
50+
Total burn time of the motor in seconds. Required if `thrust_source`
51+
is a constant value or a callable function, and `propellant_final_mass`
52+
is not provided. If `thrust_source` is a CSV, array, or Function,
53+
the burn time is derived from it.
3654
propellant_final_mass : float, optional
37-
Required if thrust_source is callable.
38-
burn_time : float or tuple of float, optional
39-
Required if thrust_source is callable or if a thrust value is given.
40-
center_of_dry_mass_position : float, optional
41-
Initial position of the motor, default is 0.
42-
interpolation_method : string, optional
43-
Interpolation method for thrust curve, default is 'linear'.
55+
Final mass of the propellant in kg. Required if `thrust_source`
56+
is a callable function and `burn_time` is not provided. If not
57+
provided, it is calculated by the base Motor class.
58+
reshape_thrust_curve : bool, optional
59+
Whether to reshape the thrust curve to start at t=0 and end at
60+
burn_time. Defaults to False.
61+
interpolation_method : str, optional
62+
Interpolation method for the thrust curve, if applicable.
63+
Defaults to 'linear'.
64+
65+
Raises
66+
------
67+
ValueError
68+
If insufficient data is provided for mass flow rate calculation.
69+
TypeError
70+
If an invalid type is provided for `thrust_source`.
4471
"""
45-
if isinstance(thrust_source, (Function, np.ndarray, str)):
46-
if thrust_curve is None or propellant_initial_mass is None:
47-
raise ValueError("thrust_curve and propellant_initial_mass are required for csv, Function, or np.array inputs.")
48-
elif callable(thrust_source):
49-
if any(param is None for param in [thrust_curve, propellant_initial_mass, burn_time, propellant_final_mass]):
50-
raise ValueError("thrust_curve, propellant_initial_mass, burn_time, and propellant_final_mass are required for callable inputs.")
51-
elif isinstance(thrust_source, (int, float)):
52-
if any(param is None for param in [thrust_curve, propellant_initial_mass, burn_time]):
53-
raise ValueError("thrust_curve, propellant_initial_mass, and burn_time are required when a thrust value is given.")
72+
# Input validation: Ensure critical parameters for mass flow are present
73+
if isinstance(thrust_source, (int, float, Callable)):
74+
if propellant_initial_mass is None:
75+
raise ValueError(
76+
"For constant or callable thrust, 'propellant_initial_mass' is required."
77+
)
78+
if burn_time is None and propellant_final_mass is None:
79+
raise ValueError(
80+
"For constant or callable thrust, either 'burn_time' or "
81+
"'propellant_final_mass' must be provided."
82+
)
5483

55-
self._propellant_initial_mass = propellant_initial_mass
84+
elif isinstance(thrust_source, (Function, np.ndarray, str)):
85+
if propellant_initial_mass is None:
86+
raise ValueError(
87+
"For thrust from a Function, NumPy array, or CSV, 'propellant_initial_mass' is required."
88+
)
89+
else:
90+
raise TypeError(
91+
"Invalid 'thrust_source' type. Must be int, float, callable, str, numpy.ndarray, or Function."
92+
)
93+
94+
self.propellant_initial_mass = propellant_initial_mass
95+
self.propellant_final_mass = propellant_final_mass
96+
97+
# Call the superclass constructor, passing center_of_dry_mass_position=0
5698
super().__init__(
5799
thrust_source=thrust_source,
58-
dry_inertia=(0, 0, 0),
59-
nozzle_radius=0,
60-
center_of_dry_mass_position=center_of_dry_mass_position,
100+
dry_inertia=(0, 0, 0), # Inertia is zero for a point mass
101+
nozzle_radius=0, # Nozzle radius is irrelevant for a point mass model
102+
center_of_dry_mass_position=0, # Pass 0 directly to the superclass
61103
dry_mass=dry_mass,
62-
nozzle_position=0,
104+
nozzle_position=0, # Nozzle is at the motor's origin
63105
burn_time=burn_time,
64-
reshape_thrust_curve=reshape_thrust_curve,
106+
reshape_thrust_curve=reshape_thrust_curve, # Pass the user-provided value
65107
interpolation_method=interpolation_method,
66-
coordinate_system_orientation=coordinate_system_orientation,
67-
)
68-
@funcify_method("Time (s)", "Thrust (N)")
69-
def thrust(self):
70-
"""Returns the thrust of the motor as a function of time."""
71-
return self.thrust_source
72-
73-
@funcify_method("Time (s)", "Acceleration (m/s^2)")
74-
def total_mass(self):
75-
"""Returns the constant total mass of the point mass motor."""
76-
return self.dry_mass
77-
78-
@funcify_method("Time (s)", "Acceleration (m/s^2)")
79-
def acceleration(self):
80-
"""Computes the acceleration of the motor as thrust divided by mass."""
81-
return self.thrust() / self.total_mass
108+
coordinate_system_orientation="nozzle_to_combustion_chamber", # Standard orientation
109+
)
82110

83-
@funcify_method("Time (s)", "Propellant Mass (kg)")
84-
def center_of_propellant_mass(self):
85-
return 0
111+
# Removed the thrust method. It will now be inherited directly from the Motor base class,
112+
# which already correctly handles the conversion of thrust_source to a Function
113+
# and exposes it as a cached property.
114+
115+
# Removed the total_mass override. The base Motor class's total_mass property
116+
# will now correctly calculate dry_mass + propellant_mass(t), which is the desired
117+
# varying mass behavior for the point mass motor.
86118

87-
@funcify_method("Time (s)", "Exhaust Velocity (m/s)")
88-
def exhaust_velocity(self):
89-
return 2000 # m/s, estimated value
119+
# Removed the center_of_dry_mass_position override. It is now passed directly
120+
# to the super().__init__ as 0.
90121

122+
@cached_property
91123
@funcify_method("Time (s)", "Propellant Mass (kg)")
92-
def propellant_initial_mass(self):
93-
return self._propellant_initial_mass
124+
def center_of_propellant_mass(self) -> Function:
125+
"""Returns the position of the center of mass of the propellant.
126+
127+
For a point mass motor, the propellant's center of mass is considered
128+
to be at the origin (0) of the motor's coordinate system.
94129
95-
@property
96-
def is_point_mass(self):
97-
return True
98-
130+
Returns
131+
-------
132+
Function
133+
A Function object representing the center of propellant mass (always 0).
134+
"""
135+
return 0
136+
137+
# Removed exhaust_velocity override. It will now be inherited from the Motor base class,
138+
# which calculates it dynamically based on thrust and mass_flow_rate.
139+
140+
@cached_property
99141
@funcify_method("Time (s)", "Inertia (kg·m²)")
100-
def propellant_I_11(self):
101-
return 0
142+
def propellant_I_11(self) -> Function:
143+
"""Returns the propellant moment of inertia around the x-axis.
102144
145+
For a point mass motor, this is always zero.
146+
147+
Returns
148+
-------
149+
Function
150+
A Function object representing zero propellant inertia.
151+
"""
152+
return 0
153+
154+
@cached_property
103155
@funcify_method("Time (s)", "Inertia (kg·m²)")
104-
def propellant_I_12(self):
156+
def propellant_I_12(self) -> Function:
157+
"""Returns the propellant product of inertia I_xy.
158+
159+
For a point mass motor, this is always zero.
160+
161+
Returns
162+
-------
163+
Function
164+
A Function object representing zero propellant inertia.
165+
"""
105166
return 0
106167

168+
@cached_property
107169
@funcify_method("Time (s)", "Inertia (kg·m²)")
108-
def propellant_I_13(self):
170+
def propellant_I_13(self) -> Function:
171+
"""Returns the propellant product of inertia I_xz.
172+
173+
For a point mass motor, this is always zero.
174+
175+
Returns
176+
-------
177+
Function
178+
A Function object representing zero propellant inertia.
179+
"""
109180
return 0
110181

182+
@cached_property
111183
@funcify_method("Time (s)", "Inertia (kg·m²)")
112-
def propellant_I_22(self):
184+
def propellant_I_22(self) -> Function:
185+
"""Returns the propellant moment of inertia around the y-axis.
186+
187+
For a point mass motor, this is always zero.
188+
189+
Returns
190+
-------
191+
Function
192+
A Function object representing zero propellant inertia.
193+
"""
113194
return 0
114195

196+
@cached_property
115197
@funcify_method("Time (s)", "Inertia (kg·m²)")
116-
def propellant_I_23(self):
198+
def propellant_I_23(self) -> Function:
199+
"""Returns the propellant product of inertia I_yz.
200+
201+
For a point mass motor, this is always zero.
202+
203+
Returns
204+
-------
205+
Function
206+
A Function object representing zero propellant inertia.
207+
"""
117208
return 0
118209

210+
@cached_property
119211
@funcify_method("Time (s)", "Inertia (kg·m²)")
120-
def propellant_I_33(self):
212+
def propellant_I_33(self) -> Function:
213+
"""Returns the propellant moment of inertia around the z-axis.
214+
215+
For a point mass motor, this is always zero.
216+
217+
Returns
218+
-------
219+
Function
220+
A Function object representing zero propellant inertia.
221+
"""
121222
return 0

0 commit comments

Comments
 (0)