155 lines
4.6 KiB
Python
155 lines
4.6 KiB
Python
from dataclasses import dataclass
|
|
import unittest
|
|
import cadquery as Cq
|
|
import nhf.joints
|
|
|
|
@dataclass(frozen=True)
|
|
class Parameters:
|
|
|
|
"""
|
|
Thickness of the exoskeleton panel in millimetres
|
|
"""
|
|
panel_thickness: float = 25.4 / 16
|
|
|
|
# Wing root properties
|
|
"""
|
|
Radius of the mounting mechanism of the wing root. This is constrained by
|
|
the size of the harness.
|
|
"""
|
|
root_radius: float = 60
|
|
|
|
"""
|
|
Heights for various wing joints, where the numbers start from the first joint.
|
|
"""
|
|
wing_r1_height = 100
|
|
wing_r1_width = 400
|
|
wing_r2_height = 100
|
|
wing_r3_height = 100
|
|
|
|
"""
|
|
The Houjuu-Scarlett joint mechanism at the base of the wing
|
|
"""
|
|
hs_joint_base_width = 85
|
|
hs_joint_base_thickness = 10
|
|
hs_joint_ring_thickness = 10
|
|
hs_joint_tooth_height = 10
|
|
hs_joint_radius = 30
|
|
hs_joint_radius_inner = 20
|
|
hs_joint_corner_fillet = 5
|
|
hs_joint_corner_cbore_diam = 12
|
|
hs_joint_corner_cbore_depth = 12
|
|
hs_joint_corner_diam = 15
|
|
hs_joint_corner_inset = 15
|
|
|
|
def print_geometries(self):
|
|
return [
|
|
self.hs_joint_parent()
|
|
]
|
|
|
|
def hs_joint_parent(self):
|
|
"""
|
|
Parent part of the Houjuu-Scarlett joint, which is composed of a Hirth
|
|
coupling, a cylindrical base, and a mounting base.
|
|
"""
|
|
hirth = nhf.joints.hirth_joint(
|
|
radius=self.hs_joint_radius,
|
|
radius_inner=self.hs_joint_radius_inner,
|
|
tooth_height=self.hs_joint_tooth_height,
|
|
base_height=self.hs_joint_ring_thickness)
|
|
hole_rect_width = self.hs_joint_base_width - 2 * self.hs_joint_corner_inset
|
|
hirth = (
|
|
hirth
|
|
.faces("<Z")
|
|
.workplane()
|
|
.transformed(
|
|
offset=Cq.Vector(0, 0, -self.hs_joint_ring_thickness / 2),
|
|
rotate=Cq.Vector(90, 0, 0))
|
|
# This hole will drill only to the centre and not through. This is
|
|
# intended.
|
|
.hole(5)
|
|
.val()
|
|
)
|
|
result = (
|
|
Cq.Workplane('XY')
|
|
.box(
|
|
self.hs_joint_base_width,
|
|
self.hs_joint_base_width,
|
|
self.hs_joint_base_thickness,
|
|
centered=(True, True, False))
|
|
.edges("|Z")
|
|
.fillet(self.hs_joint_corner_fillet)
|
|
.faces(">Z")
|
|
.workplane()
|
|
.rect(hole_rect_width, hole_rect_width, forConstruction=True)
|
|
.vertices()
|
|
.cboreHole(
|
|
diameter=self.hs_joint_corner_diam,
|
|
cboreDiameter=self.hs_joint_corner_cbore_diam,
|
|
cboreDepth=self.hs_joint_corner_cbore_depth)
|
|
.faces(">Z")
|
|
.workplane()
|
|
.union(hirth.move((0, 0, self.hs_joint_base_thickness)), tol=0.1)
|
|
.clean()
|
|
)
|
|
return result
|
|
|
|
|
|
|
|
def wing_r1_profile(self) -> Cq.Sketch:
|
|
"""
|
|
Generates the first wing segment profile, with the wing root pointing in
|
|
the positive x axis.
|
|
"""
|
|
# Depression of the wing middle
|
|
bend = 200
|
|
factor = 0.7
|
|
result = (
|
|
Cq.Sketch()
|
|
.segment((0, 0), (0, self.wing_r1_height))
|
|
.spline([
|
|
(0, self.wing_r1_height),
|
|
(0.5 * self.wing_r1_width, self.wing_r1_height - factor * bend),
|
|
(self.wing_r1_width, self.wing_r1_height - bend),
|
|
])
|
|
.segment(
|
|
(self.wing_r1_width, self.wing_r1_height - bend),
|
|
(self.wing_r1_width, -bend),
|
|
)
|
|
.spline([
|
|
(self.wing_r1_width, - bend),
|
|
(0.5 * self.wing_r1_width, - factor * bend),
|
|
(0, 0),
|
|
])
|
|
.assemble()
|
|
)
|
|
return result
|
|
|
|
def wing_r1(self) -> Cq.Solid:
|
|
profile = self.wing_r1_profile()
|
|
result = (
|
|
Cq.Workplane("XY")
|
|
.placeSketch(profile)
|
|
.extrude(self.panel_thickness)
|
|
.val()
|
|
)
|
|
return result
|
|
|
|
def wing_root(self,
|
|
side_width=30,
|
|
side_height=100) -> Cq.Shape:
|
|
"""
|
|
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()
|
|
.val()
|
|
)
|
|
return result
|
|
|