Add flight controller

Signed-off-by: Arnaud Morin <arnaud.gfpv@mailops.fr>
This commit is contained in:
Arnaud Morin
2026-09-05 14:47:42 +02:00
parent 61025489a4
commit bfb87fbee8
5 changed files with 117 additions and 16 deletions

View File

@@ -16,6 +16,7 @@ from camera_mount import result as CAMERA_MOUNT
import standoff as SO
from standoff import result as STANDOFF
from lollipop import result as LOLLIPOP
from fc import result as FC, PCB_DENSITY
OUT = "build"
@@ -28,10 +29,9 @@ COLORS = {
"spar": cq.Color(0.22, 0.62, 0.35), # green
"camera_mount": cq.Color(0.95, 0.78, 0.09), # yellow TPU
"standoff": cq.Color(0.75, 0.76, 0.78), # aluminium
"lollipop": cq.Color(0.95, 0.78, 0.09), # yellow TPU, as the mount
"lollipop": cq.Color(0.95, 0.78, 0.09), # yellow TPU
"fc": cq.Color(0.42, 0.28, 0.62), # PCB purple
"prop": cq.Color(0.55, 0.55, 0.60), # opaque: a ring hides
# nothing, so there is no
# call for transparency
}
DENSITY = {
@@ -40,6 +40,7 @@ DENSITY = {
"camera_mount": TPU_DENSITY,
"standoff": SO.ALU_DENSITY,
"lollipop": TPU_DENSITY,
"fc": PCB_DENSITY,
}
# --- propellers -------------------------------------------------------------
@@ -77,6 +78,7 @@ PARTS = [
("camera_mount", CAMERA_MOUNT, P.THICKNESS, "solid"),
("standoff", STANDOFF, SO.OD, "solid"),
("lollipop", LOLLIPOP, 3.5, "solid"),
("fc", FC, 11.0, "solid"),
]
@@ -90,9 +92,9 @@ def _loc(x, y, z, rot_z, flip=0.0):
def pieces():
"""[(name, tag, solid, Location)] -- the 19 bodies, straight off the
placement helpers: 2 plates, 4 arms, 8 motor bases, 4 spars, 1 camera
mount."""
"""[(name, tag, solid, Location)] -- the 25 bodies, straight off the
placement helpers: 2 plates, 4 arms, 8 motor bases, 4 spars, 4 standoffs,
1 camera mount, 1 antenna holder, 1 fc stack."""
out = []
for i, (x, y, z, rz) in enumerate(P.plate_placements()):
out.append(("plate", "plate_%s" % ("bottom", "top")[i],
@@ -121,6 +123,14 @@ def pieces():
# height that clears both plates.
out.append(("lollipop", "lollipop_0", LOLLIPOP,
_loc(0.0, -22.0, 7.0, 90.0)))
# fc: the stack stands on the bottom plate's top face, over the 25.5 square
# the plate is drilled for. fc.py puts its own origin at the underside of
# its posts, so that face is the whole placement. The 45 deg is not
# cosmetic: fc.py sets its posts on the diagonals at (+-12.75, +-12.75),
# while the plate drills the same 25.5 square with its holes on the axes at
# 25.5/sqrt(2) = 18.03. Same radius, turned an eighth of a turn, so without
# this the screws miss.
out.append(("fc", "fc_0", FC, _loc(0.0, 0.0, P.THICKNESS, 45.0)))
return out
@@ -175,11 +185,13 @@ def bom(ps):
print(" %-12s %4d %6.1f %9.3f %9.3f"
% (name, qty, thick, each, each * qty))
print(" %-12s %4d %6s %9s %9.3f" % ("FRAME", len(ps), "", "", total))
print(" carbon at %.2f g/cm3, TPU camera_mount at %.2f g/cm3,"
" aluminium standoffs at %.2f g/cm3;"
% (P.CF_DENSITY * 1e3, TPU_DENSITY * 1e3, SO.ALU_DENSITY * 1e3))
print(" the standoffs are the only hardware counted -- no screws, motors"
" or electronics")
print(" carbon at %.2f g/cm3, TPU parts at %.2f g/cm3, aluminium"
" standoffs at %.2f g/cm3," % (P.CF_DENSITY * 1e3, TPU_DENSITY * 1e3,
SO.ALU_DENSITY * 1e3))
print(" fc as a solid block of FR4 at %.2f g/cm3 -- an envelope, not a"
" board" % (PCB_DENSITY * 1e3,))
print(" hardware counted is the standoffs and the fc stack -- no screws,"
" motors, props or receiver")
return total