@@ -209,32 +209,47 @@ def __init__(
209209
210210 Has no effect when ``radius`` is explicitly provided.
211211 """
212+
213+ # Save arguments as attributes
212214 self .name = name
213215 self .cd_s = cd_s
214216 self .trigger = trigger
215217 self .sampling_rate = sampling_rate
216218 self .lag = lag
217219 self .noise = noise
218220 self .drag_coefficient = drag_coefficient
219- # Estimate radius from cd_s if not provided.
220- # cd_s = Cd * S = Cd * π * R² => R = sqrt(cd_s / (Cd * π))
221- if radius is None :
222- self .radius = np .sqrt (cd_s / (drag_coefficient * np .pi ))
223- else :
224- self .radius = radius
225- self .height = height or self .radius
226221 self .porosity = porosity
227- self .added_mass_coefficient = 1.068 * (
228- 1
229- - 1.465 * self .porosity
230- - 0.25975 * self .porosity ** 2
231- + 1.2626 * self .porosity ** 3
232- )
233222
223+ # Initialize derived attributes
224+ self .radius = self .__resolve_radius (radius , cd_s , drag_coefficient )
225+ self .height = self .__resolve_height (height , self .radius )
226+ self .added_mass_coefficient = self .__compute_added_mass_coefficient (
227+ self .porosity
228+ )
234229 self .__init_noise (noise )
235- self .prints = _ParachutePrints (self )
236230 self .__evaluate_trigger_function (trigger )
237231
232+ # Prints and plots
233+ self .prints = _ParachutePrints (self )
234+
235+ def __resolve_radius (self , radius , cd_s , drag_coefficient ):
236+ """Resolves parachute radius from input or aerodynamic relation."""
237+ if radius is not None :
238+ return radius
239+
240+ # cd_s = Cd * S = Cd * pi * R^2 => R = sqrt(cd_s / (Cd * pi))
241+ return np .sqrt (cd_s / (drag_coefficient * np .pi ))
242+
243+ def __resolve_height (self , height , radius ):
244+ """Resolves parachute height defaulting to radius when not provided."""
245+ return height or radius
246+
247+ def __compute_added_mass_coefficient (self , porosity ):
248+ """Computes the added-mass coefficient from canopy porosity."""
249+ return 1.068 * (
250+ 1 - 1.465 * porosity - 0.25975 * porosity ** 2 + 1.2626 * porosity ** 3
251+ )
252+
238253 def __init_noise (self , noise ):
239254 """Initializes all noise-related attributes.
240255
@@ -263,7 +278,8 @@ def __evaluate_trigger_function(self, trigger):
263278 interact with the Flight class.
264279 """
265280 # pylint: disable=unused-argument, function-redefined
266- # The parachute is deployed by a custom function
281+
282+ # Case 1: The parachute is deployed by a custom function
267283 if callable (trigger ):
268284 # work around for having added sensors to parachute triggers
269285 # to avoid breaking changes
@@ -276,26 +292,29 @@ def triggerfunc(p, h, y, sensors):
276292
277293 self .triggerfunc = triggerfunc
278294
295+ # Case 2: The parachute is deployed at a given height
279296 elif isinstance (trigger , (int , float )):
280297 # The parachute is deployed at a given height
281- def triggerfunc (p , h , y , sensors ): # pylint: disable=unused-argument
298+ def triggerfunc (p , h , y , sensors ):
282299 # p = pressure considering parachute noise signal
283300 # h = height above ground level considering parachute noise signal
284301 # y = [x, y, z, vx, vy, vz, e0, e1, e2, e3, w1, w2, w3]
285302 return y [5 ] < 0 and h < trigger
286303
287304 self .triggerfunc = triggerfunc
288305
306+ # Case 3: The parachute is deployed at apogee
289307 elif trigger .lower () == "apogee" :
290308 # The parachute is deployed at apogee
291- def triggerfunc (p , h , y , sensors ): # pylint: disable=unused-argument
309+ def triggerfunc (p , h , y , sensors ):
292310 # p = pressure considering parachute noise signal
293311 # h = height above ground level considering parachute noise signal
294312 # y = [x, y, z, vx, vy, vz, e0, e1, e2, e3, w1, w2, w3]
295313 return y [5 ] < 0
296314
297315 self .triggerfunc = triggerfunc
298316
317+ # Case 4: Invalid trigger input
299318 else :
300319 raise ValueError (
301320 f"Unable to set the trigger function for parachute '{ self .name } '. "
@@ -327,7 +346,7 @@ def info(self):
327346 def all_info (self ):
328347 """Prints all information about the Parachute class."""
329348 self .info ()
330- # self.plots.all() # Parachutes still doesn't have plots
349+ # self.plots.all() # TODO: Parachutes still doesn't have plots
331350
332351 def to_dict (self , ** kwargs ):
333352 allow_pickle = kwargs .get ("allow_pickle" , True )
0 commit comments