Katalog erweitern
Eine Marke ist eine YAML-Datei. Neue Hersteller, neue Flügel und neue Masten brauchen keine Code-Änderung — nur Katalogdaten. Diese Datei erklärt, wie das geht und wie sich das Modell mit realen Sessiondaten nachschärfen lässt.
- Katalogverzeichnis:
backend/pumpfoil/catalog/ - Vorlage:
backend/pumpfoil/catalog/_template.yaml - Schema und Loader:
backend/pumpfoil/catalog/_schema.py
Dateien mit führendem Unterstrich ignoriert der Loader. Alles andere mit der Endung .yaml wird beim Start eingelesen und validiert.
Neuen Hersteller anlegen
cd backend/pumpfoil/catalog
cp _template.yaml armstrong.yamlDanach brand, display_name und source setzen. brand ist der Schlüssel in der API und muss eindeutig und kleingeschrieben sein.
brand: armstrong
display_name: Armstrong Foils
source: armstrongfoils.comPrüfen, dass die Datei geladen wird:
cd backend
.venv/bin/python -c "from pumpfoil.catalog import load_catalogs; print(sorted(load_catalogs()))"Der Loader cacht das Ergebnis (lru_cache). Nach Katalogänderungen den uvicorn-Prozess neu starten oder mit --reload laufen lassen.
Welche Felder wirklich nötig sind
Pflicht sind nur id, name, span_mm und area_cm2. Alles Weitere leitet das Schema ab:
mean_chord_mm = area_cm2 · 100 / span_mm
aspect_ratio = (span_mm / 10)² / area_cm2
thickness_ratio = volume_cm3 / (0,685 · area_cm2 · mean_chord_cm)
camber_ratio aus camber_classJe mehr echte Herstellerangaben eingetragen sind, desto weniger wird geraten. Nach Wirkung sortiert:
| Feld | Wirkung, wenn es fehlt |
|---|---|
volume_cm3 | t/c fällt auf 0,11 zurück, Reibungswiderstand wird ungenau |
mean_chord_mm | wird aus Fläche und Spannweite gerechnet, bei stark elliptischen Grundrissen zu grob |
mass_g | fehlt in der Gesamtmasse, verfälscht Take-off und Pumpleistung |
camber_class | Standard medium_camber (3 %), verschiebt den Nullauftriebswinkel |
cl_max | Standard 1,35, verschiebt Take-off-Speed und Stall-Grenze |
Wenn ein Wert geschätzt ist, gehört das ins Feld notes. Der Axis-Katalog macht das konsequent so, damit später erkennbar bleibt, welche Zahl belastbar ist.
Frontwing eintragen
front_wings:
- id: hs-1250
name: HS 1250
family: HS
span_mm: 1250
area_cm2: 1584
volume_cm3: 1810
max_chord_mm: 170
mean_chord_mm: 126.7 # weglassen, wenn nicht veröffentlicht
mass_g: 1450
camber_class: high_camber # high | medium | low | symmetric
cl_max: 1.38
oswald_e: 0.93
mount: proprietary
notes: Masse geschätzt.Zu den beiden Werten, die eine Einschätzung verlangen:
camber_class bestimmt den Nullauftriebswinkel und damit, wie viel Anstellwinkel ein Flügel für sein Gewicht braucht.
| Klasse | Wölbung | typisch für |
|---|---|---|
high_camber | 4,5 % | Pump-, Dockstart-, Downwind-Flügel mit viel Low-End |
medium_camber | 3,0 % | Allround-Wingfoils |
low_camber | 1,8 % | Speed- und Race-Flügel |
symmetric | 0 % | Rearwings, Masten |
oswald_e beschreibt, wie nah die Auftriebsverteilung an der elliptischen liegt. 0,94 für sehr schlanke Hochleistungsflügel, 0,90 bis 0,92 für die Allroundklasse, darunter für stark gepfeilte oder rechteckige Grundrisse.
Beide Werte kann man aus einem einzelnen Sessionvergleich nicht sauber zurückrechnen. Im Zweifel bei den Standardwerten bleiben — der Vergleich zwischen Setups bleibt aussagekräftig, solange man dieselben Annahmen für alle Flügel benutzt.
Rearwing, Fuselage, Mast, Board
rear_wings:
- id: stab-330
name: Stab 330
span_mm: 330
area_cm2: 145
volume_cm3: 42
chord_mm: 44
mass_g: 200
camber_class: low_camberfuselages:
- id: fuse-685
name: Fuselage 685
length_mm: 685
geometry: standard # standard | advance_20 | advance_plus | fatty
diameter_mm: 26
mass_g: 545geometry verschiebt die Mastachse relativ zum Frontwing-Neutralpunkt: standard 0 mm, advance_20 20 mm nach vorn, advance_plus und fatty 60 mm. Das ändert nicht den Auftrieb, aber die Fußposition und damit, ob ein Setup überhaupt ausbalancierbar ist (trimmable). Für andere Hersteller ist standard die richtige Wahl, solange keine Angabe zur Mastposition vorliegt.
Der Hebelarm zwischen den Neutralpunkten ergibt sich als 92 % der Fuselage-Länge; die Enden tragen Verschraubung und Überstand, nicht Hebelarm.
masts:
- id: mast-850
name: Performance Mast 850
length_mm: 850
chord_mm: 122
thickness_mm: 14.0
mass_g: 1650Mastdicke und Chord bestimmen zusammen das Profil-t/c und damit rund 10 bis 15 % des Gesamtwiderstands. Wenn ein Hersteller nur die Dicke angibt, ist eine Chord von 115 bis 130 mm eine brauchbare Annahme für einen modernen Highaspect-Mast.
boards:
- id: pump-45
name: Pump Board 4'8" 45L
volume_l: 45
length_cm: 142.0
width_cm: 46.0 # optional, geht in keine Rechnung ein
mass_kg: 4.1
discipline: pump # pump | wing | downwind | allround
# UI-Auswahl: nur discipline=pump;
# wing/allround/downwind bleiben im Katalog.
track_center_from_nose_cm: 65.0 # optional, sonst Heuristik
track_travel_cm: 28.0
front_strap_from_nose_cm: 102.0
rear_strap_from_nose_cm: 60.0Optional für Pump-Boards: track_center_from_nose_cm, track_travel_cm, front_strap_from_nose_cm, rear_strap_from_nose_cm. Fehlen die Angaben, leitet das Schema Track-Mitte (~46 % der Länge), Travel (~28–30 cm) und Straps aus der Referenz-Stance ab.
Im Flug geht das Board nur über die Masse ein. Volumen und Länge dienen der Darstellung und späteren Take-off-Modellierung, die Breite ist rein informativ und darf fehlen.
Preise & Bezug
Optional auf Marken- und Teilebene. Fehlen die Felder, bleibt die Physik unverändert — die Oberfläche zeigt dann „keine Preise“ bzw. nur den Bezugsweg.
commerce:
channel: direct # direct | partner | mixed
currency: EUR
shop_url: https://example.com/shop
dealer_url: https://example.com/dealers # partner / mixed
price_checked: "2026-09-08"
notes: Shoppreise Stand Herstellerseite.channel | Bedeutung |
|---|---|
direct | Kauf über Hersteller-Shop; Live-Refresh möglich |
partner | Nur über Händler; kein Refresh-Button |
mixed | Beides; Refresh nur für Teile mit product_url |
Pro Teil (Frontwing, Rearwing, Fuselage, Mast, Board):
price: 1299
currency: EUR # optional, sonst Marken-currency
product_url: https://example.com/shop/... # nötig für Live-Refresh
price_checked: "2026-09-08"Baseline: Preise im YAML committen (Quartals-Review / Saison).
Live: Button „Preise für diesen Hersteller aktualisieren“ holt Shop-Preise nur für hinterlegte product_urls und speichert sie als Session-Overlay im Browser — die YAML-Datei auf dem Server wird nicht überschrieben.
Komponenten über Markengrenzen mischen
Flügel, Fuselage und Mast sind herstellerspezifisch verschraubt und kommen deshalb aus der Leitmarke des Setups. Das Board sitzt über die Tracks auf jedem Mast und ist das einzige Teil, das frei kombinierbar bleibt. Dafür gibt es die qualifizierte Referenz marke:id:
build_setup(brand="axis", board_id="gong:strada-hdcc-79")Ohne Doppelpunkt gilt die Leitmarke. Die Auflösung steckt in split_reference und greift für alle Komponentenarten, auch wenn sie praktisch nur beim Board gebraucht wird.
Eine Marke darf deshalb auch nur Boards führen, so wie gong.yaml. Ihr Flag rig_capable steht dann auf false: die Oberfläche bietet sie nicht als Hersteller an, ihre Boards erscheinen aber im Board-Dropdown unter eigenem Gruppentitel. /catalog liefert dafür neben brands eine flache Liste boards, in der jeder Eintrag seine ref mitbringt.
Änderungen prüfen
cd backend
.venv/bin/python -m pytest # Schema und Physik
.venv/bin/python - <<'PY'
from pumpfoil.geometry import build_setup
from pumpfoil.steady import steady_report
setup = build_setup(brand="armstrong", front_wing_id="hs-1250",
rear_wing_id="stab-330", fuselage_id="fuse-685",
mast_id="mast-850", board_id="pump-45")
report = steady_report(setup)
print("t/c ", round(setup.front_wing.thickness_ratio, 4))
print("AR ", round(setup.front_wing.aspect_ratio, 2))
print("Take-off ", round(report.takeoff_speed * 3.6, 1), "km/h")
print("Beste L/D ", round(report.best_glide.lift_to_drag, 1),
"bei", round(report.best_glide.speed * 3.6, 1), "km/h")
PYPlausibilitätsanker für einen Pumpflügel um 1400 cm² mit 85 kg Fahrer:
| Größe | erwarteter Bereich | Alarmzeichen |
|---|---|---|
| t/c | 0,10 bis 0,15 | unter 0,08 oder über 0,18 → Volumen prüfen |
| Take-off | 9 bis 14 km/h | unter 8 → Fläche oder cl_max zu optimistisch |
| Beste Gleitzahl | 13 bis 20 | über 25 → Kalibrierung zu günstig |
Fällt ein Wert heraus, liegt der Fehler fast immer im Katalog und nicht im Modell: vertauschte Einheiten bei area_cm2 oder ein Volumen in Litern statt cm³.
Kalibrierung mit realen Sessiondaten
Jede Marke hat einen eigenen calibration-Block. Er ist die einzige Stelle, an der Modellergebnisse an die Realität angepasst werden:
calibration:
cd_viscous_scale: 0.78 # Reibungsniveau, wichtigster Regler
cd_interference: 0.06 # Zuschlag für Verbindungsstellen
lift_slope_scale: 0.92 # Grenzschichtabschlag am Auftriebsanstieg
notes: >
Woher die Werte stammen — Datum, Setup, Messgröße.Was sich womit korrigieren lässt
| Beobachtung | Regler | Richtung |
|---|---|---|
| Modell sagt zu hohe Gleitzahl / zu wenig Leistung | cd_viscous_scale | erhöhen (0,78 → 0,90) |
| Modell sagt zu viel Widerstand | cd_viscous_scale | senken (0,78 → 0,70) |
| Take-off passt, Höchstgeschwindigkeit zu hoch | cd_interference | erhöhen (0,06 → 0,10) |
| Take-off zu früh, Rest passt | lift_slope_scale | senken (0,92 → 0,88) |
Nur einen Faktor auf einmal ändern. cd_viscous_scale wirkt auf alle Bauteile gleichzeitig und ist der einzige Regler, der auch bei einer einzelnen Messgröße eindeutig bestimmbar ist.
Welche Sessiondaten brauchbar sind
Nach Aussagekraft sortiert:
- Take-off-Geschwindigkeit aus einem GPS-Log mit 5 bis 10 Hz. Die Geschwindigkeit im Moment des Abhebens, gemittelt über mehrere Starts. Am besten reproduzierbar am Dock, weil die Anfahrt gleichmäßig ist.
- Gleitgeschwindigkeit im Glide — die Geschwindigkeit, bei der ein Setup ohne Pumpen am weitesten trägt. Da der Auftrieb im getrimmten Flug immer gleich dem Gewicht ist, fällt der kleinste Widerstand mit der besten Gleitzahl zusammen; die Kennzahl
best_glideist also der richtige Vergleichswert. - Ausrollversuch: nach einem Downwind-Run aufhören zu pumpen und die Geschwindigkeit über der Zeit aufzeichnen. Die Verzögerung
dU/dtmal Gesamtmasse ergibt direkt den Widerstand bei dieser Geschwindigkeit. Das ist die einzige Methode, die den Absolutwert misst statt nur einen Betriebspunkt. - Herzfrequenz oder gefühlte Anstrengung: nur für relative Vergleiche zwischen zwei Setups derselben Session brauchbar, nicht für Absolutwerte.
Wichtig: immer Wassertemperatur, Salzgehalt und Fahrergewicht mit Ausrüstung notieren. Ohne diese drei Angaben lässt sich eine Session nicht nachrechnen.
Ablauf
- Session fahren, dabei ein Setup und die Bedingungen exakt festhalten.
- Dasselbe Setup in der Oberfläche einstellen, Wassertemperatur und Salzgehalt auf die Session setzen.
- Modellwert und Messwert vergleichen. Für den Ausrollversuch: die Simulation liefert bei jeder Geschwindigkeit
drag_nin Panel E. cd_viscous_scaleso anpassen, dass der Widerstand passt. Der Zusammenhang ist nahezu linear im Reibungsanteil, aber nicht im Gesamtwiderstand — bei niedriger Fahrt dominiert der induzierte Anteil, der vom Faktor unberührt bleibt. Deshalb möglichst bei hoher Fahrt kalibrieren, dort ist der Reibungsanteil groß und der Hebel eindeutig.- Ergebnis in
notesdokumentieren, inklusive Datum und Setup. pytestlaufen lassen. Wenn Plausibilitätstests jetzt fehlschlagen, ist die Kalibrierung entweder zu aggressiv oder ein Testgrenzwert war zu eng.
Kalibrierung gegensteuern statt überanpassen
Ein einzelner Messpunkt rechtfertigt keine Änderung um mehr als etwa 15 %. Der Standardwert cd_viscous_scale = 0,78 bildet ab, dass moderne Foilprofile bei Re um 5·10⁵ rund ein Viertel der Lauflänge laminar halten und damit unter der voll turbulenten ITTC-57-Plattenreibung liegen. Wer daraus 0,50 macht, um eine Session zu treffen, hat wahrscheinlich einen Katalogfehler kaschiert.
Und der wichtigste Punkt: Setup-Vergleiche im selben Katalog sind auch unkalibriert belastbar, weil sich systematische Fehler herauskürzen. Die Kalibrierung braucht man nur, wenn Absolutwerte für Widerstand und Leistung stimmen sollen.
Checkliste für einen Pull Request am Katalog
- [ ]
ideindeutig innerhalb der Marke, kleingeschrieben, mit Bindestrichen - [ ] Einheiten geprüft:
span_mmin mm,area_cm2in cm²,volume_cm3in cm³ - [ ]
mass_gbeziehungsweisemass_kggesetzt oder als geschätzt markiert - [ ] Geschätzte Werte in
notesgekennzeichnet - [ ]
sourcezeigt auf die Datenquelle - [ ]
pytestläuft grün - [ ] Take-off und Gleitzahl liegen in den Plausibilitätsbereichen oben
