15 KiB
Introduction:
This is a project for a museum to demonstrate a simulation of a 1950's to 1960's vintage marine radar.
There will be two scopes. An early A Scope and a PPI scope.
The PPI scope will take up the entire right hand side of the display (1 inch margins on top,bottom, and right hand side) and the A Scope will be smaller, located in the center of the left hand side of the display near the left margin.
Please impliment 1 inch margins around both scopes. I am getting them cut off
Display should be whole screen. An escape, possibly with the escape key needs to be provided to exit the program and go back to shell.
We have to simulate everything as we are not allowed to have an actual radar at our location because we are not on the water.
The proposed location of the radar antenna is in the middle of Bellingham Bay on a 100 foot platform. Location is 48.74361448950435 latitude, -122.56466911663048 longitude
Zero degrees on Radar Scope is True North.
The proposed maximum range is 15 miles. Selectable ranges should be 2, 5, 10, and 15 miles
The project will be implemented on a Geekom A8 Max with AMD AI chip R9-8945HS with 32 GB ram
The communications for the SDR radios will be handled by Raspberry Pi 5
The operating system is Linux (Ubuntu) Details:
Distributor ID: Ubuntu Description: Ubuntu 25.10 Release: 25.10 Codename: questing
The compiler is cpp (Ubuntu 15.2.0-4ubuntu4) 15.2.0
We plan to use the cmake for building.
Here is the directory structure with files already installed:
./shaders ./shaders/CLAUDE.md ./glad ./glad/src ./glad/src/glad.c ./include ./include/glad ./include/glad/glad.h ./include/CLAUDE.md ./include/KHR ./include/KHR/khrplatform.h ./new-claude ./README.md ./CMakeLists.txt ./build ./build/CLAUDE.md ./CLAUDE.md ./.new-claude.swp ./LICENSE ./src ./src/CLAUDE.md
The following classes would be needed:
-
Operation of display; set up of display and any operation that feeds data to the display. This should be in the main context. It cannot wait for data or anything. It would require a mutex for each user sending data.
-
Operator controls. These feed to control data input to the display class using appropriate mutexes. This would also include updating graticules for changing range on the PPI scope and changing range and bearing for the A scope
-
Radar targets from receivers AIS, ADS-B, and UAT
-
Simulated (fake) radar targets
-
Any code needed to process topographical data for the shoreline
Each of these can run as its own thread, but they all have to use mutexes in order to send anything to the display. Perhaps they could be polled by a dispatcher that will tell each one its turn to send data to the display. The simulator will use ads-b and ais and uat received on airspy SDR radios communicating with Raspberry Pi 5 single board computers running linux.
I plan to have a variety of phony targets simulated in addition to those received on uat, ads-b, and ais.
Note that directions shall be true, not magnetic
Note that shoreline data is from NOAA maps
(NOAA provides free ENC (Electronic Nautical Chart) data in S-57 format covering
Bellingham Bay and surrounding waters.)
I prefer to have separate shader sets for each major function to facilitate troubleshooting Major functions:
- A scope radar
- A scope graticule operation
- PPI scope active targets
- PPI scope graticule Bearing marks
- PPI scope graticule range rings
- PPI scope handling of the shoreline using some sort of topographical map
- PPI scope persistence phosphor
- Rain scatter
- Wave scatter
Display colors:
- A Scope is P1 (same as oscilloscope)
- A Scope graticule is incandescent color
- PPI scope active targets including scatters, graticule range rings, shoreline, all p7 phosphor (active blue)
- All persistence (also p7 greenish yellow persistence) for PPI scope active targets including scatters, graticule range rings, shoreline
- PPI scope bearing ring and ticks is incandescent color.
Coordinates:
Please note that all target information furnished to the display be in local coordinates. Local coordinates have center (0,0) at location of radar base at the community boating center. Maximum coordinate size is 6 miles from the center.
Signal strength:
Need to have following fixed signal strength: Size is part of data for some targets (based on AIS and ADS-B data. Use size of boat (usually in feet) expressed in length and width. Use those values in relation of the heading if known. Unknown heading shall assume size is between length and width.
- large ship (over 100 feet) would be bright and blooming slightly
- yachts ( 50 to 100 feet) feet would be bright but not blooming
- sailboats ( 10 to 50 feet) would be medium bright and not blooming
- kayaks and rowboats would be dim
- May consider fading small boats like kayaks and sailboats above 10 miles
Details of each feature:
A scope:
-
Displays range, does not rotate. You must use control to set bearing. Range is horizontal axis and strength of signal is vertical axis. The full range setting is shared with the full range setting of the PPI scope
-
Graticule is tricky. In the day, the operator would have a stack of graticules for each range setting. To fake this out, We could have the graticule appear to move up and out and the replacement graticule move in and down in place. The operator takes them out from a slot above the scope and inserts the replacement through the same slot. All these graticules are lighted with incandescent colors. Graticule should have vertical lines for each range and a horizontal line at the bottom. Left of the screen you have the words "SIGNAL STRENGTH" and bottom of the screen you have the words "RANGE" Movement of graticles would be a bit slow and erratic (maybe about 10 seconds)
Note on screen update vs pulse repetition frequency. We need to be careful since we have no control of the display update frequency and need to do whatever is needed to reduce aliasing or flickering
PPI Scope active targets
- Active boats/planes; brightness determined by size as noted above
- Blue
PPI Scope range rings
- blue (dim)
- These change if operator changes max range
PPI Scope cursor (In the day, this was a moveable plastic overlay on scope, back lit by incandescent lamp. We need to simulate this. Movement of this is via the Range and Bearing controls cursor consists of flat line for range and box for bearing.
PPI Scope Bearing ticks and ring
- Tick mark every degree
- 0 degrees is top of display
- Degrees count clockwise.
- Use text for every 10 degrees, but text on outside of ring.
- Have ring around tick marks
- 2nd ring around the text marks
Controls:
Here are the controls that I am proposing
- Intensity
- Focus
- Astigmatism
- Range selection (for both a scope and ppi scope) for maximum range. Changes range rings on ppi and changes graticule selection on A scope
- Sensitivity
- Sensitivity time control STC / sea clutter
- Bearing A scope: which in the old days uses a servo motor to rotate the antenna. Feedback was with mechanical numbers. I am proposing to use a small USB digital display; Size should be no larger than 1 by 3 inches. PPI Scope: This control can also be for the ppi cursor.
- Magnetron tune
- FTC / Rain Clutter
- Off-centering (two controls; one for each axis)
- Graticule brilliance
- Reset (in case kids really mess things up)
- Pulse length selection (short pulse for better range resolution, long pulse for better sensitivity at distance; operator selectable)
- Pulse repetition frequency
(Please suggest other controls I may have missed.)
Now, for controls, the tentative approach is to use encoders (that do not have end stops so they cannot be broken by visitors at the museum) I will need help on how to implement them. I am guessing a few Raspberry Pis to handle the encoders. I am thinking of encoders that have one common terminal and a clockwise pulse terminal and a counter clockwise pulse terminal.
Let's do this like this. The control handling will be a different class and run as a separate thread from the display. Each control function will have a parameter for how many pulses received and in what direction. That would be permanent.
Temporary code necessary for changing control selection and value via the keyboard until I get the necessary hardware for the controls.
Also please note that this will need to be flexible as encoders can be expensive, especially robust ones that kids cannot break.
Text Rendering:
Use freetype fonts libfreetype6:amd64
Communication:
All I know now is that I plan to use a combination of Raspberry Pi 5 and an Airspy SDR for each of ais, ads-b, and uat. UAT (978 MHz) and ADS-B (1090 MHz) are different frequencies and require separate SDRs, but a single Raspberry Pi 5 is powerful enough to run both dump1090 (ADS-B) and dump978 (UAT) simultaneously with two SDRs on its USB ports. AIS requires a separate Raspberry Pi with its own SDR tuned to VHF 161/162 MHz.
Each Raspberry Pi will act as a server fielding requests from this program.
Each Raspberry Pi is a separate instantiation of a class called RemoteTargetSource. Those classes will use a common target data structure:
- double longitude
- double latitude
- std::string vessel_name
- std::string registration
- float length_meters
- float beam_meters
- int vessel_type (AIS type code; aircraft type for ADS-B/UAT)
- uint32_t mmsi (AIS unique identifier; ICAO hex address for aircraft)
- float course (course over ground, degrees based on true north)
- float speed (speed over ground, knots)
- time_t timestamp (time of last fix; used to age out stale targets)
- float altitude (meters; 0 for surface vessels)
- TargetType type (enum: vessel, aircraft, etc.)
The RPi communication thread blocks on a socket read until data arrives, then writes to a shared target queue protected by a mutex and signals a condition variable. The main application consumes from that queue. Prefer TCP.
The Raspberry Pi code will live in a separate git repository with its own CLAUDE.md and its own CMakeLists.txt, since it targets a different architecture (ARM) and has a different toolchain and dependencies. Do not mix it into this repository hierarchy
NEW suggestions =======
-
The a scope bearing must not follow the rotating sweep on the ppi scope. The A scope during the time they were popular before the ppi scope used a manual control to set the bearing. The bearing setting uses a servo motor to rotate the dish antenna to the bearing desired by the operator. We need to simulate that by not a scope not to follow the bearing shown on the ppi scope. This bearing must be controled by control 7.
-
Add two more controls; Range for ppi scope cursor and Bearing for the PPI scope cursor
-
Pleae add a small window under the A scope to show the setting of the A scope bearnig.
-
Temporary: Have the bearing for a scope set to the location of one of the current targets.
-
Have the cursor on the ppi scope follow one of the targets and not move around.
New update 1
- I notice that the height of the pulse on the A scope seems to be going up and down in sync with the ppi scope rotating.
- Add a range figure in the small box under the A scope
- Have the a scope graticules change a little faster
- it appears that the cursor range ring sometimes appears outside the boundary of the scope
New update 2
- Add small text window above that a scope that says "Operator Manually Changing Range Graticule" This appears only when the graticule is changing
New update 3 (This involves the four fake targets.
We need to change the timing of the operator as there is no real controls nor real operator and I want to show a video of the radar operations on a video I will take on my phone.
Fist, make the target brighter so they can be seen on a smartphone video
2nd, make sure the height of pulse on a scope should reflect the sterength of target
- As the operator turns the bearing crank for the a scope, the target must gradually gets bigger as the bearing gets close to that of the target they are moving to and then gets smaller as the operator moves the crank from that target and moves on.
Target 1. One mile north of radar. A strong signal (large yacht) Target 2. One mile south of radar. A bit weaker, (20 foot lobster boat) Target 3. 1/3 mile northwest of radar. (person on paddle board) Target 4. 3/4 mile southwest of radar. (20 foot metal workboat)
Maintain current target speeds and headings.
Let cycle repeat until the application exits via keyboard escape key
Adjust speeds and heading for boats that have been assigned closer
for target 3, make the target on A scope very small, but still visible and on ppi scope, barely visible.
Cycle of operator
-
set range to maximum on both a scope and ppi scope so they can watch entire bay
-
Wait 5 seconds
-
change range of both scopes to 2 miles so they can look closer to targets
-
Wait 1 second
-
In operating range and bearing, make the movement of the cranks by a human; not perfect automatic cranking. Combination of small random jitter/wobble; occasional slight overshooting and correction; variable speeed 5a. Move the cursor to the Target 1. Also rotate a scope bearing to that of Target 1
-
wait 5 seconds
-
Move cursor to target 2 on ppi and bearing on a scope to bearing of target 2
-
wait 5 seconds 8a. change range to 1 mile. and wait 5 seconds.
-
Move cursor to target 3 on ppi and bearing on a scope to bearing of target 3
-
Wait 5 seconds
-
Move cursor to target 4 on ppi and bearing on a scope to bearing of target 4
-
Wait 5 seconds move range to maximum for 5 seconds and then go to step 1
NOTE on my plan for coding -
I want to test and debug the code feature by feature.
-
I do not want any code created on features until I am ready.
Order of testing features.
- General initialization and set up basic boundaries of the two scopes on the screen. No features on each scope yet.
- Edge graticule on ppi scope (Bearing ticks and numbers)
- Replaceable graticule on A Scope. Have it update for each different range and hold for 5 seconds for each range
- PPI scope range rings; both active display and persistence display - test for each range settings; hold for 5 seconds each
- PPI scope active target operation, as well as persistance. Create
four fake targets: one small, one large and two very large with
- target 5 miles north of radar, 100 feet long heding 1 knot south head on, width of target is 20 feet.
- target 5 miles south of radar, 20 feet long, 5 feet wide headng away at 20 knots
- 6 mile east 30 feet long, heading north about 30 knots, full side view to radar
- 6 mile west 100 feet long, heading south 5 knots, full side view
- PPI scope cursor - test by slowly changing range and bearing
- PPI scope weather noise - test by changing noise level slowly
- PPI scope waves noise - test by changing noise level slowly
- PPI scope handling of shoreline - test by running for a few seconds
========================================================
Generate code for testiong feature 1,2,3,4,5,6 nly;