diff --git a/nhf/touhou/houjuu_nue/joints.py b/nhf/touhou/houjuu_nue/joints.py index 126259d..ea4947f 100644 --- a/nhf/touhou/houjuu_nue/joints.py +++ b/nhf/touhou/houjuu_nue/joints.py @@ -305,13 +305,28 @@ class ShoulderJoint(Model): angle_neutral: float = -15.0 angle_max_deflection: float = 65.0 + spool_radius: float = 14.0 + spool_groove_depth: float = 1.0 + spool_base_height: float = 3.0 + spool_height: float = 5.0 + spool_groove_inset: float = 2.0 + def __post_init__(self): assert self.parent_lip_length * 2 < self.height + assert self.spool_groove_depth < self.spool_radius < self.torsion_joint.radius_rider - self.child_core_thickness + assert self.spool_base_height > self.spool_groove_depth @property def radius(self): return self.torsion_joint.radius + @property + def draft_length(self): + """ + Amount of wires that need to draft on the spool + """ + return (self.spool_radius - self.spool_groove_depth / 2) * math.radians(self.angle_max_deflection) + def parent_lip_loc(self, left: bool=True) -> Cq.Location: """ 2d location of the arm surface on the parent side, relative to axle @@ -416,7 +431,10 @@ class ShoulderJoint(Model): @target(name="parent-bot") def parent_bot(self) -> Cq.Assembly: - return self.parent(top=False) + result = ( + self.parent(top=False) + ) + return result @target(name="parent-top") def parent_top(self) -> Cq.Assembly: return self.parent(top=True) @@ -430,6 +448,36 @@ class ShoulderJoint(Model): joint = self.torsion_joint return self.height - 2 * joint.total_height + 2 * joint.rider_disk_height + def _spool(self) -> Cq.Workplane: + """ + Generates the spool piece which holds the line in tension + """ + t = self.spool_groove_depth + bulk = Cq.Solid.makeCylinder( + radius=self.spool_radius, + height=self.spool_height, + ).located(Cq.Location((0, 0, self.spool_base_height))) + base = Cq.Solid.makeCylinder( + radius=self.spool_radius - t, + height=self.spool_base_height, + ) + hole_x = self.spool_radius - (t + self.spool_groove_inset) + slot = Cq.Solid.makeBox( + length=t + self.spool_groove_inset, + width=t, + height=self.spool_base_height, + ).located(Cq.Location((hole_x, -t/2, 0))) + hole = Cq.Solid.makeBox( + length=t, + width=t, + height=self.spool_height + self.spool_base_height, + ).located(Cq.Location((hole_x, -t/2, 0))) + centre_hole = Cq.Solid.makeCylinder( + radius=self.torsion_joint.radius_axle, + height=self.spool_height + self.spool_base_height, + ) + return bulk.fuse(base).cut(slot, hole, centre_hole) + @target(name="child") def child(self) -> Cq.Assembly: """ @@ -512,6 +560,8 @@ class ShoulderJoint(Model): loc_rotate = Cq.Location((0, 0, 0), (1, 0, 0), 180) loc_axis_rotate_bot = Cq.Location((0, 0, 0), (0, 0, 1), self.axis_rotate_bot + self.angle_neutral) loc_axis_rotate_top = Cq.Location((0, 0, 0), (0, 0, 1), self.axis_rotate_top + self.angle_neutral) + spool_dz = self.height / 2 - self.torsion_joint.total_height + spool_angle = 180 + self.angle_neutral result = ( Cq.Assembly() .add(core, name="core", loc=Cq.Location()) @@ -523,6 +573,8 @@ class ShoulderJoint(Model): loc=Cq.Location((self.child_guard_ext, 0, dh))) .add(lip, name="lip_bot", loc=Cq.Location((self.child_guard_ext, 0, -dh)) * loc_rotate) + .add(self._spool(), name="spool", + loc=Cq.Location((0, 0, -spool_dz), (0, 0, 1), spool_angle)) ) return result