Compare commits
9 Commits
main
...
touhou/yas
Author | SHA1 | Date |
---|---|---|
|
0a5c14521b | |
|
81245f42f3 | |
|
b34ff7007b | |
|
7ce54f458a | |
|
04532d15f7 | |
|
332db357ad | |
|
de829577aa | |
|
2840315a51 | |
|
c3f9d5a3be |
|
@ -1,37 +0,0 @@
|
|||
import nhf.touhou.yasaka_kanako.mirror as MM
|
||||
import nhf.touhou.yasaka_kanako.onbashira as MO
|
||||
import nhf.touhou.yasaka_kanako.shimenawa as MS
|
||||
from nhf.build import Model, TargetKind, target, assembly, submodel
|
||||
import nhf.utils
|
||||
|
||||
from dataclasses import dataclass, field
|
||||
import cadquery as Cq
|
||||
|
||||
@dataclass
|
||||
class Parameters(Model):
|
||||
|
||||
mirror: MM.Mirror = field(default_factory=lambda: MM.Mirror())
|
||||
onbashira: MO.Onbashira = field(default_factory=lambda: MO.Onbashira())
|
||||
shimenawa: MS.Shimenawa = field(default_factory=lambda: MS.Shimenawa())
|
||||
|
||||
def __post_init__(self):
|
||||
super().__init__(name="yasaka-kanako")
|
||||
|
||||
@submodel(name="mirror")
|
||||
def submodel_mirror(self) -> Model:
|
||||
return self.mirror
|
||||
@submodel(name="onbashira")
|
||||
def submodel_onbashira(self) -> Model:
|
||||
return self.onbashira
|
||||
@submodel(name="shimenawa")
|
||||
def submodel_shimenawa(self) -> Model:
|
||||
return self.shimenawa
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
|
||||
p = Parameters()
|
||||
if len(sys.argv) == 1:
|
||||
p.build_all()
|
||||
sys.exit(0)
|
|
@ -0,0 +1,37 @@
|
|||
from .mirror import Mirror
|
||||
from .onbashira import Onbashira
|
||||
from .shimenawa import Shimenawa
|
||||
from nhf.build import Model, TargetKind, target, assembly, submodel
|
||||
import nhf.utils
|
||||
|
||||
from dataclasses import dataclass, field
|
||||
import cadquery as Cq
|
||||
|
||||
@dataclass
|
||||
class Parameters(Model):
|
||||
|
||||
mirror: Mirror = field(default_factory=Mirror)
|
||||
onbashira: Onbashira = field(default_factory=Onbashira)
|
||||
shimenawa: Shimenawa = field(default_factory=Shimenawa)
|
||||
|
||||
def __post_init__(self):
|
||||
super().__init__(name="yasaka-kanako")
|
||||
|
||||
@submodel(name="mirror")
|
||||
def submodel_mirror(self) -> Model:
|
||||
return self.mirror
|
||||
@submodel(name="onbashira")
|
||||
def submodel_onbashira(self) -> Model:
|
||||
return self.onbashira
|
||||
@submodel(name="shimenawa")
|
||||
def submodel_shimenawa(self) -> Model:
|
||||
return self.shimenawa
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
|
||||
p = Parameters()
|
||||
if len(sys.argv) == 1:
|
||||
p.build_all()
|
||||
sys.exit(0)
|
|
@ -1,9 +1,10 @@
|
|||
from nhf.build import Model, TargetKind, target, assembly, submodel
|
||||
from nhf.materials import Role, Material
|
||||
import nhf.utils
|
||||
from nhf.parts.fasteners import FlatHeadBolt, HexNut, Washer
|
||||
from nhf.parts.electronics import ArduinoUnoR3, BatteryBox18650
|
||||
import nhf.utils
|
||||
|
||||
import unittest
|
||||
from typing import Optional, Union
|
||||
import math
|
||||
from dataclasses import dataclass, field
|
||||
|
@ -274,7 +275,7 @@ class Onbashira(Model):
|
|||
chamber_side_length: float = 400.0
|
||||
chamber_side_width_ex: float = 20.0
|
||||
# Circular hole to hold a switch
|
||||
chamber_front_switch_diam: float = 20.0
|
||||
hatch_switch_diam: float = 20.0
|
||||
|
||||
# Dimensions of gun barrels
|
||||
barrel_diam: float = 25.4 * 1.5
|
||||
|
@ -348,8 +349,15 @@ class Onbashira(Model):
|
|||
motor_coupler_conn_dx: float = 30.0
|
||||
motor_coupler_wall_thickness: float = 5.0
|
||||
motor_coupler_inner_gap: float = 1.0
|
||||
|
||||
turning_bar_tilt: float = 12.0
|
||||
turning_bar_hole_dy: float = 20.0
|
||||
turning_bar_parent_hole_diam_extra: float = 1.0
|
||||
turning_bar_child_hole_diam: float = 4.0
|
||||
turning_bar_width: float = 15.0
|
||||
electronic_mount_dx: float = 50.0
|
||||
turning_bar_height: float = 30.0
|
||||
electronics_panel_width_ratio: float = 0.7
|
||||
electronics_mount_dx: float = 40.0
|
||||
|
||||
material_side: Material = Material.WOOD_BIRCH
|
||||
material_bearing: Material = Material.PLASTIC_PLA
|
||||
|
@ -438,6 +446,14 @@ class Onbashira(Model):
|
|||
"""
|
||||
return self.chamber_side_width / 2 / math.tan(math.radians(self.angle_side / 2))
|
||||
|
||||
def interior_length(self, section_length: float) -> float:
|
||||
"""
|
||||
Given the outside length of a section, calculate the length between the
|
||||
mount holes on the angle joints on the two ends of it.
|
||||
"""
|
||||
z2 = self.angle_joint_gap - self.angle_joint_flange_thickness
|
||||
return section_length + z2
|
||||
|
||||
@target(name="sanding-block")
|
||||
def sanding_block(self) -> Cq.Workplane:
|
||||
# Dihedral angle / 2
|
||||
|
@ -1259,14 +1275,8 @@ class Onbashira(Model):
|
|||
### Electronics ###
|
||||
|
||||
@property
|
||||
def turning_bar_hole_dy(self) -> float:
|
||||
"""
|
||||
Distance between centre of mounting holes in the turning bar and top of
|
||||
the side panels.
|
||||
"""
|
||||
panel_to_mount = self.angle_joint_flange_thickness / 2 - self.angle_joint_gap / 2
|
||||
return panel_to_mount + self.turning_bar_width / 2
|
||||
|
||||
def turning_bar_parent_hole_diam(self) -> float:
|
||||
return BOLT_COMMON.diam_thread + self.turning_bar_parent_hole_diam_extra
|
||||
@target(name="turning-bar")
|
||||
def turning_bar(self) -> Cq.Workplane:
|
||||
"""
|
||||
|
@ -1276,6 +1286,39 @@ class Onbashira(Model):
|
|||
_, dx = self.angle_joint_bind_pos.to2d_pos()
|
||||
t = 8
|
||||
w = self.turning_bar_width
|
||||
h = self.turning_bar_height
|
||||
flange = Cq.Solid.makeBox(
|
||||
length=w,
|
||||
width=t,
|
||||
height=w/2,
|
||||
).moved(-w/2, 0, 0) + Cq.Solid.makeCylinder(
|
||||
radius=w/2,
|
||||
height=t,
|
||||
pnt=(0, 0, 0),
|
||||
dir=(0, 1, 0),
|
||||
) - Cq.Solid.makeCylinder(
|
||||
radius=self.turning_bar_parent_hole_diam/2,
|
||||
height=w*2,
|
||||
pnt=(0, -w, 0),
|
||||
dir=(0, 1, 0),
|
||||
)
|
||||
flange = flange.moved(0, -t, -w/2-h)
|
||||
|
||||
leg = (
|
||||
Cq.Workplane('YZ')
|
||||
.sketch()
|
||||
.polygon([
|
||||
(0, -h),
|
||||
(-t, -h),
|
||||
(-t-self.turning_bar_tilt, 0),
|
||||
(-self.turning_bar_tilt, 0),
|
||||
])
|
||||
.finalize()
|
||||
.extrude(w)
|
||||
.translate((-w/2, 0, 0))
|
||||
.union(flange)
|
||||
.val()
|
||||
)
|
||||
result = (
|
||||
Cq.Workplane()
|
||||
.box(
|
||||
|
@ -1284,50 +1327,47 @@ class Onbashira(Model):
|
|||
height=t,
|
||||
centered=(True, True, False)
|
||||
)
|
||||
.translate((0, -w/2-self.turning_bar_tilt, -t))
|
||||
)
|
||||
flange = Cq.Solid.makeBox(
|
||||
length=w,
|
||||
width=t,
|
||||
height=w/2,
|
||||
).moved(-w/2, -t, -w/2) + Cq.Solid.makeCylinder(
|
||||
radius=w/2,
|
||||
height=t,
|
||||
pnt=(0, -t, -w/2),
|
||||
dir=(0, 1, 0),
|
||||
)
|
||||
remover = Cq.Solid.makeCylinder(
|
||||
radius=BOLT_COMMON.diam_thread/2,
|
||||
holeC = Cq.Solid.makeCylinder(
|
||||
radius=self.turning_bar_child_hole_diam/2,
|
||||
height=w,
|
||||
)
|
||||
removerf = Cq.Solid.makeCylinder(
|
||||
radius=BOLT_COMMON.diam_thread/2,
|
||||
height=w*2,
|
||||
pnt=(0, -w, -w/2),
|
||||
dir=(0, 1, 0),
|
||||
)
|
||||
dxe = self.electronic_mount_dx
|
||||
dxe = self.electronics_mount_dx
|
||||
result = (
|
||||
result
|
||||
+ flange.moved(dx, w/2, 0)
|
||||
+ flange.moved(-dx, w/2, 0)
|
||||
- remover.moved(dxe, 0, 0)
|
||||
- remover.moved(-dxe, 0, 0)
|
||||
- removerf.moved(dx, 0, 0)
|
||||
- removerf.moved(-dx, 0, 0)
|
||||
+ leg.moved(dx, 0, 0)
|
||||
+ leg.moved(-dx, 0, 0)
|
||||
- holeC.moved(dxe, -self.turning_bar_hole_dy, -w)
|
||||
- holeC.moved(-dxe, -self.turning_bar_hole_dy, -w)
|
||||
)
|
||||
result.tagAbsolute("holeBO1", (dx, w/2, -w/2), direction="+Y")
|
||||
result.tagAbsolute("holeBO2", (-dx, w/2, -w/2), direction="+Y")
|
||||
result.tagAbsolute("holeMO1", (dxe, 0, t))
|
||||
result.tagAbsolute("holeMO2", (-dxe, 0, t))
|
||||
result.tagAbsolute("holeBO1", (dx, 0, -w/2-h), direction="+Y")
|
||||
result.tagAbsolute("holeBO2", (-dx, 0, -w/2-h), direction="+Y")
|
||||
result.tagAbsolute("holeMO1", (dxe, -self.turning_bar_hole_dy, 0))
|
||||
result.tagAbsolute("holeMO2", (-dxe, -self.turning_bar_hole_dy, 0))
|
||||
return result
|
||||
|
||||
def profile_electronics_panel(self) -> Cq.Sketch:
|
||||
"""
|
||||
Generic electronics panel
|
||||
"""
|
||||
hole_dx = self.electronics_mount_dx
|
||||
# Distance between the holes
|
||||
y = self.interior_length(self.side_length3) - self.turning_bar_hole_dy * 2
|
||||
l = y + 15
|
||||
w = self.side_width * self.electronics_panel_width_ratio
|
||||
return (
|
||||
Cq.Sketch()
|
||||
.rect(l, w)
|
||||
.rect(y, hole_dx * 2, mode="c", tag="corner")
|
||||
.vertices(tag="corner")
|
||||
.circle(self.turning_bar_child_hole_diam/2, mode="s")
|
||||
.reset()
|
||||
)
|
||||
|
||||
@target(name="electronics-panel1", kind=TargetKind.DXF)
|
||||
def profile_electronics_panel1(self) -> Cq.Sketch:
|
||||
hole_dy = self.turning_bar_hole_dy
|
||||
hole_dx = self.electronic_mount_dx
|
||||
l = self.side_length3 - hole_dy * 2 + 12
|
||||
y = self.side_length3 - hole_dy * 2
|
||||
w = self.side_width
|
||||
# Distance between the holes
|
||||
controller_holes = [
|
||||
self.controller_loc * Cq.Location.from2d(*h).flip_y()
|
||||
for h in self.controller.holes
|
||||
|
@ -1338,12 +1378,7 @@ class Onbashira(Model):
|
|||
for loc in self.battery_box_locs
|
||||
]
|
||||
profile = (
|
||||
Cq.Sketch()
|
||||
.rect(l, w)
|
||||
.rect(y, hole_dx * 2, mode="c", tag="corner")
|
||||
.vertices(tag="corner")
|
||||
.circle(BOLT_COMMON.diam_thread/2, mode="s")
|
||||
.reset()
|
||||
self.profile_electronics_panel()
|
||||
.push([
|
||||
h.to2d_pos() for h in controller_holes
|
||||
] + [
|
||||
|
@ -1354,21 +1389,20 @@ class Onbashira(Model):
|
|||
return profile
|
||||
|
||||
def electronics_panel1(self) -> Cq.Workplane:
|
||||
hole_dy = self.turning_bar_hole_dy
|
||||
hole_dx = self.electronic_mount_dx
|
||||
l = self.side_length3
|
||||
hole_dx = self.electronics_mount_dx
|
||||
y = self.interior_length(self.side_length3) - self.turning_bar_hole_dy * 2
|
||||
l = y + 15
|
||||
t = self.side_thickness
|
||||
result = (
|
||||
Cq.Workplane()
|
||||
.placeSketch(self.profile_electronics_panel1())
|
||||
.extrude(t)
|
||||
)
|
||||
x = l/2 - hole_dy
|
||||
for side, z, d in [("T", t, "+Z"), ("B", 0, "-Z")]:
|
||||
result.tagAbsolute(f"holeLP{side}", (-x, hole_dx, z), direction=d)
|
||||
result.tagAbsolute(f"holeLS{side}", (-x, -hole_dx, z), direction=d)
|
||||
result.tagAbsolute(f"holeRP{side}", (x, -hole_dx, z), direction=d)
|
||||
result.tagAbsolute(f"holeRS{side}", (x, hole_dx, z), direction=d)
|
||||
result.tagAbsolute(f"holeLP{side}", (-y/2, hole_dx, z), direction=d)
|
||||
result.tagAbsolute(f"holeLS{side}", (-y/2, -hole_dx, z), direction=d)
|
||||
result.tagAbsolute(f"holeRP{side}", (y/2, -hole_dx, z), direction=d)
|
||||
result.tagAbsolute(f"holeRS{side}", (y/2, hole_dx, z), direction=d)
|
||||
for (i, h) in enumerate(self.controller.holes):
|
||||
loc = self.controller_loc * Cq.Location.from2d(*h).flip_y()
|
||||
hx, hy = loc.to2d_pos()
|
||||
|
@ -1451,6 +1485,84 @@ class Onbashira(Model):
|
|||
)
|
||||
return a.solve()
|
||||
|
||||
@target(name="electronics-panel2", kind=TargetKind.DXF)
|
||||
def profile_electronics_panel2(self) -> Cq.Sketch:
|
||||
n = 15
|
||||
h_hole = 10
|
||||
y = self.interior_length(self.side_length3) - self.turning_bar_hole_dy * 2
|
||||
w_hole = self.side_width * self.electronics_panel_width_ratio * 0.75
|
||||
profile = (
|
||||
self.profile_electronics_panel()
|
||||
.rarray(y / n, 0, n, 1)
|
||||
.slot(w_hole, h_hole, mode="s", angle=90)
|
||||
)
|
||||
return profile
|
||||
|
||||
def electronics_panel2(self) -> Cq.Workplane:
|
||||
hole_dx = self.electronics_mount_dx
|
||||
y = self.interior_length(self.side_length3) - self.turning_bar_hole_dy * 2
|
||||
l = y + 15
|
||||
t = self.side_thickness
|
||||
result = (
|
||||
Cq.Workplane()
|
||||
.placeSketch(self.profile_electronics_panel2())
|
||||
.extrude(t)
|
||||
)
|
||||
for side, z, d in [("T", t, "+Z"), ("B", 0, "-Z")]:
|
||||
result.tagAbsolute(f"holeLP{side}", (-y/2, hole_dx, z), direction=d)
|
||||
result.tagAbsolute(f"holeLS{side}", (-y/2, -hole_dx, z), direction=d)
|
||||
result.tagAbsolute(f"holeRP{side}", (y/2, -hole_dx, z), direction=d)
|
||||
result.tagAbsolute(f"holeRS{side}", (y/2, hole_dx, z), direction=d)
|
||||
return result
|
||||
|
||||
@assembly()
|
||||
def assembly_electronics2(self) -> Cq.Assembly:
|
||||
name_barL = "barL"
|
||||
name_barR = "barR"
|
||||
name_panel = "panel"
|
||||
a = (
|
||||
Cq.Assembly()
|
||||
.addS(
|
||||
self.turning_bar(),
|
||||
name=name_barL,
|
||||
material=self.material_brace,
|
||||
role=Role.STRUCTURE,
|
||||
)
|
||||
.addS(
|
||||
self.turning_bar(),
|
||||
name=name_barR,
|
||||
material=self.material_brace,
|
||||
role=Role.STRUCTURE,
|
||||
)
|
||||
.addS(
|
||||
self.electronics_panel2(),
|
||||
name=name_panel,
|
||||
material=self.material_auxiliary,
|
||||
role=Role.STRUCTURE,
|
||||
)
|
||||
.constrain(
|
||||
f"{name_panel}?holeLPB",
|
||||
f"{name_barL}?holeMO1",
|
||||
"Plane"
|
||||
)
|
||||
.constrain(
|
||||
f"{name_panel}?holeLSB",
|
||||
f"{name_barL}?holeMO2",
|
||||
"Plane"
|
||||
)
|
||||
.constrain(
|
||||
f"{name_panel}?holeRPB",
|
||||
f"{name_barR}?holeMO1",
|
||||
"Plane"
|
||||
)
|
||||
.constrain(
|
||||
f"{name_panel}?holeRSB",
|
||||
f"{name_barR}?holeMO2",
|
||||
"Plane"
|
||||
)
|
||||
)
|
||||
return a.solve()
|
||||
|
||||
### Side Panels
|
||||
|
||||
@target(name="front-bracket")
|
||||
|
@ -1476,7 +1588,7 @@ class Onbashira(Model):
|
|||
.translate((0, 0, -self.front_bracket_depth/2))
|
||||
)
|
||||
hole_subtractor = Cq.Solid.makeCylinder(
|
||||
radius=BOLT_COMMON.diam_thread/2,
|
||||
radius=(BOLT_COMMON.diam_thread + 2)/2,
|
||||
height=self.bulk_radius,
|
||||
dir=(1, 0, 0)
|
||||
)
|
||||
|
@ -1757,7 +1869,7 @@ class Onbashira(Model):
|
|||
angle=shift,
|
||||
mode="c", tag="bolt")
|
||||
.vertices(tag="bolt")
|
||||
.circle(self.rotor_bind_bolt_diam/2, mode="s")
|
||||
.circle(BOLT_COMMON.diam_thread/2, mode="s")
|
||||
)
|
||||
def chamber_back(self) -> Cq.Workplane:
|
||||
sketch = self.profile_chamber_back()
|
||||
|
@ -1789,10 +1901,11 @@ class Onbashira(Model):
|
|||
)
|
||||
return a
|
||||
|
||||
@target(name="chamber-front", kind=TargetKind.DXF)
|
||||
def profile_chamber_front(self) -> Cq.Sketch:
|
||||
@target(name="hatch", kind=TargetKind.DXF)
|
||||
def profile_hatch(self) -> Cq.Sketch:
|
||||
"""
|
||||
Front chamber must allow access to the electronics section
|
||||
Front chamber must allow access to the electronics section. This is the
|
||||
wall sitting on the 3rd ring which connects to the previous section.
|
||||
"""
|
||||
l = self.side_width
|
||||
h = self.side_width
|
||||
|
@ -1802,18 +1915,18 @@ class Onbashira(Model):
|
|||
.reset()
|
||||
.rect(l, h, mode="s")
|
||||
.push([
|
||||
(l/2 + gap + self.chamber_front_switch_diam/2, 0)
|
||||
(l/2 + gap + self.hatch_switch_diam/2, 0)
|
||||
])
|
||||
.circle(self.chamber_front_switch_diam/2, mode="s")
|
||||
.circle(self.hatch_switch_diam/2, mode="s")
|
||||
.reset()
|
||||
.push([
|
||||
(0, h/2 + gap),
|
||||
(0, -h/2 - gap),
|
||||
(gap, h/2 + gap),
|
||||
(gap, -h/2 - gap),
|
||||
])
|
||||
.rect(l/4, gap, mode="s")
|
||||
)
|
||||
def chamber_front(self) -> Cq.Sketch:
|
||||
sketch = self.profile_chamber_front()
|
||||
def hatch(self) -> Cq.Sketch:
|
||||
sketch = self.profile_hatch()
|
||||
result = (
|
||||
Cq.Workplane()
|
||||
.placeSketch(sketch)
|
||||
|
@ -1848,7 +1961,7 @@ class Onbashira(Model):
|
|||
h = self.angle_joint_flange_thickness
|
||||
# drill hole
|
||||
cyl = Cq.Solid.makeCylinder(
|
||||
radius=self.rotor_bind_bolt_diam/2,
|
||||
radius=BOLT_COMMON.diam_thread/2,
|
||||
height=h,
|
||||
pnt=(ri * math.cos(th), ri * math.sin(th), -h/2),
|
||||
)
|
||||
|
@ -2104,7 +2217,7 @@ class Onbashira(Model):
|
|||
- hole_negative.moved(p1r) \
|
||||
- hole_negative.moved(p2r)
|
||||
# Mark the absolute locations of the mount points
|
||||
dr = self.bulk_radius + self.angle_joint_thickness
|
||||
dr = self.chamber_bulk_radius
|
||||
dr0 = self.bulk_radius
|
||||
for i, (x, y) in enumerate(self.angle_joint_bolt_position):
|
||||
py = dy + y
|
||||
|
@ -2252,7 +2365,6 @@ class Onbashira(Model):
|
|||
result.tagAbsolute(f"holeRSM{i}", locrot * Cq.Location(dr0, -x, -py), direction="-X")
|
||||
|
||||
# Generate the flange geometry
|
||||
flange = self.angle_joint_flange()
|
||||
result = result + self.angle_joint_flange()
|
||||
th = math.pi / self.n_side
|
||||
ri = self.angle_joint_bind_radius
|
||||
|
@ -2340,6 +2452,42 @@ class Onbashira(Model):
|
|||
self.assembly_ring(self.angle_joint()),
|
||||
name="ring1",
|
||||
)
|
||||
name_handle1 = "handle1_1"
|
||||
a = a.addS(
|
||||
self.handle(),
|
||||
name=name_handle1,
|
||||
material=self.material_brace,
|
||||
role=Role.HANDLE,
|
||||
)
|
||||
name_handle2 = "handle1_2"
|
||||
a = a.addS(
|
||||
self.handle(),
|
||||
name=name_handle2,
|
||||
material=self.material_brace,
|
||||
role=Role.HANDLE,
|
||||
)
|
||||
# Handle constrain
|
||||
for ih, (_x, _y) in enumerate(self.angle_joint_bolt_position):
|
||||
a = a.constrain(
|
||||
f"{name_handle1}?holeLPI{ih}",
|
||||
f"ring1/side3?holeLPO{ih}",
|
||||
"Plane",
|
||||
)
|
||||
a = a.constrain(
|
||||
f"{name_handle1}?holeRPI{ih}",
|
||||
f"ring1/side3?holeRPO{ih}",
|
||||
"Plane",
|
||||
)
|
||||
a = a.constrain(
|
||||
f"{name_handle2}?holeLPI{ih}",
|
||||
f"ring1/side5?holeLPO{ih}",
|
||||
"Plane",
|
||||
)
|
||||
a = a.constrain(
|
||||
f"{name_handle2}?holeRPI{ih}",
|
||||
f"ring1/side5?holeRPO{ih}",
|
||||
"Plane",
|
||||
)
|
||||
if has_part(parts, "section2"):
|
||||
a = a.add(
|
||||
self.assembly_section(length=self.side_length2, hasFrontHole=True, hasBackHole=True),
|
||||
|
@ -2351,42 +2499,6 @@ class Onbashira(Model):
|
|||
name="ring2",
|
||||
)
|
||||
|
||||
name_handle1 = "handle2_1"
|
||||
a = a.addS(
|
||||
self.handle(),
|
||||
name=name_handle1,
|
||||
material=self.material_brace,
|
||||
role=Role.HANDLE,
|
||||
)
|
||||
name_handle2 = "handle2_2"
|
||||
a = a.addS(
|
||||
self.handle(),
|
||||
name=name_handle2,
|
||||
material=self.material_brace,
|
||||
role=Role.HANDLE,
|
||||
)
|
||||
# Handle constrain
|
||||
for ih, (x, y) in enumerate(self.angle_joint_bolt_position):
|
||||
a = a.constrain(
|
||||
f"{name_handle1}?holeLPI{ih}",
|
||||
f"ring2/side2?holeLPO{ih}",
|
||||
"Plane",
|
||||
)
|
||||
a = a.constrain(
|
||||
f"{name_handle1}?holeRPI{ih}",
|
||||
f"ring2/side2?holeRPO{ih}",
|
||||
"Plane",
|
||||
)
|
||||
a = a.constrain(
|
||||
f"{name_handle2}?holeLPI{ih}",
|
||||
f"ring2/side4?holeLPO{ih}",
|
||||
"Plane",
|
||||
)
|
||||
a = a.constrain(
|
||||
f"{name_handle2}?holeRPI{ih}",
|
||||
f"ring2/side4?holeRPO{ih}",
|
||||
"Plane",
|
||||
)
|
||||
if has_part(parts, "section3"):
|
||||
a = a.add(
|
||||
self.assembly_section(length=self.side_length3, hasFrontHole=True, hasBackHole=True),
|
||||
|
@ -2397,6 +2509,42 @@ class Onbashira(Model):
|
|||
self.assembly_ring(self.angle_joint_chamber_front()),
|
||||
name="ring3",
|
||||
)
|
||||
name_handle1 = "handle3_1"
|
||||
a = a.addS(
|
||||
self.handle(),
|
||||
name=name_handle1,
|
||||
material=self.material_brace,
|
||||
role=Role.HANDLE,
|
||||
)
|
||||
name_handle2 = "handle3_2"
|
||||
a = a.addS(
|
||||
self.handle(),
|
||||
name=name_handle2,
|
||||
material=self.material_brace,
|
||||
role=Role.HANDLE,
|
||||
)
|
||||
# Handle constrain
|
||||
for ih, (x, y) in enumerate(self.angle_joint_bolt_position):
|
||||
a = a.constrain(
|
||||
f"{name_handle1}?holeLPI{ih}",
|
||||
f"ring3/side1?holeLPO{ih}",
|
||||
"Plane",
|
||||
)
|
||||
a = a.constrain(
|
||||
f"{name_handle1}?holeLSI{ih}",
|
||||
f"ring3/side0?holeLSO{ih}",
|
||||
"Plane",
|
||||
)
|
||||
a = a.constrain(
|
||||
f"{name_handle2}?holeLPI{ih}",
|
||||
f"ring3/side3?holeLPO{ih}",
|
||||
"Plane",
|
||||
)
|
||||
a = a.constrain(
|
||||
f"{name_handle2}?holeLSI{ih}",
|
||||
f"ring3/side2?holeLSO{ih}",
|
||||
"Plane",
|
||||
)
|
||||
if has_part(parts, "chamber"):
|
||||
a = a.add(
|
||||
self.assembly_chamber(),
|
||||
|
@ -2414,13 +2562,39 @@ class Onbashira(Model):
|
|||
material=self.material_side,
|
||||
role=Role.STRUCTURE | Role.DECORATION,
|
||||
)
|
||||
if has_part(parts, "chamber_front"):
|
||||
for i in range(self.n_side):
|
||||
name_bolt = f"chamber_back{i}boltFPI{i}"
|
||||
a = a.addS(
|
||||
BOLT_COMMON.generate(),
|
||||
name=name_bolt,
|
||||
material=self.material_fastener,
|
||||
role=Role.CONNECTION,
|
||||
)
|
||||
a = a.constrain(
|
||||
f"chamber_back?holeF{i}",
|
||||
f"{name_bolt}?root",
|
||||
"Plane",
|
||||
)
|
||||
if has_part(parts, "hatch"):
|
||||
a = a.addS(
|
||||
self.chamber_front(),
|
||||
name="chamber_front",
|
||||
self.hatch(),
|
||||
name="hatch",
|
||||
material=self.material_side,
|
||||
role=Role.STRUCTURE | Role.DECORATION,
|
||||
)
|
||||
for i in range(self.n_side):
|
||||
name_bolt = f"hatch{i}boltFPI{i}"
|
||||
a = a.addS(
|
||||
BOLT_COMMON.generate(),
|
||||
name=name_bolt,
|
||||
material=self.material_fastener,
|
||||
role=Role.CONNECTION,
|
||||
)
|
||||
a = a.constrain(
|
||||
f"hatch?holeF{i}",
|
||||
f"{name_bolt}?root",
|
||||
"Plane",
|
||||
)
|
||||
if has_part(parts, "motor"):
|
||||
a = a.add(self.assembly_motor(), name="motor")
|
||||
if has_part(parts, "machine"):
|
||||
|
@ -2428,6 +2602,8 @@ class Onbashira(Model):
|
|||
if has_part(parts, "electronics1"):
|
||||
a = a.add(self.assembly_electronics1(), name="electronics1")
|
||||
a = a.constrain("electronics1/controller", "Fixed")
|
||||
if has_part(parts, "electronics2"):
|
||||
a = a.add(self.assembly_electronics2(), name="electronics2")
|
||||
if has_part(parts, ["electronics1", "ring3"]):
|
||||
a = a.constrain(
|
||||
f"electronics1/barL?holeBO2",
|
||||
|
@ -2439,8 +2615,18 @@ class Onbashira(Model):
|
|||
f"ring3/side2?holeStatorL",
|
||||
"Plane",
|
||||
)
|
||||
if has_part(parts, ["electronics2", "ring3"]):
|
||||
a = a.constrain(
|
||||
f"electronics2/barL?holeBO2",
|
||||
f"ring3/side3?holeStatorL",
|
||||
"Plane",
|
||||
)
|
||||
a = a.constrain(
|
||||
f"electronics2/barL?holeBO1",
|
||||
f"ring3/side4?holeStatorL",
|
||||
"Plane",
|
||||
)
|
||||
|
||||
# FIXME: Filter
|
||||
if has_part(parts, ["motor", "ring2"]):
|
||||
for i in range(self.n_side // 2):
|
||||
j = self.n_side // 2 - 1 - i
|
||||
|
@ -2454,27 +2640,34 @@ class Onbashira(Model):
|
|||
# f"ring2/side{i*2+1}?holeStatorL",
|
||||
# "Plane",
|
||||
#)
|
||||
|
||||
if parts:
|
||||
return a.solve()
|
||||
|
||||
for i in range(self.n_side):
|
||||
j = (i + 1) % self.n_side
|
||||
ir = (self.n_side - i) % self.n_side
|
||||
|
||||
coupler_name = f"stator_coupler{i}"
|
||||
a = a.addS(
|
||||
self.stator_coupler(),
|
||||
name=coupler_name,
|
||||
material=self.material_brace,
|
||||
role=Role.STRUCTURE,
|
||||
)
|
||||
a = a.constrain(
|
||||
f"{coupler_name}?holeOB",
|
||||
f"ring1/side{i}?holeStatorR",
|
||||
"Plane",
|
||||
)
|
||||
a = a.constrain(
|
||||
f"{coupler_name}?holeIF",
|
||||
f"machine/stator1?holeF{ir}",
|
||||
"Plane",
|
||||
)
|
||||
if has_part(parts, "ring1") or has_part(parts, "machine"):
|
||||
coupler_name = f"stator_coupler{i}"
|
||||
a = a.addS(
|
||||
self.stator_coupler(),
|
||||
name=coupler_name,
|
||||
material=self.material_brace,
|
||||
role=Role.STRUCTURE,
|
||||
)
|
||||
if has_part(parts, "ring1"):
|
||||
a = a.constrain(
|
||||
f"{coupler_name}?holeOB",
|
||||
f"ring1/side{i}?holeStatorR",
|
||||
"Plane",
|
||||
)
|
||||
if has_part(parts, "machine"):
|
||||
a = a.constrain(
|
||||
f"{coupler_name}?holeIF",
|
||||
f"machine/stator1?holeF{ir}",
|
||||
"Plane",
|
||||
)
|
||||
|
||||
#name_bolt =f"stator_outer_bolt{i}"
|
||||
#a = a.addS(
|
||||
|
@ -2489,31 +2682,7 @@ class Onbashira(Model):
|
|||
# "Plane",
|
||||
#)
|
||||
|
||||
name_bolt =f"chamber_back{i}boltFPI{i}"
|
||||
a = a.addS(
|
||||
BOLT_COMMON.generate(),
|
||||
name=name_bolt,
|
||||
material=self.material_fastener,
|
||||
role=Role.CONNECTION,
|
||||
)
|
||||
a = a.constrain(
|
||||
f"chamber_back?holeF{i}",
|
||||
f"{name_bolt}?root",
|
||||
"Plane",
|
||||
)
|
||||
|
||||
name_bolt =f"chamber_front{i}boltFPI{i}"
|
||||
a = a.addS(
|
||||
BOLT_COMMON.generate(),
|
||||
name=name_bolt,
|
||||
material=self.material_fastener,
|
||||
role=Role.CONNECTION,
|
||||
)
|
||||
a = a.constrain(
|
||||
f"chamber_front?holeF{i}",
|
||||
f"{name_bolt}?root",
|
||||
"Plane",
|
||||
)
|
||||
for ih in range(len(self.angle_joint_bolt_position)):
|
||||
a = a.constrain(
|
||||
f"chamber/side{i}?holeFPI{ih}",
|
||||
|
@ -2532,7 +2701,7 @@ class Onbashira(Model):
|
|||
)
|
||||
a = a.constrain(
|
||||
f"ring3/side{i}?holeStatorR",
|
||||
f"chamber_front?holeB{i}",
|
||||
f"hatch?holeB{i}",
|
||||
"Plane",
|
||||
)
|
||||
|
||||
|
@ -2559,5 +2728,18 @@ class Onbashira(Model):
|
|||
f"{nc}/side{i}?holeRSM{ih}",
|
||||
"Plane",
|
||||
)
|
||||
|
||||
|
||||
return a.solve()
|
||||
|
||||
|
||||
class TestOnbashira(unittest.TestCase):
|
||||
|
||||
def test_collision(self):
|
||||
from nhf.checks import pairwise_intersection
|
||||
|
||||
o = Onbashira()
|
||||
a = o.assembly()
|
||||
self.assertEqual(pairwise_intersection(a), [])
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
|
Loading…
Reference in New Issue