feat: Cut polygons to remove joint conflict
This commit is contained in:
parent
f5b048d0b9
commit
d3a6f1e1c5
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue