Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
e557e17
DRAFT: for ENH/3-dof-simulation (See #655)
aZira371 Dec 3, 2024
a768648
ENH/3-dof-simulation (See RocketPy-Team#655)
aZira371 Dec 6, 2024
9b00c57
MNT: cleaned up new functions and
aZira371 Dec 6, 2024
87e9180
Rebase: Merge branch 'develop' of https://github.com/aZira371/RocketP…
aZira371 Feb 25, 2025
4524219
ENH: Addition of point mass classes to rocketpy.rocket and rocketpy.m…
aZira371 Feb 25, 2025
57b4732
ENH: PointMassMotor and PointMassRocket working as intended after som…
aZira371 Apr 11, 2025
81ce869
MNT: Removing unnecessary files added by mistake.
aZira371 Apr 11, 2025
0673076
Merge branch 'RocketPy-Team:master' into enh/3-dof-simulation
aZira371 Apr 24, 2025
47c9f2f
MNT: Cleaned up PointMassMotor and PointMassRocket class
aZira371 May 10, 2025
f6ad658
Merge branch 'enh/3-dof-simulation' of https://github.com/aZira371/Ro…
aZira371 May 10, 2025
33cb63a
MNT: Cleaning up flight class and PointMassMotor class
aZira371 May 10, 2025
1d2d4dc
Merge branch 'enh/3-dof-simulation' into develop
aZira371 Jun 10, 2025
fe21271
Merge pull request #1 from aZira371/develop
aZira371 Jun 10, 2025
b18b241
MNT: point mass motor cleanup
aZira371 Jun 26, 2025
8aa1016
ENH: restructuring rocket class
aZira371 Jun 30, 2025
87e7dce
MNT: fixing certain calculations on point mass motor
aZira371 Jul 11, 2025
0e4d8a4
Rename PointMassMotor.py to pointmassmotor.py
aZira371 Jul 11, 2025
41e94f1
Merge branch 'develop' into enh/3-dof-simulation
aZira371 Jul 11, 2025
e299a30
MNT: updates to 3dof example
aZira371 Jul 11, 2025
d4dc989
MNT: lint cleanup and adding 3dof to init
aZira371 Jul 11, 2025
c8096c5
MNT: Point mass motor and rocket fixes
aZira371 Aug 30, 2025
724f9dd
MNT: flight class fix on simulation mode detection
aZira371 Aug 30, 2025
f1e0fb0
MNT: make format changes
aZira371 Sep 9, 2025
4b9b952
MNT: point mass motor cleanup
aZira371 Jun 26, 2025
45380fd
ENH: restructuring rocket class
aZira371 Jun 30, 2025
5cd1535
MNT: fixing certain calculations on point mass motor
aZira371 Jul 11, 2025
1e590c2
Rename PointMassMotor.py to pointmassmotor.py
aZira371 Jul 11, 2025
981dda5
ENH: _MotorPrints inheritance - issue #460 (#828)
Gui-FernandesBR Jun 19, 2025
5c75298
MNT: fix deprecations and warnings (#829)
Gui-FernandesBR Jun 20, 2025
70f24ee
DEV: streamline caching of Python dependencies in GitHub Actions
Gui-FernandesBR Jun 20, 2025
0cb0994
ENH: Add the Coriolis Force to the Flight class (#799)
kevin-alcaniz Jul 4, 2025
58f8b0d
MNT: deprecated decorator (#830)
Gui-FernandesBR Jul 4, 2025
191744f
MNT: updates to 3dof example
aZira371 Jul 11, 2025
265dd93
MNT: lint cleanup and adding 3dof to init
aZira371 Jul 11, 2025
5aa2027
MNT: Point mass motor and rocket fixes
aZira371 Aug 30, 2025
464212d
MNT: flight class fix on simulation mode detection
aZira371 Aug 30, 2025
a1b1d1f
MNT: make format changes
aZira371 Sep 9, 2025
d9cbde5
Merge branch 'enh/3-dof-simulation' of https://github.com/aZira371/Ro…
aZira371 Sep 9, 2025
0aa32b5
Merge branch 'develop' into enh/3-dof-simulation
aZira371 Sep 9, 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
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@
"outerboundaryis",
"overshootable",
"planform",
"pointmassmotor",
"polystyle",
"powerseries",
"Prandtl",
Expand Down
245 changes: 245 additions & 0 deletions docs/examples/3_DOF_TRIAL.ipynb

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions rocketpy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
MassBasedTank,
MassFlowRateBasedTank,
Motor,
PointMassMotor,
SolidMotor,
SphericalTank,
Tank,
Expand All @@ -35,6 +36,7 @@
LinearGenericSurface,
NoseCone,
Parachute,
PointMassRocket,
RailButtons,
Rocket,
Tail,
Expand Down
1 change: 1 addition & 0 deletions rocketpy/motors/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from .hybrid_motor import HybridMotor
from .liquid_motor import LiquidMotor
from .motor import GenericMotor, Motor
from .point_mass_motor import PointMassMotor
from .solid_motor import SolidMotor
from .tank import (
LevelBasedTank,
Expand Down
106 changes: 106 additions & 0 deletions rocketpy/motors/point_mass_motor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
from functools import cached_property
from typing import Callable

import numpy as np

from rocketpy.mathutils.function import Function, funcify_method

from .motor import Motor


class PointMassMotor(Motor):
"""Motor modeled as a point mass for 3-DOF simulations."""

def __init__(
self,
thrust_source,
dry_mass,
propellant_initial_mass,
burn_time=None,
propellant_final_mass=None,
reshape_thrust_curve=False,
interpolation_method="linear",
):
if isinstance(thrust_source, (int, float, Callable)):
if propellant_initial_mass is None:
raise ValueError(
"For constant or callable thrust, 'propellant_initial_mass' is required."
)
if burn_time is None and propellant_final_mass is None:
raise ValueError(
"For constant or callable thrust, either 'burn_time' or "
"'propellant_final_mass' must be provided."
)
elif isinstance(thrust_source, (Function, np.ndarray, str)):
if propellant_initial_mass is None:
raise ValueError(
"For thrust from a Function, NumPy array, or CSV, 'propellant_initial_mass' is required."
)
else:
raise TypeError(
"Invalid 'thrust_source' type. Must be int, float, callable, str, numpy.ndarray, or Function."
)

self._propellant_initial_mass = propellant_initial_mass
self.propellant_final_mass = propellant_final_mass

super().__init__(
thrust_source=thrust_source,
dry_inertia=(0, 0, 0),
nozzle_radius=0,
center_of_dry_mass_position=0,
dry_mass=dry_mass,
nozzle_position=0,
burn_time=burn_time,
reshape_thrust_curve=reshape_thrust_curve,
interpolation_method=interpolation_method,
coordinate_system_orientation="nozzle_to_combustion_chamber",
)

@property
def propellant_initial_mass(self):
return self._propellant_initial_mass

@funcify_method("Time (s)", "Exhaust velocity (m/s)")
def exhaust_velocity(self):
"""Assume constant exhaust velocity: total impulse / propellant mass"""
v_e = self.total_impulse / self.propellant_initial_mass
return Function(v_e).set_discrete_based_on_model(self.thrust)

@cached_property
def total_mass_flow_rate(self) -> Function:
"""Mass flow rate: -thrust / exhaust_velocity"""
return -self.thrust / self.exhaust_velocity
Comment on lines +64 to +73
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These two methods seem to be equal to the parent class Motor.exhaust_velocity and Motor.total_mass_flow_rate. If I understood correctly, they could be deleted without any problems (the parent class one would be used).


@cached_property
def center_of_propellant_mass(self):
"""Center of propellant mass is always zero"""
return Function(0.0)

# Propellant inertias: always zero, but return as Function objects
def _zero_inertia_func(self):
return Function(0.0)

@cached_property
def propellant_I_11(self):
return self._zero_inertia_func()

@cached_property
def propellant_I_12(self):
return self._zero_inertia_func()

@cached_property
def propellant_I_13(self):
return self._zero_inertia_func()

@cached_property
def propellant_I_22(self):
return self._zero_inertia_func()

@cached_property
def propellant_I_23(self):
return self._zero_inertia_func()

@cached_property
def propellant_I_33(self):
return self._zero_inertia_func()
2 changes: 1 addition & 1 deletion rocketpy/rocket/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@
)
from rocketpy.rocket.components import Components
from rocketpy.rocket.parachute import Parachute
from rocketpy.rocket.rocket import Rocket
from rocketpy.rocket.rocket import PointMassRocket, Rocket
109 changes: 109 additions & 0 deletions rocketpy/rocket/rocket.py
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could we also accept drag curves, instead of only float values?

Original file line number Diff line number Diff line change
Expand Up @@ -2052,3 +2052,112 @@ def from_dict(cls, data):
)

return rocket


class PointMassRocket(Rocket):
def __init__(
self,
radius: float = 0.05,
mass: float = 0,
center_of_mass_without_motor: float = 0,
power_off_drag: float = 0.4,
power_on_drag: float = 0.4,
):
self._center_of_mass_without_motor_pointmass = center_of_mass_without_motor
self._center_of_dry_mass_position = center_of_mass_without_motor
self._center_of_mass = center_of_mass_without_motor
# Dry inertias are zero for point mass
self._dry_I_11 = 0.0
self._dry_I_22 = 0.0
self._dry_I_33 = 0.0
self._dry_I_12 = 0.0
self._dry_I_13 = 0.0
self._dry_I_23 = 0.0

# Call base init with safe defaults
super().__init__(
radius=radius,
mass=mass,
inertia=(0, 0, 0),
power_off_drag=power_off_drag,
power_on_drag=power_on_drag,
center_of_mass_without_motor=center_of_mass_without_motor,
)

# ------------------------------------------------------------------
# Center of Mass Properties
# ------------------------------------------------------------------
@property
def center_of_mass_without_motor(self):
return self._center_of_mass_without_motor_pointmass

@center_of_mass_without_motor.setter
def center_of_mass_without_motor(self, value):
self._center_of_mass_without_motor_pointmass = value

@property
def center_of_dry_mass_position(self):
return self._center_of_dry_mass_position

@center_of_dry_mass_position.setter
def center_of_dry_mass_position(self, value):
self._center_of_dry_mass_position = value

@property
def center_of_mass(self):
return self._center_of_mass

@center_of_mass.setter
def center_of_mass(self, value):
self._center_of_mass = value

# ------------------------------------------------------------------
# Inertia Properties (always zero)
# ------------------------------------------------------------------
@property
def dry_I_11(self):
return 0.0

@dry_I_11.setter
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: do you really need a @dry_I_11.setter? Apparently you have already set the properties to always be 0

def dry_I_11(self, value):
self._dry_I_11 = 0.0

@property
def dry_I_22(self):
return 0.0

@dry_I_22.setter
def dry_I_22(self, value):
self._dry_I_22 = 0.0

@property
def dry_I_33(self):
return 0.0

@dry_I_33.setter
def dry_I_33(self, value):
self._dry_I_33 = 0.0

@property
def dry_I_12(self):
return 0.0

@dry_I_12.setter
def dry_I_12(self, value):
self._dry_I_12 = 0.0

@property
def dry_I_13(self):
return 0.0

@dry_I_13.setter
def dry_I_13(self, value):
self._dry_I_13 = 0.0

@property
def dry_I_23(self):
return 0.0

@dry_I_23.setter
def dry_I_23(self, value):
self._dry_I_23 = 0.0
Loading
Loading