feat: Cut polygons to remove joint conflict

This commit is contained in:
Leni Aniva 2024-07-19 22:29:57 -07:00
parent f5b048d0b9
commit d3a6f1e1c5
Signed by: aniva
GPG Key ID: 4D9B1C8D10EA4C50
2 changed files with 64 additions and 7 deletions

View File

@ -95,7 +95,7 @@ class RootJoint(Model):
child_height: float = 60.0 child_height: float = 60.0
child_width: float = 50.0 child_width: float = 50.0
child_mount_thickness: float = 25.4 / 8 child_mount_thickness: float = 25.4 / 4
def corner_pos(self) -> list[tuple[int, int]]: def corner_pos(self) -> list[tuple[int, int]]:
""" """
@ -888,6 +888,10 @@ class ElbowJoint(Model):
def total_thickness(self): def total_thickness(self):
return self.disk_joint.total_thickness return self.disk_joint.total_thickness
@property
def motion_span(self) -> float:
return self.disk_joint.movement_angle
def parent_arm_loc(self) -> Cq.Location: def parent_arm_loc(self) -> Cq.Location:
""" """
2d Location of the centre of the arm surface on the parent side, assuming 2d Location of the centre of the arm surface on the parent side, assuming

View File

@ -24,7 +24,9 @@ class WingProfile(Model):
root_joint: RootJoint = field(default_factory=lambda: RootJoint()) root_joint: RootJoint = field(default_factory=lambda: RootJoint())
panel_thickness: float = 25.4 / 16 panel_thickness: float = 25.4 / 16
spacer_thickness: float = 25.4 / 8 # 1/4" acrylic for the spacer. Anything thinner would threathen structural
# strength
spacer_thickness: float = 25.4 / 4
shoulder_joint: ShoulderJoint = field(default_factory=lambda: ShoulderJoint( shoulder_joint: ShoulderJoint = field(default_factory=lambda: ShoulderJoint(
)) ))
@ -325,9 +327,52 @@ class WingProfile(Model):
### s1, s2, s3 ### ### s1, s2, s3 ###
def profile(self) -> Cq.Sketch: def profile(self) -> Cq.Sketch:
""" """
Generates profile from shoulder and above Generates profile from shoulder and above. Subclass should implement
""" """
def _elbow_joint_retract_cut_polygon(self, loc: Cq.Location) -> Cq.Sketch:
"""
Creates a cutting polygon for removing the contraction part of a joint
"""
theta = math.radians(self.elbow_joint.motion_span)
h = self.elbow_height
dx = h * math.tan(theta / 2)
dy = h
sign = -1 if self.flip else 1
points = [
(0, 0),
(dx, sign * dy),
(-dx, sign * dy),
]
return (
Cq.Sketch()
.polygon([
(loc * Cq.Location.from2d(*p)).to2d_pos()
for p in points
])
)
def _wrist_joint_retract_cut_polygon(self, loc: Cq.Location) -> Cq.Sketch:
"""
Creates a cutting polygon for removing the contraction part of a joint
"""
theta = math.radians(self.wrist_joint.motion_span)
dx = self.wrist_height * math.tan(theta)
dy = self.wrist_height
sign = -1 if self.flip else 1
points = [
(0, 0),
(0, -sign * dy),
(-dx, -sign * dy),
]
return (
Cq.Sketch()
.polygon([
(loc * Cq.Location.from2d(*p)).to2d_pos()
for p in points
])
)
def _assembly_insert_spacer( def _assembly_insert_spacer(
self, self,
a: Cq.Assembly, a: Cq.Assembly,
@ -374,8 +419,7 @@ class WingProfile(Model):
self, self,
joint: ElbowJoint, joint: ElbowJoint,
segment_thickness: float, segment_thickness: float,
dx: float, dx: float) -> MountingBox:
bot=False) -> MountingBox:
length = joint.lip_length / 2 - dx length = joint.lip_length / 2 - dx
holes = [ holes = [
Hole(x - dx) Hole(x - dx)
@ -398,6 +442,9 @@ class WingProfile(Model):
self.profile() self.profile()
.reset() .reset()
.polygon(self._mask_elbow(), mode='i') .polygon(self._mask_elbow(), mode='i')
.reset()
.push([self.elbow_axle_loc])
.each(self._elbow_joint_retract_cut_polygon, mode='s')
) )
return profile return profile
def surface_s1(self, front: bool = True) -> Cq.Workplane: def surface_s1(self, front: bool = True) -> Cq.Workplane:
@ -471,6 +518,12 @@ class WingProfile(Model):
.polygon(self._mask_elbow(), mode='s') .polygon(self._mask_elbow(), mode='s')
.reset() .reset()
.polygon(self._mask_wrist(), mode='i') .polygon(self._mask_wrist(), mode='i')
.reset()
.push([self.elbow_axle_loc])
.each(self._elbow_joint_retract_cut_polygon, mode='s')
.reset()
.push([self.wrist_axle_loc])
.each(self._wrist_joint_retract_cut_polygon, mode='s')
) )
return profile return profile
def surface_s2(self, front: bool = True) -> Cq.Workplane: def surface_s2(self, front: bool = True) -> Cq.Workplane:
@ -638,7 +691,7 @@ class WingProfile(Model):
.constrain("s1/shoulder_bot?conn1", f"shoulder/child/lip_{tag_bot}?conn1", "Plane") .constrain("s1/shoulder_bot?conn1", f"shoulder/child/lip_{tag_bot}?conn1", "Plane")
) )
if "elbow" in parts: if "elbow" in parts:
angle = self.elbow_joint.disk_joint.movement_angle * elbow_wrist_deflection 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), name="elbow")
if "s1" in parts and "elbow" in parts: if "s1" in parts and "elbow" in parts:
( (
@ -659,7 +712,7 @@ class WingProfile(Model):
.constrain("s2/elbow_bot?conn1", f"elbow/child/lip?conn_{tag_bot}1", "Plane") .constrain("s2/elbow_bot?conn1", f"elbow/child/lip?conn_{tag_bot}1", "Plane")
) )
if "wrist" in parts: if "wrist" in parts:
angle = self.wrist_joint.disk_joint.movement_angle * elbow_wrist_deflection 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), name="wrist")
if "s2" in parts and "wrist" in parts: if "s2" in parts and "wrist" in parts:
# Mounted backwards to bend in other direction # Mounted backwards to bend in other direction