10 KiB
Hello, this is a project to create a simulation of a vintage marine radar before the days of digital electronics and we had to use a cathode ray tube with p7 phosphor
I plan to use c++ and opengl and shaders for access to a GPU. I am in ubuntu 25.10.
I wish the c++ be arranged as follows:
All code in the src subdirectory
The main program and the binary would be called radar-simulation.
The shaders are in the shaders subdirectory
We need to use classes. For now, I can see one class for all things having to do with putting stuff on the screen. Includes initializing OpenGL and put up two windows on the screen. One is for the PPI display, locate on the right hand side of the screen with margins for the sides of the monitor. The A Scope is a smaller window on the center of the left side of the display.
All inputs to either display will be performed in that class. Data fields for the methods of that class should be put into a header file in the headers directory.
Another class would be used to communicate with the raspberry pies that will obtain data from the ais and ads-b software defined radios. This is for purposes of adding targets. Marine radar can pick up low flying targets plus I may (in the future) add an option for a vintage air traffic control radar with precision approach radar, but not now.
Another class would be used for simulating targets, like for example a sailboat regatta race.
Classes:
-
Anything to do with sending anything to the display. Needs to be on the same thread as the main function
-
Communications with outside sources; ais and ads-b for targets
-
Operator controls
-
Internal target simulation
-
All of these have to use mutex for anything going into the display class
There may be more classes TBD
The platform is a Geekom GEEKOM A8 Max, AMD Ryzen 9 8945HS 5.2GHz 32GB RAM
Now here is the overall project and proposed architecture
This project is to simulate a period 1950 to 1960 marine radar with a crt p7 phosphor for the ppi scope and a p1 phosphor (this is oscilloscope phosphor) for the a scope. The ppi scope will be on the right side of the screen and the a scope will be on the left hand side of the screen.
The maximum range should be enough to cover the entirity of Bellingham bay as seen from the dock of the Community Boating Center.
Use one window with viewports covering the entire screen. For development, F11 toggles fullscreen, Escape exits the program entirely.
The radar is fixed at the Community Boating Center dock in Bellingham, Washington. That location is 0,0 in local Cartesian coordinates. North on the radar display is true north.
GPS coordinates from targets are converted to local Cartesian coordinates referenced to this origin using a flat-earth equirectangular projection, which is accurate enough for harbor radar ranges (0-24 nautical miles):
x = (lon - origin_lon) * cos(origin_lat) * R y = (lat - origin_lat) * R
Where R is Earth's radius (6,371,000 m). Result is in meters from the origin. No need to be concerned with spherical or vector geometry at these ranges.
Coordinate conversion belongs in the main application, not in the Raspberry Pi communication class. The RPi class delivers raw lat/lon; the main app converts to local Cartesian. This keeps the RPi code simple and means a change to the radar origin only requires changing one place.
Notes for controls the user can play with
Here are the controls that I am proposing
- Intensity
- Focus
- Astignatism
- Range selection (for both a scope and ppi scope)
- Sensitivity
- Clutter elimination (I believe only ppi scope; please research)
- There is some sort of control having to do with the mangatron but I don't know what its called and what it does.
- Bearing (only for a scope) which in the old days uses a servo motor to rotate the antenna. I don't know what form of feedback (text on the screen or mechanical numbers on a dial)
- Magnetron tune
- Anti clutter rain (ftc)
- Will not need heading (this will be a fixed radar location for the harbor master or lifeguard
- Off-centering
- 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)
(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 impliment them. I am guessing a few raspberry pies to handle the encoders. I am thinking of encoders have one common terminal and a clockwise pulse terminal and a counter clockwise pulse terminal.
Let 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.
Shaders:
Each of the following is a separate shader set. Keeping them separate is intentional for easier debugging — each layer can be disabled, modified, or tested independently without affecting the others. At least the following shader sets
- PPI targets, current, in white blue
- clutter for rain, in white blue
- clutter for waves, in white blue
- graticule for PPI for bearing ticks, numbers, and range rings that will change with range selection
- Have operator switch graticules on the vintage a scope
- Shoreline; tricky as shoreline has hills.
- This may be overkill, but something for notable buildings and docks. The curved south bay trail and taylor dock comes to mind, also the squalicum marina and the breakwaters.
Details for A scope (predecessor to the PPI scope)
The a scope will have pulse amplitude on the vertical axis and the range on the horizontal axis. There will be a graticule for the a scope. This will show range markings. In the day, the operator would physically change the graticule overlay. What we can do is to electronically change the overlay and put a brief message saying operator changes the graticule. graticule lit with an equivalent color. Horizontal is range, vertical is strength of the return blip. The phosphor of the A scope is green, similar to P1, which was used on oscillosopes.
On vintage a scope, the operator changes the graticule when range is changed. Suggest briefly display the message "operator inserts new graticule manually". If possible for realism, have the old graticule move up and off the screen and then the new graticule move onto and down the screen until it is in place, simulating the operator changing the graticule.
There are as of now, no shaders nor any c++ files created yet
Details for PPI display:
Located on right hand of the screen. Put 1/2 inch margins on the right and top and bottom.
The PPI display will need shaders for the following:
-
Active radar target echos (blue white phosphor) Have different brighness for size and blooming for larger sizes
-
Graticule (warm incandescent color, it was a plastic overlay lit with lamps. Does not get included with persistant phosphor. Can change if the operator changes the range. Have ticks for bearing; each degree. Every 10 degrees have a small text label, put these outside the ring. No range rings for now. Have to figure out how that is done with vintage radars. Perhaps you can suggest. Does operator have to change the plastic graticule when they change the range?
-
facility to change clutter, rain and waves. Immediate is blue white same as targets
-
facility to include shore lines. This will change with range settings. If possible, can we include docks and tall buildings? Immediate is blue white same as targets.
-
Persistence (green yellow) for targets, clutter, and shore lines. Persistence uses ping-pong framebuffers with a decay multiplier each frame. Target persistence is approximately 3 seconds, matching the P7 phosphor decay to 10% brightness.
-
The pulse repetition frequency (PRF) is a simulation parameter. At 24 RPM antenna rotation, one full sweep takes 2.5 seconds and produces ~150 frames at 60 fps — smooth with no aliasing concern.
Communication:
All I know now is that I plan to use a combination of raspberry pi 4 and a 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 4 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)
- 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.
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.
Is is possible to create the softward with the following temporary files:
- leave all controls to default; center for everything.
- create five fake targets, at random locations within the range of the radar, moving randomly at normal boat speeds. Us variety of sizes
Have it able to run without the controls and the Raspbery pi stuff as I need to purchase the raspberry pi 5 units
Just evaluate and give estimate on amouint of time/tokens and about the total tokens, time, and number of lines of code
Please do not generate code. Just comments.