re doing to facilitate debugging
This commit is contained in:
543
CLAUDE.md
543
CLAUDE.md
@@ -67,19 +67,38 @@ GENERAL STUFF
|
||||
|
||||
==================================================================
|
||||
|
||||
COLORS
|
||||
|
||||
1. P7 Strike Color (when things are written to p7 = Blue white Hex #F0F8FF
|
||||
2. P7 Persistence (during persistence after strike = Yellow Hex #F2BF1C
|
||||
3. All Graticules and PPI Cursors are incandescent #47 lamp Hex #FFF4CC
|
||||
This is for bearing rings on ppi scope as well as bearing ticks and
|
||||
bearing degree texts
|
||||
4. Left Panel Text for description is white hex #FFFFFF except for controls
|
||||
as described below
|
||||
5. Control operation via keyboard key strokes are light red Hex #FFCCCB
|
||||
6. Control operation description are light green #64E3A1
|
||||
7. Status text panel under scope are cyan hex #00FFFF
|
||||
8. Note that all targets are to be p7; this includes land features and
|
||||
active targets. Range rings on ppi are also p7
|
||||
Please note that range rings shall be fixed brightness; not affected
|
||||
by sensitivity.
|
||||
9. Range markings and range calibration pips shall be p7 on the chain
|
||||
home scope.
|
||||
10. Center line on precision approach radar horizontal and guide path
|
||||
on precision approach radar vertical shall be p7
|
||||
11. Rain noise as well as water wave noise shall also be p7 and be
|
||||
affected by gain as well as noise filtering controls
|
||||
12. Please note for each color in this table, there shall be a variable
|
||||
in the settings.h file that can be used to change the color. Values should be in hex.
|
||||
13. The marine a scope display is p1 phosphor (green)
|
||||
14. The chain home scope display is p2 phosphor (blue green with some persistence)
|
||||
|
||||
==================================================================
|
||||
|
||||
Please note that all on-screen text shall be white and fully
|
||||
illuminated and is not subject to phosphor persistence or decay.
|
||||
|
||||
Exceptions:
|
||||
|
||||
Graticule text: should be incandescent for the bearing marks.
|
||||
Graticule text for all a-scope should be incandescent, not white
|
||||
and not phosphor as they are dependent on glass graticules with etched
|
||||
lines and text.
|
||||
|
||||
PPI Scope Range Ring Markers Text on the PPI scope range rings shall be blue
|
||||
fade to yellow green as on p7 phosphor. Which is the same for ppi targets.
|
||||
|
||||
Please note that direction as stated here are True directions. 000 is True North
|
||||
|
||||
Maximum Range is 6 miles for marine type radar
|
||||
@@ -120,6 +139,9 @@ description window for each scope. When the main exhibit descriptor screen comes
|
||||
important to highlight the feature that the user can press the s key or the S key any time to 'hurry up'
|
||||
the scope advancement.
|
||||
|
||||
Please note that controls are used for the current scope that is selected. When you move to another scope or to scope
|
||||
1 after leaving the Exhibit introduction screen; the controls must be reset for the scope you are entering
|
||||
|
||||
Also ensure that the timeout clock will reset when the user changes to a new scope, or presses
|
||||
any key or operates any control on the panel. This
|
||||
should be articulated in the descriptive text
|
||||
@@ -132,12 +154,14 @@ should be articulated in the descriptive text
|
||||
2. Marine A-Scope - (horizontal axis is range; vertical axis is amplitude of
|
||||
return pulse; bearing will be set via a bearing control; current implementation
|
||||
would be two keys on the keyboard; one key to go clockwise on bearing and another
|
||||
key would be to go counterclockwise. The A scope phosphor is P1, which is green.
|
||||
key would be to go counterclockwise.
|
||||
The c key for clockwise on a scope and v for counterclockwise.
|
||||
The step rate for this control, before the knob is implemented would be one or two
|
||||
degrees per key press, but if the key is held down, it would increase slowly due to
|
||||
how long the key is depressed
|
||||
|
||||
The max range setting shall be included in the status text window below the scope
|
||||
|
||||
The A scope graticule is manually swapped out at each maximum range value
|
||||
by the operator during the period. Here we will have to fake it out. And that
|
||||
graticule needs to have an incandescent color. That graticule will have three horizontal
|
||||
@@ -167,6 +191,8 @@ should be articulated in the descriptive text
|
||||
The u and d keys are ignored during the swap animation (operator's hands are busy).
|
||||
The graticule remains incandescent color throughout — it is edge-lit glass.
|
||||
|
||||
The sliding out, bare crt, and sliding in should all be settable in settings.h
|
||||
|
||||
3. Chain Home A Scope There is a second use of the a-scope.
|
||||
That is for the early world war 2 chain home
|
||||
radar. This operated very differently. You have a large array of high power transmitters
|
||||
@@ -187,6 +213,9 @@ should be articulated in the descriptive text
|
||||
for single press, but a slow build of of speed if key is held down. This has to stay
|
||||
slow due to the sudden appearance of the null.
|
||||
|
||||
The status for goniometer switch shall be shown in the status text windo below
|
||||
the scope as well as the goniometer setting in degrees as selected by the switch
|
||||
|
||||
Targets for Chain Home would all have to be simulated as there will be no ais
|
||||
nor ads-b. Simulations would show several aircraft approaching the radar in many
|
||||
different directions and ranges. The museum visitor for exercise could try to sort
|
||||
@@ -215,10 +244,7 @@ should be articulated in the descriptive text
|
||||
Let's assign key . for toggling between 25 and 12.5 PRF. There is no range selection.
|
||||
Note on description; this is to reduce use of the shift key.
|
||||
|
||||
Because of the slow repetition rate, the phosphor used was P2 (long-persistence green)
|
||||
so that the targets will still glow between the sweeps and not cause flickering. P2 is
|
||||
a single-layer green phosphor with longer decay than P1, appropriate for an A-scope at
|
||||
low PRF. Unlike P7, it does not produce a blue flash or a seconds-long smearing tail.
|
||||
The setting for the range should be on the status text panel below the scope.
|
||||
|
||||
Another unique feature would be a response to the drifting problem in early electronics.
|
||||
The scope electronics would use a crystal calibrator that puts tiny pips or spikes at
|
||||
@@ -229,20 +255,9 @@ should be articulated in the descriptive text
|
||||
Let's assign key n for shrink and m for stretch. (may be ambiguous, but I am running
|
||||
out of keys. Note in the descriptor.
|
||||
|
||||
|
||||
4. Marine PPI Scope -
|
||||
marine scopes have the following items in common:
|
||||
Targets, range rings, and range ring text levels shall be treated the same for
|
||||
presentation. All are P7 phosphor. Immediate strike by the electron beam is blue.
|
||||
persistence is green/yellow. Targets, range rings, and range ring labels shall all
|
||||
persist and fade out together. They should be faded out by the time the sweep
|
||||
returns to that location.
|
||||
|
||||
IMPORTANT — range rings are beam-painted, not a static overlay:
|
||||
Range rings and their labels are written by the rotating sweep beam on
|
||||
each pass, exactly like target echoes. They are NOT rendered as a fixed
|
||||
overlay on top of the scope. This means they are fully subject to P7
|
||||
persistence and decay just as targets are.
|
||||
4. All PPI Scopes (common features)
|
||||
All three ppi scopes (marine stationary; marine police boat; and Air Traffic Control
|
||||
Have the following common features:
|
||||
|
||||
When the operator changes max range (u/d keys), the new ring geometry
|
||||
takes effect only for the sector the sweep is currently painting. The
|
||||
@@ -254,20 +269,7 @@ should be articulated in the descriptive text
|
||||
holds whatever the beam last wrote. No special transition animation is
|
||||
needed; the behavior emerges naturally from the phosphor model.
|
||||
|
||||
The maximum range settings are 6 miles for the marine radar scope
|
||||
Rings should be 2,4, and 6 miles for marine.
|
||||
The max range settings for marine ppi will be u for up and d for
|
||||
down. If you are in the marine ppi, you change only the max range for the marine
|
||||
ppi. The possible max range values for
|
||||
the marine radar are 2,4,6
|
||||
miles.
|
||||
|
||||
Marine:
|
||||
Max is 2; one interim range at 1, final ring at 2
|
||||
Max is 4; one interim range at 2, final ring at 4
|
||||
Max is 6; one interim range at 4, final ring at 6
|
||||
|
||||
Note on range. If cursor range is beyone max, clamp it to the max.
|
||||
Note on range. If cursor range is beyond max, clamp it to the max.
|
||||
|
||||
Bear in mind that the max range setting is independent for both radars.
|
||||
|
||||
@@ -278,8 +280,6 @@ should be articulated in the descriptive text
|
||||
an outer ring. Both inner and outer rings, along with ticks, and the bearing
|
||||
labels are to be incandescent color.
|
||||
|
||||
The sweep time shall be 4 seconds for the marine scope
|
||||
|
||||
The sweep direction is clockwise, which means that the antenna
|
||||
dish rotates clockwise.
|
||||
|
||||
@@ -292,9 +292,27 @@ should be articulated in the descriptive text
|
||||
the scope. In the real day, it was a machanical readout. The key sequence would be
|
||||
r for bearing to the right and l for bearing for the left; and t for higher range
|
||||
and y for smaller range. These controls should have slow movement for single stroke; but
|
||||
gradual for for holding key down.
|
||||
gradual for holding key down.
|
||||
|
||||
5. Police Patrol Boat PPI
|
||||
5. Marine PPI Scope specific items:
|
||||
|
||||
This scope is for a fixed location marine radar. It is for marine traffic control.
|
||||
The maximum range settings are 6 miles for the marine radar scope
|
||||
Rings should be 2,4, and 6 miles for marine.
|
||||
The max range settings for marine ppi will be u for up and d for
|
||||
down. If you are in the marine ppi, you change only the max range for the marine
|
||||
ppi. The possible max range values for
|
||||
the marine radar are 2,4,6
|
||||
miles.
|
||||
|
||||
Marine:
|
||||
Max is 2; one interim range at 1, final ring at 2
|
||||
Max is 4; one interim range at 2, final ring at 4
|
||||
Max is 6; one interim range at 4, final ring at 6
|
||||
|
||||
|
||||
|
||||
6. Police Patrol Boat PPI
|
||||
|
||||
This scope shows the radar display aboard a simulated Bellingham Police
|
||||
Department patrol vessel making its routine waterfront patrol. Unlike all
|
||||
@@ -349,6 +367,9 @@ should be articulated in the descriptive text
|
||||
a white dashed line from scope center toward the bow, drawn after all
|
||||
phosphor content so it never decays.
|
||||
|
||||
The heading and the range max settings shall be indicated on the status text
|
||||
panel below the scope
|
||||
|
||||
TERRAIN AND BREAKWATER CLUTTER
|
||||
The concrete Squalicum Harbor outer breakwater is a strong radar return and
|
||||
a significant shadow-caster. Everything behind the breakwater from the
|
||||
@@ -368,12 +389,7 @@ should be articulated in the descriptive text
|
||||
Cursor brg: XXX°T
|
||||
Max range: X.X mi
|
||||
|
||||
6. Air Traffic PPI Scope -
|
||||
Targets, range rings, and range ring text levels
|
||||
All are P7 phosphor. Immediate strike by the electron beam is blue.
|
||||
persistence is green/yellow. Targets, range rings, and range ring labels shall all
|
||||
persist and fade out together. They should be faded out by the time the sweep
|
||||
to that location.
|
||||
7. Air Traffic PPI Scope -
|
||||
|
||||
Rings should be 5,10,15,20 for the air traffic control radar.
|
||||
The max range settings for air ppi will be u for up and d for
|
||||
@@ -388,7 +404,7 @@ should be articulated in the descriptive text
|
||||
Max is 15; three interim ranges four total; 4,8,12; final ring at 15
|
||||
Max is 20, three interim ranges four total; 5,10,15; final ring at 20
|
||||
|
||||
Note on range. If cursor range is beyone max, clamp it to the max.
|
||||
Note on range. If cursor range is beyond max, clamp it to the max.
|
||||
|
||||
Bear in mind that the max range setting is independent for both radars.
|
||||
|
||||
@@ -407,17 +423,16 @@ should be articulated in the descriptive text
|
||||
|
||||
The scope has cursor for range and bearing. The cursor consists of a
|
||||
section of a ring ( 10 degrees) and a cross line for bearing.
|
||||
The cursor should be yellow (it
|
||||
a plastic overlay in the period time. Two controls control the cursor; range and
|
||||
Two controls control the cursor; range and
|
||||
bearing. Both were physical crank controls. For now, both we need to use key pairs
|
||||
on the keyboard. A white text indication of range and bearing should be put under
|
||||
the scope. In the real day, it was a machanical readout. The key sequence would be
|
||||
r for bearing to the right and l for bearing for the left; and t for higher range
|
||||
and y for smaller range.
|
||||
These controls should have slow movement for single stroke; but
|
||||
gradual for for holding key down.
|
||||
gradual increase movement for holding key down.
|
||||
|
||||
7. Precision approach (PAR for short)
|
||||
8. Precision approach (PAR for short)
|
||||
PAR was developed in WWII and matured in the 1950s. With a fixed 10 mile range, it was
|
||||
controller who talked the pilot down verbally over radio, which means that the pilot
|
||||
does not have to rely on any equipment on the plane itself to help with landing.
|
||||
@@ -431,7 +446,7 @@ should be articulated in the descriptive text
|
||||
at Bellingham Airport (BLI). Two vertically stacked scopes share the
|
||||
right panel. Top scope: azimuth (lateral deviation vs. range from
|
||||
touchdown). Bottom scope: elevation (vertical deviation vs. range).
|
||||
Have the azimuth scope to about 1/3 larger than the elevation scope
|
||||
Both the azimuth scope and the elevation scope should be the same size
|
||||
Both use P7 phosphor; graticules are incandescent etched glass.
|
||||
Range: 10 miles maximum, fixed (no range change control).
|
||||
Non-linear scale: inner 5 miles occupies 70% of horizontal width.
|
||||
@@ -580,13 +595,8 @@ Scope and left window arrangement.
|
||||
For each scope, put the scope itself on the right hand of the window.
|
||||
On the left hand of the window will be a text description of that scope.
|
||||
|
||||
Underneath each scope's description will be cursor range and bearing from the radar
|
||||
location; and the setting of maximum range; and the bearing offset; for 0 would
|
||||
be to have 0 degrees pointing to true north (this is needed if I decide to
|
||||
implement a radar on a boat. If implemented, use k for bearing to right; and
|
||||
j for bearing to left. Make note in description that this is only used if this
|
||||
is a radar on a boat. (perhaps later on, I could add a PPI on a boat scenario)
|
||||
|
||||
The text status panel under each scope shall show, in addition to notes above,
|
||||
the bearing and range for the cursor in the status text panel below the scope.
|
||||
Please note that some keys may be the same from scope to scope. This is okay. Each
|
||||
scope's controls are for that scope that you are connected do.They will not effect
|
||||
settings on another scope.
|
||||
@@ -600,8 +610,6 @@ different radars. Range and bearing for the precision approach radar will be dif
|
||||
than any other radar as that radar is located at the end of the runway and scan both
|
||||
horizontal and vertical.
|
||||
|
||||
Please analyze and comment. Please do not generate any code file nor shader files.
|
||||
|
||||
==================================================================
|
||||
|
||||
CLASS DESIGN AND FILE LAYOUT
|
||||
@@ -636,7 +644,6 @@ AScope : public Scope (abstract) — shared A-scope behavior:
|
||||
- Noise floor rendering (rain/wave clutter)
|
||||
- Incandescent graticule (three horizontal amplitude lines + vertical range lines)
|
||||
- Bearing control with key-hold acceleration
|
||||
- Phosphor type as parameter (P1, P2, or P7)
|
||||
|
||||
MarineAScope : public AScope
|
||||
- P1 phosphor (green)
|
||||
@@ -647,7 +654,7 @@ MarineAScope : public AScope
|
||||
u and d ignored during graticule swap animation
|
||||
|
||||
ChainHomeAScope : public AScope
|
||||
- P2 phosphor (long-persistence green)
|
||||
- P2 phosphor (blue green)
|
||||
- Goniometer state: H/V mode toggle, azimuth angle, elevation angle
|
||||
- PRF toggle: 25 Hz / 12.5 Hz
|
||||
- Calibrator stretch/shrink scale factor
|
||||
@@ -657,16 +664,15 @@ ChainHomeAScope : public AScope
|
||||
PPIScope : public Scope (abstract) — shared PPI behavior:
|
||||
- Clockwise sweep with P7 phosphor persistence (blue strike, green/yellow decay)
|
||||
- Incandescent bearing graticule (1-degree ticks, 15-degree labels, inner/outer rings)
|
||||
- Yellow cursor: 10-degree arc + bearing crossline
|
||||
- Incandescent cursor: 10-degree arc + bearing crossline
|
||||
- Cursor range/bearing readout under scope (white text)
|
||||
- Bearing offset for boat mode (k/j)
|
||||
- Cursor range clamped to max range
|
||||
- There shall be a gain independent channel for the p7 phosphor
|
||||
that shall not be impacted by the operator gain control.
|
||||
- Range rings are beam-painted per sweep sector with P7 persistence and decay;
|
||||
however they are stored in the GAIN-INDEPENDENT G channel of the phosphor FBO
|
||||
(see PHOSPHOR FBO ARCHITECTURE below) so operator gain does not dim the rings
|
||||
- renderRingLabels() — virtual method (default no-op); concrete PPI scopes that
|
||||
have labelled range rings override this to render mile-distance text labels in
|
||||
P7 fresh-blue colour at a fixed bearing (RING_LABEL_BRG_DEG = 045°)
|
||||
operator gain does not dim the rings
|
||||
- No range ring labels. That era had no text in the p7.
|
||||
|
||||
IMPLEMENTER CHECKLIST — required in every new PPIScope subclass:
|
||||
1. computeRingRadii(): multiply each normalised ring radius by
|
||||
@@ -674,38 +680,7 @@ PPIScope : public Scope (abstract) — shared PPI behavior:
|
||||
places the outer ring at the scope boundary where it is clipped
|
||||
and hidden behind the graticule. Target positions are scaled
|
||||
automatically by PhosphorRenderer::update(); ring radii are not.
|
||||
2. Override renderRingLabels() using the same pattern as
|
||||
MarinePPIScope::renderRingLabels() but with the scope's own
|
||||
ring-mile table. The base-class no-op produces no labels.
|
||||
The p7Color() fix, two-channel FBO gain-separation, and target
|
||||
position scaling are all automatic via the shared PhosphorRenderer
|
||||
and shaders — no per-scope action required for those.
|
||||
|
||||
==================================================================
|
||||
|
||||
PHOSPHOR FBO ARCHITECTURE
|
||||
|
||||
==================================================================
|
||||
|
||||
The phosphor FBO is GL_RG32F (two independent float channels):
|
||||
|
||||
R channel — signal energy
|
||||
Written by: target echoes in the sweep shader
|
||||
Multiplied by: u_gain in the display shader
|
||||
Effect: operator gain knob dims/brightens received echoes without
|
||||
affecting the sweep beam or range rings
|
||||
|
||||
G channel — timing/geometry energy
|
||||
Written by: range rings + sweep background glow in the sweep shader
|
||||
NOT multiplied by gain in the display shader
|
||||
Effect: rings always appear at a fixed brightness; the rotating
|
||||
sweep-line glow is always visible even at minimum gain
|
||||
|
||||
Both channels decay at the same P7 rate (P7_DECAY_RATE in settings.h).
|
||||
The display shader combines them: totalEnergy = max(R * gain, G).
|
||||
This produces the correct visual priority: a strong target echo always
|
||||
shows above the ring but a dim echo below gain threshold fades away
|
||||
while the ring stays steady.
|
||||
2. No labeling of range rings.That era did not have them
|
||||
|
||||
RANGE POSITION NORMALISATION
|
||||
|
||||
@@ -718,28 +693,6 @@ If max-range mapped to 1.0, the outer ring would sit at the scope
|
||||
boundary — half-clipped by the sweep shader's rng > 1.0 early-exit and
|
||||
visually hidden behind the graticule outer ring.
|
||||
|
||||
Mapping max-range → GRAT_INNER_RING_FRAC keeps all rings and targets
|
||||
within the clean active display area inside the bearing scale overlay.
|
||||
|
||||
Scale is applied in two places:
|
||||
1. PhosphorRenderer::update() — target range: × GRAT_INNER_RING_FRAC
|
||||
2. computeRingRadii() in each concrete PPI scope — ring radii: × GRAT_INNER_RING_FRAC
|
||||
|
||||
P7 COLOUR FUNCTION
|
||||
|
||||
p7Color() in phosphor.frag is a piecewise linear ramp over [0, 1]:
|
||||
e ≥ T_BLUE (0.82) → pure C_BLUE
|
||||
[T_GREEN, T_BLUE) → mix(C_GREEN, C_BLUE, normalised within range)
|
||||
[T_YGREE, T_GREEN) → mix(C_YGREE, C_GREEN, normalised within range)
|
||||
[T_DARK, T_YGREE) → mix(C_YELLW, C_YGREE, normalised within range)
|
||||
[0, T_DARK) → mix(C_BLACK, C_YELLW, normalised within range)
|
||||
|
||||
Each mix() factor is in [0, 1] and the function is continuous at every
|
||||
threshold boundary. An earlier version had each branch using the formula
|
||||
of the branch below it (off-by-one), which caused SWEEP_BACKGROUND_ENERGY
|
||||
= 0.10 to render as saturated yellow (factor 3.33) instead of dim
|
||||
yellow-green, producing an unwanted solid-yellow band behind the sweep.
|
||||
|
||||
==================================================================
|
||||
|
||||
|
||||
@@ -769,7 +722,7 @@ ATCPPIScope : public PPIScope
|
||||
- Keys: u (range up), d (range down) — this scope only
|
||||
|
||||
PARScope : public Scope
|
||||
- Two stacked sub-scopes: azimuth (top, ~1/3 larger) and elevation (bottom)
|
||||
- Two stacked sub-scopes: azimuth on top and elevation below
|
||||
- 30 Hz alternating scan between planes (~15 Hz each)
|
||||
- Fixed 10-mile range, non-linear scale (inner 5 miles = 70% width)
|
||||
- P7 phosphor; incandescent etched glass graticules
|
||||
@@ -777,7 +730,7 @@ PARScope : public Scope
|
||||
|
||||
Supporting classes:
|
||||
ScopeManager Thread 1 — owns scope list, s/S switching, 120s auto-advance timer
|
||||
PhosphorRenderer Thread 1 — P1 and P7 decay/persistence; shared dependency
|
||||
PhosphorRenderer Thread 1 — P1, P2 and P7 decay/persistence; shared dependency
|
||||
Graticule Thread 1 — incandescent graticule lines/text; parameterized per scope
|
||||
LeftPanel Thread 1 — scope description text panel (left side of window)
|
||||
SharedRenderState Threads 1,2,3 — Mutex A; state vars Thread 1 reads each frame for shader uniforms
|
||||
@@ -789,104 +742,96 @@ Supporting classes:
|
||||
|
||||
File layout:
|
||||
|
||||
src/
|
||||
main.cpp
|
||||
scope_manager.h / scope_manager.cpp
|
||||
scope.h / scope.cpp — abstract Scope base
|
||||
scope_intro.h / scope_intro.cpp
|
||||
scope_ascope.h / scope_ascope.cpp — abstract AScope
|
||||
scope_marine_a.h / scope_marine_a.cpp
|
||||
scope_chain_home.h / scope_chain_home.cpp
|
||||
scope_ppi.h / scope_ppi.cpp — abstract PPIScope
|
||||
scope_marine_ppi.h / scope_marine_ppi.cpp
|
||||
scope_boat_ppi.h / scope_boat_ppi.cpp — BoatPPIScope; police patrol boat;
|
||||
moving radar origin; variable speed;
|
||||
heading marker; display-mode tracking;
|
||||
nearest-mask selection from TerrainMap
|
||||
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
|
||||
src/scope.cpp / scope.h = scope abstract
|
||||
src/ascope.cpp /ascope.h = a scope abstract and shared a scope logic
|
||||
src/marine_ascope.cpp / marine_ascope.h - MarineAScope
|
||||
src/chain_ascope.cpp / chain_ascope.h - ChainHomeAScope
|
||||
src/ppi_scope.cpp / ppi_scope.h - ppi scope abstract
|
||||
src/ppi_scope_marine.cpp / ppi_scope_marine.h - marine ppi scope abstract
|
||||
src/ppi_scope_marine_tower_scope.cpp / ppi_scope_marine_tower_scope.h - MarineTowerScope
|
||||
src/ppi_scope_police_boat.cpp /ppi_scope_police_boat.h - MarinePoliceScope
|
||||
src/ppi_scope_atc.cpp / ppi_scope_atc.h - AirTrafficScope
|
||||
src/par_scope.cpp / src/par_scope.h - PARScope - note; this is for precision approach radar
|
||||
src/status_text.cpp / status_text.h - StatusText - note; this is for status text below scope
|
||||
src/land_feature.cpp / land_feature.h - LandFeature - note; this is for land feature terrain, shore, lidar
|
||||
src/descriptive_text.cpp / descriptive_text.h - DescriptiveText note; this is for left panel text
|
||||
including keyboard control descriptions
|
||||
src/traffic_cop.cpp / src/traffic_cop.h - InputTrafficCop note; receiving data from rpis and simulator
|
||||
src/simulator.cpp / simulator.h - TargetSimulator
|
||||
src/rpi_receiver.cpp / src/rpi_receiver.h - RPIReceiver
|
||||
src/keyboard_control.cpp / keyboard_control.h - KeyBoardControls
|
||||
src/physical_control.cpp / physical_control.h - PhysicalControls
|
||||
src/shared_render_state.cpp / shared_render.h - SharedRenderState
|
||||
src/scope_manager.cpp / scope_manager.h - ScopeManager
|
||||
|
||||
settings.h — all tunable constants; no .cpp needed
|
||||
Shader pairs (include .vert and .frag
|
||||
|
||||
data/
|
||||
patrol_route.json — boat waypoints with lat/lon and speed per
|
||||
segment; loaded by Simulator at startup;
|
||||
not compiled in — edit without rebuild
|
||||
P7_persistent_stage - having to do with the persistent (yellow green) of the p7 phosphor
|
||||
marine_ascope_targets - handling marine ascope targets
|
||||
marine_ascope_land - handling land for ascope
|
||||
marine_ascope_bearing - handling marine a scope bearing
|
||||
marine_ascope_graticule - handling changing marine ascope graticules
|
||||
chainhome_ascope_graticules - handling chain home a scope graticules
|
||||
chainhome_ascope_targets - handling chain home targets including the
|
||||
goniometer operation
|
||||
ppi_scope_graticules - handling all ppi scope graticules
|
||||
ppi_scope_target - handling target for all ppi scopes
|
||||
terrain_clutter - for terrain
|
||||
par_scope_graticule - handling graticules for Precision Approach Radar Scopes
|
||||
par_scope_targets - handling targets for Precision Approach Radar Scopes
|
||||
bloom - two pass gaussian blur on pixels above luminance threshold, three tuning constants in settings.h
|
||||
rain_noise - noise caused by rain amount to be set by a random CPU function
|
||||
sea_wave_noise - noise caused by wind on waves; stronger when close to radar ; amount to be set by CPU function
|
||||
|
||||
shaders/
|
||||
phosphor.vert / phosphor.frag — parameterized for P1 and P7 via uniforms
|
||||
graticule.vert / graticule.frag
|
||||
text.vert / text.frag
|
||||
sweep.vert / sweep.frag
|
||||
==================================================================
|
||||
|
||||
settings.h — tunable constants:
|
||||
All magic numbers live here. Every source file that needs a tunable value
|
||||
includes settings.h. No values are hardcoded elsewhere.
|
||||
Categories planned:
|
||||
- Phosphor P1 color
|
||||
- Phosphor P2 color and decay time (Chain Home A-Scope)
|
||||
- Phosphor P7 strike color, persistence color, decay times (PPI scopes and PAR)
|
||||
- Sweep line width, brightness, fade trail, periods per scope
|
||||
- PAR scan rate; Chain Home PRF high and low
|
||||
- Graticule incandescent color, line widths
|
||||
- PPI bearing ring tick lengths, label interval, font size
|
||||
- PPI range ring line width, label size, label color
|
||||
- Cursor color, line width, arc span
|
||||
- Noise floor amplitude and variation (Marine A-Scope)
|
||||
- Graticule swap animation durations (slide out, bare CRT, slide in)
|
||||
- Key-hold acceleration (initial step, rate, max) — separate for goniometer
|
||||
- Auto-advance timer interval (120 seconds)
|
||||
- Window size and panel layout fractions
|
||||
- PAR azimuth/elevation height fractions
|
||||
- UI text color and size; cursor readout text size
|
||||
- Graticule label color (incandescent)
|
||||
- Gain: default (0.5), minimum (0.0), maximum (1.0), keyboard step size
|
||||
- Rain clutter filter: default (0.0 = off), minimum (0.0), maximum (1.0), keyboard step size
|
||||
- Wave clutter filter: default (0.0 = off), minimum (0.0), maximum (1.0), keyboard step size
|
||||
- Key-hold acceleration for gain, rain clutter, and wave clutter keys
|
||||
- Terrain bounding box (lat/lon min/max) and processed cell size
|
||||
- Terrain material σ° values (soil, rock, concrete, water calm/rough)
|
||||
- Terrain material speckle/grain amplitudes (soil, rock, concrete)
|
||||
- Terrain classification thresholds (rock elevation, rock slope)
|
||||
- Terrain polar grid dimensions (range bins, bearing bins)
|
||||
- Terrain clutter brightness scale for marine PPI
|
||||
- Terrain boat recompute threshold (degrees bearing offset change)
|
||||
- ATC terrain clutter suppressed flag (bool, default true)
|
||||
- ATC terrain shadow enabled flag (bool, default true)
|
||||
- LiDAR structure height threshold for man-made classification
|
||||
- BOAT_PATROL_ROUTE_JSON: path to patrol route file (default "data/patrol_route.json")
|
||||
Waypoints and per-segment speeds live in the JSON, not in settings.h, so
|
||||
the route can be adjusted without recompiling
|
||||
- BOAT_WAYPOINT_ARRIVAL_M: radius within which a waypoint is considered
|
||||
reached, advancing to the next (default 50.0 m)
|
||||
- BOAT_HEADING_TURN_RATE_DEG_S: maximum turn rate deg/s for heading
|
||||
interpolation — realistic, not instantaneous (default 3.0)
|
||||
- BOAT_HEADUP_TOLERANCE_DEG: offset within ±this value of boat heading
|
||||
triggers "Head-up" label in left panel (default 5.0)
|
||||
- BOAT_HEADING_MARKER_COLOR: RGB color of heading marker line (default white)
|
||||
- BOAT_HEADING_MARKER_FRACTION: marker length as fraction of scope radius
|
||||
(default 0.35)
|
||||
- BOAT_HEADING_MARKER_DASH_PX: dash length in pixels (default 8)
|
||||
- BOAT_HEADING_MARKER_GAP_PX: gap length in pixels (default 4)
|
||||
- BOAT_CLUTTER_MASK_COUNT: number of pre-computed boat shadow masks (default 6)
|
||||
- BOAT_MASK_SWITCH_THRESHOLD_M: minimum boat displacement from last selected
|
||||
mask waypoint before a new mask is selected (default 500.0 m)
|
||||
- METERS_PER_DEGREE: flat-earth scale factor for lat/lon → meters conversion
|
||||
(111320.0, valid for 2 nm max range)
|
||||
- Patrol boat radar parameters: BOAT_PEAK_POWER_W (6000), BOAT_FREQ_HZ,
|
||||
BOAT_HORIZ_BEAMWIDTH_DEG (1.9), BOAT_VERT_BEAMWIDTH_DEG (20.0),
|
||||
BOAT_ANTENNA_HEIGHT_M (3.5)
|
||||
- Boat PPI range steps: BOAT_RANGE_STEPS[] = {0.5, 1.0, 2.0} miles,
|
||||
BOAT_RANGE_STEP_COUNT = 3
|
||||
PHOSPHOR FBO ARCHITECTURE
|
||||
|
||||
==================================================================
|
||||
|
||||
The P7 phosphor simulation uses a single floating-point offscreen
|
||||
texture (the phosphor FBO) to store the current glow state of every
|
||||
pixel in the scope. The texture format is RGBA16F.
|
||||
|
||||
CHANNEL ASSIGNMENTS
|
||||
R channel — gain-affected content: targets, land clutter, noise.
|
||||
Multiplied by u_gain during the display pass.
|
||||
G channel — gain-independent content: range rings only.
|
||||
Displayed at full brightness regardless of u_gain.
|
||||
B, A — reserved for future use.
|
||||
|
||||
THREE PASSES PER FRAME
|
||||
|
||||
1. DECAY PASS (P7_persistent_stage.vert / .frag)
|
||||
Reads the phosphor FBO and writes back to it with both R and G
|
||||
channels multiplied by P7_DECAY_FACTOR (default ~0.985 at 60 Hz,
|
||||
settable in settings.h). Both channels decay at the same rate.
|
||||
When P7_PERSISTENCE_ENABLED is false in settings.h this pass is
|
||||
skipped — the FBO is cleared each frame — allowing debugging of
|
||||
raw strike data only.
|
||||
|
||||
2. STRIKE PASS (per-scope target shaders and terrain_clutter)
|
||||
Runs during the sweep. Each fragment that the beam illuminates
|
||||
writes a brightness value into the appropriate channel:
|
||||
- Targets, clutter, noise → write to R, leave G unchanged
|
||||
- Range rings → write to G, leave R unchanged
|
||||
The brightness value is computed from the radar equation result
|
||||
uploaded per-target via SSBO or uniform array.
|
||||
|
||||
3. DISPLAY PASS (composited in each scope's render method)
|
||||
Reads both channels and maps to P7 colors:
|
||||
target_glow = phosphorFBO.R × u_gain
|
||||
ring_glow = phosphorFBO.G (no gain factor)
|
||||
output = P7_color(target_glow) + P7_color(ring_glow)
|
||||
P7_color() maps the glow value to the P7 palette: high values
|
||||
produce P7_STRIKE_COLOR (#F0F8FF), lower values produce
|
||||
P7_PERSISTENCE_COLOR (#F2BF1C).
|
||||
|
||||
DEBUGGING SUPPORT
|
||||
P7_PERSISTENCE_ENABLED (settings.h) — set false to skip decay pass;
|
||||
each frame shows only raw strike data.
|
||||
P7_STRIKE_DEBUG_ALPHA (settings.h) — scales the strike brightness
|
||||
to evaluate persistence timing by eye.
|
||||
|
||||
==================================================================
|
||||
|
||||
@@ -1238,7 +1183,7 @@ POSTGRESQL DATABASE
|
||||
==================================================================
|
||||
|
||||
PostgreSQL is installed. Database: radar. User: radar. Password: radar.
|
||||
User has full privileges on database radar.
|
||||
User has full privileges on database radar. Table is target_data.
|
||||
|
||||
Schema (all dimensions in METERS):
|
||||
|
||||
@@ -1400,33 +1345,13 @@ DATA SOURCES
|
||||
northeast of Bellingham Bay; used for terrain shadowing from the
|
||||
northeast quadrant.
|
||||
|
||||
All three sources are processed offline by terrain_preprocess into
|
||||
All four sources are processed offline by terrain_preprocess into
|
||||
binary grids in map/lidar_processed/. The raw files are never opened
|
||||
at exhibit runtime. See TERRAIN PREPROCESSING section below.
|
||||
|
||||
GDAL (libgdal-dev) is a required build dependency for
|
||||
terrain_preprocess. It is NOT linked into the main radar binary.
|
||||
|
||||
CLASSES
|
||||
|
||||
TerrainMap (Thread 1, read-only after init)
|
||||
Loaded once at startup from map/lidar_processed/. Reads the four
|
||||
binary grids and the metadata JSON. Provides:
|
||||
- Elevation query by lat/lon
|
||||
- Material query by lat/lon
|
||||
- Pre-computed polar clutter grid (range × bearing bins) per
|
||||
fixed radar location
|
||||
- Line-of-sight shadow mask per radar location
|
||||
Thread 1 only after init; no mutex required.
|
||||
|
||||
LandClutter (Thread 1)
|
||||
Queries TerrainMap to generate clutter returns for each scope.
|
||||
Called once per full sweep rotation, not once per frame.
|
||||
- Marine A-Scope: produces amplitude samples along the current
|
||||
antenna bearing for injection into the range trace.
|
||||
- Marine PPI / ATC PPI: produces a polar texture (range × bearing)
|
||||
uploaded to the GPU once per sweep period.
|
||||
|
||||
TERRAIN MATERIALS AND RCS
|
||||
|
||||
Each terrain cell is classified as one of four materials. Normalized
|
||||
@@ -1558,7 +1483,7 @@ TERRAIN PREPROCESSING
|
||||
|
||||
==================================================================
|
||||
|
||||
All three raw terrain sources are processed in a single pass by the
|
||||
All four raw terrain sources are processed in a single pass by the
|
||||
offline tool terrain_preprocess, which writes ready-to-use binary grids
|
||||
to map/lidar_processed/. Must be run before first launch and re-run
|
||||
whenever TERRAIN_BBOX_* or TERRAIN_PROCESSED_CELL_DEG constants in
|
||||
@@ -1618,7 +1543,7 @@ PIPELINE (runs in order)
|
||||
shadow_boat_NNN.u8 uint8 visibility masks for boat waypoints;
|
||||
NNN = zero-padded waypoint index
|
||||
terrain_meta.json grid dimensions, lat/lon origin, cell size,
|
||||
checksums for all three source files,
|
||||
checksums for all four source files,
|
||||
processing date,
|
||||
boat mask waypoint lat/lon list
|
||||
|
||||
@@ -1650,7 +1575,7 @@ BOAT SCENARIO
|
||||
|
||||
==================================================================
|
||||
|
||||
The boat scenario (scope 5 — Police Patrol Boat PPI) simulates a Bellingham
|
||||
The boat scenario (scope 6 — Police Patrol Boat PPI) simulates a Bellingham
|
||||
Police Department patrol vessel making its waterfront patrol. The radar is a
|
||||
6 kW professional open-array unit (1.9° beamwidth), not the same hardware as
|
||||
the fixed coastal marine radar. The radar origin moves with the boat every sweep.
|
||||
@@ -1707,43 +1632,6 @@ BOAT NAVIGATION SIMULATION (Simulator, Thread 4)
|
||||
On reverse-loop: flip traversal direction at each end.
|
||||
5. Store updated state in BoatNavigator; return to TrafficCop on poll.
|
||||
|
||||
SIMULATED SMALL TARGETS
|
||||
|
||||
The Simulator generates two categories of small targets for the patrol scope:
|
||||
|
||||
Scripted paddleboarder:
|
||||
A single stand-up paddleboarder drifts slowly across the ferry departure
|
||||
lane on a fixed looping path (~0.5 kt, random drift added). RCS set to
|
||||
BOAT_SUP_RCS_M2 (default 0.2 m²). This target also appears on the fixed
|
||||
Marine PPI scope (same Bellingham Bay coverage area, same target pipeline).
|
||||
|
||||
Random kayakers:
|
||||
BOAT_RANDOM_KAYAK_COUNT (default 2) kayaks wander within a defined zone
|
||||
near the ferry terminal and harbor mouth. RCS set to BOAT_KAYAK_RCS_M2
|
||||
(default 0.4 m² — slightly larger than SUP due to hull and occupant).
|
||||
Random targets also appear on the fixed Marine PPI.
|
||||
|
||||
These use the same radar equation path as all other targets; the low RCS
|
||||
values naturally produce faint, intermittent blips in any sea state, which
|
||||
is the exhibit's intended behavior. No special-casing required.
|
||||
|
||||
Settings.h additions for small targets:
|
||||
BOAT_SUP_RCS_M2 0.2 — stand-up paddleboard + paddler RCS (m²)
|
||||
BOAT_KAYAK_RCS_M2 0.4 — kayak + occupant RCS (m²)
|
||||
BOAT_RANDOM_KAYAK_COUNT 2 — number of random kayak targets
|
||||
BOAT_KAYAK_ZONE_LAT/LON — bounding box for random kayak positions
|
||||
|
||||
SHARED STATE ADDITIONS
|
||||
|
||||
SharedRenderState new fields (all under Mutex A):
|
||||
float boatLatDeg = 0.0f (set from JSON WP0 at startup)
|
||||
float boatLonDeg = 0.0f
|
||||
float boatHeadingDeg = 0.0f
|
||||
float boatSpeedKts = 0.0f
|
||||
char boatZone[64] = "" — zone label, copied from JSON waypoint
|
||||
bool boatModeActive = false — set TRUE by ScopeManager when BoatPPIScope
|
||||
active, FALSE for all other scopes
|
||||
|
||||
TARGET PROJECTION FOR MOVING RADAR ORIGIN
|
||||
|
||||
For fixed scopes, target positions are projected from a known constant origin.
|
||||
@@ -1801,7 +1689,6 @@ TERRAIN CLUTTER AND BREAKWATER SHADOWS
|
||||
|
||||
V1 GEOMETRY SCOPE (open water only — marina deferred)
|
||||
|
||||
Vector features needed from NOAA ENC 18424 for the v1 patrol route:
|
||||
- Outer shoreline of Bellingham Bay
|
||||
- Squalicum Harbor outer breakwater (solid, strong return, shadow-caster)
|
||||
- Ferry terminal structure (Bellingham Cruise Terminal area)
|
||||
@@ -1811,58 +1698,36 @@ V1 GEOMETRY SCOPE (open water only — marina deferred)
|
||||
Pacific / Waterfront District structures are deferred until the patrol
|
||||
route is extended into those areas in a future version.
|
||||
|
||||
==================================================================
|
||||
|
||||
FILE LAYOUT (COMPLETE — including additions)
|
||||
IMPORTANT NOTES ON IMPLEMENTATION
|
||||
|
||||
==================================================================
|
||||
To facilitate debugging:
|
||||
|
||||
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_boat_ppi.h / scope_boat_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)
|
||||
terrain_map.h / terrain_map.cpp — DEM load, shadow mask, polar clutter
|
||||
grid; read-only after init, Thread 1
|
||||
land_clutter.h / land_clutter.cpp — per-sweep clutter arrays for A-scope
|
||||
range trace and PPI clutter texture
|
||||
terrain_preprocess.cpp — standalone offline preprocessing tool;
|
||||
separate CMake target; links GDAL only;
|
||||
NOT part of main radar binary
|
||||
settings.h — all constexpr constants; no .cpp
|
||||
1. All p7 persistent stuff should be in one shader; with uniforms that are set by
|
||||
the settings.h file for time of decay and anything else to facilitate debugging
|
||||
The p7 persistent shader itself shall be able to be turned off by way of the settings
|
||||
file. This would allow debugging of the strike (blue) data for each scope.
|
||||
2. The blue strike activity (prior to persistence) should have a debugging variable
|
||||
in settings.h so I could do a persistence evaluation by my eyes without the persistence
|
||||
shader
|
||||
3. each scope shall have its own shaders for the target activity (what is struck in
|
||||
the blue color on the screen). This will allow debugging. Note that these shall
|
||||
have on/off toggles.
|
||||
4. The three land features (shoreline, terrain, and lidar) should each have their own shaders
|
||||
to facilitate debugging. Each of these shaders should be turned off and on via settings in
|
||||
the settings.h file so that I can try each one one at a time.
|
||||
|
||||
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
|
||||
C++ files for the CPU should be divided as follows:
|
||||
|
||||
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
|
||||
terrain_clutter.vert / terrain_clutter.frag — polar clutter texture overlay
|
||||
on PPI; P7-compatible decay;
|
||||
bearing offset rotation uniform;
|
||||
u_radarOffsetM vec2 for boat origin
|
||||
1. Programs that feed the shaders for each scope
|
||||
2. Receiving program (the traffic cop) for handling targets for each raspberry pi as well as
|
||||
the simulator.
|
||||
3. The simulator
|
||||
4. Initialization of the display
|
||||
5. Loading the shaders
|
||||
6. handling controls from keyboard for each scope
|
||||
7. Each scope's general operation including targets, graticules, max range,
|
||||
8. The code (now stubs) that handles input from a real control panel with knobs.
|
||||
|
||||
|
||||
DO NOT CODE ANYTHING
|
||||
|
||||
Reference in New Issue
Block a user