229 lines
10 KiB
Markdown
229 lines
10 KiB
Markdown
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:
|
|
|
|
1. Anything to do with sending anything to the display. Needs to be on the
|
|
same thread as the main function
|
|
|
|
2. Communications with outside sources; ais and ads-b for targets
|
|
|
|
3. Operator controls
|
|
|
|
4. Internal target simulation
|
|
|
|
5. 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.
|
|
|
|
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
|
|
|
|
1. Intensity
|
|
2. Focus
|
|
3. Astignatism
|
|
4. Range selection (for both a scope and ppi scope)
|
|
5. Sensitivity
|
|
6. Clutter elimination (I believe only ppi scope; please research)
|
|
7. There is some sort of control having to do with the mangatron
|
|
but I don't know what its called and what it does.
|
|
8. 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)
|
|
9. Magnetron tune
|
|
10. Anti clutter rain (ftc)
|
|
11. Will not need heading (this will be a fixed radar location for
|
|
the harbor master or lifeguard
|
|
12. Off-centering
|
|
13. Graticule brilliance
|
|
14. Reset (in case kids really mess things up)
|
|
15. 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
|
|
|
|
1. PPI targets, current, in white blue
|
|
2. clutter for rain, in white blue
|
|
3. clutter for waves, in white blue
|
|
4. graticule for PPI for bearing ticks, numbers, and range rings that
|
|
will change with range selection
|
|
5. Have operator switch graticules on the vintage a scope
|
|
6. Shoreline; tricky as shoreline has hills.
|
|
7. 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.
|
|
|
|
The graticule was illuminated with #47 incandescent dial lights, we need to have that
|
|
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:
|
|
|
|
1. Active radar target echos (blue white phosphor)
|
|
|
|
2. 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?
|
|
|
|
3. facility to change clutter, rain and waves. Immediate is blue white same as targets
|
|
|
|
4. 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.
|
|
|
|
5. 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.
|
|
|
|
6. 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:
|
|
|
|
1. double longitude
|
|
2. double latitude
|
|
3. std::string vessel_name
|
|
4. std::string registration
|
|
5. float length_meters
|
|
6. float beam_meters
|
|
7. int vessel_type (AIS type code; aircraft type for ADS-B/UAT)
|
|
8. uint32_t mmsi (AIS unique identifier; ICAO hex address for aircraft)
|
|
9. float course (course over ground, degrees)
|
|
10. float speed (speed over ground, knots)
|
|
11. time_t timestamp (time of last fix; used to age out stale targets)
|
|
12. float altitude (meters; 0 for surface vessels)
|
|
13. 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.
|
|
|
|
Right now, I just want to make sure that the structure is okay and that the
|
|
CMakeLists.txt looks okay. I am not ready to ask you to create any code
|