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.
This commit is contained in:
Leni Aniva 2024-07-17 21:37:08 -07:00
parent 6c6c17ea07
commit e73c6c0fed
Signed by: aniva
GPG Key ID: 4D9B1C8D10EA4C50
5 changed files with 27 additions and 10 deletions

View File

@ -219,6 +219,8 @@ class TorsionJoint:
assert self.groove_radius_inner > self.spring.radius > self.radius_axle assert self.groove_radius_inner > self.spring.radius > self.radius_axle
assert self.spring.height > self.groove_depth, "Groove is too deep" assert self.spring.height > self.groove_depth, "Groove is too deep"
assert self.groove_depth < self.spring.height - self.spring.thickness * 2 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 @property
def total_height(self): def total_height(self):
@ -373,7 +375,9 @@ class TorsionJoint:
) )
theta_begin = -math.radians(rider_slot_begin) theta_begin = -math.radians(rider_slot_begin)
theta_span = math.radians(self.rider_slot_span) 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 theta_step = theta_span / self.rider_n_slots
else: else:
theta_step = theta_span / (self.rider_n_slots - 1) theta_step = theta_span / (self.rider_n_slots - 1)

View File

@ -50,14 +50,14 @@ class Parameters(Model):
wing_r1: MW.WingR = field(default_factory=lambda: MW.WingR( wing_r1: MW.WingR = field(default_factory=lambda: MW.WingR(
name="r1", name="r1",
shoulder_joint=MJ.ShoulderJoint(directrix_id=1), shoulder_angle_bias = 15.0,
)) ))
wing_r2: MW.WingR = field(default_factory=lambda: MW.WingR( wing_r2: MW.WingR = field(default_factory=lambda: MW.WingR(
name="r2", name="r2",
)) ))
wing_r3: MW.WingR = field(default_factory=lambda: MW.WingR( wing_r3: MW.WingR = field(default_factory=lambda: MW.WingR(
name="r3", name="r3",
shoulder_joint=MJ.ShoulderJoint(directrix_id=1), shoulder_angle_bias = 15.0,
)) ))
wing_l1: MW.WingL = field(default_factory=lambda: MW.WingL( wing_l1: MW.WingL = field(default_factory=lambda: MW.WingL(
name="l1", name="l1",
@ -66,7 +66,7 @@ class Parameters(Model):
wing_l2: MW.WingL = field(default_factory=lambda: MW.WingL( wing_l2: MW.WingL = field(default_factory=lambda: MW.WingL(
name="l2", name="l2",
wrist_angle=-30.0, 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( wing_l3: MW.WingL = field(default_factory=lambda: MW.WingL(
name="l3", name="l3",
@ -84,6 +84,8 @@ class Parameters(Model):
self.wing_l2.base_joint = self.harness.hs_hirth_joint self.wing_l2.base_joint = self.harness.hs_hirth_joint
self.wing_l3.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_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_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 assert self.wing_r3.hs_joint_axis_diam == self.harness.hs_joint_axis_diam

View File

@ -32,8 +32,8 @@ class ShoulderJoint(Model):
height=7.5, height=7.5,
), ),
rider_slot_begin=0, rider_slot_begin=0,
rider_n_slots=2, rider_n_slots=1,
rider_slot_span=15, rider_slot_span=0,
)) ))
# On the parent side, drill vertical holes # On the parent side, drill vertical holes

View File

@ -10,11 +10,21 @@ class TestJoints(unittest.TestCase):
j = MJ.ShoulderJoint() j = MJ.ShoulderJoint()
assembly = j.torsion_joint.rider_track_assembly() assembly = j.torsion_joint.rider_track_assembly()
self.assertEqual(pairwise_intersection(assembly), []) self.assertEqual(pairwise_intersection(assembly), [])
def test_shoulder_collision_0(self): def test_shoulder_collision_0(self):
j = MJ.ShoulderJoint() j = MJ.ShoulderJoint()
assembly = j.assembly() assembly = j.assembly()
self.assertEqual(pairwise_intersection(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): def test_shoulder_joint_dist(self):
""" """
Tests the arm radius Tests the arm radius

View File

@ -39,6 +39,7 @@ class WingProfile(Model):
shoulder_joint: ShoulderJoint = field(default_factory=lambda: ShoulderJoint( shoulder_joint: ShoulderJoint = field(default_factory=lambda: ShoulderJoint(
)) ))
shoulder_angle_bias: float = 0.0
shoulder_width: float = 36.0 shoulder_width: float = 36.0
shoulder_tip_x: float = -200.0 shoulder_tip_x: float = -200.0
shoulder_tip_y: float = 160.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.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.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") @submodel(name="shoulder-joint")
def submodel_shoulder_joint(self) -> Model: def submodel_shoulder_joint(self) -> Model:
@ -287,14 +288,14 @@ class WingProfile(Model):
sw = self.shoulder_width sw = self.shoulder_width
axle_dist = self.shoulder_joint.parent_lip_ext axle_dist = self.shoulder_joint.parent_lip_ext
theta = math.radians(self.shoulder_joint.angle_neutral) theta = math.radians(self.shoulder_angle_neutral)
c, s = math.cos(-theta), math.sin(-theta) c, s = math.cos(theta), math.sin(theta)
tags = [ tags = [
# transforms [axle_dist, -sw/2] about the centre (tip_x, tip_y - sw/2) # transforms [axle_dist, -sw/2] about the centre (tip_x, tip_y - sw/2)
("shoulder", Cq.Location.from2d( ("shoulder", Cq.Location.from2d(
self.shoulder_tip_x + axle_dist * c + (-sw/2) * s, self.shoulder_tip_x + axle_dist * c + (-sw/2) * s,
self.shoulder_tip_y - sw / 2 - axle_dist * s + (-sw/2) * c, 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)), ("base", Cq.Location.from2d(base_dx, base_dy, 90)),
] ]
result = extrude_with_markers( result = extrude_with_markers(