442 lines
15 KiB
Python
442 lines
15 KiB
Python
"""Herringbone ring, planet, carrier, and output parts for the 20:1 reducer."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import math
|
|
|
|
import simplecadapi as scad
|
|
|
|
try:
|
|
from .common import (
|
|
apply_tags,
|
|
make_axis_part_rpart,
|
|
make_axial_hole_cutters_rsolids,
|
|
make_z_rotation_rplacement,
|
|
)
|
|
from .dimensions import (
|
|
ADDENDUM_FACTOR,
|
|
BACKLASH,
|
|
CLEARANCE_FACTOR,
|
|
GEAR_HEIGHT,
|
|
HELIX_ANGLE,
|
|
INTERSTAGE_BEARING_CENTER_Z,
|
|
INTERSTAGE_SHAFT_RADIUS,
|
|
OUTPUT_BEARING_1_CENTER_Z,
|
|
OUTPUT_BEARING_2_CENTER_Z,
|
|
OUTPUT_FLANGE_BOTTOM_Z,
|
|
OUTPUT_FLANGE_RADIUS,
|
|
OUTPUT_FLANGE_TOP_Z,
|
|
OUTPUT_LINK_BOLT_ANGLES_DEGREES,
|
|
OUTPUT_LINK_BOLT_COUNT,
|
|
OUTPUT_LINK_HOLE_PCD,
|
|
OUTPUT_LINK_TAP_RADIUS,
|
|
OUTPUT_LINK_THREAD_DEPTH,
|
|
OUTPUT_REGISTER_HEIGHT,
|
|
OUTPUT_SHAFT_RADIUS,
|
|
PLANET_BEARING,
|
|
PLANET_COUNT,
|
|
PRESSURE_ANGLE,
|
|
RING_INSERT_OUTER_RADIUS,
|
|
RING_RIM_THICKNESS,
|
|
RING_SUPPORT_OVERLAP,
|
|
STAGE1_ARM_WIDTH,
|
|
STAGE1_CARRIER_BOTTOM_Z,
|
|
STAGE1_CARRIER_THICKNESS,
|
|
STAGE1_HUB_RADIUS,
|
|
STAGE1_PAD_RADIUS,
|
|
STAGE1_PIN_BOTTOM_Z,
|
|
STAGE1_PIN_RADIUS,
|
|
STAGE2_ARM_WIDTH,
|
|
STAGE2_CARRIER_BOTTOM_Z,
|
|
STAGE2_CARRIER_THICKNESS,
|
|
STAGE2_HUB_RADIUS,
|
|
STAGE2_PAD_RADIUS,
|
|
STAGE2_PIN_BOTTOM_Z,
|
|
STAGE2_PIN_RADIUS,
|
|
STAGE_1,
|
|
STAGE_2,
|
|
StageSpec,
|
|
)
|
|
except ImportError: # Support direct execution from this example directory.
|
|
from common import (
|
|
apply_tags,
|
|
make_axis_part_rpart,
|
|
make_axial_hole_cutters_rsolids,
|
|
make_z_rotation_rplacement,
|
|
)
|
|
from dimensions import (
|
|
ADDENDUM_FACTOR,
|
|
BACKLASH,
|
|
CLEARANCE_FACTOR,
|
|
GEAR_HEIGHT,
|
|
HELIX_ANGLE,
|
|
INTERSTAGE_BEARING_CENTER_Z,
|
|
INTERSTAGE_SHAFT_RADIUS,
|
|
OUTPUT_BEARING_1_CENTER_Z,
|
|
OUTPUT_BEARING_2_CENTER_Z,
|
|
OUTPUT_FLANGE_BOTTOM_Z,
|
|
OUTPUT_FLANGE_RADIUS,
|
|
OUTPUT_FLANGE_TOP_Z,
|
|
OUTPUT_LINK_BOLT_ANGLES_DEGREES,
|
|
OUTPUT_LINK_BOLT_COUNT,
|
|
OUTPUT_LINK_HOLE_PCD,
|
|
OUTPUT_LINK_TAP_RADIUS,
|
|
OUTPUT_LINK_THREAD_DEPTH,
|
|
OUTPUT_REGISTER_HEIGHT,
|
|
OUTPUT_SHAFT_RADIUS,
|
|
PLANET_BEARING,
|
|
PLANET_COUNT,
|
|
PRESSURE_ANGLE,
|
|
RING_INSERT_OUTER_RADIUS,
|
|
RING_RIM_THICKNESS,
|
|
RING_SUPPORT_OVERLAP,
|
|
STAGE1_ARM_WIDTH,
|
|
STAGE1_CARRIER_BOTTOM_Z,
|
|
STAGE1_CARRIER_THICKNESS,
|
|
STAGE1_HUB_RADIUS,
|
|
STAGE1_PAD_RADIUS,
|
|
STAGE1_PIN_BOTTOM_Z,
|
|
STAGE1_PIN_RADIUS,
|
|
STAGE2_ARM_WIDTH,
|
|
STAGE2_CARRIER_BOTTOM_Z,
|
|
STAGE2_CARRIER_THICKNESS,
|
|
STAGE2_HUB_RADIUS,
|
|
STAGE2_PAD_RADIUS,
|
|
STAGE2_PIN_BOTTOM_Z,
|
|
STAGE2_PIN_RADIUS,
|
|
STAGE_1,
|
|
STAGE_2,
|
|
StageSpec,
|
|
)
|
|
|
|
|
|
def make_stage_ring_gear_rpart(
|
|
*,
|
|
stage: StageSpec,
|
|
material: scad.Material,
|
|
) -> scad.Part:
|
|
"""Create one herringbone ring insert with a full housing support rim."""
|
|
|
|
ring = scad.std.gear.make_herringbone_ring_gear_rsolid(
|
|
n_teeth=stage.ring_teeth,
|
|
module=stage.module,
|
|
pressure_angle=PRESSURE_ANGLE,
|
|
helix_angle=-HELIX_ANGLE,
|
|
gear_height=GEAR_HEIGHT,
|
|
rim_thickness=RING_RIM_THICKNESS,
|
|
backlash=BACKLASH,
|
|
addendum_factor=ADDENDUM_FACTOR,
|
|
clearance_factor=CLEARANCE_FACTOR,
|
|
)
|
|
support = scad.make_cylinder_rsolid(
|
|
radius=RING_INSERT_OUTER_RADIUS,
|
|
height=GEAR_HEIGHT,
|
|
bottom_face_center=(0.0, 0.0, 0.0),
|
|
axis=(0.0, 0.0, 1.0),
|
|
)
|
|
support_bore = scad.make_cylinder_rsolid(
|
|
radius=stage.ring_outer_radius - RING_SUPPORT_OVERLAP,
|
|
height=GEAR_HEIGHT + 2.0,
|
|
bottom_face_center=(0.0, 0.0, -1.0),
|
|
axis=(0.0, 0.0, 1.0),
|
|
)
|
|
support = scad.cut_rsolid(support, support_bore, skip_non_intersecting=False)
|
|
ring = scad.union_rsolid(ring, support, glue=False)
|
|
ring = apply_tags(
|
|
shape=ring,
|
|
tags=(f"role.{stage.stage_id}.fixed_ring_gear", "role.ring_gear_press_fit", "group.two_stage_reducer"),
|
|
)
|
|
print(
|
|
f"{stage.stage_id}_ring: teeth={stage.ring_teeth} pitch_r={stage.ring_pitch_radius:.3f} "
|
|
f"toothed_outer_r={stage.ring_outer_radius:.3f} insert_d={RING_INSERT_OUTER_RADIUS * 2.0:.2f}"
|
|
)
|
|
return make_axis_part_rpart(
|
|
part_id=f"{stage.stage_id}_fixed_ring",
|
|
body=ring,
|
|
name=f"{stage.label} replaceable fixed herringbone ring insert",
|
|
material=material,
|
|
connectors=(("axis", (0.0, 0.0, GEAR_HEIGHT / 2.0), "Fixed ring axis"),),
|
|
)
|
|
|
|
|
|
def make_stage_planet_gear_rpart(
|
|
*,
|
|
stage: StageSpec,
|
|
material: scad.Material,
|
|
) -> scad.Part:
|
|
"""Create one reusable herringbone planet with a standard-bearing seat."""
|
|
|
|
planet = scad.std.gear.make_herringbone_gear_rsolid(
|
|
n_teeth=stage.planet_teeth,
|
|
module=stage.module,
|
|
pressure_angle=PRESSURE_ANGLE,
|
|
helix_angle=-HELIX_ANGLE,
|
|
gear_height=GEAR_HEIGHT,
|
|
addendum_factor=ADDENDUM_FACTOR,
|
|
clearance_factor=CLEARANCE_FACTOR,
|
|
backlash=BACKLASH,
|
|
)
|
|
bearing_seat_radius = PLANET_BEARING.outer_diameter / 2.0 + 0.05
|
|
bearing_seat = scad.make_cylinder_rsolid(
|
|
radius=bearing_seat_radius,
|
|
height=GEAR_HEIGHT + 2.0,
|
|
bottom_face_center=(0.0, 0.0, -1.0),
|
|
axis=(0.0, 0.0, 1.0),
|
|
)
|
|
planet = scad.cut_rsolid(planet, bearing_seat, skip_non_intersecting=False)
|
|
planet = apply_tags(
|
|
shape=planet,
|
|
tags=(f"role.{stage.stage_id}.planet_gear", "role.planet_bearing_seat", "group.two_stage_reducer"),
|
|
)
|
|
root_radius = stage.planet_pitch_radius - stage.module * (ADDENDUM_FACTOR + CLEARANCE_FACTOR)
|
|
print(
|
|
f"{stage.stage_id}_planet: teeth={stage.planet_teeth} pitch_r={stage.planet_pitch_radius:.3f} "
|
|
f"bearing_seat_r={bearing_seat_radius:.3f} root_ligament={root_radius - bearing_seat_radius:.3f}"
|
|
)
|
|
return make_axis_part_rpart(
|
|
part_id=f"{stage.stage_id}_reusable_planet",
|
|
body=planet,
|
|
name=f"{stage.label} reusable bearing-supported planet",
|
|
material=material,
|
|
connectors=(
|
|
("axis", (0.0, 0.0, GEAR_HEIGHT / 2.0), "Planet spin axis"),
|
|
("bearing_axis", (0.0, 0.0, GEAR_HEIGHT / 2.0), "Planet bearing outer-ring axis"),
|
|
),
|
|
)
|
|
|
|
|
|
def make_stage1_carrier_sun_rpart(*, material: scad.Material) -> scad.Part:
|
|
"""Create the first carrier and integral second-stage sun/shaft."""
|
|
|
|
carrier = _make_carrier_body_rsolid(
|
|
stage=STAGE_1,
|
|
plate_bottom_z=STAGE1_CARRIER_BOTTOM_Z,
|
|
plate_thickness=STAGE1_CARRIER_THICKNESS,
|
|
pin_bottom_z=STAGE1_PIN_BOTTOM_Z,
|
|
pin_radius=STAGE1_PIN_RADIUS,
|
|
hub_radius=STAGE1_HUB_RADIUS,
|
|
arm_width=STAGE1_ARM_WIDTH,
|
|
pad_radius=STAGE1_PAD_RADIUS,
|
|
)
|
|
shaft = scad.make_cylinder_rsolid(
|
|
radius=INTERSTAGE_SHAFT_RADIUS,
|
|
height=STAGE_2.top_z - STAGE1_CARRIER_BOTTOM_Z + 0.1,
|
|
bottom_face_center=(0.0, 0.0, STAGE1_CARRIER_BOTTOM_Z - 0.05),
|
|
axis=(0.0, 0.0, 1.0),
|
|
)
|
|
stage2_sun = scad.std.gear.make_herringbone_gear_rsolid(
|
|
n_teeth=STAGE_2.sun_teeth,
|
|
module=STAGE_2.module,
|
|
pressure_angle=PRESSURE_ANGLE,
|
|
helix_angle=HELIX_ANGLE,
|
|
gear_height=GEAR_HEIGHT,
|
|
addendum_factor=ADDENDUM_FACTOR,
|
|
clearance_factor=CLEARANCE_FACTOR,
|
|
backlash=BACKLASH,
|
|
)
|
|
stage2_sun = scad.translate_shape(shape=stage2_sun, vector=(0.0, 0.0, STAGE_2.bottom_z))
|
|
carrier = scad.union_rsolid(carrier, shaft, stage2_sun, glue=False)
|
|
carrier = apply_tags(
|
|
shape=carrier,
|
|
tags=("role.stage1.planet_carrier", "role.stage2.sun_gear", "role.integral_interstage_drive", "group.two_stage_reducer"),
|
|
)
|
|
connectors = [
|
|
("carrier_axis", (0.0, 0.0, INTERSTAGE_BEARING_CENTER_Z), "Stage 1 carrier bearing axis"),
|
|
(
|
|
"interstage_bearing_axis",
|
|
(0.0, 0.0, INTERSTAGE_BEARING_CENTER_Z),
|
|
"Interstage bearing inner-ring seat",
|
|
),
|
|
("stage2_sun_axis", (0.0, 0.0, STAGE_2.mid_z), "Integral stage 2 sun axis"),
|
|
]
|
|
for index in range(PLANET_COUNT):
|
|
center = planet_center_xy(stage=STAGE_1, index=index)
|
|
connectors.extend(
|
|
(
|
|
(f"planet_{index + 1}_axis", (*center, STAGE_1.mid_z), f"Stage 1 planet {index + 1} axis"),
|
|
(f"planet_{index + 1}_bearing_axis", (*center, STAGE_1.mid_z), f"Stage 1 planet {index + 1} bearing pin"),
|
|
)
|
|
)
|
|
print(
|
|
f"stage1_carrier_sun: pins={PLANET_COUNT} shaft_d={INTERSTAGE_SHAFT_RADIUS * 2.0:.2f} "
|
|
f"stage2_sun_teeth={STAGE_2.sun_teeth}"
|
|
)
|
|
return make_axis_part_rpart(
|
|
part_id="stage1_carrier_integral_stage2_sun",
|
|
body=carrier,
|
|
name="Stage 1 carrier with integral stage-2 sun shaft",
|
|
material=material,
|
|
connectors=connectors,
|
|
)
|
|
|
|
|
|
def make_output_carrier_flange_rpart(
|
|
*,
|
|
stage: StageSpec,
|
|
material: scad.Material,
|
|
) -> scad.Part:
|
|
"""Create the second carrier, 16 mm bearing land, and output flange."""
|
|
|
|
carrier = _make_carrier_body_rsolid(
|
|
stage=stage,
|
|
plate_bottom_z=STAGE2_CARRIER_BOTTOM_Z,
|
|
plate_thickness=STAGE2_CARRIER_THICKNESS,
|
|
pin_bottom_z=STAGE2_PIN_BOTTOM_Z,
|
|
pin_radius=STAGE2_PIN_RADIUS,
|
|
hub_radius=STAGE2_HUB_RADIUS,
|
|
arm_width=STAGE2_ARM_WIDTH,
|
|
pad_radius=STAGE2_PAD_RADIUS,
|
|
)
|
|
shaft = scad.make_cylinder_rsolid(
|
|
radius=OUTPUT_SHAFT_RADIUS,
|
|
height=(
|
|
OUTPUT_FLANGE_TOP_Z
|
|
+ OUTPUT_REGISTER_HEIGHT
|
|
- STAGE2_CARRIER_BOTTOM_Z
|
|
+ 0.05
|
|
),
|
|
bottom_face_center=(0.0, 0.0, STAGE2_CARRIER_BOTTOM_Z - 0.05),
|
|
axis=(0.0, 0.0, 1.0),
|
|
)
|
|
flange = scad.make_cylinder_rsolid(
|
|
radius=OUTPUT_FLANGE_RADIUS,
|
|
height=OUTPUT_FLANGE_TOP_Z - OUTPUT_FLANGE_BOTTOM_Z,
|
|
bottom_face_center=(0.0, 0.0, OUTPUT_FLANGE_BOTTOM_Z),
|
|
axis=(0.0, 0.0, 1.0),
|
|
)
|
|
output = scad.union_rsolid(carrier, shaft, flange, glue=False)
|
|
output = scad.cut_rsolid(
|
|
output,
|
|
make_axial_hole_cutters_rsolids(
|
|
count=OUTPUT_LINK_BOLT_COUNT,
|
|
pcd=OUTPUT_LINK_HOLE_PCD,
|
|
hole_radius=OUTPUT_LINK_TAP_RADIUS,
|
|
bottom_z=OUTPUT_FLANGE_TOP_Z - OUTPUT_LINK_THREAD_DEPTH,
|
|
height=OUTPUT_LINK_THREAD_DEPTH + 1.0,
|
|
angle_offset=OUTPUT_LINK_BOLT_ANGLES_DEGREES[0],
|
|
),
|
|
skip_non_intersecting=False,
|
|
)
|
|
output = apply_tags(
|
|
shape=output,
|
|
tags=("role.stage2.output_carrier", "role.output_bearing_land", "role.output_link_flange", "group.two_stage_reducer"),
|
|
)
|
|
connectors = [
|
|
("carrier_axis", (0.0, 0.0, STAGE2_CARRIER_BOTTOM_Z + STAGE2_CARRIER_THICKNESS / 2.0), "Stage 2 output carrier axis"),
|
|
("bearing_1_axis", (0.0, 0.0, OUTPUT_BEARING_1_CENTER_Z), "Rear output bearing inner-ring seat"),
|
|
("bearing_2_axis", (0.0, 0.0, OUTPUT_BEARING_2_CENTER_Z), "Front output bearing inner-ring seat"),
|
|
("output_link_axis", (0.0, 0.0, OUTPUT_FLANGE_TOP_Z), "Six-hole driven-link flange"),
|
|
]
|
|
for index in range(PLANET_COUNT):
|
|
center = planet_center_xy(stage=stage, index=index)
|
|
connectors.extend(
|
|
(
|
|
(f"planet_{index + 1}_axis", (*center, stage.mid_z), f"Stage 2 planet {index + 1} axis"),
|
|
(f"planet_{index + 1}_bearing_axis", (*center, stage.mid_z), f"Stage 2 planet {index + 1} bearing pin"),
|
|
)
|
|
)
|
|
radial_ligament = OUTPUT_FLANGE_RADIUS - (OUTPUT_LINK_HOLE_PCD / 2.0 + OUTPUT_LINK_TAP_RADIUS)
|
|
print(
|
|
f"output_carrier_flange: shaft_d={OUTPUT_SHAFT_RADIUS * 2.0:.2f} "
|
|
f"pilot_h={OUTPUT_REGISTER_HEIGHT:.1f} tapped_holes={OUTPUT_LINK_BOLT_COUNT} "
|
|
f"pcd={OUTPUT_LINK_HOLE_PCD:.1f} thread_depth={OUTPUT_LINK_THREAD_DEPTH:.1f} "
|
|
f"radial_ligament={radial_ligament:.2f}"
|
|
)
|
|
return make_axis_part_rpart(
|
|
part_id="stage2_output_carrier_flange",
|
|
body=output,
|
|
name="Stage 2 carrier with paired-bearing shaft and output flange",
|
|
material=material,
|
|
connectors=connectors,
|
|
)
|
|
|
|
|
|
def make_planet_rplacement(*, stage: StageSpec, index: int) -> scad.Placement:
|
|
"""Place and visually phase one planet at its pitch center."""
|
|
|
|
center = planet_center_xy(stage=stage, index=index)
|
|
carrier_angle = 360.0 * index / PLANET_COUNT
|
|
spin = carrier_angle + 180.0 - 180.0 / stage.planet_teeth
|
|
print(
|
|
f"{stage.stage_id}_planet_{index + 1}_placement: center="
|
|
f"({center[0]:.3f},{center[1]:.3f},{stage.bottom_z:.3f}) spin={spin:.2f}"
|
|
)
|
|
return make_z_rotation_rplacement(
|
|
origin=(center[0], center[1], stage.bottom_z),
|
|
angle_degrees=spin,
|
|
)
|
|
|
|
|
|
def planet_center_xy(*, stage: StageSpec, index: int) -> tuple[float, float]:
|
|
"""Return one equally spaced planet pitch center."""
|
|
|
|
angle = math.radians(360.0 * index / PLANET_COUNT)
|
|
return (
|
|
stage.planet_center_radius * math.cos(angle),
|
|
stage.planet_center_radius * math.sin(angle),
|
|
)
|
|
|
|
|
|
def _make_carrier_body_rsolid(
|
|
*,
|
|
stage: StageSpec,
|
|
plate_bottom_z: float,
|
|
plate_thickness: float,
|
|
pin_bottom_z: float,
|
|
pin_radius: float,
|
|
hub_radius: float,
|
|
arm_width: float,
|
|
pad_radius: float,
|
|
) -> scad.Solid:
|
|
hub = scad.make_cylinder_rsolid(
|
|
radius=hub_radius,
|
|
height=plate_thickness,
|
|
bottom_face_center=(0.0, 0.0, plate_bottom_z),
|
|
axis=(0.0, 0.0, 1.0),
|
|
)
|
|
solids = [hub]
|
|
pin_height = plate_bottom_z + plate_thickness - pin_bottom_z
|
|
arm_inner_radius = hub_radius - 1.25
|
|
arm_outer_radius = stage.planet_center_radius + pad_radius - 0.25
|
|
arm_length = arm_outer_radius - arm_inner_radius
|
|
arm_center_radius = (arm_inner_radius + arm_outer_radius) / 2.0
|
|
for index in range(PLANET_COUNT):
|
|
angle = 360.0 * index / PLANET_COUNT
|
|
center = planet_center_xy(stage=stage, index=index)
|
|
arm = scad.make_box_rsolid(
|
|
width=arm_length,
|
|
height=arm_width,
|
|
depth=plate_thickness,
|
|
bottom_face_center=(arm_center_radius, 0.0, plate_bottom_z),
|
|
)
|
|
solids.append(
|
|
scad.rotate_shape(
|
|
shape=arm,
|
|
angle=angle,
|
|
axis=(0.0, 0.0, 1.0),
|
|
origin=(0.0, 0.0, 0.0),
|
|
)
|
|
)
|
|
solids.append(
|
|
scad.make_cylinder_rsolid(
|
|
radius=pad_radius,
|
|
height=plate_thickness,
|
|
bottom_face_center=(center[0], center[1], plate_bottom_z),
|
|
axis=(0.0, 0.0, 1.0),
|
|
)
|
|
)
|
|
solids.append(
|
|
scad.make_cylinder_rsolid(
|
|
radius=pin_radius,
|
|
height=pin_height,
|
|
bottom_face_center=(center[0], center[1], pin_bottom_z),
|
|
axis=(0.0, 0.0, 1.0),
|
|
)
|
|
)
|
|
carrier = scad.union_rsolid(solids, glue=False)
|
|
print(
|
|
f"{stage.stage_id}_carrier_body: arm_length={arm_length:.3f} "
|
|
f"hub_embed={hub_radius - arm_inner_radius:.3f} pin_height={pin_height:.3f}"
|
|
)
|
|
return carrier
|