From da58eeafe6a409f373bb6fe15bd740944d64534b Mon Sep 17 00:00:00 2001 From: Leni Aniva Date: Tue, 23 Jul 2024 22:40:49 -0700 Subject: [PATCH] feat: Option to simplify geometry --- nhf/touhou/houjuu_nue/electronics.py | 3 ++ nhf/touhou/houjuu_nue/joints.py | 69 ++++++++++++++++++---------- nhf/touhou/houjuu_nue/wing.py | 36 ++++++++++++--- 3 files changed, 76 insertions(+), 32 deletions(-) diff --git a/nhf/touhou/houjuu_nue/electronics.py b/nhf/touhou/houjuu_nue/electronics.py index ae114e1..8f5db83 100644 --- a/nhf/touhou/houjuu_nue/electronics.py +++ b/nhf/touhou/houjuu_nue/electronics.py @@ -390,6 +390,8 @@ class Flexor: pos = (target_length - self.actuator.conn_length) / self.actuator.stroke_length if tag_prefix: tag_prefix = tag_prefix + "_" + else: + tag_prefix = "" name_actuator = f"{tag_prefix}actuator" name_bracket_front = f"{tag_prefix}bracket_front" name_bracket_back = f"{tag_prefix}bracket_back" @@ -397,6 +399,7 @@ class Flexor: name_bolt_back = f"{tag_prefix}back_bolt" name_nut_front = f"{tag_prefix}front_nut" name_nut_back = f"{tag_prefix}back_nut" + print(name_bracket_back) ( a .add(self.actuator.assembly(pos=pos), name=name_actuator) diff --git a/nhf/touhou/houjuu_nue/joints.py b/nhf/touhou/houjuu_nue/joints.py index 3489746..e5c6f13 100644 --- a/nhf/touhou/houjuu_nue/joints.py +++ b/nhf/touhou/houjuu_nue/joints.py @@ -208,7 +208,8 @@ class RootJoint(Model): def assembly(self, offset: int = 0, - fastener_pos: float = 0) -> Cq.Assembly: + fastener_pos: float = 0, + ignore_fasteners: bool = False) -> Cq.Assembly: """ Specify knob position to determine the position of the knob from fully inserted (0) or fully uninserted (1) @@ -223,13 +224,17 @@ class RootJoint(Model): .addS(self.child(), name="child", material=Material.PLASTIC_PLA, role=Role.CHILD) - .addS(self.hex_nut.assembly(), name="hex_nut") - .addS(self.knob.assembly(), name="knob", - loc=Cq.Location((0, 0, knob_h * fastener_pos))) - .constrain("knob/thread", "Fixed") - .constrain("hex_nut?bot", "parent?base", "Plane", param=0) - .constrain("hex_nut?dirX", "parent@faces@>X", "Axis", param=0) ) + if not ignore_fasteners: + ( + result + .addS(self.hex_nut.assembly(), name="hex_nut") + .addS(self.knob.assembly(), name="knob", + loc=Cq.Location((0, 0, knob_h * fastener_pos))) + .constrain("knob/thread", "Fixed") + .constrain("hex_nut?bot", "parent?base", "Plane", param=0) + .constrain("hex_nut?dirX", "parent@faces@>X", "Axis", param=0) + ) self.hirth_joint.add_constraints( result, "parent", @@ -526,6 +531,7 @@ class ShoulderJoint(Model): self, fastener_pos: float = 0.0, deflection: float = 0.0, + ignore_fasteners: bool = False, ) -> Cq.Assembly: assert deflection <= self.angle_max_deflection directrix = self.directrix_id @@ -547,14 +553,18 @@ class ShoulderJoint(Model): .addS(self.parent_bot(), name="parent_bot", role=Role.PARENT, material=mat) - # Fasteners - .addS(self.bolt.assembly(), name="bolt_top", - loc=Cq.Location((0, 0, bolt_z))) - .constrain("bolt_top?root", 'Fixed') - .addS(self.bolt.assembly(), name="bolt_bot", - loc=Cq.Location((0, 0, -bolt_z), (1,0,0), 180)) - .constrain("bolt_bot?root", 'Fixed') ) + if not ignore_fasteners: + ( + result + # Fasteners + .addS(self.bolt.assembly(), name="bolt_top", + loc=Cq.Location((0, 0, bolt_z))) + .constrain("bolt_top?root", 'Fixed') + .addS(self.bolt.assembly(), name="bolt_bot", + loc=Cq.Location((0, 0, -bolt_z), (1,0,0), 180)) + .constrain("bolt_bot?root", 'Fixed') + ) TorsionJoint.add_constraints( result, rider="child/rider_top", @@ -1075,7 +1085,7 @@ class ElbowJoint(Model): return self.disk_joint.housing_lower() @target(name="parent-upper") - def parent_joint_upper(self): + def parent_joint_upper(self, generate_mount: bool=False): axial_offset = Cq.Location((self.parent_arm_radius, 0, 0)) housing_dz = self.disk_joint.housing_upper_dz conn_h = self.disk_joint.total_thickness @@ -1120,16 +1130,25 @@ class ElbowJoint(Model): #.solve() ) if self.flexor: - # Orientes the hole surface so it faces +X - loc_thickness = Cq.Location((-self.lip_thickness, 0, 0), (0, 1, 0), 90) - result.add( - self.actuator_mount(), - name="act", - loc=self.actuator_mount_loc(child=False) * loc_thickness) + if generate_mount: + # Orientes the hole surface so it faces +X + loc_thickness = Cq.Location((-self.lip_thickness, 0, 0), (0, 1, 0), 90) + result.add( + self.actuator_mount(), + name="act", + loc=self.actuator_mount_loc(child=False) * loc_thickness) + else: + result.add( + Cq.Edge.makeLine((-1,0,0), (1,0,0)), + name="act", + loc=self.actuator_mount_loc(child=False)) return result @assembly() - def assembly(self, angle: float = 0) -> Cq.Assembly: + def assembly(self, + angle: float = 0, + generate_mount: bool = False, + ignore_actuators: bool = False) -> Cq.Assembly: assert 0 <= angle <= self.motion_span result = ( Cq.Assembly() @@ -1137,7 +1156,7 @@ class ElbowJoint(Model): role=Role.CHILD, material=self.material) .addS(self.parent_joint_lower(), name="parent_lower", role=Role.CASING, material=self.material) - .addS(self.parent_joint_upper(), name="parent_upper", + .addS(self.parent_joint_upper(generate_mount=generate_mount), name="parent_upper", role=Role.PARENT, material=self.material) #.constrain("child/disk?mate_bot", "Fixed") ) @@ -1148,14 +1167,14 @@ class ElbowJoint(Model): disk="child/disk", angle=angle, ) - if self.flexor: + if not ignore_actuators and self.flexor: target_length = self.flexor.target_length_at_angle( angle=angle, ) self.flexor.add_to( result, target_length=target_length, - tag_hole_back="parent_upper/act?mount", + tag_hole_back="parent_upper/act", tag_hole_front="child/act?mount", tag_dir="parent_lower?mate", ) diff --git a/nhf/touhou/houjuu_nue/wing.py b/nhf/touhou/houjuu_nue/wing.py index c33deda..b18358a 100644 --- a/nhf/touhou/houjuu_nue/wing.py +++ b/nhf/touhou/houjuu_nue/wing.py @@ -362,7 +362,9 @@ class WingProfile(Model): return result @assembly() - def assembly_s0(self, ignore_detail: bool=False) -> Cq.Assembly: + def assembly_s0( + self, + ignore_electronics: bool=False) -> Cq.Assembly: result = ( Cq.Assembly() .addS(self.surface_s0(top=True), name="bot", @@ -401,7 +403,7 @@ class WingProfile(Model): .constrain(f"{tag}?{top_tag}", f"top?{tag}", "Plane") .constrain(f"{tag}?dir", f"top?{tag}_dir", "Axis") ) - if not ignore_detail: + if not ignore_electronics: result.add(self.electronic_board.assembly(), name="electronic_board") for hole in self.electronic_board.mount_holes: assert hole.tag @@ -923,7 +925,9 @@ class WingProfile(Model): elbow_wrist_deflection: float = 0.0, root_offset: int = 5, fastener_pos: float = 0.0, - ignore_detail: bool = False, + ignore_fasteners: bool = False, + ignore_electronics: bool = False, + ignore_actuators: bool = False, ) -> Cq.Assembly(): if parts is None: parts = [ @@ -944,11 +948,14 @@ class WingProfile(Model): tag_top, tag_bot = tag_bot, tag_top if "s0" in parts: - result.add(self.assembly_s0(ignore_detail=ignore_detail), name="s0") + result.add(self.assembly_s0( + ignore_electronics=ignore_electronics + ), name="s0") if "root" in parts: result.addS(self.root_joint.assembly( offset=root_offset, fastener_pos=fastener_pos, + ignore_fasteners=ignore_fasteners, ), name="root") result.constrain("root/parent", "Fixed") if "s0" in parts and "root" in parts: @@ -962,7 +969,8 @@ class WingProfile(Model): angle = shoulder_deflection * self.shoulder_joint.angle_max_deflection result.add(self.shoulder_joint.assembly( fastener_pos=fastener_pos, - deflection=angle), name="shoulder") + deflection=angle, + ignore_fasteners=ignore_fasteners), name="shoulder") if "s0" in parts and "shoulder" in parts: for i in range(len(self.shoulder_joint.parent_conn_hole_pos)): ( @@ -984,7 +992,9 @@ class WingProfile(Model): ) if "elbow" in parts: angle = self.elbow_joint.motion_span * elbow_wrist_deflection - result.add(self.elbow_joint.assembly(angle=angle), name="elbow") + result.add(self.elbow_joint.assembly( + angle=angle, + ignore_actuators=ignore_actuators), name="elbow") if "s1" in parts and "elbow" in parts: ( result @@ -993,6 +1003,11 @@ class WingProfile(Model): .constrain("s1/elbow_bot?conn0", "elbow/parent_upper/lip?conn_bot0", "Plane") .constrain("s1/elbow_bot?conn1", "elbow/parent_upper/lip?conn_bot1", "Plane") ) + if not ignore_actuators: + ( + result + .constrain("elbow/bracket_back?conn_side", "s1/elbow_act?conn0", "Plane") + ) if "s2" in parts: result.add(self.assembly_s2(), name="s2") if "s2" in parts and "elbow" in parts: @@ -1005,7 +1020,9 @@ class WingProfile(Model): ) if "wrist" in parts: angle = self.wrist_joint.motion_span * elbow_wrist_deflection - result.add(self.wrist_joint.assembly(angle=angle), name="wrist") + result.add(self.wrist_joint.assembly( + angle=angle, + ignore_actuators=ignore_actuators), name="wrist") wrist_n_holes = len(self.wrist_joint.hole_pos) if "s2" in parts and "wrist" in parts: for i in range(wrist_n_holes): @@ -1023,6 +1040,11 @@ class WingProfile(Model): .constrain(f"s3/wrist_top?conn{i}", f"wrist/child/lip?conn_top{i}", "Plane") .constrain(f"s3/wrist_bot?conn{i}", f"wrist/child/lip?conn_bot{i}", "Plane") ) + if not ignore_actuators: + ( + result + .constrain("wrist/bracket_back?conn_side", "s2/wrist_act?conn0", "Plane") + ) if len(parts) > 1: result.solve()