Files
gears/gearfunc/_bevel_tooth.py
2015-10-28 14:13:22 +01:00

170 lines
9.4 KiB
Python

# -*- coding: utf-8 -*-
#***************************************************************************
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* This program is distributed in the hope that it will be useful, *
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
#* GNU Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
from __future__ import division
from __future__ import division
from numpy import cos, sin, tan, arccos, arctan, pi, array, linspace, transpose, vstack, sqrt
import numpy as np
from _functions import rotation3D, reflection3D, intersection_line_circle
class bevel_tooth(object):
def __init__(self, pressure_angle=70 * pi / 180, pitch_angle=pi / 4, clearance=0.1,
z=21, backlash=0.00, module=0.25):
self.pressure_angle = pressure_angle
self.pitch_angle = pitch_angle
self.z = z
self.clearance = clearance
self.backlash = backlash
self.module = module
self.involute_end = arccos(
1 / sqrt(2) * sqrt((42. + 16.*cos(2.*self.pressure_angle) +
6.*cos(4.*self.pressure_angle) + cos(4.*self.pressure_angle - 4.*self.pitch_angle) - 8.*cos(2.*self.pressure_angle - 2.*self.pitch_angle) -
4.*cos(4.*self.pressure_angle - 2.*self.pitch_angle) + 24.*cos(2.*self.pitch_angle) - 2.*cos(4.*self.pitch_angle) -
8.*cos(2.*(self.pressure_angle + self.pitch_angle)) + cos(4.*(self.pressure_angle + self.pitch_angle)) -
4.*cos(4.*self.pressure_angle + 2.*self.pitch_angle) + 24.*cos((4.*sin(self.pitch_angle))/self.z) +
4.*cos(2.*self.pressure_angle - (4.*sin(self.pitch_angle))/self.z) + 4.*cos(2.*self.pressure_angle -
4.*self.pitch_angle - (4.*sin(self.pitch_angle))/self.z) - 8.*cos(2.*self.pressure_angle - 2.*self.pitch_angle -
(4.*sin(self.pitch_angle))/self.z) + 24.*cos(4.*(self.pitch_angle + sin(self.pitch_angle)/self.z)) -
8.*cos(2.*(self.pressure_angle + self.pitch_angle + (2.*sin(self.pitch_angle))/self.z)) + 4.*cos(2.*self.pressure_angle +
(4.*sin(self.pitch_angle))/self.z) + 16.*cos(2.*self.pitch_angle + (4.*sin(self.pitch_angle))/self.z) +
4.*cos(2.*self.pressure_angle + 4.*self.pitch_angle + (4.*sin(self.pitch_angle))/self.z) + 32.*abs(cos(self.pitch_angle +
(2.*sin(self.pitch_angle))/self.z))*cos(self.pressure_angle)*sqrt(4.*cos(2.*self.pressure_angle) -
2.*(-2. + cos(2.*self.pressure_angle - 2.*self.pitch_angle) - 2.*cos(2.*self.pitch_angle) + cos(2.*(self.pressure_angle + self.pitch_angle)) +
4.*cos(2.*self.pitch_angle + (4.*sin(self.pitch_angle))/self.z)))*sin(2.*self.pitch_angle))/(-6. - 2.*cos(2.*self.pressure_angle) +
cos(2.*self.pressure_angle - 2.*self.pitch_angle) - 2.*cos(2.*self.pitch_angle) + cos(2.*(self.pressure_angle + self.pitch_angle)))**2))
self.involute_start = -pi/2. + arctan(1/tan(self.pitch_angle)*1/cos(self.pressure_angle))
self.involute_start_radius = self.get_radius(self.involute_start)
self.r_f = sin(self.pitch_angle - sin(pitch_angle) * 2 / self.z) - self.clearance * sin(self.pitch_angle)
self.z_f = cos(self.pitch_angle - sin(pitch_angle) * 2 / self.z)
self.add_foot = True
# if self.involute_start_radius < self.r_f:
# self.add_foot = False
# self.involute_start = -arccos(
# sqrt((42 + 16*cos(2*self.pressure_angle) + 6*cos(4*self.pressure_angle) -
# 4*cos(4*self.pressure_angle - 2*self.pitch_angle) - 8*cos(2*(self.pressure_angle - self.pitch_angle)) +
# cos(4*(self.pressure_angle - self.pitch_angle)) + 24*cos(2*self.pitch_angle) - 2*cos(4*self.pitch_angle) -
# 8*cos(2*(self.pressure_angle + self.pitch_angle)) + cos(4*(self.pressure_angle + self.pitch_angle)) -
# 4*cos(2*(2*self.pressure_angle + self.pitch_angle)) + 24*cos((4*sin(self.pitch_angle))/self.z) +
# 4*cos(2*self.pressure_angle - (4*sin(self.pitch_angle))/self.z) + 16*cos(2*self.pitch_angle -
# (4*sin(self.pitch_angle))/self.z) + 24*cos(4*self.pitch_angle - (4*sin(self.pitch_angle))/self.z) +
# 4*cos(2*self.pressure_angle + 4*self.pitch_angle - (4*sin(self.pitch_angle))/self.z) -
# 8*cos(2*(self.pressure_angle + self.pitch_angle - (2*sin(self.pitch_angle))/self.z)) +
# 4*cos(2*self.pressure_angle + (4*sin(self.pitch_angle))/self.z) + 4*cos(2*self.pressure_angle -
# 4*self.pitch_angle + (4*sin(self.pitch_angle))/self.z) - 8*cos(2*self.pressure_angle - 2*self.pitch_angle +
# (4*sin(self.pitch_angle))/self.z) + 32*sqrt(2)*sqrt(-(cos(self.pressure_angle)**2*
# (-2 - 2*cos(2*self.pressure_angle) + cos(2*(self.pressure_angle - self.pitch_angle)) -
# 2*cos(2*self.pitch_angle) + cos(2*(self.pressure_angle + self.pitch_angle)) +
# 4*cos(2*self.pitch_angle - (4*sin(self.pitch_angle))/self.z))*cos(self.pitch_angle - (2*sin(self.pitch_angle))/self.z)**2*
# sin(2*self.pitch_angle)**2)))/(-6 - 2*cos(2*self.pressure_angle) + cos(2*(self.pressure_angle - self.pitch_angle)) -
# 2*cos(2*self.pitch_angle) + cos(2*(self.pressure_angle + self.pitch_angle)))**2)/sqrt(2))
def involute_function_x(self):
def func(s):
return((
-(cos(s*1/sin(self.pressure_angle)*1/sin(self.pitch_angle))*sin(self.pressure_angle)*sin(s)) +
(cos(s)*sin(self.pitch_angle) + cos(self.pressure_angle)*cos(self.pitch_angle)*sin(s))*
sin(s*1/sin(self.pressure_angle)*1/sin(self.pitch_angle))))
return(func)
def involute_function_y(self):
def func(s):
return((
cos(s*1/sin(self.pressure_angle)*1/sin(self.pitch_angle))*(cos(s)*sin(self.pitch_angle) +
cos(self.pressure_angle)*cos(self.pitch_angle)*sin(s)) + sin(self.pressure_angle)*sin(s)*
sin(s*1/sin(self.pressure_angle)*1/sin(self.pitch_angle))))
return(func)
def involute_function_z(self):
def func(s):
return((
cos(self.pitch_angle)*cos(s) - cos(self.pressure_angle)*sin(self.pitch_angle)*sin(s)))
return(func)
def get_radius(self, s):
x = self.involute_function_x()
y = self.involute_function_y()
rx = x(s)
ry = y(s)
return(sqrt(rx**2 + ry**2))
def involute_points(self, num=10):
pts = linspace(self.involute_start, self.involute_end, num=num)
fx = self.involute_function_x()
x = array(map(fx, pts))
fy = self.involute_function_y()
y = array(map(fy, pts))
fz = self.involute_function_z()
z = array(map(fz, pts))
xyz = transpose(array([x, y, z]))
# conical projection to z=1
xy = [[i[0] / i[2], i[1] / i[2]] for i in xyz]
xy = array([[0, 0]] + xy)
r_cut = self.r_f / self.z_f
for i, point in enumerate(xy[1:]):
if point.dot(point) >= r_cut ** 2:
break
if i > 0:
self.add_foot = False
intersection_point = intersection_line_circle(xy[i], point, r_cut)
xy = array([intersection_point] + list(xy[i+1:]))
xyz = [[p[0], p[1], 1] for p in xy]
backlash_rot = rotation3D(self.backlash / 4)
xyz = backlash_rot(xyz)
return(xyz)
def points(self, num=10):
pts = self.involute_points(num=num)
rot = rotation3D(-pi/self.z/2)
pts = rot(pts)
ref = reflection3D(pi/2)
pts1 = ref(pts)[::-1]
rot = rotation3D(2*pi/self.z)
if self.add_foot:
return(array([
[pts[0], pts[1]],
pts[1:],
[pts[-1], pts1[0]],
pts1[:-1],
[pts1[-2], pts1[-1]]
]))
else:
return(array([pts, [pts[-1], pts1[0]], pts1]))
def _update(self):
self.__init__(z=self.z, clearance=self.clearance,
pressure_angle=self.pressure_angle,
pitch_angle=self.pitch_angle,
backlash=self.backlash, module=self.module)
if __name__ == "__main__":
from matplotlib import pyplot
gear = bevel_tooth(z=60, clearance=0.0, pitch_angle=np.deg2rad(45))
x, y, z = gear.involute_points().T
pyplot.plot(x, y)
pyplot.show()