def predict_one(self, conditions): # evaluate T = T_lin(conditions, *self.params) F = F_lin(conditions, *self.params) # repack and return return Prediction(*conditions.unpack(), T, F)
def loss(self, prediction: Prediction): """ Find the "loss" for this problem. Loss is defined as the inverse of (optimality * failure metric). This is boosted by 1e8 to deal with floating point precision. """ return -(1e8 * (optimality(prediction.conditions())) * self.failure(prediction))
def deflection_load(D_a, prediction: Prediction, machinechar: MachineChar, E_e=650e9): """ Calculates ratio of tool deflection to allowed deflection. Uses FEA model described in doi:10.1016/j.ijmachtools.2005.09.009. Also includes machine deflection if it is defined. Args: D_a: Allowed deflection (m) prediction: A prediction object E_e: Modulus of elasticity (default is for Carbide) (Pa) Returns: Ratio of tool deflection to allowed deflection """ _, _, _, _, endmill, _, F = prediction.unpack() K_machine = machinechar.K_machine Fy = F[1] N, r_c, r_s, l_c, l_s = endmill.unpack() # prepare variables, this must be done since the FEA model has arbitrary constants defined for certain units d_1 = r_c * 2 * 1e3 # convert to diameter in mm d_2 = r_s * 2 * 1e3 l_1 = l_c * 1e3 l_2 = (l_s + l_c) * 1e3 E = E_e * 1e-6 # convert to MPa # set constants C = None G = None if N == 4: C = 9.05 G = 0.950 elif N == 3: C = 8.30 G = 0.965 elif N == 2: C = 7.93 G = 0.974 else: raise ValueError("Flute count must be between 2-4") # calculate tool bending D_t = C * (Fy / E) * ((l_1**3 / d_1**4) + ((l_2**3 - l_1**3) / d_2**4))**G * 1e-3 # calculate machine deflection D_m = Fy / K_machine return (D_t + D_m) / D_a
def motor_torque_load(prediction: Prediction, machinechar: MachineChar): """ Calculates ratio of current motor torque to max motor torque. Args: prediction: A prediction object. machinechar: A machinechar object. Returns: Ratio of current motor torque to max achievable torque """ _, _, _, _, _, T, _ = prediction.unpack() r_e, K_T, _, _, I_max, T_nom, _, _, _ = machinechar.unpack() T_m = (T + T_nom) / r_e # store K_V for convenience # max torque is either determined by max current that can be supplied return T_m / (K_T * I_max)
def motor_speed_load(prediction: Prediction, machinechar: MachineChar): """ Calculates ratio of motor speed to maximum motor speed Args: prediction: A prediction object machinechar: A machinechar object Returns: Ratio of current motor speed to max achievable speed """ _, _, _, w, _, T, _ = prediction.unpack() r_e, K_T, R_w, V_max, _, T_nom, _, _, _ = machinechar.unpack() w_m = w * r_e T_m = (T + T_nom) / r_e # store K_V for convenience K_V = 1 / K_T # max speed is affected by winding resistive voltage drop along with backemf return w_m / (K_V * (V_max - T_m * R_w / K_T))
def failure_prob_milling(prediction: Prediction, m=4, o=1500e6, a_c=0.8): """ Calculates failure probability according to Weibull distribution. Method adapted from https://doi.org/10.1016/S0007-8506(07)62072-1 Args: prediction: A prediction object roughing: Whether or not the cutter has roughing serrations (true/false) m: Weibull parameter for carbide tooling (dimensionless) o: Weibull parameter for carbide tooling (N) a_c: Compensated cutter diameter due to helical flutes (dimensionless) Returns: Probability of failure """ D, _, _, _, endmill, T, F = prediction.unpack() F = np.linalg.norm(F) _, r_c, r_s, l_c, l_s = endmill.unpack() # establish base variables r_ceq = r_c * a_c # equivalent cutter radius I_ceq = np.pi / 4 * r_ceq**4 # equivalent cutter 2nd inertia I_s = np.pi / 4 * r_s**4 # shank 2nd inertia J_ceq = np.pi * r_ceq**4 / 2 # equivalent cutter polar inertia # reusable expression to get peak stress in cutter def stress_tensile(r, l, I): return (F * r * (l - D / 2)) / I # finding surface stress at cutter-shank interface at the depth of the cutter edge stress_c = stress_tensile(r_c, l_c, I_ceq) # finding surface stress at shaft-collet interface stress_s = stress_tensile(r_s, l_c + l_s, I_s) # adjusting torsion to compensate for shear-tensile difference stress_t = 1 / 0.577 * T * r_c / J_ceq # unknown if von mises stress criterion makes any sense for weibull analysis, taking max of all stresses instead stress_peak = max(stress_c, stress_s, stress_t) # cdf for weibull distribution failure_prob = 1 - np.exp(-(stress_peak / o)**m) return failure_prob
def deflection_load_simple(prediction: Prediction, machinechar: MachineChar, E_e=600e9, a_c=0.8): """ Calculates ratio of deflection to allowable deflection. Uses simple approximation that assumes endmill cutter can be approx. as 0.8 of its diameter. Args: D_a: Allowed deflection (m) prediction: Prediction of force machinechar: Characterization of machine E_e: Modulus of elasticity for endmill a_c: Diameter reduction of cutter for cantilever beam model of endmill. Returns: Ratio of tool deflection to allowed deflection along y axis (since this is the only axis that matters for milling a face) """ D, _, _, _, endmill, _, F = prediction.unpack() _, _, _, _, _, _, _, K_machine, D_a = machinechar.unpack() F_y = F[1] _, r_c, r_s, l_c, l_s = endmill.unpack() # calculate basic params D_m = F_y / K_machine r_ceq = r_c * a_c # equivalent cutter radius I_ceq = np.pi / 4 * r_ceq**4 # equivalent cutter 2nd inertia I_s = np.pi / 4 * r_s**4 # shank 2nd inertia M_s = F_y * (l_c - D / 2) # find moment at end of shank D_s = (M_s * l_s ** 2) / (2 * E_e * I_s) + (F_y * l_s ** 3) / \ (3 * E_e * I_s) # deflection of shank from moment and force theta_s = (M_s * l_s) / (E_e * I_s) # slope at end of shank D_c = (F_y * (l_c - D / 2)**2 * (3 * l_c - (l_c - D / 2))) / ( 6 * E_e * I_ceq ) + D_s + theta_s * l_c # deflection at cutter tip from everything return (D_m + D_c) / D_a
MACHINE_PORT = '/dev/ttyS25' SPINDLE_PORT = '/dev/ttyS33' TFD_PORT = '/dev/ttyS36' D = 1e-3 W = 1e-3 f_r = 0.001 w = 100 D_A = 0.1e-3 N = 100 CONFIDENCE_RATE = np.linspace(0.2, 1, 10) MACHINE = MachineChar(r_e=1, K_T=0.10281, R_w=0.188, V_max=48, I_max=10, T_nom=0.12, f_r_max=0.010, K_machine=5e6, D_a=D_A) ENDMILL = EndMill(3, 3.175e-3, 3.175e-3, 19.05e-3, 1e-3) FIXED_CONDITIONS = Conditions(D=D, W=W, f_r=f_r, w=w, endmill=ENDMILL) print( deflection_load_simple( D_A, Prediction(*FIXED_CONDITIONS.unpack(), 0.1, [100, 100]), MACHINE)) print( deflection_load(D_A, Prediction(*FIXED_CONDITIONS.unpack(), 0.1, [100, 100]), MACHINE))