From ca98cb66bac4156edad3ec27c64a101aed3b3326 Mon Sep 17 00:00:00 2001 From: itsrubberduck Date: Fri, 20 Feb 2026 18:18:44 +0100 Subject: [PATCH] docs: add learn-pfd medienstation design document Co-Authored-By: Claude Opus 4.6 --- docs/plans/2026-02-20-learn-pfd-design.md | 146 ++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 docs/plans/2026-02-20-learn-pfd-design.md diff --git a/docs/plans/2026-02-20-learn-pfd-design.md b/docs/plans/2026-02-20-learn-pfd-design.md new file mode 100644 index 0000000..60c6beb --- /dev/null +++ b/docs/plans/2026-02-20-learn-pfd-design.md @@ -0,0 +1,146 @@ +# Learn PFD — Medienstation Design + +## Overview + +Interactive media station at `/flightlab/medienstationen/learn-pfd` that teaches Airbus A320 PFD reading and FBW Normal Law handling through progressive, hands-on lessons. + +Users receive sidestick (pitch/roll) and throttle input via WebSocket from an external touchscreen (later: hardware via Python script). A PFD is built up element-by-element with TTS narration, and a 3D aircraft model reacts in real-time to the FBW physics output. + +## Routing + +``` +/app/pages/flightlab/medienstationen/ + index.vue ← Grid overview of all media stations + learn-pfd.vue ← PFD learning station (fullscreen) +``` + +## Learning Phases + +Stepper-based, reusing FlightLab TTS + audio patterns. + +| # | Phase | PFD Elements Visible | Focus | Interaction | +|---|-------|---------------------|-------|-------------| +| 1 | Willkommen | None (black) | 3D model large | Listen to intro | +| 2 | Horizont | Attitude indicator | Sky/ground, bank | "Roll left — watch the horizon" | +| 3 | Pitch | Attitude indicator | Pitch ladder, Normal Law | "Pull stick back — nose goes up. Let go — it holds." | +| 4 | Speed Tape | + Speed tape (left) | IAS, throttle effect | "Push throttle forward — speed increases" | +| 5 | Altitude Tape | + Altitude tape (right) | Altitude, climb | "You're climbing — watch altitude change" | +| 6 | Vertical Speed | + VS indicator | VS ↔ pitch relationship | "Pitch up more — VS increases" | +| 7 | Heading | + Heading band (bottom) | Heading, turns | "Bank right and watch heading change" | +| 8 | Zusammenspiel | All elements | Combined reading | Mini-tasks: "Climb to 5000ft", "Turn to heading 270" | +| 9 | Freies Üben | All elements | Free practice | Optional takeoff scenario | + +Each phase: TTS explains → element fades in (animated) → user interacts → next button or auto-advance. + +## Architecture + +### Tech Stack + +- **PFD**: SVG-based Vue components (one per instrument) +- **3D Model**: Three.js with GLTF A320 model +- **FBW Physics**: `useAirbusFBW()` composable — 60fps simulation loop +- **Input**: WebSocket via existing `/api/flightlab/ws` with new message type +- **Audio/TTS**: Reuse `useFlightLabAudio()` composable +- **Stepper**: Reuse pattern from `takeoff.vue` (sidebar phases, progress) + +### PFD Components + +``` +app/components/flightlab/pfd/ + PfdContainer.vue ← Orchestrates visibility per phase + PfdAttitudeIndicator.vue ← Artificial horizon, pitch ladder, bank scale + PfdSpeedTape.vue ← Scrolling speed scale, speed bug, trend + PfdAltitudeTape.vue ← Scrolling altitude scale, alt bug + PfdVerticalSpeed.vue ← VS scale with needle/band + PfdHeadingIndicator.vue ← Rotating compass band +``` + +All receive flight state as props from FBW composable output. + +### FBW Composable (`useAirbusFBW`) + +``` +shared/composables/flightlab/useAirbusFBW.ts +``` + +**Input:** `{ pitch: -1..+1, roll: -1..+1, throttle: 0..1 }` + +**Normal Law simulation:** +- Pitch stick → target load factor (1G neutral, ~2.5G full back, ~-1G full forward) +- Pitch rate derived from current-G vs target-G delta +- Roll stick → roll rate (max ~15°/s), neutral holds bank angle +- Bank > 33° with stick neutral → slow rollback to 33° +- Protections: max 67° bank, alpha floor (simplified) +- Throttle → thrust → acceleration (simplified drag model) +- Derived: altitude (integrated VS), heading (from bank + speed), VS (from pitch + speed) + +**Output (reactive):** +```typescript +{ + pitch: number, // degrees + roll: number, // degrees (bank angle) + heading: number, // 0-360 + speed: number, // knots IAS + altitude: number, // feet + verticalSpeed: number, // fpm + bankAngle: number, // degrees + aoa: number, // angle of attack + throttlePercent: number // 0-100 +} +``` + +### 3D Aircraft Model + +``` +app/components/flightlab/pfd/PfdAircraftModel.vue +``` + +- Three.js canvas with GLTF A320 model +- Camera: slightly above/behind, follows aircraft +- Model rotation mirrors FBW output (pitch, roll, heading) +- Simple sky gradient + cloud layer for motion reference +- Responsive sizing via container + +### WebSocket Input + +Extends existing `/api/flightlab/ws` with new message type: + +```typescript +// From touchscreen/Python to server +{ type: 'stick-input', data: { pitch: number, roll: number, throttle: number } } + +// Server broadcasts to PFD client in same session +{ type: 'stick-input', data: { pitch: number, roll: number, throttle: number } } +``` + +No new WS endpoint needed — reuses session infrastructure. + +### Dynamic Layout + +Layout shifts based on current phase, animated via CSS Grid transitions: + +**Phase 1-3 (intro/horizon/pitch):** 3D model 70%, PFD overlay small +**Phase 4-7 (instruments):** PFD 50%, 3D model 50% side by side +**Phase 8-9 (practice):** PFD 70%, 3D model 30% + +Transitions: animated `grid-template-columns` + opacity/transform. + +### Scenario Data + +``` +shared/data/flightlab/learn-pfd.ts +``` + +Phase definitions following existing `FlightLabPhase` pattern with extensions for: +- `visiblePfdElements: string[]` — which PFD components to show +- `layoutMode: 'model-focus' | 'split' | 'pfd-focus'` — dynamic layout +- `interactionGoal?: { type, target, tolerance }` — e.g. "reach altitude 5000±200" + +## Medienstationen Index + +Grid of cards (like `/flightlab/index.vue`). Each card: +- Title, description, icon +- Status badge (ready / coming soon) +- Click navigates to station page + +First entry: "PFD verstehen" — learn-pfd station.