Skip to content

iRuperth/hydra-warden

Repository files navigation

HydraWarden

HydraWarden

RF-based drone detection, classification and proximity tracking

Python PyTorch ONNX Runtime FastAPI React TypeScript Tailwind Vite uv pnpm HackRF One

🌐 English · Español


Overview

HydraWarden is a passive radio-frequency drone detection system. It listens to the 2.4 GHz ISM band with a HackRF One software-defined radio, converts the raw IQ samples into time-frequency spectrograms, and runs a two-stage convolutional pipeline:

  1. Stage 1 — Detection. A binary CNN decides whether the spectrogram contains a drone control link or not.
  2. Stage 2 — Classification. A multi-class CNN identifies the manufacturer / model when a drone is present (DJI Mavic, Phantom, Parrot Anafi, Autel EVO II, Skydio 2, …).

A proximity tracker then estimates the drone's range from RSSI using a free-space path-loss model, computes approach/retreat trends from a rolling buffer of measurements, and raises tactical alerts (GREEN / YELLOW / RED).

The whole stack ships with a React + TypeScript tactical HUD that displays detections, range, velocity, threat level and history in real time over a WebSocket. It runs in two modes:

  • Real mode — uses the HackRF capture, trained models, and the proximity tracker.
  • Simulator mode — a built-in drone simulator drives the same UI with realistic approach / retreat / patrol / hover patterns. No SDR or trained models required — perfect for demos and frontend work.

Screenshots

HydraWarden HUD — GREEN observed state tracking a DJI Phantom 4

Tactical HUD — GREEN OBSERVED state. DJI Phantom 4 detected at low confidence, stable range trend.

HydraWarden HUD — YELLOW caution state tracking a DJI Mavic Pro

YELLOW CAUTION — DJI Mavic Pro identified with high confidence, RSSI history and signal-quality bands updating live.

HydraWarden HUD — RED imminent threat with approaching DJI Phantom 4

RED IMMINENT — DJI Phantom 4 at 99% confidence, close range and rising RSSI trigger the highest threat tier.

Tech stack

Layer Technology
SDR capture HackRF One @ 20 MHz sample rate, 2.4 GHz center
Signal processing NumPy, SciPy STFT (256-point window, 50% overlap)
Detection model ResNet-18 (binary head) — PyTorch / ONNX
Classification model ResNet-18 (N-class head) — PyTorch / ONNX
Proximity tracking Free-space path-loss + linear-regression trend on RSSI
Backend FastAPI + Uvicorn, WebSocket streaming
Frontend Vite + React 19 + TypeScript + Tailwind v3 + Recharts
Python tooling uv (lockfile, virtualenv, scripts)
JS tooling pnpm
Target hardware Mac mini / x86 Linux (PyTorch) · Raspberry Pi 5 (ONNX)

Architecture

┌──────────────────────────────────────────────────────────────────────┐
│                          HARDWARE LAYER                              │
│  HackRF One ──► IQ samples @ 2.4 GHz, 20 MHz BW, 100 ms blocks       │
└──────────────────────────────────────────────────────────────────────┘
                                  │
                                  ▼
┌──────────────────────────────────────────────────────────────────────┐
│                       SIGNAL PROCESSING                              │
│  src/processing/spectrogram.py                                       │
│    • STFT (nperseg=256, noverlap=128, hann window)                   │
│    • log-power → min/max normalize → 224×224 uint8                   │
│    • compute_rssi()  (avg power → dBm)                               │
└──────────────────────────────────────────────────────────────────────┘
                                  │
                                  ▼
┌──────────────────────────────────────────────────────────────────────┐
│                    TWO-STAGE INFERENCE PIPELINE                      │
│  src/models/inference.py                                             │
│                                                                      │
│   Stage 1 ── DroneDetector (ResNet-18, 2 classes)                    │
│              ├─ no drone   → emit "No activity"                      │
│              └─ drone      ↓                                         │
│   Stage 2 ── DroneClassifier (ResNet-18, N classes)                  │
│              ├─ conf ≥ threshold → emit brand/model                  │
│              └─ conf < threshold → emit "Unknown brand"              │
└──────────────────────────────────────────────────────────────────────┘
                                  │
                                  ▼
┌──────────────────────────────────────────────────────────────────────┐
│                       PROXIMITY TRACKER                              │
│  src/tracking/proximity.py                                           │
│    • Free-space path loss: d = 10^((RSSI_ref - RSSI)/(10n))          │
│    • Trend (APPROACHING / MOVING_AWAY / STABLE / DRONE_LOST)         │
│    • Alert level (GREEN / YELLOW / RED) from estimated distance      │
└──────────────────────────────────────────────────────────────────────┘
                                  │
                                  ▼
┌──────────────────────────────────────────────────────────────────────┐
│                    FASTAPI BACKEND  (src/api/server.py)              │
│    • /ws            WebSocket — pushes DetectionPayload every cycle  │
│    • /api/status    Health check                                     │
│    • /api/demo/*    Simulator control (spawn / approach / patrol …)  │
│    • Serves the built React app from web/dist/                       │
└──────────────────────────────────────────────────────────────────────┘
                                  │
                                  ▼
┌──────────────────────────────────────────────────────────────────────┐
│                  REACT TACTICAL HUD  (web/)                          │
│    • Alert banner: AREA CLEAR · APPROACHING · HOSTILE INBOUND …      │
│    • Range / velocity / threat-level / RSSI panels                   │
│    • 60-second rolling charts for RSSI and range                     │
│    • Contact log table                                               │
│    • Demo controls (only visible when WARDEN_DEMO=1)                 │
│    • Day / night theming (desert ops / tactical HUD)                 │
└──────────────────────────────────────────────────────────────────────┘

Repository layout

hydra-warden/
├── config.py                  All thresholds, frequencies and paths
├── Makefile                   make / make demo / make dev / make build …
├── pyproject.toml             Python deps managed by uv
├── src/
│   ├── api/server.py          FastAPI app, WebSocket, demo endpoints
│   ├── capture/
│   │   ├── hackrf.py          Live HackRF IQ capture (real mode)
│   │   ├── replay.py          Offline replay from a dataset directory
│   │   └── demo.py            Interactive drone simulator
│   ├── processing/spectrogram.py    STFT + normalization
│   ├── models/
│   │   ├── detector.py        Stage-1 binary detector (PyTorch/ONNX)
│   │   ├── classifier.py      Stage-2 multi-class classifier
│   │   └── inference.py       Two-stage pipeline wrapper
│   ├── tracking/proximity.py  RSSI → distance, trend, alert level
│   └── utils/signal.py        Spectrogram → tensor/numpy helpers
├── notebooks/
│   ├── 01_preprocess_dronerf.ipynb
│   ├── 02_preprocess_dronedetect.ipynb
│   ├── 03_preprocess_drone_rc.ipynb
│   ├── 04_train_detector.ipynb
│   ├── 05_train_classifier.ipynb
│   └── 06_export_models.ipynb
├── tests/                     pytest suite (spectrogram, inference, proximity)
├── web/                       Vite + React + TS frontend
│   ├── src/
│   │   ├── App.tsx
│   │   ├── api/client.ts
│   │   ├── hooks/             useDetectionFeed, useTheme
│   │   └── components/        HudPanel, AlertBanner, DemoControls, …
│   └── public/HydraWarden.png
├── models/                    Trained weights (gitignored)
└── data/                      Datasets (gitignored)

Models

Stage Architecture Input Output File
1 — Detection ResNet-18 (ImageNet init, 2-class head) 3×224×224 spectrogram [drone, no_drone] softmax models/detector_full.pth
2 — Classification ResNet-18 (ImageNet init, N-class head) 3×224×224 spectrogram softmax over N brands models/classifier_full.pth

For Raspberry Pi 5 deployments both models are exported to ONNX (detector_lite.onnx, classifier_lite.onnx) and served via onnxruntime.

Class names for the classifier live in models/class_names.json.

Datasets used during training (none of them shipped in the repo):

  • DroneRF (Allahham et al.)
  • DroneDetect
  • Drone-RC

Preprocessing notebooks turn each raw dataset into 224×224 spectrogram PNGs that the training notebooks consume.

Quick start

Prerequisites

  • Python 3.11+
  • uv (Python package & venv manager)
  • Node 20+ and pnpm
  • (Optional, for real mode) HackRF One + libhackrf

Install

git clone https://github.com/iRuperth/hydra-warden.git
cd hydra-warden
make install      # uv sync  +  pnpm install (web/)

Run the simulator (no models, no SDR)

make demo

This starts the FastAPI backend on :8000 with WARDEN_DEMO=1, the Vite dev server on :5173, and opens the dashboard in your browser. Inside the dashboard, the Tactical Simulator panel lets you:

  • Spawn a drone with a chosen brand and starting range
  • Approach, Retreat, Hover, Patrol (orbit at constant distance)
  • Signal Lost, Reset
  • Toggle AUTO mode — the drone cycles through coherent patterns on its own (approach → patrol → retreat → hover) with directional inertia.

Run in real mode (requires trained models + HackRF)

make dev          # fails loudly if models/ is empty

This sets WARDEN_DEMO=0 so the backend refuses to silently fall back to the simulator — if models/detector_full.pth or the HackRF aren't available, you'll get a clear error.

To replay a dataset directory instead of using the HackRF:

WARDEN_REPLAY=/path/to/dataset make dev

Production-style single-port

make build        # bundles the React app into web/dist/
make run          # FastAPI serves the bundle and the WebSocket on :8000

All Make targets

make            same as `make dev` (real mode)
make dev        Real mode: API + Vite, fails if no models
make demo       Simulator mode: API + Vite, no models needed
make dev-api    Only the FastAPI backend (auto-detect mode)
make dev-web    Only the Vite dev server
make build      Build the frontend into web/dist/
make run        Serve the built frontend from FastAPI on a single port
make install    uv sync + pnpm install
make help       Print this list

Configuration

All tunable parameters live in config.py:

Section Key parameters
HackRF HACKRF_CENTER_FREQ, HACKRF_SAMPLE_RATE, HACKRF_LNA_GAIN, HACKRF_VGA_GAIN
STFT STFT_NPERSEG, STFT_NOVERLAP, STFT_WINDOW, SPECTROGRAM_SIZE
Cycle CAPTURE_DURATION_S, CYCLE_INTERVAL_S
CNN thresholds DETECTION_THRESHOLD, CLASSIFICATION_THRESHOLD
Proximity RSSI_REF, PATH_LOSS_EXPONENT, RSSI_BUFFER_SIZE, TREND_WINDOW
Alerts ALERT_RED_MAX, ALERT_YELLOW_MAX
Deployment DEPLOYMENT_MODE (fixed = PyTorch, mobile = ONNX)

Environment overrides:

Variable Effect
WARDEN_DEMO=1 Force simulator mode
WARDEN_DEMO=0 Force real mode (fail if models/SDR missing)
WARDEN_REPLAY=<dir> Use a dataset directory instead of the HackRF
DEPLOYMENT_MODE=mobile Use ONNX models instead of PyTorch

Tests

uv run pytest

Covers spectrogram generation, the two-stage inference path (with mock models), and the proximity tracker (distance estimation, trend detection, alert levels).

Training the models

  1. Download DroneRF / DroneDetect / Drone-RC into data/.
  2. Run notebooks 01-03 to generate spectrograms in data/spectrograms/.
  3. Run 04_train_detector.ipynb and 05_train_classifier.ipynb. Weights land in models/.
  4. Run 06_export_models.ipynb to produce ONNX exports for the Pi 5.

📩 The trained model isn't shipped here. If you'd like to try HydraWarden in real mode with the actual weights, reach out to me privately and I'll share them with you.


HydraWarden — Tactical RF drone detection

About

Passive RF counter-drone system. Listens to the 2.4 GHz band, detects and classifies the drone model with a two-stage neural pipeline, estimates range from signal strength, and streams threat alerts to a tactical HUD in real time.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors