cosplay: Touhou/Houjuu Nue #4

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

View File

@ -75,6 +75,7 @@ class MountingBox(Model):
profile_callback: Optional[Callable[[Cq.Sketch], Cq.Sketch]] = None profile_callback: Optional[Callable[[Cq.Sketch], Cq.Sketch]] = None
def __post_init__(self): def __post_init__(self):
assert self.thickness > 0
for i, hole in enumerate(self.holes): for i, hole in enumerate(self.holes):
if hole.tag is None: if hole.tag is None:
hole.tag = f"conn{i}" hole.tag = f"conn{i}"

View File

@ -72,7 +72,7 @@ ELBOW_AXLE_BOLT = FlatHeadBolt(
diam_head=6.87, diam_head=6.87,
height_head=3.06, height_head=3.06,
diam_thread=4.0, diam_thread=4.0,
height_thread=20.0, height_thread=15.0,
) )
ELBOW_AXLE_WASHER = Washer( ELBOW_AXLE_WASHER = Washer(
mass=0.0, mass=0.0,
@ -888,11 +888,10 @@ class DiskJoint(Model):
radius_housing: float = 22.0 radius_housing: float = 22.0
radius_disk: float = 20.0 radius_disk: float = 20.0
radius_axle: float = 3.0
housing_thickness: float = 4.0 housing_thickness: float = 2.0
disk_thickness: float = 8.0 disk_thickness: float = 6.0
tongue_thickness: float = 10.0 tongue_thickness: float = 12.0
# Amount by which the wall carves in # Amount by which the wall carves in
wall_inset: float = 2.0 wall_inset: float = 2.0
@ -924,7 +923,6 @@ class DiskJoint(Model):
assert self.housing_upper_carve_offset > 0 assert self.housing_upper_carve_offset > 0
assert self.spring_tail_hole_height > self.spring.thickness assert self.spring_tail_hole_height > self.spring.thickness
assert self.tongue_thickness <= self.total_thickness
assert self.axle_bolt.diam_thread == self.axle_washer.diam_thread assert self.axle_bolt.diam_thread == self.axle_washer.diam_thread
assert self.axle_bolt.diam_thread == self.axle_hex_nut.diam_thread assert self.axle_bolt.diam_thread == self.axle_hex_nut.diam_thread
@ -937,6 +935,10 @@ class DiskJoint(Model):
return a return a
return None return None
@property
def radius_axle(self) -> float:
return self.axle_bolt.diam_thread
@property @property
def total_thickness(self) -> float: def total_thickness(self) -> float:
return self.housing_thickness * 2 + self.disk_thickness return self.housing_thickness * 2 + self.disk_thickness
@ -1268,8 +1270,11 @@ class ElbowJoint(Model):
yield -x, f"conn_bot{i}" yield -x, f"conn_bot{i}"
@property @property
def total_thickness(self): def total_thickness(self) -> float:
return self.disk_joint.total_thickness candidate1 = self.disk_joint.axle_bolt.height_thread
candidate2 = self.disk_joint.total_thickness + self.disk_joint.axle_hex_nut.thickness
head_thickness = self.disk_joint.axle_bolt.height_head
return head_thickness + max(candidate1, candidate2)
@property @property
def motion_span(self) -> float: def motion_span(self) -> float:
@ -1338,6 +1343,8 @@ class ElbowJoint(Model):
def post(sketch: Cq.Sketch) -> Cq.Sketch: def post(sketch: Cq.Sketch) -> Cq.Sketch:
y_outer = self.disk_joint.total_thickness / 2 y_outer = self.disk_joint.total_thickness / 2
y_inner = self.disk_joint.tongue_thickness / 2 y_inner = self.disk_joint.tongue_thickness / 2
if y_outer < y_inner:
return sketch
y = (y_outer + y_inner) / 2 y = (y_outer + y_inner) / 2
width = self.lip_side_depression_width width = self.lip_side_depression_width
height = y_outer - y_inner height = y_outer - y_inner

View File

@ -29,6 +29,11 @@ ELBOW_PARAMS = dict(
actuator=LINEAR_ACTUATOR_50, actuator=LINEAR_ACTUATOR_50,
parent_arm_width=15, parent_arm_width=15,
) )
ELBOW_DISK_PARAMS = dict(
housing_thickness=2.5,
disk_thickness=6.8,
tongue_thickness=12.3,
)
WRIST_DISK_PARAMS = dict( WRIST_DISK_PARAMS = dict(
movement_angle=30, movement_angle=30,
radius_disk=13.0, radius_disk=13.0,
@ -116,8 +121,8 @@ class WingProfile(Model):
self.wrist_axle_loc = self.wrist_bot_loc * \ self.wrist_axle_loc = self.wrist_bot_loc * \
Cq.Location.from2d(0, self.wrist_height * self.wrist_axle_pos) 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.elbow_joint.total_thickness < min(self.s1_thickness, self.s2_thickness)
assert self.wrist_joint.total_thickness < min(self.s2_thickness, self.s3_thickness) #assert self.wrist_joint.total_thickness < min(self.s2_thickness, self.s3_thickness)
self.shoulder_joint.angle_neutral = -self.shoulder_angle_neutral - self.shoulder_angle_bias self.shoulder_joint.angle_neutral = -self.shoulder_angle_neutral - self.shoulder_angle_bias
self.shoulder_axle_loc = Cq.Location.from2d(self.shoulder_tip_x, self.shoulder_tip_y - self.shoulder_width / 2, 0) self.shoulder_axle_loc = Cq.Location.from2d(self.shoulder_tip_x, self.shoulder_tip_y - self.shoulder_width / 2, 0)
@ -642,6 +647,29 @@ class WingProfile(Model):
profile_callback=carve_sides, profile_callback=carve_sides,
) )
return mbox return mbox
def _actuator_mount(self, thickness: float, joint: ElbowJoint) -> MountingBox:
def post(sketch: Cq.Sketch) -> Cq.Sketch:
x = thickness / 2 - self.light_strip.height / 2
w = self.light_strip.height
h = self.light_strip.width
return (
sketch
.push([(x, 0), (-x, 0)])
.rect(w, h, mode='s')
#.push([(0, x), (0, -x)])
#.rect(h, w, mode='s')
)
return MountingBox(
length=thickness,
width=thickness,
thickness=self.spacer_thickness,
holes=[Hole(x=0,y=0)],
centred=(True, True),
hole_diam=joint.hole_diam,
centre_left_right_tags=True,
profile_callback=post,
)
@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:
@ -709,14 +737,9 @@ class WingProfile(Model):
) )
@submodel(name="spacer-s1-elbow-act") @submodel(name="spacer-s1-elbow-act")
def spacer_s1_elbow_act(self) -> MountingBox: def spacer_s1_elbow_act(self) -> MountingBox:
return MountingBox( return self._actuator_mount(
length=self.s1_thickness, thickness=self.s1_thickness,
width=self.s1_thickness, joint=self.elbow_joint
thickness=self.spacer_thickness,
holes=[Hole(x=0,y=0)],
centred=(True, True),
hole_diam=self.elbow_joint.hole_diam,
centre_left_right_tags=True,
) )
@assembly() @assembly()
def assembly_s1(self) -> Cq.Assembly: def assembly_s1(self) -> Cq.Assembly:
@ -838,14 +861,9 @@ class WingProfile(Model):
) )
@submodel(name="spacer-s2-elbow-act") @submodel(name="spacer-s2-elbow-act")
def spacer_s2_elbow_act(self) -> MountingBox: def spacer_s2_elbow_act(self) -> MountingBox:
return MountingBox( return self._actuator_mount(
length=self.s2_thickness, thickness=self.s2_thickness,
width=self.s2_thickness, joint=self.elbow_joint
thickness=self.spacer_thickness,
holes=[Hole(x=0,y=0)],
centred=(True, True),
hole_diam=self.elbow_joint.hole_diam,
centre_left_right_tags=True,
) )
@submodel(name="spacer-s2-wrist") @submodel(name="spacer-s2-wrist")
def spacer_s2_wrist(self) -> MountingBox: def spacer_s2_wrist(self) -> MountingBox:
@ -855,14 +873,9 @@ class WingProfile(Model):
) )
@submodel(name="spacer-s2-wrist-act") @submodel(name="spacer-s2-wrist-act")
def spacer_s2_wrist_act(self) -> MountingBox: def spacer_s2_wrist_act(self) -> MountingBox:
return MountingBox( return self._actuator_mount(
length=self.s2_thickness, thickness=self.s2_thickness,
width=self.s2_thickness, joint=self.wrist_joint
thickness=self.spacer_thickness,
holes=[Hole(x=0,y=0)],
centred=(True, True),
hole_diam=self.wrist_joint.hole_diam,
centre_left_right_tags=True,
) )
@assembly() @assembly()
def assembly_s2(self) -> Cq.Assembly: def assembly_s2(self) -> Cq.Assembly:
@ -979,14 +992,9 @@ class WingProfile(Model):
) )
@submodel(name="spacer-s3-wrist-act") @submodel(name="spacer-s3-wrist-act")
def spacer_s3_wrist_act(self) -> MountingBox: def spacer_s3_wrist_act(self) -> MountingBox:
return MountingBox( return self._actuator_mount(
length=self.s3_thickness, thickness=self.s3_thickness,
width=self.s3_thickness, joint=self.wrist_joint
thickness=self.spacer_thickness,
holes=[Hole(x=0,y=0)],
centred=(True, True),
hole_diam=self.wrist_joint.hole_diam,
centre_left_right_tags=True,
) )
@assembly() @assembly()
def assembly_s3(self) -> Cq.Assembly: def assembly_s3(self) -> Cq.Assembly:
@ -1160,6 +1168,7 @@ class WingR(WingProfile):
disk_joint=DiskJoint( disk_joint=DiskJoint(
movement_angle=55, movement_angle=55,
spring_angle_at_0=75, spring_angle_at_0=75,
**ELBOW_DISK_PARAMS,
), ),
flexor_offset_angle=15, flexor_offset_angle=15,
flexor_mount_angle_child=-75, flexor_mount_angle_child=-75,
@ -1416,6 +1425,7 @@ class WingL(WingProfile):
disk_joint=DiskJoint( disk_joint=DiskJoint(
spring_angle_at_0=100, spring_angle_at_0=100,
movement_angle=50, movement_angle=50,
**ELBOW_DISK_PARAMS,
), ),
angle_neutral=30.0, angle_neutral=30.0,
flexor_mount_angle_child=220, flexor_mount_angle_child=220,
@ -1442,6 +1452,7 @@ class WingL(WingProfile):
wrist_height: float = 43.0 wrist_height: float = 43.0
wrist_joint: ElbowJoint = field(default_factory=lambda: ElbowJoint( wrist_joint: ElbowJoint = field(default_factory=lambda: ElbowJoint(
disk_joint=DiskJoint( disk_joint=DiskJoint(
tongue_thickness=8.0,
**WRIST_DISK_PARAMS, **WRIST_DISK_PARAMS,
), ),
flip=False, flip=False,