Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PHAROS — Phased/Pulse-Doppler Active Radar Operations Simulator

PHAROS

We sweep. We see. We know.

A real-time, GPU-accelerated active-radar simulator — from first-principles detection physics to a full signal-processing chain running on CUDA, with a live tactical display and statistical charts.

Why "PHAROS"? A double meaning. It's the acronym — Phased / Pulse-Doppler Active Radar Operations Simulator — and a nod to the Pharos of Alexandria, the ancient lighthouse whose rotating beam swept the darkness to reveal what was out there. Which is exactly what a radar's PPI sweep does.

Built in modern C++20 with CUDA, OpenGL, Dear ImGui and ImPlot. It models an active monostatic surveillance radar: targets move through a 2D tactical scene, the antenna sweeps, and detections are produced both from the radar range equation (analytic) and from a range-Doppler signal-processing pipeline (matched filter → Doppler FFT → CFAR) executed on the GPU.

PHAROS in action — PPI scope, range-Doppler map, and live charts

The live dashboard: rotating PPI scope (top-centre), GPU range-Doppler map (bottom-centre), SNR/Pd/detection charts (right), and full parameter control (left).


Why this project

It sits at the intersection of several domains I wanted to demonstrate end to end:

  • Radar / DSP — the radar equation, probability of detection, LFM pulse compression, range-Doppler processing, and constant-false-alarm-rate detection.
  • GPU computing — custom CUDA kernels, batched/strided cuFFT, and CUDA-OpenGL interop that paints the heatmap straight from device memory with no host round-trip.
  • Real-time graphics & UX — an interactive 60 fps dashboard (PPI scope, range-Doppler map, live charts, full parameter control).
  • Engineering discipline — a clean layered architecture, a dependency-free unit-tested physics core, and a build that degrades gracefully when no GPU toolkit is present.

Features

Area What it does
Tactical sim Fixed-timestep kinematics; targets with position, velocity and RCS; rotating antenna scan.
Detection physics Radar range equation SNR ∝ Pt·G²·λ²·σ / (R⁴…); probability of detection via Albersheim's approximation; measurement noise; Poisson false alarms.
PPI scope Rotating sweep with afterglow, range rings, azimuth spokes, fading detection blips, optional ground-truth overlay.
GPU signal chain LFM chirp synthesis → matched-filter pulse compression → Hann-windowed Doppler FFT → CA-CFAR detection, all on the GPU.
Range-Doppler map Live heatmap painted by a CUDA surface-write kernel via OpenGL interop; range/velocity axes; CFAR markers; noise-floor-relative colour scaling.
Signal mode Overlays the GPU pipeline's CFAR detections back onto the PPI for comparison with the analytic detector.
Live analytics ImPlot charts: SNR-vs-range, Pd-vs-range (with per-target markers and Pd=0.5/0.9 range lines), detections-per-scan.
Full interactivity Every radar parameter on sliders; add/move/remove targets live; play/pause/time-scale.

How it works

Detection physics (analytic path)

Single-look signal-to-noise ratio from the monostatic radar range equation:

        Pt · G² · λ² · σ · N
SNR =  ───────────────────────────
       (4π)³ · R⁴ · k·T·B·F · L

Probability of detection is obtained from SNR with Albersheim's equation (closed-form, invertible), which also yields the "Pd = 0.9 range" style readouts.

Signal-processing path (GPU)

For the beam's current pointing direction the pipeline builds a synthetic range × pulse data cube and processes it entirely on the GPU:

  1. Waveform — linear-FM (chirp) reference, time-bandwidth product ≈ 40.
  2. Echo synthesis — each in-beam target's delayed, Doppler-shifted, antenna- pattern-weighted echo, plus complex thermal noise.
  3. Matched filterIFFT( FFT(x) · conj(H) ) for pulse compression, using strided cufftPlanMany so the range and Doppler transforms run on the same cube layout with no explicit transpose.
  4. Doppler FFT — Hann-windowed FFT across pulses → range-Doppler map.
  5. CA-CFAR — cell-averaging constant-false-alarm-rate detection in range, producing a detection list with per-cell SNR.

The result is colour-mapped (relative to the estimated noise floor) directly into an OpenGL texture through CUDA graphics interop.

Architecture

The core physics is deliberately free of any GPU/GL dependency, so it is fully unit-testable and the whole project builds and runs even without a CUDA toolkit.

src/
  core/    Math, entities, polar/Cartesian geometry        (no deps)
  radar/   Radar equation, Pd, antenna pattern, detector    (no deps)
  sim/     SimEngine: fixed-step scan + detection history    (no deps)
  dsp/     CUDA pipeline: chirp, matched filter, RD FFT, CFAR (CUDA, optional)
  render/  PPI scope + range-Doppler heatmap view            (OpenGL/ImGui)
  ui/      Control panels + ImPlot charts                    (ImGui/ImPlot)
  app/     Window, sim loop, glue
tests/     Catch2 — physics + GPU pipeline validation

CUDA is optional and auto-detected. With a toolkit present the DSP layer and range-Doppler map are enabled; without one, the application still builds and runs as the analytic radar simulator.

Tech stack

C++20 · CMake · CUDA + cuFFT · OpenGL 4.5 · GLFW · glad · Dear ImGui · ImPlot · GLM · Catch2. All third-party libraries except the CUDA Toolkit are fetched automatically by CMake (FetchContent).

Building

Prerequisites: CMake ≥ 3.24, a C++20 compiler, and network access on first configure (to fetch dependencies).

cmake -S . -B build
cmake --build build --config Release
ctest --test-dir build -C Release --output-on-failure

Run it:

./build/bin/Release/radar_app      # path varies by generator/config

glad loader: the OpenGL loader is generated at build time with Python and needs the jinja2 package. If CMake selects the wrong Python, point it at a real interpreter: pip install jinja2 then cmake -S . -B build -DPython_EXECUTABLE=/path/to/python.

Enabling the GPU signal chain (optional)

Requires a CUDA Toolkit (12.x or 13.x) and a host compiler it supports (CUDA 13 needs Visual Studio 2022). Point CMake at nvcc if it isn't on PATH:

cmake -S . -B build -DCMAKE_CUDA_COMPILER="/path/to/nvcc"

The target GPU architecture defaults to sm_86 (Ampere / RTX 30-series); override with -DCMAKE_CUDA_ARCHITECTURES=<arch>. The required CUDA runtime DLLs are copied next to the executable automatically, so no PATH changes are needed to run. Force-disable with -DRADAR_ENABLE_CUDA=OFF.

Testing

Catch2 suite run via ctest. The physics core is validated independently of the GPU (R⁻⁴ falloff, RCS scaling, Pd monotonicity, detection-range inversion, geometry round-trips, end-to-end sim detection). When CUDA is enabled, two extra tests assert that the range-Doppler peak lands at the physically-expected range and Doppler bin and that CFAR detects a known target with few false alarms — the GPU pipeline is checked against the analytics, not just smoke-tested.

Roadmap

  • M0 — build system, window, optional CUDA smoke test
  • M1 — kinematic sim, radar-equation detection, PPI scope, live charts
  • M2 — GPU range-Doppler chain (chirp → matched filter → FFT → CFAR) + interop heatmap
  • M3 — multi-target tracker with track trails, ground/rain clutter, noise jammer, scenario save/load, recorded demo GIFs

License

MIT © Patrik Kalabus · PHAROS


Educational radar-simulation project. All models are textbook formulations implemented from public-domain physics; no classified or proprietary data is used.

About

Phased/Pulse-Doppler Active Radar Operations Simulator — real-time GPU (CUDA) radar DSP: matched filter, range-Doppler, CFAR, with an OpenGL/ImGui tactical display.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages