@@ -3970,74 +3970,106 @@ def __lt__(self, other):
39703970 otherwise.
39713971 """
39723972 return self .t < other .t
3973+
39733974 @cached_property
39743975 def calculate_rail_button_bending_moments (self ):
39753976 """
39763977 Calculate internal bending moments at rail button attachment points.
39773978
3978- Uses beam theory with simple support assumptions (ΣF≠0, M_contact=0)
3979- to determine internal structural moments for stress analysis.
3979+ Uses beam theory to determine internal structural moments for stress
3980+ analysis of the rail button attachments (fasteners and airframe).
3981+
3982+ The bending moment at each button attachment consists of:
3983+ 1. Bending from shear force at button contact point: M = S × h
3984+ where S is the shear (tangential) force and h is button height
3985+ 2. Direct moment contribution from the button's reaction forces
39803986
3981- The bending moment at each button consists of two components:
3982- 1. Main bending from the opposing button's normal force (M = N × L)
3983- 2. Additional moment from shear force at button tip (M = S × h)
3987+ Notes
3988+ -----
3989+ - Calculated only during the rail phase of flight
3990+ - Maximum values use absolute values for worst-case stress analysis
3991+ - The bending moments represent internal stresses in the rocket
3992+ airframe at the rail button attachment points
39843993
39853994 Returns
39863995 -------
39873996 tuple
3988- (rail_button1_bending_moment, max_rail_button1_bending_moment,
3989- rail_button2_bending_moment, max_rail_button2_bending_moment)
3997+ (rail_button1_bending_moment : Function,
3998+ max_rail_button1_bending_moment : float,
3999+ rail_button2_bending_moment : Function,
4000+ max_rail_button2_bending_moment : float)
4001+
4002+ Where rail_button1/2_bending_moment are Function objects of time
4003+ in N·m, and max values are floats in N·m.
39904004 """
39914005 # Check if rail buttons exist
4006+ null_moment = Function (0 )
39924007 if len (self .rocket .rail_buttons ) == 0 :
39934008 warnings .warn (
39944009 "Trying to calculate rail button bending moments without "
39954010 "rail buttons defined. Setting moments to zero." ,
39964011 UserWarning ,
39974012 )
3998- null_moment = Function (0 )
3999- self .rail_button1_bending_moment = null_moment
4000- self .rail_button2_bending_moment = null_moment
4001- self .max_rail_button1_bending_moment = 0.0
4002- self .max_rail_button2_bending_moment = 0.0
4003- return
4004- #distance between points
4005- button1_pos = self .rocket .rail_buttons .component_coordinate_system_orientation * (self .rocket .rail_buttons .position )
4006- button2_pos = button1_pos + self .rocket .rail_buttons .buttons_distance
4007- d1 = abs (button1_pos - self .rocket .center_of_mass_without_motor )
4008- d2 = abs (button2_pos - self .rocket .center_of_mass_without_motor )
4009- L = d1 + d2 # Distance between buttons
4010- h_button = self .rocket .rail_buttons .button_height #rail button height
4011- #forces
4013+ return (null_moment , 0.0 , null_moment , 0.0 )
4014+
4015+ # Get rail button geometry
4016+ rail_buttons_tuple = self .rocket .rail_buttons [0 ]
4017+ upper_button_position = (
4018+ rail_buttons_tuple .component .buttons_distance
4019+ + rail_buttons_tuple .position .z
4020+ )
4021+ lower_button_position = rail_buttons_tuple .position .z
4022+
4023+ # Signed distances from buttons to center of dry mass
4024+ D1 = upper_button_position - self .rocket .center_of_dry_mass_position (
4025+ self .rocket ._csys
4026+ )
4027+ D2 = lower_button_position - self .rocket .center_of_dry_mass_position (
4028+ self .rocket ._csys
4029+ )
4030+ d1 = abs (D1 )
4031+ d2 = abs (D2 )
4032+
4033+ # Rail button standoff height
4034+ h_button = rail_buttons_tuple .component .button_height
4035+
4036+ # forces
40124037 N1 = self .rail_button1_normal_force
40134038 N2 = self .rail_button2_normal_force
40144039 S1 = self .rail_button1_shear_force
40154040 S2 = self .rail_button2_shear_force
40164041 t = N1 .source [:, 0 ]
4017- # Main bending from opposing button + additional moment from shear at tip
4018- M1_values = N2 .source [:, 1 ] * L + S1 .source [:, 1 ] * h_button
4019- M2_values = N1 .source [:, 1 ] * L + S2 .source [:, 1 ] * h_button
4020- self .rail_button1_bending_moment = Function (
4021- np .column_stack ([t , M1_values ]),
4042+
4043+ # Calculate bending moments at attachment points
4044+ # Primary contribution from shear force acting at button height
4045+ # Secondary contribution from normal force creating moment about attachment
4046+ m1_values = N2 .source [:, 1 ] * d2 + S1 .source [:, 1 ] * h_button
4047+ m2_values = N1 .source [:, 1 ] * d1 + S2 .source [:, 1 ] * h_button
4048+
4049+ rail_button1_bending_moment = Function (
4050+ np .column_stack ([t , m1_values ]),
40224051 inputs = "Time (s)" ,
40234052 outputs = "Bending Moment (N·m)" ,
40244053 interpolation = "linear" ,
40254054 )
4026- self . rail_button2_bending_moment = Function (
4027- np .column_stack ([t , M2_values ]),
4055+ rail_button2_bending_moment = Function (
4056+ np .column_stack ([t , m2_values ]),
40284057 inputs = "Time (s)" ,
40294058 outputs = "Bending Moment (N·m)" ,
40304059 interpolation = "linear" ,
40314060 )
4032- # Maximum bending moments in terms of absolute value for stress calculations
4033- self .max_rail_button1_bending_moment = float (np .max (np .abs (M1_values )))
4034- self .max_rail_button2_bending_moment = float (np .max (np .abs (M2_values )))
4061+
4062+ # Maximum bending moments (absolute value for stress calculations)
4063+ max_rail_button1_bending_moment = float (np .max (np .abs (m1_values )))
4064+ max_rail_button2_bending_moment = float (np .max (np .abs (m2_values )))
4065+
40354066 return (
4036- self . rail_button1_bending_moment ,
4037- self . max_rail_button1_bending_moment ,
4038- self . rail_button2_bending_moment ,
4039- self . max_rail_button2_bending_moment ,
4067+ rail_button1_bending_moment ,
4068+ max_rail_button1_bending_moment ,
4069+ rail_button2_bending_moment ,
4070+ max_rail_button2_bending_moment ,
40404071 )
4072+
40414073 @property
40424074 def rail_button1_bending_moment (self ):
40434075 """Upper rail button bending moment as a Function of time."""
@@ -4056,4 +4088,4 @@ def rail_button2_bending_moment(self):
40564088 @property
40574089 def max_rail_button2_bending_moment (self ):
40584090 """Maximum lower rail button bending moment, in N·m."""
4059- return self .calculate_rail_button_bending_moments [3 ]
4091+ return self .calculate_rail_button_bending_moments [3 ]
0 commit comments