Skip to content

Commit c8096c5

Browse files
committed
MNT: Point mass motor and rocket fixes
- MNT: pointmassmotor fixing the various properties. - MNT: fixing super init and init inheritance by changing order in pointmassrocket - MNT: pointmassrocket property setter and default value fixes
1 parent d4dc989 commit c8096c5

2 files changed

Lines changed: 98 additions & 288 deletions

File tree

rocketpy/motors/pointmassmotor.py

Lines changed: 32 additions & 207 deletions
Original file line numberDiff line numberDiff line change
@@ -1,74 +1,22 @@
11
from functools import cached_property
2-
32
import numpy as np
4-
5-
from typing import Callable
6-
3+
from typing import Callable
74
from rocketpy.mathutils.function import Function, funcify_method
8-
from .motor import Motor
5+
from .motor import Motor
96

10-
class PointMassMotor(Motor):
11-
"""Class representing a motor modeled as a point mass.
12-
13-
Inherits from the Motor class and simplifies the model to a thrust-producing
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-
"""
7+
class PointMassMotor(Motor):
8+
"""Motor modeled as a point mass for 3-DOF simulations."""
199

2010
def __init__(
2111
self,
2212
thrust_source,
2313
dry_mass,
2414
propellant_initial_mass,
25-
burn_time = None,
26-
propellant_final_mass = None,
27-
reshape_thrust_curve = False,
28-
interpolation_method = "linear",
15+
burn_time=None,
16+
propellant_final_mass=None,
17+
reshape_thrust_curve=False,
18+
interpolation_method="linear",
2919
):
30-
"""Initialize the PointMassMotor class.
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-
38-
Parameters
39-
----------
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.
44-
dry_mass : float
45-
Total dry mass of the motor in kg.
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.
54-
propellant_final_mass : float, optional
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`.
71-
"""
7220
if isinstance(thrust_source, (int, float, Callable)):
7321
if propellant_initial_mass is None:
7422
raise ValueError(
@@ -79,14 +27,13 @@ def __init__(
7927
"For constant or callable thrust, either 'burn_time' or "
8028
"'propellant_final_mass' must be provided."
8129
)
82-
8330
elif isinstance(thrust_source, (Function, np.ndarray, str)):
8431
if propellant_initial_mass is None:
8532
raise ValueError(
8633
"For thrust from a Function, NumPy array, or CSV, 'propellant_initial_mass' is required."
8734
)
8835
else:
89-
raise TypeError(
36+
raise TypeError(
9037
"Invalid 'thrust_source' type. Must be int, float, callable, str, numpy.ndarray, or Function."
9138
)
9239

@@ -95,172 +42,50 @@ def __init__(
9542

9643
super().__init__(
9744
thrust_source=thrust_source,
98-
dry_inertia=(0, 0, 0), # Inertia is zero for a point mass
99-
nozzle_radius=0, # Nozzle radius is irrelevant for a point mass model
100-
center_of_dry_mass_position=0, # Pass 0 directly to the superclass
45+
dry_inertia=(0, 0, 0),
46+
nozzle_radius=0,
47+
center_of_dry_mass_position=0,
10148
dry_mass=dry_mass,
102-
nozzle_position=0, # Nozzle is at the motor's origin
49+
nozzle_position=0,
10350
burn_time=burn_time,
104-
reshape_thrust_curve=reshape_thrust_curve,
51+
reshape_thrust_curve=reshape_thrust_curve,
10552
interpolation_method=interpolation_method,
106-
coordinate_system_orientation="nozzle_to_combustion_chamber", # Standard orientation
53+
coordinate_system_orientation="nozzle_to_combustion_chamber",
10754
)
10855

109-
# Removed the thrust method. It will now be inherited directly from the Motor base class,
110-
# which already correctly handles the conversion of thrust_source to a Function
111-
# and exposes it as a cached property.
112-
113-
# Removed the total_mass override. The base Motor class's total_mass property
114-
# will now correctly calculate dry_mass + propellant_mass(t), which is the desired
115-
# varying mass behavior for the point mass motor.
116-
117-
# Removed the center_of_dry_mass_position override. It is now passed directly
118-
# to the super().__init__ as 0.
11956
@property
12057
def propellant_initial_mass(self):
121-
"""Returns the initial propellant mass for a point mass motor.
122-
123-
This property retrieves the value set during initialization. This implementation
124-
is required as 'propellant_initial_mass' is an abstract method in the parent Motor class.
125-
126-
Returns
127-
-------
128-
float
129-
Propellant initial mass in kg.
130-
"""
13158
return self._propellant_initial_mass
132-
59+
13360
@funcify_method("Time (s)", "Exhaust velocity (m/s)")
13461
def exhaust_velocity(self):
135-
"""Exhaust velocity by assuming it as a constant. The formula used is
136-
total impulse/propellant initial mass.
137-
138-
Returns
139-
-------
140-
self.exhaust_velocity : Function
141-
Gas exhaust velocity of the motor.
62+
"""Assume constant exhaust velocity: total impulse / propellant mass"""
63+
v_e = self.total_impulse / self.propellant_initial_mass
64+
return Function(v_e).set_discrete_based_on_model(self.thrust)
14265

143-
Notes
144-
-----
145-
This corresponds to the actual exhaust velocity only when the nozzle
146-
exit pressure equals the atmospheric pressure.
147-
"""
148-
return Function(
149-
self.total_impulse / self.propellant_initial_mass
150-
).set_discrete_based_on_model(self.thrust)
151-
15266
@cached_property
153-
@funcify_method("Time (s)", "Mass flow rate (kg/s)", extrapolation="zero")
15467
def total_mass_flow_rate(self) -> Function:
155-
"""Time derivative of the propellant mass as a function of time.
156-
157-
It calculates mass flow rate as the negative of thrust divided by exhaust velocity,
158-
consistent with the fundamental rocket equation.
159-
160-
Returns
161-
-------
162-
Function
163-
Time derivative of total propellant mass a function of time.
164-
"""
165-
166-
exhaust_vel_func = self.exhaust_velocity
167-
return -self.thrust / exhaust_vel_func
68+
"""Mass flow rate: -thrust / exhaust_velocity"""
69+
return -self.thrust / self.exhaust_velocity
16870

16971
@cached_property
170-
@funcify_method("Time (s)", "Propellant Mass (kg)")
17172
def center_of_propellant_mass(self):
172-
"""Returns the position of the center of mass of the propellant.
173-
174-
For a point mass motor, the propellant's center of mass is considered
175-
to be at the origin (0) of the motor's coordinate system.
73+
"""Center of propellant mass is always zero"""
74+
return Function(0.0)
17675

177-
Returns
178-
-------
179-
Function
180-
A Function object representing the center of propellant mass (always 0).
181-
"""
182-
return 0
76+
# Propellant inertias: always zero, but return as Function objects
77+
def _zero_inertia_func(self):
78+
return Function(0.0)
18379

18480
@cached_property
185-
@funcify_method("Time (s)", "Inertia (kg·m²)")
186-
def propellant_I_11(self):
187-
"""Returns the propellant moment of inertia around the x-axis.
188-
189-
For a point mass motor, this is always zero.
190-
191-
Returns
192-
-------
193-
Function
194-
A Function object representing zero propellant inertia.
195-
"""
196-
return 0
197-
81+
def propellant_I_11(self): return self._zero_inertia_func()
19882
@cached_property
199-
@funcify_method("Time (s)", "Inertia (kg·m²)")
200-
def propellant_I_12(self):
201-
"""Returns the propellant product of inertia I_xy.
202-
203-
For a point mass motor, this is always zero.
204-
205-
Returns
206-
-------
207-
Function
208-
A Function object representing zero propellant inertia.
209-
"""
210-
return 0
211-
83+
def propellant_I_12(self): return self._zero_inertia_func()
21284
@cached_property
213-
@funcify_method("Time (s)", "Inertia (kg·m²)")
214-
def propellant_I_13(self):
215-
"""Returns the propellant product of inertia I_xz.
216-
217-
For a point mass motor, this is always zero.
218-
219-
Returns
220-
-------
221-
Function
222-
A Function object representing zero propellant inertia.
223-
"""
224-
return 0
225-
85+
def propellant_I_13(self): return self._zero_inertia_func()
22686
@cached_property
227-
@funcify_method("Time (s)", "Inertia (kg·m²)")
228-
def propellant_I_22(self):
229-
"""Returns the propellant moment of inertia around the y-axis.
230-
231-
For a point mass motor, this is always zero.
232-
233-
Returns
234-
-------
235-
Function
236-
A Function object representing zero propellant inertia.
237-
"""
238-
return 0
239-
87+
def propellant_I_22(self): return self._zero_inertia_func()
24088
@cached_property
241-
@funcify_method("Time (s)", "Inertia (kg·m²)")
242-
def propellant_I_23(self):
243-
"""Returns the propellant product of inertia I_yz.
244-
245-
For a point mass motor, this is always zero.
246-
247-
Returns
248-
-------
249-
Function
250-
A Function object representing zero propellant inertia.
251-
"""
252-
return 0
253-
89+
def propellant_I_23(self): return self._zero_inertia_func()
25490
@cached_property
255-
@funcify_method("Time (s)", "Inertia (kg·m²)")
256-
def propellant_I_33(self):
257-
"""Returns the propellant moment of inertia around the z-axis.
258-
259-
For a point mass motor, this is always zero.
260-
261-
Returns
262-
-------
263-
Function
264-
A Function object representing zero propellant inertia.
265-
"""
266-
return 0
91+
def propellant_I_33(self): return self._zero_inertia_func()

0 commit comments

Comments
 (0)