Files
updated-radar/CLAUDE.md
2026-05-17 20:31:28 -07:00

641 lines
30 KiB
Markdown

This is a project for a museum to demonstrate a simulation of a 1940's to 1960's
vintage radar, including the Chain Home radar from early World War 2, marine radar
at a marine traffic control station,
and marine radar on a boat.
The project will be implemented on a Geekom A8 Max
32 GB RAM
AMD Ryzen 9 8945HS w/ Radeon 780M Graphics
We need to render to the Radeon 780M Graphics GPU
Tech Stack: We are using C++20, OpenGL 4.3 Core, GLFW, GLAD, FreeType, GDAL (libgdal-dev)
Compiler: is g++ (Ubuntu 15.2.0-4ubuntu4) 15.2.0
FreeType is the text type we use
GDAL is used for reading the LIDAR/ENC chart files
GLFW (graphics library framework) open-source, multi-platform library used to manage windows
GLAD (Multi-Language GL/GLES/WGL/GLX Loader-Generator) Loads the pointers to
OpenGL functions (like glDrawArrays or glCompileShader)
PostgreSQL is installed. Database: radar. User: radar. Password: radar.
User has full privileges on database radar. Table is target_data.
Operating system details:
Distributor ID: Ubuntu
Description: Ubuntu 25.10
Release: 25.10
Codename: questing
Use cmake for building.
[DIRECTIVE: GPU ROBUSTNESS PROTOCOL]
Debug Callback: Enable GL_DEBUG_OUTPUT and glDebugMessageCallback
to capture driver-level warnings and errors in real-time.
I will be using SSH from Windows to write code and check with claude.
You may compile the code during an SSH session.
Please do not try to run the code during SSH session.
I will run the code while physically using the Geekom.
Please add MIT license header to each file
Please add Author: Mark Allyn to each file
Use snake_case for variables and PascalCase for classes
use #pragma once
Use // for single line comments
use /* */ for multiple block comments spanning multiple lines
avoid using auto
Please use a settings.h file for defines and variables that I can
change and do a simple re-compile instead of having the ai re write the
code. This is for debugging. For example, I may want to disable the p7 persistance
to troubleshoot the actual target processnig before it goes to persistance,
disable the land and terrain so that I can see the targets alone. Things like
that.
Summary of project:
This is a museum exhibit displaying and providing some interaction
of vintage 1940's, 1950's, and 1960's radars. A key objective is to
provide interaction with and viewing of radars from that era.
The name of the application (the name of it's executable file) shall be
radar_simulator. Therefore, if you are in the directory in which the executable
is compiled, which in this case would be the build subdirectory of the project
directory, you would type ./radar_simulator, or use a full path name
of {PROJECT_DIR}/build/radar_simulator.
In the CMakeLists.txt, plese use the name radar_simulator for the add_executable call.
There will be three main areas of the screen. On the right hand side will be the radar
scope.
On the left hand side of the screen will be a text description of the scope as well
as the controls of the scope and keyboard keys for each control. This text will be
white while the control labels will be red and the keystrokes will be in pink.
At some point, pending a decision with the museum, we may purchase components to mount the controls on a panel. Until that is done, the controls will be on the keyboard.
On the right hand side of the screen, below the scope, would be a text status window, showing current
maximum range, range, and bearing as appropriate to which scope we are using as well as the identification
of the scope that we are using.
Suggest that we use glViewport to define the left-hand text area, the main scope,
and the yellow status bar. This allows you to render the scope with its own coordinate
system while keeping the text fixed. Along with glViewport, use glScissor and glEnable(GL_SCISSOR_TEST)
Below the scope will be a text status window. This text will be yellow
Scopes in the right panel
1. Introduction of Exhibit (Explanation of the project on the left hand text panel.
2. A-scope for Chain Home Radar in the 1940's (first radar and could be tricky)
3. A-scope for marine radar in the 1940's (Before PPI radar); was a bit tedious to operate
4. PPI scope for marine traffic control (uses beam sweeping in all 360 degrees of
rotation); Easier to use than a scope
5. PPI scope on board a boat. Shows how movement of a boat affects the radar display
Please note that these scopes will not appear all at once. The selection of which scope
the visitor sees is done by pressing a forward control and a reverse control to go around
the loop of scopes. The first display when the system is turned on or booted up is the
Introduction of the exhibit.
Before going, we must point out the target information handling which will
affect all scopes.
====================================================================================
TARGET DETAILS
Targets for this project will come from two sources:
1. Raspberry pis communicating with an AIS receiver for boats and
an ADS-b receiver for aircraft
2. An on-board simulator that will simulate targets using an internal
table of target information in the postgresql database.
Please note that the components for the AIS and ADS-B target
handling are not yet available, thereby the programming for that
souce will not be defined at this point.
Please note that all targets, both from the AIS, ADS-b, and and the
on board simulator will all follow the following C data structure:
struct target_data_structure {
double target_longitude;
double target_latitude;
std::strong vessel_name; // will be null for no available name
std::strng registration; // will be null for no registration
float length; // in meters
float beam; // in meters
int vessel_type; // AIS type code or aircraft type
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, but 0 for boats
TargetType type; // type of target; vessel or aircraft
};
Of this structure, only the following structure needs to be submitted to the
shaders for this project (this may change later if we want to simulate new
radars that have the capability to show detailed information on each target.
struct target_data_to_shader_structure {
double target_longitude;
double target_latitude;
float length;
float beam;
float course;
float altitude;
time_t timestamp;
};
The section of the project's code for handling targets coming in from the
raspberry pis as well as the simulator will be called the traffic_cop.
The traffic cop will run on a different thread than the software that directly
feeds the shaders. Mutexes shall be used to control feeding data to the software
that feeds the shaders.
This traffic cop will receive the targets and peform the following:
1. Check to see if the target is beyond the maximum range of the radar being used;
disccarding those beyond the maximum range.
2. Check that aircraft if below 40 meters in altitude for marine type radars;
marine chain home and all ppi marine radars. If not, that target shall
be discarded. Convert the incoming target data structure to that
to be used by the shaders.
3. Assert mutex to get permission to provide an array of target information
for the shaders.
4. Copy the array into the target data structure for the shaders.
5. Clear the mutex.
Note suggestion that target data be given as a batch once every sweep of the
beam through the 0 degree (top) of the scope.
Note that the construction of the simulator will be discussed later in this document.
=============================================================================
Please note that the first iteration of the project will have only minimal controls.
This is a suggestion I got after meeting with the museum staff. Perhaps later we may
add more controls.
Also, please note that the state of the controls of each scope is independent of any
other scope. Furthermore, the controls will reset when a scope is exited and then re-entered.
Controls to affect the behavior of the scopes; (these first implemented using keyboard
strokes; later when and if physical controls are completed, the keyboard controls will be removed)
These controls will affect the state variables and the uniform variables of the shaders.
Please note that identical controls will be the same keyboard strikes or physical controls for all scopes.
=======================================================
Overall control information
These are knobs on the panel once that is built. Keyboard keys until then
1. Intensity - scope overall intensity - Keyboard 3 is lower; 4 is higher
2. Receiver Sensitivity - signal intensity - Keyboard 5 is lower; 6 is higher
3. STC Sensitivity - sensitivity for closer in targets which can overwhelm
overall sensitivity - keyboard q for lower; w for higher
4. STC Range - range to which sensitivity to closer targets is effective
keyboard e for lower; r for higher
5. Radiogoniometer knob for Chain Home; keyboard t for left turn; y for right turn.
6. Maximum Range for all scopes except for chain home, which is fixed. This control
will not operate for Chain Home. These maximum
range selections will be defined for each scope; If you try to go beyond the stated
maximum ranges, the control will have no effect; note that the default maximum range would
be the highest for that scope; keyboard u for lower; i for higher
7. Range Cursor (for ppi scopes, not for a scopes) keyboard o for lower; p for higher
8. Bearing Cursor (for all ppi scopes; not for a scopes)
keyboard a for counterclockwise s for clockwise
9. Bearing for Marine A Scope. This is not for a cursor, but this operates the motor
that revolves the antenna unit keyboard d for counterclockwise and f for clockwise
Notes; I am maintaining control separation between radiogon, marine a scope bearing, and ppi bearing.
However, when I make the control panel, those will be combined as one physical knob with three
labels, chain home radiogon, marine a scope antenna rotation, and ppi scope bearing to save on
hardware; the same physical control can be used for multiple scopes.
Note that the range cursor is different from the maximum range. Maximum range is the maximum
radar range setting and range cursor is the range portion of the ppi cursor.
=========================================================================
RADAR EQUATION (for all radars; note that is different for chain home)
Lets start here by mentioning the radar equation that sets the perceived strength of any
radar echoes, no matter what kind of radar (a scope and ppi scopes)
Summary of radar equation:
The fundamental radar equation describes how much power returns to a radar system
after bouncing off a distant target.
Physically, it follows a "round-trip" journey
of energy: the radar transmits a signal that spreads out as a sphere (losing strength
by the square of the distance, $R^2$), hits a target that reflects a portion of that
energy (the Radar Cross Section, $\sigma$), and that reflection then spreads out
again as a second sphere on its way back (losing another factor of $R^2$).
Mathematically, this results in the received power being inversely proportional to the fourth
power of the distance ($1/R^4$), meaning that if a target moves twice as far away,
the returning signal becomes 16 times weaker. To calculate the final received power
($P_r$), you multiply the transmitted power ($P_t$) by the antenna's ability to
focus that energy (Gain, $G$) and its physical size (Aperture, $A$), then factor
in the target's reflectivity ($\sigma$) and the wavelength of the signal ($\lambda$),
all while dividing by the spreading losses $(4\pi)^3 R^4$.
$$P_r = \frac{P_t G^2 \lambda^2 \sigma}{(4\pi)^3 R^4}$$
Since we had four distinct radar types, and each one has it's own hardware loop gain
that does not change, we can set that as a constant in each radar's target handling shader set.
========================================================
Individual scope informations
1. Introduction to project. Just text. No scopes. Only one control for entering
scope selection loop. Keyboard keys 1 for forward; 2 for backward.
This is a loop type selection If you are in the Introduction, and you touch
keyboard 2 for backward, you would go to scope 5, PPI Scope for a boat.
=================================================================
To control the extent of the selection of the scopes by the user, there sill be
a selection of what scopes are to be avaiable to the museum visitor. This
will enable the museum to select what scopes will be available and what scopes
will not be available at all. A script that will invoke the radar simulator
application will need to pass parameters to indicate what will be available.
For example, if the script were to call:
{PROJECT_DIR}/build/radar_simulator chain_home marine_ascope marine_traffic_ppi
then only the chain_home, marine_ascope and marine_traffic_ppi will be availablel
but the marine_ppi_on_a_boat will not be available.
This feature is needed for troubleshooting but also to allow the museum to control
what is available. For example, if the museum is crowded with large school groups,
then they would only have one scope available; so if they did
{PROJECT_DIR}/build/radar_simulator marine_traffic_ppi
Only the marine traffic control ppi scope will be available and the scope
selection controls will not be operatable.
To be clear, the names of the scopes currently being built are:
1. chain_home
2. marine_ascope
3. marine_traffic_ppi
4. marine_boat_ppi
Startup behavior rules based on argument count:
- No arguments: all four scopes available, Introduction shown first,
navigation keys 1 and 2 are active.
- Two or more scope names: only those scopes available in the loop,
Introduction shown first, navigation keys 1 and 2 are active.
- Exactly one scope name: Introduction is suppressed entirely. The
application launches directly into that scope and stays there.
Navigation keys 1 and 2 are disabled. The public will have no
awareness that any other scope exists. This mode is intended for
large groups and high-traffic museum days where staff want to
dedicate the exhibit to one display without contention.
====================================================================
2. A Scope - sweep on horizontal axis. A pulse will appear for a return. The distance from
the left hand side to the pulse is the range. The height of the pulse is the strength
of the return signal. The bearing is determined by manual control.
The basic controls for both A Scopes include:
Intensity
Sensitivity (the strength of the signal amplification of the
receiver). This has nothing to do with the brightness of the
pulses. This only affects the height of the pulse and the height
of any noise floor.
STC sensitivity; sensitivity for close in targets.
STC sensitivity range; how far shall the STC sensitivity have effect.
Please note that the phosphor (chemical that glows when hit by
electrons in the tube) is green, similar to an oscilloscope. The Hex
for green is #39FF14; there is a short persistance of the phosphor after being
struck by the electron beam. That persistance is about 25 milliseconds and its color
is darker green at about Hex #004400
Please also note that there are no graticules on either the Chain Home a scope nor
the marine a a scope. The only thing on the external plate is the base line (zero signal
which the operator can refer to that is going on (grass, calibration, and signals). It
is an important point of reference. That base line is illuminated on the sides with small
incandescent lamps. It is a different color than the display itself. The incandescent
color is that of the #47 pilot lamp hex #FFB347.
2-1 Chain Home A Scope
==========================================================
Downward PIP and mixing calibration pips with target pips and noise grass
Very important. The Chain Home A Scope is upside down. That is, the baseline
is at the top of the display and noise and distance pips and target blips will
go down.
This is done so that the operator can look at the top of the scope for the
base reference. The cone apearance of a target blip (ristime of a signal due
due to non perfect bursts of radio frequency pulses from the transmitters)
can be measured against the calibration pips.
Also note that the calibration pips, the noise floor, and the target pips
are mixed together before being sent to the deflection plates of the tube.
This is a hardware reality of any CRT A-scope: the deflection plates receive
a single voltage, so all sources must be combined into that one signal.
That means that the three sources are summed together before you see them
on the scope. Remember that zero signal is the reference line at the top.
Importantly, the calibration pips are generated by a crystal oscillator and
injected into the video chain AFTER the receiver gain stage. This means
turning the Sensitivity control up or down does NOT change the height of the
calibration pips — only the noise floor and target echoes are scaled by the
receiver gain. This is true for both Chain Home and the Marine A-scope.
For example, if one of the calibration pips is exactly the same distance as
a target blip, that would look like it is extending the target blip. This was
a known operational hazard; operators were trained to account for it.
For your reference, the work inside the shader may be something like:
/* Simulated Summing Amplifier Logic.
Cal pips are outside the sensitivity multiply because they are injected
after the receiver gain stage in the real hardware. */
float receiver_signal = (noise_floor + target_echoes) * sensitivity;
float total_deflection = receiver_signal + calibration_pips;
// Apply to your downward-hanging baseline
float final_y = baseline_y - total_deflection;
==========================================================================
Because the receiving antennas are very large (about 100 feet), the
operator cannot physically move them.
Therefore, the bearing is determined through a process called radio direction
finding (RDF) using a specialized instrument known as a Radiogoniometer.
The receiver towers (which were separate from the transmitter towers)
featured two sets of dipole antennas mounted at right angles to one
another—essentially one oriented North-South and the other East-West.
The signals from these two perpendicular antennas were fed into a Radiogoniometer
located in the receiver hut. Inside the device there are two fixed coils (field coils)
that were mounted at right angles matching the orientation of the outdoor antennas.
A third coil, the search coil, is mounted on a rotating shaft inside the two
field coils. The operator would physically turn a knob to rotate the search coil.
The relative strength of the signal in each antenna depended on the angle of the
incoming wave. For example, a target directly to the North would produce a maximum
signal in the North-South antenna and zero in the East-West antenna.
The operator would look for a null point (a signal or pip weaker than the noise floor).
At that point, the operator would read the bearing from a calibrated scale attached
to the radiogoniometer knob.
We can simulate the radiogoniometer knob that would affect the null point depending
on the bearing of a target. The museum visitor could experience seeing different
null points for each target. Since we do not have a physical calibrated knob, we
can put the bearing as a text indicator below the A Scope.
The range is 200 miles. That is the only range option for this scope.
RADAR EQUATION STUFF FOR CHAIN HOME
For Chain Home:
Transmitter Power : 500 KW
Wavelength 12 Meters
Antenna Gain 5 dB
Pulse Width 20 microseconds
Beam Width 150 degrees (floodlight)
PRF 25 HZ
Airplane acts as a half wave dipole
Sine based resonance Multiplier in target handling
// Pseudocode for Shader/Logic
float resonance = (targetLength >= wavelength * 0.4 && targetLength <= wavelength * 0.6) ? 1.5 : 1.0;
float final_sigma = base_sigma * resonance;
The 20-Mile Markers: Chain Home used crystal-controlled oscillators to create
fixed reference "pips" every 20 miles. These should be rendered as thin,
vertical spikes that never move, regardless of target sensitivity.
The "Floodlight" Effect: Because the beam is 150° wide, the A-Scope will
show every aircraft in that massive sector simultaneously. The only way to
tell them apart was the range (distance from left) and the Radiogoniometer nulling.
The Waveform Shape: For CH, the pips should be slightly "noisier" than
marine radar. Use a random jitter function in your vertex shader to
simulate the atmospheric noise floor common at 25 MHz.
2-2 Marine A Scope
Utilization of A scope marine was limited to military use prior to PPI scope
invention. An example is British Type 271 radar, introduced in 1941.
Marine radar frequencies allowed the use of much smaller antennas;
dishes or horns. Those antennas would be mounted on the shaft of a servo motor. The
servo motor would be driven by another servo that is attached to the bearing control
knob on the radar console. The bearing is on a calibrated dial on the bearing control
knob.
We can simulate the bearing knob that would affect the simulated pointing of the
dish antenna. The museum visitor could experience seeing different
pips appear as they rotate the antenna toward them. Likewise the pips would disappear
as the antenna is rotated away.
The range is indicated at how far the pip is from the left hand side of the scope which
is the location of the radar transmitter. If the target goes further away,
the pip will move to the right. If the target comes close to you, the pip will
move left.
This pip has a finite rise time as the transmitter starts.
The width is set by the modulator stage in the transmitter.
Following the width, the pip has a finite fall time as the transmitter stops. This
creates a curved waveform; not just a line.
A photograph for this display show no graticule at all. Only range pips formed by an oscillator.
Those oscillator pips are fixed. Range settings do not affect them. There is a baseline at the
bottom, etched in glass, that is side illuminated by incandescent lamps.
Like Chain Home, the Marine A-scope sums noise, calibration pips, and target echoes into a
single signal before the deflection plates — this is a hardware reality of any CRT A-scope.
The calibration pips are injected after the receiver gain stage, so they remain at constant
height regardless of the Sensitivity control. The shader summing follows the same structure:
/* Simulated Summing Amplifier Logic — same pattern as Chain Home.
Cal pips outside sensitivity multiply because they bypass the receiver gain stage. */
float receiver_signal = (noise_floor + target_echoes) * sensitivity;
float total_deflection = receiver_signal + calibration_pips;
// Apply to upward-deflecting baseline (Marine scope is right-side up)
float final_y = baseline_y + total_deflection;
The maximum ranges for this scope are:
1. 1.5 miles; marker pips every 0.25 miles
2. 3.0 miles; marker pips every 0.5 miles
3. 6.0 miles; marker pips every 1.0 miles
4. 12.0 miles; marker pips every 2.0 miles
RADAR EQUATION FOR MARINE A SCOPE
Here are the fixed values (those values that can be declared as
uniforms) for the marine a scope radar. I suggest these for the uniform names
peak_power = 500 KW
wavelength = 10 centimeters
antenna_gain = 30 db
pulse_rep_frequency = 500 hz
horizontal_beamwidth = 2.5 degrees
Now we have some stuff for the settings file:
SYSTEM_TEMPERATURE ($T_s$): Usually 290K; used to calculate the noise floor
NOISE_FIGURE ($F$): A value in dB that determines how much "grass" your
specific receiver adds to the signal.
BOLTZMANN_CONSTANT ($k$): $1.38 \times 10^{-23}$, essential for the thermal
noise part of your simulation.
Now, here is a snippet of pseudo code:
/* Uniform Variables provided by CPU */
uniform float u_AntennaBearing; // Current rotation of knob/motor
uniform float horizontal_beamwidth; // Fixed for the scope (e.g., 2.5 degrees)
/* Logic for each Target (calculated on CPU or in Geometry Shader) */
float angle_diff = abs(target.bearing - u_AntennaBearing);
// Handle the 359 to 0 degree wrap-around
if (angle_diff > 180.0) angle_diff = 360.0 - angle_diff;
// BeamFactor: 1.0 at center, drops to 0.5 at horizontal_beamwidth/2
// This creates the "fade in / fade out" effect as you turn the knob
float beam_factor = exp(-2.77 * pow(angle_diff / (horizontal_beamwidth / 2.0), 2.0));
// Final received power Pr
float Pr = (peak_power * pow(antenna_gain, 2) * pow(wavelength, 2) * target.rcs * beam_factor) /
(pow(4.0 * PI, 3.0) * pow(target.range, 4.0));
3. PPI Scope
PPI stands for Plan Position Indicator
The Core VisualizationThe PPI scope represents the radar antenna as a
central point (the origin).The "Sweep": A radial line rotates 360
degrees around the center, synchronized with the physical rotation of the
radar antenna.Distance (Range):
The distance from the center of the screen to a "blip"
represents how far away the object is.
Bearing (Azimuth): The angle of the blip
relative to the top of the screen (usually North or the front of a ship/aircraft)
represents its direction.
Key Technical ComponentsIf you are prompting an AI to simulate or analyze a PPI,
use these technical markers:Persistence: Older CRT scopes used "long-persistence
phosphors" so that a target would remain visible as a glowing trail
even after the sweep line passed over it.
Range Rings: Concentric circles overlaid on the display to help the operator estimate
distance at a glance.
Strobe/Cursor: A line or marker used to pinpoint the exact coordinates of a specific target.
Mathematical LogicFor an AI to process PPI data, it needs to understand the conversion
from Polar to Cartesian coordinates. If a radar detects a target at distance $r$ and
angle $\theta$, the position on the 2D screen $(x, y)$ is calculated as:$$x = r \cdot
\sin(\theta)$$$$y = r \cdot \cos(\theta)$$.
Why it differs from other ScopesTo clarify for the AI, distinguish it from the A-Scope: A
simple 1D graph showing "Energy vs. Distance" (looks like an EKG).
Please note that the P7 phosphor for vintage PPI radar has several colors; the
following table describes this:
Suggested Simulation Table for the P7 PPI phosphor
1. Excitation 0 (flash) Bright Blue hex #A0CFFF - note this is active electron beam
2. Immediate blue - 1 ms duration after Excitation; Blue hex #1010FF - note that
from here on is afterglow after beam stops
3. Short term Yellow Green - 1 second duration after Immediate blue; yellow green hex #E2FF80
4. Long Term Amber - 10 seconds duration after Short Term; Amber hex #FFA040
5. Expiration - 12 seconds duration after Long Term Amber; very dark hex #050700
=========================================================================
Important Nuance For PPI Scope.
The radio frequency beam from the antenna has a finite width. It's not just a pencil thin
beam.
So what that means is the if there is any intersection between the target (whose dimentions
are passed to the shaders) and any part of the beam, including the very edges; you will get
an echo. The echo will be the weakest when the edge of the beam intersects with the edge of
the target that is closest to the beam. The strength is greatest when the axis of the radio
frequency beam is center to the center of the target as it appears in the direction of the
radar. This, of course, is affected by the heading of the target (the direction the target
is movine in relation to the position of the radar; if the target is heading to the radar, the
profile as see to the radar would be the smallest). Then as the radio frequency bearm moves
past the target, the intensity of the return signal would be weaker and weaker until the beam
completely passes the target and no more energy is returned.
So, the target would appear as a curved line that is perpendicular to the angle of the radio
frequency beam. The ends of the line would be the dimmest in intensity (weaker) and the center
of the target would be the brightest.
Graticules - These are plastic overlays over the face of the scope. They are
for the purposes of showing the bearing. They are calibrated in degrees; short line (1/8 inch)
each degree; medium line (1/4 inch) for every 5 degrees; and a longer line (1/2 inch) for every
10 degrees. Line for true north; 2/3 inch.
Notes that these graticule lines are lit by a #47 incandescent bulb #FFB347.
=======================================================================
==================================
settings.h file suggestions:
/* Radar Hardware Constants */
namespace ChainHome {
const float PEAK_POWER = 500000.0f; // 500 KW
const float WAVELENGTH = 12.0f; // 12 Meters
const float ANTENNA_GAIN = 3.16f; // 5 dB expressed as linear gain
const float PULSE_WIDTH = 0.000020f; // 20 microseconds
const float BEAM_WIDTH = 150.0f; // in degrees (large floodlight)
const float PRF = 25.0f; // pulse repetition rate in times per second
}
namespace MarineAScope {
const float PEAK_POWER = 500000.0f; // 500 KW
const float WAVELENGTH = 0.10f; // 10 cm
const float ANTENNA_GAIN = 1000.0f; // 30 dB expressed as linear gain
const float PRF = 500.0f; // pulse repetition frequency
const float HORIZONTAL_BEAMWIDTH = 2.5f; // horizontal beamwidth
const float SYSTEM_TEMPERATURE = 290.0f; // system temperature
const float NOISE_FIGURE = 20.0f; // for period receivers; this is in Db
const float BOLTZMANN_CONSTANT = 1.38e-23f;
}