Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
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
Prev Previous commit
Next Next commit
refactor: apply remaining Copilot review suggestions
  • Loading branch information
ayoubdsp committed Mar 16, 2026
commit 74022e7fa84091d5172336653c025fb8540586db
34 changes: 25 additions & 9 deletions rocketpy/motors/cluster_motor.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,18 @@
radius : float
Distance from center of rocket to center of motor (m).
"""
if not isinstance(number, int):
raise TypeError(f"number must be an int, got {type(number).__name__}")
if number < 2:
raise ValueError("number must be >= 2 for a ClusterMotor")
if not isinstance(radius, (int, float)):
raise TypeError(f"radius must be a real number, got {type(radius).__name__}")
if radius < 0:
raise ValueError("radius must be non-negative")

self.motor = motor
self.number = number
self.radius = float(radius)
self.motor = motor
self.number = number
self.radius = radius
Expand Down Expand Up @@ -158,9 +170,9 @@
@propellant_I_23.setter
def propellant_I_23(self, value):
self._propellant_I_23 = value

def exhaust_velocity(self, t):
return self.motor.exhaust_velocity(t)
@property
def exhaust_velocity(self):
return self.motor.exhaust_velocity

def _calculate_dry_inertia(self):
Ixx_loc = self.motor.dry_I_11
Expand All @@ -169,19 +181,19 @@
m_dry = self.motor.dry_mass

Izz_cluster = self.number * Izz_loc + self.number * m_dry * (self.radius**2)
I_transverse = self.number * Ixx_loc + (self.number / 2) * m_dry * (
self.radius**2
)
Ixx_cluster = self.number * Ixx_loc + (self.number / 2) * m_dry * (self.radius**2)
Iyy_cluster = self.number * Iyy_loc + (self.number / 2) * m_dry * (self.radius**2)

return (I_transverse, I_transverse, Izz_cluster)
return (Ixx_cluster, Iyy_cluster, Izz_cluster)

def info(self):
print(f"Cluster Configuration:")

Check failure on line 190 in rocketpy/motors/cluster_motor.py

View workflow job for this annotation

GitHub Actions / lint (3.10)

ruff (F541)

rocketpy/motors/cluster_motor.py:190:15: F541 f-string without any placeholders help: Remove extraneous `f` prefix
print(f" - Motors: {self.number} x {type(self.motor).__name__}")
print(f" - Radial Distance: {self.radius} m")
return self.motor.info()

def draw_cluster_layout(self, rocket_radius=None):
def draw_cluster_layout(self, rocket_radius=None,show=True):
"""Draw the geometric layout of the clustered motors."""
fig, ax = plt.subplots(figsize=(6, 6))
ax.plot(0, 0, "k+", markersize=10, label="Central axis")
if rocket_radius:
Expand Down Expand Up @@ -229,4 +241,8 @@
ax.set_title(f"Cluster Configuration : {self.number} engines")
ax.grid(True, linestyle=":", alpha=0.6)
ax.legend(loc="upper right")
plt.show()
if show:
plt.show()
return fig, ax


5 changes: 4 additions & 1 deletion tests/integration/motors/test_cluster_motor.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def test_cluster_initialization(base_motor):

def test_cluster_mass_and_thrust_scaling(base_motor):
"""
Tests if scalar properties (Thrust, Mass) are correctly multiplied by N.
Tests if scalar and derived properties are correctly multiplied by N and that functional properties preserve their Function behavior
"""
N = 4
R = 0.2
Expand All @@ -61,6 +61,9 @@ def test_cluster_mass_and_thrust_scaling(base_motor):

# 3. Check Propellant Mass Scaling
assert np.isclose(cluster.propellant_mass(0), base_motor.propellant_mass(0) * N)
assert np.isclose(cluster.total_impulse, base_motor.total_impulse * N)
assert np.isclose(cluster.average_thrust, base_motor.average_thrust * N)


def test_cluster_dry_inertia_steiner_theorem(base_motor):
"""
Expand Down
Loading