Files
cadSet/text-to-cad/models/robots/juno/juno_parts/joints.py
T
2026-07-22 19:38:36 +08:00

163 lines
6.7 KiB
Python

"""Connective joint hardware for juno: yokes, carriers, collars.
These small machined parts link the sculpted body segments and carry the
exposed actuator cans for the joints they own. Frames follow the chain table
in juno.py; all builders return identity-location compounds.
"""
from __future__ import annotations
from build123d import Box, Compound, Cylinder, Pos, Rot, chamfer
from .juno_lib import (
ACCENT_COLOR,
ALU_COLOR,
STRUCT_COLOR,
actuator_solids,
part_compound,
styled,
)
def _s(side: str) -> float:
return 1.0 if side == "left" else -1.0
def build_hip_bracket(side: str) -> Compound:
"""Hip yaw can + C-yoke down to the hip-roll axis. Origin: hip-yaw center.
Compact stack (proportion audit): yaw can dia 70 x 34, roll axis at
z = -64, sized for the carrier's dia-56 roll housing (caps to |x| 30).
"""
children = actuator_solids(
"hip_yaw", 70, 34, center=(0, 0, -17), axis=(0, 0, 1), bolts=False
)
plates = []
for sx in (1.0, -1.0):
plates.append(Pos(sx * 38, 0, -65) * Box(12, 46, 54))
bridge = Pos(0, 0, -38) * Box(88, 46, 8)
yoke = plates[0].fuse(plates[1]).fuse(bridge)
children.append(styled(yoke, "hip_yoke", STRUCT_COLOR))
for sx in (1.0, -1.0):
boss = Pos(sx * 47, 0, -64) * Rot(0, 90, 0) * Cylinder(radius=25, height=6)
children.append(styled(boss, f"hip_roll_boss_{'f' if sx > 0 else 'b'}", ALU_COLOR))
return part_compound(f"hip_bracket_{side}", children)
def build_hip_carrier(side: str) -> Compound:
"""Hip roll housing + medial plate to the hip-pitch axis. Origin: roll center.
Compact stack: dia-56 roll housing, hip-pitch axis at z = -78 (clears the
thigh's dia-92 pitch can: 78 > 28 + 46).
"""
s = _s(side)
children = []
housing = Rot(0, 90, 0) * Cylinder(radius=28, height=48)
plate = Pos(0, -s * 44, -42) * Box(76, 8, 110)
bridge = Pos(0, -s * 36, 0) * Box(56, 16, 50)
body = housing.fuse(bridge).fuse(plate)
children.append(styled(body, "hip_carrier_body", STRUCT_COLOR))
for sx in (1.0, -1.0):
cap = Pos(sx * 27, 0, 0) * Rot(0, 90, 0) * Cylinder(radius=30, height=6)
children.append(styled(cap, f"hip_roll_cap_{'f' if sx > 0 else 'b'}", ALU_COLOR))
boss = Pos(0, -s * 38.5, -78) * Rot(90, 0, 0) * Cylinder(radius=32, height=3)
children.append(styled(boss, "hip_pitch_boss", ALU_COLOR))
return part_compound(f"hip_carrier_{side}", children)
def build_ankle_link(side: str) -> Compound:
"""Fused two-axis ankle block: pitch core at origin, roll core 30 below."""
children = []
pitch_core = Rot(90, 0, 0) * Cylinder(radius=27, height=36)
roll_core = Pos(0, 0, -30) * Rot(0, 90, 0) * Cylinder(radius=22, height=28)
neck = Pos(0, 0, -15) * Box(30, 30, 30)
body = pitch_core.fuse(roll_core).fuse(neck)
children.append(styled(body, "ankle_body", STRUCT_COLOR))
for sy in (1.0, -1.0):
cap = Pos(0, sy * 20.5, 0) * Rot(90, 0, 0) * Cylinder(radius=24, height=5)
children.append(styled(cap, f"ankle_pitch_cap_{'l' if sy > 0 else 'r'}", ALU_COLOR))
for sx in (1.0, -1.0):
cap = Pos(sx * 16, 0, -30) * Rot(0, 90, 0) * Cylinder(radius=19, height=4)
children.append(styled(cap, f"ankle_roll_cap_{'f' if sx > 0 else 'b'}", ALU_COLOR))
return part_compound(f"ankle_link_{side}", children)
def build_shoulder_pod(side: str) -> Compound:
"""Shoulder-pitch can + outboard drum + roll clevis. Origin: pitch center.
The outboard module is a chamfered cylindrical drum capping the pitch can
(reads as the shoulder actuator housing, per style review), with a blade
dropping to the shoulder-roll clevis.
"""
s = _s(side)
children = actuator_solids(
"shoulder_pitch", 72, 58, center=(0, s * 14, 0), axis=(0, 1, 0)
)
drum = Pos(0, s * 50, 0) * Rot(90, 0, 0) * Cylinder(radius=40, height=14)
try:
drum = chamfer(drum.edges(), 3.0)
except Exception:
pass
blade = Pos(0, s * 50, -42) * Box(58, 14, 90)
clevis_f = Pos(35, s * 34, -72) * Box(10, 48, 56)
clevis_b = Pos(-35, s * 34, -72) * Box(10, 48, 56)
body = drum.fuse(blade).fuse(clevis_f).fuse(clevis_b)
children.append(styled(body, "pod_body", STRUCT_COLOR))
face = Pos(0, s * 58.5, 0) * Rot(90, 0, 0) * Cylinder(radius=30, height=3)
children.append(styled(face, "pod_face_ring", ALU_COLOR))
hub = Pos(0, s * 61, 0) * Rot(90, 0, 0) * Cylinder(radius=12, height=2)
children.append(styled(hub, "pod_face_hub", ACCENT_COLOR))
for sx in (1.0, -1.0):
boss = (
Pos(sx * 43, s * 34, -72) * Rot(0, 90, 0) * Cylinder(radius=25, height=6)
)
children.append(styled(boss, f"roll_boss_{'f' if sx > 0 else 'b'}", ALU_COLOR))
return part_compound(f"shoulder_pod_{side}", children)
def build_yaw_housing(side: str) -> Compound:
"""Shoulder-roll can + saddle to the upper-arm yaw ring. Origin: roll center."""
children = []
parts = actuator_solids("shoulder_roll", 70, 56, center=(0, 0, 0), axis=(1, 0, 0))
core = parts[0]
saddle = Pos(0, 0, -14) * Cylinder(radius=26, height=16)
core = styled(core.fuse(saddle), "shoulder_roll_can", STRUCT_COLOR)
children.append(core)
children.extend(parts[1:])
ring = Pos(0, 0, -22) * Cylinder(radius=28, height=4)
children.append(styled(ring, "yaw_ring", ALU_COLOR))
return part_compound(f"yaw_housing_{side}", children)
def build_wrist_carrier(side: str) -> Compound:
"""Wrist-roll disc + wrist-pitch can block. Origin: roll center."""
children = []
disc = Pos(0, 0, -2) * Cylinder(radius=22, height=4)
children.append(styled(disc, "wrist_roll_disc", ALU_COLOR))
parts = actuator_solids(
"wrist_pitch", 48, 40, center=(0, 0, -28), axis=(0, 1, 0), bolts=False
)
core = parts[0]
block = Pos(0, 0, -10) * Box(34, 34, 14)
core = styled(core.fuse(block), "wrist_pitch_can", STRUCT_COLOR)
children.append(core)
children.extend(parts[1:])
return part_compound(f"wrist_carrier_{side}", children)
def build_neck_collar() -> Compound:
"""Neck yaw can + pitch clevis. Origin: neck-yaw joint center."""
children = actuator_solids(
"neck_yaw", 44, 30, center=(0, 0, 15), axis=(0, 0, 1), bolts=False
)
for sy in (1.0, -1.0):
plate = Pos(0, sy * 19, 44) * Box(36, 6, 36)
children.append(styled(plate, f"neck_clevis_{'l' if sy > 0 else 'r'}", STRUCT_COLOR))
boss = Pos(0, sy * 23, 46) * Rot(90, 0, 0) * Cylinder(radius=14, height=3)
children.append(styled(boss, f"neck_boss_{'l' if sy > 0 else 'r'}", ALU_COLOR))
can = actuator_solids(
"neck_pitch", 40, 28, center=(0, 0, 46), axis=(0, 1, 0), bolts=False
)
children.extend(can)
return part_compound("neck_collar", children)