def _make_form_coords(self): """ Tooth form coordinates in transverse cross-section (half tooth and half gap) points returned in 2D-cartesian coordinates, origin on wheel axis old form coordinates (if existend) will be replaced! This method should be used only if no user-supplied form coordinates are present. INPUT parameter: - """ # module imports from scipy.optimize import fsolve from numpy.linalg import norm from numpy import insert # tolerance for comparisons tol = self._tol_default * self.data.get("m_n") # delete old form coordinates if existend if self.formcoords: del self.formcoords if self._formwire: del self._formwire # indicator whether gear is external (number of teeth positive) or internal isexternal = sign(self.data.get("z")) inv_extension = False # indices for adressing parts of tooth form lower_index = 0 start_rootcirc_index = lower_index + 1 # one entry reserved for origin end_rootcirc_index = start_rootcirc_index + self.points_root - 1 start_fillet_index = end_rootcirc_index end_fillet_index = start_fillet_index + self.points_fillet - 1 start_involute_index = end_fillet_index + 1 # can differ from end of fillet end_involute_index = start_involute_index + self.points_flank - 1 start_chamfer_index = end_involute_index + 1 end_chamfer_index = start_chamfer_index + self.points_chamfer - 1 start_tipcirc_index = end_chamfer_index + 1 # differs from end of involute if chamfer present end_tipcirc_index = start_tipcirc_index + self.points_tip - 1 upper_index = end_tipcirc_index # determine boundary of half tooth segment on root circle rootcirc_start_point = ( self.data.get("d_f") / 2 * np.array([-sin(radians(self.data.get("tau") / 2)), cos(radians(self.data.get("tau") / 2))]) ) # determine how the root shape is defined and calculate significant points # root shape is circular in transverse cross-section if isexternal > 0: # for external gears if "d_Ff" not in self.data: # root circle is tangent to involute if ( self.data.get("d_f") ** 2 + 4 * self.data.get("rho_f") * self.data.get("d_f") >= self.data.get("d_b") ** 2 ): self.data.update( { "d_Ff": isexternal * sqrt( ( sqrt( (self.data.get("d_f") + 2 * self.data.get("rho_f")) ** 2 - self.data.get("d_b") ** 2 ) - 2 * self.data.get("rho_f") ) ** 2 + self.data.get("d_b") ** 2 ) } ) s_yt, d_yc = self._tooth_thickness(self.data.get("d_Ff")) fil_end_point = np.array([-s_yt / 2, d_yc / 2]) # no tangency possible: undercut elif self.data.get("d_f") + 4 * self.data.get("rho_f") >= self.data.get("d_b"): self.data.update({"d_Ff": self.data.get("d_b")}) s_yt, d_yc = self._tooth_thickness(self.data.get("d_b")) fil_end_point = np.array([-s_yt / 2, d_yc / 2]) # end of involute at base circle print "Warning: undercutting occurs!" else: self.data.update({"d_Ff": self.data.get("d_b")}) d_tangent = sqrt( self.data.get("d_f") ** 2 + 4 * self.data.get("rho_f") * self.data.get("d_f") ) # diameter around gear center on that tangency point of fillet curve is located s_yt, d_yc = self._tooth_thickness(self.data.get("d_b")) nu = atan(s_yt / d_yc) fil_end_point = np.array( [-d_tangent / 2 * sin(nu), d_tangent / 2 * cos(nu)] ) # tangential extension of involute beyond base circle print "Warning: involute had to be extended below base cicle to achieve root fillet tangency!" inv_extension = True else: # if root form circle diameter is supplied, it is forced strictly if possible if (self.data.get("d_Ff") - self.data.get("d_f")) / 2 > 2 * self.data.get( "rho_f" ): # check if root fillet circle fits beetween root form circle and root circle raise ValueError("root fillet radius too small: root shape cannot be determined") s_yt, d_yc = self._tooth_thickness(self.data.get("d_Ff")) if abs(self.data.get("d_Ff")) >= abs(self.data.get("d_b")): # fillet ends at root form circle fil_end_point = np.array([-s_yt / 2, d_yc / 2]) else: # base circle diameter greater than root form diameter: tangential extension of involute nu = atan(s_yt / d_yc) fil_end_point = np.array([-self.data.get("d_Ff") * sin(nu), self.data.get("d_Ff") * cos(nu)]) print "Warning: involute had to be extended below base cicle to enforce root form circle diameter!" inv_extension = True else: # for internal gears if "d_Ff" not in self.data: # root circle is tangent to involute t_b = sqrt((self.data.get("d_f") / 2 + self.data.get("rho_f")) ** 2 - (self.data.get("d_b") / 2) ** 2) self.data.update( {"d_Ff": -2 * sqrt((t_b + self.data.get("rho_f")) ** 2 + (self.data.get("d_b") / 2) ** 2)} ) else: # if root form circle diameter is supplied, it is forced strictly if possible if (self.data.get("d_Ff") - self.data.get("d_f")) / 2 > 2 * self.data.get( "rho_f" ): # check if root fillet circle fits beetween root form circle and root circle raise ValueError("root fillet radius too small: root shape cannot be determined") s_yt, d_yc = self._tooth_thickness(self.data.get("d_Ff")) fil_end_point = np.array([-s_yt / 2, d_yc / 2]) # find center of root fillet circle by cutting circle around fillet end point with radius rho_f # with circle around center of gear wheel with radius d_f/2+rho_f def root_circle_center_func(phi): return ( fil_end_point + self.data.get("rho_f") * np.array([sin(phi[0]), cos(phi[0])]) - (self.data.get("d_f") / 2 + self.data.get("rho_f")) * np.array([sin(phi[1]), cos(phi[1])]) ) phi_fil_center = fsolve(root_circle_center_func, [-pi / 2, 0.0]) fil_center_point = (self.data.get("d_f") / 2 + self.data.get("rho_f")) * np.array( [sin(phi_fil_center[1]), cos(phi_fil_center[1])] ) # boundary point of root fillet and root circle fil_start_point = fil_center_point * self.data.get("d_f") / (self.data.get("d_f") + 2 * self.data.get("rho_f")) # if boundary point and fillet center are outside half tooth segment the shape of the root fillet # cannot be determined (root fillet curve is not continously differentiable and d_f is not matched) if abs(atan(fil_start_point[0] / fil_start_point[1])) > abs(radians(self.data.get("tau") / 2)): raise ValueError("root fillet radius too large: root shape cannot be determined") # determine boundary points of involute s_yt, d_yc = self._tooth_thickness(self.data.get("d_Ff")) inv_start_point = np.array([-s_yt / 2, d_yc / 2]) # involute starts at root form circle s_yt, d_yc = self._tooth_thickness(self.data.get("d_Fa")) inv_end_point = np.array([-s_yt / 2, d_yc / 2]) # involute ends at tip form circle # determine boundary points of tip circle nu = self.data.get("s_aK") / self.data.get("d_a") tipcirc_start_point = np.array( [-self.data.get("d_a") / 2 * sin(nu), self.data.get("d_a") / 2 * cos(nu)] ) # tip circle starts at end of tip chamfer tipcirc_end_point = np.array([0.0, self.data.get("d_a") / 2]) # tip circle ends at symmetry line # create array for tooth form coordinates formcoord_array = np.zeros([upper_index, 2]) # compute points on root circle phi_start = -asin(2 * rootcirc_start_point[0] / self.data.get("d_f")) # starting angle of root circle if abs(phi_start - acos(2 * rootcirc_start_point[1] / self.data.get("d_f"))) > tol: # computation is not unique phi_start = pi - phi_start phi_end = -asin(2 * fil_start_point[0] / self.data.get("d_f")) # end angle of root circle if abs(phi_end - acos(2 * fil_start_point[1] / self.data.get("d_f"))) > tol: # computation is not unique phi_end = pi - phi_end if abs(phi_start - phi_end) > tol: # check if a root circle curve exists delta_phi = (phi_end - phi_start) / (self.points_root - 1) n = 0 for index in range(start_rootcirc_index, end_rootcirc_index): formcoord_array[index] = ( self.data.get("d_f") / 2 * np.array([-sin(phi_start + n * delta_phi), isexternal * cos(phi_start + n * delta_phi)]) ) n += 1 # compute points on root fillet print "Warning: circular root fillet in transverse cross-section assumed!" phi_start = asin( (fil_start_point[0] - fil_center_point[0]) / self.data.get("rho_f") ) # starting angle of root fillet if ( abs(phi_start - acos(-(fil_start_point[1] - fil_center_point[1]) / self.data.get("rho_f"))) > tol ): # computation is not unique phi_start = pi - phi_start phi_end = asin((fil_end_point[0] - fil_center_point[0]) / self.data.get("rho_f")) # end angle of root fillet if ( abs(phi_end - acos(-(fil_end_point[1] - fil_center_point[1]) / self.data.get("rho_f"))) > tol ): # computation is not unique phi_end = pi - phi_end if abs(phi_start - phi_end) > tol: # check if a root fillet curve exists delta_phi = (phi_end - phi_start) / (self.points_fillet - 1) n = 0 for index in range(start_fillet_index, end_fillet_index + 1): formcoord_array[index] = fil_center_point + self.data.get("rho_f") * np.array( [sin(phi_start + n * delta_phi), -isexternal * cos(phi_start + n * delta_phi)] ) n += 1 if (inv_start_point - fil_end_point).any(): # check if a root fillet circle connects directly to flank print "involute was extended" # placeholder for future # compute points on flank d_start = isexternal * norm(inv_start_point, 2) * 2 # start diameter of involute flank (root form diameter) d_end = isexternal * norm(inv_end_point, 2) * 2 # end diameter of involute flank (tip form diameter) delta_d = (d_end - d_start) / (self.points_flank - 1) n = 0 for index in range(start_involute_index, end_involute_index + 1): s_yt, d_yc = self._tooth_thickness(d_start + n * delta_d) formcoord_array[index] = np.array([-s_yt / 2, d_yc / 2]) n += 1 # compute points on tip chamfer if "h_k" in self.data and (self.data.get("h_k") > 0): print "Warning: straight tip chamfer assumed!" delta_k = 1 / (self.points_chamfer - 1) n = 0 for index in range(end_involute_index, end_chamfer_index): formcoord_array[index] = inv_end_point + (tipcirc_start_point - inv_end_point) * n * delta_k n += 1 # compute points on tip circle phi_start = -asin(2 * tipcirc_start_point[0] / self.data.get("d_a")) # starting angle of tip circle if abs(phi_start - acos(2 * tipcirc_start_point[1] / self.data.get("d_a"))) > tol: # computation is not unique phi_start = pi - phi_start phi_end = -asin(2 * tipcirc_end_point[0] / self.data.get("d_a")) # end angle of tip circle if abs(phi_end - acos(2 * tipcirc_end_point[1] / self.data.get("d_a"))) > tol: # computation is not unique phi_end = pi - phi_end if isexternal < 0: phi_end = phi_end + pi if abs(phi_start - phi_end) > tol: # check if a tip circle curve exists delta_phi = (phi_end - phi_start) / (self.points_tip - 1) n = 1 for index in range(end_chamfer_index + 1, end_tipcirc_index): formcoord_array[index] = ( self.data.get("d_a") / 2 * np.array([-sin(phi_start + n * delta_phi), isexternal * cos(phi_start + n * delta_phi)]) ) n += 1 # compute points on tangential extension of involute below base circle if inv_extension: delta_k = 1 / (self.points_ext - 1) for n in range(1, self.points_ext - 1): formcoord_array = insert( formcoord_array, start_involute_index, inv_start_point + (fil_end_point - inv_start_point) * n * delta_k, axis=0, ) self.formcoords = self._make_unique(formcoord_array)
def _make_form_coords(self): """ Tooth form coordinates in transverse cross-section (half tooth and half gap) points returned in 2D-cartesian coordinates, origin on wheel axis old form coordinates (if existend) will be replaced! This method should be used only if no user-supplied form coordinates are present. INPUT parameter: - """ # module imports from scipy.optimize import fsolve from numpy.linalg import norm from numpy import insert # tolerance for comparisons tol = self._tol_default * self.data.get('m_n') # delete old form coordinates if existend if self.formcoords: del self.formcoords if self._formwire: del self._formwire # indicator whether gear is external (number of teeth positive) or internal isexternal = sign(self.data.get('z')) inv_extension = False # indices for adressing parts of tooth form lower_index = 0 start_rootcirc_index = lower_index + 1 # one entry reserved for origin end_rootcirc_index = start_rootcirc_index + self.points_root - 1 start_fillet_index = end_rootcirc_index end_fillet_index = start_fillet_index + self.points_fillet - 1 start_involute_index = end_fillet_index + 1 # can differ from end of fillet end_involute_index = start_involute_index + self.points_flank - 1 start_chamfer_index = end_involute_index + 1 end_chamfer_index = start_chamfer_index + self.points_chamfer - 1 start_tipcirc_index = end_chamfer_index + 1 # differs from end of involute if chamfer present end_tipcirc_index = start_tipcirc_index + self.points_tip - 1 upper_index = end_tipcirc_index # determine boundary of half tooth segment on root circle rootcirc_start_point = self.data.get('d_f') / 2 * np.array([ -sin(radians(self.data.get('tau') / 2)), cos(radians(self.data.get('tau') / 2)) ]) # determine how the root shape is defined and calculate significant points # root shape is circular in transverse cross-section if isexternal > 0: # for external gears if 'd_Ff' not in self.data: # root circle is tangent to involute if (self.data.get('d_f')**2 + 4 * self.data.get('rho_f') * self.data.get('d_f') >= self.data.get('d_b')**2): self.data.update({ 'd_Ff': isexternal * sqrt((sqrt( (self.data.get('d_f') + 2 * self.data.get('rho_f') )**2 - self.data.get('d_b')**2) - 2 * self.data.get('rho_f'))**2 + self.data.get('d_b')**2) }) s_yt, d_yc = self._tooth_thickness(self.data.get('d_Ff')) fil_end_point = np.array([-s_yt / 2, d_yc / 2]) # no tangency possible: undercut elif self.data.get('d_f') + 4 * self.data.get( 'rho_f') >= self.data.get('d_b'): self.data.update({'d_Ff': self.data.get('d_b')}) s_yt, d_yc = self._tooth_thickness(self.data.get('d_b')) fil_end_point = np.array( [-s_yt / 2, d_yc / 2]) # end of involute at base circle print 'Warning: undercutting occurs!' else: self.data.update({'d_Ff': self.data.get('d_b')}) d_tangent = sqrt( self.data.get('d_f')**2 + 4 * self.data.get('rho_f') * self.data.get('d_f') ) # diameter around gear center on that tangency point of fillet curve is located s_yt, d_yc = self._tooth_thickness(self.data.get('d_b')) nu = atan(s_yt / d_yc) fil_end_point = np.array([ -d_tangent / 2 * sin(nu), d_tangent / 2 * cos(nu) ]) # tangential extension of involute beyond base circle print 'Warning: involute had to be extended below base cicle to achieve root fillet tangency!' inv_extension = True else: # if root form circle diameter is supplied, it is forced strictly if possible if ( self.data.get('d_Ff') - self.data.get('d_f') ) / 2 > 2 * self.data.get( 'rho_f' ): # check if root fillet circle fits beetween root form circle and root circle raise ValueError( 'root fillet radius too small: root shape cannot be determined' ) s_yt, d_yc = self._tooth_thickness(self.data.get('d_Ff')) if abs(self.data.get('d_Ff')) >= abs(self.data.get( 'd_b')): # fillet ends at root form circle fil_end_point = np.array([-s_yt / 2, d_yc / 2]) else: # base circle diameter greater than root form diameter: tangential extension of involute nu = atan(s_yt / d_yc) fil_end_point = np.array([ -self.data.get('d_Ff') * sin(nu), self.data.get('d_Ff') * cos(nu) ]) print 'Warning: involute had to be extended below base cicle to enforce root form circle diameter!' inv_extension = True else: # for internal gears if 'd_Ff' not in self.data: # root circle is tangent to involute t_b = sqrt((self.data.get('d_f') / 2 + self.data.get('rho_f'))**2 - (self.data.get('d_b') / 2)**2) self.data.update({ 'd_Ff': -2 * sqrt((t_b + self.data.get('rho_f'))**2 + (self.data.get('d_b') / 2)**2) }) else: # if root form circle diameter is supplied, it is forced strictly if possible if ( self.data.get('d_Ff') - self.data.get('d_f') ) / 2 > 2 * self.data.get( 'rho_f' ): # check if root fillet circle fits beetween root form circle and root circle raise ValueError( 'root fillet radius too small: root shape cannot be determined' ) s_yt, d_yc = self._tooth_thickness(self.data.get('d_Ff')) fil_end_point = np.array([-s_yt / 2, d_yc / 2]) # find center of root fillet circle by cutting circle around fillet end point with radius rho_f # with circle around center of gear wheel with radius d_f/2+rho_f def root_circle_center_func(phi): return fil_end_point + self.data.get('rho_f') * np.array([ sin(phi[0]), cos(phi[0]) ]) - (self.data.get('d_f') / 2 + self.data.get('rho_f') ) * np.array([sin(phi[1]), cos(phi[1])]) phi_fil_center = fsolve(root_circle_center_func, [-pi / 2, 0.0]) fil_center_point = ( self.data.get('d_f') / 2 + self.data.get('rho_f')) * np.array( [sin(phi_fil_center[1]), cos(phi_fil_center[1])]) # boundary point of root fillet and root circle fil_start_point = fil_center_point * self.data.get('d_f') / ( self.data.get('d_f') + 2 * self.data.get('rho_f')) # if boundary point and fillet center are outside half tooth segment the shape of the root fillet # cannot be determined (root fillet curve is not continously differentiable and d_f is not matched) if abs(atan(fil_start_point[0] / fil_start_point[1])) > abs( radians(self.data.get('tau') / 2)): raise ValueError( 'root fillet radius too large: root shape cannot be determined' ) # determine boundary points of involute s_yt, d_yc = self._tooth_thickness(self.data.get('d_Ff')) inv_start_point = np.array([-s_yt / 2, d_yc / 2 ]) # involute starts at root form circle s_yt, d_yc = self._tooth_thickness(self.data.get('d_Fa')) inv_end_point = np.array([-s_yt / 2, d_yc / 2 ]) # involute ends at tip form circle # determine boundary points of tip circle nu = self.data.get('s_aK') / self.data.get('d_a') tipcirc_start_point = np.array([ -self.data.get('d_a') / 2 * sin(nu), self.data.get('d_a') / 2 * cos(nu) ]) # tip circle starts at end of tip chamfer tipcirc_end_point = np.array([0.0, self.data.get('d_a') / 2 ]) # tip circle ends at symmetry line # create array for tooth form coordinates formcoord_array = np.zeros([upper_index, 2]) # compute points on root circle phi_start = -asin( 2 * rootcirc_start_point[0] / self.data.get('d_f')) # starting angle of root circle if abs(phi_start - acos(2 * rootcirc_start_point[1] / self.data.get('d_f'))) > tol: # computation is not unique phi_start = pi - phi_start phi_end = -asin(2 * fil_start_point[0] / self.data.get('d_f')) # end angle of root circle if abs(phi_end - acos(2 * fil_start_point[1] / self.data.get('d_f')) ) > tol: # computation is not unique phi_end = pi - phi_end if abs(phi_start - phi_end) > tol: # check if a root circle curve exists delta_phi = (phi_end - phi_start) / (self.points_root - 1) n = 0 for index in range(start_rootcirc_index, end_rootcirc_index): formcoord_array[index] = self.data.get('d_f') / 2 * np.array([ -sin(phi_start + n * delta_phi), isexternal * cos(phi_start + n * delta_phi) ]) n += 1 # compute points on root fillet print 'Warning: circular root fillet in transverse cross-section assumed!' phi_start = asin( (fil_start_point[0] - fil_center_point[0]) / self.data.get('rho_f')) # starting angle of root fillet if abs(phi_start - acos(-(fil_start_point[1] - fil_center_point[1]) / self.data.get('rho_f')) ) > tol: # computation is not unique phi_start = pi - phi_start phi_end = asin((fil_end_point[0] - fil_center_point[0]) / self.data.get('rho_f')) # end angle of root fillet if abs(phi_end - acos(-(fil_end_point[1] - fil_center_point[1]) / self.data.get('rho_f')) ) > tol: # computation is not unique phi_end = pi - phi_end if abs(phi_start - phi_end) > tol: # check if a root fillet curve exists delta_phi = (phi_end - phi_start) / (self.points_fillet - 1) n = 0 for index in range(start_fillet_index, end_fillet_index + 1): formcoord_array[index] = fil_center_point + self.data.get( 'rho_f') * np.array([ sin(phi_start + n * delta_phi), -isexternal * cos(phi_start + n * delta_phi) ]) n += 1 if (inv_start_point - fil_end_point).any( ): # check if a root fillet circle connects directly to flank print 'involute was extended' # placeholder for future # compute points on flank d_start = isexternal * norm( inv_start_point, 2) * 2 # start diameter of involute flank (root form diameter) d_end = isexternal * norm( inv_end_point, 2) * 2 # end diameter of involute flank (tip form diameter) delta_d = (d_end - d_start) / (self.points_flank - 1) n = 0 for index in range(start_involute_index, end_involute_index + 1): s_yt, d_yc = self._tooth_thickness(d_start + n * delta_d) formcoord_array[index] = np.array([-s_yt / 2, d_yc / 2]) n += 1 # compute points on tip chamfer if 'h_k' in self.data and (self.data.get('h_k') > 0): print 'Warning: straight tip chamfer assumed!' delta_k = 1 / (self.points_chamfer - 1) n = 0 for index in range(end_involute_index, end_chamfer_index): formcoord_array[index] = inv_end_point + ( tipcirc_start_point - inv_end_point) * n * delta_k n += 1 # compute points on tip circle phi_start = -asin(2 * tipcirc_start_point[0] / self.data.get('d_a')) # starting angle of tip circle if abs(phi_start - acos(2 * tipcirc_start_point[1] / self.data.get('d_a'))) > tol: # computation is not unique phi_start = pi - phi_start phi_end = -asin(2 * tipcirc_end_point[0] / self.data.get('d_a')) # end angle of tip circle if abs(phi_end - acos(2 * tipcirc_end_point[1] / self.data.get('d_a')) ) > tol: # computation is not unique phi_end = pi - phi_end if isexternal < 0: phi_end = phi_end + pi if abs(phi_start - phi_end) > tol: # check if a tip circle curve exists delta_phi = (phi_end - phi_start) / (self.points_tip - 1) n = 1 for index in range(end_chamfer_index + 1, end_tipcirc_index): formcoord_array[index] = self.data.get('d_a') / 2 * np.array([ -sin(phi_start + n * delta_phi), isexternal * cos(phi_start + n * delta_phi) ]) n += 1 # compute points on tangential extension of involute below base circle if inv_extension: delta_k = 1 / (self.points_ext - 1) for n in range(1, self.points_ext - 1): formcoord_array = insert( formcoord_array, start_involute_index, inv_start_point + (fil_end_point - inv_start_point) * n * delta_k, axis=0) self.formcoords = self._make_unique(formcoord_array)
def __init__(self, geardata, flankmods=None, formcoords=None): """ Initialization of GearWheel-object. All parameters in accordance to DIN 3960 and DIN 3967. INPUT parameters: z : number of teeth (numeric, integer) m_n : normal module (numeric, positive) d : pitch diameter (numeric) two of the three parameters z, m_n, d, must be supplied b : tooth width (numeric, positive) d_f : root circle diameter (numeric) optional - calculated if not supplied d_a : tip diameter (numeric) optional - calculated if not supplied d_Ff : root form diameter (numeric) optional - will be estimated if not supplied d_Fa : tip form diameter (numeric) optional - set equal da if not supplied (no chamfer) rho_f : fillet radius (numeric) optional - set equal 0.38*mn if not supplied x : addendum modification factor (numeric) optional - set equal 0.0 if not supplied alpha_n : pressure angle (numeric, positive)[degrees] optional - set equal 20.0 if not supplied beta : helix angle (numeric)[degrees] optional - set equal 0.0 if not supplied a : addendum (numeric) optional - no estimation c : tip clearance (numeric, positive, 0.1...0.3*mn) optional - set equal 0.25*mn if not supplied alpha_wt : service pressure angle (numeric, positive)[degrees] optional - calculated from z_2 or d_w d_w : service pitch diameter (numeric) optional - calculated from alpha_wt or z_2 h_k : radial size of tip chamfer (numeric) optional - set equal d_a-d_Fa or 0.0 if not supplied s_aK : remaining tooth thickness at tip, chord-length (numeric) optional - set equal s_a-2*h_k if not supplied z_2 : number of teeth of counter gear (numeric, integer) optional - calculated from alpha_wt or d_w d_s : shaft diameter, inner gear wheel diameter (numeric) optional - set equal 0.0 if not supplied A_s : tooth thickness allowance in normal cross-section (numeric, negative) optional - set equal 0.0 if not supplied All input parameters above are arranged in a dictionary. The keys are the names of the parameters as listed above. formcoords : 2D cartesian coordinates of points on the toothflank, describing a half tooth (TColgp_Array1OfPnt2d, pythonOCC) There are several possibilities for defining a complete gearwheel: 1) z, m_n, b, (beta), formcoords 2) z, m_n, b, (beta), d_f, d_a, d_Ff, d_Fa, rho_f 3) z, m_n, b, (beta), alpha_n, alpha_wt, x, a, rho_f 4) z, m_n, b, (beta), alpha_n, z_2, x, a, rho_f Some parameters can be left out, but the result might differ from your real gear. Missing parameters are estimated if possible. The helix angle beta doesn't have to be supplied for a spur gear. The constructor does not check for unit consistency. The user is responsible for supplying all values with consistent units. """ super(CylindricalGearWheel, self).__init__(geardata) self.data = deepcopy(geardata) self.modifications = deepcopy(flankmods) # form coordinates: value check (at least two points for defining a # tooth form (straight flanks) and two coordinates per point) if formcoords: self.data.update(self._analyze_formcoords()) # module: value check if "m_n" in self.data and not self.data.get("m_n") >= 0: raise ValueError("module non-positive") if "beta" not in self.data: self.data.update({"beta": self._beta_default}) self.data.update( {"alpha_t": degrees(atan(tan(radians(self.data.get("alpha_n"))) / cos(radians(self.data.get("beta")))))} ) self.data.update( { "s_p": (pi * self.data["m_n"] / 2) + 2 * self.data["m_n"] * self.data["x"] * tan(radians(self.data["alpha_n"])) } ) if "tau" in self.data and "z" not in self.data: self.data.update({"z": int(2 * pi / self.data.get("tau"))}) if "z" in self.data and "m_n" in self.data: self.data.update({"d": self.data.get("m_n") * self.data.get("z") / cos(radians(self.data.get("beta")))}) elif "z" in self.data and "d" in self.data: self.data.update({"m_n": self.data.get("d") * cos(radians(self.data.get("beta"))) / self.data.get("z")}) elif "m_n" in self.data and "d" in self.data: self.data.update( {"z": int(self.data.get("d") * cos(radians(self.data.get("beta"))) / self.data.get("m_n"))} ) else: raise AttributeError("insufficient data supplied") if "tau" not in self.data: self.data.update({"tau": degrees(2 * pi / self.data.get("z"))}) isexternal = sign(self.data.get("z")) if not sign(self.data.get("d")) == isexternal: raise ValueError("sign of pitch diameter") self.data.update({"m_t": self.data.get("m_n") / cos(radians(self.data.get("beta")))}) if "alpha_n" in self.data: if self.data.get("alpha_n") < 0: raise ValueError("pitch angle non-positive") else: self.data.update({"alpha_n": self._alpha_n_default}) if "x" not in self.data: self.data.update({"x": self._x_default}) if "A_s" not in self.data: self.data.update({"A_s": self._A_s_default}) # tooth thickness allowance: value check else: if not self.data.get("A_s") <= 0: raise ValueError("tooth thickness allowance positive") self.data.update( { "x_E": self.data.get("x") + self.data.get("A_s") / 2 / tan(radians(self.data.get("alpha_n"))) / self.data.get("m_n") } ) if "d_w" in self.data and "alpha_wt" not in self.data: if not sign(self.data.get("d_w")) == isexternal: raise ValueError("sign of service pitch diameter") self.data.update( { "alpha_wt": degrees( acos(self.data.get("d") / self.data.get("d_w") * cos(radians(self.data.get("alpha_t")))) ) } ) if "alpha_wt" in self.data and "d_w" not in self.data: self.data.update( { "d_w": self.data.get("d") * cos(radians(self.data.get("alpha_t"))) / cos(radians(self.data.get("alpha_wt"))) } ) self.data.update({"d_b": self.data.get("d") * cos(radians(self.data.get("alpha_t")))}) if formcoords: self.data.update(self._analyze_formcoords()) if not formcoords: # tip clearance: value check, set to default if not supplied if "c" in self.data: if self.data.get("c") < 0.1 * self.data.get("m_n") or self.data.get("c") > 0.3 * self.data.get("m_n"): raise ValueError("tip clearance out of bounds") else: self.data.update({"c": self._c_default * self.data.get("m_n")}) # fillet radius: value check, set to default if not supplied if "rho_f" not in self.data: self.data.update({"rho_f": self._rho_f_default * self.data.get("m_n")}) else: if self.data.get("rho_f") < 0: raise ValueError("fillet radius negative") # CAUTION: THE FOLLOWING SECTION OF CODE WILL BE REMOVED IN FUTURE RELEASES! # tool fillet radius: value check if "rho_fP" in self.data: if self.data.get("rho_fP") < 0: raise ValueError("tool fillet radius negative") if not self.data.get("beta") == 0: raise ValueError("fillet trochoid cannot be generated for helical gears") # END OF CODE SECTION TO BE REMOVED # calculate tip height modification factor if possible (else set to default) # various attempts are made if "a" in self.data and "k" not in self.data: self.data.update({"a_d": self.data.get("m_t") * (self.data.get("z") + self.data.get("z_2")) / 2}) self.data.update( { "k": (self.data.get("a") - self.data.get("a_d")) / self.data.get("m_n") - (self.data.get("x") + self.data.get("x_2")) } ) else: self.data.update({"k": self._k_default}) # root circle diameter: value check, calculate if not supplied if "d_f" in self.data: if "d_f" in self.data > "d" in self.data: raise ValueError("root circle diameter greater than pitch diameter") if not sign(self.data.get("d_f")) == isexternal: raise ValueError("sign of root circle diameter") else: self.data.update( { "d_f": self.data.get("d") + 2 * self.data.get("x_E") * self.data.get("m_n") - 2 * (self.data.get("m_n") + self.data.get("c")) } ) # tip diameter: value check, calculate if not supplied if "d_a" in self.data: # if self.data.get('d_a')<self.data.get('d'): # raise ValueError, 'tip diameter less than pitch diameter' if not sign(self.data.get("d_a")) == isexternal: raise ValueError("sign of tip diameter") else: self.data.update( { "d_a": self.data.get("d") + 2 * self.data.get("x") * self.data.get("m_n") + 2 * self.data.get("m_n") + 2 * self.data.get("k") * self.data.get("m_n") } ) # radial value of tip chamfer: value check, calculate or set to default # if not supplied if "h_k" in self.data: if self.data.get("h_k") < 0: raise ValueError("value of tip chamfer negative") elif "d_Fa" in self.data: self.data.update({"h_k": abs(self.data.get("d_a") - self.data.get("d_Fa")) / 2}) else: self.data.update({"h_k": self._h_k_default}) # remaining tooth thickness: value check, set to default if not supplied s_a, d_ac = self._tooth_thickness(self.data.get("d_a")) if "s_aK" not in self.data: self.data.update({"s_aK": s_a - 2 * self.data.get("h_k")}) if self.data.get("s_aK") < 0: raise ValueError("remaining tooth thickness at tip negative") if self.data.get("s_aK") > s_a: raise ValueError("remaining tip tooth thickness greater than tooth thickness") if "d_Ff" in self.data: if self.data.get("d_Ff") > self.data.get("d"): raise ValueError("root form diameter greater than pitch diameter") if self.data.get("d_Ff") < self.data.get("d_f"): raise ValueError("root form diameter less than root circle diameter") if not sign(self.data.get("d_Ff")) == isexternal: raise ValueError("sign of root form diameter") # tip form diameter: value check if "d_Fa" in self.data: if self.data.get("d_Fa") < self.data.get("d"): raise ValueError("tip form diameter less than pitch diameter") if self.data.get("d_Fa") > self.data.get("d_a"): raise ValueError("tip form diameter greater than tip diameter") if not sign(self.data.get("d_Fa")) == isexternal: raise ValueError("sign of tip form diameter") else: self.data.update({"d_Fa": self.data.get("d_a") - 2 * self.data.get("h_k")}) if "d_s" not in self.data: self.data.update({"d_s": self._d_s_default}) if abs(self.data.get("d_s")) > self._tol_default: if not sign(self.data.get("d_s")) == isexternal: raise ValueError("sign of shaft diameter") if not self.data.get("d_s") < self.data.get("d_f"): raise ValueError("shaft diameter greater than root circle diameter") if not self.formcoords: self._make_form_coords() else: self.formcoords = self._make_unique(self.formcoords)
def __init__(self, geardata, flankmods=None, formcoords=None): """ Initialization of GearWheel-object. All parameters in accordance to DIN 3960 and DIN 3967. INPUT parameters: z : number of teeth (numeric, integer) m_n : normal module (numeric, positive) d : pitch diameter (numeric) two of the three parameters z, m_n, d, must be supplied b : tooth width (numeric, positive) d_f : root circle diameter (numeric) optional - calculated if not supplied d_a : tip diameter (numeric) optional - calculated if not supplied d_Ff : root form diameter (numeric) optional - will be estimated if not supplied d_Fa : tip form diameter (numeric) optional - set equal da if not supplied (no chamfer) rho_f : fillet radius (numeric) optional - set equal 0.38*mn if not supplied x : addendum modification factor (numeric) optional - set equal 0.0 if not supplied alpha_n : pressure angle (numeric, positive)[degrees] optional - set equal 20.0 if not supplied beta : helix angle (numeric)[degrees] optional - set equal 0.0 if not supplied a : addendum (numeric) optional - no estimation c : tip clearance (numeric, positive, 0.1...0.3*mn) optional - set equal 0.25*mn if not supplied alpha_wt : service pressure angle (numeric, positive)[degrees] optional - calculated from z_2 or d_w d_w : service pitch diameter (numeric) optional - calculated from alpha_wt or z_2 h_k : radial size of tip chamfer (numeric) optional - set equal d_a-d_Fa or 0.0 if not supplied s_aK : remaining tooth thickness at tip, chord-length (numeric) optional - set equal s_a-2*h_k if not supplied z_2 : number of teeth of counter gear (numeric, integer) optional - calculated from alpha_wt or d_w d_s : shaft diameter, inner gear wheel diameter (numeric) optional - set equal 0.0 if not supplied A_s : tooth thickness allowance in normal cross-section (numeric, negative) optional - set equal 0.0 if not supplied All input parameters above are arranged in a dictionary. The keys are the names of the parameters as listed above. formcoords : 2D cartesian coordinates of points on the toothflank, describing a half tooth (TColgp_Array1OfPnt2d, pythonOCC) There are several possibilities for defining a complete gearwheel: 1) z, m_n, b, (beta), formcoords 2) z, m_n, b, (beta), d_f, d_a, d_Ff, d_Fa, rho_f 3) z, m_n, b, (beta), alpha_n, alpha_wt, x, a, rho_f 4) z, m_n, b, (beta), alpha_n, z_2, x, a, rho_f Some parameters can be left out, but the result might differ from your real gear. Missing parameters are estimated if possible. The helix angle beta doesn't have to be supplied for a spur gear. The constructor does not check for unit consistency. The user is responsible for supplying all values with consistent units. """ super(CylindricalGearWheel, self).__init__(geardata) self.data = deepcopy(geardata) self.modifications = deepcopy(flankmods) # form coordinates: value check (at least two points for defining a # tooth form (straight flanks) and two coordinates per point) if formcoords: self.data.update(self._analyze_formcoords()) # module: value check if 'm_n' in self.data and not self.data.get('m_n') >= 0: raise ValueError('module non-positive') if 'beta' not in self.data: self.data.update({'beta': self._beta_default}) self.data.update({ 'alpha_t': degrees( atan( tan(radians(self.data.get('alpha_n'))) / cos(radians(self.data.get('beta'))))) }) self.data.update({ 's_p': (pi * self.data['m_n'] / 2) + 2 * self.data['m_n'] * self.data['x'] * tan(radians(self.data['alpha_n'])) }) if 'tau' in self.data and 'z' not in self.data: self.data.update({'z': int(2 * pi / self.data.get('tau'))}) if 'z' in self.data and 'm_n' in self.data: self.data.update({ 'd': self.data.get('m_n') * self.data.get('z') / cos(radians(self.data.get('beta'))) }) elif 'z' in self.data and 'd' in self.data: self.data.update({ 'm_n': self.data.get('d') * cos(radians(self.data.get('beta'))) / self.data.get('z') }) elif 'm_n' in self.data and 'd' in self.data: self.data.update({ 'z': int( self.data.get('d') * cos(radians(self.data.get('beta'))) / self.data.get('m_n')) }) else: raise AttributeError('insufficient data supplied') if 'tau' not in self.data: self.data.update({'tau': degrees(2 * pi / self.data.get('z'))}) isexternal = sign(self.data.get('z')) if not sign(self.data.get('d')) == isexternal: raise ValueError('sign of pitch diameter') self.data.update({ 'm_t': self.data.get('m_n') / cos(radians(self.data.get('beta'))) }) if 'alpha_n' in self.data: if self.data.get('alpha_n') < 0: raise ValueError('pitch angle non-positive') else: self.data.update({'alpha_n': self._alpha_n_default}) if 'x' not in self.data: self.data.update({'x': self._x_default}) if 'A_s' not in self.data: self.data.update({'A_s': self._A_s_default}) # tooth thickness allowance: value check else: if not self.data.get('A_s') <= 0: raise ValueError('tooth thickness allowance positive') self.data.update({ 'x_E': self.data.get('x') + self.data.get('A_s') / 2 / tan(radians(self.data.get('alpha_n'))) / self.data.get('m_n') }) if 'd_w' in self.data and 'alpha_wt' not in self.data: if not sign(self.data.get('d_w')) == isexternal: raise ValueError('sign of service pitch diameter') self.data.update({ 'alpha_wt': degrees( acos( self.data.get('d') / self.data.get('d_w') * cos(radians(self.data.get('alpha_t'))))) }) if 'alpha_wt' in self.data and 'd_w' not in self.data: self.data.update({ 'd_w': self.data.get('d') * cos(radians(self.data.get('alpha_t'))) / cos(radians(self.data.get('alpha_wt'))) }) self.data.update({ 'd_b': self.data.get('d') * cos(radians(self.data.get('alpha_t'))) }) if formcoords: self.data.update(self._analyze_formcoords()) if not formcoords: # tip clearance: value check, set to default if not supplied if 'c' in self.data: if self.data.get( 'c') < 0.1 * self.data.get('m_n') or self.data.get( 'c') > 0.3 * self.data.get('m_n'): raise ValueError('tip clearance out of bounds') else: self.data.update({'c': self._c_default * self.data.get('m_n')}) # fillet radius: value check, set to default if not supplied if 'rho_f' not in self.data: self.data.update( {'rho_f': self._rho_f_default * self.data.get('m_n')}) else: if self.data.get('rho_f') < 0: raise ValueError('fillet radius negative') # CAUTION: THE FOLLOWING SECTION OF CODE WILL BE REMOVED IN FUTURE RELEASES! # tool fillet radius: value check if 'rho_fP' in self.data: if self.data.get('rho_fP') < 0: raise ValueError('tool fillet radius negative') if not self.data.get('beta') == 0: raise ValueError( 'fillet trochoid cannot be generated for helical gears' ) # END OF CODE SECTION TO BE REMOVED # calculate tip height modification factor if possible (else set to default) # various attempts are made if 'a' in self.data and 'k' not in self.data: self.data.update({ 'a_d': self.data.get('m_t') * (self.data.get('z') + self.data.get('z_2')) / 2 }) self.data.update({ 'k': (self.data.get('a') - self.data.get('a_d')) / self.data.get('m_n') - (self.data.get('x') + self.data.get('x_2')) }) else: self.data.update({'k': self._k_default}) # root circle diameter: value check, calculate if not supplied if 'd_f' in self.data: if 'd_f' in self.data > 'd' in self.data: raise ValueError( 'root circle diameter greater than pitch diameter') if not sign(self.data.get('d_f')) == isexternal: raise ValueError('sign of root circle diameter') else: self.data.update({ 'd_f': self.data.get('d') + 2 * self.data.get('x_E') * self.data.get('m_n') - 2 * (self.data.get('m_n') + self.data.get('c')) }) # tip diameter: value check, calculate if not supplied if 'd_a' in self.data: # if self.data.get('d_a')<self.data.get('d'): # raise ValueError, 'tip diameter less than pitch diameter' if not sign(self.data.get('d_a')) == isexternal: raise ValueError('sign of tip diameter') else: self.data.update({ 'd_a': self.data.get('d') + 2 * self.data.get('x') * self.data.get('m_n') + 2 * self.data.get('m_n') + 2 * self.data.get('k') * self.data.get('m_n') }) # radial value of tip chamfer: value check, calculate or set to default # if not supplied if 'h_k' in self.data: if self.data.get('h_k') < 0: raise ValueError('value of tip chamfer negative') elif 'd_Fa' in self.data: self.data.update({ 'h_k': abs(self.data.get('d_a') - self.data.get('d_Fa')) / 2 }) else: self.data.update({'h_k': self._h_k_default}) # remaining tooth thickness: value check, set to default if not supplied s_a, d_ac = self._tooth_thickness(self.data.get('d_a')) if 's_aK' not in self.data: self.data.update({'s_aK': s_a - 2 * self.data.get('h_k')}) if self.data.get('s_aK') < 0: raise ValueError('remaining tooth thickness at tip negative') if self.data.get('s_aK') > s_a: raise ValueError( 'remaining tip tooth thickness greater than tooth thickness' ) if 'd_Ff' in self.data: if self.data.get('d_Ff') > self.data.get('d'): raise ValueError( 'root form diameter greater than pitch diameter') if self.data.get('d_Ff') < self.data.get('d_f'): raise ValueError( 'root form diameter less than root circle diameter') if not sign(self.data.get('d_Ff')) == isexternal: raise ValueError('sign of root form diameter') # tip form diameter: value check if 'd_Fa' in self.data: if self.data.get('d_Fa') < self.data.get('d'): raise ValueError( 'tip form diameter less than pitch diameter') if self.data.get('d_Fa') > self.data.get('d_a'): raise ValueError( 'tip form diameter greater than tip diameter') if not sign(self.data.get('d_Fa')) == isexternal: raise ValueError('sign of tip form diameter') else: self.data.update( {'d_Fa': self.data.get('d_a') - 2 * self.data.get('h_k')}) if 'd_s' not in self.data: self.data.update({'d_s': self._d_s_default}) if abs(self.data.get('d_s')) > self._tol_default: if not sign(self.data.get('d_s')) == isexternal: raise ValueError('sign of shaft diameter') if not self.data.get('d_s') < self.data.get('d_f'): raise ValueError( 'shaft diameter greater than root circle diameter') if not self.formcoords: self._make_form_coords() else: self.formcoords = self._make_unique(self.formcoords)