Cosplay/nhf/touhou/houjuu_nue/electronics.py

156 lines
4.3 KiB
Python

"""
Electronic components
"""
from dataclasses import dataclass
import cadquery as Cq
from nhf.materials import Role
from nhf.parts.item import Item
from nhf.parts.fasteners import FlatHeadBolt, HexNut
@dataclass(frozen=True)
class LinearActuator(Item):
stroke_length: float
shaft_diam: float = 9.04
front_hole_ext: float = 4.41
front_hole_diam: float = 4.41
front_length: float = 9.55
front_width: float = 9.24
front_height: float = 5.98
segment1_length: float = 37.55
segment1_width: float = 15.95
segment1_height: float = 11.94
segment2_length: float = 37.47
segment2_width: float = 20.03
segment2_height: float = 15.03
back_hole_ext: float = 4.58
back_hole_diam: float = 4.18
back_length: float = 9.27
back_width: float = 10.16
back_height: float = 8.12
@property
def name(self) -> str:
return f"LinearActuator {self.stroke_length}mm"
@property
def role(self) -> Role:
return Role.MOTION
@property
def conn_length(self):
return self.segment1_length + self.segment2_length + self.front_hole_ext + self.back_hole_ext
def generate(self, pos: float=0) -> Cq.Assembly:
stroke_x = pos * self.stroke_length
front = (
Cq.Workplane('XZ')
.cylinder(
radius=self.front_width / 2,
height=self.front_height,
centered=True,
)
.box(
length=self.front_hole_ext,
width=self.front_width,
height=self.front_height,
combine=True,
centered=(False, True, True)
)
.copyWorkplane(Cq.Workplane('XZ'))
.cylinder(
radius=self.front_hole_diam / 2,
height=self.front_height,
centered=True,
combine='cut',
)
)
if stroke_x > 0:
shaft = (
Cq.Workplane('YZ')
.cylinder(
radius=self.shaft_diam / 2,
height=stroke_x,
centered=(True, True, False)
)
)
else:
shaft = None
segment1 = (
Cq.Workplane()
.box(
length=self.segment1_length,
height=self.segment1_width,
width=self.segment1_height,
centered=(False, True, True),
)
)
segment2 = (
Cq.Workplane()
.box(
length=self.segment2_length,
height=self.segment2_width,
width=self.segment2_height,
centered=(False, True, True),
)
)
back = (
Cq.Workplane('XZ')
.cylinder(
radius=self.back_width / 2,
height=self.back_height,
centered=True,
)
.box(
length=self.back_hole_ext,
width=self.back_width,
height=self.back_height,
combine=True,
centered=(False, True, True)
)
.copyWorkplane(Cq.Workplane('XZ'))
.cylinder(
radius=self.back_hole_diam / 2,
height=self.back_height,
centered=True,
combine='cut',
)
)
result = (
Cq.Assembly()
.add(front, name="front",
loc=Cq.Location((-self.front_hole_ext, 0, 0)))
.add(segment1, name="segment1",
loc=Cq.Location((stroke_x, 0, 0)))
.add(segment2, name="segment2",
loc=Cq.Location((stroke_x + self.segment1_length, 0, 0)))
.add(back, name="back",
loc=Cq.Location((stroke_x + self.segment1_length + self.segment2_length + self.back_hole_ext, 0, 0), (0, 1, 0), 180))
)
if shaft:
result.add(shaft, name="shaft")
return result
LINEAR_ACTUATOR_SHOULDER = LinearActuator(
mass=34.0,
stroke_length=30,
)
LINEAR_ACTUATOR_HEX_NUT = HexNut(
mass=0.8,
diam_thread=4,
pitch=0.7,
thickness=4.16,
width=6.79,
)
LINEAR_ACTUATOR_BOLT = FlatHeadBolt(
mass=1.7,
diam_head=16.68,
height_head=2.98,
diam_thread=4.0,
height_thread=15.83,
)