feat: Tension fibre
This commit is contained in:
parent
a6ddfec552
commit
bbfeb50f8e
|
@ -0,0 +1,58 @@
|
|||
"""
|
||||
A fibre, for bearing tension
|
||||
"""
|
||||
import cadquery as Cq
|
||||
from dataclasses import dataclass
|
||||
import nhf.utils
|
||||
|
||||
def tension_fibre(
|
||||
length: float,
|
||||
hole_diam: float,
|
||||
hole_twist: float=0,
|
||||
thickness: float=0.5) -> Cq.Workplane:
|
||||
"""
|
||||
A fibre which holds tension, with an eyes on each end.
|
||||
|
||||
"""
|
||||
eye_female = Cq.Solid.makeTorus(
|
||||
radius1=hole_diam/2 + thickness/2,
|
||||
radius2=thickness/2,
|
||||
dir=(1,0,0),
|
||||
)
|
||||
hole_length_male = hole_diam * 2.5
|
||||
hole_height_male = hole_diam * 1.2
|
||||
eye_male = Cq.Solid.makeBox(
|
||||
length=hole_length_male + thickness * 2,
|
||||
width=thickness,
|
||||
height=hole_height_male + thickness * 2,
|
||||
).located(
|
||||
Cq.Location((-hole_length_male/2-thickness, -thickness/2, -hole_height_male/2-thickness))
|
||||
).cut(Cq.Solid.makeBox(
|
||||
length=hole_length_male,
|
||||
width=thickness,
|
||||
height=hole_height_male,
|
||||
).located(Cq.Location((-hole_length_male/2, -thickness/2, -hole_height_male/2))))
|
||||
height = length - hole_diam - thickness
|
||||
assert height > 0, "String is too short to support the given hole sizes"
|
||||
h1 = length/2 - hole_diam/2 - thickness/2
|
||||
h2 = length/2 - hole_height_male - thickness/2
|
||||
result = (
|
||||
Cq.Workplane('XY')
|
||||
.cylinder(
|
||||
radius=thickness/2,
|
||||
height=h1,
|
||||
centered=(True, True, False),
|
||||
)
|
||||
.copyWorkplane(Cq.Workplane('YX'))
|
||||
.cylinder(
|
||||
radius=thickness/2,
|
||||
height=h2,
|
||||
centered=(True, True, False),
|
||||
)
|
||||
.union(eye_female.located(Cq.Location((0, 0,length/2))))
|
||||
.union(eye_male.located(Cq.Location((0, 0,-length/2+hole_height_male/2+thickness/2), (0,0,1), hole_twist)))
|
||||
)
|
||||
result.copyWorkplane(Cq.Workplane(Cq.Plane(origin=(0,0,length/2), normal=(1,0,0)))).tagPlane("female")
|
||||
conn1_normal, _ = (Cq.Location((0,0,0),(0,0,1),hole_twist) * Cq.Location((1,0,0))).toTuple()
|
||||
result.copyWorkplane(Cq.Workplane(Cq.Plane(origin=(0,0,-length/2), normal=conn1_normal))).tagPlane("male")
|
||||
return result
|
|
@ -8,6 +8,7 @@ import cadquery as Cq
|
|||
from nhf.build import Model, TargetKind, target, assembly, submodel
|
||||
from nhf.materials import Role, Material
|
||||
from nhf.parts.box import MountingBox, Hole
|
||||
from nhf.parts.fibre import tension_fibre
|
||||
from nhf.parts.item import Item
|
||||
from nhf.parts.fasteners import FlatHeadBolt, HexNut
|
||||
from nhf.touhou.houjuu_nue.common import NUT_COMMON, BOLT_COMMON
|
||||
|
@ -333,7 +334,7 @@ LINEAR_ACTUATOR_BRACKET = MountingBracket()
|
|||
|
||||
BATTERY_BOX = BatteryBox18650()
|
||||
|
||||
@dataclass
|
||||
@dataclass(kw_only=True)
|
||||
class Flexor:
|
||||
"""
|
||||
Actuator assembly which flexes, similar to biceps
|
||||
|
@ -346,17 +347,30 @@ class Flexor:
|
|||
nut: HexNut = LINEAR_ACTUATOR_HEX_NUT
|
||||
bolt: FlatHeadBolt = LINEAR_ACTUATOR_BOLT
|
||||
bracket: MountingBracket = LINEAR_ACTUATOR_BRACKET
|
||||
# Length of line attached to the flexor
|
||||
line_length: float = 0.0
|
||||
line_thickness: float = 0.5
|
||||
# By how much is the line permitted to slack. This reduces the effective stroke length
|
||||
line_slack: float = 0.0
|
||||
|
||||
# FIXME: Add a compression spring so the serviceable distances are not as fixed
|
||||
def __post_init__(self):
|
||||
assert self.line_slack <= self.line_length < self.actuator.stroke_length
|
||||
|
||||
@property
|
||||
def mount_height(self):
|
||||
return self.bracket.hole_to_side_ext
|
||||
|
||||
@property
|
||||
def d_open(self):
|
||||
return self.actuator.conn_length + self.actuator.stroke_length + self.line_length - self.line_slack
|
||||
@property
|
||||
def d_closed(self):
|
||||
return self.actuator.conn_length + self.line_length
|
||||
|
||||
def open_pos(self) -> Tuple[float, float, float]:
|
||||
r, phi, r_ = nhf.geometry.contraction_span_pos_from_radius(
|
||||
d_open=self.actuator.conn_length + self.actuator.stroke_length,
|
||||
d_closed=self.actuator.conn_length,
|
||||
d_open=self.d_open,
|
||||
d_closed=self.d_closed,
|
||||
theta=math.radians(self.motion_span),
|
||||
r=self.arm_radius,
|
||||
smaller=self.pos_smaller,
|
||||
|
@ -376,8 +390,8 @@ class Flexor:
|
|||
|
||||
result = math.sqrt(r * r + rp * rp - 2 * r * rp * math.cos(th))
|
||||
#result = math.sqrt((r * math.cos(th) - rp) ** 2 + (r * math.sin(th)) ** 2)
|
||||
assert self.actuator.conn_length <= result <= self.actuator.conn_length + self.actuator.stroke_length, \
|
||||
f"Illegal length: {result} in {self.actuator.conn_length}+{self.actuator.stroke_length}"
|
||||
assert self.d_closed -1e-6 <= result <= self.d_open + 1e-6,\
|
||||
f"Illegal length: {result} not in [{self.d_closed}, {self.d_open}]"
|
||||
return result
|
||||
|
||||
|
||||
|
@ -393,7 +407,9 @@ class Flexor:
|
|||
Adds the necessary mechanical components to this assembly. Does not
|
||||
invoke `a.solve()`.
|
||||
"""
|
||||
pos = (target_length - self.actuator.conn_length) / self.actuator.stroke_length
|
||||
draft = max(0, target_length - self.d_closed - self.line_length)
|
||||
pos = draft / self.actuator.stroke_length
|
||||
line_l = target_length - draft - self.actuator.conn_length
|
||||
if tag_prefix:
|
||||
tag_prefix = tag_prefix + "_"
|
||||
else:
|
||||
|
@ -411,8 +427,6 @@ class Flexor:
|
|||
.add(self.bracket.assembly(), name=name_bracket_front)
|
||||
.add(self.bolt.assembly(), name=name_bolt_front)
|
||||
.add(self.nut.assembly(), name=name_nut_front)
|
||||
.constrain(f"{name_actuator}/front?conn", f"{name_bracket_front}?conn_mid",
|
||||
"Plane", param=0)
|
||||
.constrain(f"{name_bolt_front}?root", f"{name_bracket_front}?conn_top",
|
||||
"Plane", param=0)
|
||||
.constrain(f"{name_nut_front}?bot", f"{name_bracket_front}?conn_bot",
|
||||
|
@ -427,6 +441,30 @@ class Flexor:
|
|||
.constrain(f"{name_nut_back}?bot", f"{name_bracket_back}?conn_bot",
|
||||
"Plane")
|
||||
)
|
||||
if self.line_length == 0.0:
|
||||
a.constrain(
|
||||
f"{name_actuator}/front?conn",
|
||||
f"{name_bracket_front}?conn_mid",
|
||||
"Plane", param=0)
|
||||
else:
|
||||
(
|
||||
a
|
||||
.addS(tension_fibre(
|
||||
length=line_l,
|
||||
hole_diam=self.nut.diam_thread,
|
||||
thickness=self.line_thickness,
|
||||
), name="fibre", role=Role.CONNECTION)
|
||||
.constrain(
|
||||
f"{name_actuator}/front?conn",
|
||||
"fibre?male",
|
||||
"Plane"
|
||||
)
|
||||
.constrain(
|
||||
f"{name_bracket_front}?conn_mid",
|
||||
"fibre?female",
|
||||
"Plane"
|
||||
)
|
||||
)
|
||||
if tag_hole_front:
|
||||
a.constrain(tag_hole_front, f"{name_bracket_front}?conn_side", "Plane")
|
||||
if tag_hole_back:
|
||||
|
|
|
@ -1067,7 +1067,7 @@ class ElbowJoint(Model):
|
|||
flip: bool = False
|
||||
angle_neutral: float = 30.0
|
||||
|
||||
actuator: Optional[LinearActuator]
|
||||
actuator: Optional[LinearActuator] = None
|
||||
flexor: Optional[Flexor] = None
|
||||
# Rotates the entire flexor
|
||||
flexor_offset_angle: float = 0
|
||||
|
@ -1076,6 +1076,8 @@ class ElbowJoint(Model):
|
|||
flexor_mount_angle_child: float = -90
|
||||
flexor_pos_smaller: bool = True
|
||||
flexor_child_arm_radius: Optional[float] = None
|
||||
flexor_line_length: float = 0.0
|
||||
flexor_line_slack: float = 0.0
|
||||
|
||||
def __post_init__(self):
|
||||
assert self.child_arm_radius > self.disk_joint.radius_housing
|
||||
|
@ -1087,6 +1089,8 @@ class ElbowJoint(Model):
|
|||
motion_span=self.motion_span,
|
||||
pos_smaller=self.flexor_pos_smaller,
|
||||
arm_radius=self.flexor_child_arm_radius,
|
||||
line_length=self.flexor_line_length,
|
||||
line_slack=self.flexor_line_slack,
|
||||
)
|
||||
|
||||
def hole_loc_tags(self):
|
||||
|
|
|
@ -1291,6 +1291,10 @@ class WingL(WingProfile):
|
|||
angle_neutral=30.0,
|
||||
flexor_mount_angle_child=170,
|
||||
flexor_mount_angle_parent=-30,
|
||||
flexor_line_length=30.0,
|
||||
flexor_line_slack=5.0,
|
||||
#flexor_line_length=0.0,
|
||||
#flexor_line_slack=0.0,
|
||||
flexor_offset_angle=15,
|
||||
child_lip_extra_length=5.0,
|
||||
flexor_child_arm_radius=60.0,
|
||||
|
|
Loading…
Reference in New Issue