BowCapital Defense Hackathon 2026 — Logistics & Cybersecurity track.
A signature library (Dedrone, DroneShield) catches drones it has seen before;
the unknown ones fall into NO_MATCH and walk through. We built an
anomaly-based detector that learns the ambient RF and flags emitters that
don't fit — whether or not they were ever in a training set.
On a held-out novel emitter (synthetic, but the same code path that loads real captures):
| Class | Role | Library miss | Anomaly miss |
|---|---|---|---|
| ambient | ambient (FP rate) | 0% | 5% |
| wifi | known emitter | 0% | 0% |
| bluetooth | known emitter | 9% | 0% |
| lora | known emitter | 0% | 0% |
| expresslrs | known emitter | 15% | 0% |
| novel | held-out novel | 100% | 0% |
Library baseline is a NearestNeighbors template matcher tuned to mimic a real
signature library (under threshold → NO_MATCH → no detection). The anomaly
detector is IsolationForest trained on ambient only. Numbers regenerated by
python evaluate.py in physical_demo/library_contrast/.
┌────────────────────────────────────────────────┐
│ Live RF capture (RTL-SDR or ADALM-Pluto) │
└────────────────────┬───────────────────────────┘
│ IQ
▼
┌────────────────────────────────────────────────┐
│ Detection service physical_demo/ │
│ • Welch PSD per ~10 ms window │
│ • Learn ambient (~30 s) → per-bin baseline │
│ • Watch: max z-score ≥ threshold → flag │
│ • HTTP GET :5001/status │
│ • UDP 239.1.1.1:5000 (detection events) │
│ • UDP relay sensor ingress (unicast) │
└────────────────────┬───────────────────────────┘
│ detection JSON
▼
┌────────────────────────────────────────────────┐
│ Mesh relay physical_demo/ │
│ • Bootstrap-by-known-peer (no multicast) │
│ • Gossip via HELLO; full peer list in ~2 s │
│ • Each detection → broadcast to peers │
└────────────────────┬───────────────────────────┘
│
▼
┌────────────────────────────────────────────────┐
│ Pylon dashboard dashboard/ │
│ • Next.js + Mapbox + deck.gl │
│ • 3D terrain, slanted node pads │
│ • AIR / WATER / GROUND hostiles, swarms │
│ • Tracking interceptors w/ burst rings │
└────────────────────────────────────────────────┘
The judging artifact: library-vs-anomaly miss-rate experiment, runs standalone
on synthetic IQ. Produces out/miss_rates.png + out/results.md.
cd physical_demo/library_contrast
pip install -r requirements.txt
python evaluate.pyTwo SDR backends behind one capture seam:
--sdr rtl— NESDR SMArt v5 (100 kHz–1.75 GHz). Demo target: a 315/433 MHz key fob.--sdr pluto— ADALM-Pluto via libiio over USB. Reaches 2.4 GHz (WiFi/BT band), where a novel emitter introduced into the busy ambient triggers a detection.
cd physical_demo/drone_detection
brew install librtlsdr
pip install -r requirements.txt
# RTL — 433 MHz key fob, ~30 s learn (fob OFF), then press it
python main.py --source live --detector anomaly --freq 433920000 --gain 49.6
# Pluto — 2.4 GHz WiFi/BT ambient + novel emitter
python main.py --source live --sdr pluto --detector anomaly
# No SDR? Manual fallback:
python main.py --source sim
curl -X POST localhost:5001/sim -H 'content-type: application/json' \
-d '{"detected":true}'35 unit tests + 1 hardware smoke test (pytest).
No multicast, no broadcast. Each node binds one UDP port; new nodes JOIN through a known peer; gossip in periodic HELLO propagates the full peer list within seconds.
# Hub (one laptop):
./create_network.sh # mesh :5000, sensor ingress :5050
# Detector on the hub forwards events into the mesh:
./run_detector.sh --source live --sdr pluto
# Other laptops on the same Wi-Fi:
./join_network.sh <hub-ip>:5000Next.js 14 + Mapbox GL + deck.gl 9 + zustand. Free-running interactive sandbox: deploy a relay ring, click to place relays/FOBs, launch AIR/WATER/GROUND hostile swarms over real terrain, watch mesh self-heal when a relay is destroyed, and tracking interceptors run threats down with an expanding burst on impact. Search for a real location and fly there.
cd dashboard
echo "NEXT_PUBLIC_MAPBOX_TOKEN=pk.your_token_here" > .env.local
npm install
npm run dev # http://localhost:3000- The 100% / 0% headline is on synthetic IQ (3200 windows per class, seed
1337). The harness loads real captures by swapping one function in
synthetic.py; the rest of the pipeline is unchanged. - The dashboard runs its own synthetic gated-carrier RF model. A
WebSocketRFSourceexists for live ingestion; bridging the detector's UDP stream to it is future work — for the demo, treat the dashboard as the operator-facing visualization layer for the concept, and the detector + mesh as the live-RF working prototype. - The detection service has no signature classifier. It reports a coarse
comms-like/jamming-likelabel from occupied-bandwidth fraction, not a drone model.
May 29–31 2026, UCSD Design & Innovation Building. Software-only Logistics & Cybersecurity track. Build window is the hackathon — all code in this repo was written between hand-out and the 11 AM Sun 5/31 submission deadline.
