cosplay: Touhou/Houjuu Nue #4
|
@ -634,12 +634,15 @@ class ElbowJoint(Model):
|
||||||
axle is at position 0, and parent direction is -X
|
axle is at position 0, and parent direction is -X
|
||||||
"""
|
"""
|
||||||
return Cq.Location.from2d(-self.parent_arm_radius, 0, 0)
|
return Cq.Location.from2d(-self.parent_arm_radius, 0, 0)
|
||||||
def child_arm_loc(self) -> Cq.Location:
|
def child_arm_loc(self, flip: bool = False) -> Cq.Location:
|
||||||
"""
|
"""
|
||||||
2d Location of the centre of the arm surface on the child side, assuming
|
2d Location of the centre of the arm surface on the child side, assuming
|
||||||
axle is at position 0, and parent direction is -X
|
axle is at position 0, and parent direction is -X
|
||||||
|
|
||||||
|
Set `flip=True` to indicate that the joint is supposed to be installed upside down
|
||||||
"""
|
"""
|
||||||
return Cq.Location.rot2d(self.angle_neutral) * Cq.Location.from2d(self.child_arm_radius, 0, 180)
|
result = Cq.Location.rot2d(self.angle_neutral) * Cq.Location.from2d(self.child_arm_radius, 0, 180)
|
||||||
|
return result.flip_y() if flip else result
|
||||||
|
|
||||||
def lip(self) -> Cq.Workplane:
|
def lip(self) -> Cq.Workplane:
|
||||||
holes = [
|
holes = [
|
||||||
|
|
|
@ -62,7 +62,7 @@ class WingProfile(Model):
|
||||||
|
|
||||||
wrist_joint: ElbowJoint = field(default_factory=lambda: ElbowJoint(
|
wrist_joint: ElbowJoint = field(default_factory=lambda: ElbowJoint(
|
||||||
disk_joint=DiskJoint(
|
disk_joint=DiskJoint(
|
||||||
movement_angle=45,
|
movement_angle=30,
|
||||||
radius_disk=13.0,
|
radius_disk=13.0,
|
||||||
radius_housing=15.0,
|
radius_housing=15.0,
|
||||||
),
|
),
|
||||||
|
@ -91,6 +91,7 @@ class WingProfile(Model):
|
||||||
elbow_rotate: float = -5.0
|
elbow_rotate: float = -5.0
|
||||||
wrist_rotate: float = 30.0
|
wrist_rotate: float = 30.0
|
||||||
|
|
||||||
|
# False for the right side, True for the left side
|
||||||
flip: bool = False
|
flip: bool = False
|
||||||
|
|
||||||
def __post_init__(self):
|
def __post_init__(self):
|
||||||
|
@ -447,9 +448,9 @@ class WingProfile(Model):
|
||||||
h = self.elbow_height / 2
|
h = self.elbow_height / 2
|
||||||
loc_elbow = Cq.Location.rot2d(self.elbow_rotate) * self.elbow_joint.parent_arm_loc()
|
loc_elbow = Cq.Location.rot2d(self.elbow_rotate) * self.elbow_joint.parent_arm_loc()
|
||||||
tags_elbow = [
|
tags_elbow = [
|
||||||
("elbow_bot", self.elbow_axle_loc * loc_elbow *\
|
("elbow_bot", self.elbow_axle_loc * loc_elbow *
|
||||||
Cq.Location.from2d(0, -self.elbow_h2)),
|
Cq.Location.from2d(0, -self.elbow_h2)),
|
||||||
("elbow_top", self.elbow_axle_loc * loc_elbow *\
|
("elbow_top", self.elbow_axle_loc * loc_elbow *
|
||||||
Cq.Location.from2d(0, self.elbow_h2)),
|
Cq.Location.from2d(0, self.elbow_h2)),
|
||||||
]
|
]
|
||||||
profile = self.profile_s1()
|
profile = self.profile_s1()
|
||||||
|
@ -512,19 +513,19 @@ class WingProfile(Model):
|
||||||
return profile
|
return profile
|
||||||
def surface_s2(self, front: bool = True) -> Cq.Workplane:
|
def surface_s2(self, front: bool = True) -> Cq.Workplane:
|
||||||
h = self.elbow_height / 2
|
h = self.elbow_height / 2
|
||||||
loc_elbow = Cq.Location.rot2d(self.elbow_rotate) * self.elbow_joint.child_arm_loc()
|
loc_elbow = Cq.Location.rot2d(self.elbow_rotate) * self.elbow_joint.child_arm_loc(flip=self.flip)
|
||||||
tags_elbow = [
|
tags_elbow = [
|
||||||
("elbow_bot", self.elbow_axle_loc * loc_elbow *\
|
("elbow_bot", self.elbow_axle_loc * loc_elbow *
|
||||||
Cq.Location.from2d(0, self.elbow_h2)),
|
Cq.Location.from2d(0, self.elbow_h2)),
|
||||||
("elbow_top", self.elbow_axle_loc * loc_elbow *\
|
("elbow_top", self.elbow_axle_loc * loc_elbow *
|
||||||
Cq.Location.from2d(0, -self.elbow_h2)),
|
Cq.Location.from2d(0, -self.elbow_h2)),
|
||||||
]
|
]
|
||||||
h = self.wrist_height / 2
|
h = self.wrist_height / 2
|
||||||
loc_wrist = Cq.Location.rot2d(self.wrist_rotate) * self.wrist_joint.parent_arm_loc().flip_y()
|
loc_wrist = Cq.Location.rot2d(self.wrist_rotate) * self.wrist_joint.parent_arm_loc()
|
||||||
tags_wrist = [
|
tags_wrist = [
|
||||||
("wrist_bot", self.wrist_axle_loc * loc_wrist *\
|
("wrist_bot", self.wrist_axle_loc * loc_wrist *
|
||||||
Cq.Location.from2d(0, -self.wrist_h2)),
|
Cq.Location.from2d(0, -self.wrist_h2)),
|
||||||
("wrist_top", self.wrist_axle_loc * loc_wrist *\
|
("wrist_top", self.wrist_axle_loc * loc_wrist *
|
||||||
Cq.Location.from2d(0, self.wrist_h2)),
|
Cq.Location.from2d(0, self.wrist_h2)),
|
||||||
]
|
]
|
||||||
profile = self.profile_s2()
|
profile = self.profile_s2()
|
||||||
|
@ -580,11 +581,11 @@ class WingProfile(Model):
|
||||||
def surface_s3(self,
|
def surface_s3(self,
|
||||||
front: bool = True) -> Cq.Workplane:
|
front: bool = True) -> Cq.Workplane:
|
||||||
h = self.wrist_height / 2
|
h = self.wrist_height / 2
|
||||||
loc_wrist = Cq.Location.rot2d(self.wrist_rotate) * self.wrist_joint.child_arm_loc().flip_y()
|
loc_wrist = Cq.Location.rot2d(self.wrist_rotate) * self.wrist_joint.child_arm_loc(flip=not self.flip)
|
||||||
tags = [
|
tags = [
|
||||||
("wrist_bot", self.wrist_axle_loc * loc_wrist *\
|
("wrist_bot", self.wrist_axle_loc * loc_wrist *
|
||||||
Cq.Location.from2d(0, self.wrist_h2)),
|
Cq.Location.from2d(0, self.wrist_h2)),
|
||||||
("wrist_top", self.wrist_axle_loc * loc_wrist *\
|
("wrist_top", self.wrist_axle_loc * loc_wrist *
|
||||||
Cq.Location.from2d(0, -self.wrist_h2)),
|
Cq.Location.from2d(0, -self.wrist_h2)),
|
||||||
]
|
]
|
||||||
profile = self.profile_s3()
|
profile = self.profile_s3()
|
||||||
|
@ -662,42 +663,42 @@ class WingProfile(Model):
|
||||||
if "s1" in parts and "elbow" in parts:
|
if "s1" in parts and "elbow" in parts:
|
||||||
(
|
(
|
||||||
result
|
result
|
||||||
.constrain("s1/elbow_top?conn0", "elbow/parent_upper/lip?conn_top0", "Plane")
|
.constrain("s1/elbow_top?conn0", f"elbow/parent_upper/lip?conn_{tag_top}0", "Plane")
|
||||||
.constrain("s1/elbow_top?conn1", "elbow/parent_upper/lip?conn_top1", "Plane")
|
.constrain("s1/elbow_top?conn1", f"elbow/parent_upper/lip?conn_{tag_top}1", "Plane")
|
||||||
.constrain("s1/elbow_bot?conn0", "elbow/parent_upper/lip?conn_bot0", "Plane")
|
.constrain("s1/elbow_bot?conn0", f"elbow/parent_upper/lip?conn_{tag_bot}0", "Plane")
|
||||||
.constrain("s1/elbow_bot?conn1", "elbow/parent_upper/lip?conn_bot1", "Plane")
|
.constrain("s1/elbow_bot?conn1", f"elbow/parent_upper/lip?conn_{tag_bot}1", "Plane")
|
||||||
)
|
)
|
||||||
if "s2" in parts:
|
if "s2" in parts:
|
||||||
result.add(self.assembly_s2(), name="s2")
|
result.add(self.assembly_s2(), name="s2")
|
||||||
if "s2" in parts and "elbow" in parts:
|
if "s2" in parts and "elbow" in parts:
|
||||||
(
|
(
|
||||||
result
|
result
|
||||||
.constrain("s2/elbow_top?conn0", "elbow/child/lip?conn_top0", "Plane")
|
.constrain("s2/elbow_top?conn0", f"elbow/child/lip?conn_{tag_top}0", "Plane")
|
||||||
.constrain("s2/elbow_top?conn1", "elbow/child/lip?conn_top1", "Plane")
|
.constrain("s2/elbow_top?conn1", f"elbow/child/lip?conn_{tag_top}1", "Plane")
|
||||||
.constrain("s2/elbow_bot?conn0", "elbow/child/lip?conn_bot0", "Plane")
|
.constrain("s2/elbow_bot?conn0", f"elbow/child/lip?conn_{tag_bot}0", "Plane")
|
||||||
.constrain("s2/elbow_bot?conn1", "elbow/child/lip?conn_bot1", "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.disk_joint.movement_angle * elbow_wrist_deflection
|
||||||
result.add(self.wrist_joint.assembly(angle=elbow_wrist_deflection), 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
|
||||||
(
|
(
|
||||||
result
|
result
|
||||||
.constrain("s2/wrist_top?conn0", "wrist/parent_upper/lip?conn_bot0", "Plane")
|
.constrain("s2/wrist_top?conn0", f"wrist/parent_upper/lip?conn_{tag_bot}0", "Plane")
|
||||||
.constrain("s2/wrist_top?conn1", "wrist/parent_upper/lip?conn_bot1", "Plane")
|
.constrain("s2/wrist_top?conn1", f"wrist/parent_upper/lip?conn_{tag_bot}1", "Plane")
|
||||||
.constrain("s2/wrist_bot?conn0", "wrist/parent_upper/lip?conn_top0", "Plane")
|
.constrain("s2/wrist_bot?conn0", f"wrist/parent_upper/lip?conn_{tag_top}0", "Plane")
|
||||||
.constrain("s2/wrist_bot?conn1", "wrist/parent_upper/lip?conn_top1", "Plane")
|
.constrain("s2/wrist_bot?conn1", f"wrist/parent_upper/lip?conn_{tag_top}1", "Plane")
|
||||||
)
|
)
|
||||||
if "s3" in parts:
|
if "s3" in parts:
|
||||||
result.add(self.assembly_s3(), name="s3")
|
result.add(self.assembly_s3(), name="s3")
|
||||||
if "s3" in parts and "wrist" in parts:
|
if "s3" in parts and "wrist" in parts:
|
||||||
(
|
(
|
||||||
result
|
result
|
||||||
.constrain("s3/wrist_top?conn0", "wrist/child/lip?conn_bot0", "Plane")
|
.constrain("s3/wrist_top?conn0", f"wrist/child/lip?conn_{tag_bot}0", "Plane")
|
||||||
.constrain("s3/wrist_top?conn1", "wrist/child/lip?conn_bot1", "Plane")
|
.constrain("s3/wrist_top?conn1", f"wrist/child/lip?conn_{tag_bot}1", "Plane")
|
||||||
.constrain("s3/wrist_bot?conn0", "wrist/child/lip?conn_top0", "Plane")
|
.constrain("s3/wrist_bot?conn0", f"wrist/child/lip?conn_{tag_top}0", "Plane")
|
||||||
.constrain("s3/wrist_bot?conn1", "wrist/child/lip?conn_top1", "Plane")
|
.constrain("s3/wrist_bot?conn1", f"wrist/child/lip?conn_{tag_top}1", "Plane")
|
||||||
)
|
)
|
||||||
if len(parts) > 1:
|
if len(parts) > 1:
|
||||||
result.solve()
|
result.solve()
|
||||||
|
@ -845,10 +846,10 @@ class WingL(WingProfile):
|
||||||
def __post_init__(self):
|
def __post_init__(self):
|
||||||
assert self.wrist_height <= self.shoulder_joint.height
|
assert self.wrist_height <= self.shoulder_joint.height
|
||||||
self.wrist_bot_loc = self.wrist_bot_loc.with_angle_2d(self.wrist_angle)
|
self.wrist_bot_loc = self.wrist_bot_loc.with_angle_2d(self.wrist_angle)
|
||||||
self.elbow_joint.angle_neutral = -15.0
|
self.elbow_joint.angle_neutral = 15.0
|
||||||
self.elbow_rotate = 5.0
|
self.elbow_rotate = 5.0
|
||||||
self.wrist_joint.angle_neutral = -self.wrist_bot_loc.to2d_rot() - 30.0
|
self.wrist_joint.angle_neutral = self.wrist_bot_loc.to2d_rot() + 30.0
|
||||||
self.wrist_rotate = self.wrist_joint.angle_neutral
|
self.wrist_rotate = -self.wrist_joint.angle_neutral
|
||||||
|
|
||||||
super().__post_init__()
|
super().__post_init__()
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue