From 98a93cc6514dc861ed7fd80c3be887e58f2e45f0 Mon Sep 17 00:00:00 2001 From: Leni Aniva Date: Wed, 24 Jul 2024 18:03:43 -0700 Subject: [PATCH] feat: Elbow joint connectedness --- nhf/touhou/houjuu_nue/joints.py | 21 ++++++++++++++++++--- nhf/touhou/houjuu_nue/wing.py | 16 +++++++++++----- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/nhf/touhou/houjuu_nue/joints.py b/nhf/touhou/houjuu_nue/joints.py index 05cf0e7..25b0ebc 100644 --- a/nhf/touhou/houjuu_nue/joints.py +++ b/nhf/touhou/houjuu_nue/joints.py @@ -1050,6 +1050,8 @@ class ElbowJoint(Model): parent_arm_radius: float = 40.0 lip_thickness: float = 5.0 + # Extra bit on top of the lip to connect to actuator mount + child_lip_extra_length: float = 1.0 lip_length: float = 60.0 hole_pos: list[float] = field(default_factory=lambda: [15, 25]) parent_arm_width: float = 10.0 @@ -1069,8 +1071,9 @@ class ElbowJoint(Model): flexor: Optional[Flexor] = None # Rotates the entire flexor flexor_offset_angle: float = 0 - # Rotates the surface of the mount - flexor_mount_rot: float = 0 + # Rotates the surface of the mount relative to radially inwards + flexor_mount_angle_parent: float = 0 + flexor_mount_angle_child: float = -90 def __post_init__(self): assert self.child_arm_radius > self.disk_joint.radius_housing @@ -1133,7 +1136,8 @@ class ElbowJoint(Model): ) -> Cq.Location: # Moves the hole so the axle of the mount is perpendicular to it loc_mount = Cq.Location.from2d(self.flexor.mount_height, 0) * Cq.Location.rot2d(180) - loc_mount_orient = Cq.Location.rot2d(self.flexor_mount_rot * (-1 if child else 1)) + mount_angle = self.flexor_mount_angle_child if child else self.flexor_mount_angle_parent + loc_mount_orient = Cq.Location.rot2d(mount_angle) # Moves the hole to be some distance apart from 0 mount_r, mount_loc_angle, mount_parent_r = self.flexor.open_pos() loc_span = Cq.Location.from2d(mount_r if child else mount_parent_r, 0) @@ -1182,12 +1186,23 @@ class ElbowJoint(Model): loc_cut_rel = Cq.Location((0, self.disk_joint.spring.radius_inner, -self.disk_joint.disk_bot_thickness)) disk_cut = self.disk_joint._disk_cut().located( loc_lip.inverse * loc_cut_rel * loc_disk) + lip_extra = Cq.Solid.makeBox( + length=self.child_lip_extra_length, + width=self.total_thickness, + height=self.lip_thickness, + ).located(Cq.Location(( + self.lip_length / 2, + -self.total_thickness / 2, + 0, + ))) result = ( Cq.Assembly() .add(self.disk_joint.disk(), name="disk", loc=loc_rot_neutral * Cq.Location((0, 0, -dz), (0,0,1), angle)) .add(self.lip().cut(disk_cut), name="lip", loc=loc_rot_neutral * loc_disk.inverse * loc_lip) + .add(lip_extra, name="lip_extra", + loc=loc_rot_neutral * loc_disk.inverse * loc_lip) ) # Orientes the hole surface so it faces +X loc_thickness = Cq.Location((-self.lip_thickness, 0, 0), (0, 1, 0), 90) diff --git a/nhf/touhou/houjuu_nue/wing.py b/nhf/touhou/houjuu_nue/wing.py index 985080d..8d4c241 100644 --- a/nhf/touhou/houjuu_nue/wing.py +++ b/nhf/touhou/houjuu_nue/wing.py @@ -64,6 +64,7 @@ class WingProfile(Model): actuator=LINEAR_ACTUATOR_50, flexor_offset_angle=30, parent_arm_width=15, + child_lip_extra_length=8, flip=False, )) # Distance between the two spacers on the elbow, halved @@ -99,12 +100,12 @@ class WingProfile(Model): wrist_bot_loc: Cq.Location wrist_height: float elbow_rotate: float = 10.0 - elbow_joint_overlap_median: float = 0.3 - wrist_joint_overlap_median: float = 0.5 wrist_rotate: float = -30.0 # Position of the elbow axle with 0 being bottom and 1 being top (flipped on the left side) - elbow_axle_pos: float = 0.5 - wrist_axle_pos: float = 0.0 + elbow_axle_pos: float + wrist_axle_pos: float + elbow_joint_overlap_median: float + wrist_joint_overlap_median: float # False for the right side, True for the left side flip: bool @@ -1089,6 +1090,10 @@ class WingR(WingProfile): ring_radius_inner: float = 22.0 flip: bool = False + elbow_axle_pos: float = 0.4 + wrist_axle_pos: float = 0.0 + elbow_joint_overlap_median: float = 0.35 + wrist_joint_overlap_median: float = 0.5 def __post_init__(self): super().__post_init__() @@ -1099,6 +1104,8 @@ class WingR(WingProfile): * Cq.Location.rot2d(self.arrow_angle) \ * Cq.Location.from2d(0, self.arrow_height + self.wrist_height) self.ring_loc = self.wrist_top_loc * self.ring_rel_loc + self.elbow_joint.flexor_offset_angle = 15 + self.elbow_joint.flexor_mount_angle_child = -75 assert self.ring_radius > self.ring_radius_inner assert 0 > self.blade_overlap_angle > self.arrow_angle @@ -1316,7 +1323,6 @@ class WingL(WingProfile): flip: bool = True elbow_axle_pos: float = 0.4 wrist_axle_pos: float = 0.5 - elbow_joint_overlap_median: float = 0.5 wrist_joint_overlap_median: float = 0.5