cosplay: Touhou/Houjuu Nue #4

Open
aniva wants to merge 189 commits from touhou/houjuu-nue into main
3 changed files with 45 additions and 33 deletions
Showing only changes of commit ddeaf1194f - Show all commits

View File

@ -300,6 +300,8 @@ LINEAR_ACTUATOR_10 = LinearActuator(
back_hole_ext=4.5/2,
segment1_length=30.0,
segment2_length=30.0,
segment1_width=15.0,
segment2_width=21.0,
)
LINEAR_ACTUATOR_HEX_NUT = HexNut(
mass=0.8,

View File

@ -882,8 +882,8 @@ class ElbowJoint(Model):
angle_neutral: float = 30.0
actuator: LinearActuator
flexor: Flexor = None
actuator: Optional[LinearActuator]
flexor: Optional[Flexor] = None
# Rotates the entire flexor
flexor_offset_angle: float = 0
# Rotates the surface of the mount
@ -893,6 +893,7 @@ class ElbowJoint(Model):
assert self.child_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.lip_thickness / 2
if self.actuator:
self.flexor = Flexor(
actuator=self.actuator,
motion_span=self.motion_span
@ -990,8 +991,9 @@ class ElbowJoint(Model):
Cq.Assembly()
.add(self.disk_joint.disk(), name="disk", loc=Cq.Location((0, 0, -dz)))
.add(self.lip().cut(disk_cut), name="lip", loc=loc_disk.inverse * loc_lip)
.add(self.actuator_mount(), name="act", loc=self.actuator_mount_loc(child=True))
)
if self.flexor:
result.add(self.actuator_mount(), name="act", loc=self.actuator_mount_loc(child=True))
return result
@target(name="parent-lower")
@ -1040,12 +1042,15 @@ class ElbowJoint(Model):
Cq.Location((0, 0, 0), (0, 1, 0), 90))
.add(connector, name="connector",
loc=loc_net_housing.inverse * axial_offset)
.add(self.actuator_mount(),
name="act", loc=self.actuator_mount_loc(child=False))
#.constrain("housing", "Fixed")
#.constrain("connector", "Fixed")
#.solve()
)
if self.flexor:
result.add(
self.actuator_mount(),
name="act",
loc=self.actuator_mount_loc(child=False))
return result
@assembly()

View File

@ -51,7 +51,7 @@ class WingProfile(Model):
disk_joint=DiskJoint(
movement_angle=55,
),
hole_diam=6.0,
hole_diam=4.0,
angle_neutral=15.0,
actuator=LINEAR_ACTUATOR_50,
flexor_offset_angle=-15,
@ -65,13 +65,14 @@ class WingProfile(Model):
radius_disk=13.0,
radius_housing=15.0,
),
hole_pos=[10, 20],
lip_length=50,
hole_pos=[10],
lip_length=30,
child_arm_radius=23.0,
parent_arm_radius=30.0,
hole_diam=4.0,
angle_neutral=-30.0,
actuator=LINEAR_ACTUATOR_10,
# The left side wrist is too small for an actuator to work
actuator=None, #LINEAR_ACTUATOR_10,
))
# Distance between the two spacers on the elbow, halved
wrist_h2: float = 5.0
@ -90,6 +91,7 @@ class WingProfile(Model):
wrist_rotate: float = -30.0
# Position of the elbow axle with 0 being bottom and 1 being top (flipped on the left side)
elbow_axle_pos: float = 0.3
wrist_axle_pos: float = 0.0
# False for the right side, True for the left side
flip: bool
@ -103,9 +105,8 @@ class WingProfile(Model):
self.elbow_axle_pos = 1 - self.elbow_axle_pos
self.elbow_axle_loc = self.elbow_bot_loc * Cq.Location.from2d(0, self.elbow_height * self.elbow_axle_pos)
if self.flip:
self.wrist_axle_loc = self.wrist_bot_loc * Cq.Location.from2d(0, self.wrist_height / 2)
else:
self.wrist_axle_loc = self.wrist_bot_loc
self.wrist_axle_pos = 1 - self.wrist_axle_pos
self.wrist_axle_loc = self.wrist_bot_loc * Cq.Location.from2d(0, self.wrist_height * self.wrist_axle_pos)
assert self.elbow_joint.total_thickness < min(self.s1_thickness, self.s2_thickness)
assert self.wrist_joint.total_thickness < min(self.s2_thickness, self.s3_thickness)
@ -126,7 +127,8 @@ class WingProfile(Model):
"""
s3 does not need to duck under s2
"""
return self.s1_thickness - 2 * self.panel_thickness
extra = 2 * self.panel_thickness if self.flip else 0
return self.s1_thickness - 2 * self.panel_thickness - extra
@submodel(name="shoulder-joint")
def submodel_shoulder_joint(self) -> Model:
@ -395,7 +397,7 @@ class WingProfile(Model):
for p in points
])
)
def _joint_extension_profile(
def _child_joint_extension_profile(
self,
axle_loc: Cq.Location,
radius: float,
@ -640,8 +642,10 @@ class WingProfile(Model):
return extrude_with_markers(profile, self.panel_thickness, tags, reverse=front)
@target(name="profile-s2-bridge", kind=TargetKind.DXF)
def profile_s2_bridge(self) -> Cq.Workplane:
# FIXME: Leave some margin here so we can glue the panels
# Generates the extension profile, which is required on both sides
profile = self._joint_extension_profile(
profile = self._child_joint_extension_profile(
axle_loc=self.wrist_axle_loc,
radius=self.wrist_height * (0.5 if self.flip else 1),
angle_span=self.wrist_joint.motion_span,
@ -881,24 +885,23 @@ class WingProfile(Model):
if "wrist" in parts:
angle = self.wrist_joint.motion_span * elbow_wrist_deflection
result.add(self.wrist_joint.assembly(angle=angle), name="wrist")
wrist_n_holes = len(self.wrist_joint.hole_pos)
if "s2" in parts and "wrist" in parts:
# Mounted backwards to bend in other direction
for i in range(wrist_n_holes):
(
result
.constrain("s2/wrist_top?conn0", f"wrist/parent_upper/lip?conn_{tag_bot}0", "Plane")
.constrain("s2/wrist_top?conn1", f"wrist/parent_upper/lip?conn_{tag_bot}1", "Plane")
.constrain("s2/wrist_bot?conn0", f"wrist/parent_upper/lip?conn_{tag_top}0", "Plane")
.constrain("s2/wrist_bot?conn1", f"wrist/parent_upper/lip?conn_{tag_top}1", "Plane")
.constrain(f"s2/wrist_top?conn{i}", f"wrist/parent_upper/lip?conn_{tag_bot}{i}", "Plane")
.constrain(f"s2/wrist_bot?conn{i}", f"wrist/parent_upper/lip?conn_{tag_top}{i}", "Plane")
)
if "s3" in parts:
result.add(self.assembly_s3(), name="s3")
if "s3" in parts and "wrist" in parts:
for i in range(wrist_n_holes):
(
result
.constrain("s3/wrist_top?conn0", f"wrist/child/lip?conn_{tag_bot}0", "Plane")
.constrain("s3/wrist_top?conn1", f"wrist/child/lip?conn_{tag_bot}1", "Plane")
.constrain("s3/wrist_bot?conn0", f"wrist/child/lip?conn_{tag_top}0", "Plane")
.constrain("s3/wrist_bot?conn1", f"wrist/child/lip?conn_{tag_top}1", "Plane")
.constrain(f"s3/wrist_top?conn{i}", f"wrist/child/lip?conn_{tag_bot}{i}", "Plane")
.constrain(f"s3/wrist_bot?conn{i}", f"wrist/child/lip?conn_{tag_top}{i}", "Plane")
)
if len(parts) > 1:
result.solve()
@ -1095,6 +1098,8 @@ class WingL(WingProfile):
arrow_height: float = 120.0
flip: bool = True
elbow_axle_pos: float = 0.4
wrist_axle_pos: float = 0.5
def __post_init__(self):
assert self.wrist_height <= self.shoulder_joint.height