feat: Comma joint, Nue wing root stub

This commit is contained in:
Leni Aniva 2024-06-19 21:23:41 -07:00
parent 75c06585ed
commit 8ad5eb9fe6
Signed by: aniva
GPG Key ID: 4D9B1C8D10EA4C50
2 changed files with 161 additions and 15 deletions

View File

@ -99,10 +99,139 @@ def hirth_assembly():
) )
return result return result
def comma_joint(radius=30,
shaft_radius=10,
height=10,
flange=10,
flange_thickness=25,
n_serration=16,
serration_angle_offset=0,
serration_height=5,
serration_inner_radius=20,
serration_theta=2 * math.pi / 48,
serration_tilt=-30,
right_handed=False):
"""
Produces a "o_" shaped joint, with serrations to accomodate a torsion spring
"""
assert flange_thickness <= radius
flange_poly = [
(0, radius - flange_thickness),
(0, radius),
(flange + radius, radius),
(flange + radius, radius - flange_thickness)
]
if right_handed:
flange_poly = [(x, -y) for x,y in flange_poly]
sketch = (
Cq.Sketch()
.circle(radius)
.polygon(flange_poly, mode='a')
.circle(shaft_radius, mode='s')
)
serration_poly = [
(0, 0), (radius, 0),
(radius, radius * math.tan(serration_theta))
]
serration = (
Cq.Workplane('XY')
.sketch()
.polygon(serration_poly)
.circle(radius, mode='i')
.circle(serration_inner_radius, mode='s')
.finalize()
.extrude(serration_height)
.translate(Cq.Vector((-serration_inner_radius, 0, height)))
.rotate(
axisStartPoint=(0, 0, 0),
axisEndPoint=(0, 0, height),
angleDegrees=serration_tilt)
.val()
)
serrations = (
Cq.Workplane('XY')
.polarArray(radius=serration_inner_radius,
startAngle=0+serration_angle_offset,
angle=360+serration_angle_offset,
count=n_serration)
.eachpoint(lambda loc: serration.located(loc))
)
result = (
Cq.Workplane()
.add(sketch)
.extrude(height)
.union(serrations)
.clean()
)
result.polyline([
(0, 0, height - serration_height),
(0, 0, height + serration_height)],
forConstruction=True).tag("serrated")
result.polyline([
(0, radius, 0),
(flange + radius, radius, 0)],
forConstruction=True).tag("tail")
result.faces('>X').tag("tail_end")
return result
def torsion_spring(radius=12,
height=20,
thickness=2,
omega=90,
tail_length=25):
"""
Produces a torsion spring with abridged geometry since sweep is very slow in
cq-editor.
"""
base = (
Cq.Workplane('XY')
.cylinder(height=height, radius=radius,
centered=(True, True, False))
)
base.faces(">Z").tag("mate_top")
base.faces("<Z").tag("mate_bottom")
result = (
base
.cylinder(height=height, radius=radius - thickness, combine='s',
centered=(True, True, True))
.transformed(
offset=(0, radius-thickness),
rotate=(0, 0, 0))
.box(length=tail_length, width=thickness, height=thickness, centered=False)
.copyWorkplane(Cq.Workplane('XY'))
.transformed(
offset=(0, 0, height - thickness),
rotate=(0, 0, omega))
.center(-tail_length, radius-thickness)
.box(length=tail_length, width=thickness, height=thickness, centered=False)
)
return result
def comma_assembly():
joint1 = comma_joint()
joint2 = comma_joint()
spring = torsion_spring()
result = (
Cq.Assembly()
.add(joint1, name="joint1", color=Cq.Color(0.8,0.8,0.5,0.3))
.add(joint2, name="joint2", color=Cq.Color(0.8,0.8,0.5,0.3))
.add(spring, name="spring", color=Cq.Color(0.5,0.5,0.5,1))
.constrain("joint1?serrated", "spring?mate_bottom", "Plane")
.constrain("joint2?serrated", "spring?mate_top", "Plane")
.constrain("joint1?tail", "FixedAxis", (1, 0, 0))
.constrain("joint2?tail", "FixedAxis", (-1, 0, 0))
.solve()
)
return result
class TestJoints(unittest.TestCase): class TestJoints(unittest.TestCase):
def test_hirth_assembly(self): def test_hirth_assembly(self):
hirth_assembly() hirth_assembly()
def test_comma_assembly(self):
comma_assembly()
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()

View File

@ -1,17 +1,34 @@
import cadquery as Cq import cadquery as Cq
from dataclasses import dataclass
def mystery(): @dataclass(frozen=True)
return ( class Parameters:
Cq.Workplane()
.box(1, 1, 1) """
.tag("base") Thickness of the exoskeleton panel in millimetres
.wires(">Z") """
.toPending() panel_thickness: float = 25.4 / 16
.translate((0.1, 0.1, 1.0))
.toPending() # Wing root properties
.loft() """
.faces(">>X", tag="base") Radius of the mounting mechanism of the wing root. This is constrained by
.workplane(centerOption="CenterOfMass") the size of the harness.
.circle(0.2) """
.extrude(3) root_radius: float = 60
)
def wing_root(self,
side_width=30,
side_height=100):
"""
Generate the wing root which contains a Hirth joint at its base and a
rectangular opening on its side, with the necessary interfaces.
"""
result = (
Cq.Workplane("XY")
.circle(self.root_radius)
.transformed(offset=Cq.Vector(80, 0, 80),
rotate=Cq.Vector(0, 45, 0))
.rect(side_width, side_height)
.loft()
)
return result