cosplay: Touhou/Houjuu Nue #4

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

View File

@ -390,6 +390,8 @@ class Flexor:
pos = (target_length - self.actuator.conn_length) / self.actuator.stroke_length pos = (target_length - self.actuator.conn_length) / self.actuator.stroke_length
if tag_prefix: if tag_prefix:
tag_prefix = tag_prefix + "_" tag_prefix = tag_prefix + "_"
else:
tag_prefix = ""
name_actuator = f"{tag_prefix}actuator" name_actuator = f"{tag_prefix}actuator"
name_bracket_front = f"{tag_prefix}bracket_front" name_bracket_front = f"{tag_prefix}bracket_front"
name_bracket_back = f"{tag_prefix}bracket_back" name_bracket_back = f"{tag_prefix}bracket_back"
@ -397,6 +399,7 @@ class Flexor:
name_bolt_back = f"{tag_prefix}back_bolt" name_bolt_back = f"{tag_prefix}back_bolt"
name_nut_front = f"{tag_prefix}front_nut" name_nut_front = f"{tag_prefix}front_nut"
name_nut_back = f"{tag_prefix}back_nut" name_nut_back = f"{tag_prefix}back_nut"
print(name_bracket_back)
( (
a a
.add(self.actuator.assembly(pos=pos), name=name_actuator) .add(self.actuator.assembly(pos=pos), name=name_actuator)

View File

@ -208,7 +208,8 @@ class RootJoint(Model):
def assembly(self, def assembly(self,
offset: int = 0, offset: int = 0,
fastener_pos: float = 0) -> Cq.Assembly: fastener_pos: float = 0,
ignore_fasteners: bool = False) -> Cq.Assembly:
""" """
Specify knob position to determine the position of the knob from fully Specify knob position to determine the position of the knob from fully
inserted (0) or fully uninserted (1) inserted (0) or fully uninserted (1)
@ -223,13 +224,17 @@ class RootJoint(Model):
.addS(self.child(), name="child", .addS(self.child(), name="child",
material=Material.PLASTIC_PLA, material=Material.PLASTIC_PLA,
role=Role.CHILD) role=Role.CHILD)
.addS(self.hex_nut.assembly(), name="hex_nut")
.addS(self.knob.assembly(), name="knob",
loc=Cq.Location((0, 0, knob_h * fastener_pos)))
.constrain("knob/thread", "Fixed")
.constrain("hex_nut?bot", "parent?base", "Plane", param=0)
.constrain("hex_nut?dirX", "parent@faces@>X", "Axis", param=0)
) )
if not ignore_fasteners:
(
result
.addS(self.hex_nut.assembly(), name="hex_nut")
.addS(self.knob.assembly(), name="knob",
loc=Cq.Location((0, 0, knob_h * fastener_pos)))
.constrain("knob/thread", "Fixed")
.constrain("hex_nut?bot", "parent?base", "Plane", param=0)
.constrain("hex_nut?dirX", "parent@faces@>X", "Axis", param=0)
)
self.hirth_joint.add_constraints( self.hirth_joint.add_constraints(
result, result,
"parent", "parent",
@ -526,6 +531,7 @@ class ShoulderJoint(Model):
self, self,
fastener_pos: float = 0.0, fastener_pos: float = 0.0,
deflection: float = 0.0, deflection: float = 0.0,
ignore_fasteners: bool = False,
) -> Cq.Assembly: ) -> Cq.Assembly:
assert deflection <= self.angle_max_deflection assert deflection <= self.angle_max_deflection
directrix = self.directrix_id directrix = self.directrix_id
@ -547,14 +553,18 @@ class ShoulderJoint(Model):
.addS(self.parent_bot(), .addS(self.parent_bot(),
name="parent_bot", name="parent_bot",
role=Role.PARENT, material=mat) role=Role.PARENT, material=mat)
# Fasteners
.addS(self.bolt.assembly(), name="bolt_top",
loc=Cq.Location((0, 0, bolt_z)))
.constrain("bolt_top?root", 'Fixed')
.addS(self.bolt.assembly(), name="bolt_bot",
loc=Cq.Location((0, 0, -bolt_z), (1,0,0), 180))
.constrain("bolt_bot?root", 'Fixed')
) )
if not ignore_fasteners:
(
result
# Fasteners
.addS(self.bolt.assembly(), name="bolt_top",
loc=Cq.Location((0, 0, bolt_z)))
.constrain("bolt_top?root", 'Fixed')
.addS(self.bolt.assembly(), name="bolt_bot",
loc=Cq.Location((0, 0, -bolt_z), (1,0,0), 180))
.constrain("bolt_bot?root", 'Fixed')
)
TorsionJoint.add_constraints( TorsionJoint.add_constraints(
result, result,
rider="child/rider_top", rider="child/rider_top",
@ -1075,7 +1085,7 @@ class ElbowJoint(Model):
return self.disk_joint.housing_lower() return self.disk_joint.housing_lower()
@target(name="parent-upper") @target(name="parent-upper")
def parent_joint_upper(self): def parent_joint_upper(self, generate_mount: bool=False):
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.disk_joint.total_thickness conn_h = self.disk_joint.total_thickness
@ -1120,16 +1130,25 @@ class ElbowJoint(Model):
#.solve() #.solve()
) )
if self.flexor: if self.flexor:
# Orientes the hole surface so it faces +X if generate_mount:
loc_thickness = Cq.Location((-self.lip_thickness, 0, 0), (0, 1, 0), 90) # Orientes the hole surface so it faces +X
result.add( loc_thickness = Cq.Location((-self.lip_thickness, 0, 0), (0, 1, 0), 90)
self.actuator_mount(), result.add(
name="act", self.actuator_mount(),
loc=self.actuator_mount_loc(child=False) * loc_thickness) name="act",
loc=self.actuator_mount_loc(child=False) * loc_thickness)
else:
result.add(
Cq.Edge.makeLine((-1,0,0), (1,0,0)),
name="act",
loc=self.actuator_mount_loc(child=False))
return result return result
@assembly() @assembly()
def assembly(self, angle: float = 0) -> Cq.Assembly: def assembly(self,
angle: float = 0,
generate_mount: bool = False,
ignore_actuators: bool = False) -> Cq.Assembly:
assert 0 <= angle <= self.motion_span assert 0 <= angle <= self.motion_span
result = ( result = (
Cq.Assembly() Cq.Assembly()
@ -1137,7 +1156,7 @@ class ElbowJoint(Model):
role=Role.CHILD, material=self.material) role=Role.CHILD, material=self.material)
.addS(self.parent_joint_lower(), name="parent_lower", .addS(self.parent_joint_lower(), name="parent_lower",
role=Role.CASING, material=self.material) role=Role.CASING, material=self.material)
.addS(self.parent_joint_upper(), name="parent_upper", .addS(self.parent_joint_upper(generate_mount=generate_mount), name="parent_upper",
role=Role.PARENT, material=self.material) role=Role.PARENT, material=self.material)
#.constrain("child/disk?mate_bot", "Fixed") #.constrain("child/disk?mate_bot", "Fixed")
) )
@ -1148,14 +1167,14 @@ class ElbowJoint(Model):
disk="child/disk", disk="child/disk",
angle=angle, angle=angle,
) )
if self.flexor: if not ignore_actuators and self.flexor:
target_length = self.flexor.target_length_at_angle( target_length = self.flexor.target_length_at_angle(
angle=angle, angle=angle,
) )
self.flexor.add_to( self.flexor.add_to(
result, result,
target_length=target_length, target_length=target_length,
tag_hole_back="parent_upper/act?mount", tag_hole_back="parent_upper/act",
tag_hole_front="child/act?mount", tag_hole_front="child/act?mount",
tag_dir="parent_lower?mate", tag_dir="parent_lower?mate",
) )

View File

@ -362,7 +362,9 @@ class WingProfile(Model):
return result return result
@assembly() @assembly()
def assembly_s0(self, ignore_detail: bool=False) -> Cq.Assembly: def assembly_s0(
self,
ignore_electronics: bool=False) -> Cq.Assembly:
result = ( result = (
Cq.Assembly() Cq.Assembly()
.addS(self.surface_s0(top=True), name="bot", .addS(self.surface_s0(top=True), name="bot",
@ -401,7 +403,7 @@ class WingProfile(Model):
.constrain(f"{tag}?{top_tag}", f"top?{tag}", "Plane") .constrain(f"{tag}?{top_tag}", f"top?{tag}", "Plane")
.constrain(f"{tag}?dir", f"top?{tag}_dir", "Axis") .constrain(f"{tag}?dir", f"top?{tag}_dir", "Axis")
) )
if not ignore_detail: if not ignore_electronics:
result.add(self.electronic_board.assembly(), name="electronic_board") result.add(self.electronic_board.assembly(), name="electronic_board")
for hole in self.electronic_board.mount_holes: for hole in self.electronic_board.mount_holes:
assert hole.tag assert hole.tag
@ -923,7 +925,9 @@ class WingProfile(Model):
elbow_wrist_deflection: float = 0.0, elbow_wrist_deflection: float = 0.0,
root_offset: int = 5, root_offset: int = 5,
fastener_pos: float = 0.0, fastener_pos: float = 0.0,
ignore_detail: bool = False, ignore_fasteners: bool = False,
ignore_electronics: bool = False,
ignore_actuators: bool = False,
) -> Cq.Assembly(): ) -> Cq.Assembly():
if parts is None: if parts is None:
parts = [ parts = [
@ -944,11 +948,14 @@ class WingProfile(Model):
tag_top, tag_bot = tag_bot, tag_top tag_top, tag_bot = tag_bot, tag_top
if "s0" in parts: if "s0" in parts:
result.add(self.assembly_s0(ignore_detail=ignore_detail), name="s0") result.add(self.assembly_s0(
ignore_electronics=ignore_electronics
), name="s0")
if "root" in parts: if "root" in parts:
result.addS(self.root_joint.assembly( result.addS(self.root_joint.assembly(
offset=root_offset, offset=root_offset,
fastener_pos=fastener_pos, fastener_pos=fastener_pos,
ignore_fasteners=ignore_fasteners,
), name="root") ), name="root")
result.constrain("root/parent", "Fixed") result.constrain("root/parent", "Fixed")
if "s0" in parts and "root" in parts: if "s0" in parts and "root" in parts:
@ -962,7 +969,8 @@ class WingProfile(Model):
angle = shoulder_deflection * self.shoulder_joint.angle_max_deflection angle = shoulder_deflection * self.shoulder_joint.angle_max_deflection
result.add(self.shoulder_joint.assembly( result.add(self.shoulder_joint.assembly(
fastener_pos=fastener_pos, fastener_pos=fastener_pos,
deflection=angle), name="shoulder") deflection=angle,
ignore_fasteners=ignore_fasteners), name="shoulder")
if "s0" in parts and "shoulder" in parts: if "s0" in parts and "shoulder" in parts:
for i in range(len(self.shoulder_joint.parent_conn_hole_pos)): for i in range(len(self.shoulder_joint.parent_conn_hole_pos)):
( (
@ -984,7 +992,9 @@ class WingProfile(Model):
) )
if "elbow" in parts: if "elbow" in parts:
angle = self.elbow_joint.motion_span * 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,
ignore_actuators=ignore_actuators), name="elbow")
if "s1" in parts and "elbow" in parts: if "s1" in parts and "elbow" in parts:
( (
result result
@ -993,6 +1003,11 @@ class WingProfile(Model):
.constrain("s1/elbow_bot?conn0", "elbow/parent_upper/lip?conn_bot0", "Plane") .constrain("s1/elbow_bot?conn0", "elbow/parent_upper/lip?conn_bot0", "Plane")
.constrain("s1/elbow_bot?conn1", "elbow/parent_upper/lip?conn_bot1", "Plane") .constrain("s1/elbow_bot?conn1", "elbow/parent_upper/lip?conn_bot1", "Plane")
) )
if not ignore_actuators:
(
result
.constrain("elbow/bracket_back?conn_side", "s1/elbow_act?conn0", "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:
@ -1005,7 +1020,9 @@ class WingProfile(Model):
) )
if "wrist" in parts: if "wrist" in parts:
angle = self.wrist_joint.motion_span * 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,
ignore_actuators=ignore_actuators), name="wrist")
wrist_n_holes = len(self.wrist_joint.hole_pos) wrist_n_holes = len(self.wrist_joint.hole_pos)
if "s2" in parts and "wrist" in parts: if "s2" in parts and "wrist" in parts:
for i in range(wrist_n_holes): for i in range(wrist_n_holes):
@ -1023,6 +1040,11 @@ class WingProfile(Model):
.constrain(f"s3/wrist_top?conn{i}", f"wrist/child/lip?conn_top{i}", "Plane") .constrain(f"s3/wrist_top?conn{i}", f"wrist/child/lip?conn_top{i}", "Plane")
.constrain(f"s3/wrist_bot?conn{i}", f"wrist/child/lip?conn_bot{i}", "Plane") .constrain(f"s3/wrist_bot?conn{i}", f"wrist/child/lip?conn_bot{i}", "Plane")
) )
if not ignore_actuators:
(
result
.constrain("wrist/bracket_back?conn_side", "s2/wrist_act?conn0", "Plane")
)
if len(parts) > 1: if len(parts) > 1:
result.solve() result.solve()