From 0cc6100d0ed89b578d9de969074913fbe0d44132 Mon Sep 17 00:00:00 2001 From: Leni Aniva Date: Tue, 16 Jul 2024 14:25:17 -0700 Subject: [PATCH] refactor: Move flip to ElbowJoint --- nhf/touhou/houjuu_nue/__init__.py | 2 -- nhf/touhou/houjuu_nue/joints.py | 22 +++++++++++++------ nhf/touhou/houjuu_nue/wing.py | 36 ++++++++++++++++++++----------- 3 files changed, 39 insertions(+), 21 deletions(-) diff --git a/nhf/touhou/houjuu_nue/__init__.py b/nhf/touhou/houjuu_nue/__init__.py index 0a05a35..d9b3f26 100644 --- a/nhf/touhou/houjuu_nue/__init__.py +++ b/nhf/touhou/houjuu_nue/__init__.py @@ -65,8 +65,6 @@ class Parameters(Model): shoulder_joint=MJ.ShoulderJoint( height=100.0, ), - elbow_joint=MJ.ElbowJoint(), - wrist_joint=MJ.ElbowJoint(), elbow_height=110.0, )) diff --git a/nhf/touhou/houjuu_nue/joints.py b/nhf/touhou/houjuu_nue/joints.py index 5d2b895..cff350e 100644 --- a/nhf/touhou/houjuu_nue/joints.py +++ b/nhf/touhou/houjuu_nue/joints.py @@ -261,18 +261,22 @@ class Beam: plane.moveTo(-dx, 0).tagPlane("conn0") return result - def beam(self) -> Cq.Assembly: + def generate(self, flip: bool = False) -> Cq.Assembly: beam = ( Cq.Workplane('XZ') .box(self.spine_length, self.spine_thickness, self.spine_height) ) h = self.spine_height / 2 + self.foot_height + + tag_p, tag_n = "top", "bot" + if flip: + tag_p, tag_n = tag_n, tag_p result = ( Cq.Assembly() .add(beam, name="beam") - .add(self.foot(), name="top", + .add(self.foot(), name=tag_p, loc=Cq.Location((0, h, 0))) - .add(self.foot(), name="bot", + .add(self.foot(), name=tag_n, loc=Cq.Location((0, -h, 0), (1, 0, 0), 180)) ) return result @@ -301,7 +305,7 @@ class DiskJoint(Model): #disk_thickness_gap: float = 0.1 # Spring angle at 0 degrees of movement - spring_angle_at_0: float = 30.0 + spring_angle_at_0: float = 60.0 spring_slot_offset: float = 15.0 wall_inset: float = 2.0 @@ -493,6 +497,7 @@ class DiskJoint(Model): disk: str, angle: float = 0.0, ) -> Cq.Assembly: + assert 0 <= angle <= self.movement_angle deflection = angle - self.neutral_movement_angle spring_name = disk.replace("/", "__Z") + "_spring" ( @@ -541,7 +546,7 @@ class DiskJoint(Model): return result.solve() -@dataclass +@dataclass(kw_only=True) class ElbowJoint: """ Creates the elbow and wrist joints. @@ -576,6 +581,9 @@ class ElbowJoint: material: Material = Material.RESIN_TRANSPERENT + # If true, flip the top and bottom tags + flip: bool = False + def __post_init__(self): assert self.child_arm_radius > self.disk_joint.radius_housing assert self.parent_arm_radius > self.disk_joint.radius_housing @@ -605,7 +613,7 @@ class ElbowJoint: flip_x = Cq.Location((0, 0, 0), (1, 0, 0), 180) flip_z = Cq.Location((0, 0, 0), (0, 0, 1), 180) result = ( - self.child_beam.beam() + self.child_beam.generate(flip=self.flip) .add(self.disk_joint.disk(), name="disk", loc=flip_x * flip_z * Cq.Location((-self.child_arm_radius, 0, -dz), (0, 0, 1), angle)) #.constrain("disk", "Fixed") @@ -641,7 +649,7 @@ class ElbowJoint: -self.disk_joint.tongue_span / 2 ) result = ( - self.parent_beam.beam() + self.parent_beam.generate(flip=self.flip) .add(housing, name="housing", loc=axial_offset * housing_loc) .add(connector, name="connector", diff --git a/nhf/touhou/houjuu_nue/wing.py b/nhf/touhou/houjuu_nue/wing.py index 99fcde2..c1e038f 100644 --- a/nhf/touhou/houjuu_nue/wing.py +++ b/nhf/touhou/houjuu_nue/wing.py @@ -11,10 +11,10 @@ from nhf import Material, Role from nhf.build import Model, target, assembly from nhf.parts.box import box_with_centre_holes, MountingBox, Hole from nhf.parts.joints import HirthJoint -from nhf.touhou.houjuu_nue.joints import ShoulderJoint, ElbowJoint +from nhf.touhou.houjuu_nue.joints import ShoulderJoint, ElbowJoint, DiskJoint import nhf.utils -@dataclass +@dataclass(kw_only=True) class WingProfile(Model): name: str = "wing" @@ -34,7 +34,12 @@ class WingProfile(Model): s1_thickness: float = 25.0 - elbow_joint: ElbowJoint = field(default_factory=lambda: ElbowJoint()) + elbow_joint: ElbowJoint = field(default_factory=lambda: ElbowJoint( + disk_joint=DiskJoint( + movement_angle=55, + ), + flip=False, + )) elbow_height: float = 100 elbow_x: float = 240 elbow_y: float = 30 @@ -43,7 +48,12 @@ class WingProfile(Model): s2_thickness: float = 25.0 - wrist_joint: ElbowJoint = field(default_factory=lambda: ElbowJoint()) + wrist_joint: ElbowJoint = field(default_factory=lambda: ElbowJoint( + disk_joint=DiskJoint( + movement_angle=45, + ), + flip=True, + )) wrist_height: float = 70 # Bottom point of the wrist wrist_x: float = 400 @@ -548,6 +558,8 @@ class WingProfile(Model): parts: Optional[list[str]] = None, angle_elbow_wrist: float = 0.0, ) -> Cq.Assembly(): + assert not self.elbow_joint.flip + assert self.wrist_joint.flip if parts is None: parts = ["s0", "shoulder", "s1", "elbow", "s2", "wrist", "s3"] result = ( @@ -601,20 +613,20 @@ class WingProfile(Model): # Mounted backwards to bend in other direction ( result - .constrain("s2/wrist_top?conn0", "wrist/parent_upper/bot?conn0", "Plane") - .constrain("s2/wrist_top?conn1", "wrist/parent_upper/bot?conn1", "Plane") - .constrain("s2/wrist_bot?conn0", "wrist/parent_upper/top?conn0", "Plane") - .constrain("s2/wrist_bot?conn1", "wrist/parent_upper/top?conn1", "Plane") + .constrain("s2/wrist_top?conn0", "wrist/parent_upper/top?conn0", "Plane") + .constrain("s2/wrist_top?conn1", "wrist/parent_upper/top?conn1", "Plane") + .constrain("s2/wrist_bot?conn0", "wrist/parent_upper/bot?conn0", "Plane") + .constrain("s2/wrist_bot?conn1", "wrist/parent_upper/bot?conn1", "Plane") ) if "s3" in parts: result.add(self.assembly_s3(), name="s3") if "s3" in parts and "wrist" in parts: ( result - .constrain("s3/wrist_top?conn0", "wrist/child/bot?conn0", "Plane") - .constrain("s3/wrist_top?conn1", "wrist/child/bot?conn1", "Plane") - .constrain("s3/wrist_bot?conn0", "wrist/child/top?conn0", "Plane") - .constrain("s3/wrist_bot?conn1", "wrist/child/top?conn1", "Plane") + .constrain("s3/wrist_top?conn0", "wrist/child/top?conn0", "Plane") + .constrain("s3/wrist_top?conn1", "wrist/child/top?conn1", "Plane") + .constrain("s3/wrist_bot?conn0", "wrist/child/bot?conn0", "Plane") + .constrain("s3/wrist_bot?conn1", "wrist/child/bot?conn1", "Plane") ) if len(parts) > 1: result.solve()