diff --git a/CLAUDE.md b/CLAUDE.md index 687d40e..1c2c89c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -881,3 +881,218 @@ PANEL 6 — PRECISION APPROACH RADAR (PAR) │ 1/2 │ Gain increase / decrease │ │ 3/4 │ Rain filter increase / dec │ └──────┴──────────────────────────────┘ + +================================================================== + +UNITS + +================================================================== + +All dimensions are stored and computed in METERS throughout the +entire system — in shared state, in the database, in shaders, and +in all target data structures. + +Any incoming value that arrives in feet (e.g. ADS-B altitude, +antenna heights from configuration) MUST be converted to meters +at the data boundary — in RPiReceiver::parseFrame() or +Simulator::poll() — before the value enters any shared data +structure. No feet values may appear anywhere inside the system +after the conversion point. + +Conversion constant in settings.h: + FEET_TO_METERS = 0.3048 (exact) + +================================================================== + +DEFAULT TARGET DIMENSIONS + +================================================================== + +When a target is first seen with no database record, the system +inserts a row using the defaults below. All values in meters. +need_update is set TRUE so the operator knows to fill in real data. + + ┌──────────────────┬───────────┬──────────────────┬────────────┐ + │ Category │ Length (m)│ Width/Beam (m) │ Material │ + ├──────────────────┼───────────┼──────────────────┼────────────┤ + │ GA aircraft │ 4.0 │ 1.0 (fuselage) │ aluminum │ + │ Commercial a/c │ 30.0 │ 5.0 (fuselage) │ aluminum │ + │ AIS vessel │ 20.0 │ 5.0 (beam) │ steel │ + │ Simulator boat │ 6.0 │ 2.0 (beam) │ fiberglass │ + └──────────────────┴───────────┴──────────────────┴────────────┘ + +Notes: +- AIS vessels are legally required commercial traffic, so steel is + the correct default material. +- Simulator boats are small pleasure craft, so fiberglass is correct. +- The system defaults all new aircraft to GA. The operator must + update commercial entries via the --database panel. +- Height above water/ground defaults to 0 for vessels and 0 for + aircraft (updated by live data). + +================================================================== + +POSTGRESQL DATABASE + +================================================================== + +PostgreSQL is installed. Database: radar. User: radar. Password: radar. +User has full privileges on database radar. + +Schema (all dimensions in METERS): + + 1. target_type ENUM('AIS', 'ADSB', 'LOCAL') + 2. target_id BIGINT — MMSI for marine; ICAO 24-bit address for + aircraft; simulator may reuse same space + 3. length_m REAL — length in meters + 4. width_m REAL — beam (vessels) or fuselage width (aircraft) + in meters + 5. height_m REAL — height above water/ground in meters + 6. material ENUM('fiberglass', 'wood', 'aluminum', 'steel') + 7. need_update BOOLEAN DEFAULT TRUE + 8. last_seen TIMESTAMPTZ — ISO 8601, updated each time target + is received from any source + 9. last_updated TIMESTAMPTZ — ISO 8601, updated when operator saves + changes via DB panel + 10. track history — deferred to a future version; not in v1 schema + +The fields length_m, width_m, height_m, and material are used by the +CPU to compute RCS before passing to the shader. They are static +per-target data uploaded to GPU via SSBO or uniform array each frame. + +Per-frame dynamic fields (location, heading, altitude) are NOT stored +in the database. They live in TargetBuffer (Threads 2/4) and are +updated from live Raspberry Pi or simulator data each sweep. + +================================================================== + +DATABASE MANAGEMENT PANEL + +================================================================== + +Activated by command-line flag: --database +In this mode NO radar display is shown. main.cpp skips all scope +and shader initialization and starts the Dear ImGui loop instead. + +Toolkit: Dear ImGui, integrated with GLFW/OpenGL 3.3. +Source lives in src/imgui/ and is compiled directly into the project +(no separate install step required). + +The panel provides: + - Scrollable table of all targets with need_update highlighted + - Inline edit fields for length, width, height, material + - Dropdown for target_type + - Save button that writes to PostgreSQL via libpq + - Quit button to exit the DB panel (then start main exhibit separately) + +================================================================== + +RADAR EQUATION AND BLOOM + +================================================================== + +The radar equation is evaluated CPU-side to compute received power +(P_r) for each target. The result drives target brightness and bloom. +Computation happens in TrafficCop after each poll, outside any mutex +lock (read-only access to target physical data at that point). + +The computed brightness value is uploaded per-target to the GPU via +SSBO or uniform array. The phosphor shader reads it to set amplitude. + +BLOOM POST-PROCESSING (bloom.vert / bloom.frag): + Separate shader pair. Pipeline: + 1. Render targets to offscreen FBO at full computed brightness + 2. Apply two-pass Gaussian blur to pixels above luminance threshold + 3. Additively blend blurred result back onto main framebuffer + Constants in settings.h: BLOOM_LUMINANCE_THRESHOLD, + BLOOM_BLUR_RADIUS_PX, BLOOM_BLEND_STRENGTH + +RADAR PARAMETERS — MARINE (X Band): + Frequency: 9225 MHz + Peak power: 30 kW + Horizontal beamwidth: 0.5 degrees + Vertical beamwidth: 20 degrees + Antenna length: 15 feet (4.572 m) + Antenna height: 50 feet (15.24 m) above surface + +RADAR PARAMETERS — ATC (S Band): + Frequency: 3000 MHz (3 GHz) + Peak power: 25 kW (exhibit value; real ASR is higher) + Horizontal beamwidth: 1.4 degrees + Vertical beamwidth: 5 degrees + Antenna width: 20 feet (6.096 m) + Antenna height: 50 feet (15.24 m) above runway + +RADAR PARAMETERS — CHAIN HOME (AMES Type 1): + Frequency: 30 MHz + Peak power: 500 kW + Pulse width: 20 microseconds + PRF: 25 Hz or 12.5 Hz (operator selectable) + Transmit gain (Gt): ~7.5 linear (~8.7 dBi) — floodlight, not a beam + formula: G = 30000 / (az_bw_deg × el_bw_deg) + with az ~100 deg, el ~40 deg + Receive gain (Gr): 4 to 10 linear (6–10 dBi) + System loss: ~8 dB (transmission line) + Bistatic: yes — separate transmit and receive antennas + RCS resonance: at 30 MHz (lambda ~10 m) aircraft are in the + Mie/resonant scattering region; RCS is multiplied + by CHAIN_HOME_RCS_RESONANCE_FACTOR (default 3.0) + before radar equation computation. Applied to + Chain Home targets only. + +RADAR PARAMETERS — PAR (X Band): + Peak power: 100 kW + Frequency: ~10 GHz (lambda ~3 cm) + Antenna size: ~5 meters + Beamwidth: ~0.34 degrees (lambda/D) + Horizontal scan: 20 degrees total + Vertical scan: 10 degrees total + Pulse width: short (high range resolution) + PRF: high (~30 Hz alternating az/el) + +All radar parameters shall have corresponding constexpr constants +in settings.h so they can be tuned without touching equation code. + +================================================================== + +FILE LAYOUT (COMPLETE — including additions) + +================================================================== + +src/ + main.cpp + scope_manager.h / scope_manager.cpp + scope.h / scope.cpp + scope_intro.h / scope_intro.cpp + scope_ascope.h / scope_ascope.cpp + scope_marine_a.h / scope_marine_a.cpp + scope_chain_home.h / scope_chain_home.cpp + scope_ppi.h / scope_ppi.cpp + scope_marine_ppi.h / scope_marine_ppi.cpp + scope_atc_ppi.h / scope_atc_ppi.cpp + scope_par.h / scope_par.cpp + phosphor.h / phosphor.cpp + graticule.h / graticule.cpp + left_panel.h / left_panel.cpp + shared_render_state.h / shared_render_state.cpp + target_buffer.h / target_buffer.cpp + traffic_cop.h / traffic_cop.cpp + simulator.h / simulator.cpp + knob_panel.h / knob_panel.cpp + rpi_receiver.h / rpi_receiver.cpp + db_panel.h / db_panel.cpp — Dear ImGui DB management panel + (--database mode only) + settings.h — all constexpr constants; no .cpp + + imgui/ — Dear ImGui source, compiled in + imgui.h / imgui.cpp + imgui_impl_glfw.h / imgui_impl_glfw.cpp + imgui_impl_opengl3.h / imgui_impl_opengl3.cpp + imgui_draw.cpp / imgui_tables.cpp / imgui_widgets.cpp + +shaders/ + phosphor.vert / phosphor.frag — P1 and P7 via uniforms + graticule.vert / graticule.frag + text.vert / text.frag + sweep.vert / sweep.frag + bloom.vert / bloom.frag — FBO bloom post-processing diff --git a/DESIGN.md b/DESIGN.md index b282b52..961a5b3 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -187,13 +187,25 @@ src/ simulator.h / simulator.cpp knob_panel.h / knob_panel.cpp rpi_receiver.h / rpi_receiver.cpp + db_panel.h / db_panel.cpp — Dear ImGui database management panel + (active only when --database flag passed; + no radar rendering in this mode) settings.h — all tunable constants (no .cpp needed) + imgui/ — Dear ImGui source, compiled into project + imgui.h / imgui.cpp + imgui_impl_glfw.h / imgui_impl_glfw.cpp + imgui_impl_opengl3.h / imgui_impl_opengl3.cpp + imgui_draw.cpp / imgui_tables.cpp / imgui_widgets.cpp + shaders/ phosphor.vert / phosphor.frag — parameterized for P1 and P7 via uniforms graticule.vert / graticule.frag text.vert / text.frag sweep.vert / sweep.frag + bloom.vert / bloom.frag — two-pass bloom: render to FBO, Gaussian + blur bright spots, blend back; used for + target blooming from radar equation output ``` --- @@ -342,3 +354,51 @@ No raw `new` or `delete` anywhere in the codebase. No `malloc`/`free`. are blocked during the animation. The new range value is latched when the key is pressed but not applied to the scope state until SLIDING_IN completes. Animation duration is approximately 0.5 seconds per slide (out and in). + +12. **All dimensions are stored and computed in meters** throughout the system. + Any incoming data from Raspberry Pi receivers or the simulator that arrives in + feet (e.g., altitude from ADS-B in feet, antenna heights) is converted to + meters at the boundary in `RPiReceiver::parseFrame()` or `Simulator::poll()` + before the value enters any shared data structure. No feet values appear + anywhere inside the system after the conversion point. + Conversion: 1 foot = 0.3048 meters exactly. + +13. **Default target dimensions** used when a target is first seen with no + database record. All values in meters. `need_update` is set TRUE for all + defaults so the operator knows to fill in real data. + + | Category | Length (m) | Fuselage/Beam width (m) | Material | + |---|---|---|---| + | GA aircraft | 4.0 | 1.0 | aluminum | + | Commercial a/c| 30.0 | 5.0 | aluminum | + | AIS vessel | 20.0 | 5.0 | steel | + | Simulator boat| 6.0 | 2.0 | fiberglass | + + AIS-sourced vessels default to steel (legally required commercial traffic). + Simulator-sourced boats default to fiberglass (small pleasure craft). + Aircraft source type does not disambiguate GA vs. commercial — the system + defaults to GA and lets the operator correct it. + +14. **Bloom post-processing** uses a dedicated `bloom.vert` / `bloom.frag` shader + pair. The pipeline is: render targets to an offscreen FBO at full computed + brightness (from radar equation output), apply a two-pass Gaussian blur to + pixels above a luminance threshold, then additively blend the blurred result + back onto the main framebuffer. Bloom threshold and blur radius are + `constexpr` constants in `settings.h`. + +15. **Dear ImGui** is used for the database management panel, activated by the + `--database` command-line flag. In that mode no radar rendering occurs — + main.cpp skips the scope/shader initialization path entirely and starts the + ImGui loop instead. ImGui source files live under `src/imgui/` and are + compiled directly into the project (no separate install step). The panel + provides: a scrollable target table with `need_update` highlighted, inline + edit fields for length/width/height/material, a dropdown for target type, + and a Save button that writes to PostgreSQL via libpq. + +16. **Chain Home RCS resonance** is modelled with a multiplier constant + `CHAIN_HOME_RCS_RESONANCE_FACTOR` in `settings.h`. At 30 MHz (λ ≈ 10 m), + aircraft with wingspans of 10–30 m are in the Mie/resonant scattering + region; RCS can be 2–5× the geometric cross section. The default value is + 3.0 (a mid-range estimate). This is applied in the radar equation computation + for Chain Home targets only, before the result is passed to the bloom/ + brightness pipeline. diff --git a/src/settings.h b/src/settings.h index 46a87e8..7c5b533 100644 --- a/src/settings.h +++ b/src/settings.h @@ -297,6 +297,70 @@ * larger frames are discarded as malformed */ +/* + * ================================================================ + * UNITS AND CONVERSION + * ================================================================ + * All dimensions inside the system are stored and computed in meters. + * Any incoming value in feet (ADS-B altitude, antenna heights, etc.) + * must be converted at the data boundary before entering shared state. + * + * FEET_TO_METERS Exact conversion factor: 0.3048 + */ + +/* + * ================================================================ + * DEFAULT TARGET DIMENSIONS (meters, need_update = TRUE) + * ================================================================ + * Used when a target is first seen with no database record. + * All values in meters. Operator must update with real dimensions. + * + * GA aircraft (general aviation): + * DEFAULT_GA_LENGTH_M 4.0 (approx Cessna-class) + * DEFAULT_GA_WIDTH_M 1.0 (fuselage width) + * + * Commercial aircraft: + * DEFAULT_COMM_LENGTH_M 30.0 (narrow-body airliner) + * DEFAULT_COMM_WIDTH_M 5.0 (fuselage width) + * + * AIS vessel (commercially registered, defaults to steel): + * DEFAULT_AIS_VESSEL_LENGTH_M 20.0 + * DEFAULT_AIS_VESSEL_BEAM_M 5.0 + * + * Simulator boat (small pleasure craft, defaults to fiberglass): + * DEFAULT_SIM_BOAT_LENGTH_M 6.0 + * DEFAULT_SIM_BOAT_BEAM_M 2.0 + * + * Note: system defaults all new aircraft to GA; operator corrects + * commercial entries via the --database panel. + */ + +/* + * ================================================================ + * BLOOM POST-PROCESSING + * ================================================================ + * Two-pass Gaussian blur applied to pixels above a luminance + * threshold, then additively blended onto the main framebuffer. + * Driven by radar equation output brightness. + * + * BLOOM_LUMINANCE_THRESHOLD Minimum brightness to bloom (0.0–1.0) + * BLOOM_BLUR_RADIUS_PX Gaussian kernel half-width in pixels + * BLOOM_BLEND_STRENGTH Additive blend weight (0.0–1.0) + */ + +/* + * ================================================================ + * CHAIN HOME — RCS RESONANCE + * ================================================================ + * At 30 MHz (lambda ~10 m) aircraft wingspans fall in the Mie/ + * resonant scattering region. RCS is multiplied by this factor + * before the radar equation computes received power. Applied to + * Chain Home targets only. + * + * CHAIN_HOME_RCS_RESONANCE_FACTOR 3.0 (mid-range Mie estimate; + * range is approximately 2–5) + */ + /* * ================================================================ * PAR GEOMETRY