diff --git a/nhf/joints.py b/nhf/joints.py index 9cdd0ad..02c7527 100644 --- a/nhf/joints.py +++ b/nhf/joints.py @@ -99,10 +99,139 @@ def hirth_assembly(): ) 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") - .toPending() - .translate((0.1, 0.1, 1.0)) - .toPending() - .loft() - .faces(">>X", tag="base") - .workplane(centerOption="CenterOfMass") - .circle(0.2) - .extrude(3) - ) +@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 + + 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