From e73c6c0fedc2912bbfcad31422bef3c377c7626f Mon Sep 17 00:00:00 2001 From: Leni Aniva Date: Wed, 17 Jul 2024 21:37:08 -0700 Subject: [PATCH] feat: Reduce the number of slots on shoulder Previously every shoulder joint was the same with two slots that specify the neutral position. Experiment reveals this to be too fragile. --- nhf/parts/joints.py | 6 +++++- nhf/touhou/houjuu_nue/__init__.py | 8 +++++--- nhf/touhou/houjuu_nue/joints.py | 4 ++-- nhf/touhou/houjuu_nue/test.py | 10 ++++++++++ nhf/touhou/houjuu_nue/wing.py | 9 +++++---- 5 files changed, 27 insertions(+), 10 deletions(-) diff --git a/nhf/parts/joints.py b/nhf/parts/joints.py index 20fd507..8602147 100644 --- a/nhf/parts/joints.py +++ b/nhf/parts/joints.py @@ -219,6 +219,8 @@ class TorsionJoint: assert self.groove_radius_inner > self.spring.radius > self.radius_axle assert self.spring.height > self.groove_depth, "Groove is too deep" assert self.groove_depth < self.spring.height - self.spring.thickness * 2 + if self.rider_n_slots == 1: + assert self.rider_slot_span == 0.0, "Non-zero span is impossible with multiple riders" @property def total_height(self): @@ -373,7 +375,9 @@ class TorsionJoint: ) theta_begin = -math.radians(rider_slot_begin) theta_span = math.radians(self.rider_slot_span) - if abs(math.remainder(self.rider_slot_span, 360)) < TOL: + if self.rider_n_slots <= 1: + theta_step = 0 + elif abs(math.remainder(self.rider_slot_span, 360)) < TOL: theta_step = theta_span / self.rider_n_slots else: theta_step = theta_span / (self.rider_n_slots - 1) diff --git a/nhf/touhou/houjuu_nue/__init__.py b/nhf/touhou/houjuu_nue/__init__.py index 13df365..f0c996a 100644 --- a/nhf/touhou/houjuu_nue/__init__.py +++ b/nhf/touhou/houjuu_nue/__init__.py @@ -50,14 +50,14 @@ class Parameters(Model): wing_r1: MW.WingR = field(default_factory=lambda: MW.WingR( name="r1", - shoulder_joint=MJ.ShoulderJoint(directrix_id=1), + shoulder_angle_bias = 15.0, )) wing_r2: MW.WingR = field(default_factory=lambda: MW.WingR( name="r2", )) wing_r3: MW.WingR = field(default_factory=lambda: MW.WingR( name="r3", - shoulder_joint=MJ.ShoulderJoint(directrix_id=1), + shoulder_angle_bias = 15.0, )) wing_l1: MW.WingL = field(default_factory=lambda: MW.WingL( name="l1", @@ -66,7 +66,7 @@ class Parameters(Model): wing_l2: MW.WingL = field(default_factory=lambda: MW.WingL( name="l2", wrist_angle=-30.0, - shoulder_joint=MJ.ShoulderJoint(directrix_id=1), + shoulder_angle_bias = 15.0, )) wing_l3: MW.WingL = field(default_factory=lambda: MW.WingL( name="l3", @@ -84,6 +84,8 @@ class Parameters(Model): self.wing_l2.base_joint = self.harness.hs_hirth_joint self.wing_l3.base_joint = self.harness.hs_hirth_joint + self.wing_r1.shoulder_joint.torsion_joint + assert self.wing_r1.hs_joint_axis_diam == self.harness.hs_joint_axis_diam assert self.wing_r2.hs_joint_axis_diam == self.harness.hs_joint_axis_diam assert self.wing_r3.hs_joint_axis_diam == self.harness.hs_joint_axis_diam diff --git a/nhf/touhou/houjuu_nue/joints.py b/nhf/touhou/houjuu_nue/joints.py index 45bce76..5fa9a6d 100644 --- a/nhf/touhou/houjuu_nue/joints.py +++ b/nhf/touhou/houjuu_nue/joints.py @@ -32,8 +32,8 @@ class ShoulderJoint(Model): height=7.5, ), rider_slot_begin=0, - rider_n_slots=2, - rider_slot_span=15, + rider_n_slots=1, + rider_slot_span=0, )) # On the parent side, drill vertical holes diff --git a/nhf/touhou/houjuu_nue/test.py b/nhf/touhou/houjuu_nue/test.py index 01fcc74..9dbb41b 100644 --- a/nhf/touhou/houjuu_nue/test.py +++ b/nhf/touhou/houjuu_nue/test.py @@ -10,11 +10,21 @@ class TestJoints(unittest.TestCase): j = MJ.ShoulderJoint() assembly = j.torsion_joint.rider_track_assembly() self.assertEqual(pairwise_intersection(assembly), []) + def test_shoulder_collision_0(self): j = MJ.ShoulderJoint() assembly = j.assembly() self.assertEqual(pairwise_intersection(assembly), []) + def test_shoulder_align(self): + j = MJ.ShoulderJoint() + a = j.assembly() + l_t_c0 = a.get_abs_location("parent_top/lip?conn0") + l_b_c0 = a.get_abs_location("parent_bot/lip?conn0") + v = l_t_c0 - l_b_c0 + self.assertAlmostEqual(v.x, 0) + self.assertAlmostEqual(v.y, 0) + def test_shoulder_joint_dist(self): """ Tests the arm radius diff --git a/nhf/touhou/houjuu_nue/wing.py b/nhf/touhou/houjuu_nue/wing.py index b43b802..e122c58 100644 --- a/nhf/touhou/houjuu_nue/wing.py +++ b/nhf/touhou/houjuu_nue/wing.py @@ -39,6 +39,7 @@ class WingProfile(Model): shoulder_joint: ShoulderJoint = field(default_factory=lambda: ShoulderJoint( )) + shoulder_angle_bias: float = 0.0 shoulder_width: float = 36.0 shoulder_tip_x: float = -200.0 shoulder_tip_y: float = 160.0 @@ -94,7 +95,7 @@ class WingProfile(Model): self.elbow_top_loc = self.elbow_bot_loc * Cq.Location.from2d(0, self.elbow_height) self.wrist_top_loc = self.wrist_bot_loc * Cq.Location.from2d(0, self.wrist_height) - self.shoulder_joint.angle_neutral = -self.shoulder_angle_neutral + self.shoulder_joint.angle_neutral = -self.shoulder_angle_neutral - self.shoulder_angle_bias @submodel(name="shoulder-joint") def submodel_shoulder_joint(self) -> Model: @@ -287,14 +288,14 @@ class WingProfile(Model): sw = self.shoulder_width axle_dist = self.shoulder_joint.parent_lip_ext - theta = math.radians(self.shoulder_joint.angle_neutral) - c, s = math.cos(-theta), math.sin(-theta) + theta = math.radians(self.shoulder_angle_neutral) + c, s = math.cos(theta), math.sin(theta) tags = [ # transforms [axle_dist, -sw/2] about the centre (tip_x, tip_y - sw/2) ("shoulder", Cq.Location.from2d( self.shoulder_tip_x + axle_dist * c + (-sw/2) * s, self.shoulder_tip_y - sw / 2 - axle_dist * s + (-sw/2) * c, - self.shoulder_joint.angle_neutral)), + -self.shoulder_angle_neutral)), ("base", Cq.Location.from2d(base_dx, base_dy, 90)), ] result = extrude_with_markers(