diff --git a/cq_gears/__init__.py b/cq_gears/__init__.py index c99ced4..30bc011 100644 --- a/cq_gears/__init__.py +++ b/cq_gears/__init__.py @@ -17,7 +17,7 @@ ''' -__version__='0.6' +__version__='0.62' import cadquery as cq from .spur_gear import SpurGear, HerringboneGear diff --git a/cq_gears/bevel_gear.py b/cq_gears/bevel_gear.py index db590f1..ab4bea9 100644 --- a/cq_gears/bevel_gear.py +++ b/cq_gears/bevel_gear.py @@ -29,6 +29,8 @@ class BevelGear(GearBase): + surface_splines = 12 + def __init__(self, module, teeth_number, cone_angle, face_width, pressure_angle=20.0, helix_angle=0.0, clearance=0.0, backlash=0.0, **build_params): @@ -70,6 +72,8 @@ def __init__(self, module, teeth_number, cone_angle, face_width, self.surface_splines = 2 self.twist_angle = 0.0 + assert np.isnan(self.twist_angle) == False, 'Twist angle is NaN' + self.build_params = build_params # The distance between the cone apex and the bottom of the gear @@ -164,9 +168,12 @@ def _build_tooth_faces(self): ta1 = -(pc_f - self.gs_r) / self.face_width * self.twist_angle ta2 = (self.gs_r - tc_f) / self.face_width * self.twist_angle + surf_splines = int(np.ceil(abs(self.twist_angle) / (np.pi * 2.0))) + surf_splines = max(1, surf_splines) * self.surface_splines + # Transformation parameters: (radius, twist angle) spline_tf = np.linspace((pc_f, ta1), (tc_f - 0.01, ta2), - self.surface_splines) + surf_splines) tcp_size = tc_rb * 1000.0 top_cut_plane = cq.Face.makePlane(length=tcp_size, width=tcp_size, @@ -299,7 +306,7 @@ def _make_bore(self, body, bore_d): return body.val() - def _build(self, bore_d=None, trim_bottom=True, trim_top=True): + def _build(self, bore_d=None, trim_bottom=True, trim_top=True, **kv_args): faces = self._build_gear_faces() shell = make_shell(faces) @@ -326,6 +333,9 @@ def _build(self, bore_d=None, trim_bottom=True, trim_top=True): class BevelGearPair(GearBase): gear_cls = BevelGear + + asm_gear_color = 'goldenrod' + asm_pinion_color = 'lightsteelblue' def __init__(self, module, gear_teeth, pinion_teeth, face_width, axis_angle=90.0, pressure_angle=20.0, helix_angle=0.0, @@ -352,44 +362,60 @@ def __init__(self, module, gear_teeth, pinion_teeth, face_width, self.build_params = build_params - def _build(self, gear=True, pinion=True, transform_pinion=True, - gear_build_args={}, pinion_build_args={}, **kv_args): + def assemble(self, build_gear=True, build_pinion=True, + transform_pinion=True, gear_build_args={}, + pinion_build_args={}, **kv_args): - gearset = cq.Workplane('XY') + gearset = cq.Assembly(name='bevel_pair') + + if build_gear: + if 'gear_build_args' in self.build_params: + in_args = self.build_params['gear_build_args'] + else: + in_args = {} + + args = {**self.build_params, + **in_args, + **kv_args, + **gear_build_args} - if gear: - args = {**kv_args, **gear_build_args} gear = self.gear.build(**args) + gearset.add(gear, name='gear', loc=cq.Location(), + color=cq.Color(self.asm_gear_color)) + + if build_pinion: + if 'pinion_build_args' in self.build_params: + in_args = self.build_params['pinion_build_args'] + else: + in_args = {} - gearset.add(gear) + args = {**self.build_params, + **in_args, + **kv_args, + **pinion_build_args} - if pinion: - args = {**kv_args, **pinion_build_args} pinion = self.pinion.build(**args) - if transform_pinion: - dist = -self.pinion.cone_h + self.gear.cone_h - angle = np.pi / 2.0 - self.axis_angle + loc = cq.Location() - if self.pinion.z % 2 == 0: - pinion = pinion.rotate( - (0.0, 0.0, 0.0), - (0.0, 0.0, 1.0), - np.degrees(np.pi / self.pinion.z)) - - pinion = (pinion - .rotate((0.0, -1.0, self.gear.cone_h), - (0.0, 1.0, self.gear.cone_h), + if transform_pinion: + loc *= cq.Location(cq.Vector(0.0, 0.0, self.gear.cone_h), + cq.Vector(0.0, 1.0, 0.0), np.degrees(self.axis_angle)) - .translate((dist * np.cos(angle), - 0.0, - dist * np.sin(angle)))) + + loc *= cq.Location(cq.Vector((0.0, 0.0, -self.pinion.cone_h))) + + if self.pinion.z % 2 == 0: + loc *= cq.Location(cq.Vector(0.0, 0.0, 0.0), + cq.Vector(0.0, 0.0, 1.0), + np.degrees(np.pi / self.pinion.z)) + + gearset.add(pinion, name='pinion', loc=loc, + color=cq.Color(self.asm_pinion_color)) - gearset.add(pinion) + return gearset - gearset = gearset.vals() - - if len(gearset) == 1: - return gearset[0] - return cq.Compound.makeCompound(gearset) + def _build(self, *args, **kv_args): + asm = self.assemble(*args, **kv_args) + return asm.toCompound() diff --git a/cq_gears/crossed_helical_gear.py b/cq_gears/crossed_helical_gear.py index 1b4cf1c..7a3c87a 100644 --- a/cq_gears/crossed_helical_gear.py +++ b/cq_gears/crossed_helical_gear.py @@ -123,6 +123,8 @@ class CrossedGearPair(GearBase): gear1_cls = CrossedHelicalGear gear2_cls = CrossedHelicalGear + asm_gear1_color = 'goldenrod' + asm_gear2_color = 'lightsteelblue' def __init__(self, module, gear1_teeth_number, gear2_teeth_number, gear1_width, gear2_width, pressure_angle=20.0, @@ -148,52 +150,59 @@ def __init__(self, module, gear1_teeth_number, gear2_teeth_number, helix_angle=g2_helix, clearance=clearance, backlash=backlash) - self.shaft_angle = shaft_angle + self.shaft_angle = np.radians(shaft_angle) self.build_params = build_params + + + def assemble(self, build_gear1=True, build_gear2=True, transform_gear2=True, + gear1_build_args={}, gear2_build_args={}, **kv_args): - - def _build(self, gear1=True, gear2=True, transform_gear2=True, - gear1_build_args={}, gear2_build_args={}, **kv_args): - - gearset = cq.Workplane('XY') - - if gear1: + gearset = cq.Assembly(name='crossed_pair') + + if build_gear1: args = {**self.build_params, **kv_args, **gear1_build_args} gear1 = self.gear1.build(**args) - gearset = gearset.add(gear1) - - if gear2: + gearset.add(gear1, name='gear1', loc=cq.Location(), + color=cq.Color(self.asm_gear1_color)) + + if build_gear2: args = {**self.build_params, **kv_args, **gear2_build_args} gear2 = self.gear2.build(**args) if transform_gear2: - ratio = self.gear1.z / self.gear2.z - align_angle = 0.0 if self.gear2.z % 2 else 180.0 / self.gear2.z + align_angle = 0.0 if self.gear2.z % 2 else 180.0 / self.gear2.z align_angle += np.degrees(self.gear2.twist_angle + \ self.gear1.twist_angle * ratio) / 2.0 - - gear2 = (gear2 - .rotate((0.0, 0.0, 0.0), (0.0, 0.0, 1.0), align_angle) - .translate((0.0, 0.0, (self.gear1.width - \ - self.gear2.width) / 2.0)) - .rotate((0.0, 0.0, self.gear1.width / 2.0), - (1.0, 0.0, self.gear1.width / 2.0), - self.shaft_angle) - .translate((self.gear1.r0 + self.gear2.r0, 0.0, 0.0))) - - gearset = gearset.add(gear2) - gearset = gearset.vals() - - if len(gearset) == 1: - return gearset[0] - - return cq.Compound.makeCompound(gearset) + loc = cq.Location(cq.Vector(self.gear1.r0 + self.gear2.r0, + 0.0, + self.gear1.width / 2.0)) + loc *= cq.Location(cq.Vector(0.0, 0.0, 0.0), + cq.Vector(1.0, 0.0, 0.0), + np.degrees(self.shaft_angle)) + loc *= cq.Location(cq.Vector(0.0, 0.0, -self.gear2.width / 2.0)) + loc *= cq.Location(cq.Vector(0.0, 0.0, 0.0), + cq.Vector(0.0, 0.0, 1.0), + align_angle) + + else: + loc = cq.Loaction() + + gearset.add(gear2, name='gear2', loc=loc, + color=cq.Color(self.asm_gear2_color)) + + return gearset + + + def _build(self, *args, **kv_args): + asm = self.assemble(*args, **kv_args) + return asm.toCompound() class HyperbolicGear(SpurGear): + surface_splines = 2 def __init__(self, module, teeth_number, width, twist_angle, @@ -220,6 +229,8 @@ def __init__(self, module, teeth_number, width, twist_angle, class HyperbolicGearPair(GearBase): gear_cls = HyperbolicGear + asm_gear1_color = 'goldenrod' + asm_gear2_color = 'lightsteelblue' def __init__(self, module, gear1_teeth_number, width, shaft_angle, gear2_teeth_number=None, pressure_angle=20.0, @@ -238,8 +249,8 @@ def __init__(self, module, gear1_teeth_number, width, shaft_angle, gear2_twist_angle = np.arcsin(hh / g2_r0) * 2.0 if np.isnan(gear1_twist_angle) or np.isnan(gear2_twist_angle): - raise ValueError('Impossible to calculate a twist angle for the ' - 'given shaft angle/teeth number/gear width') + raise ValueError('Impossible to calculate the twist angle for the ' + 'given shaft angle / teeth number / gear width') self.shaft_angle = np.radians(shaft_angle) @@ -256,17 +267,18 @@ def __init__(self, module, gear1_teeth_number, width, shaft_angle, backlash=backlash) self.build_params = build_params - - def _build(self, build_gear1=True, build_gear2=True, transform_gear2=True, - gear1_build_args={}, gear2_build_args={}, **kv_args): - - gearset = cq.Workplane('XY') - + + def assemble(self, build_gear1=True, build_gear2=True, transform_gear2=True, + gear1_build_args={}, gear2_build_args={}, **kv_args): + + gearset = cq.Assembly(name='hyperbolic_pair') + if build_gear1: args = {**self.build_params, **kv_args, **gear1_build_args} gear1 = self.gear1.build(**args) - gearset = gearset.add(gear1) - + gearset.add(gear1, name='gear1', loc=cq.Location(), + color=cq.Color(self.asm_gear1_color)) + if build_gear2: args = {**self.build_params, **kv_args, **gear2_build_args} gear2 = self.gear2.build(**args) @@ -277,20 +289,27 @@ def _build(self, build_gear1=True, build_gear2=True, transform_gear2=True, align_angle = 0.0 if self.gear2.z % 2 else 180.0 / self.gear2.z align_angle += np.degrees(self.gear2.twist_angle + \ self.gear1.twist_angle * ratio) / 2.0 + + loc = cq.Location(cq.Vector(self.gear1.throat_r + \ + self.gear2.throat_r, + 0.0, + self.gear1.width / 2.0)) + loc *= cq.Location(cq.Vector(0.0, 0.0, 0.0), + cq.Vector(1.0, 0.0, 0.0), + np.degrees(self.shaft_angle)) + loc *= cq.Location(cq.Vector(0.0, 0.0, -self.gear2.width / 2.0)) + loc *= cq.Location(cq.Vector(0.0, 0.0, 0.0), + cq.Vector(0.0, 0.0, 1.0), + align_angle) + else: + loc = cq.Location() + + gearset.add(gear2, name='gear2', loc=loc, + color=cq.Color(self.asm_gear2_color)) + + return gearset + - gear2 = (gear2 - .rotate((0.0, 0.0, 0.0), (0.0, 0.0, 1.0), align_angle) - .rotate((0.0, 0.0, self.gear1.width / 2.0), - (1.0, 0.0, self.gear1.width / 2.0), - np.degrees(self.shaft_angle)) - .translate((self.gear1.throat_r + self.gear2.throat_r, - 0.0, 0.0))) - - gearset = gearset.add(gear2) - - gearset = gearset.vals() - - if len(gearset) == 1: - return gearset[0] - - return cq.Compound.makeCompound(gearset) + def _build(self, *args, **kv_args): + asm = self.assemble(*args, **kv_args) + return asm.toCompound() diff --git a/cq_gears/ring_gear.py b/cq_gears/ring_gear.py index 5f40c9b..45950f1 100644 --- a/cq_gears/ring_gear.py +++ b/cq_gears/ring_gear.py @@ -168,7 +168,7 @@ def _build_gear_faces(self): return wp.vals() - def _build(self): + def _build(self, *args, **kv_args): faces = self._build_gear_faces() shell = make_shell(faces) @@ -195,6 +195,10 @@ class PlanetaryGearset(GearBase): gear_cls = SpurGear ring_gear_cls = RingGear + asm_sun_color = 'gold' + asm_planet_color = 'lightsteelblue' + asm_ring_color = 'goldenrod' + def __init__(self, module, sun_teeth_number, planet_teeth_number, width, rim_width, n_planets, pressure_angle=20.0, helix_angle=0.0, clearance=0.0, backlash=0.0, **build_params): @@ -232,56 +236,88 @@ def __init__(self, module, sun_teeth_number, planet_teeth_number, width, self.build_params = build_params - def _build(self, sun=True, planets=True, ring=True, - sun_build_args={}, planet_build_args={}, **kv_args): + def _build(self, *args, **kv_args): + asm = self.assemble(*args, **kv_args) + return asm.toCompound() - gearset = cq.Workplane('XY') - if sun: - args = {**kv_args, **sun_build_args} - sun = self.sun.build(**args) + def assemble(self, build_sun=True, build_planets=True, build_ring=True, + sun_build_args={}, planet_build_args={}, + ring_build_args={}, **kv_args): + + gearset = cq.Assembly(name='planetary') + + if build_sun: + if 'sun_build_args' in self.build_params: + in_args = self.build_params['sun_build_args'] + else: + in_args = {} + args = {**self.build_params, + **in_args, + **kv_args, + **sun_build_args} + + sun = self.sun.build(**args) + if (self.planet.z % 2) != 0: - sun = sun.rotate((0.0, 0.0, 0.0), (0.0, 0.0, 1.0), - np.degrees(self.sun.tau / 2.0)) - gearset.add(sun) + loc = cq.Location(cq.Vector(0.0, 0.0, 0.0), + cq.Vector(0.0, 0.0, 1.0), + np.degrees(self.sun.tau / 2.0)) + else: + loc = cq.Location() + + gearset.add(sun, name='sun', loc=loc, + color=cq.Color(self.asm_sun_color)) - if planets and self.n_planets > 0: + if build_planets and self.n_planets > 0: planet_a = np.pi * 2.0 / self.n_planets - if isinstance(planets, (list, tuple)): - tobuild = planets + if isinstance(build_planets, (list, tuple)): + tobuild = build_planets else: tobuild = [True, ] * self.n_planets - args = {**kv_args, **planet_build_args} + + if 'planet_build_args' in self.build_params: + in_args = self.build_params['planet_build_args'] + else: + in_args = {} + + args = {**self.build_params, + **in_args, + **kv_args, + **planet_build_args} planet_body = self.planet.build(**args) + + planets = cq.Assembly(name='planets') - for i in range(self.n_planets): - if not tobuild[i]: + for i, bld in enumerate(tobuild): + if not bld: continue - planet = (planet_body - .rotate((0.0, 0.0, 0.0), (0.0, 0.0, 1.0), + loc = cq.Location(cq.Vector(np.cos(i * planet_a) * self.orbit_r, + np.sin(i * planet_a) * self.orbit_r, + 0.0), + cq.Vector(0.0, 0.0, 1.0), np.degrees(self.planet.tau / 2.0)) - .translate((np.cos(i * planet_a) * self.orbit_r, - np.sin(i * planet_a) * self.orbit_r, - 0.0))) - gearset.add(planet) - - if ring: - ring = (self.ring.build() - .rotate((0.0, 0.0, 0.0), (0.0, 0.0, 1.0), - np.degrees(self.ring.tau / 2.0))) - gearset.add(ring) - - gearset = gearset.vals() - - if len(gearset) == 1: - return gearset[0] + + planets.add(planet_body, name=f'planet_{i:02}', loc=loc, + color=cq.Color(self.asm_planet_color)) + gearset.add(planets) - return cq.Compound.makeCompound(gearset) + if build_ring: + args = ring_build_args + + ring = self.ring.build(**args) + loc = cq.Location(cq.Vector(0.0, 0.0, 0.0), + cq.Vector(0.0, 0.0, 1.0), + np.degrees(self.ring.tau / 2.0)) + gearset.add(ring, name='ring', loc=loc, + color=cq.Color(self.asm_ring_color)) + + return gearset class HerringbonePlanetaryGearset(PlanetaryGearset): diff --git a/cq_gears/spur_gear.py b/cq_gears/spur_gear.py index cd45911..fdab755 100644 --- a/cq_gears/spur_gear.py +++ b/cq_gears/spur_gear.py @@ -161,11 +161,13 @@ def gear_points(self): def _build_tooth_faces(self, twist_angle_a, twist_angle_b, z_pos, width): - + surf_splines = int(np.ceil(abs(self.twist_angle) / (np.pi * 2.0))) + surf_splines = max(1, surf_splines) * self.surface_splines + # Spline transformation parameters: (angle around z-axis, z-pos) spline_tf = np.linspace((twist_angle_a, z_pos), (twist_angle_b, z_pos + width), - self.surface_splines) + surf_splines) t_faces = [] for spline in (self.t_lflank_pts, self.t_tip_pts, @@ -369,31 +371,84 @@ def _make_spokes(self, body, spokes_id, spokes_od, n_spokes, return body.val() + def _make_chamfer(self, body, chamfer=None, chamfer_top=None, + chamfer_bottom=None): + E = 0.01 + + if chamfer is None and chamfer_top is None and chamfer_bottom is None: + return body + + if chamfer is not None: + if chamfer_top is None: + chamfer_top = chamfer + if chamfer_bottom is None: + chamfer_bottom = chamfer + + if chamfer_top is not None: + if isinstance(chamfer_top, (list, tuple)): + wx, wy = chamfer_top + else: + wx, wy = chamfer_top, chamfer_top + + cutter = (cq.Workplane('XZ') + .moveTo(self.ra - wx, self.width + E) + .hLine(wx + E) + .vLine(-wy - E) + .close() + .revolve()) + + body = (cq.Workplane('XY') + .add(body) + .cut(cutter)) + + if chamfer_bottom is not None: + if isinstance(chamfer_bottom, (list, tuple)): + wx, wy = chamfer_bottom + else: + wx, wy = chamfer_bottom, chamfer_bottom + + cutter = (cq.Workplane('XZ') + .moveTo(self.ra + E, wy) + .vLine(-wy - E) + .hLine(-wx - E) + .close() + .revolve()) + + body = (cq.Workplane('XY') + .add(body) + .cut(cutter)) + + + return body.val() + + def _build(self, bore_d=None, missing_teeth=None, hub_d=None, hub_length=None, recess_d=None, recess=None, n_spokes=None, spoke_width=None, spoke_fillet=None, - spokes_id=None, spokes_od=None): - faces = self._build_gear_faces() + spokes_id=None, spokes_od=None, chamfer=None, chamfer_top=None, + chamfer_bottom=None, *args, **kv_args): + faces = self._build_gear_faces() - shell = make_shell(faces, tol=self.shell_sewing_tol) - body = cq.Solid.makeSolid(shell) + shell = make_shell(faces, tol=self.shell_sewing_tol) + body = cq.Solid.makeSolid(shell) - body = self._make_bore(body, bore_d) - body = self._make_missing_teeth(body, missing_teeth) - body = self._make_recess(body, hub_d, recess_d, recess) - body = self._make_hub(body, hub_d, hub_length, bore_d) - - if spokes_id is None: - spokes_id = hub_d + body = self._make_chamfer(body, chamfer, chamfer_top, chamfer_bottom) + body = self._make_bore(body, bore_d) + body = self._make_missing_teeth(body, missing_teeth) + body = self._make_recess(body, hub_d, recess_d, recess) + body = self._make_hub(body, hub_d, hub_length, bore_d) + + if spokes_id is None: + spokes_id = hub_d - if spokes_od is None: - spokes_od = recess_d + if spokes_od is None: + spokes_od = recess_d - body = self._make_spokes(body, spokes_id, spokes_od, n_spokes, - spoke_width, spoke_fillet) + body = self._make_spokes(body, spokes_id, spokes_od, n_spokes, + spoke_width, spoke_fillet) - return body + return body class HerringboneGear(SpurGear): diff --git a/examples/animated.ipynb b/examples/animated.ipynb new file mode 100644 index 0000000..7e9e167 --- /dev/null +++ b/examples/animated.ipynb @@ -0,0 +1,666 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "95606c2d-399e-4ede-a450-3068bd422717", + "metadata": {}, + "outputs": [], + "source": [ + "import cadquery as cq\n", + "import numpy as np\n", + "from jupyter_cadquery.cadquery import show\n", + "from jupyter_cadquery import set_defaults, set_sidecar\n", + "from jupyter_cadquery.cadquery import PartGroup, Part, Edges, Faces, Vertices\n", + "from jupyter_cadquery.cad_animation import Animation\n", + "\n", + "\n", + "set_defaults(display='sidecar', axes=False, axes0=True, grid=False,\n", + " default_color='lightgrey', tools=True, ortho=True, black_edges=True)\n", + "\n", + "from cq_gears import (SpurGear, HerringboneGear, RackGear, HerringboneRackGear,\n", + " PlanetaryGearset, HerringbonePlanetaryGearset,\n", + " BevelGearPair, Worm, CrossedGearPair, HyperbolicGearPair)\n", + "\n", + "set_sidecar('Gears', init=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "44118b21-996c-410f-b2b2-8fb0c74c2d40", + "metadata": {}, + "outputs": [], + "source": [ + "L = lambda *args: cq.Location(cq.Vector(*args))\n", + "Lrz = lambda loc, r: cq.Location(cq.Vector(*loc), cq.Vector(0.0, 0.0, 1.0), r)\n", + "C = lambda *args: cq.Color(*args)" + ] + }, + { + "cell_type": "markdown", + "id": "645ad6ca-cdde-4873-848e-97bcf581f589", + "metadata": {}, + "source": [ + "## Parallel axes gears" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f61f975c-f0c5-4181-be4f-5f2bfb830595", + "metadata": { + "jupyter": { + "source_hidden": true + }, + "tags": [] + }, + "outputs": [], + "source": [ + "def animate_pinion_and_gear(pinion, gear):\n", + " ratio = pinion.z / gear.z\n", + "\n", + " asm = (cq.Assembly(name='gears')\n", + " .add(pinion.build(), name='pinion', color=C('goldenrod'),\n", + " loc=L(0.0, 0.0, 0.0))\n", + " .add(gear.build(), name='gear', color=C('lightsteelblue'),\n", + " loc=L(gear.r0 + pinion.r0, 0.0, 0.0)))\n", + "\n", + " view = show(asm)\n", + "\n", + " n_frames = 800\n", + "\n", + " times = np.linspace(0.0, 10.0, n_frames)\n", + " pinion_angles = np.linspace(0.0, 360.0, n_frames)\n", + " gear_angles = -pinion_angles * ratio\n", + "\n", + " anim = Animation(view.root_group)\n", + "\n", + " anim.add_track(f'gears/pinion', 'rz', times, pinion_angles)\n", + " anim.add_track(f'gears/gear', 'rz', times, gear_angles)\n", + "\n", + " return anim.animate(autoplay=True)" + ] + }, + { + "cell_type": "markdown", + "id": "ac41d845-4691-463b-b221-c8b1138155e7", + "metadata": {}, + "source": [ + "### Spur gears" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "45b666be-2c95-48c6-bf56-7197b12b4440", + "metadata": {}, + "outputs": [], + "source": [ + "pinion = SpurGear(module=2.0, teeth_number=17, width=10.0, helix_angle=0.0,\n", + " bore_d=10.0, chamfer=0.5)\n", + "gear = SpurGear(module=2.0, teeth_number=29, width=10.0, helix_angle=0.0,\n", + " bore_d=10.0, chamfer=0.5, n_spokes=4, spokes_id=20.0,\n", + " spokes_od=44.0, spoke_width=6.0, spoke_fillet=4.0)\n", + "\n", + "animate_pinion_and_gear(pinion, gear)" + ] + }, + { + "cell_type": "markdown", + "id": "542aaa6f-d614-4cef-961a-7e424fde8f91", + "metadata": {}, + "source": [ + "### Helical gears" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a4c9aa21-7a3e-43d3-896d-3381441efe41", + "metadata": {}, + "outputs": [], + "source": [ + "pinion = SpurGear(module=2.0, teeth_number=17, width=10.0, helix_angle=30.0,\n", + " bore_d=10.0, chamfer=0.5)\n", + "gear = SpurGear(module=2.0, teeth_number=29, width=10.0, helix_angle=-30.0,\n", + " bore_d=10.0, chamfer=0.5, n_spokes=4, spokes_id=20.0,\n", + " spokes_od=44.0, spoke_width=6.0, spoke_fillet=4.0)\n", + "\n", + "animate_pinion_and_gear(pinion, gear)" + ] + }, + { + "cell_type": "markdown", + "id": "c2768b77-b48f-48e1-89a0-4c310311074a", + "metadata": {}, + "source": [ + "### Herringbone gears" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fc0f6e8c-9384-47c2-a402-79d497229a3d", + "metadata": {}, + "outputs": [], + "source": [ + "pinion = HerringboneGear(module=2.0, teeth_number=17, width=10.0,\n", + " helix_angle=-30.0, bore_d=10.0)\n", + "gear = HerringboneGear(module=2.0, teeth_number=29, width=10.0,\n", + " helix_angle=30.0, bore_d=10.0, n_spokes=4,\n", + " spokes_id=20.0, spokes_od=44.0, spoke_width=6.0,\n", + " spoke_fillet=4.0)\n", + "\n", + "animate_pinion_and_gear(pinion, gear)" + ] + }, + { + "cell_type": "markdown", + "id": "736287c1-6374-4bac-bf76-966bd0e9bb33", + "metadata": {}, + "source": [ + "## Gear rack and pinion" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "02247639-9d6d-4425-950f-ae8c27b03bf5", + "metadata": {}, + "outputs": [], + "source": [ + "def animate_rack_and_pinion(rack, pinion):\n", + " cfr = pinion.r0 * 2.0 * np.pi\n", + " rp = cfr / pinion.z\n", + " start_x = rp * 1.0\n", + " end_x = rack.length - rp * 2.0\n", + " start_angle = 360.0 / pinion.z * 2.0 - 90.0 + np.degrees(pinion.tau) / 2.0\n", + " end_angle = (end_x - start_x) / cfr * 360.0\n", + " \n", + " asm = (cq.Assembly(name='gears')\n", + " .add(rack.build(), name='rack', color=C('goldenrod'),\n", + " loc=L(0.0, 0.0, 0.0))\n", + " .add(pinion.build(), name='pinion', color=C('lightsteelblue'),\n", + " loc=Lrz((start_x, pinion.r0, 0.0), start_angle))\n", + " )\n", + "\n", + " view = show(asm)\n", + "\n", + " n_frames = 800\n", + "\n", + " times = np.linspace(0.0, 10.0, n_frames)\n", + " pinion_angles = -np.linspace(0.0, end_angle, n_frames // 2)\n", + " pinion_angles = np.concatenate((pinion_angles,\n", + " -np.linspace(end_angle, 0.0, n_frames // 2)))\n", + " pinion_tx = np.linspace(start_x, end_x, n_frames // 2)\n", + " pinion_tx = np.concatenate((pinion_tx, \n", + " np.linspace(end_x, start_x, n_frames // 2)))\n", + "\n", + " anim = Animation(view.root_group)\n", + "\n", + " anim.add_track(f'gears/pinion', 'rz', times, pinion_angles)\n", + " anim.add_track(f'gears/pinion', 'tx', times, pinion_tx)\n", + "\n", + " return anim.animate(autoplay=True)\n" + ] + }, + { + "cell_type": "markdown", + "id": "e758ab17-29de-44c7-9f2a-48fa1cf81180", + "metadata": {}, + "source": [ + "### Straigh teeth rack and pinion" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7eb446ed-e995-41ca-a140-c707293d1b85", + "metadata": {}, + "outputs": [], + "source": [ + "pinion = SpurGear(module=2.0, teeth_number=18, width=10.0,\n", + " bore_d=10.0, chamfer=0.5)\n", + "rack = RackGear(module=2.0, length=140.0, width=10.0, height=20.0)\n", + "\n", + "animate_rack_and_pinion(rack, pinion)" + ] + }, + { + "cell_type": "markdown", + "id": "1abc0e58-9d7e-44f6-acf5-660427bde677", + "metadata": {}, + "source": [ + "### Helical rack and pinion" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4ad010df-19a7-4e03-b93b-4293b597b548", + "metadata": {}, + "outputs": [], + "source": [ + "pinion = SpurGear(module=2.0, teeth_number=18, width=10.0, helix_angle=30.0,\n", + " bore_d=10.0, chamfer=0.5)\n", + "rack = RackGear(module=2.0, length=140.0, width=10.0, height=20.0,\n", + " helix_angle=-30.0)\n", + "\n", + "animate_rack_and_pinion(rack, pinion)" + ] + }, + { + "cell_type": "markdown", + "id": "a280a4fd-9f5d-4952-abfc-3534b944185d", + "metadata": {}, + "source": [ + "### Herringbone rack and pinion" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ecc712fe-073d-44da-b9a6-e1a700b1e6e4", + "metadata": {}, + "outputs": [], + "source": [ + "pinion = HerringboneGear(module=2.0, teeth_number=18, width=10.0,\n", + " helix_angle=30.0, bore_d=10.0, chamfer=0.5)\n", + "rack = HerringboneRackGear(module=2.0, length=140.0, width=10.0, height=20.0,\n", + " helix_angle=-30.0)\n", + "\n", + "animate_rack_and_pinion(rack, pinion)" + ] + }, + { + "cell_type": "markdown", + "id": "a5b20e0b-75b3-44a4-aba6-5d27d73222fc", + "metadata": {}, + "source": [ + "## Planetary gearsets" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0df2c86c-86f7-440f-a4d5-8afc41536de1", + "metadata": {}, + "outputs": [], + "source": [ + "def animate_planetary_gearset(gearset):\n", + " planet_ratio = gearset.sun.z / (gearset.planet.z * 2.0)\n", + " carrier_ratio = 1.0 / (gearset.ring.z / gearset.sun.z + 1.0)\n", + "\n", + " asm = gearset.assemble()\n", + " view = show(asm)\n", + "\n", + " n_frames = 4000\n", + "\n", + " times = np.linspace(0.0, 60.0, n_frames)\n", + " sun_angles = np.linspace(0.0, 360.0 * 4.0, n_frames)\n", + " carrier_angles = sun_angles * carrier_ratio\n", + " planet_angles = -sun_angles * planet_ratio\n", + "\n", + " anim = Animation(view.root_group)\n", + "\n", + " anim.add_track(f'planetary/sun', 'rz', times, sun_angles)\n", + " anim.add_track(f'planetary/planets', 'rz', times, carrier_angles)\n", + "\n", + " for i in range(gearset.n_planets):\n", + " anim.add_track(f'planetary/planets/planet_{i:02}', 'rz', times,\n", + " planet_angles - carrier_angles)\n", + "\n", + " return anim.animate(autoplay=True)" + ] + }, + { + "cell_type": "markdown", + "id": "71029871-2c44-44a4-8912-204198b5c1ce", + "metadata": {}, + "source": [ + "### Straight teeth planetary gearset" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2056aab6-064a-4d82-b5b2-dbafe9ea1da6", + "metadata": {}, + "outputs": [], + "source": [ + "gearset = PlanetaryGearset(module=1.0,\n", + " sun_teeth_number=40, planet_teeth_number=20,\n", + " width=10.0, rim_width=5.0, n_planets=6,\n", + " bore_d=6.0, chamfer=0.5,\n", + " sun_build_args={'bore_d': 20.0})\n", + "\n", + "animate_planetary_gearset(gearset)" + ] + }, + { + "cell_type": "markdown", + "id": "e3dd91ac-bdc5-4c5e-9255-9ae998a439cd", + "metadata": {}, + "source": [ + "### Helical planetary gearset" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5dbc2089-742f-4083-a1e5-26aefb8ee722", + "metadata": {}, + "outputs": [], + "source": [ + "gearset = PlanetaryGearset(module=1.0, helix_angle=30.0,\n", + " sun_teeth_number=40, planet_teeth_number=20,\n", + " width=10.0, rim_width=5.0, n_planets=6,\n", + " bore_d=6.0, chamfer=0.5,\n", + " sun_build_args={'bore_d': 20.0})\n", + "\n", + "animate_planetary_gearset(gearset)" + ] + }, + { + "cell_type": "markdown", + "id": "8bebd3fe-1aa1-40e0-a774-a42c99f367cb", + "metadata": {}, + "source": [ + "### Herringbone planetary gearset" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bcdb9992-afb0-4bb5-9c39-3e1f5701625e", + "metadata": {}, + "outputs": [], + "source": [ + "gearset = HerringbonePlanetaryGearset(\n", + " module=1.0, helix_angle=30.0,\n", + " sun_teeth_number=40, planet_teeth_number=20,\n", + " width=10.0, rim_width=5.0, n_planets=6,\n", + " bore_d=6.0, chamfer=0.5,\n", + " sun_build_args={'bore_d': 20.0})\n", + "\n", + "animate_planetary_gearset(gearset)" + ] + }, + { + "cell_type": "markdown", + "id": "bf11dec0-5aff-4a75-870e-d6fc4e335842", + "metadata": {}, + "source": [ + "## Bevel gears" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "696197b2-0164-4f5b-a65b-d1f05cf62323", + "metadata": {}, + "outputs": [], + "source": [ + "def animate_bevel_gear_pair(gearset):\n", + " asm = gearset.assemble(transform_pinion=True)\n", + "\n", + " view = show(asm)\n", + "\n", + " n_frames = 4000\n", + " ratio = gearset.pinion.z / gearset.gear.z\n", + "\n", + " times = np.linspace(0.0, 60.0, n_frames)\n", + " pinion_angles = np.linspace(0.0, 360.0 * 4.0, n_frames)\n", + " gear_angles = -pinion_angles * ratio\n", + "\n", + " anim = Animation(view.root_group)\n", + "\n", + " anim.add_track(f'bevel_pair/pinion', 'rz', times, pinion_angles)\n", + " anim.add_track(f'bevel_pair/gear', 'rz', times, gear_angles)\n", + "\n", + " return anim.animate(autoplay=True)" + ] + }, + { + "cell_type": "markdown", + "id": "b3322b32-7b25-47d2-bebd-202f16b133dd", + "metadata": {}, + "source": [ + "### Straight bevel gears" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6b1c29f9-1d9e-40f8-bc29-9ee456821a70", + "metadata": {}, + "outputs": [], + "source": [ + "gearset = BevelGearPair(module=2.0, gear_teeth=23, pinion_teeth=14,\n", + " face_width=12.0, axis_angle=90.0, bore_d=12.0,\n", + " pinion_build_args={'bore_d': 8.0})\n", + "\n", + "animate_bevel_gear_pair(gearset)" + ] + }, + { + "cell_type": "markdown", + "id": "700da365-4a24-4204-8919-8420a9b508ab", + "metadata": {}, + "source": [ + "### Helical bevel gears" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "aef90db1-7a3f-40f1-8b44-90b2637723c1", + "metadata": {}, + "outputs": [], + "source": [ + "gearset = BevelGearPair(module=2.0, gear_teeth=23, pinion_teeth=14,\n", + " face_width=12.0, helix_angle=30.0, axis_angle=90.0,\n", + " bore_d=12.0, pinion_build_args={'bore_d': 8.0})\n", + "\n", + "animate_bevel_gear_pair(gearset)" + ] + }, + { + "cell_type": "markdown", + "id": "d6880b94-9d56-4bd5-b064-6f350232a4a2", + "metadata": {}, + "source": [ + "## Worm gears" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fb0f86c7-b33c-42ab-b2c0-56cdc5dec275", + "metadata": {}, + "outputs": [], + "source": [ + "def animate_worm_and_gear(worm, gear):\n", + " ratio = worm.n_threads / gear.z\n", + " align_angle = -90.0 - np.degrees(gear.tau / 2.0 - gear.twist_angle / 2.0)\n", + "\n", + " n_frames = 1000\n", + " times = np.linspace(0.0, 60.0, n_frames)\n", + " worm_angles = np.linspace(0.0, 360.0 * 10.0, n_frames)\n", + " gear_angles = worm_angles * ratio\n", + "\n", + " asm = (cq.Assembly(name='gears')\n", + " .add(worm.build(), name='worm', color=C('lightsteelblue'),\n", + " loc=L(0.0, 0.0, worm.r0))\n", + " .add(gear.build(), name='gear', color=C('goldenrod'),\n", + " loc=Lrz((0.0,\n", + " worm.r0 + gear.r0,\n", + " worm.r0 - gear.width / 2.0), align_angle)))\n", + "\n", + " view = show(asm)\n", + "\n", + " anim = Animation(view.root_group)\n", + " anim.add_track('gears/worm', 'rx', times, worm_angles)\n", + " anim.add_track('gears/gear', 'rz', times, gear_angles)\n", + "\n", + " return anim.animate(autoplay=True)\n", + " " + ] + }, + { + "cell_type": "markdown", + "id": "5671e36f-d0e1-4e3f-8e77-7ae3b1db426e", + "metadata": {}, + "source": [ + "### Worm and gear (non-throated)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "837f9c21-0f56-4ffa-8503-b35c5a8abd3f", + "metadata": {}, + "outputs": [], + "source": [ + "lead_angle = 7.0\n", + "worm = Worm(module=2.0, lead_angle=lead_angle, n_threads=2, length=60.0,\n", + " bore_d=20.0)\n", + "gear = SpurGear(module=2.0, teeth_number=32, width=16.0, helix_angle=lead_angle,\n", + " chamfer=0.5, bore_d=10.0, recess_d=50.0, recess=6.0,\n", + " hub_d=20.0, hub_length=5.0)\n", + "\n", + "animate_worm_and_gear(worm, gear)" + ] + }, + { + "cell_type": "markdown", + "id": "ed65b523-33b4-4aee-98e7-25efb384e6c2", + "metadata": {}, + "source": [ + "## Crossed axes helical gears" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8050d1ef-3450-4550-8fcc-b073248ab895", + "metadata": {}, + "outputs": [], + "source": [ + "def animate_crossed_gear_pair(gearset):\n", + " asm = gearset.assemble()\n", + "\n", + " view = show(asm)\n", + "\n", + " n_frames = 1000\n", + " ratio = gearset.gear1.z / gearset.gear2.z\n", + "\n", + " times = np.linspace(0.0, 60.0, n_frames)\n", + " gear1_angles = np.linspace(0.0, 360.0 * 4.0, n_frames)\n", + " gear2_angles = -gear1_angles * ratio\n", + "\n", + " anim = Animation(view.root_group)\n", + "\n", + " anim.add_track('crossed_pair/gear1', 'rz', times, gear1_angles)\n", + " anim.add_track('crossed_pair/gear2', 'rz', times, gear2_angles)\n", + "\n", + " return anim.animate(autoplay=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c13f124a-92c5-45ae-a74a-1dc0c9c345b5", + "metadata": {}, + "outputs": [], + "source": [ + "gears = CrossedGearPair(module=2.0,\n", + " gear1_teeth_number=19, gear2_teeth_number=19,\n", + " gear1_width=16.0, gear2_width=40.0,\n", + " gear1_helix_angle=40.0, shaft_angle=90.0,\n", + " bore_d=16.0, chamfer=1.0)\n", + "\n", + "animate_crossed_gear_pair(gears)" + ] + }, + { + "cell_type": "markdown", + "id": "2d8ae659-882f-4a78-945e-76b93c1cf464", + "metadata": {}, + "source": [ + "## Hyperbolic gears" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "21e0947e-a894-4bf0-951e-534851cb5658", + "metadata": {}, + "outputs": [], + "source": [ + "def animate_hyperbolic_gear_pair(gearset):\n", + " asm = gearset.assemble()\n", + "\n", + " view = show(asm)\n", + "\n", + " n_frames = 1000\n", + " ratio = gearset.gear1.z / gearset.gear2.z\n", + "\n", + " times = np.linspace(0.0, 60.0, n_frames)\n", + " gear1_angles = np.linspace(0.0, 360.0 * 4.0, n_frames)\n", + " gear2_angles = -gear1_angles * ratio\n", + "\n", + " anim = Animation(view.root_group)\n", + "\n", + " anim.add_track('hyperbolic_pair/gear1', 'rz', times, gear1_angles)\n", + " anim.add_track('hyperbolic_pair/gear2', 'rz', times, gear2_angles)\n", + "\n", + " return anim.animate(autoplay=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "59fa6df1-56de-43ff-ade5-74778dc47e8b", + "metadata": {}, + "outputs": [], + "source": [ + "gears = HyperbolicGearPair(module=2.0, gear1_teeth_number=13, width=60.0,\n", + " shaft_angle=42.0, gear2_teeth_number=13,\n", + " bore_d=8.0, chamfer=(4.0, 8.0))\n", + "\n", + "animate_hyperbolic_gear_pair(gears)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5d1bfe85-1e38-42c9-8795-11a8d8fc9283", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/setup.py b/setup.py index 786e200..b4d7fdd 100644 --- a/setup.py +++ b/setup.py @@ -19,7 +19,7 @@ from setuptools import setup, find_packages -version = '0.6' +version = '0.62' setup( name='cq_gears', diff --git a/tests/report.py b/tests/report.py new file mode 100755 index 0000000..cdd1bd1 --- /dev/null +++ b/tests/report.py @@ -0,0 +1,125 @@ +#! /usr/bin/python3 + +''' +CQ_Gears - CadQuery based involute profile gear generator + +Copyright 2021 meadiode@github + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +''' + +import os +import json +from datetime import datetime +from collections import Counter, defaultdict + +FAIL_TAGS = ('UNDEFINED', 'PRECALC', 'BUILDING', 'NOT_SOLID', 'VOLUME', + 'BBOX_Z', 'BBOX_XY', 'TIMEOUT') + + +class Report: + '''Summarizes test result data. + + Also organizes parameters which failed to produce a valid gear for further + case reproduction and debugging. + ''' + + def __init__(self, filename): + info = filename.split('_') + self.branch = info[-3] + self.git_sha = info[-2] + date_str = info[-1].split('.')[0] + self.dt = datetime.strptime(date_str, '%Y%m%d%H%M%S') + + data = json.loads(open(filename).read()) + + self.n_passed = data['summary']['passed'] + self.n_failed = data['summary']['failed'] + self.n_total = data['summary']['total'] + self.duration = data['duration'] + + self.fail_tags = Counter() + self.fail_tags_per_test = defaultdict(Counter) + self.fails = defaultdict(lambda: defaultdict(list)) + + for test in data['tests']: + if test['outcome'] == 'passed': + continue + + tag = test['metadata']['failure_tag'] + self.fail_tags[tag] += 1 + + test_name = test['nodeid'].split('::')[-2] + params = test['metadata']['gear_params'] + + self.fails[test_name][tag].append(params) + self.fail_tags_per_test[test_name][tag] += 1 + + + def print_summary(self): + dt = self.dt.strftime('%d-%m-%Y, %H:%M:%S') + prc = self.n_passed / self.n_total * 100.0 + fprc = 100.0 - prc + + secs = int(self.duration) + hrs = secs // (60 * 60) + secs %= (60 * 60) + mins = secs // 60 + secs %= 60 + + print(f'branch: {self.branch}') + print(f'git SHA: {self.git_sha}') + print(f'date & time: {dt}') + print(f'running time: {hrs} hours, {mins} minutes, {secs} seconds') + print(f'passed: {self.n_passed} ({prc:.2f}%)') + print(f'failed: {self.n_failed} ({fprc:.2f}%)') + + header = ' ' * 26 + for tag in FAIL_TAGS: + header = header + f'{tag:>10}' + + print(header) + + for tname, tags in self.fail_tags_per_test.items(): + line = f'{tname:<26}' + for tag in FAIL_TAGS: + n = tags[tag] + line = line + f'{n:>10}' + + print(line) + + + @staticmethod + def gather_reports(dir_): + reps = [] + + for fname in os.listdir(dir_): + fname = os.path.join(dir_, fname) + if os.path.isfile(fname) and fname.endswith('.json'): + reps.append(Report(fname)) + + reps.sort(key=lambda e: e.dt, reverse=True) + + return reps + + +if __name__ == '__main__': + reps = Report.gather_reports('./reports') + + print('\n') + for rep in reps: + rep.print_summary() + print() + print('=' * 106) + print('=' * 106) + print() diff --git a/tests/test_bevel_gear.py b/tests/test_bevel_gear.py index 9e19813..ee71277 100644 --- a/tests/test_bevel_gear.py +++ b/tests/test_bevel_gear.py @@ -15,7 +15,7 @@ TEETH_NUMBER_MAX = 200 CONE_ANGLE_MIN = 1.0 -CONE_ANGLE_MAX = 89.0 +CONE_ANGLE_MAX = 80.0 PRESSURE_ANGLE_MIN = 0.5 PRESSURE_ANGLE_MAX = 30.0 @@ -23,7 +23,7 @@ HELIX_ANGLE_MIN = -70.0 HELIX_ANGLE_MAX = 70.0 -BBOX_CHECK_TOL = 0.5 +BBOX_CHECK_TOL = 1.5 class TestBevelGear(_TestGear): @@ -103,7 +103,7 @@ def gear_build(out_q, gear): width = gear.cone_h - \ np.cos(gear.gamma_f) * (gear.gs_r - gear.face_width) - if abs(width - (bb.zmax + bb.zmin)) > BBOX_CHECK_TOL: + if abs(width - (bb.zmax - bb.zmin)) > BBOX_CHECK_TOL: out_q.put(BBoxZCheckFailure()) return diff --git a/tests/test_worm_gear.py b/tests/test_worm.py similarity index 91% rename from tests/test_worm_gear.py rename to tests/test_worm.py index 2f969c1..1966ab2 100644 --- a/tests/test_worm_gear.py +++ b/tests/test_worm.py @@ -1,7 +1,7 @@ import numpy as np import cadquery as cq -from cq_gears import WormGear +from cq_gears import Worm from utils import (BuildFailure, SolidBuildFailure, VolumeCheckFailure, BBoxZCheckFailure, BBoxXYCheckFailure) @@ -26,9 +26,9 @@ BBOX_CHECK_TOL = 0.5 -class TestWormGear(_TestGear): +class TestWorm(_TestGear): - gear_cls = WormGear + gear_cls = Worm argnames = ['module', 'lead_angle', 'n_threads', 'length', 'pressure_angle'] @staticmethod @@ -38,7 +38,7 @@ def gen_params(seed, n): module = MODULE_MIN + (MODULE_MAX - MODULE_MIN) * rng.random(n) n_threads = rng.integers(THREADS_MIN, THREADS_MAX + 1, n) lead_angle_max = (n_threads * module) / \ - (2.0 * WormGear.kd * module + 2.0 * ROOT_RADIUS_MIN) + (2.0 * Worm.kd * module + 2.0 * ROOT_RADIUS_MIN) lead_angle = LEAD_ANGLE_MIN + \ (lead_angle_max - LEAD_ANGLE_MIN) * rng.random(n) length = LENGTH_MIN + (LENGTH_MAX - LENGTH_MIN) * rng.random(n) @@ -49,7 +49,7 @@ def gen_params(seed, n): for vals in zip(module, lead_angle, n_threads, length, pressure_angle): params.append({k : v.item() for k, v in \ - zip(TestWormGear.argnames, vals)}) + zip(TestWorm.argnames, vals)}) return params