cosplay: Touhou/Houjuu Nue #4
|
@ -593,44 +593,45 @@ class ElbowJoint(Model):
|
||||||
child_arm_radius: float = 40.0
|
child_arm_radius: float = 40.0
|
||||||
parent_arm_radius: float = 40.0
|
parent_arm_radius: float = 40.0
|
||||||
|
|
||||||
child_beam: Beam = field(default_factory=lambda: Beam())
|
lip_thickness: float = 5.0
|
||||||
parent_beam: Beam = field(default_factory=lambda: Beam(
|
lip_length: float = 60.0
|
||||||
spine_thickness=8.0,
|
hole_pos: list[float] = field(default_factory=lambda: [15, 25])
|
||||||
))
|
parent_arm_span: float = 30.0
|
||||||
parent_arm_span: float = 40.0
|
|
||||||
# Angle of the beginning of the parent arm
|
# Angle of the beginning of the parent arm
|
||||||
parent_arm_angle: float = 180.0
|
parent_arm_angle: float = 180.0
|
||||||
parent_binding_hole_radius: float = 30.0
|
|
||||||
|
|
||||||
# Size of the mounting holes
|
# Size of the mounting holes
|
||||||
hole_diam: float = 8.0
|
hole_diam: float = 6.0
|
||||||
|
|
||||||
material: Material = Material.RESIN_TRANSPERENT
|
material: Material = Material.RESIN_TRANSPERENT
|
||||||
|
|
||||||
# If true, flip the top and bottom tags
|
angle_neutral: float = 20.0
|
||||||
flip: bool = False
|
|
||||||
|
|
||||||
def __post_init__(self):
|
def __post_init__(self):
|
||||||
assert self.child_arm_radius > self.disk_joint.radius_housing
|
assert self.child_arm_radius > self.disk_joint.radius_housing
|
||||||
assert self.parent_arm_radius > self.disk_joint.radius_housing
|
assert self.parent_arm_radius > self.disk_joint.radius_housing
|
||||||
self.disk_joint.tongue_length = self.child_arm_radius - self.disk_joint.radius_disk
|
self.disk_joint.tongue_length = self.child_arm_radius - self.disk_joint.radius_disk
|
||||||
assert self.disk_joint.movement_angle < self.parent_arm_angle < 360 - self.parent_arm_span
|
assert self.disk_joint.movement_angle < self.parent_arm_angle < 360 - self.parent_arm_span
|
||||||
assert self.parent_binding_hole_radius - self.hole_diam / 2 > self.disk_joint.radius_housing
|
|
||||||
|
|
||||||
def child_hole_pos(self) -> list[float]:
|
def lip(self) -> Cq.Workplane:
|
||||||
"""
|
holes = [
|
||||||
List of hole positions measured from axle
|
h
|
||||||
"""
|
for i, x in enumerate(self.hole_pos)
|
||||||
dx = self.child_beam.hole_dist / 2
|
for h in [
|
||||||
r = self.child_arm_radius
|
Hole(x=x, tag=f"conn_top{i}"),
|
||||||
return [r - dx, r + dx]
|
Hole(x=-x, tag=f"conn_bot{i}")
|
||||||
def parent_hole_pos(self) -> list[float]:
|
]
|
||||||
"""
|
]
|
||||||
List of hole positions measured from axle
|
mbox = MountingBox(
|
||||||
"""
|
length=self.lip_length,
|
||||||
dx = self.parent_beam.hole_dist / 2
|
width=self.disk_joint.total_thickness,
|
||||||
r = self.parent_arm_radius
|
thickness=self.lip_thickness,
|
||||||
return [r - dx, r + dx]
|
holes=holes,
|
||||||
|
hole_diam=self.hole_diam,
|
||||||
|
centred=(True, True),
|
||||||
|
generate_side_tags=False,
|
||||||
|
)
|
||||||
|
return mbox.generate()
|
||||||
|
|
||||||
@target(name="child")
|
@target(name="child")
|
||||||
def child_joint(self) -> Cq.Assembly:
|
def child_joint(self) -> Cq.Assembly:
|
||||||
|
@ -639,14 +640,15 @@ class ElbowJoint(Model):
|
||||||
# We need to ensure the disk is on the "other" side so
|
# We need to ensure the disk is on the "other" side so
|
||||||
flip_x = Cq.Location((0, 0, 0), (1, 0, 0), 180)
|
flip_x = Cq.Location((0, 0, 0), (1, 0, 0), 180)
|
||||||
flip_z = Cq.Location((0, 0, 0), (0, 0, 1), 180)
|
flip_z = Cq.Location((0, 0, 0), (0, 0, 1), 180)
|
||||||
|
lip_dz = self.lip_thickness / 2
|
||||||
result = (
|
result = (
|
||||||
self.child_beam.generate(flip=self.flip)
|
Cq.Assembly()
|
||||||
|
.add(self.lip(), name="lip", loc=
|
||||||
|
Cq.Location((0, 0, 0), (0, 1, 0), 180) *
|
||||||
|
Cq.Location((-lip_dz, 0, 0), (1, 0, 0), 90) *
|
||||||
|
Cq.Location((0, 0, 0), (0, 1, 0), 90))
|
||||||
.add(self.disk_joint.disk(), name="disk",
|
.add(self.disk_joint.disk(), name="disk",
|
||||||
loc=flip_x * flip_z * Cq.Location((-self.child_arm_radius, 0, -dz), (0, 0, 1), angle))
|
loc=flip_x * flip_z * Cq.Location((-self.child_arm_radius, 0, -dz), (0, 0, 1), angle))
|
||||||
#.constrain("disk", "Fixed")
|
|
||||||
#.constrain("top", "Fixed")
|
|
||||||
#.constrain("bot", "Fixed")
|
|
||||||
#.solve()
|
|
||||||
)
|
)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
@ -658,7 +660,7 @@ class ElbowJoint(Model):
|
||||||
def parent_joint_upper(self):
|
def parent_joint_upper(self):
|
||||||
axial_offset = Cq.Location((self.parent_arm_radius, 0, 0))
|
axial_offset = Cq.Location((self.parent_arm_radius, 0, 0))
|
||||||
housing_dz = self.disk_joint.housing_upper_dz
|
housing_dz = self.disk_joint.housing_upper_dz
|
||||||
conn_h = self.parent_beam.spine_thickness
|
conn_h = self.lip_thickness
|
||||||
connector = (
|
connector = (
|
||||||
Cq.Solid.makeCylinder(
|
Cq.Solid.makeCylinder(
|
||||||
height=conn_h,
|
height=conn_h,
|
||||||
|
@ -675,10 +677,15 @@ class ElbowJoint(Model):
|
||||||
housing_loc = Cq.Location(
|
housing_loc = Cq.Location(
|
||||||
(0, 0, housing_dz),
|
(0, 0, housing_dz),
|
||||||
(0, 0, 1),
|
(0, 0, 1),
|
||||||
-self.disk_joint.tongue_span / 2
|
-self.disk_joint.tongue_span / 2 + self.angle_neutral
|
||||||
)
|
)
|
||||||
|
lip_dz = self.lip_thickness / 2
|
||||||
result = (
|
result = (
|
||||||
self.parent_beam.generate(flip=self.flip)
|
Cq.Assembly()
|
||||||
|
.add(self.lip(), name="lip", loc=
|
||||||
|
Cq.Location((0, 0, 0), (0, 1, 0), 180) *
|
||||||
|
Cq.Location((-lip_dz, 0, 0), (1, 0, 0), 90) *
|
||||||
|
Cq.Location((0, 0, 0), (0, 1, 0), 90))
|
||||||
.add(housing, name="housing",
|
.add(housing, name="housing",
|
||||||
loc=axial_offset * housing_loc)
|
loc=axial_offset * housing_loc)
|
||||||
.add(connector, name="connector",
|
.add(connector, name="connector",
|
||||||
|
|
|
@ -50,8 +50,9 @@ class WingProfile(Model):
|
||||||
disk_joint=DiskJoint(
|
disk_joint=DiskJoint(
|
||||||
movement_angle=55,
|
movement_angle=55,
|
||||||
),
|
),
|
||||||
flip=False,
|
|
||||||
))
|
))
|
||||||
|
# Distance between the two spacers on the elbow, halved
|
||||||
|
elbow_h2: float = 5.0
|
||||||
|
|
||||||
s2_thickness: float = 25.0
|
s2_thickness: float = 25.0
|
||||||
|
|
||||||
|
@ -61,8 +62,9 @@ class WingProfile(Model):
|
||||||
radius_disk=13.0,
|
radius_disk=13.0,
|
||||||
radius_housing=15.0,
|
radius_housing=15.0,
|
||||||
),
|
),
|
||||||
flip=True,
|
|
||||||
))
|
))
|
||||||
|
# Distance between the two spacers on the elbow, halved
|
||||||
|
wrist_h2: float = 5.0
|
||||||
|
|
||||||
s3_thickness: float = 25.0
|
s3_thickness: float = 25.0
|
||||||
|
|
||||||
|
@ -367,6 +369,7 @@ class WingProfile(Model):
|
||||||
front_tag: str = "front",
|
front_tag: str = "front",
|
||||||
back_tag: str = "back",
|
back_tag: str = "back",
|
||||||
flipped: bool = False,
|
flipped: bool = False,
|
||||||
|
rotate: bool = False,
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
For a child joint facing up, front panel should be on the right, back
|
For a child joint facing up, front panel should be on the right, back
|
||||||
|
@ -375,7 +378,7 @@ class WingProfile(Model):
|
||||||
site_front, site_back = "right", "left"
|
site_front, site_back = "right", "left"
|
||||||
if flipped:
|
if flipped:
|
||||||
site_front, site_back = site_back, site_front
|
site_front, site_back = site_back, site_front
|
||||||
angle = 0
|
angle = 180 if rotate else 0
|
||||||
(
|
(
|
||||||
a
|
a
|
||||||
.addS(
|
.addS(
|
||||||
|
@ -410,6 +413,27 @@ class WingProfile(Model):
|
||||||
Polygon shape to mask wrist
|
Polygon shape to mask wrist
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
def spacer_of_joint(
|
||||||
|
self,
|
||||||
|
joint: ElbowJoint,
|
||||||
|
segment_thickness: float,
|
||||||
|
dx: float,
|
||||||
|
bot=False) -> MountingBox:
|
||||||
|
length = joint.lip_length / 2 - dx
|
||||||
|
holes = [
|
||||||
|
Hole(x - dx)
|
||||||
|
for x in joint.hole_pos
|
||||||
|
]
|
||||||
|
mbox = MountingBox(
|
||||||
|
length=length,
|
||||||
|
width=segment_thickness,
|
||||||
|
thickness=self.spacer_thickness,
|
||||||
|
holes=holes,
|
||||||
|
hole_diam=joint.hole_diam,
|
||||||
|
centred=(False, True),
|
||||||
|
)
|
||||||
|
return mbox
|
||||||
|
|
||||||
|
|
||||||
@target(name="profile-s1", kind=TargetKind.DXF)
|
@target(name="profile-s1", kind=TargetKind.DXF)
|
||||||
def profile_s1(self) -> Cq.Sketch:
|
def profile_s1(self) -> Cq.Sketch:
|
||||||
|
@ -429,15 +453,14 @@ class WingProfile(Model):
|
||||||
("shoulder_bot", (shoulder_mount_inset, h), 90),
|
("shoulder_bot", (shoulder_mount_inset, h), 90),
|
||||||
("shoulder_top", (shoulder_mount_inset, h + shoulder_h), 270),
|
("shoulder_top", (shoulder_mount_inset, h + shoulder_h), 270),
|
||||||
]
|
]
|
||||||
elbow_h = self.elbow_joint.parent_beam.total_height
|
h = self.elbow_height / 2
|
||||||
h = (self.elbow_height - elbow_h) / 2
|
|
||||||
tags_elbow = [
|
tags_elbow = [
|
||||||
("elbow_bot",
|
("elbow_bot",
|
||||||
self.elbow_to_abs(-elbow_mount_inset, h),
|
self.elbow_to_abs(-elbow_mount_inset, h - self.elbow_h2),
|
||||||
self.elbow_angle + 90),
|
self.elbow_angle + 0),
|
||||||
("elbow_top",
|
("elbow_top",
|
||||||
self.elbow_to_abs(-elbow_mount_inset, h + elbow_h),
|
self.elbow_to_abs(-elbow_mount_inset, h + self.elbow_h2),
|
||||||
self.elbow_angle + 270),
|
self.elbow_angle + 0),
|
||||||
]
|
]
|
||||||
profile = self.profile_s1()
|
profile = self.profile_s1()
|
||||||
tags = tags_shoulder + tags_elbow
|
tags = tags_shoulder + tags_elbow
|
||||||
|
@ -457,16 +480,10 @@ class WingProfile(Model):
|
||||||
)
|
)
|
||||||
@submodel(name="spacer-s1-elbow")
|
@submodel(name="spacer-s1-elbow")
|
||||||
def spacer_s1_elbow(self) -> MountingBox:
|
def spacer_s1_elbow(self) -> MountingBox:
|
||||||
holes = [
|
return self.spacer_of_joint(
|
||||||
Hole(x)
|
joint=self.elbow_joint,
|
||||||
for x in self.elbow_joint.parent_hole_pos()
|
segment_thickness=self.s1_thickness,
|
||||||
]
|
dx=self.elbow_h2,
|
||||||
return MountingBox(
|
|
||||||
length=70.0, # FIXME: magic
|
|
||||||
width=self.s1_thickness,
|
|
||||||
thickness=self.spacer_thickness,
|
|
||||||
holes=holes,
|
|
||||||
hole_diam=self.elbow_joint.hole_diam,
|
|
||||||
)
|
)
|
||||||
@assembly()
|
@assembly()
|
||||||
def assembly_s1(self) -> Cq.Assembly:
|
def assembly_s1(self) -> Cq.Assembly:
|
||||||
|
@ -488,7 +505,7 @@ class WingProfile(Model):
|
||||||
result,
|
result,
|
||||||
o,
|
o,
|
||||||
point_tag=t,
|
point_tag=t,
|
||||||
flipped=is_top != is_parent,
|
flipped=is_top != True #is_parent,
|
||||||
)
|
)
|
||||||
return result.solve()
|
return result.solve()
|
||||||
|
|
||||||
|
@ -503,58 +520,43 @@ class WingProfile(Model):
|
||||||
)
|
)
|
||||||
return profile
|
return profile
|
||||||
def surface_s2(self,
|
def surface_s2(self,
|
||||||
thickness: float = 25.4/16,
|
|
||||||
elbow_mount_inset: float = 0,
|
elbow_mount_inset: float = 0,
|
||||||
wrist_mount_inset: float = 0,
|
wrist_mount_inset: float = 0,
|
||||||
front: bool = True) -> Cq.Workplane:
|
front: bool = True) -> Cq.Workplane:
|
||||||
elbow_h = self.elbow_joint.child_beam.total_height
|
h = self.elbow_height / 2
|
||||||
h = (self.elbow_height - elbow_h) / 2
|
|
||||||
tags_elbow = [
|
tags_elbow = [
|
||||||
("elbow_bot",
|
("elbow_bot",
|
||||||
self.elbow_to_abs(elbow_mount_inset, h),
|
self.elbow_to_abs(elbow_mount_inset, h - self.elbow_h2),
|
||||||
self.elbow_angle + 90),
|
self.elbow_angle),
|
||||||
("elbow_top",
|
("elbow_top",
|
||||||
self.elbow_to_abs(elbow_mount_inset, h + elbow_h),
|
self.elbow_to_abs(elbow_mount_inset, h + self.elbow_h2),
|
||||||
self.elbow_angle - 90),
|
self.elbow_angle),
|
||||||
]
|
]
|
||||||
wrist_h = self.wrist_joint.parent_beam.total_height
|
h = self.wrist_height / 2
|
||||||
h = (self.wrist_height - wrist_h) / 2
|
|
||||||
tags_wrist = [
|
tags_wrist = [
|
||||||
("wrist_bot",
|
("wrist_bot",
|
||||||
self.wrist_to_abs(-wrist_mount_inset, h),
|
self.wrist_to_abs(-wrist_mount_inset, h - self.wrist_h2),
|
||||||
self.wrist_angle + 90),
|
self.wrist_angle),
|
||||||
("wrist_top",
|
("wrist_top",
|
||||||
self.wrist_to_abs(-wrist_mount_inset, h + wrist_h),
|
self.wrist_to_abs(-wrist_mount_inset, h + self.wrist_h2),
|
||||||
self.wrist_angle - 90),
|
self.wrist_angle),
|
||||||
]
|
]
|
||||||
profile = self.profile_s2()
|
profile = self.profile_s2()
|
||||||
tags = tags_elbow + tags_wrist
|
tags = tags_elbow + tags_wrist
|
||||||
return nhf.utils.extrude_with_markers(profile, thickness, tags, reverse=front)
|
return nhf.utils.extrude_with_markers(profile, self.panel_thickness, tags, reverse=front)
|
||||||
@submodel(name="spacer-s2-elbow")
|
@submodel(name="spacer-s2-elbow")
|
||||||
def spacer_s2_elbow(self) -> MountingBox:
|
def spacer_s2_elbow(self) -> MountingBox:
|
||||||
holes = [
|
return self.spacer_of_joint(
|
||||||
Hole(x)
|
joint=self.elbow_joint,
|
||||||
for x in self.elbow_joint.child_hole_pos()
|
segment_thickness=self.s2_thickness,
|
||||||
]
|
dx=self.elbow_h2,
|
||||||
return MountingBox(
|
|
||||||
length=50.0, # FIXME: magic
|
|
||||||
width=self.s2_thickness,
|
|
||||||
thickness=self.spacer_thickness,
|
|
||||||
holes=holes,
|
|
||||||
hole_diam=self.elbow_joint.hole_diam,
|
|
||||||
)
|
)
|
||||||
@submodel(name="spacer-s2-wrist")
|
@submodel(name="spacer-s2-wrist")
|
||||||
def spacer_s2_wrist(self) -> MountingBox:
|
def spacer_s2_wrist(self) -> MountingBox:
|
||||||
holes = [
|
return self.spacer_of_joint(
|
||||||
Hole(x)
|
joint=self.wrist_joint,
|
||||||
for x in self.wrist_joint.parent_hole_pos()
|
segment_thickness=self.s2_thickness,
|
||||||
]
|
dx=self.wrist_h2,
|
||||||
return MountingBox(
|
|
||||||
length=70.0, # FIXME: magic
|
|
||||||
width=self.s1_thickness,
|
|
||||||
thickness=self.spacer_thickness,
|
|
||||||
holes=holes,
|
|
||||||
hole_diam=self.wrist_joint.hole_diam,
|
|
||||||
)
|
)
|
||||||
@assembly()
|
@assembly()
|
||||||
def assembly_s2(self) -> Cq.Assembly:
|
def assembly_s2(self) -> Cq.Assembly:
|
||||||
|
@ -576,7 +578,8 @@ class WingProfile(Model):
|
||||||
result,
|
result,
|
||||||
o.generate(),
|
o.generate(),
|
||||||
point_tag=t,
|
point_tag=t,
|
||||||
flipped=is_top != is_parent,
|
flipped=is_top,# != is_parent,
|
||||||
|
rotate=is_parent,
|
||||||
)
|
)
|
||||||
return result.solve()
|
return result.solve()
|
||||||
|
|
||||||
|
@ -591,30 +594,23 @@ class WingProfile(Model):
|
||||||
def surface_s3(self,
|
def surface_s3(self,
|
||||||
front: bool = True) -> Cq.Workplane:
|
front: bool = True) -> Cq.Workplane:
|
||||||
wrist_mount_inset = 0
|
wrist_mount_inset = 0
|
||||||
wrist_h = self.wrist_joint.child_beam.total_height
|
h = self.wrist_height / 2
|
||||||
h = (self.wrist_height - wrist_h) / 2
|
|
||||||
tags = [
|
tags = [
|
||||||
("wrist_bot",
|
("wrist_bot",
|
||||||
self.wrist_to_abs(wrist_mount_inset, h),
|
self.wrist_to_abs(wrist_mount_inset, h - self.wrist_h2),
|
||||||
self.wrist_angle + 90),
|
self.wrist_angle),
|
||||||
("wrist_top",
|
("wrist_top",
|
||||||
self.wrist_to_abs(wrist_mount_inset, h + wrist_h),
|
self.wrist_to_abs(wrist_mount_inset, h + self.wrist_h2),
|
||||||
self.wrist_angle - 90),
|
self.wrist_angle),
|
||||||
]
|
]
|
||||||
profile = self.profile_s3()
|
profile = self.profile_s3()
|
||||||
return nhf.utils.extrude_with_markers(profile, self.panel_thickness, tags, reverse=front)
|
return nhf.utils.extrude_with_markers(profile, self.panel_thickness, tags, reverse=front)
|
||||||
@submodel(name="spacer-s3-wrist")
|
@submodel(name="spacer-s3-wrist")
|
||||||
def spacer_s3_wrist(self) -> MountingBox:
|
def spacer_s3_wrist(self) -> MountingBox:
|
||||||
holes = [
|
return self.spacer_of_joint(
|
||||||
Hole(x)
|
joint=self.wrist_joint,
|
||||||
for x in self.wrist_joint.child_hole_pos()
|
segment_thickness=self.s3_thickness,
|
||||||
]
|
dx=self.wrist_h2,
|
||||||
return MountingBox(
|
|
||||||
length=70.0, # FIXME: magic
|
|
||||||
width=self.s1_thickness,
|
|
||||||
thickness=self.spacer_thickness,
|
|
||||||
holes=holes,
|
|
||||||
hole_diam=self.wrist_joint.hole_diam
|
|
||||||
)
|
)
|
||||||
@assembly()
|
@assembly()
|
||||||
def assembly_s3(self) -> Cq.Assembly:
|
def assembly_s3(self) -> Cq.Assembly:
|
||||||
|
@ -645,8 +641,6 @@ class WingProfile(Model):
|
||||||
parts: Optional[list[str]] = None,
|
parts: Optional[list[str]] = None,
|
||||||
angle_elbow_wrist: float = 0.0,
|
angle_elbow_wrist: float = 0.0,
|
||||||
) -> Cq.Assembly():
|
) -> Cq.Assembly():
|
||||||
assert not self.elbow_joint.flip
|
|
||||||
assert self.wrist_joint.flip
|
|
||||||
if parts is None:
|
if parts is None:
|
||||||
parts = ["s0", "shoulder", "s1", "elbow", "s2", "wrist", "s3"]
|
parts = ["s0", "shoulder", "s1", "elbow", "s2", "wrist", "s3"]
|
||||||
result = (
|
result = (
|
||||||
|
@ -683,20 +677,20 @@ 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/top?conn0", "Plane")
|
.constrain("s1/elbow_top?conn0", "elbow/parent_upper/lip?conn_top0", "Plane")
|
||||||
.constrain("s1/elbow_top?conn1", "elbow/parent_upper/top?conn1", "Plane")
|
.constrain("s1/elbow_top?conn1", "elbow/parent_upper/lip?conn_top1", "Plane")
|
||||||
.constrain("s1/elbow_bot?conn0", "elbow/parent_upper/bot?conn0", "Plane")
|
.constrain("s1/elbow_bot?conn0", "elbow/parent_upper/lip?conn_bot0", "Plane")
|
||||||
.constrain("s1/elbow_bot?conn1", "elbow/parent_upper/bot?conn1", "Plane")
|
.constrain("s1/elbow_bot?conn1", "elbow/parent_upper/lip?conn_bot1", "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/top?conn0", "Plane")
|
.constrain("s2/elbow_top?conn0", "elbow/child/lip?conn_top0", "Plane")
|
||||||
.constrain("s2/elbow_top?conn1", "elbow/child/top?conn1", "Plane")
|
.constrain("s2/elbow_top?conn1", "elbow/child/lip?conn_top1", "Plane")
|
||||||
.constrain("s2/elbow_bot?conn0", "elbow/child/bot?conn0", "Plane")
|
.constrain("s2/elbow_bot?conn0", "elbow/child/lip?conn_bot0", "Plane")
|
||||||
.constrain("s2/elbow_bot?conn1", "elbow/child/bot?conn1", "Plane")
|
.constrain("s2/elbow_bot?conn1", "elbow/child/lip?conn_bot1", "Plane")
|
||||||
)
|
)
|
||||||
if "wrist" in parts:
|
if "wrist" in parts:
|
||||||
result.add(self.wrist_joint.assembly(angle=angle_elbow_wrist), name="wrist")
|
result.add(self.wrist_joint.assembly(angle=angle_elbow_wrist), name="wrist")
|
||||||
|
@ -704,20 +698,20 @@ class WingProfile(Model):
|
||||||
# Mounted backwards to bend in other direction
|
# Mounted backwards to bend in other direction
|
||||||
(
|
(
|
||||||
result
|
result
|
||||||
.constrain("s2/wrist_top?conn0", "wrist/parent_upper/top?conn0", "Plane")
|
.constrain("s2/wrist_top?conn0", "wrist/parent_upper/bot?conn0", "Plane")
|
||||||
.constrain("s2/wrist_top?conn1", "wrist/parent_upper/top?conn1", "Plane")
|
.constrain("s2/wrist_top?conn1", "wrist/parent_upper/bot?conn1", "Plane")
|
||||||
.constrain("s2/wrist_bot?conn0", "wrist/parent_upper/bot?conn0", "Plane")
|
.constrain("s2/wrist_bot?conn0", "wrist/parent_upper/top?conn0", "Plane")
|
||||||
.constrain("s2/wrist_bot?conn1", "wrist/parent_upper/bot?conn1", "Plane")
|
.constrain("s2/wrist_bot?conn1", "wrist/parent_upper/top?conn1", "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/top?conn0", "Plane")
|
.constrain("s3/wrist_top?conn0", "wrist/child/bot?conn0", "Plane")
|
||||||
.constrain("s3/wrist_top?conn1", "wrist/child/top?conn1", "Plane")
|
.constrain("s3/wrist_top?conn1", "wrist/child/bot?conn1", "Plane")
|
||||||
.constrain("s3/wrist_bot?conn0", "wrist/child/bot?conn0", "Plane")
|
.constrain("s3/wrist_bot?conn0", "wrist/child/top?conn0", "Plane")
|
||||||
.constrain("s3/wrist_bot?conn1", "wrist/child/bot?conn1", "Plane")
|
.constrain("s3/wrist_bot?conn1", "wrist/child/top?conn1", "Plane")
|
||||||
)
|
)
|
||||||
if len(parts) > 1:
|
if len(parts) > 1:
|
||||||
result.solve()
|
result.solve()
|
||||||
|
|
Loading…
Reference in New Issue