Files
cadSet/SimpleCADAPI/examples/20_integrated_bldc_joint_actuator/assembly.py
T

449 lines
20 KiB
Python

"""Top-level integrated BLDC motor, controller, reducer, and housing assembly."""
from __future__ import annotations
import simplecadapi as scad
try:
from .bearings import (
make_coaxial_bearing_rplacement,
make_main_bearing_rassembly,
make_planet_bearing_rplacement,
make_standard_planet_bearing_rassembly,
)
from .common import connector_ref, ground_constraint_report
from .dimensions import (
FRONT_MOTOR_BEARING,
FRONT_MOTOR_BEARING_CENTER_Z,
INTERSTAGE_BEARING,
INTERSTAGE_BEARING_CENTER_Z,
OUTPUT_BEARING,
OUTPUT_BEARING_1_CENTER_Z,
OUTPUT_BEARING_2_CENTER_Z,
PLANET_BEARING,
PLANET_COUNT,
REAR_BEARING_CENTER_Z,
REAR_MOTOR_BEARING,
STAGE_1,
STAGE_2,
TOTAL_REDUCTION,
StageSpec,
)
from .electronics import make_integrated_controller_rassembly
from .gears import (
make_output_carrier_flange_rpart,
make_planet_rplacement,
make_stage1_carrier_sun_rpart,
make_stage_planet_gear_rpart,
make_stage_ring_gear_rpart,
)
from .housing import (
make_motor_shell_rpart,
make_output_bearing_cap_rpart,
make_rear_bearing_spider_rpart,
make_rear_electronics_cover_rpart,
make_reducer_housing_rpart,
)
from .motor import make_bldc_rotor_rassembly, make_bldc_stator_rassembly
except ImportError: # Support direct execution from this example directory.
from bearings import (
make_coaxial_bearing_rplacement,
make_main_bearing_rassembly,
make_planet_bearing_rplacement,
make_standard_planet_bearing_rassembly,
)
from common import connector_ref, ground_constraint_report
from dimensions import (
FRONT_MOTOR_BEARING,
FRONT_MOTOR_BEARING_CENTER_Z,
INTERSTAGE_BEARING,
INTERSTAGE_BEARING_CENTER_Z,
OUTPUT_BEARING,
OUTPUT_BEARING_1_CENTER_Z,
OUTPUT_BEARING_2_CENTER_Z,
PLANET_BEARING,
PLANET_COUNT,
REAR_BEARING_CENTER_Z,
REAR_MOTOR_BEARING,
STAGE_1,
STAGE_2,
TOTAL_REDUCTION,
StageSpec,
)
from electronics import make_integrated_controller_rassembly
from gears import (
make_output_carrier_flange_rpart,
make_planet_rplacement,
make_stage1_carrier_sun_rpart,
make_stage_planet_gear_rpart,
make_stage_ring_gear_rpart,
)
from housing import (
make_motor_shell_rpart,
make_output_bearing_cap_rpart,
make_rear_bearing_spider_rpart,
make_rear_electronics_cover_rpart,
make_reducer_housing_rpart,
)
from motor import make_bldc_rotor_rassembly, make_bldc_stator_rassembly
@scad.requires_session
def make_integrated_bldc_joint_actuator_rassembly(
*, materials: dict[str, scad.Material]
) -> scad.Assembly:
"""Build and solve the complete compact 50 mm joint actuator."""
component_specs = make_integrated_bldc_joint_actuator_components_rtuple(
materials=materials
)
actuator = scad.make_assembly_rassembly(
assembly_id="integrated_50mm_bldc_joint_actuator",
name="50 mm 12-slot/14-pole BLDC joint actuator with 20:1 reducer and circular ESC",
)
for component_id, item, placement, name in component_specs:
actuator = scad.add_component_rassembly(
assembly=actuator,
item=item,
component_id=component_id,
placement=placement,
name=name,
)
actuator = _add_public_connectors_rassembly(assembly=actuator)
actuator = _add_constraints_rassembly(assembly=actuator)
actuator = scad.solve_assembly_constraints_rassembly(assembly=actuator, strict=True)
ground_constraint_report(label="actuator", assembly=actuator)
return actuator
@scad.requires_session
def make_integrated_bldc_joint_actuator_components_rtuple(
*, materials: dict[str, scad.Material]
) -> tuple[tuple[str, scad.Part | scad.Assembly, scad.Placement, str], ...]:
"""Build the actuator component inventory without creating a parent assembly."""
print(
f"ratio_plan: stage1={STAGE_1.fixed_ring_ratio:.1f}:1 "
f"stage2={STAGE_2.fixed_ring_ratio:.1f}:1 total={TOTAL_REDUCTION:.1f}:1"
)
reducer_housing = make_reducer_housing_rpart(material=materials["housing"])
motor_shell = make_motor_shell_rpart(material=materials["housing"])
rear_spider = make_rear_bearing_spider_rpart(material=materials["carrier"])
rear_cover = make_rear_electronics_cover_rpart(material=materials["housing"])
output_cap = make_output_bearing_cap_rpart(material=materials["carrier"])
stator = make_bldc_stator_rassembly(
steel_material=materials["electrical_steel"],
copper_material=materials["copper"],
)
rotor = make_bldc_rotor_rassembly(
steel_material=materials["gear"],
magnet_material=materials["magnet"],
)
controller = make_integrated_controller_rassembly(
pcb_material=materials["pcb"],
terminal_material=materials["terminal"],
)
stage1_ring = make_stage_ring_gear_rpart(stage=STAGE_1, material=materials["gear"])
stage1_planet = make_stage_planet_gear_rpart(stage=STAGE_1, material=materials["gear"])
stage1_carrier = make_stage1_carrier_sun_rpart(material=materials["gear"])
stage2_ring = make_stage_ring_gear_rpart(stage=STAGE_2, material=materials["gear"])
stage2_planet = make_stage_planet_gear_rpart(stage=STAGE_2, material=materials["gear"])
output_carrier = make_output_carrier_flange_rpart(stage=STAGE_2, material=materials["carrier"])
rear_motor_bearing = make_main_bearing_rassembly(
bearing_id="rear_motor_8x16x5",
spec=REAR_MOTOR_BEARING,
material=materials["gear"],
)
front_motor_bearing = make_main_bearing_rassembly(
bearing_id="front_motor_8x19x6",
spec=FRONT_MOTOR_BEARING,
material=materials["gear"],
)
interstage_bearing = make_main_bearing_rassembly(
bearing_id="interstage_5x10x3",
spec=INTERSTAGE_BEARING,
material=materials["gear"],
)
planet_bearing = make_standard_planet_bearing_rassembly(
bearing_id="planet_3x6x3",
spec=PLANET_BEARING,
material=materials["gear"],
)
output_bearing = make_main_bearing_rassembly(
bearing_id="output_16x24x5",
spec=OUTPUT_BEARING,
material=materials["gear"],
)
fixed_components = (
("reducer_housing", reducer_housing, scad.identity_placement_rplacement(), "Fixed reducer housing"),
("motor_shell", motor_shell, scad.identity_placement_rplacement(), "Fixed BLDC shell"),
("rear_bearing_spider", rear_spider, scad.identity_placement_rplacement(), "Rear motor-bearing spider"),
("rear_electronics_cover", rear_cover, scad.identity_placement_rplacement(), "Rear controller cover"),
("output_bearing_cap", output_cap, scad.identity_placement_rplacement(), "Output bearing cap"),
("stator", stator, scad.identity_placement_rplacement(), "12-slot fixed stator"),
("rotor", rotor, scad.identity_placement_rplacement(), "14-pole rotor and direct sun shaft"),
("controller", controller, scad.identity_placement_rplacement(), "Circular integrated controller"),
("stage1_carrier", stage1_carrier, scad.identity_placement_rplacement(), "Stage 1 carrier and stage 2 sun"),
("output_carrier", output_carrier, scad.identity_placement_rplacement(), "Stage 2 carrier and output flange"),
("stage1_ring", stage1_ring, _stage_rplacement(stage=STAGE_1), "Stage 1 fixed ring insert"),
("stage2_ring", stage2_ring, _stage_rplacement(stage=STAGE_2), "Stage 2 fixed ring insert"),
)
print(f"actuator_base_components: count={len(fixed_components)}")
planet_components = []
for stage, planet in ((STAGE_1, stage1_planet), (STAGE_2, stage2_planet)):
for index in range(PLANET_COUNT):
planet_components.append(
(
f"{stage.stage_id}_planet_{index + 1}",
planet,
make_planet_rplacement(stage=stage, index=index),
f"{stage.label} planet {index + 1}",
)
)
bearing_components = (
(
"rear_motor_bearing",
rear_motor_bearing,
make_coaxial_bearing_rplacement(center_z=REAR_BEARING_CENTER_Z),
"Rear rotor bearing",
),
(
"front_motor_bearing",
front_motor_bearing,
make_coaxial_bearing_rplacement(center_z=FRONT_MOTOR_BEARING_CENTER_Z),
"Front rotor bearing",
),
(
"interstage_bearing",
interstage_bearing,
make_coaxial_bearing_rplacement(center_z=INTERSTAGE_BEARING_CENTER_Z),
"Stage 1 carrier support bearing",
),
(
"output_bearing_1",
output_bearing,
make_coaxial_bearing_rplacement(center_z=OUTPUT_BEARING_1_CENTER_Z),
"Rear output bearing",
),
(
"output_bearing_2",
output_bearing,
make_coaxial_bearing_rplacement(center_z=OUTPUT_BEARING_2_CENTER_Z),
"Front output bearing",
),
)
planet_bearing_components = []
for stage in (STAGE_1, STAGE_2):
for index in range(PLANET_COUNT):
planet_bearing_components.append(
(
f"{stage.stage_id}_planet_bearing_{index + 1}",
planet_bearing,
make_planet_bearing_rplacement(stage=stage, index=index),
f"{stage.label} planet bearing {index + 1}",
)
)
print(f"bearing_components: motor=2 interstage=1 output=2 planet={PLANET_COUNT * 2}")
return tuple(
[
*fixed_components,
*planet_components,
*bearing_components,
*planet_bearing_components,
]
)
@scad.requires_session
def _add_public_connectors_rassembly(*, assembly: scad.Assembly) -> scad.Assembly:
forwarded = (
("case_clamp_axis", "reducer_housing", "case_clamp_axis", "External split-clamp datum"),
("case_mount_axis", "output_bearing_cap", "case_mount_axis", "Fixed actuator case datum"),
("output_link_axis", "output_carrier", "output_link_axis", "Rotating six-hole output flange"),
("phase_terminal_access", "controller", "phase_access", "Rear phase-terminal service datum"),
("power_can_terminal_access", "controller", "power_can_access", "Rear power/CAN service datum"),
)
for connector_id, source_component_id, source_connector_id, name in forwarded:
assembly = scad.forward_connector_rassembly(
assembly=assembly,
connector_id=connector_id,
source_component_id=source_component_id,
source_connector_id=source_connector_id,
name=name,
offset=None,
)
print("actuator_public_connectors: " + ",".join(item[0] for item in forwarded))
return assembly
@scad.requires_session
def _add_constraints_rassembly(*, assembly: scad.Assembly) -> scad.Assembly:
assembly = scad.ground_component_rassembly(assembly=assembly, component_id="reducer_housing")
assembly = scad.ground_component_rassembly(assembly=assembly, component_id="stage1_ring")
assembly = scad.ground_component_rassembly(assembly=assembly, component_id="stage2_ring")
fixed_pairs = (
("motor_shell_to_reducer_housing", "reducer_housing", "motor_mount_axis", "motor_shell", "reducer_mount_axis"),
("rear_spider_to_motor_shell", "motor_shell", "rear_spider_axis", "rear_bearing_spider", "shell_axis"),
("rear_cover_to_motor_shell", "motor_shell", "rear_cover_axis", "rear_electronics_cover", "shell_axis"),
("stator_to_motor_shell", "motor_shell", "stator_axis", "stator", "shell_axis"),
("controller_to_rear_cover", "rear_electronics_cover", "pcb_axis", "controller", "cover_axis"),
("stage1_ring_fixed", "reducer_housing", "stage1_ring_axis", "stage1_ring", "axis"),
("stage2_ring_fixed", "reducer_housing", "stage2_ring_axis", "stage2_ring", "axis"),
("output_cap_to_reducer_housing", "reducer_housing", "output_cap_axis", "output_bearing_cap", "housing_axis"),
)
for constraint_id, a_component, a_connector, b_component, b_connector in fixed_pairs:
assembly = scad.add_fixed_constraint_rassembly(
assembly=assembly,
constraint_id=constraint_id,
connector_a=connector_ref(component_id=a_component, connector_id=a_connector),
connector_b=connector_ref(component_id=b_component, connector_id=b_connector),
name=constraint_id.replace("_", " "),
)
primary_revolutes = (
("rotor_revolute", "reducer_housing", "front_motor_bearing_axis", "rotor", "front_bearing_axis"),
("stage1_carrier_revolute", "reducer_housing", "stage1_carrier_axis", "stage1_carrier", "carrier_axis"),
("output_carrier_revolute", "reducer_housing", "stage2_carrier_axis", "output_carrier", "carrier_axis"),
)
for constraint_id, a_component, a_connector, b_component, b_connector in primary_revolutes:
assembly = scad.add_revolute_constraint_rassembly(
assembly=assembly,
constraint_id=constraint_id,
connector_a=connector_ref(component_id=a_component, connector_id=a_connector),
connector_b=connector_ref(component_id=b_component, connector_id=b_connector),
drive_angle_degrees=0.0,
angle_limit=None,
name=constraint_id.replace("_", " "),
)
assembly = _add_stage_constraints_rassembly(
assembly=assembly,
stage=STAGE_1,
sun_component="rotor",
sun_connector="front_bearing_axis",
ring_component="stage1_ring",
carrier_component="stage1_carrier",
)
assembly = _add_stage_constraints_rassembly(
assembly=assembly,
stage=STAGE_2,
sun_component="stage1_carrier",
sun_connector="carrier_axis",
ring_component="stage2_ring",
carrier_component="output_carrier",
)
assembly = _add_bearing_constraints_rassembly(assembly=assembly)
print("actuator_constraints: fixed=8 primary_revolute=3 planet_revolute=6 gear=6 internal=6 bearing_interfaces=22")
return assembly
@scad.requires_session
def _add_stage_constraints_rassembly(
*,
assembly: scad.Assembly,
stage: StageSpec,
sun_component: str,
sun_connector: str,
ring_component: str,
carrier_component: str,
) -> scad.Assembly:
for index in range(PLANET_COUNT):
planet_component = f"{stage.stage_id}_planet_{index + 1}"
assembly = scad.add_revolute_constraint_rassembly(
assembly=assembly,
constraint_id=f"{planet_component}_revolute",
connector_a=connector_ref(component_id=carrier_component, connector_id=f"planet_{index + 1}_axis"),
connector_b=connector_ref(component_id=planet_component, connector_id="axis"),
drive_angle_degrees=None,
angle_limit=None,
name=f"{stage.label} planet {index + 1} bearing axis",
)
assembly = scad.add_gear_constraint_rassembly(
assembly=assembly,
constraint_id=f"{stage.stage_id}_sun_planet_{index + 1}_mesh",
connector_a=connector_ref(component_id=sun_component, connector_id=sun_connector),
connector_b=connector_ref(component_id=planet_component, connector_id="axis"),
pitch_radius_a=stage.sun_pitch_radius,
pitch_radius_b=stage.planet_pitch_radius,
phase_offset=None,
name=f"{stage.label} sun to planet {index + 1} external mesh",
)
assembly = scad.add_belt_constraint_rassembly(
assembly=assembly,
constraint_id=f"{stage.stage_id}_ring_planet_{index + 1}_internal_mesh",
connector_a=connector_ref(component_id=ring_component, connector_id="axis"),
connector_b=connector_ref(component_id=planet_component, connector_id="axis"),
pulley_radius_a=stage.ring_pitch_radius,
pulley_radius_b=stage.planet_pitch_radius,
phase_offset=None,
name=f"{stage.label} fixed-ring to planet {index + 1} internal mesh",
)
print(
f"{stage.stage_id}_mesh: sun_r={stage.sun_pitch_radius:.3f} "
f"planet_r={stage.planet_pitch_radius:.3f} center={stage.planet_center_radius:.3f}"
)
return assembly
@scad.requires_session
def _add_bearing_constraints_rassembly(*, assembly: scad.Assembly) -> scad.Assembly:
interfaces = (
("rear_bearing_outer_to_spider", "rear_bearing_spider", "bearing_axis", "rear_motor_bearing", "outer_axis"),
("rear_bearing_inner_to_rotor", "rotor", "rear_bearing_axis", "rear_motor_bearing", "inner_axis"),
("front_bearing_outer_to_housing", "reducer_housing", "front_motor_bearing_axis", "front_motor_bearing", "outer_axis"),
("front_bearing_inner_to_rotor", "rotor", "front_bearing_axis", "front_motor_bearing", "inner_axis"),
("interstage_bearing_outer_to_housing", "reducer_housing", "interstage_bearing_axis", "interstage_bearing", "outer_axis"),
("interstage_bearing_inner_to_carrier", "stage1_carrier", "interstage_bearing_axis", "interstage_bearing", "inner_axis"),
("output_bearing_1_outer_to_cap", "output_bearing_cap", "bearing_1_axis", "output_bearing_1", "outer_axis"),
("output_bearing_1_inner_to_carrier", "output_carrier", "bearing_1_axis", "output_bearing_1", "inner_axis"),
("output_bearing_2_outer_to_cap", "output_bearing_cap", "bearing_2_axis", "output_bearing_2", "outer_axis"),
("output_bearing_2_inner_to_carrier", "output_carrier", "bearing_2_axis", "output_bearing_2", "inner_axis"),
)
for constraint_id, a_component, a_connector, b_component, b_connector in interfaces:
assembly = scad.add_revolute_constraint_rassembly(
assembly=assembly,
constraint_id=constraint_id,
connector_a=connector_ref(component_id=a_component, connector_id=a_connector),
connector_b=connector_ref(component_id=b_component, connector_id=b_connector),
drive_angle_degrees=None,
angle_limit=None,
name=constraint_id.replace("_", " "),
)
for stage, carrier_component in ((STAGE_1, "stage1_carrier"), (STAGE_2, "output_carrier")):
for index in range(PLANET_COUNT):
planet = f"{stage.stage_id}_planet_{index + 1}"
bearing = f"{stage.stage_id}_planet_bearing_{index + 1}"
assembly = scad.add_revolute_constraint_rassembly(
assembly=assembly,
constraint_id=f"{bearing}_outer_to_planet",
connector_a=connector_ref(component_id=planet, connector_id="bearing_axis"),
connector_b=connector_ref(component_id=bearing, connector_id="outer_axis"),
drive_angle_degrees=None,
angle_limit=None,
name=f"{stage.label} planet {index + 1} bearing outer-ring fit",
)
assembly = scad.add_revolute_constraint_rassembly(
assembly=assembly,
constraint_id=f"{bearing}_inner_to_pin",
connector_a=connector_ref(
component_id=carrier_component,
connector_id=f"planet_{index + 1}_bearing_axis",
),
connector_b=connector_ref(component_id=bearing, connector_id="inner_axis"),
drive_angle_degrees=None,
angle_limit=None,
name=f"{stage.label} planet {index + 1} bearing inner-ring pin fit",
)
return assembly
@scad.requires_session
def _stage_rplacement(*, stage: StageSpec) -> scad.Placement:
return scad.make_placement_rplacement(origin=(0.0, 0.0, stage.bottom_z))