Skip to content

Commit 5846ffb

Browse files
committed
connector: add support for shifted gears
1 parent 7edc50c commit 5846ffb

File tree

2 files changed

+35
-24
lines changed

2 files changed

+35
-24
lines changed

freecad/gears/connector.py

+12-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import FreeCAD
2323
from pygears import __version__
2424
from .features import InvoluteGear
25+
from pygears.computation import compute_shifted_gears
2526

2627
class ViewProviderGearConnector(object):
2728
def __init__(self, vobj, icon_fn=None):
@@ -66,8 +67,18 @@ def onChanged(self, fp, prop):
6667
angle_master = fp.master_gear.Placement.Rotation.Angle
6768
dw_master = fp.master_gear.dw
6869
dw_slave = fp.slave_gear.dw
70+
dist = (dw_master + dw_slave) / 2
71+
if fp.master_gear.shift != 0 or fp.slave_gear.shift != 0:
72+
dist, alpha_w = compute_shifted_gears(
73+
fp.master_gear.module,
74+
np.deg2rad(fp.master_gear.pressure_angle.Value),
75+
fp.master_gear.teeth,
76+
fp.slave_gear.teeth,
77+
fp.master_gear.shift,
78+
fp.slave_gear.shift)
79+
6980
mat0 = FreeCAD.Matrix() # unity matrix
70-
trans = FreeCAD.Vector(dw_master + dw_slave) / 2
81+
trans = FreeCAD.Vector(dist)
7182
mat0.move(trans)
7283
rot = FreeCAD.Rotation(FreeCAD.Vector(0,0,1), fp.angle1).toMatrix()
7384
angle2 = dw_master / dw_slave * fp.angle1.Value

pygears/computation.py

+23-23
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
# ***************************************************************************
1818

1919
import numpy as np
20-
from scipy import optimize as opt
2120

2221

2322
def compute_shifted_gears(m, alpha, t1, t2, x1, x2):
@@ -34,31 +33,32 @@ def compute_shifted_gears(m, alpha, t1, t2, x1, x2):
3433
Returns:
3534
(float, float): distance between gears [length], pressure angle of the assembly [rad]
3635
"""
37-
def inv(x): return np.tan(x) - x
38-
inv_alpha_w = inv(alpha) + 2 * np.tan(alpha) * (x1 + x2) / (t1 + t2)
36+
def inv(x):
37+
return np.tan(x) - x
3938

40-
def root_inv(x): return inv(x) - inv_alpha_w
41-
alpha_w = opt.fsolve(root_inv, 0.)
42-
dist = m * (t1 + t2) / 2 * np.cos(alpha) / np.cos(alpha_w)
43-
return dist, alpha_w
39+
inv_alpha_w = inv(alpha) + 2 * np.tan(alpha) * (x1 + x2) / (t1 + t2)
4440

41+
def root_inv(x):
42+
return inv(x) - inv_alpha_w
4543

46-
def shifted_pitch_diameter(m, alpha, t1, x1):
47-
"""Summary
44+
def d_root_inv(x):
45+
return 1. / np.cos(x) - 1
4846

49-
Args:
50-
m (float): common module of both gears [length]
51-
alpha (float): pressure-angle [rad]
52-
t1 (int): number of teeth of gear1
53-
x1 (float): relative profile-shift of gear1
47+
alpha_w = find_root(alpha, root_inv, d_root_inv)
48+
dist = m * (t1 + t2) / 2 * np.cos(alpha) / np.cos(alpha_w)
49+
return dist, alpha_w
5450

55-
Returns:
56-
(float, float): distance between gears [length], pressure angle of the assembly [rad]
57-
"""
58-
def inv(x): return np.tan(x) - x
59-
inv_alpha_w = inv(alpha) + 2 * np.tan(alpha) * x1 / t1
6051

61-
def root_inv(x): return inv(x) - inv_alpha_w
62-
alpha_w = opt.fsolve(root_inv, 0.)
63-
pitch_diameter = m * t1 * np.cos(alpha) / np.cos(alpha_w)
64-
return pitch_diameter, alpha_w
52+
def find_root(x0, f, df, epsilon=2e-10, max_iter=100):
53+
x_n = x0
54+
for i in range(max_iter):
55+
f_xn = f(x_n)
56+
if abs(f_xn) < epsilon:
57+
return x_n
58+
else:
59+
df_xn = df(x_n)
60+
if df_xn == 0:
61+
return None
62+
else:
63+
x_n = x_n - f_xn / df_xn / 2 # adding (/ 2) to avoid oscillation
64+
return None

0 commit comments

Comments
 (0)