Add angle joint stub, hole in rotor
This commit is contained in:
parent
74145f88d2
commit
97675a2fc8
|
@ -3,7 +3,7 @@ from nhf.materials import Role, Material
|
||||||
import nhf.utils
|
import nhf.utils
|
||||||
|
|
||||||
import math
|
import math
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass, field
|
||||||
import cadquery as Cq
|
import cadquery as Cq
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
|
@ -13,28 +13,43 @@ class Onbashira(Model):
|
||||||
# Dimensions of each side panel
|
# Dimensions of each side panel
|
||||||
side_width: float = 200.0
|
side_width: float = 200.0
|
||||||
side_length: float = 600.0
|
side_length: float = 600.0
|
||||||
|
|
||||||
side_thickness: float = 25.4 / 8
|
side_thickness: float = 25.4 / 8
|
||||||
|
|
||||||
|
# Joints between two sets of side panels
|
||||||
|
angle_joint_thickness: float = 25.4 / 4
|
||||||
|
# Z-axis size of each angle joint
|
||||||
|
angle_joint_depth: float = 50.0
|
||||||
|
# Gap of each angle joint to connect the outside to the inside
|
||||||
|
angle_joint_gap: float = 10.0
|
||||||
|
angle_joint_bolt_length: float = 50.0
|
||||||
|
angle_joint_bolt_diam: float = 10.0
|
||||||
|
# Position of the holes, with (0, 0) being the centre of each side
|
||||||
|
angle_joint_hole_position: list[float] = field(default_factory=lambda: [
|
||||||
|
(20, 20),
|
||||||
|
(70, 20),
|
||||||
|
])
|
||||||
|
|
||||||
# Dimensions of gun barrels
|
# Dimensions of gun barrels
|
||||||
barrel_diam: float = 25.4 * 2
|
barrel_diam: float = 25.4 * 2
|
||||||
barrel_length: float = 300.0
|
barrel_length: float = 300.0
|
||||||
# Radius from barrel centre to axis
|
# Radius from barrel centre to axis
|
||||||
rotation_radius: float = 75.0
|
rotation_radius: float = 90.0
|
||||||
n_bearing_balls: int = 24
|
n_bearing_balls: int = 24
|
||||||
# Size of ball bearings
|
# Size of ball bearings
|
||||||
bearing_ball_diam: float = 25.4 * 1/2
|
bearing_ball_diam: float = 25.4 * 1/2
|
||||||
bearing_ball_gap: float = .5
|
bearing_ball_gap: float = .5
|
||||||
# Thickness of bearing disks
|
# Thickness of bearing disks
|
||||||
bearing_thickness: float = 20.0
|
bearing_thickness: float = 20.0
|
||||||
bearing_track_radius: float = 120.0
|
bearing_track_radius: float = 135.0
|
||||||
# Gap between the inner and outer bearing disks
|
# Gap between the inner and outer bearing disks
|
||||||
bearing_gap: float = 10.0
|
bearing_gap: float = 10.0
|
||||||
bearing_disk_thickness: float = 25.4 / 8
|
bearing_disk_thickness: float = 25.4 / 8
|
||||||
|
|
||||||
|
rotor_inner_radius: float = 55.0
|
||||||
|
|
||||||
rotor_bind_bolt_diam: float = 10.0
|
rotor_bind_bolt_diam: float = 10.0
|
||||||
rotor_bind_radius: float = 50.0
|
rotor_bind_radius: float = 110.0
|
||||||
stator_bind_radius: float = 150.0
|
stator_bind_radius: float = 170.0
|
||||||
|
|
||||||
material_side: Material = Material.WOOD_BIRCH
|
material_side: Material = Material.WOOD_BIRCH
|
||||||
material_bearing: Material = Material.PLASTIC_PLA
|
material_bearing: Material = Material.PLASTIC_PLA
|
||||||
|
@ -47,18 +62,37 @@ class Onbashira(Model):
|
||||||
assert self.bulk_radius - self.side_thickness - self.bearing_thickness - self.bearing_diam > self.rotation_radius + self.barrel_diam / 2
|
assert self.bulk_radius - self.side_thickness - self.bearing_thickness - self.bearing_diam > self.rotation_radius + self.barrel_diam / 2
|
||||||
assert self.bearing_gap < 0.95 * self.bearing_ball_diam
|
assert self.bearing_gap < 0.95 * self.bearing_ball_diam
|
||||||
assert self.rotor_bind_bolt_diam < self.rotor_bind_radius < self.bearing_track_radius
|
assert self.rotor_bind_bolt_diam < self.rotor_bind_radius < self.bearing_track_radius
|
||||||
assert self.bearing_track_radius < self.stator_bind_radius
|
assert self.rotor_inner_radius < self.bearing_track_radius < self.stator_bind_radius
|
||||||
|
assert self.angle_joint_thickness > self.side_thickness
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def angle_side(self) -> float:
|
def angle_side(self) -> float:
|
||||||
return 360 / self.n_side
|
return 360 / self.n_side
|
||||||
|
@property
|
||||||
|
def side_width_inner(self) -> float:
|
||||||
|
"""
|
||||||
|
Interior side width
|
||||||
|
|
||||||
|
If outer width is `wi`, inner width is `wo`, each side's cross section
|
||||||
|
is a trapezoid with sides `wi`, `wo`, and height `h` (side thickness)
|
||||||
|
"""
|
||||||
|
theta = math.pi / self.n_side
|
||||||
|
dt = self.side_thickness * math.tan(theta)
|
||||||
|
return self.side_width - dt * 2
|
||||||
|
@property
|
||||||
|
def angle_joint_extra_width(self) -> float:
|
||||||
|
theta = math.pi / self.n_side
|
||||||
|
dt = self.angle_joint_thickness * math.tan(theta)
|
||||||
|
return dt * 2
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def angle_dihedral(self) -> float:
|
def angle_dihedral(self) -> float:
|
||||||
return 180 - self.angle_side
|
return 180 - self.angle_side
|
||||||
@property
|
@property
|
||||||
def bulk_radius(self) -> float:
|
def bulk_radius(self) -> float:
|
||||||
"""
|
"""
|
||||||
Calculate radius of the bulk to the centre
|
Radius of the bulk (surface of each side) to the centre
|
||||||
"""
|
"""
|
||||||
return self.side_width / 2 / math.tan(math.radians(self.angle_side / 2))
|
return self.side_width / 2 / math.tan(math.radians(self.angle_side / 2))
|
||||||
@property
|
@property
|
||||||
|
@ -78,7 +112,7 @@ class Onbashira(Model):
|
||||||
def profile_bearing_stator(self) -> Cq.Sketch:
|
def profile_bearing_stator(self) -> Cq.Sketch:
|
||||||
return (
|
return (
|
||||||
Cq.Sketch()
|
Cq.Sketch()
|
||||||
.regularPolygon(self.side_width, self.n_side)
|
.regularPolygon(self.side_width - self.side_thickness, self.n_side)
|
||||||
.circle(self.bearing_track_radius + self.bearing_gap/2, mode="s")
|
.circle(self.bearing_track_radius + self.bearing_gap/2, mode="s")
|
||||||
.reset()
|
.reset()
|
||||||
.regularPolygon(
|
.regularPolygon(
|
||||||
|
@ -99,6 +133,7 @@ class Onbashira(Model):
|
||||||
return (
|
return (
|
||||||
Cq.Sketch()
|
Cq.Sketch()
|
||||||
.circle(self.bearing_track_radius - self.bearing_gap/2)
|
.circle(self.bearing_track_radius - self.bearing_gap/2)
|
||||||
|
.circle(self.rotor_inner_radius, mode="s")
|
||||||
.reset()
|
.reset()
|
||||||
.regularPolygon(
|
.regularPolygon(
|
||||||
self.rotation_radius, self.n_side,
|
self.rotation_radius, self.n_side,
|
||||||
|
@ -143,6 +178,9 @@ class Onbashira(Model):
|
||||||
|
|
||||||
@target(name="pipe", kind=TargetKind.DXF)
|
@target(name="pipe", kind=TargetKind.DXF)
|
||||||
def pipe(self) -> Cq.Sketch:
|
def pipe(self) -> Cq.Sketch:
|
||||||
|
"""
|
||||||
|
The rotating pipes. Purely for decoration
|
||||||
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@target(name="side-panel", kind=TargetKind.DXF)
|
@target(name="side-panel", kind=TargetKind.DXF)
|
||||||
|
@ -160,6 +198,7 @@ class Onbashira(Model):
|
||||||
.placeSketch(self.profile_side_panel())
|
.placeSketch(self.profile_side_panel())
|
||||||
.extrude(self.side_thickness)
|
.extrude(self.side_thickness)
|
||||||
)
|
)
|
||||||
|
# Bevel the edges
|
||||||
intersector = (
|
intersector = (
|
||||||
Cq.Workplane('XZ')
|
Cq.Workplane('XZ')
|
||||||
.polyline([
|
.polyline([
|
||||||
|
@ -174,6 +213,71 @@ class Onbashira(Model):
|
||||||
# Intersect the side panel
|
# Intersect the side panel
|
||||||
return result * intersector
|
return result * intersector
|
||||||
|
|
||||||
|
def angle_joint(self) -> Cq.Workplane:
|
||||||
|
"""
|
||||||
|
Angular joint between two side panels. This sits at the intersection of
|
||||||
|
4 side panels to provide compressive, shear, and tensile strength.
|
||||||
|
|
||||||
|
To provide tensile strength along the Z-axis, the panels must be bolted
|
||||||
|
onto the angle joint.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Create the slot carving
|
||||||
|
slot = (
|
||||||
|
Cq.Sketch()
|
||||||
|
.regularPolygon(
|
||||||
|
self.side_width,
|
||||||
|
self.n_side
|
||||||
|
)
|
||||||
|
.regularPolygon(
|
||||||
|
self.side_width_inner,
|
||||||
|
self.n_side, mode="s",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
slot = (
|
||||||
|
Cq.Workplane()
|
||||||
|
.placeSketch(slot)
|
||||||
|
.extrude(self.angle_joint_depth)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Construct the overall shape of the joint, and divide it into sections for printing later.
|
||||||
|
sketch = (
|
||||||
|
Cq.Sketch()
|
||||||
|
.regularPolygon(
|
||||||
|
self.side_width + self.angle_joint_extra_width,
|
||||||
|
self.n_side
|
||||||
|
)
|
||||||
|
.regularPolygon(
|
||||||
|
self.side_width - self.angle_joint_extra_width,
|
||||||
|
self.n_side, mode="s"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
h = (self.bulk_radius + self.angle_joint_extra_width) * 2
|
||||||
|
# Intersector for 1/n of the ring
|
||||||
|
intersector = (
|
||||||
|
Cq.Workplane()
|
||||||
|
.sketch()
|
||||||
|
.polygon([
|
||||||
|
(0, 0),
|
||||||
|
(h, 0),
|
||||||
|
(h, h * math.tan(2 * math.pi / self.n_side))
|
||||||
|
])
|
||||||
|
.finalize()
|
||||||
|
.extrude(self.angle_joint_depth*4)
|
||||||
|
.translate((0, 0, -self.angle_joint_depth*2))
|
||||||
|
)
|
||||||
|
result = (
|
||||||
|
Cq.Workplane()
|
||||||
|
.placeSketch(sketch)
|
||||||
|
.extrude(self.angle_joint_depth)
|
||||||
|
.translate((0, 0, -self.angle_joint_depth/2))
|
||||||
|
.cut(slot.translate((0, 0, self.angle_joint_gap/2)))
|
||||||
|
.cut(slot.translate((0, 0, -self.angle_joint_depth-self.angle_joint_gap/2)))
|
||||||
|
.intersect(intersector)
|
||||||
|
)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def bearing_ball(self) -> Cq.Solid:
|
def bearing_ball(self) -> Cq.Solid:
|
||||||
|
|
Loading…
Reference in New Issue