"""Serviceable motor shell, reducer case, bearing caps, and electronics cover.""" from __future__ import annotations import simplecadapi as scad try: from .common import ( apply_tags, make_annulus_rsolid, make_axis_part_rpart, make_axial_hole_cutters_rsolids, radial_centers, ) from .dimensions import ( FRONT_MOTOR_BEARING, FRONT_MOTOR_BEARING_CENTER_Z, HOUSING_INTERFACE_LAND_INNER_RADIUS, INTERSTAGE_BEARING, INTERSTAGE_BEARING_CENTER_Z, MOTOR_INTERFACE_PCD, MOTOR_SHELL_BOTTOM_Z, MOTOR_SHELL_INNER_RADIUS, MOTOR_SHELL_TOP_Z, MOTOR_STATOR_BOTTOM_Z, MOTOR_STATOR_TOP_Z, M3_CLEARANCE_RADIUS, OUTPUT_BEARING_1_CENTER_Z, OUTPUT_BEARING_2_CENTER_Z, OUTPUT_CAP_BOTTOM_Z, OUTPUT_CAP_CARTRIDGE_TOP_Z, OUTPUT_CAP_INTERFACE_PCD, OUTPUT_CAP_TOP_Z, OUTPUT_CASE_CLAMP_CENTER_Z, OUTPUT_FLANGE_RADIUS, PACKAGE_RADIUS, PCB_BOTTOM_Z, PCB_STANDOFF_PCD, REAR_BEARING_CENTER_Z, REAR_COLUMN_PCD, REAR_COLUMN_RADIUS, REAR_COVER_BOTTOM_Z, REAR_COVER_THICKNESS, REAR_FASTENER_HOLE_RADIUS, REAR_SPIDER_BOSS_RADIUS, REAR_SPIDER_BOTTOM_Z, REDUCER_HOUSING_BOTTOM_Z, REDUCER_HOUSING_FRONT_Z, REDUCER_HOUSING_INNER_RADIUS, STAGE1_CARRIER_BOTTOM_Z, STAGE2_CARRIER_BOTTOM_Z, STAGE_1, STAGE_2, ) except ImportError: # Support direct execution from this example directory. from common import ( apply_tags, make_annulus_rsolid, make_axial_hole_cutters_rsolids, make_axis_part_rpart, radial_centers, ) from dimensions import ( FRONT_MOTOR_BEARING, FRONT_MOTOR_BEARING_CENTER_Z, HOUSING_INTERFACE_LAND_INNER_RADIUS, INTERSTAGE_BEARING, INTERSTAGE_BEARING_CENTER_Z, M3_CLEARANCE_RADIUS, MOTOR_INTERFACE_PCD, MOTOR_SHELL_BOTTOM_Z, MOTOR_SHELL_INNER_RADIUS, MOTOR_SHELL_TOP_Z, MOTOR_STATOR_BOTTOM_Z, MOTOR_STATOR_TOP_Z, OUTPUT_BEARING_1_CENTER_Z, OUTPUT_BEARING_2_CENTER_Z, OUTPUT_CAP_BOTTOM_Z, OUTPUT_CAP_CARTRIDGE_TOP_Z, OUTPUT_CAP_INTERFACE_PCD, OUTPUT_CAP_TOP_Z, OUTPUT_CASE_CLAMP_CENTER_Z, OUTPUT_FLANGE_RADIUS, PACKAGE_RADIUS, PCB_BOTTOM_Z, PCB_STANDOFF_PCD, REAR_BEARING_CENTER_Z, REAR_COLUMN_PCD, REAR_COLUMN_RADIUS, REAR_COVER_BOTTOM_Z, REAR_COVER_THICKNESS, REAR_FASTENER_HOLE_RADIUS, REAR_SPIDER_BOSS_RADIUS, REAR_SPIDER_BOTTOM_Z, REDUCER_HOUSING_BOTTOM_Z, REDUCER_HOUSING_FRONT_Z, REDUCER_HOUSING_INNER_RADIUS, STAGE1_CARRIER_BOTTOM_Z, STAGE2_CARRIER_BOTTOM_Z, STAGE_1, STAGE_2, ) def make_motor_shell_rpart(*, material: scad.Material) -> scad.Part: """Create the stator sleeve, front attachment land, and rear columns.""" sleeve = make_annulus_rsolid( outer_radius=PACKAGE_RADIUS, inner_radius=MOTOR_SHELL_INNER_RADIUS, bottom_z=MOTOR_SHELL_BOTTOM_Z, height=MOTOR_SHELL_TOP_Z - MOTOR_SHELL_BOTTOM_Z, tags=("role.motor_shell", "role.stator_thermal_path"), ) front_land = make_annulus_rsolid( outer_radius=PACKAGE_RADIUS, inner_radius=HOUSING_INTERFACE_LAND_INNER_RADIUS, bottom_z=MOTOR_SHELL_TOP_Z - 1.4, height=1.4, tags=("role.motor_reducer_mount",), ) columns = [] for _index, _angle, center in radial_centers(count=4, radius=REAR_COLUMN_PCD / 2.0): columns.append( scad.make_cylinder_rsolid( radius=REAR_COLUMN_RADIUS, height=REAR_SPIDER_BOTTOM_Z - MOTOR_SHELL_BOTTOM_Z, bottom_face_center=(center[0], center[1], MOTOR_SHELL_BOTTOM_Z), axis=(0.0, 0.0, 1.0), ) ) shell = scad.union_rsolid(sleeve, front_land, columns, glue=False) shell = scad.cut_rsolid( shell, make_axial_hole_cutters_rsolids( count=6, pcd=MOTOR_INTERFACE_PCD, hole_radius=M3_CLEARANCE_RADIUS, bottom_z=MOTOR_SHELL_TOP_Z - 2.8, height=3.6, angle_offset=30.0, ), make_axial_hole_cutters_rsolids( count=4, pcd=REAR_COLUMN_PCD, hole_radius=REAR_FASTENER_HOLE_RADIUS, bottom_z=MOTOR_SHELL_BOTTOM_Z - 1.0, height=10.4, ), skip_non_intersecting=False, ) shell = apply_tags( shape=shell, tags=("role.fixed_motor_housing", "group.integrated_bldc_actuator"), ) print( f"motor_shell_interface: stator_d={MOTOR_SHELL_INNER_RADIUS * 2.0:.2f} " f"front_holes=6 rear_columns=4 wall={PACKAGE_RADIUS - MOTOR_SHELL_INNER_RADIUS:.2f}" ) return make_axis_part_rpart( part_id="motor_shell", body=shell, name="50 mm BLDC motor shell with rear structural columns", material=material, connectors=( ("reducer_mount_axis", (0.0, 0.0, MOTOR_SHELL_TOP_Z), "Six-screw reducer mount"), ( "stator_axis", (0.0, 0.0, (MOTOR_STATOR_BOTTOM_Z + MOTOR_STATOR_TOP_Z) / 2.0), "Stator thermal press-fit axis", ), ("rear_spider_axis", (0.0, 0.0, REAR_SPIDER_BOTTOM_Z), "Rear bearing spider mount"), ("rear_cover_axis", (0.0, 0.0, MOTOR_SHELL_BOTTOM_Z), "Rear electronics cover mount"), ), ) def make_reducer_housing_rpart(*, material: scad.Material) -> scad.Part: """Create the reducer sleeve and front motor-bearing bulkhead.""" sleeve = make_annulus_rsolid( outer_radius=PACKAGE_RADIUS, inner_radius=REDUCER_HOUSING_INNER_RADIUS, bottom_z=REDUCER_HOUSING_BOTTOM_Z, height=REDUCER_HOUSING_FRONT_Z - REDUCER_HOUSING_BOTTOM_Z, tags=("role.reducer_housing_sleeve",), ) bulkhead = make_annulus_rsolid( outer_radius=23.10, inner_radius=FRONT_MOTOR_BEARING.outer_diameter / 2.0 + 0.05, bottom_z=REDUCER_HOUSING_BOTTOM_Z, height=STAGE_1.bottom_z - REDUCER_HOUSING_BOTTOM_Z, tags=("role.motor_front_bearing_bulkhead",), ) interstage_divider = make_annulus_rsolid( outer_radius=23.10, inner_radius=INTERSTAGE_BEARING.outer_diameter / 2.0 + 0.05, bottom_z=INTERSTAGE_BEARING_CENTER_Z - INTERSTAGE_BEARING.width / 2.0, height=INTERSTAGE_BEARING.width, tags=("role.interstage_bearing_divider",), ) output_mount_land = make_annulus_rsolid( outer_radius=PACKAGE_RADIUS, inner_radius=HOUSING_INTERFACE_LAND_INNER_RADIUS, bottom_z=REDUCER_HOUSING_FRONT_Z - 2.2, height=2.2, tags=("role.output_cap_mount_land",), ) housing = scad.union_rsolid( sleeve, bulkhead, interstage_divider, output_mount_land, glue=False, ) housing = scad.cut_rsolid( housing, make_axial_hole_cutters_rsolids( count=6, pcd=MOTOR_INTERFACE_PCD, hole_radius=M3_CLEARANCE_RADIUS, bottom_z=REDUCER_HOUSING_BOTTOM_Z - 1.0, height=STAGE_1.bottom_z - REDUCER_HOUSING_BOTTOM_Z + 2.0, angle_offset=30.0, ), make_axial_hole_cutters_rsolids( count=6, pcd=OUTPUT_CAP_INTERFACE_PCD, hole_radius=M3_CLEARANCE_RADIUS, bottom_z=REDUCER_HOUSING_FRONT_Z - 2.2, height=3.2, ), skip_non_intersecting=False, ) housing = apply_tags( shape=housing, tags=("role.fixed_reducer_housing", "role.ring_gear_press_fit", "group.integrated_bldc_actuator"), ) print( f"reducer_housing: bore_d={REDUCER_HOUSING_INNER_RADIUS * 2.0:.2f} " f"wall={PACKAGE_RADIUS - REDUCER_HOUSING_INNER_RADIUS:.2f} bulkhead=8.00 " f"interstage_bearing_z={INTERSTAGE_BEARING_CENTER_Z:.2f} " f"m3_inner_ligament={MOTOR_INTERFACE_PCD / 2.0 - M3_CLEARANCE_RADIUS - HOUSING_INTERFACE_LAND_INNER_RADIUS:.2f}" ) return make_axis_part_rpart( part_id="reducer_housing", body=housing, name="50 mm reducer housing with motor bearing bulkhead", material=material, connectors=( ("motor_mount_axis", (0.0, 0.0, MOTOR_SHELL_TOP_Z), "Motor shell six-screw interface"), ("front_motor_bearing_axis", (0.0, 0.0, FRONT_MOTOR_BEARING_CENTER_Z), "Front motor bearing seat"), ("stage1_ring_axis", (0.0, 0.0, STAGE_1.mid_z), "Stage 1 fixed ring seat"), ("stage1_carrier_axis", (0.0, 0.0, INTERSTAGE_BEARING_CENTER_Z), "Stage 1 carrier axis"), ("interstage_bearing_axis", (0.0, 0.0, INTERSTAGE_BEARING_CENTER_Z), "Interstage bearing outer seat"), ("stage2_ring_axis", (0.0, 0.0, STAGE_2.mid_z), "Stage 2 fixed ring seat"), ("stage2_carrier_axis", (0.0, 0.0, STAGE2_CARRIER_BOTTOM_Z + 1.50), "Output carrier axis"), ( "case_clamp_axis", (0.0, 0.0, OUTPUT_CASE_CLAMP_CENTER_Z), "External split-clamp datum on reducer sleeve", ), ("output_cap_axis", (0.0, 0.0, REDUCER_HOUSING_FRONT_Z), "Output bearing cap interface"), ), ) def make_rear_bearing_spider_rpart(*, material: scad.Material) -> scad.Part: """Create a four-arm removable rear motor-bearing support.""" bottom_z = REAR_SPIDER_BOTTOM_Z hub = make_annulus_rsolid( outer_radius=10.5, inner_radius=8.05, bottom_z=bottom_z, height=5.0, tags=("role.rear_motor_bearing_seat",), ) solids = [hub] for _index, angle, center in radial_centers(count=4, radius=REAR_COLUMN_PCD / 2.0): arm = scad.make_box_rsolid( width=12.0, height=3.0, depth=5.0, bottom_face_center=(14.5, 0.0, 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=REAR_SPIDER_BOSS_RADIUS, height=5.0, bottom_face_center=(center[0], center[1], bottom_z), axis=(0.0, 0.0, 1.0), ) ) spider = scad.union_rsolid(solids, glue=False) spider = scad.cut_rsolid( spider, make_axial_hole_cutters_rsolids( count=4, pcd=REAR_COLUMN_PCD, hole_radius=REAR_FASTENER_HOLE_RADIUS, bottom_z=bottom_z - 1.0, height=7.0, ), skip_non_intersecting=False, ) spider = apply_tags( shape=spider, tags=("role.removable_rear_bearing_spider", "group.integrated_bldc_actuator"), ) print("rear_bearing_spider: arms=4 bearing_seat_d=16.10 fasteners=4") return make_axis_part_rpart( part_id="rear_bearing_spider", body=spider, name="Four-arm removable rear motor-bearing spider", material=material, connectors=( ("shell_axis", (0.0, 0.0, REAR_SPIDER_BOTTOM_Z), "Motor shell column interface"), ("bearing_axis", (0.0, 0.0, REAR_BEARING_CENTER_Z), "Rear motor bearing outer seat"), ), ) def make_rear_electronics_cover_rpart(*, material: scad.Material) -> scad.Part: """Create the rear cover with PCB standoffs and terminal apertures.""" cover = scad.make_cylinder_rsolid( radius=PACKAGE_RADIUS, height=REAR_COVER_THICKNESS, bottom_face_center=(0.0, 0.0, REAR_COVER_BOTTOM_Z), axis=(0.0, 0.0, 1.0), ) standoffs = [] for _index, _angle, center in radial_centers(count=4, radius=PCB_STANDOFF_PCD / 2.0, angle_offset=45.0): standoffs.append( scad.make_cylinder_rsolid( radius=2.4, height=PCB_BOTTOM_Z - REAR_COVER_BOTTOM_Z - REAR_COVER_THICKNESS + 0.1, bottom_face_center=(center[0], center[1], REAR_COVER_BOTTOM_Z + REAR_COVER_THICKNESS - 0.1), axis=(0.0, 0.0, 1.0), ) ) cover = scad.union_rsolid(cover, standoffs, glue=False) phase_aperture = scad.make_box_rsolid( width=9.2, height=7.2, depth=REAR_COVER_THICKNESS + 2.0, bottom_face_center=(-11.0, 0.0, REAR_COVER_BOTTOM_Z - 1.0), ) power_aperture = scad.make_box_rsolid( width=9.2, height=7.2, depth=REAR_COVER_THICKNESS + 2.0, bottom_face_center=(11.0, 0.0, REAR_COVER_BOTTOM_Z - 1.0), ) center_service = scad.make_cylinder_rsolid( radius=3.2, height=REAR_COVER_THICKNESS + 2.0, bottom_face_center=(0.0, 0.0, REAR_COVER_BOTTOM_Z - 1.0), axis=(0.0, 0.0, 1.0), ) cover = scad.cut_rsolid( cover, phase_aperture, power_aperture, center_service, make_axial_hole_cutters_rsolids( count=4, pcd=REAR_COLUMN_PCD, hole_radius=REAR_FASTENER_HOLE_RADIUS, bottom_z=REAR_COVER_BOTTOM_Z - 1.0, height=REAR_COVER_THICKNESS + 2.0, ), make_axial_hole_cutters_rsolids( count=4, pcd=PCB_STANDOFF_PCD, hole_radius=1.1, bottom_z=REAR_COVER_BOTTOM_Z - 1.0, height=PCB_BOTTOM_Z - REAR_COVER_BOTTOM_Z + 2.0, angle_offset=45.0, ), skip_non_intersecting=False, ) cover = apply_tags( shape=cover, tags=("role.rear_electronics_cover", "role.terminal_access", "group.integrated_bldc_actuator"), ) print("rear_cover_access: phase_opening=9.2x7.2 power_can_opening=9.2x7.2 pcb_holes=4") return make_axis_part_rpart( part_id="rear_electronics_cover", body=cover, name="Rear electronics cover with terminal access", material=material, connectors=( ("shell_axis", (0.0, 0.0, MOTOR_SHELL_BOTTOM_Z), "Four-screw motor shell interface"), ("pcb_axis", (0.0, 0.0, PCB_BOTTOM_Z + 0.8), "Controller PCB mounting plane"), ("phase_access", (-11.0, 0.0, REAR_COVER_BOTTOM_Z), "Three-phase terminal access"), ("power_can_access", (11.0, 0.0, REAR_COVER_BOTTOM_Z), "Power and CAN terminal access"), ), ) def make_output_bearing_cap_rpart(*, material: scad.Material) -> scad.Part: """Create the removable paired-bearing cartridge and front cap.""" bearing_clearance_radius = 12.05 rear_flange = make_annulus_rsolid( outer_radius=PACKAGE_RADIUS, inner_radius=bearing_clearance_radius, bottom_z=OUTPUT_CAP_BOTTOM_Z, height=3.0, tags=("role.output_cap_mount_flange",), ) cartridge = make_annulus_rsolid( outer_radius=15.0, inner_radius=bearing_clearance_radius, bottom_z=OUTPUT_CAP_BOTTOM_Z, height=OUTPUT_CAP_CARTRIDGE_TOP_Z - OUTPUT_CAP_BOTTOM_Z + 0.1, tags=("role.paired_output_bearing_seat",), ) bearing_retainer = make_annulus_rsolid( outer_radius=PACKAGE_RADIUS, inner_radius=8.10, bottom_z=OUTPUT_CAP_CARTRIDGE_TOP_Z - 0.1, height=0.5, tags=("role.output_axial_retainer",), ) outer_lip = make_annulus_rsolid( outer_radius=PACKAGE_RADIUS, inner_radius=OUTPUT_FLANGE_RADIUS + 0.30, bottom_z=OUTPUT_CAP_CARTRIDGE_TOP_Z - 0.1, height=OUTPUT_CAP_TOP_Z - OUTPUT_CAP_CARTRIDGE_TOP_Z + 0.1, tags=("role.output_labyrinth_lip",), ) cap = scad.union_rsolid(rear_flange, cartridge, bearing_retainer, outer_lip, glue=False) cap = scad.cut_rsolid( cap, make_axial_hole_cutters_rsolids( count=6, pcd=OUTPUT_CAP_INTERFACE_PCD, hole_radius=M3_CLEARANCE_RADIUS, bottom_z=OUTPUT_CAP_BOTTOM_Z - 1.0, height=OUTPUT_CAP_TOP_Z - OUTPUT_CAP_BOTTOM_Z + 2.0, ), skip_non_intersecting=False, ) cap = apply_tags( shape=cap, tags=("role.removable_output_bearing_cap", "group.integrated_bldc_actuator"), ) print( f"output_bearing_cap: bearing_seat_d={bearing_clearance_radius * 2.0:.2f} " f"bearing_span={OUTPUT_BEARING_2_CENTER_Z - OUTPUT_BEARING_1_CENTER_Z:.1f} fasteners=6" ) return make_axis_part_rpart( part_id="output_bearing_cap", body=cap, name="Paired output-bearing cartridge and removable cap", material=material, connectors=( ("housing_axis", (0.0, 0.0, OUTPUT_CAP_BOTTOM_Z), "Six-screw housing interface"), ("bearing_1_axis", (0.0, 0.0, OUTPUT_BEARING_1_CENTER_Z), "Rear output bearing seat"), ("bearing_2_axis", (0.0, 0.0, OUTPUT_BEARING_2_CENTER_Z), "Front output bearing seat"), ("case_mount_axis", (0.0, 0.0, OUTPUT_CAP_TOP_Z), "Fixed actuator case datum"), ), )