Airloom — glossary

Terms of the evolutionary algorithm, of the quadcopter-frame domain it optimizes, and of the result pages themselves. Companion to the gallery, the family tree page and the README.

the evolutionary algorithm

Genome / gene
The complete parametric description of one frame: 12 numbers that morph the official Source One V6 plate drawings — arm stretch/width/waist/thickness, front and rear sweep about the drawing's bolt anchors, plate scales, deck gap, battery wedge, material. Scale genes at ×1.00 reproduce the real V6 exactly. The genome is all the optimizer may change — battery, motors, propellers and electronics are fixed kit.
Candidate / individual
One genome, built into a frame and evaluated. Identified everywhere by its genome hash.
Genome hash
A stable 12-hex-digit ID derived (SHA-1) from the gene values rounded to 10−6. Identical genomes always get identical IDs, which is what makes caching, resuming and lineage queries trivial.
Population
The set of candidates alive in one generation (default 16).
Generation
One full cycle: propose a population → evaluate every candidate in all scenarios → select who breeds. Generation 0 is seeded: the real Source One V6 7-inch DC itself (every scale gene at ×1.00, measured from the official drawing) plus random design-space probes.
Fitness
The single scalar being minimized. Here: mean Wh/km across scenarios + λ · worst-scenario Wh/km with λ = 0.5. The mean rewards general efficiency; the worst-case term punishes designs that are great in five scenarios and terrible in one. aggregation: minimax switches to pure worst-case. Lower is better; invalid candidates get fitness = ∞.
Selection (tournament)
To pick a parent, draw k = 3 random candidates from the previous generation and keep the fittest. Repeats per parent. Gentle, noise-tolerant selection pressure.
Crossover (SBX)
Simulated Binary Crossover: a child gene is sampled around its two parents’ values with a spread controlled by the distribution index η (higher η = children closer to the parents). The digital analogue of breeding two good frames.
Mutation
Gaussian noise added to a subset of genes. Its standard deviation (sigma, a fraction of each gene’s range) is adaptive: it decays per generation, so early search is exploratory and late search fine-tunes. The recorded mutation magnitude is the RMS of the normalized perturbation.
Operator
How a candidate came to exist: seed, crossover, mutation, immigrant, elite, pivot, designer (or cmaes). Stored per candidate and shown as edge colors in the family tree.
Elitism / elite carry-over
The top 2 candidates pass into the next generation unchanged, so the best design can never be lost. Drawn as dotted vertical pass-through edges in lineage.svg.
Random immigrant
An occasional entirely random genome injected into the population (10 % per non-elite slot) to keep genetic diversity from collapsing.
Lineage / parentage
Every candidate records parent_a, parent_b, its operator, its birth generation and mutation magnitude — a self-referencing SQLite table, so airloom lineage <hash> walks the full ancestor chain (WITH RECURSIVE) and shows how fitness improved along it.
Designer round
Every 6 generations a headless Claude receives the elites, their per-scenario numbers and the invalid-design histogram, and proposes new genome vectors as reasoned design hypotheses (operator designer, violet edges in the family tree; rationales in results/designer_log.md). Complements the GA's local operators with non-local, physics-informed jumps.
Lab notebook (narrator)
After each generation, one headless-Claude call writes three short notes per new candidate — hypothesis (the pre-flight “why”: what the search had observed and what bet this design makes), method (what concretely changed vs. the parents), result (outcome vs. parents and best-so-far, or the constraint that killed it, plus an idea worth testing next). Rule-based fallback notes are written instantly; the enrichment runs off the loop's critical path. Shown in the gallery detail blocks and the family-tree hover cards.
Patience / pivot
Plateau escape. If the best-so-far fails to improve by ≥0.5 % for 6 generations (the longest gap healthy searches showed was 4), the next generation pivots: half the non-elite offspring are bred by crossing a tournament winner with a far parent — the most genetically distant still-decent candidate from the whole run — with mutation temporarily boosted. Plateaus that survive another window escalate to fully random far-parents. Pivot generations are marked ⟳ on the progress chart and pivot edges are teal in the family tree.
Early-reject
Optional cost control: fly the cheap calm_warm scenario first; a candidate much worse than the population median skips the other five scenarios and receives a finite penalized fitness — evolution still gets gradient information without paying full price.
Convergence
Fitness vs. generation (convergence.png): population median and best-so-far falling and flattening as the search settles.
CMA-ES
Covariance Matrix Adaptation Evolution Strategy, the flag-gated alternative optimizer (--optimizer cmaes). It samples each generation from one adapted multivariate Gaussian, so candidates have no discrete parents; distribution-level provenance (mean and step size σ per generation) is stored instead, and the family tree is skipped.
Determinism / resume
Per-generation RNG seeds and fixed per-scenario turbulence seeds make evaluations reproducible; after a crash or a graceful stop, airloom run resumes the latest run by default (--fresh forces a new one), continuing from the last completed generation and re-using every already-evaluated genome via its hash.

the domain

the shape (what the genes mean)

Arm length / width / waist scale
Stretch and reshape the REAL Source One V6 arm outlines: the shaft between the bolt tongue and the motor mount stretches (wheelbase, disk clearance), its width scales, and the waist gene adds extra mid-shaft narrowing (drag vs. stiffness). The tongue and the 16 × 19 mm motor pattern never deform.
Arm thickness
Plate thickness of the arms (real V6: 6 mm carbon).
Front / rear sweep
Rotate each arm pair about its plate anchor. The front anchors are exact bolt-pattern registrations from the official drawing (stock: 31.4°); left and right arms keep their true mirrored chirality.
Plate length / width / thickness scale
Stretch the real main / mid / top deck plates with their cutouts and holes; the 30.5 mm stack pattern stays pinned exactly.
Deck gap
Standoff length between mid and top plate (real: M3×30). Must fit the FC/ESC stack; also sets the vertical margin between the rear props and the top-plate corners.
Battery wedge (battery_wedge_deg)
Nose-down tilt of the cell pack on the top plate, trimming the biggest bluff body in forward flight.
Material (gene)
Selects the frame material — plates and arms — from the platform library: CNC-cut carbon plate, carbon-fiber nylon (PA12-CF), PET-CF, PLA+, PETG or ASA. Each brings its own density, tensile strength and stiffness, so the optimizer trades mass against the structural constraints. Printed values are XY-direction datasheet numbers; layer-line weakness is only covered by the global 1.5 safety factor.

the target metric

Wh/km (watt-hours per kilometer)
Electrical energy drawn from the battery per kilometer flown — the quantity being minimized. Computed per scenario over the fixed 4 km mission, then aggregated (see Fitness). Typical values here for the 7-inch class: ≈ 3.5 Wh/km calm, ≈ 5–6 Wh/km in storm conditions.
Target & record lines
The two horizontal benchmarks on the gallery progress chart: ≈ 5.0 Wh/km aggregate — what current 7-inch long-range practice (~8 g/W at cruise) works out to on this scenario portfolio — and ≈ 4.0 as a record-class stretch (ultralight record builds at ~2 Wh/km calm cruise). Both set in config/scenarios.yaml.
Mission
Identical in every scenario: 2 km north, then 2 km south, at 12 m/s commanded ground speed, 30 m altitude. Flying both directions keeps headwind/tailwind honest.
Scenario portfolio
Six weather cases every candidate must fly: calm_warm (baseline), cold_headwind, storm (wind + severe gusts + 25 mm/h rain), crosswind, gusty_light (severe gusts, light mean wind), hot_thin (1500 m density altitude). Evaluating the portfolio prevents overfitting the frame to one weather condition.
All-up mass (AUW)
Frame mass (the only variable part, from the genome) plus the fixed 0.78 kg of battery (470 g self-built 6S1P 21700 Li-Ion), four 2806-class motors with props, FC stack, camera, VTX and receiver. The baseline deck comes out around 1.0 kg AUW and hovers at ≈ 150 W on the measured Master Airscrew GF 7×4 data.

constraints (fitness = ∞ when violated)

Deck gap vs. FC/ESC stack
The standoff gap between the plates must fit the FC/ESC stack (the 30.5 mm hole pattern itself stays pinned exactly in every morph).
Arm tongue interlock
The placed arm outlines must not overlap on the main plate — the real V6's notch interlock is not redesigned, so colliding tongues invalidate the design. Tends to bite when both sweeps sit near their minimums with wide arms.
Tongue bolts on plate
Each arm tongue's bolt pair must land on main-plate material. Sweeps far from stock need the plate scales to grow with them, or the bolts walk off the plate.
Plate web width
Every morphed deck plate must keep ≥ 80 % of the stock part’s narrowest material web between its holes, cutouts and outer edge. The FC-stack holes stay pinned while the plates scale, so shrinking plates would otherwise slide cutouts into the holes and collapse the webs to unprintable slivers.
Plate thickness (printed)
Printed materials require ≥ 1.6 mm deck plates (CNC carbon: ≥ 1.2 mm) — per-material floors set in config/platform.yaml.
Rotor clearance
Rotor disks need ≥ 5 mm from each other, and the prop disks are checked against the deck/battery in 3D (the real V6's rear props sweep below the top-plate corners; the deck gap trades that margin). Violations are still meshed and archived (_INVALID STLs) — the failures are instructive — but never simulated.
Rotor saturation
If holding the commanded speed would require rotor speeds above the motor ceiling (or per-motor power beyond its limit) for more than half a second cumulative, the candidate fails that scenario.
Arm stress / deflection
Euler–Bernoulli cantilever check under the worst per-rotor thrust seen in any scenario, times a 1.5 safety factor: root bending stress ≤ the genome-selected material's tensile strength, and tip deflection ≤ 5 % of arm length.
Resonance (1P)
The arm’s first bending natural frequency must sit outside ±15 % of the rotor’s hover rotation frequency (the “1P” excitation), or vibration would shake the frame apart.

the physics vocabulary

Advance ratio J, CT, CP
Propeller performance is tabulated as thrust and power coefficients versus advance ratio J = V/(nD): thrust T = ρn²D⁴CT, shaft power P = ρn³D⁵CP. Ground truth here: the UIUC Propeller Database measurements of the Master Airscrew GF 7×4 prop (2-blade; the kit's 3-blade 7×4 is absorbed into the same tables).
Motor + ESC efficiency
Fixed 85 % conversion from electrical to shaft power (ESC = electronic speed controller). Wh/km is measured on the electrical side.
CdA / drag table
Drag area (drag coefficient × projected area, m²). Computed per candidate by rasterizing the frame’s STL along the flow at tilt angles 0–60°, per component class (arms vs body), each with its own Cd. Drag = ½ ρV² CdA.
Rotor wash / download
The induced downwash of each rotor presses on the arm planform underneath its disk — an interference penalty that makes wide arms under rotors expensive.
Tilt
A quadcopter can only push along its rotor axes, so it leans into the relative wind to fly forward or fight gusts; tilt sets both the thrust demand and which silhouette the frame shows the airflow.
Dryden turbulence (MIL-F-8785C)
The standard military gust model: time-correlated random wind with prescribed intensity σ and length scales (light / moderate / severe map to 15 / 30 / 45 kt wind at 20 ft). Each scenario uses a fixed seed, so every candidate flies the identical gust history — fitness differences are frame differences, never gust luck.
Density altitude / air density ρ
Hot or high air is thin (lower ρ): rotors must spin faster for the same thrust, and drag falls. hot_thin flies at the density found 1500 m up a standard atmosphere.
Rain model
Empirical, per NASA heavy-rain research (NASA TP-2671): a water film adds mass on upward-facing area, suspended rain adds momentum drag, and rotor thrust coefficient is derated 15 %.
Component drag buildup
Phase-A method: total drag ≈ sum of per-component projected areas × handbook drag coefficients. Fast and honest about being approximate; Phase B would replace it with OpenFOAM CFD on the top candidates.

reading the results

Progress chart
Top of the gallery: every candidate in evaluation order. Gray dots are evaluated designs, drawn at their aggregate Wh/km (lower is better); hollow dots are valid but so poor they are clipped at the 95th-percentile cap and pinned to the top edge. The black step line tracks the best-so-far; its black dots are the improvements and click through to the detail cards. Red ×’s on the ∞ row above the scale are invalid designs (fitness = ∞, see constraints) that never flew. Teal ⟳ axis ticks mark pivot generations; the dashed horizontal rules are the target & record lines. Every legend entry explains itself on hover.
Improvement setter / run champion
A candidate that lowered the best-so-far score when it was evaluated (the black dots of the step line). Setters render inverted — ink background, bright text — in both the generation grids and the detail list; the run champion, the best design of the entire run, additionally carries a rust outline and chip.
Detail card
One per candidate, below the grids: the metric table (energy score = fitness, scenario mean and worst, frame mass, material, birth), the lab notebook’s hypothesis / method / result notes (see Lab notebook), and the scenario results & genome tables — per-scenario Wh/km, average power and max tilt, plus every gene value. The side column shows the parents’ renders.
3D overlay
Click any render to open the interactive viewer; it starts zoomed to fit the whole frame at a tilted-down view (drag to rotate, ⌘-drag to pan, scroll to zoom, double-click resets, esc closes; corner buttons snap to fit / front / top / bottom / left / right / default views). Four tabs: full-kit model, the complete candidate; evolved components, just the deck + arms that evolution changes; compare with oldest ancestor, the candidate’s evolved parts next to its lineage root’s, both rotating and zooming in sync; and evolution difference, superimposing the evolved parts — solid color = this candidate, gray ghost = oldest ancestor, fixed kit hidden — starting near top-down, where plan-shape changes read best.
Family tree
lineage.html: one row per generation, candidates ordered best→worst, edge colors naming the operator (see Operator, Elitism, Lineage). Hover any node for the candidate’s card and its full ancestry; click to pin the highlight while scrolling.

See the README for physics assumptions, sources, and known limitations in full.