Introduction
This document describes a buildable, weekend-scope hardware project: a passive bistatic radar that detects small consumer drones by listening for FM radio reflections off them, computed in real time on an NVIDIA Jetson Orin Nano. Two identical sensor nodes, deployed ~50 m apart on tripods, share GPS-disciplined time and produce confirmed detections of any drone-sized object flying within ~1 km. A tablet shows live results.
What the finished v1 system does
- Detects drone-class targets at 300–1000 m typical range, 1500 m best-case (depends on local FM tower power and antenna height) using only ambient FM broadcast radio as the illuminator. No active emissions. Covert.
- Updates the operator's tablet at 10 Hz with live range, Doppler velocity, and a per-detection label (drone / bird / helicopter / other) produced by a hosted vision-language model — no training, no on-device classifier.
- Runs fully on battery for 3+ hours per site. Two sites form a self-organizing mesh with no infrastructure required.
- Costs ~$2,800 total for the full two-site system, or roughly $1,000 per node, plus a ~$300 test drone.
- Builds in ~8 hours of focused integration after parts arrive, plus a few weekends for the radar pipeline software.
Why this is worth building, the cost-vs-commercial story, and the prior art that makes it credible — see the Rationale tab.
Who this guide is for
- A motivated student or builder who can read a datasheet, solder a header, and follow shell commands.
- Someone working with an AI coding assistant (Claude, Cascade, Cursor, etc.) to write the radar pipeline. The guide assumes you have an LLM partner; the Playbook tab is structured as atomic tasks the LLM can help you execute one by one.
- Anyone with a few weekends and ~$3K who wants to actually run a radar, not just read about one.
How to read this document
- Introduction (you are here). What v1 is, who it's for, how to navigate the doc.
- Rationale. Why this is worth building: the gap in the commercial market, why it's newly possible, prior art at industrial scale, and the cost-vs-commercial story.
- Architecture. How passive radar works. The big-picture data flow. The supervisory-control pattern for human oversight.
- Sensor Node. The Jetson-based hardware design — block diagram, enclosure, power, antennas.
- Bill of Materials. Every part, every link, every cost. Click to buy.
- User Interface. The tablet, the mesh, the supervisory-control UI. How a human watches and authorizes.
- Extensions & ideas. Near-term improvements that extend v1 without replacing it: rotor micro-Doppler, acoustic mic array for nighttime, cell-tower illuminator upgrade (v1.5), and parking-lot ideas to come back to.
- Chaser (v2) / CAP (v3) / Starlink (v4). Where this is heading architecturally. Future scope, not part of v1 — these replace the system rather than extend it.
- Playbook. ~91 atomic v1 build tasks (plus 20 more for the Extensions phases), ordered by phase, with dependencies, success criteria, and time estimates. The thing you actually work through.
Tip: read Rationale + Architecture once, skim Sensor Node and BOM to understand what you're building, skim User Interface and Chaser to see where it's going, then live in Playbook.
Rationale — why this is worth building
Three questions a sceptical reader is entitled to ask before spending a weekend and ~$3K on a hardware project: (1) what's wrong with what already exists? (2) why is this newly possible? (3) who's already doing the same thing at industrial scale, and how does this build relate?
1. What's wrong with what exists
Drone detection is mostly sold as $50K–$200K active radar boxes — DroneShield RfPatrol, Dedrone DroneTracker, Aaronia AARTOS, Echodyne MESA-DAA. They work, they're FCC/CE certified, they have polished UIs and 24/7 support. But:
- They emit RF. Active radars announce themselves at 2–10 GHz with a clear waveform, which means an adversary with a $50 SDR can detect them from kilometres away. For covert deployments — forward observation posts, undisclosed VIP locations, anti-smuggling at borders — this is the wrong tool.
- They're closed. No source, no algorithm transparency. When the system misses a hostile drone, there is nothing to debug — just a vendor support ticket. For research, education, or any deployment where you need to understand why a detection happened, they're black boxes.
- They scale linearly with money. Two sites = $100K–$400K. Five sites for full coverage of a small facility = $250K–$1M. The economic model only works for organisations that already have a $10M security budget.
- They detect what their training data covers. Most commercial systems lean heavily on RF-fingerprint detection of known drone models (DJI, Autel, etc.). New, hobby-built, or first-person-view racing drones — the ones increasingly used in modern conflicts — are not in the database, and the system goes blind.
For the specific use case of small consumer drones in cluttered low airspace, on a hobbyist or research budget, with full algorithmic transparency — there is essentially nothing in the market. That's the gap this build fills.
2. Why this is newly possible
Two parts dropped in price and complexity in the last 24 months. Either alone wouldn't be enough; the combination is what makes a $3K passive radar realistic.
| Used to be | Now | What this unlocks | |
|---|---|---|---|
| Coherent multi-channel SDR | $5K of custom phase-locked Ettus B210s + GPSDOs + 10 MHz reference cabling | KrakenSDR — $400. 5× RTL2832U on a common 28.8 MHz clock with built-in noise-source calibration. Plug-and-play over USB. | The phase-coherent multi-antenna receiver that passive radar actually needs is now consumer-priced. |
| GPU compute for radar DSP | $3K Jetson AGX Xavier or rack-scale CUDA box for cuFFT cross-ambiguity at 10 Hz | Jetson Orin Nano Super — $249. 67 TOPS at 15 W. cuFFT runs cross-ambiguity comfortably; TensorRT runs classification in spare cycles. | The compute that used to fill a 1U rack now fits in a power bank. |
| Classification | Months of dataset collection + custom CNN training | Hosted VLMs (Claude, GPT-4o, DeepSeek-VL) at sub-cent per call. Zero-shot classification of range-Doppler maps and micro-Doppler spectrograms. | The labelling step that used to require an ML team is now a 10-line API call. |
None of these were viable for a hobbyist budget two years ago. All three are off-the-shelf today.
3. Prior art — what scaled-up versions of this look like
Passive bistatic radar isn't a new idea. It has a 70-year history (the British Chain Home auxiliary system in WWII used a similar principle) and a vibrant academic and industrial community today.
- Lockheed Martin Silent Sentry (1998–present) — FM- and TV-illuminated passive radar against aircraft-class targets at 100+ km. Multi-metre antenna arrays, rack-scale processing, integrated with Patriot and other air-defence networks.
- Hensoldt TwInvis (Germany) — commercial passive radar product using DVB-T illuminators, deployed in NATO air-policing roles. Tracks airliners, helicopters, and military aircraft simultaneously over national-scale areas.
- Fraunhofer FHR PARADE / FKIE — German research consortium publishing extensively on FM/DAB/DVB-T passive radar, including specific work on small-UAV detection and micro-Doppler classification.
- Warsaw University of Technology (Malanowski et al.) — academic work on FM and DAB passive radar against UAVs at sub-kilometre range, using hardware not unlike what we're using here.
- Strathclyde / Cranfield (UK) — academic work on Wi-Fi, LTE, and most recently Starlink as illuminators of opportunity.
The build in this guide uses the same underlying technique as those systems — cross-ambiguity processing of a reference channel against a surveillance channel, with GPS-coherent multi-receiver geometry. The performance envelope is much smaller: where Silent Sentry detects airliners at 100 km using a 30-metre antenna array, our two log-periodics detect drones at 1 km. That's a deliberate choice. The small-drone problem doesn't need 100 km range, and the hardware that does reach 100 km is two-to-three orders of magnitude more expensive.
4. The cost-vs-commercial story
| System | Cost (one site) | Cost (two-site coverage) | Active or passive? | Source available? |
|---|---|---|---|---|
| DroneShield RfPatrol | ~$8K (RF-detection only, no localisation) | $16K + $20K controller | Passive RF-fingerprinting | No |
| Dedrone DroneTracker | ~$30K (RF + acoustic) | $60K + ~$15K cloud subscription/yr | Passive RF + acoustic | No |
| Aaronia AARTOS | ~$60K–$150K depending on config | $120K–$300K | Passive RF (wideband direction-finding) | No |
| Echodyne MESA-DAA | ~$50K–$80K | $100K–$160K | Active (4D radar) | No |
| This build (v1) | ~$1,400 | ~$2,800 | Passive bistatic radar (covert, no emissions) | Yes — every line |
The headline number is one thing; the operational difference matters more. This build is the only entry in that table that is simultaneously covert (no emissions), open-source, and under $5K. For research, education, NGO security work, hobbyist defence-tech, and forward-deployed scenarios where active emissions are unacceptable, that combination has no commercial alternative.
5. What this build is not
To pre-empt over-claiming, here's what v1 will not do:
- It will not detect aircraft at 100 km. The antenna aperture is small and the bandwidth is narrow. The performance envelope is small drones at sub-kilometre range, period.
- It will not work in zero-FM-coverage areas. The illuminator is ambient FM broadcast. In the middle of the Pacific or behind a hill with no clear line-of-sight to a station, you'll need a different illuminator (DAB / DVB-T / cell tower — see Extensions tab).
- It will not stop drones. Detection is one half of the problem; interception is the other half, and it's a much larger project covered separately in the Chaser (v2) tab.
- It will not be FCC-certified. Passive receivers don't need certification, but if you commercialise this you'll have your own regulatory path to walk.
What it will do: reliably detect, localise, and classify small consumer drones at 300–1500 m in cluttered low airspace, on battery, covertly, with every line of code and every part-number documented. That's the value proposition.
Architecture
Four concepts to understand before touching any hardware: passive bistatic radar (how detection works without an emitter), GPS-disciplined timing (how two nodes 50 m apart can act as one coherent radar), foundation-model classification (how we skip training entirely and just ask a hosted VLM), and supervisory control (how a human stays in the loop without piloting anything).
1. Passive bistatic radar — detection without emission
Conventional radar emits a pulse and listens for the echo. Passive radar doesn't emit anything. It listens for energy that's already in the air — usually FM broadcast or DVB-T television — and looks for the reflections off targets. The illuminator is somebody else's transmitter; you only own the receivers.
For each target the system measures two things:
- Bistatic range — the extra distance the signal travels by bouncing off the target, vs the direct path from transmitter to receiver. Computed from the time delay between the two paths.
- Bistatic Doppler — the velocity component of the target along the bistatic geometry. Computed from the frequency shift in the reflected signal.
One receiver gives you a bistatic ellipse the target lies on (constant total-path distance). Two receivers give you the intersection of two ellipses → a localized target. With two sites and an FM transmitter ~5 km away, you get drone-class detection out to ~1 km in clear conditions. The diagram below is drawn with just one FM transmitter — that's the v1 build. The following diagram shows the recommended deployed picture, where each sentry listens to that FM tower and multiple cell sectors concurrently.
The math behind this is the cross-ambiguity function: a 2D correlation of the reference and surveillance channels over a grid of (delay, Doppler shift) hypotheses. Where the function peaks, there's a target. The peak's coordinates give you bistatic range and Doppler. This is what runs on the GPU at 10 Hz.
1b. Deployed view — one FM tower plus many cell sectors
The diagram above shows v1 with FM as the only illuminator — that's what you build on the first weekend. In any real urban or suburban deployment, however, you're surrounded by many radio sources, and the recommended deployed configuration adds a second KrakenSDR per sentry to listen to nearby LTE cell sectors concurrently with FM. The top-down view below shows what that looks like operationally — one strong, distant FM tower plus 5–20 weaker, closer cell sectors all illuminating the same airspace at once, with the sentries listening to all of them in parallel.
The two illuminator classes give you concentric detection rings: FM reaches further because it's 125× more powerful and uses 10× longer wavelengths; cell reaches less far but is 100× higher resolution and provides many independent geometric baselines. Inside the inner ring both bands see the target — that's where cross-band confirmation kills false alarms. See the Extensions tab → "Dual-illuminator" for the BOM delta (~$720/sentry) and the operational handoff sequence.
Top-down view of a deployed sentry pair. The FM tower (1, far, 10 kW) creates the outer "candidate" detection ring; the surrounding cell sectors (5–20, near, ~80 W each) create the inner "confirmation" ring. As a drone enters from outside, FM catches it first ("Target 1"); when it crosses into the cell ring it's confirmed and refined by the cell pipeline ("Target 2"). Build v1 with FM only, then add the second KrakenSDR per sentry to unlock the cell pipeline — see Extensions tab.
2. GPS-disciplined timing — making two boxes act as one radar
For two sites 50 m apart to combine their views into a single picture, they need to share a time reference. If site B's clock is off by 1 µs from site A's, the apparent target position is wrong by 300 m (1 µs × c). For useful localization you want sub-100 ns timing error.
The cheap, robust solution: each Jetson has a GPS receiver with a Pulse-Per-Second (PPS) output. Both Jetsons discipline their system clocks to GPS time using chrony. Each site independently times its IQ samples against its own GPS-synced clock. They are now coherent in time to within ~100 ns typical, ~30 ns best-case with strong GPS lock — well under the 1 µs threshold needed for sub-100 m localisation.
This replaces a much more expensive setup involving GPSDOs, 10 MHz reference distribution, and PPS cabling. We get good-enough time alignment by burning a few hundred lines of Python on cross-correlating the direct path between sites at startup (which calibrates out residual nanosecond-scale offsets), then maintaining via GPS-PPS continuously.
3. Foundation-model classification — skip training, just ask a VLM
Once the radar peaks at a (range, Doppler) cell, you still need to label it: drone, bird, helicopter, car, noise. The traditional move is to train a custom classifier — collect a labeled dataset, fine-tune a CNN on micro-Doppler signatures, deploy as a TensorRT engine. That's months of work and ongoing maintenance.
The shortcut: render each detection as an image and ask a hosted vision-language model to label it. Range-Doppler maps, micro-Doppler spectrograms, and (in v2) actual camera frames are all just images. Claude, GPT-4o, Gemini, and DeepSeek-VL all classify them with zero training data and roughly human-expert accuracy.
| Approach | Setup cost | Per-detection latency | Per-detection cost | Accuracy |
|---|---|---|---|---|
| Custom-trained CNN (TensorRT, on-device) | Weeks of dataset + training | ~1 ms | $0 (free after training) | High once tuned, brittle out of distribution |
| Hosted VLM (Claude / GPT-4o / DeepSeek-VL) | ~10 lines of code | 200 ms – 2 s | $0.001 – $0.01 per image | Surprisingly high zero-shot, robust to weird cases |
| Hybrid (cheap on-device gate → VLM for uncertain) | Days | 1 ms typical, 1 s when escalated | ~$0.001 per uncertain detection | Best of both |
The classifier doesn't run on the sensor node at all. Each Jetson detects and computes a small image (a 128×128 range-Doppler patch, or a 1-second micro-Doppler spectrogram), packages it with a detection JSON, and ships both to the operator tablet over the mesh. The tablet — or the operator's laptop, or a cloud function — calls the VLM API and returns a label. Total round-trip ≈ 500 ms, which is well under the human decision time anyway.
Why this works in practice:
- The sensor's job is detection, not classification. CFAR + cross-ambiguity reliably tells you something is there. Naming it is a separate, slower step that benefits from a much bigger brain than fits on the Jetson.
- VLMs are good at "what is this image of?". Even when they've never seen a Doppler spectrogram before, a prompt like "this is a micro-Doppler spectrogram of a flying object — is it most likely a drone, bird, helicopter, or other? answer with one word and a confidence 0–1" gets useful answers.
- The model doesn't need to be on the drone. The chaser sends a JPEG over Wi-Fi 6E to the base station; the base station calls Claude / DeepSeek-VL; the answer comes back in <1 s. The chaser saves weight, power, and complexity by carrying just a camera and an encoder.
- Cost is negligible. A two-hour mission with one detection every 10 s is 720 API calls. At Claude Haiku rates that's ~$0.50.
- You can swap models at any time. Today's best VLM gets replaced by next quarter's. No retraining, just change the API endpoint.
4. Supervisory control — humans in the loop without flying anything
Once you have detections, what does a human do with them? There are three operating modes for any drone-detection-and-response system, and only one of them is sane.
| Mode | Operator role | Verdict |
|---|---|---|
| Fully autonomous | None — system detects, classifies, intercepts | Fast, scales — but legally and ethically untenable for kinetic action. Fails on edge cases (news helicopters, neighbour's RC plane). |
| Manually piloted | Operator flies the chaser with sticks and FPV goggles | One operator per drone, no scaling, can't out-fly autonomy at 30 m/s. Wrong abstraction. |
| Supervisory control | Operator watches video + telemetry, authorizes high-level decisions: investigate, abort, RTB, terminal | The pattern Anduril Lattice and Shield AI Hivemind use. Humans where humans are good (judgment), autonomy where autonomy is good (closed-loop control). |
The architecture treats the operator as the slow, smart, legal-authority component — not as a pilot. The chaser flies itself; the operator says yes or no. Latency budget is hundreds of milliseconds (operator decision time), which Wi-Fi handles trivially. We never need a sub-50 ms FPV link.
System block diagram — v1 (sensor only) → v2 (with chasers)
Why this design holds up
- Both nodes are identical. Same hardware, same software image, same OS. Configuration is one file (
/etc/nomio/node.conf) that sets the unique node ID. Spares are interchangeable. - Edge processing. Each node runs the full DSP pipeline locally on its GPU. Only KB/s of detections cross the mesh — never raw IQ (which would be 16 MB/s and saturate Wi-Fi).
- No infrastructure. No servers, no cloud, no fixed network. Two batteries, two tripods, one tablet, drop-in deploy.
- Failure modes are graceful. If one node dies, the other still produces single-site bistatic detections (just no localization). If GPS dies, you can fall back to direct-path cross-correlation. If the tablet dies, the OLED + LEDs on each box still tell you what's happening.
- Upgrade path is linear. v1 ships with a hosted-VLM classifier from day one (no training step) → add 3rd/4th sites for TDOA 3D localization (no architecture change) → add chasers (v2).
Sensor Node
Each site is one self-contained box. Inside: a Jetson Orin Nano running the radar pipeline on its CUDA GPU, a KrakenSDR doing the coherent multi-channel RF capture, a GPS HAT for time discipline, an OLED + LEDs for status, and a power bank running the whole thing. The box sits on a tripod with two log-periodic antennas mounted alongside.
Per-site block diagram
Power budget
The Jetson is configurable: 7 W, 15 W, or 25 W power modes. We run at 15 W ("MAXN_SUPER" mode at conservative throttle) — full 67 TOPS available, but moderated for battery life.
| Component | Idle | Active (DSP only — VLM lives at base) | Notes |
|---|---|---|---|
| Jetson Orin Nano (15 W mode, headless) | ~5 W | ~13 W | cuFFT cross-ambiguity at 10 Hz + spectrogram render. No on-device classifier. Plenty of headroom. |
| Uputronics GPS HAT | 0.3 W | 0.3 W | Powered from 40-pin header. |
| KrakenSDR | 10 W | 12 W | Dominant load. Powered from its own USB-C PWR port — never from the Jetson. |
| OLED + LEDs | 0.1 W | 0.2 W | Negligible. |
| Site total | ~16 W | ~26 W |
An 87 Wh power bank (Anker 737) gives ~3 hours of continuous operation. Add a 40 W folding solar panel ($60) for indefinite daytime use. For static deployment near power, just plug into a wall adapter.
3D-printed enclosure
A two-piece PETG case houses the Jetson + KrakenSDR + power bank in three internal trays. ~12 hour print on a Bambu A1, $8 in filament. External: 220 × 130 × 90 mm.
- Top tray: Jetson Orin Nano dev kit + GPS HAT stacked on the 40-pin header.
- Middle tray: KrakenSDR. Heat conducted to case wall via thermal pad.
- Bottom tray: Anker 737 power bank, slides in/out from rear.
- Front face: 0.96" OLED, 3 status LEDs, 1 push button.
- Rear face: 2× SMA bulkhead (RF in), 1× SMA bulkhead (GPS), 1× USB-C in (charging), 1× IP67 vent membrane.
- Bottom face: 1/4"-20 brass insert for tripod mount.
- Side faces: hex vent grilles aligned with Jetson cooler intake/exhaust.
STL files are produced by an OpenSCAD parametric model (in the project repo, enclosure/nomio_node.scad) where you set compute_module = "jetson_orin_nano", battery, weatherproofing, and mount.
What runs on each Jetson — software stack
Same software image for both nodes. Identity comes from a single config file.
- JetPack 6 (NVIDIA's Ubuntu 22.04 LTS for Jetson) as the base OS, on NVMe.
gpsd+chronyreading NMEA + PPS from the Uputronics HAT. Disciplines the system clock to ~1 µs of GPS time.- KrakenSDR DAQ daemon (official) capturing coherent IQ over USB 3.2.
nomio-radar(the pipeline you'll write — see Playbook): Python + CuPy + cuFFT, ~600 lines, runs on the GPU. Cross-ambiguity at 10 Hz, CFAR detection, spectrogram-patch render. No on-device classifier — the patch ships to the base station which calls a hosted VLM.nomio-status: OLED + LED + button daemon (~100 lines Python).nomio-mesh:batman-advmesh interface, mDNS via Avahi, signed message bus.nomio-web: FastAPI + WebSocket server for the operator tablet web UI.
All seven services managed by systemd, starting in dependency order on boot. Total install footprint ~3 GB on the NVMe.
Why not a Raspberry Pi 5?
Honest comparison. The Pi 5 is a fine general-purpose Linux box, but its compute envelope is a real bottleneck for radar work.
| Capability | Pi 5 (NEON SIMD) | Jetson Orin Nano (CUDA + TensorRT) |
|---|---|---|
| Cross-ambiguity update rate | ~1 Hz | 10–20 Hz |
| Coherent integration time (more SNR = farther detections) | 0.1 s typical | 1.0 s easy |
| Render spectrogram patch for VLM classifier | ~50 ms (CPU, marginal) | ~2 ms (CUDA, easy) |
| Multiple illuminator bands in parallel | 1 | 3–4 |
| Headroom for upgrades (DOA, beamforming) | none | ~50% spare |
| Cost (compute board only) | $80 | $249 |
$170 difference, 40× compute uplift, and the difference between "barely functional demo" and "actually useful detection." If results matter, get the Jetson.
Bill of Materials
Every part you need to order, with linked sources and prices. Two columns: Per site means buy two (one for each node); Shared means one for the whole build. Prices are USD as of late 2025 — sanity-check at order time.
1 · Core compute & RF — buy 2 of each
| Item | Source | Qty | Unit | Notes |
|---|---|---|---|---|
| Jetson Orin Nano 8 GB Super Developer Kit | NVIDIA · Arrow · Seeed · Amazon | 2 | $249 | The "Super" variant only — the 2024 firmware refresh that gives 67 TOPS. Carrier board + module + cooler all in one box. |
| NVMe M.2 2280 SSD, 256 GB | Samsung 980 / WD SN570 / Crucial P3 — Amazon | 2 | $30 | Jetson boots from NVMe (no SD card). Required for IQ logging. |
| Intel AX210 Wi-Fi 6E + BT 5.3 M.2 2230 | Amazon | 2 | $25 | Dev kit doesn't include Wi-Fi. Goes into the carrier board's M.2 Key E slot. Includes BT 5.3 for tablet pairing. |
| Wi-Fi antenna kit (2× MHF4 → RP-SMA pigtail + 2× dipole) | Amazon | 2 sets | $10 | The AX210 needs external antennas. Route them through small holes in the case. |
| Uputronics GPS / RTC HAT (with active GPS antenna) | Pi Hut (canonical) | 2 | $50 | Pi-compatible 40-pin HAT. Works on Jetson with jetson-gpio. PPS via GPIO 18, NMEA via UART. Includes magnetic-base GPS antenna. |
| KrakenSDR (unit only — no antennas) | Crowd Supply (canonical) · KrakenRF direct | 2 | $400 | 5-channel coherent SDR. We use only 2 channels (ref + surv) for v1. Other 3 are upgrade path for DOA. |
| Subtotal core compute & RF | $764 ×2 | $1,528 | ||
2 · Antennas — buy 4 total (2 per site)
| Item | Source | Qty | Unit | Notes |
|---|---|---|---|---|
| Log-periodic antenna, 400 MHz – 1 GHz (LP0410 / WA5VJB-style) | Kent Electronics (canonical) · AliExpress clones | 4 | $50 (Kent) / $20 (clone) | Directional, ~7 dBi, narrow lobe — important for separating direct and reflected paths. Two per site (ref + surv). Clone is fine for v1; Kent is better-matched. |
| SMA-to-SMA coax cable, 1 m, low-loss | Amazon (RG316 or similar) | 4 | $10 | Antenna → bulkhead. RG316 is fine at FM band over 1 m. |
| Subtotal antennas | $240 | |||
3 · Power — per site
| Item | Source | Qty | Unit | Notes |
|---|---|---|---|---|
| Anker 737 Power Bank (PowerCore 24K, 87 Wh, 140 W PD) | Anker direct · Amazon | 2 | $130 | Two USB-C output ports — one for Jetson, one for KrakenSDR. ~3 hr runtime. Airline-legal. |
| USB-C to USB-C, 100 W PD, 1 m (per site, 2 cables) | Amazon | 4 | $10 | One per powered device per site. |
| Optional: 40 W folding solar panel (USB-C PD output) | Amazon (BigBlue, Anker, Jackery, etc.) | 2 | $60 | Sustains daytime operation indefinitely. Skip for indoor or grid-tied use. |
| Subtotal power (without solar) | $300 | |||
4 · Status display + I/O — per site
| Item | Source | Qty | Unit | Notes |
|---|---|---|---|---|
| 0.96" OLED display, SSD1306, I2C, 128×64 | Amazon | 2 | $5 | 4-wire I2C: SDA, SCL, VCC (3.3V), GND. Drives via luma.oled Python. |
| 5 mm LED kit (assorted colours) + resistors + push button | Amazon | 1 kit | $10 | Use 1× green, 1× blue, 1× red, 1× yellow per site + one momentary button. 330 Ω current-limit on each LED. |
| Hookup wire kit (22 AWG, multiple colours) | Amazon | 1 kit | $10 | Shared. For OLED + LEDs + button + GPS-PPS jumper. |
| Optional: Adafruit RFM95W LoRa Bonnet (radio HAT) | Adafruit | 2 | $23 | Long-range mesh (2–5 km). Skip if both sites have line-of-sight Wi-Fi. |
| Subtotal status + I/O (without LoRa) | $30 | |||
5 · Mechanical — per site
| Item | Source | Qty | Unit | Notes |
|---|---|---|---|---|
| Camera tripod, ~1.5 m max height, with 1/4"-20 thread | Amazon | 2 | $30 | The case mounts on this. Antennas mount on a separate bar above. |
| Antenna mast (wood dowel or PVC pipe + clamps) | hardware store / Amazon | 2 | $15 | Holds the two log-periodic antennas ~30 cm apart. |
| 3D-printed enclosure (PETG, ~280 g/site) | print at home, or Craftcloud / JLCPCB / PCBWay | 2 | $8 (DIY) / $40 (outsourced) | STL files in the project repo. ~12 hr per case on a Bambu A1. |
| M3 brass heat-set inserts + M3 bolts (assortment kit) | Amazon | 1 kit | $15 | Shared. ~30 inserts + matching bolts. Press-fit with a soldering iron. |
| 1/4"-20 brass insert + IP67 GORE vent membrane | Amazon (insert) · Amazon (vent) | 2 | $8 | Tripod mount + humidity equalization for outdoor use. |
| SMA bulkhead pigtail set (5 cm SMA-F to SMA-M, right-angle) | Amazon | 2 sets | $15 | For panel-mount RF pass-through on the rear of the case. |
| Subtotal mechanical | ~$200 | |||
6 · Test target & operator hardware (shared)
| Item | Source | Qty | Unit | Notes |
|---|---|---|---|---|
| DJI Mini 3 (or Mini 4 Pro) — your test drone | DJI direct · Amazon | 1 | $300–500 | Any sub-250 g drone works. Realistic threat to test against. |
| Android tablet (8–11", any modern model) or iPad | any retailer | 1 | $200–600 | Operator console. Web-based UI; no native app required. |
| Laptop you already own | — | 1 | $0 | Used for first-flash and SSH. Doesn't go to the field. |
| Subtotal test/operator (low/high) | $500–1,100 | |||
Grand total
| Block | Cost |
|---|---|
| Core compute & RF (×2 sites) | $1,528 |
| Antennas (×4) | $240 |
| Power (×2 sites, no solar) | $300 |
| Status + I/O (×2 sites, no LoRa) | $30 |
| Mechanical (×2 sites) | $200 |
| Test drone (shared) | $300–500 |
| Tablet (shared) | $200–600 |
| Total — minimum sane build | ~$2,800 |
| Total — fully optioned (LoRa + solar + premium tablet) | ~$3,250 |
For comparison: the equivalent commercial system from a defence vendor (DroneShield RfPatrol, Hensoldt Spexer 360r) is $50K–$200K. This is the same physics for ~$3K. The catch is you have to build it yourself, and the performance tail is shorter. For learning, prototyping, or low-stakes field work, that's a great trade.
What you don't need (and might be tempted to buy)
- A separate GPSDO (Bodnar Mini, etc., ~$300/site). Not needed in v1. The GPS HAT's PPS into
chronygets you to ~1 µs, which is good enough. Add a GPSDO only if you later want true coherent multistatic with sub-100 ns timing. - Active cooling for the KrakenSDR. Already built in.
- A discrete USB-3 hub. The Jetson dev kit has 4× USB 3.2 ports — plenty.
- Pelican case. The 3D-printed case is fine for indoor or fair-weather field use. Drop in a Pelican only if you're going to deploy in rain/dust regularly ($80/case extra if you do).
- Big batteries (Jackery 240, 1000, etc.). Tempting for runtime, but adds 3–5 kg per site. The Anker 737 is the right size for 3-hour deployments.
Fast path — first detection in one day
The seven accelerants, ranked by impact
| # | Shortcut | Saves | Adds cost | Trade-off |
|---|---|---|---|---|
| 1 | Pre-flashed NVMe with JetPack | ~3 hr (Phase 3 entirely) | ~$50 | None — strictly upside. |
| 2 | Run AI assistant in parallel chats | ~10 hr (parallelises ~all software work) | $0 | Need to manage 3–4 chat tabs concurrently. |
| 3 | One-node bring-up first (clone NVMe to second later) | ~6 hr (halves Phase 2) | $0 | Bench-side detection is bistatic with one receiver, fine. |
| 4 | Skip 3D-printed enclosure for v1 — wire on plywood / cardboard | 1 day (Phase 1) | $0 | Looks ugly. Print case in parallel with field testing. |
| 5 | Skip the trained CNN classifier — use hosted VLM only | ~4 days (B-181 / B-182) | ~$0.01/detection | Needs internet at the operator tablet. Comes back if you need offline operation. |
| 6 | Co-locate the two sentries on a desk for first end-to-end | ~2 hr per debug cycle | $0 | You only do real field deployment once you trust the pipeline. |
| 7 | AC power adapter for Jetson during all bench work | ~2 hr of mystery debugging | ~$25 | None. Battery is for field, not bench. |
All seven combined: realistic ~12 hours of focused work from boxes-on-desk to first drone detection. This assumes parts are already on hand; the dominant remaining wait is shipping (~1 week from order to inventory).
Choosing a flash host computer
The Jetson Orin Nano dev kit ships blank. You flash NVIDIA's JetPack OS image onto its NVMe SSD using NVIDIA SDK Manager, which runs on a host computer connected over USB-C while the Jetson is in recovery mode. SDK Manager officially supports Ubuntu Linux only, but there are workable paths from Mac and Windows.
| Host OS | Path | Effort | Recommendation |
|---|---|---|---|
| Ubuntu Linux 20.04 / 22.04 | Native. Download SDK Manager .deb, sudo dpkg -i, log in with NVIDIA developer account, click "Flash". |
~30 min unattended | Easiest path. If you have any Linux laptop or PC, use it. |
| macOS (Apple Silicon or Intel) | Run an Ubuntu VM with UTM (free) or Parallels ($99). Pass through the Jetson's USB-C recovery port to the VM. Inside the VM, run SDK Manager normally. | ~1 hr setup, ~30 min flash | Workable. UTM with Ubuntu 22.04 ARM is the cheapest route on Apple Silicon. Make sure USB pass-through is enabled before you put the Jetson in recovery mode. |
| Windows | Same idea — Ubuntu VM via VirtualBox, VMware Workstation Player, or Hyper-V. WSL2 does not work — it can't pass through the recovery-mode USB device. | ~1 hr setup, ~30 min flash | Workable. Slightly more friction than macOS in our testing because USB pass-through quirks are more common. |
| None of the above — escape hatch | Buy a pre-flashed NVMe SSD. Several Jetson-ecosystem vendors sell NVMe drives with JetPack already imaged on them. Pop the drive in, boot, done. Skip the entire flash process. | ~5 min | Recommended for everyone who values their Saturday morning. |
Pre-flashed NVMe vendors
This is the single biggest time-saver in the entire build. You order an NVMe SSD that already has JetPack imaged on it. You install the SSD in the Jetson's M.2 slot, plug in power, and the Jetson boots into Ubuntu on first power-on. No SDK Manager, no recovery mode, no flash host.
- Seeed Studio reComputer J3010 / J3011 — Jetson Orin Nano with pre-flashed eMMC or NVMe options. Sometimes sold as a complete pre-imaged compute module.
- Connect Tech Inc. (CTI) — JetPack-imaged NVMe drives sold as a separate SKU. Add to cart with the dev kit.
- SparkFun Jetson Orin Nano kits — bundle with optional pre-imaged storage.
- NVIDIA Reseller Network — Arrow / Symmetry / Mouser. Ask for "JetPack pre-imaged NVMe option" when ordering. Most distributors will ship it that way for an extra $50.
- DIY-but-faster fallback — find a friend with a Jetson,
sudo dd if=/dev/nvme0n1 of=jetpack.img bs=4Mon theirs,ddthe image onto your fresh NVMe in any USB-NVMe enclosure. Takes 10 min, $0.
Optional convenience SKUs (everything that makes Day 1 smoother)
None of these are in the main BOM because they're not strictly required. But each one removes a real friction point. If your time is worth more than your money, buy them all.
| Item | Cost | Why it matters | Source |
|---|---|---|---|
| Pre-flashed NVMe (JetPack 6.0+) | ~$50 over plain NVMe | Skip the entire flash process. Boots into Ubuntu on first power-on. | Seeed / CTI / Arrow add-on at order time |
| USB-C 65 W PD wall adapter | ~$25 | Run the Jetson on AC during all bench debug. Eliminates "is this a power-bank dropout?" mystery debugging. Use the Anker 737 only for field deployment. | Anker 715 Nano II 65W or equivalent |
| NESDR Smart v5 (RTL-SDR) | ~$35 | Tiny USB SDR. Plug into your Mac. Use it for the FM site survey (B-006) before the KrakenSDR ships. Permanent debug tool afterwards. | Amazon, ships next-day |
| Coat-hanger / random dipole | ~$0 | Good enough for the initial bench-side spectrum survey. Don't wait for the proper log-periodics to arrive. | Make from any wire ~75 cm long |
| USB-C hub with 4× USB 3.2 + Ethernet | ~$40 | Lets your Mac talk to the Jetson over Ethernet (faster than Wi-Fi for code transfer) and the SDR over USB simultaneously. Convenient for bench-side work. | Anker 565 USB-C Hub or similar |
| Cheap monitor + HDMI cable (one time) | ~$0 (use any TV) or $50 (cheap portable) | For the very first boot of the Jetson before you've configured Wi-Fi. After Wi-Fi is up you go headless forever. | Any HDMI display |
| USB keyboard / mouse (one time) | ~$0 (you have one) | Same — first boot Wi-Fi config only. | Anything |
| Used Linux laptop (eBay) | $80–150 | If you don't want to fight with VMs on Mac/Windows. A used ThinkPad T480 with Ubuntu 22.04 is a perfect dedicated SDK-Manager / dev box. Resells for what you paid afterwards. | eBay / Craigslist |
| Plywood / cardboard "dev rig" | $0 | Don't 3D-print the case for first detection. Lay all the parts on a board, run wires loose. The 3D print takes 12 hr you don't have on Day 1. | Garage |
| Total optional spend | ~$150–250 | Halves your Day 1 time, eliminates ~3 categories of mystery bug. |
The agentic workflow — running me in parallel
The single biggest leverage point is using your AI assistant concurrently rather than sequentially. The v1 build has roughly four independent software tracks; each can be developed in its own chat tab without conflict, then integrated.
| Chat tab | What runs there | Output |
|---|---|---|
| Tab 1 — DSP pipeline | cuFFT cross-ambiguity, CFAR detector, IQ alignment, range-Doppler renderer. | nomio_radar.py + GPU kernels. |
| Tab 2 — Web app + tablet UI | React + Leaflet + WebSocket frontend, FastAPI backend, detection JSON schema. | nomio-web/ directory, runs as systemd service on Jetson. |
| Tab 3 — Mesh + GPS + system glue | chrony.conf, batman-adv config, Avahi service definition, systemd units. | /etc configs + setup scripts. |
| Tab 4 — OLED / LED / button drivers | luma.oled status display, gpiozero LED logic, button event handler. | nomio_status.py systemd service. |
While Tab 1 is writing the DSP pipeline, Tab 2 is scaffolding the React UI, Tab 3 is producing the chrony / batman-adv configs, and Tab 4 is writing the OLED driver. Each tab is its own independent task with no shared state. You're the integration layer — pull all four into the repo, resolve the rare config conflict, run end-to-end. Four hours of parallel chatting replaces a full weekend of sequential coding.
Bench setup — first detection in one room
- Both Jetsons on AC power, sitting on your desk ~30 cm apart. Skip the battery for now.
- Both KrakenSDRs plugged in over USB. Antennas just dangling — even the random coat-hanger is fine for direct-path reception of a 50 kW FM tower 5 km away.
- Wired Ethernet between Jetsons and your Mac via a cheap unmanaged switch. Makes SCP / SSH instant. Wi-Fi works too but adds latency.
- VS Code on your Mac, Remote-SSH'd into Jetson 1. Edit code on the Jetson directly. Save → systemd restart → see effect.
- Open four chat tabs with me as described above. Drive each track in parallel.
- For the first drone fly-by: stand by the open window. Have a friend (or yourself, with a timer) fly a small drone 50–100 m past the window. Both Jetsons should see the bistatic Doppler trace simultaneously.
One-day timeline (with all shortcuts active)
| Time | What happens | You | Me |
|---|---|---|---|
| 9:00 AM | Boot pre-flashed Jetson on AC. SSH from Mac. | Power, Ethernet, ssh nomio@nomio-a1.local. | Walk you through first-boot Wi-Fi config and SSH key. |
| 9:30 AM | VS Code Remote-SSH connects. Repo cloned. Open 4 parallel chats. | Set up VS Code, clone repo, open chat tabs. | — |
| 10:00 AM | KrakenSDR streaming 5-channel IQ. First spectrogram. | Plug in USB. Run vendor's kraken_test. | Tab 3 writes a 10-line capture script. I read the spectrogram you paste back, confirm FM tower is visible. |
| 11:00 AM | cuFFT cross-ambiguity skeleton running. | Run my code, paste outputs. | Tab 1 writes the cuFFT cross-ambiguity. Tabs 2 / 3 / 4 in parallel writing UI / mesh / status. |
| 1:00 PM | Lunch. | — | — |
| 2:00 PM | End-to-end pipeline: SDR → cross-ambiguity → range-Doppler PNG dumped every second. | Paste the PNG to me, I tell you what's wrong. | Iterate on Tab 1. Tab 2 has a basic UI showing detections. |
| 3:30 PM | CFAR detector firing on direct-path. False alarm rate tuned. | Watch journalctl -fu nomio-radar. | Tab 1 wraps CFAR. Tab 4 has the OLED showing detection count. |
| 4:30 PM | First drone fly-by. Friend / partner flies a small drone past the window 100 m out. | Open the window. Watch the OLED + tablet UI. Confirm the Doppler trace. | Standby — read the output, suggest tuning if needed. |
| 5:00 PM | Detection confirmed. git tag v0.1-first-detection. | Beer. | — |
What still takes the second weekend
- Mounting in the 3D-printed case — when the print is done. Mostly mechanical work, no debugging.
- Battery / outdoor deployment — moving from bench to actual field positions on tripods. Real RF environment, real weather, real distances.
- Tuning CFAR for your specific environment — every site has a different clutter profile. Iterative.
- Polishing the operator UX — turning the bench-grade tablet UI into something you'd hand a non-engineer.
- Cloning to the second Jetson —
ddthe NVMe, change the hostname, set up mesh.
That's all real but undramatic work. The hard part is the first detection, and that fits in a Saturday with a competent partner.
User Interface — the operator's view
An Android tablet (or iPad) is the only thing the operator needs in the field. It runs a web app served from one of the sensor nodes, talks to the mesh over Wi-Fi, and pairs over Bluetooth on first use. No native app, no laptop, no flight sticks.
Pairing — once, in 5 seconds
- Boot a sensor node. Press the front-panel button. The OLED shows a 6-digit fingerprint of the node's network key.
- On the tablet, open the Nomio web app (just
http://nomio-a1.localwhen on the same Wi-Fi). Tap "Pair new node". Bluetooth scan finds the node. - Compare fingerprints. Tap "Confirm". Bluetooth exchanges the mesh key. Done.
- From now on, the tablet auto-joins the mesh whenever any sensor node is in range. Same model as Apple's AirTag/HomePod pairing.
What the tablet shows — v1 (sensor only)
┌─────────────────────────────────────────────────────────────┐ │ Nomio Operator Console mesh: ✓ GPS: ✓ power: 82% │ ├──────────────────────┬──────────────────────────────────────┤ │ MAP │ RANGE × DOPPLER (live, 10 Hz) │ │ ───── │ ┌────────────────────────────────┐ │ │ • Site A GPS ✓ │ │ ▒▒▒░░░ ▓ │ │ │ • Site B GPS ✓ │ │ ▒░░ ▓░ │ │ │ ✕ T-7 drone │ │ ░░ ▓ │ │ │ ✕ T-8 bird │ │ ░░ ░ │ │ │ ✕ T-9 car │ │ T-7 ◯ │ │ │ │ └────────────────────────────────┘ │ │ bistatic ellipses │ T-7 range 380m · -8.2 m/s · p=0.94 │ │ for each track │ │ ├──────────────────────┼──────────────────────────────────────┤ │ DETECTION QUEUE │ EVENT LOG │ │ T-7 drone p=0.94 │ 19:42:11 T-7 first seen, 580m bistat │ │ T-8 bird p=0.71 │ 19:42:14 T-7 classified drone p=0.94 │ │ T-9 car p=0.99 │ 19:42:30 T-9 confirmed across 2 nodes │ └──────────────────────┴──────────────────────────────────────┘
Three regions: map (left, ground-truth situational picture from the sensor mesh), range-Doppler heatmap + selected track (right, the actual radar output for the currently-selected detection), queue + event log (bottom, a chronological list of what's been seen).
What the tablet shows — v2 (with chasers)
When chasers are added in v2, the right-hand region splits to show live H.265 video from whichever chaser is currently engaged, with a command bar below for supervisory control. See the Chaser tab for details.
Channel comparison — why Bluetooth pairs and Wi-Fi streams
Several builders' instinct is to use Bluetooth for the data plane. It's the wrong fit. Here's the comparison.
| Channel | Throughput | Latency | Range | Right job for |
|---|---|---|---|---|
| Bluetooth 5.3 (LE 2M PHY) | ~700 kbps real | 20–40 ms | 10–30 m | Pairing, telemetry, audio. Not video. |
| Wi-Fi 6E (AX210, 5/6 GHz) | 500–1200 Mbps | 2–8 ms | 30–100 m direct, more on mesh | Video, control, sensor data — everything. |
| 5G / LTE (USB modem) | 50–500 Mbps | 20–80 ms | kilometres | Long-range backhaul (v2/v3). |
| Proprietary FPV (DJI O3, Herelink) | ~25 Mbps video + 4 Mbps control | 30–100 ms | 5–10 km | Manual override at distance. Out of scope. |
The AX210 module in the BOM already includes Bluetooth 5.3 as a side effect — it's a combo Wi-Fi+BT chip. So BT is on the unit anyway, doing what it's good at: short-range pairing.
Web UI implementation
- Single-page React app, built with Vite, served as static files from FastAPI on the sensor node.
- Detection stream over WebSocket from
/ws/detections. JSON messages, ~10 per second per active track. - Range-Doppler heatmap rendered to
<canvas>via WebGL. The heatmap is downsampled on the node side to ~256×256 px to keep the wire payload small. - Map uses MapLibre GL with offline tile bundles cached on the tablet.
- BT pairing uses the Web Bluetooth API in Chrome on Android, or a native helper app on iOS (Web Bluetooth isn't supported in iOS Safari; that's a known limitation).
Without a tablet — fall-back operator UX
- OLED on each node shows live status (GPS, SDR, peer count, dets/min, battery). Enough for "is it working" without any other device.
- LEDs on the front panel: green = healthy, blue blinking = waiting for GPS, blue solid = locked, red flash = active detection, yellow = low battery.
- SSH from any laptop on the same Wi-Fi:
ssh nomio@nomio-a1.localgets you a console with livetail -fon the detection log.
Extensions — near-term additions to v1
1. Micro-Doppler from rotors at FM band — feasibility
The first question worth answering: can the v1 FM-band passive radar see rotor-blade micro-Doppler, or only the bulk-motion Doppler of the airframe? Micro-Doppler is the modulation the spinning rotors impose on the reflected signal — a "fingerprint" that distinguishes a quad from a bird, a helicopter, or an airplane far more reliably than range/Doppler alone. It's the most powerful classification feature passive radar can produce.
The math says yes — modestly
Micro-Doppler resolution depends on integration time, not on illuminator bandwidth. With 1 s of coherent integration at 100 MHz FM:
- Doppler resolution: 1 / 1 s = 1 Hz
- Velocity resolution: c · 1 Hz / (2 · 100 MHz) = 1.5 m/s
- Quad rotor tip speed: 5,000 RPM × 0.12 m radius × 2π / 60 = ~63 m/s (so tip Doppler shift = ±42 Hz at FM — well within resolvable range)
- Number of resolvable bins on the rotor: ~84 / 1 = ~80 Doppler bins across the blade-tip return — more than enough to see "blade flash" lines
What it costs to add
- Pipeline change only — no new hardware. Increase coherent integration time from the 0.1 s baseline (used for fast detection) to 1–2 s for confirmed targets. Render the result as a 2D micro-Doppler-vs-time spectrogram (the "blade flash" pattern is unmistakable visually).
- Cost: 0$ in hardware, ~1 weekend of pipeline work. Add a "long-CPI confirmation pass" stage after the v1 detector fires.
- Compute headroom: the Jetson has ~50% spare at 10 Hz with 0.1 s CPI. A 2 s CPI confirmation runs once per detection (not every frame), so the GPU cost is trivial.
- Classifier benefit: blade-flash micro-Doppler is the single feature that most reliably separates "drone" from "bird" in VLM zero-shot classification. Send the spectrogram patch to the VLM with a prompt like "Does this micro-Doppler spectrogram show periodic blade-flash modulation lines? Yes/no, and if yes, estimate the rotor RPM." — VLMs handle this surprisingly well.
Prior art (FM-band rotor micro-Doppler on drones)
- Schroeder & Edrich, "FM-radio-based passive radar — UAV detection with focus on micro-Doppler features," FHR / IRS conference, 2017.
- Malanowski et al., "Detection of small UAVs using passive radar with FM and DAB illuminators," Warsaw University of Technology, 2018+.
- Daun & Berger, "Track-before-detect for small UAV in FM-PCL," Fraunhofer FKIE.
- Pell et al., "Drone classification from FM passive-radar micro-Doppler," 2020.
2. Acoustic mic-array — nighttime / RF-quiet complement
RF passive radar struggles in two situations: heavy urban RF clutter, and any environment where the ambient FM signal is weak (rural, indoors, behind a hill). A small acoustic mic array bolted to the side of the v1 sensor box gives you a completely independent detection modality — one that's actually better at night, when consumer drones are most likely to be flown for surveillance or smuggling.
What the literature says
- Consumer quads emit a distinctive 80–200 Hz fundamental (rotor passing frequency) plus harmonics out to ~5 kHz. Easily detectable to ~300–500 m in still, quiet air with even a single omnidirectional mic.
- A 4-element microphone array (~10 cm spacing) gives ±5° bearing-of-arrival on the drone via cross-correlation TDOA. Two acoustic-equipped sentries triangulate position the same way the FM passive radar does — and they don't care whether the FM tower is up.
- Acoustic detection is largely weather-independent at short range, works in zero ambient RF, and provides a strong "yes it's a drone" confirmation signal because the acoustic signature is unmistakably mechanical.
Hardware
| Component | Cost | Notes |
|---|---|---|
| 4× MEMS digital mics (Knowles SPH0645LM4H or InvenSense ICS-43434) | ~$5 ea / $20 total | I²S digital out, ~62 dB SNR, plenty for drone signatures. |
| Mic mount plate (3D-printed) | negligible | 4 mics in a 10-cm square, mounted on the sensor case side. |
| I²S → USB audio bridge (or use Jetson's built-in I²S pins) | $0–25 | Jetson Orin Nano dev kit exposes I²S directly on the 40-pin header — likely no extra hardware needed. |
| Total per sentry | ~$20–50 | Trivial cost. |
Pipeline
- ~50 lines of Python + numpy/scipy. 16 kHz sampling on 4 channels, sliding 1 s STFT, peak-pick the harmonic stack, GCC-PHAT TDOA across mic pairs for bearing.
- VLM confirmation: render the 4-channel spectrogram as one image, ask the same VLM that does RF classification: "Is this the acoustic signature of a small consumer drone?" One-line prompt, same code path as the radar classifier.
- Sensor fusion: when both RF radar and acoustic agree on direction within ~10° → very high confidence drone detection. When only one fires, lower confidence. The operator sees both in the UI.
3. Cell-tower variant — illuminator swap on the same hardware
The v1 build is FM-illuminated. A cell-tower (LTE / 5G NR sub-3 GHz) variant replaces only the antenna and the reference-channel logic — every other piece of the v1 system is unchanged. It's the natural next step once v1 is working, especially in areas with weak FM coverage but dense cell sites.
What changes vs v1
| Component | v1 (FM) | v1.5 (LTE / 5G cell) |
|---|---|---|
| Illuminator | Local FM tower, 88–108 MHz, ~10 kW | Local cell sites, 600–3500 MHz, ~40–80 W EIRP per sector — but many visible at once |
| Useful bandwidth | ~100 kHz | 10–100 MHz per channel (LTE 20 MHz / 5G NR 100 MHz) |
| Range resolution | ~1.5 km | ~1.5–15 m — two orders of magnitude better |
| Antenna | Two log-periodic for 88–108 MHz | Two wideband sub-3 GHz log-periodic or discone (cheaper, smaller) |
| SDR | KrakenSDR (5×RTL-SDR, 2 MHz BW) | USRP B205mini ($1,200) or BladeRF 2.0 xA9 ($720) for >10 MHz BW per channel — or KrakenSDR if you only need LTE control-channel detection (limited) |
| Reference channel | Direct path from the FM tower (point antenna at it) | Software synthesis of LTE PSS/SSS/CRS from 3GPP standard — generated locally, no separate antenna needed |
| Multistatic geometry | 1 illuminator, 2 receivers | 5–20 cell sectors visible from one receiver → free multistatic from a single sentry |
| Coverage | Wherever FM coverage is strong | Anywhere with cell coverage — basically everywhere populated |
| Software changes | — | Replace reference-channel acquisition with PSS/SSS/CRS regeneration. Pipeline math unchanged. |
Why this is the elegant successor to v1
- Same architecture. Two ground sentries, GPS-disciplined timing, mesh + tablet. Drop-in.
- Open-standard waveform. 3GPP specs are public — the reference channel synthesizes from spec, no blind reconstruction, no proprietary puzzle. Much easier than Starlink.
- Mature prior art. ESA, NATO, Lockheed, Hensoldt, and several university groups have working LTE / 5G passive radar. It's a known-good technique, decades of literature.
- Hardware cost: marginal. A wideband SDR replaces the KrakenSDR ($720–1,200 vs $400). Antennas drop in price. Per-sentry total roughly the same as v1.
- Range resolution improves 100×. 15 m vs 1.5 km. Drones are no longer "blob in a big bin" but "object with measurable structure."
- Free multistatic. From one ground location you see 5–20 cell sectors as separate illuminators — automatic geometric diversity.
4. Dual-illuminator (FM + cell tower) — the natural endpoint
Once both pipelines exist, there's no reason to choose. Run FM and LTE simultaneously on the same sentry, with each illuminator getting its own dedicated SDR + antenna array. Two cross-ambiguity pipelines on the same Jetson, fused at the track level. The Orin Nano Super has the GPU headroom and the BOM cost is modest.
Why it's worth doing
- FM gives long range, cell gives high resolution. FM detects the drone at 1–3 km but in 1.5 km bins. Cell only sees out to ~0.3–1 km but in 15 m bins. Combined you get FM's range with cell-confirmed structure once the target enters the cell-illuminated zone — best of both.
- Two completely independent modalities. A real drone shows up coherently in both bands. Birds, RFI, multipath ghosts, and most jamming attempts show up in only one. Cross-band agreement is a near-free false-alarm killer.
- Defense in depth against jamming. Adversary has to deny two very different bands (88–108 MHz and 600–3500 MHz) simultaneously. Vastly harder than jamming a single band.
- Geometric diversity stacks. 1 FM tower + 5–20 cell sectors = 6–21 independent bistatic geometries from one sentry. Track ambiguities resolve naturally.
Recommended hardware — two full KrakenSDRs (or Kraken + wideband)
The clean answer is to give each band its own full 5-channel array. Don't compromise the AoA precision on either band by sharing a single Kraken's channels.
| Band | SDR | Antenna array | Notes |
|---|---|---|---|
| FM (88–108 MHz) | KrakenSDR #1 ($400) | 5× FM dipoles, ~75 cm spacing | Unchanged from v1. |
| LTE sub-GHz (600–960 MHz) | KrakenSDR #2 ($400) — same hardware, retunes there fine | 5× compact log-periodic, ~10 cm spacing | Sub-GHz LTE bands are within KrakenSDR's tuning range and have the most range. Use this for the second board. |
| (Optional 3rd band) 5G mid-band (3.3–3.8 GHz) | USRP B205mini ($400) or BladeRF ($720) — single channel only | 1× 5G panel antenna | Above KrakenSDR's tuning range. Single-channel detection only (no AoA), used as a confirmation modality. Skip for the first build. |
BOM delta per sentry vs v1
| Item | Cost |
|---|---|
| Second KrakenSDR (sub-GHz LTE) | $400 |
| 5× compact LTE log-periodic antennas | $150 |
| External 10 MHz / 1 PPS distribution amp (drives both Krakens from the same GPS-OCXO → phase coherent) | $50 |
| Slightly larger Pelican case + extra mast bracket | $80 |
| Extra coax, connectors, bias-tee | $40 |
| Total per sentry add-on | ~$720 |
| New per-sentry total (v1 + dual) | ~$2,000 |
Two sentries = ~$4,000 total — still well below any commercial system, with simultaneous FM + LTE detection and full angle-of-arrival on both bands.
The numbers all check out on the existing Jetson
- USB. Each Kraken streams ~36 MB/s (3.6 MS/s × 5 ch × 2 B). Two Krakens = 72 MB/s. Jetson Orin Nano USB 3.2 = 5 Gbps ≈ 600 MB/s. Plenty of headroom.
- GPU. Two parallel cuFFT cross-ambiguity pipelines + two CFAR detectors ≈ 50% of Orin Nano Super's 67 TOPS. Plenty.
- Power. Each Kraken ~5 W. Sentry total goes from 25 W → 30 W. Same battery, same solar.
- GPS coherence. Drive both Krakens' external clock + PPS inputs from the same GPS-disciplined OCXO via a tiny RF distribution amp. The two boards are then phase-coherent with each other, enabling cross-band fusion that's not just track-level but signal-level if you ever want to go deeper.
- Antenna mast. FM dipole array (~3 m wide) on the bottom, LTE log-periodic array (~50 cm wide) on top. The frequencies are a decade apart — they don't electromagnetically couple in any meaningful way.
Operational handoff — FM acquires, cell confirms and refines
Because every sentry runs both bands concurrently, the two pipelines aren't an either/or — they're a tag-team that hands the target between them as it closes. The link-budget physics drives the sequence:
| Factor | FM (88–108 MHz) | Cell (~1 GHz LTE) | FM advantage |
|---|---|---|---|
| Transmitter power | ~10 kW per FM tower | ~80 W per cell sector | +21 dB |
| Wavelength² (aperture gain) | λ ≈ 3 m | λ ≈ 0.3 m | +20 dB |
| Drone RCS at this band | Rayleigh regime — small | ~Resonant — larger | –10 to –20 dB |
| Net SNR advantage to FM | ~+25 dB → ~3–5× longer detection range | ||
So in nominal geometry the operational sequence inside one sentry looks like:
- Drone enters at ~2 km. FM pipeline acquires it first. Coarse range (1.5 km bin) but a clean detection — the operator UI flashes a "candidate" track.
- Drone closes to ~800 m. Cell pipeline acquires the same target. Now the same track has a 15 m range bin, refined Doppler, and the start of micro-Doppler structure for classification.
- Inside ~500 m both pipelines track simultaneously. Cross-band agreement promotes the track from "candidate" to "confirmed." Operator UI goes red. The VLM classifier gets fed both spectrograms.
- Inside ~300 m cell dominates the position estimate (better resolution); FM provides redundancy and continues to track even if the cell network drops or is jammed.
Reference numbers from published prior art on similar consumer-quadcopter targets: FM-based passive radar reaches 1–3 km (Malanowski, Warsaw University); LTE-based reaches 0.3–1 km. Field tuning will shift these by ±50% depending on local FM/cell tower geometry, but the relative ordering — FM-first, cell-second — is consistent in the literature and falls directly out of the radar equation.
Software architecture
Two independent DSP pipelines run side by side, each producing its own track list. A small fusion module above them does track-level association: a candidate track is promoted to "confirmed" only if it appears in both bands within a small spatial + temporal gate (e.g. ±50 m, ±0.5 s). Single-band tracks remain visible but are flagged "single-modality" in the operator UI — important during the FM-acquired-only phase before the target enters the cell-illuminated zone. ~300 lines of Python on top of two copies of the v1.5 / v1 DSP code.
5. Other ideas captured here so we don't lose them
- DAB / DVB-T as a third illuminator — VHF-III (174–230 MHz) and UHF (470–800 MHz) digital TV. ~7 MHz BW gives ~21 m range resolution. Reference is fully decodable (open standard). Strong illuminator in Europe; less in the US. Slot between FM (v1) and LTE (v1.5).
- Camera + VLM cued from the radar — once a target is at known bearing, slew a $50 PTZ camera to it and capture a JPEG. Send the image + radar spectrogram + acoustic signature to the VLM together. "Three independent modalities all say drone" → very high confidence.
- Passive-RF emitter detection (companion modality) — most consumer drones emit a 2.4/5.8 GHz video downlink + telemetry. A second SDR pointed at those bands gives an independent detection channel that's deterministic when present (the drone is literally telling you it's there). Combine with passive radar to confirm.
- Lightweight on-device classifier as a gate before VLM — a tiny TensorRT model (a few MB) running on the Jetson can pre-filter the obvious noise and only escalate ambiguous detections to the VLM. Cuts API calls by ~10×, latency by ~5×.
- Long-baseline TDOA with a third sentry — adds true 3D localisation (altitude estimation), eliminates the 2-sentry ambiguity, only needs another KrakenSDR + Jetson box. ~$1,500.
- Solar / mains powering the sentries — current spec is 87 Wh power bank ⇒ ~3 hr runtime. A 100 W folding panel + small charge controller turns this into permanent deploy. Already noted in BOM but worth elevating.
- Auto-cue handoff to law enforcement / facility ops — when a confirmed drone enters a defined geofence, push an SMS / Slack / email with photo + bearing. Pure software, integrates with Twilio / Slack webhook in ~50 lines.
Suggested order of attack after v1 ships
- Acoustic mic array — best ROI by far. ~$20, weekend of code, qualitative leap in nighttime + RF-clutter performance.
- Long-CPI micro-Doppler confirmation — pure software, dramatic classifier improvement, no new hardware.
- Lightweight on-device classifier gate — cuts API costs, improves latency, frees compute headroom.
- Cell-tower (v1.5) illuminator swap — bigger lift (new SDR, new reference-channel code) but unlocks 100× range resolution and works where FM doesn't.
- Dual-illuminator (v1.5-dual) — once cell pipeline works, add a second KrakenSDR and run FM + cell concurrently. ~$720/sentry. Cross-band fusion eliminates most false alarms and raises the bar for jamming.
- Camera cue + RF emitter listener — small additions, dramatic classifier confidence improvement.
- Then Chaser / CAP / Starlink (the architectural rewrites in the Future tabs).
Chaser — v2 forward architecture
Three architectures to choose from
There are three clean ways to put the system together, and the right one depends on whether you're defending a fixed site, a mobile unit, or a forward position. Each is detailed below; this is the cheat sheet:
| Option A — Smart base, dumb drone | Option B — Smart drone, dumb base | Option C — Airborne CAP, no ground radar | |
|---|---|---|---|
| Where AI runs | Base-station Jetson + hosted VLM | Onboard Jetson on the chaser | Onboard Jetson on every chaser; ground is just a tablet |
| Sensor | v1 ground radar + chaser camera | v1 ground radar + chaser camera | Chaser cameras only — no ground radar |
| Comms | Continuous H.265 video (Mbps) | Telemetry only (kbps) | Swarm telemetry mesh + operator tablet |
| Per-chaser cost | $700 DIY / $2,790 DJI | $1,100–1,250 DIY | $1,300 DIY × 12 chasers (perimeter ring) or × 4 (raster fallback) |
| Deploy time | ~30 min (tripods + chaser) | ~30 min (tripods + chaser) | ~3–5 min (open case, launch) |
| Best for | POC speed, civilian, fixed site, single chaser | Production, multi-chaser, RF-denied, NDAA defense | Forward-deployed troops, mobile ops, expeditionary use |
Below: the original two options where ground radar does the wide-area surveillance, and a third where you skip the ground radar entirely and let an airborne swarm do both detection and engagement.
Two ways to split the AI: dumb drone (A) or smart drone (B)
Both of the next two options assume you have the v1 ground radar doing initial detection. They differ only in where the chaser's "is this still a drone?" intelligence runs:
| Option A — Smart base, dumb drone | Option B — Smart drone, dumb base | |
|---|---|---|
| Where the AI runs | Base-station Jetson (or hosted VLM) | Onboard Jetson on the chaser |
| Comms requirement | Continuous H.265 video uplink to base | Low-rate telemetry only (~1 kbps): "I see drone, here's where I am, here's what I'm doing" |
| Drone cost | $700–900 DIY or $2,790 DJI (POC default) | ~$1,000 DIY (with onboard Jetson) — DJI not available on consumer drones (Matrice-only, $14K+) |
| Range bound | Limited by video-link bandwidth | Limited by telemetry-link range only — much further |
| Operator visibility | Full live video | Status, position, occasional snapshots |
| Iteration speed | Fast — edit Python at base, restart | Slower — re-flash drone for each change |
| Multi-chaser scaling | Each needs its own video uplink — bandwidth dominates | Each is independent — scales easily |
| Best for | POC speed, civilian/research, single chaser, operator-rich workflow | Production, multi-chaser, RF-denied or air-gapped, NDAA-context defense |
Option A · Smart base, dumb drone
The chaser is deliberately stupid. It's a small quadcopter (~250–500 g) that does only three things: fly where it's told, stream H.265 video over Wi-Fi or OcuSync, and keep itself from crashing. All AI lives at the base station on a Jetson sitting next to the operator's tablet. Classification, target tracking, intercept geometry, abort decisions — all happen at the base. The chaser is just a flying camera with a flight controller.
This inverts the usual industry assumption (which is that the chaser carries its own AI compute). It works because we have a fat video link (OcuSync or Wi-Fi 6E) and a hosted VLM. The chaser doesn't need a Jetson, doesn't need a YOLO model, doesn't need a trained dataset. It needs a flight controller and a video link.
Chaser hardware (per chaser) — radically simplified
| Item | ~Cost | Notes |
|---|---|---|
| Frame: 5–7" carbon-fibre quad (e.g., iFlight, GEPRC) | $120 | Off-the-shelf FPV-style frame. |
| Flight controller (Pixhawk 6C or Holybro Kakute H7) | $80–200 | Runs PX4 or ArduPilot. Receives MAVLink waypoints over Wi-Fi from the base station. That's its only "intelligence". |
| Motors + ESCs + props | $200 | Standard FPV components. |
| Battery (4S 4Ah LiPo) | $60 | ~18 min flight time (no Jetson power draw). |
| Camera + H.265 encoder module (Runcam Hybrid 2 or DJI O3 Air Unit) | $150–230 | Self-contained 4K camera with built-in hardware H.265 encoder + Wi-Fi or analog out. No companion computer needed. |
| Wi-Fi 6E module (USB or onboard) | $25 | Joins the same mesh as the sensors. Carries MAVLink in, video out. |
| Antennas, cabling, mounting | $50 | — |
| Removed. The sensor-mesh Jetson does all the inference. The chaser doesn't need one. | ||
| Total per chaser | ~$700–900 | Down from $1,000–1,300. Build 2–4 of these. |
Industry chasers typically include a $500–1,500 companion computer (Jetson, Khadas, RB5) running on-board YOLO. By moving the brain to the base station and using a hosted VLM, the chaser collapses to "FPV drone with a video link" — a $700 part you can build from a kit.
Even better: skip the build, use a DJI
Once the chaser is "just video + waypoints", building a custom airframe is mostly hobby effort. The pragmatic move is to use an off-the-shelf DJI drone with the Mobile SDK as the chaser. You get a flight controller, gimbal, obstacle avoidance, RTH, GPS, 30+ minute battery, type certification, and a tested 5–15 km video link — all free, all reliable, all already built.
Three things to understand before picking this path: how DJI actually communicates, which SDK you need, and where the gotchas are.
How DJI drones communicate
Consumer DJI drones (Mavic, Mini, Air, Avata, FPV) talk to a remote controller (RC) over a proprietary RF link called OcuSync (currently O3 / O4 — the latest generation). It's a 2.4 / 5.8 GHz frequency-hopping link with adaptive bitrate, ~5–15 km range, and ~120 ms glass-to-glass video latency. The RC then connects to a phone or tablet via USB. Your Mobile SDK app on the phone gets the video stream and sends commands back, all via the RC.
So the path looks like:
DJI drone <-- OcuSync RF --> DJI RC <-- USB --> Android phone (your MSDK app) <-- Wi-Fi --> base-station Jetson
The phone is the bridge. It runs your Android app (built against MSDK v5), pulls H.265 video and telemetry from the drone, sends the video over Wi-Fi to the base-station Jetson for VLM tracking, and forwards waypoints/commands back to the drone. No 3G/4G needed for short-range work — the Wi-Fi 6E mesh you already have for sensors covers it.
For longer range or BVLOS work, the alternative is an enterprise drone (Matrice 30/300/350) with an LTE module — the drone uploads video over 4G straight to the cloud or your server, no RC needed. But you don't need that for v2.
Which SDK to use
| SDK | Where your code runs | Drones it supports | Use for our case? |
|---|---|---|---|
| Mobile SDK (MSDK v5) | Android (preferred) or iOS app | Mavic 3 / Air 3 / Mini 4 Pro / Avata 2 / FPV / Matrice — basically the whole current line | Yes. Right fit. Build a small Android app with Kotlin or Flutter; the assistant scaffolds it. |
| Onboard SDK (OSDK) | Companion computer bolted to the drone | Matrice 300/350/30 (enterprise only) | No — enterprise-only, expensive. We don't need a companion computer on the drone anyway. |
| Payload SDK (PSDK) | Custom payload device | Matrice series | Only if you bolt a net launcher / specialized payload. Skip for v2. |
| Cloud API / FlightHub 2 | Server-side | Matrice + LTE dongle | For BVLOS. Skip for v2. |
Recommended drone
| Drone | Cost | Top speed | Flight time | Notes |
|---|---|---|---|---|
| DJI Mini 4 Pro + RC 2 | ~$760 | 16 m/s | 34 min | Sub-250 g class — fewer regulatory hoops in most jurisdictions. MSDK supported. Good first chaser. |
| DJI Mavic 3 Pro + RC 2 | ~$2,200 | 21 m/s | 43 min | Bigger camera, longer range (15 km), best video for VLM tracking. The mid-range default. |
| DJI Avata 2 + RC Motion 3 | ~$1,000 | 27 m/s | 23 min | FPV-style, faster, more agile — built for pursuit. Use if you want to actually catch up to fast targets. |
| DJI Matrice 30T + RC Plus | ~$13,000 | 23 m/s | 41 min | Enterprise: thermal camera, IP55, LTE option, OSDK + PSDK. Only if you're going production. |
Trade-offs vs the DIY airframe
| DIY FPV airframe | DJI + MSDK | |
|---|---|---|
| Up-front cost (per chaser) | ~$700–900 | $760–$2,200 |
| Build effort | Soldering, PID tuning, flight testing | Open the box, register in DJI Fly, install your MSDK app |
| Reliability | You own all the failure modes | Battle-tested by millions of flights |
| Flight time | ~18 min (4S 4Ah) | 30–45 min |
| Range | ~150–300 m on plain Wi-Fi 6E. 1+ km requires a directional base antenna or a cellular modem on the drone (see "Long-range link options" below). | 5–15 km OcuSync, no extra hardware. |
| Video latency to base | ~40 ms over Wi-Fi (short range), ~80–200 ms over LTE | ~120 ms (OcuSync) + ~30 ms (USB → app → Wi-Fi to Jetson) |
| Geofencing / no-fly zones | None — full control | DJI GEO 2.0 enforces zones; unlockable for licensed operators but a hassle |
| Custom payloads (net launcher, beacon) | Bolt anything you want | Only via PSDK on Matrice (enterprise) |
| Use in defense / DoD context | Allowed | Banned — NDAA Section 848, US DoD blue-list excludes DJI; UK/AU/JP have similar restrictions for sensitive use. Acceptable for civilian / commercial / research. |
| Iteration speed on autonomy | Fast — you own the FC | Fast — you own the MSDK app; FC behaviour is fixed but exposed via the API |
The "headless RC" pattern — fully SDK-driven, no human pilot
OcuSync is closed. There is no OcuSync receiver chip you can wire into the Jetson directly — the only thing on Earth that demodulates an OcuSync stream is a DJI controller. So the RC stays in the system, but a human never touches it. It becomes a $0-extra USB-to-OcuSync dongle that sits inside the base-station case with antennas sticking out.
Mavic 3 Pro
| OcuSync RF (15 km, proprietary, free)
v
DJI RC 2 <-- headless: paired once, then sits next to the Jetson
with antennas up. Converts OcuSync to H.265 over USB.
| USB-C
v
Android instance <-- Anbox/Waydroid container on the Jetson, OR a
$40 Android TV stick, OR an old phone zip-tied
to the rig. Runs your MSDK v5 app (~200 lines Kotlin).
| localhost / Wi-Fi
v
Jetson Orin Nano (base station)
- NVDEC decode H.265
- CSRT fast tracker (30 Hz)
- VLM slow tracker (1 Hz)
- Mission executor sends WaypointV2 / VirtualStick back up the chain
From the operator's perspective it's pure SDK: the tablet shows the video, supervisory buttons drive WaypointV2 commands, no one ever picks up a controller. The RC is hardware infrastructure, not a UI device.
What changes in the rest of the architecture
Almost nothing. The fast/slow visual-tracker loop on the base-station Jetson is unchanged. Steering corrections become DJI VirtualStick or WaypointV2 commands (issued via the MSDK Android app) instead of MAVLink to a Pixhawk. The hybrid VLM tracker doesn't care what the airframe is.
Per-chaser BOM — DJI / SDK path
| Item | ~Cost | Notes |
|---|---|---|
| DJI Mavic 3 Pro Cine Combo (with RC 2) | ~$2,200 | Drone, gimbal, RC 2 controller, charger, props. RC 2 is the headless OcuSync dongle. |
| Spare batteries (×3) | ~$450 | For continuous operation while one charges. ~2 hr coverage with hot-swap. |
| Charging hub | ~$80 | — |
| Android TV stick OR re-use an old Android phone | ~$40 (or $0) | Hosts the MSDK v5 app. Skip if running Anbox/Waydroid on the Jetson. |
| USB-C OTG cable, mounting brackets | ~$20 | RC → Android, antenna stand-offs. |
| Total per chaser | ~$2,790 | 3× the DIY cost, ~3 weeks less build time, much higher reliability. |
For a POC, build one chaser. Add more only after the single-chaser loop works end-to-end against a real test drone.
Where the smarts actually live — the base station
The base station is just an extra Jetson Orin Nano (the same module as the sensor nodes) sitting on the operator's table next to the tablet. It runs:
- Mission executor. Takes high-level operator commands (INVESTIGATE, RTB, ABORT, HOLD) and translates them into waypoints — MAVLink for the DIY airframe, DJI
WaypointV2/VirtualStickfor the Mavic. Trivial state machine, ~500 lines. - Hybrid visual tracker (described in detail below). A fast local tracker keeps a bounding box on the drone every frame; a hosted VLM verifies identity periodically. ~600 lines of Python.
- Intercept-geometry planner. Given target velocity (from radar) and chaser state, computes a safe approach trajectory. Modified pursuit-curve logic. ~1K lines.
- Safety layer. Geofencing, battery-reserve return, lost-link return, radar-vision cross-check abort. The legally-mandatory part for civilian use. ~1K lines.
- Operator UI bridge. Same tablet as v1. Adds video feed + supervisory buttons. ~400 lines on top of the v1 web app.
- Terminal action (if applicable). Net-launcher trigger, beacon-emit-and-track, escort-and-land — depending on what the chaser is for. Always human-authorized via the supervisory pattern. ~200 lines plus the hardware.
Total base-station code: ~3K lines, all on one Jetson, all easy to iterate. When you want to upgrade the tracker, you edit one Python file. You don't re-flash any drones.
Hybrid visual tracker — fast local loop, slow semantic loop
The naïve "send every frame to Claude" pattern doesn't work for live pursuit: a hosted VLM round-trip is 200 ms – 2 s, and a drone moving at 10 m/s covers 10 m in that second. We solve it the way classical robotics does — two loops at different speeds:
| Loop | Rate | Job | Implementation |
|---|---|---|---|
| Fast loop (tracker) | 30 Hz (~33 ms) | Keep a bounding box locked on the drone every frame. Output: pixel coords + size. | Classical CV (CSRT or MOSSE correlation tracker, OpenCV) — works because the background is uniform sky. Or YOLO-World with prompt "small flying drone" — open-vocabulary, no training, ~50 ms on the Orin. |
| Slow loop (semantic verifier) | 0.5–2 Hz (every 0.5–2 s) | "Is this still our drone, or did we drift onto a bird / helicopter / a second drone? Is the bounding box still on the right object?" Output: bool + corrected box if needed. | Hosted VLM (Claude Haiku / GPT-4o / Gemini Flash), or a tiny local VLM (Moondream 2, ~150 ms on Orin) for air-gapped operation. |
| Very slow loop (operator) | ~0.1 Hz (every 10 s) | Final judgement: continue, abort, switch target. | Human eyes on the tablet. |
The fast loop drives the steering. The slow loop catches the failure modes the fast loop is blind to: target swap, occlusion recovery, "wait that's actually a kite". When the slow loop disagrees with the fast loop, the fast loop gets corrected (or the system pauses and asks the operator).
Tracker options — pick by what's available
| Tracker | Per-frame cost | Setup | When to use |
|---|---|---|---|
| OpenCV CSRT | ~5 ms (CPU) | One line of Python, no training, no GPU | Default for v2. Sky background = trivially robust. Bootstrap with the VLM's first bounding box, then track frame-to-frame. |
| YOLO-World (open-vocab, prompt: "drone, quadcopter") | ~50 ms (CUDA on Orin) | No training; just download the weights | If you want a real detector that can also re-detect after losing lock. No labelled dataset needed. |
| Moondream 2 (small VLM, local) | ~150 ms (Orin) | Pip install | Best of both: VLM-quality reasoning at near-real-time. Drop-in replacement for the slow loop when offline. |
| Claude Haiku / Gemini Flash (hosted VLM) | 200–700 ms | API key | Best quality. Use for periodic verification, occlusion recovery, identity checks. |
| YOLOv8n trained on drones | ~5 ms (CUDA) | ~1 day to label + train + deploy | Only if you've already collected the data. Skip for v2; revisit in v3. |
The recommended default for v2: CSRT (fast loop) + Claude Haiku (slow loop, every 1 s). Total tracker code: ~150 lines. No training. Cents per mission.
End-to-end latency budget — chaser pursuit
| Loop | Step | Time | Notes |
|---|---|---|---|
| Fast loop — runs every frame, drives steering | |||
| Fast | Camera capture → H.265 encode | ~30 ms | Hardware encoder on the camera module. |
| Fast | Wi-Fi 6E uplink (chaser → base) | ~5 ms | Single hop, line-of-sight. |
| Fast | NVDEC + frame extract at base | ~5 ms | Hardware decoder on the base Jetson. |
| Fast | CSRT correlation update | ~5 ms | OpenCV, CPU. |
| Fast | Steering correction → MAVLink → chaser | ~10 ms | Wi-Fi back down. |
| Fast loop total | ~55 ms (≈18 Hz steering) | Plenty for tracking a 10 m/s drone with metre-class precision. | |
| Slow loop — runs every ~1 s, verifies identity | |||
| Slow | Pick representative frame, send to VLM | ~10 ms | Just the network upload — frame is already in memory. |
| Slow | VLM API call (Claude Haiku / Gemini Flash) | 200–700 ms | Or 150 ms with local Moondream 2. |
| Slow | Update target identity / correct fast tracker | ~5 ms | Adjust CSRT bounding box if the VLM moved it. |
| Slow loop total | ~250 ms – 1 s | Runs in the background; doesn't block the fast loop. | |
The flight controller's innermost loop (attitude stabilization) runs at 200 Hz on the chaser regardless — that's the part that physically can't tolerate latency, and it's already local. The base station only ever issues outer-loop guidance ("steer 5° left", "climb 2 m"). That outer loop at 18 Hz from the fast tracker is more than enough for visual pursuit; it's the same control bandwidth a human FPV pilot has.
Option B · Smart drone, dumb base
Invert the architecture: put the AI on the chaser. The drone carries its own Jetson, runs the detector and tracker locally, makes its own go / no-go decisions about whether it's looking at a drone, and only sends a thin telemetry stream back: "I see a quadcopter, confidence 0.92, range 80 m, my position is X/Y/Z, I'm pursuing — should I continue?". The base station becomes a thin supervisory console, not a real-time AI engine.
What runs on the drone
The chaser becomes self-sufficient. Same software pattern as the base-station Jetson in Option A, just running on a smaller, drone-mounted Jetson:
- Onboard tracker. CSRT or YOLO-World at 30 Hz from the local camera. Same code as Option A's fast loop, just runs locally and never blocks on a network.
- Onboard classifier. A small VLM like Moondream 2 (~150 ms/frame on Orin Nano) or YOLO-World with the prompt "small flying drone, quadcopter, helicopter, bird, kite" — open-vocabulary, no training, no labelled dataset. The drone makes its own "yes this is the target" / "no, this is a bird" judgements.
- Onboard mission executor. Same state machine as base in Option A, just lives on the chaser. Takes high-level commands from the operator (INVESTIGATE, RTB, ABORT) over a low-bandwidth telemetry link, runs the pursuit locally.
- Periodic snapshot uplink. Every 1–2 s, the chaser sends a single ~50 KB JPEG to the operator tablet plus a few hundred bytes of telemetry. Enough for human-in-the-loop supervision; nothing like the bandwidth of a live H.265 stream.
Onboard compute options
| Module | Cost | Mass | Power | What it can run |
|---|---|---|---|---|
| Jetson Orin Nano Super 8 GB | $249 | ~50 g | ~13 W | YOLOv8 at 100 fps, YOLO-World at ~50 ms, Moondream 2 at ~150 ms, CSRT at <5 ms. The sweet spot. |
| Jetson Orin NX 16 GB | ~$700 (module only) | ~70 g (with carrier) | ~25 W | Larger VLMs (Llama-3.2-Vision 11B Q4 at ~2 s, or a quantized 7B model real-time). Overkill unless you need full VLM reasoning on-drone. |
| Hailo-8 + Pi 5 | ~$330 | ~80 g | ~7 W | YOLOv8 at 30 fps via Hailo NPU. No real VLM. Lower power than Jetson but more glue. |
| Coral Edge TPU + Pi Zero 2 | ~$80 | ~30 g | ~3 W | YOLOv8-nano at ~15 fps. Cheap and light, but no VLM, capped at small models. |
For v2, the Jetson Orin Nano is the obvious default — same module as the sensor nodes, same software stack, same JetPack environment. The drone literally runs a stripped-down clone of the base-station image.
BOM — Option B (DIY airframe with onboard Jetson)
| Item | ~Cost | Notes |
|---|---|---|
| Frame: 7" carbon-fibre quad (extra payload margin) | $140 | Needs to carry the Jetson + heatsink. |
| Flight controller (Pixhawk 6C) | $200 | MAVLink over UART to the onboard Jetson. |
| Motors + ESCs + props | $220 | Slightly beefier to lift the extra weight. |
| Battery (6S 5Ah LiPo) | $90 | Bigger pack to power the Jetson and offset its weight. |
| Jetson Orin Nano Super 8 GB + carrier board | $249 | The whole point. |
| Camera (Arducam IMX477 MIPI CSI, direct to Jetson) | $80 | Native to Jetson — no extra encoder needed. |
| Long-range telemetry radio (ELRS / RFD900x / 4G LTE modem) | $50–150 | Carries low-rate command/telemetry, not video. Tens of km range. |
| Antennas, cabling, vibration isolation, heatsinks | $80 | The Jetson needs airflow. |
| Total per chaser | ~$1,100–1,250 | Cheaper than DJI Option A ($2,790), but adds ~3 weeks of build + flight tuning. |
Why no DJI in Option B: consumer DJI drones don't let you mount a companion computer with your own code. Only Matrice 30/300/350 with OSDK do, and those start at ~$13K. So Option B is effectively DIY-only unless you're spending enterprise money.
Trade-offs vs Option A
| Option A (smart base, dumb drone) | Option B (smart drone, dumb base) | |
|---|---|---|
| Per-chaser hardware | $700 DIY / $2,790 DJI | $1,100–1,250 DIY only |
| Drone weight (effect on flight time) | Light — no Jetson, no heatsink | +50 g Jetson, +50 g bigger battery + bigger frame → ~15% less flight time per Wh |
| Comms link required | Continuous H.265 video uplink (Mbps) | Telemetry only (kbps) + occasional snapshot |
| Operational range | Bound by video link (Wi-Fi ~300 m or OcuSync ~15 km) | Bound by telemetry link — RFD900x reaches 40 km, 4G modem works anywhere with cell coverage |
| Tracking latency | ~55 ms fast-loop / ~1 s slow-loop (network-bound) | ~5 ms local CSRT / ~150 ms local Moondream — much faster decisions |
| Loss-of-comms behaviour | Drone has to RTB or hover — it doesn't know what to do | Drone keeps pursuing; degrades to RTB only after configurable timeout |
| Operator visibility | Full live video on tablet — exactly like FPV | Status, position, periodic snapshots — like watching a tracked vehicle on a map |
| Iteration speed on tracker / classifier | Edit Python on base, restart, fly. Seconds per cycle. | Re-flash drone, re-test, fly. Hours per cycle. |
| Scales to N chasers | Each consumes a video uplink — bandwidth dominates fast | Each is independent and only sips telemetry — scales cleanly to swarms |
| NDAA / defense use | DJI path banned; DIY path OK | OK |
| POC time | ~3 weeks with DJI | ~6–8 weeks (build airframe + onboard software + flight test loop) |
Option C · Airborne CAP — chaser swarm, no ground radar
A third architecture: skip the ground radar entirely. Station a ring of self-sufficient chasers (Option B compute pattern) on the perimeter of the area you're defending, each looking outward with 360° vision. Every inbound threat must cross the ring to reach the protected unit — so detection becomes a tripwire, not a search. Each chaser is both sensor and interceptor; when one sees a target, the adjacent drones instantly triangulate, and the nearest closes for terminal action. The "base station" is just a tablet plus a charging pad.
This is essentially the architecture Anduril's Roadrunner, Israeli SkyLock, and the Ukrainian FPV-interceptor programs are built on. It's the right pattern for a forward-deployed tactical scenario — troops being targeted in the field, threat area is known approximately, deploy time matters, and you can't set up two tripod-mounted radar sites.
The perimeter ring pattern — preferred mode
The cleanest deployment is a fixed perimeter ring, not a raster search. Here's the geometry:
- Station the drones in a circle at 500 m – 1 km radius around the protected unit. 9 drones equally spaced = each owns a 40° wedge of azimuth.
- Four cameras per drone — one on each face of the airframe — give every chaser a full 360° view. Onboard Jetson Orin Nano supports up to 4 MIPI CSI cameras natively. Adds ~$120 to the per-chaser BOM (3 extra IMX477 sensors).
- Each drone holds station at ~150 m altitude and watches outward. Because the FOV per camera (~90°) is wider than the 40° wedge each drone "owns", adjacent drones see overlapping airspace — so every patch of horizon is visible to at least two drones simultaneously.
- Detection is a tripwire, not a search. Any inbound threat must cross the ring to reach the protected unit. The instant it enters the field of view of any ring drone — typically when it's still ~500 m outside the ring — it's seen, in the next camera frame. Detection latency: ~33 ms, not 10–30 s.
- Triangulation is free. Two adjacent drones see the same target from different angles. Two-bearing intersection gives 3D position to ~5–15 m accuracy at 500 m. Same physics as the v1 ground radar — airborne and instant.
- Battery rotation. When a drone's battery drops below 30%, it flies inward to land at the charging pad while a fresh one takes its station. ~30 s gap per swap; the neighboring drones' overlapping FOV covers the temporary blind spot.
Coverage math — perimeter ring
| Parameter | Value | Note |
|---|---|---|
| Ring radius | 500 m – 1 km from protected unit | Trade-off: larger ring → bigger detection bubble, more battery used flying out, harder to swap rotation. |
| Drones in ring | 6–9 | 9 gives ~40° per drone with comfortable FOV overlap; 6 works if cameras have ~120° FOV. |
| Cameras per drone | 4 × 90° → full 360° | +~$120 per chaser in BOM. Onboard Jetson Orin Nano handles 4 simultaneous CSI streams. |
| Visual detection range outward | ~500 m | 30 cm quadcopter, 4K camera, YOLO-World. Telephoto on 1–2 drones can push to ~1 km. |
| Detection bubble (radius from protected unit) | 1–1.5 km | = ring radius + per-drone detection range. |
| Detection latency (target crosses ring) | ~33 ms | Next camera frame at 30 Hz. Not a search problem. |
| Triangulation accuracy (two adjacent drones) | 1–3% at 500 m → ~5–15 m position fix | Two-bearing intersection; geometry is excellent because the drones are far apart. |
| Total drones for indefinite persistence | 9 ring + 3 on charge = 12 total | One always rotating; ~2 hr per swap cycle per drone. |
| Deploy time | ~3–5 min | Drones launch, fly to assigned station coordinates, hold. |
| Power per drone (hover) | ~250 W | Hovering uses about the same as low-speed cruise on a multirotor; ~25 min on a 6S 5Ah pack. |
The raster pattern — alternative when you have fewer drones
If you have only 3–4 chasers (not 9–12), the ring becomes too sparse to be a reliable tripwire. In that case, fly a coordinated raster pattern instead: each drone owns a sector and sweeps it at 15 m/s, ~150 m altitude. Detection latency rises to 10–30 s (depending on raster phase), but you cover the same area with a third of the assets. Use raster for low-budget POC; upgrade to a ring once you have hardware to support it.
Hardware — same as Option B, plus 3 extra cameras per drone
Per-chaser BOM is Option B + four cameras instead of one:
| Item | Cost vs Option B | Notes |
|---|---|---|
| Option B base BOM | $1,100–1,250 | Frame, FC, motors, ESCs, battery, Jetson Orin Nano, telemetry radio, etc. |
| +3 extra IMX477 MIPI CSI cameras | +$120 | Mounted one per face of the airframe. |
| +Camera multiplexer / CSI hub | +$40 | Orin Nano carrier supports up to 4 cameras directly with the right adapter board. |
| Per-chaser total (ring mode) | ~$1,260–1,410 | Slightly heavier (~30 g extra) but flight time impact is <1 min. |
The "base station" collapses to:
- One Jetson Orin Nano running mission coordination, video aggregation, operator UI, and the supervisory tablet bridge
- One ruggedized tablet for the operator
- Multi-bay charging pad / battery hot-swap station (capacity for 12 × LiPo packs)
- One long-range telemetry radio (RFD900x or LTE modem) to talk to the swarm
Total system cost for a 12-chaser perimeter ring: ~$15,500–17,000 (12 × $1,300 chasers + ~$1,500 ground kit). Substantially more than the 4-chaser raster system (~$6,000) — but you get persistent 360° coverage with sub-second detection latency over a 1.5 km bubble.
Comparison: perimeter ring vs raster CAP
| Perimeter ring (9 drones) | Raster CAP (3–4 drones) | |
|---|---|---|
| Detection latency | ~33 ms (next frame) | 10–30 s (depends on raster phase) |
| Detection bubble | 1–1.5 km radius around unit | ~1.5 km radius, but probabilistic |
| Triangulation | Always available (two adjacent drones see every target) | Requires second drone to converge, +15–30 s |
| Chasers in air at once | 9 | 3 |
| Total chassis needed | 12 (9 + 3 charging) | 4 (3 + 1 charging) |
| Cost | ~$15,500 | ~$6,000 |
| Best for | Fixed forward position, "we'll be here for hours" | Mobile column, fast-moving ops, smaller budget |
Terminal action options
"Crash into it" is one option, but you have a spectrum:
| Action | Per-engagement cost | Reusable? | Notes |
|---|---|---|---|
| Kinetic ram | ~$1,200 (lose the chaser) | No | Most reliable, simplest. Acceptable trade if the target is a $50K loitering munition. |
| Net launcher | ~$50 (net) + drone recovery | Yes | Skydio + Fortem do this commercially. Drone returns, net is consumable. Custom payload needed. |
| EW disruption (jammer / spoofer) | ~$0 (just airtime) | Yes | Onboard 2.4/5.8 GHz jammer module disrupts the target's control link. Legally limited in many jurisdictions; defense-only. |
| Escort + beacon | ~$0 | Yes | Just stick to the target, broadcast its position, let ground operators decide. Useful for surveillance / intel. |
| Designate for ground fire | ~$0 | Yes | Chaser shines a laser designator; ground asset takes the shot. Pure cue-and-paint. |
Trade-offs vs ground-radar approach (v1 + Option A/B chaser)
| v1 ground radar + chaser | Option C airborne CAP | |
|---|---|---|
| Deploy time | ~30 min (two tripod sites) | ~3–5 min (open case, launch) |
| Covertness | High — passive, no emissions | Lower — drones are visible and audible |
| Mobility | Static, tied to tripods | Fully mobile, swarm moves with the protected unit |
| Threat-direction prior | 360° coverage, no prior needed | Need to know roughly where threats come from |
| Detection range | 500–1500 m, depends on illumination geometry | 200–500 m from each chaser — but the chaser moves, so effective range = patrol radius + 500 m |
| Persistence | Indefinite (mains-power site) | Indefinite with battery rotation; needs charging logistics |
| Cost (4-asset system) | ~$5,500 | ~$6,000 |
| Per-engagement cost | ~$0 (radar is reusable, chaser may or may not be) | ~$0 to $1,200 depending on terminal action |
| Best fit | Fixed sites (bases, infrastructure, perimeters) | Forward-deployed troops, mobile operations, expeditionary use |
Honest gotchas
- False positives. Birds at 300 m look exactly like drones. The VLM verification loop is what keeps you from wasting interceptors on geese. Mandatory.
- Multi-target prioritization. If the threat is a swarm, you need the chasers to not all converge on the same target. Trivial bidding protocol in code, but a real design point.
- Collision avoidance between friendlies. 3–4 drones in the same airspace. ADS-B-like beacon plus geofenced wedges per drone solves it, but you have to design for it.
- Weather. 30-min flight time becomes 20 min in 30 km/h winds. Plan for it.
- Radio congestion. Telemetry mesh between chasers + uplink to operator on the same band as the target's control link is a recipe for interference. Use a dedicated swarm band (915 MHz / 433 MHz for telemetry) separate from the target's 2.4/5.8 GHz.
- Legal. Airborne armed CAP is a defense-context capability. Civilian operators get net-capture or escort-and-report; kinetic terminal action is military / authorized law-enforcement only.
Real-world precedents
This isn't speculative — variants of this architecture are operational:
- Anduril Roadrunner-M. Reusable VTOL interceptor with onboard AI, launched on cue. Same architectural pattern.
- Anduril Anvil-M. Smaller kinetic interceptor; same idea at lower price point.
- Israeli SkyLock + Smash Dragon. Forward-deployed counter-UAS with onboard detection.
- Ukrainian "Sting" interceptors. Effective wartime use of FPV-class drones for counter-UAS, mostly with human-in-the-loop piloting today; the autonomy pieces are being added.
- Fortem DroneHunter. Net-capture interceptor, used at fixed sites and as a CAP asset.
What's new here isn't the architecture — it's that the per-chaser cost has dropped from $30–100K (Anduril class) to ~$1,200 (Jetson + commodity airframe + open-source autonomy), thanks to the same two trends that made v1 cheap: cheap edge-AI compute and foundation-model classifiers that skip the training step.
Hybrid (Option AB) — fast loop on drone, slow loop at base
The pragmatic mature design borrows from both options:
- On the drone: CSRT + tiny detector (YOLO-World) running locally at 30 Hz drives steering. Drone keeps tracking even if comms drop.
- At the base: the drone uplinks 1–2 frames per second over telemetry. Base runs a hosted VLM ("is this still the right target? did we drift to a kite?") and sends back identity corrections. Operator sees the full picture.
- Comms requirement: ~100–500 kbps (a few JPEGs/sec + telemetry), much less than the multi-Mbps of full Option A but more than the bare-telemetry Option B. Works over LTE, RFD900x with a video board, or short-range Wi-Fi.
This is what you eventually want for production. Start with Option A, evolve to Hybrid AB. Pure Option B only if your operational envelope demands it.
How the operator interacts in v2
- Confirmed track from sensor mesh appears on the tablet. Audible alert: target confirmed.
- Operator taps INVESTIGATE. The mesh dispatches the nearest idle chaser. Live H.265 video appears on the tablet within a few seconds.
- Operator can issue HOLD (chaser circles), RTB (return to base), ABORT (immediate safe land), or SWITCH TARGET.
- For systems with a terminal action, AUTHORIZE TERMINAL requires two paired tablets to confirm within a 5-second window — a hard-coded two-person rule. Configurable for non-kinetic systems.
- Chaser executes, returns, lands itself, recharges. Operator never piloted anything.
Why this is the right pattern
Three reasons to lean hard on supervisory control over either extreme:
- Legal. Civilian C-UAS regulations in essentially every jurisdiction require a human in the loop for any kinetic action. Fully autonomous engage is not legal almost anywhere.
- Robust. The autonomy will get edge cases wrong (news helicopter, mistaken classification, GPS-spoof attack). A human at the supervisory layer is the cheapest, most reliable last-line defence.
- Scalable. One operator can supervise 4–8 chasers in parallel. Manual piloting tops out at one operator per drone. Fully autonomous is nominally infinite-scale but isn't trusted enough yet.
Where v2 fits in the timeline
These estimates assume you're working with an AI coding assistant (Claude, Cascade, DeepSeek, etc.) writing 90%+ of the code. The bottlenecks are physical: hardware lead times, antenna placement, field testing windows, regulatory approvals — not lines of code.
- v1 (this guide): sensor mesh + tablet. Two focused weekends of work after parts arrive — one to assemble and bring up, one to tune in the field. Demonstrates detection, classification, multi-site fusion.
- v1.5: add a 3rd and 4th node, swap incoherent fusion for real TDOA 3D localization. One weekend on top of v1: nodes 3 & 4 are clones of node 1's image, and TDOA from already-aligned timestamps is ~200 lines of Python the LLM writes in an hour. The week-ish of elapsed time is parts shipping, not coding.
- v2 (chaser): single chaser drone with autonomy stack and supervisory UI. Realistically 2–4 focused weeks of work, gated by flight-test windows and the iteration loop on the vision tracker. Most of the "12-month" number you see in industry is regulatory paperwork, hiring, and writing code by hand — none of which apply here.
- v3 (multi-chaser, productized): swarm dispatch, formal regulatory approval, hardening for sustained outdoor operation. This is the only stage that is genuinely months of work, and almost none of it is code — it's airworthiness, certification, and operational pilots.
v1 is the only thing in this build guide. v1.5 is a small addendum. v2 is its own project, but not the year-long death-march it would be without an AI pair-programmer.
CAP — v3 perimeter ring defense
The big idea — sentries and seekers
Two specialised drone roles, not one:
- Sentries form a ring at ~1 km radius around the protected unit, hold station, watch outward, and never leave their post. They're the sensors. Reusable, expensive, persistent.
- Seekers sit on a launch pad at the base. When sentries detect and triangulate a threat, the operator authorises and one seeker launches, flies to the target's GPS coordinates, and executes the terminal action. Cheap, fast, often expendable.
Any inbound threat must cross the ring to reach you — so detection becomes a tripwire, not a search. Two adjacent sentries triangulate the target the instant it appears. The base station combines their bearings, verifies via VLM, and dispatches a seeker. Sentries stay put — ring integrity is preserved during engagement, so a second threat doesn't slip in while the first is being handled.
This is the loitering-munition pattern (Anduril Anvil-M, Switchblade 300, Lancet 1) split into a sensor+interceptor team. The novelty here is cost: per-sentry ~$1,300 and per-seeker ~$300–500 thanks to the same two trends that made v1 cheap — sub-$300 edge-AI compute and foundation-model classifiers that skip the training step.
Top-down geometry
9 drones at 1 km radius, each with a 90° camera FOV looking outward. Every wedge of horizon overlaps with two adjacent drones, giving instant two-bearing triangulation.
Single drone — 4 cameras = 360° vision
Per-drone hardware: Jetson Orin Nano + 4 cameras, one per face of the airframe. +$160 over a single-camera chaser. Onboard YOLO-World runs on all 4 streams in parallel.
Triangulation — two bearings, one position
Same physics as the v1 ground radar — two known positions, two bearings, intersection is the target. Airborne, instant, and with much better geometry because the drones are ~680 m apart.
Battery rotation — indefinite persistence
Base station — quiet most of the time
The base station is not the brain of the swarm. The sentries are. Each sentry runs its own onboard YOLO-World on its 4 cameras, and adjacent sentries swap bearings directly with each other over the mesh to triangulate. The base is silent during nominal operation — no video streams, no detector running, no triangulation. It only wakes up when neighbors have already agreed on a track and the operator needs to authorise a seeker.
Concretely, the base station does three things, all of them rare:
- Receive track packets from the mesh — JSON, ~1 kB, fired only when two adjacent sentries have triangulated a candidate. Maybe a few per hour in quiet airspace.
- VLM verify — one JPEG patch is pulled from the closest sentry on demand, shipped to Claude/Moondream, "is this a drone?" Sub-second.
- Operator authorise → dispatch seeker — tablet shows the track + image, operator taps AUTHORIZE, base fires
WAYPOINT + ENGAGEto a seeker on the pad.
If the base is jammed, destroyed, or simply turned off, the ring keeps detecting and triangulating. Seekers can't be dispatched without it, but situational awareness survives — that's the whole point of pushing the smarts to the edge.
The base is a dispatcher and a human gate, not a sensor processor. Detection and triangulation happen at the ring.
Seeker — the cheap kamikaze (or net-capture) interceptor
Seekers don't need to detect, persist, or hold station. They only need to fly fast to a GPS coordinate, optically lock on the last 100 m, and execute. So they can be radically simpler and cheaper than sentries:
| Item | Cost | Notes |
|---|---|---|
| Frame: 5" or 7" FPV-style quad | $70 | Off-the-shelf carbon-fibre. Fast, agile, cheap. |
| Flight controller (Speedybee F405) | $40 | Tiny FPV-grade FC running ArduPilot or Betaflight. Receives waypoint command from base. |
| Motors + ESCs + props | $80 | FPV racing-class. ~25 m/s top speed. |
| Battery (4S 1300 mAh LiPo) | $25 | ~8–10 min flight time. Enough to reach any target inside the 1.5 km bubble + ram. |
| Camera + tiny ML module | $30 (Pi Zero 2 + camera) or $50 (Coral USB) | Single forward camera. Coral or Pi+Camera runs YOLO-nano for terminal homing — "lock on the white quadcopter shape and steer toward it". |
| GPS + telemetry radio (ELRS Rx) | $30 | Receives target GPS from base, reports its own position back. |
| Optional: net launcher (instead of kinetic ram) | +$80 | If you want reusable seekers — drone fires net at target, returns home. ~30 g extra payload. |
| Total per seeker | ~$275–$355 (kinetic) / $355–$435 (net) | Stockpile 4–6 ready on the launch pad. |
Operationally: target's GPS arrives from sentry triangulation, base sends WAYPOINT(x,y,z) + ENGAGE to a seeker, seeker takes off, climbs to target altitude, navigates GPS, and at ~100 m switches to optical lock. Last-100 m homing handles any drift in the GPS estimate. Time-to-engage from detection: ~30–60 s depending on target distance.
How sentries communicate — mesh, not cellular
Cellular is a non-starter for any contested or tactical scenario. LTE jammers are commercial products that cost ~$100, take down a base station, and the drones go silent. Even in non-tactical use, cellular concentrates a single point of failure (the cell tower). Real swarms don't use it. Here's how they actually communicate:
| Method | Jam resistance | How it works | Used by |
|---|---|---|---|
| Fiber-optic tether | Perfect (zero RF) | Physical cable from base to drone, carries data + power | CyPhy LVL-1, Israeli surveillance drones, Spike missiles |
| Mesh radio (MANET, FHSS) | Excellent | Drone-to-drone peer network, packets route around jamming or downed nodes; FHSS on every link | US Army Wave Relay, Silvus, Doodle Labs Mesh Rider |
| DJI OcuSync | Good (proprietary FHSS) | Star: drone ↔ one RC; not designed for mesh | DJI consumer / Enterprise |
| Cellular LTE/5G | Terrible | Drone ↔ tower ↔ server; fixed infrastructure, narrowband | Civilian only — not for tactical use |
Mesh radio — the right default
Every sentry carries a mesh-radio transceiver and routing software (this is mature, well-known technology). Each talks directly to its 2–3 nearest neighbors, not to the base. Packets hop drone-to-drone until they reach a destination. Self-healing: if a node drops out (jammed, shot down, low battery), neighbors detect the loss and route around it. The base station is just another node — typically with a high-gain antenna — not a single point of failure.
For a 9-drone ring, any sentry reaches any other in at most 3 hops, ~5–15 ms latency per hop. Triangulation gets cleaner: adjacent sentries swap bearing measurements directly with their two neighbors and triangulate locally before forwarding the result to base via the mesh.
| Mesh radio | Cost / node | Throughput | Range | Notes |
|---|---|---|---|---|
| Doodle Labs Mesh Rider | $300–1,500 | 5–20 Mbps | ~5 km LoS | The right starting point for DIY / prosumer / research scale. |
| Persistent Systems MPU5 | $2–5K | 5 Mbps | ~5 km LoS | Military-hardened, US DoD-standard radio. |
| Silvus StreamCaster 4200 | $4–10K | 30 Mbps | ~10 km LoS | Heavy NSA-grade, used in DoD swarm programs. |
Add ~$500 per sentry to the DIY BOM for a Doodle Labs Mesh Rider. Mesh + 4-camera onboard AI fit together perfectly: each sentry only needs to send ~10 kbps of telemetry over the mesh (because the AI ran locally), not 5 Mbps of video. The 10 Mbps mesh becomes a swarm command-and-control bus with comfortable headroom.
Fiber tether — for static deployments
If the protected unit is going to stay put for hours-to-days (forward observation post, fixed installation, base perimeter), fiber-tethered sentries are an option:
- 9 fibers run from the base out to 9 station points at 1 km radius
- Each sentry hovers at its station with the tether providing both data and power
- Infinite flight time — no battery rotation, no charging logistics
- Totally unjammable, zero RF — invisible to RF SIGINT, immune to all electronic warfare
- Catches: tether limits altitude to ~150 m practical, positions fixed once deployed, ~9 km of fiber to lay (deployment is a logistical operation, not "3 minutes"), tangling risk in wind, terrain has to cooperate
Tethered systems exist commercially: Elistair Orion 2 (~$30K/system), Hoverfly LiveSky, Equinox Innovative Systems tether kits. DIY is feasible — a 1 km micro-fiber + power tether spool runs ~$500–1,500 — but you give up most of the rapid-deploy advantage.
Free-space optical (FSO) — laser between drones
Genuinely better than RF on every axis except weather and pointing complexity. A modulated laser between two drones gives Gbps bandwidth, near-zero latency, practically unjammable, and almost undetectable by adversary RF SIGINT — the beam is narrow and aimed up, not radiating to the ground. Used by DARPA SDA satellites and Mynaric/Tesat in the satellite world; making its way to airborne platforms.
The challenge you'd expect: how does each drone know where the other one is, accurately enough to keep a narrow beam locked on? Standard solution is Pointing, Acquisition, and Tracking (PAT):
- GPS gives rough position (±2 m). Both ends know roughly where the other is.
- Wide-beam optical beacon (~30° cone LED) for initial discovery. Other drones see it, refine the bearing.
- Narrow tracking beam locks on once coarse bearing is known. This is the high-rate data link.
- Fast steering mirror (FSM) on the gimbal corrects beam direction at hundreds of Hz to compensate for drone vibration and wind.
| RF mesh (Doodle Labs) | Free-space optical | Fiber tether | |
|---|---|---|---|
| Jam resistance | Excellent | Outstanding — needs an attacker physically in the beam path | Perfect |
| Bandwidth | ~10 Mbps | Gbps possible | Gbps |
| Range | ~5 km | ~1–2 km (atmospheric) | Tether-limited |
| Weather robustness | Excellent — RF punches through | Poor — fog, rain, dust, snow attenuate; can ground the link | Perfect |
| Vibration / pointing | Trivial — omni antennas | Hard — needs PAT subsystem on every link | Trivial |
| Acquisition time (cold) | <1 s | 5–30 s for first lock | Instant |
| Adversary RF SIGINT detectability | Some emissions | None — beam is narrow and aimed away from ground | None |
| Cost per node | ~$500 (off-the-shelf) | $5K–50K (Mynaric Condor class) / ~$2–5K research DIY | $500–1,500 tether spool |
| Maturity for sub-2 kg drones | Production, mature | Cutting-edge — no turnkey prosumer kit yet | Production for static use |
For a v3 build today, FSO is a great future-direction but the wrong primary link: the optical terminal would cost more than the drone, and a foggy day would ground your sentries. The right architecture for a v3.5+ production system: mesh radio as the always-available backbone, FSO as a high-bandwidth jam-immune upgrade layer between key nodes when conditions allow, fiber tether on the most critical sectors. This is exactly what mature military systems do — optical primary + RF backup + adaptive routing.
Hybrid: mesh-default with tether option
For now, the practical system is: mesh radio everywhere (handles mobility, weather, rapid deploy), with fiber tether on critical sectors if the protected unit will sit for hours-to-days. Add FSO as an upgrade layer once production volume justifies the cost.
Sentry options — DIY 4-camera vs DJI
Now that comms is settled, the sentry choice is between:
| DIY 4-camera sentry + mesh radio | DJI Mavic 3 Pro + RC + base aggregation | |
|---|---|---|
| Cost per sentry | ~$1,800 ($1,300 + $500 mesh radio) | ~$2,200 |
| Onboard AI | Yes — Jetson Orin Nano runs detector locally | No — DJI consumer drones can't host code |
| Cameras | 4 × IMX477 → 360° vision | 1 × gimbal-mounted 4K, can yaw to scan |
| Comms architecture | Mesh — peer-to-peer, jam-resistant, self-healing | Star — each drone ↔ one paired RC at base |
| Jam resistance | Excellent | Good (OcuSync FHSS) but not mesh; star topology fails if base RF is contested |
| 9 sentries co-located spectrum issue | None — mesh is designed for many co-located radios | Yes — 9 simultaneous OcuSync star links co-located is at the edge of FHSS coordination |
| Build time | ~3 weeks airframe + integration | ~3 days — open boxes, write MSDK app |
| NDAA-allowed | Yes | No |
| Flight time | ~25 min | ~43 min |
| Total ring cost (12 = 9 + 3 rotation) | ~$21,600 | ~$26,400 |
| Use case | Tactical, contested RF, NDAA defense | Civilian / commercial / research POC where jamming isn't a threat |
Recommendation: DIY 4-camera + Doodle Labs mesh for any tactical use — only path that's actually jam-resistant and NDAA-clean. DJI Mavic 3 Pro only for civilian POC where you're proving out the architecture and don't yet care about a contested RF environment.
Quick numbers
| Parameter | Value |
|---|---|
| Ring radius | 500 m – 1 km from protected unit |
| Drones in ring | 9 (each owns a 40° wedge) |
| Cameras per drone | 4 × 90° = full 360° |
| Visual detection range outward | ~500 m (30 cm quadcopter, 4K + YOLO-World) |
| Detection bubble radius | 1–1.5 km from protected unit |
| Detection latency | ~33 ms (next camera frame) |
| Triangulation accuracy | ~5–15 m at 500 m range |
| Sentries (with rotation) | 9 ring + 3 charging = 12 |
| Per-sentry BOM | ~$1,800 DIY (with mesh radio) / ~$2,200 DJI Mavic 3 Pro |
| Seekers stockpiled | 4–6 ready on launch pad |
| Per-seeker BOM | ~$300 kinetic / ~$400 net-capture |
| Base station | One Jetson Orin Nano + mesh radio + tablet + pad ≈ $1,800 |
| Total system cost (DIY tactical) | ~$25,200 ($21,600 sentries + $1,800 seekers + $1,800 base) |
| Total system cost (DJI civilian POC) | ~$29,700 ($26,400 + $1,800 + $1,500) |
| Time from threat appears to seeker engages | ~30–60 s (detection ~33 ms + auth ~5 s + flight ~20–55 s) |
| Deploy time (cold to first sentry airborne) | ~3–5 min |
When CAP wins vs ground-radar approach
| v1 + Chaser (ground radar) | v3 CAP (perimeter ring) | |
|---|---|---|
| Deploy time | ~30 min | ~3–5 min |
| Mobility | Static (tripods) | Moves with the protected unit |
| Covertness | High — passive RF | Lower — drones are visible / audible |
| Threat-direction prior | None needed (360°) | Roughly known threat azimuth helps siting |
| Detection latency | ~100 ms (radar update) | ~33 ms (camera frame) |
| Position accuracy | ±20–50 m | ±5–15 m |
| Total cost (full system) | ~$5,500 | ~$25,200 (DIY tactical, with mesh) / ~$29,700 (DJI civilian POC) |
| Best fit | Fixed sites (bases, infrastructure) | Forward-deployed troops, expeditionary use |
Full design details, terminal-action options, gotchas, and real-world precedents are in the Chaser tab → Option C. This tab is the visual summary.
Starlink — v4 satellite-illuminated passive radar
The idea in one paragraph
A Starlink satellite paints a ~24 km wide spot beam of high-power Ku-band downlink (~11 GHz, ~240 MHz wide) onto any patch of ground it's serving. That beam is a free, continuous, high-bandwidth radar illuminator. Any drone flying through it scatters energy that a ground-based passive receiver can pick up. The 240 MHz of waveform bandwidth gives ~0.6 m bistatic range resolution (vs ~150 m for FM); the moving satellite gives strong Doppler separation; overlapping beams from several satellites give multistatic geometry for free, with no infrastructure of yours required.
Top-down geometry
Satellite is the illuminator. Ground sentries listen for both the direct path (reference) and the drone-scattered echo (signal). Bistatic geometry, new illuminator class.
What's new vs v1, v2, v3
- Sentries become stationary again. No flying, no battery rotation, no charge pads. Mains-powered tripod boxes — like v1, but with 5–15 km reach.
- Fiber back-haul replaces the mesh radio. Sentries are stationary, so a physical cable is the obvious answer. Zero RF emissions, near-infinite bandwidth, dramatically cheaper than mesh.
- Seeker layer unchanged from CAP (v3). Cheap kamikaze / net-capture drone on a launch pad. The only flying part of the system.
- Minimum viable system is 2 sentries (sometimes 1, with extra hardware). You don't need a perimeter — see Architecture tab.
Why Starlink is a uniquely good illuminator
| Property | FM broadcast (v1) | DVB-T | Starlink downlink (v4) |
|---|---|---|---|
| Frequency | 88–108 MHz | ~600 MHz | ~10.7–12.7 GHz (Ku) |
| Useful bandwidth | ~100 kHz | ~7 MHz | ~240 MHz per channel |
| Bistatic range resolution | ~1500 m | ~21 m | ~0.6 m |
| Illuminator stationarity | Fixed tower | Fixed tower | LEO sat at 7.5 km/s — strong, predictable |
| Coverage | Region around tower | Around tower | Anywhere with sky view — including remote / maritime |
| Target RCS at this frequency | Sub-resonant for drone — small | Near-resonant — modest | Above-resonant — large; rich micro-Doppler from rotor blades |
| Rain / atmospheric loss | Negligible | Negligible | Several dB at heavy rain (Ku — known limit) |
| Adversary jamming difficulty | Easy (one tower) | Easy (one tower) | Extreme — thousands of moving sats |
Two effects matter most. First, the 240 MHz bandwidth turns the radar from "drone-sized fuzzy blob" into "drone-sized object with measurable structure" — range resolution finer than the drone itself. Second, Ku-band is above the resonance frequency of a typical small quad's rotors, which means strong micro-Doppler signatures from the spinning blades — a fingerprint that distinguishes a quad from a bird far more cleanly than FM ever could.
The hard problems (and what's known about each)
- Reference-channel synthesis. Conventional passive radar needs a clean copy of the transmitted waveform as a reference. Starlink doesn't broadcast one — its frames are encrypted, FDMA+TDMA, and beam-steered. Two known workarounds: (a) a dedicated dish pointed at a known active beam to grab the direct path as-is; (b) blind reference reconstruction using the dominant direct-path arrival. Both have been demonstrated in academic work (Strathclyde 2022, OHB 2023).
- Beam dwell. Starlink beams hop frequently. Continuous tracking on a single illuminator is hard; you treat each beam dwell (~tens of ms) as a coherent radar burst and accumulate hits across many bursts and multiple satellites.
- Constellation knowledge. You need TLEs + a beam-pointing model to know which beam is illuminating your airspace at any moment. TLEs are public; beam-pointing is partially inferable from radio observation, partially proprietary. There's an arms race here.
- Regulatory / business risk. Using a private operator's downlink as an illuminator is legal for passive reception in most jurisdictions, but SpaceX could change waveforms or beam policy. A serious deployment hedges by also supporting OneWeb / Kuiper / Iridium NEXT downlinks.
- Rain fade. Heavy rain attenuates Ku by 3–10 dB. Range drops in weather. Mitigation: more sentries, lower-frequency fallback (LTE / DVB-T).
Prior art and reading
- Ilioudis et al., "Passive radar with Starlink", IEEE Radar 2022 — first published demonstration of Starlink as illuminator for passive radar, University of Strathclyde.
- Garry & Smith, "Passive ISAR using LEO constellations" — broader treatment of using LEO downlinks as illuminators.
- ESA "PCL with LEO" study, 2023 — feasibility analysis for ESA's space-surveillance and ground-surveillance needs.
- OHB / Fraunhofer FHR experiments — Ku-band passive radar reference reconstruction techniques.
What's the minimum that works?
The 24 km Starlink spot tells you how big an area is being lit. It says nothing about how many sentries you need. Sentries are receivers, not transmitters — they triangulate the drone using bistatic geometry. The minimum number of sentries depends on what you want to measure, not on the size of the beam.
| Sentries | What you get | What you don't get | Verdict |
|---|---|---|---|
| 1 sentry, plain dish | A bistatic range (the target lies somewhere on an ellipse around the sat-to-sentry baseline) | No direction. Can't cue a seeker. | Detection only. Useful as a tripwire ("something flew through") but not for engagement. |
| 1 sentry + small phased array | Bistatic range plus angle-of-arrival → full 3D position | No redundancy. One outage = blind. AoA hardware is non-trivial at Ku. | Conceptually possible, but Ku-band AoA arrays are expensive and finicky. Not the right minimum. |
| 2 sentries ← practical minimum | Two bistatic ranges → two intersecting ellipses → 1–2 candidate target points. Altitude + sanity filtering picks the right one. | If one fails, you're back to range-only. | This is the right way to start. Two sentries on opposite sides of the protected area, plus a base station with the seeker pad. |
| 3 sentries | Three ellipses uniquely intersect at the target. No ambiguity. Survives one sentry failure. | Marginally more cost. | Sweet spot for redundancy + geometry. |
| 4+ sentries | Full overdetermined system. Highest accuracy, redundancy against multiple failures, best coverage of the whole sky. | Diminishing returns past 4–5 for a single protected site. | What a production deployment looks like. |
How accuracy scales with number of sentries
Position-error standard deviation scales roughly as σ ∝ 1/√N for N independent bistatic receivers, but the qualitative jumps are not on that curve. They're at 1→2 (ambiguity resolved) and 2→3 (redundancy gained):
| N | Accuracy vs 2-sentry baseline | What you actually gain |
|---|---|---|
| 1 | — (range only, no position) | Detection only. Bistatic range = an ellipsoid; target is somewhere on it. Theoretically resolvable by integrating over satellite motion, but SNR-bound and ephemeris-fragile. Don't cue seekers from this. |
| 2 | baseline (1.00×) | First N where you get a target position. Still ambiguous at certain geometries; altitude/sanity filtering resolves. Use this as the v4 starting point. |
| 3 | ~18% better (σ × 0.82) | The big qualitative jump. Three ellipsoids uniquely intersect — no ambiguity. Survives one sentry failure. Equilateral triangle around base → uniform 360° coverage. |
| 4 | ~29% better (σ × 0.71) | Marginal accuracy gain. Big robustness gain — survive two failures. Resolves ghost targets when 2 drones are airborne at once. |
| 10 | ~55% better (σ × 0.45) | Diminishing returns on static accuracy (only √5 better than 2). Real wins: full near-zenith coverage, 5+ simultaneous targets resolvable, multipath/occlusion immunity in cluttered terrain, survives many failures. |
Where to place 2 sentries — 90° vs 180° from base
Bistatic localisation accuracy scales with the angle subtended at the target by the two receivers. Bigger ground-plane separation between receivers → bigger angle at the target → better accuracy (up to ~90° subtended). With 2 sentries you have a real choice about layout:
- 180° apart (opposite sides of the base, maximum separation): uniform coverage of any threat azimuth. No blind back. Use this when you don't know the threat direction. The default for a base in featureless terrain or with all-around exposure.
- 90° apart (two adjacent corners of the protected area): the pair is biased toward one quadrant of the sky. Excellent localisation in that 90° sector, poor in the opposite 270° (both sentries see the target along nearly the same axis → ellipsoids barely intersect). Use this when you know the threat axis — e.g., a base whose suspected approach is "from the north." Put both sentries on the north side and get best-possible accuracy there.
- <30° apart: avoid. Both sentries are effectively "the same place" for triangulation purposes — you've spent twice the money for no localisation benefit, only redundancy.
Where the base goes (it doesn't have to be central)
The base station is just the place where fiber from each sentry terminates, the GPU sits, the operator's tablet plugs in, and the seeker pad lives. It doesn't have to be in the middle of the protected area. It can be:
- On a corner of the protected facility — common, since that's often where the existing comms shed or guard post already is.
- In a separate building 500 m away, with the fiber simply being longer. Single-mode fiber is happy out to 20–40 km without amplification.
- Co-located with one of the sentries, even — the "base" is mostly a piece of software, not a fixed geographic role.
The bistatic geometry depends on where the sentries are. The base is just where wires meet. Place it wherever the operator and the launch pad are convenient.
How far can a sentry be from the base?
Three different constraints, with very different numbers:
| Constraint | Limit | Notes |
|---|---|---|
| Fiber link | 40 km standard, 80+ km with long-haul optics | Single-mode fiber on standard SFP+ runs 40 km without amplification. Multi-mode (OM3/OM4) only ~300 m — don't use it outdoors. For runs beyond 40 km, use a long-haul SFP+ (~$150) or add a single passive optical amplifier. Fiber is essentially never the limiting factor. |
| Bistatic geometry — minimum | ~50 m | Below this, the triangulation baseline between sentries is too short. The two range ellipsoids cut at very shallow angles, position uncertainty blows up. Doesn't matter for a single sentry, but if you have 2+ sentries close together, you've wasted them. |
| Bistatic geometry — sweet spot | 200 m – 2 km | For drones at 50–500 m altitude, the angle subtended at the target between two sentries reaches ~80° somewhere around 1 km separation. Going further gives diminishing returns on accuracy. |
| Shared Starlink illumination | ~10–15 km | Both sentries need to be inside the same Starlink spot beam to triangulate one target from one illuminator. Beams are ~24 km wide; receivers within ~10–15 km of each other reliably share. Beyond that, sentries see different beams — the pipeline can stitch across illuminators, but it's harder. |
| Power-over-copper voltage drop | ~100 m at 12 V / 30 W | If you try to send 12 V power down a copper run with the fiber, voltage drop limits you to ~100 m on 14 AWG wire. Fix: put a battery + solar at each sentry (see Implementation tab), or run mains 230 V → DC at the sentry. |
Asymmetric placement is fine
Bistatic range ellipses don't care about symmetry. Place sentries where the terrain, infrastructure, and sightlines are best — rooftops, watchtowers, hillsides, perimeter walls. As long as no two sentries are at the same position (and ideally they're separated by hundreds of metres), the triangulation works.
Two solid sentries (N + E) are the minimum-viable v4 deployment — opposite sides of the protected site, one fiber each to base. The dashed S and W sentries are optional upgrades: a 3rd resolves bistatic ambiguity into full 3D position, a 4th adds n−1 fault tolerance. Cost grows roughly linearly per added sentry (~$1–1.5K each, centralised-DSP build).
Fiber, not mesh
Once the sentries are stationary, there's no good reason to use RF for the back-haul. Run physical fiber from each sentry to the base. The mesh radio comes out of the BOM entirely:
- Perfectly covert. Zero RF emissions from sentry to base — invisible to RF SIGINT.
- Effectively infinite bandwidth. A single SFP+ link is 10 Gbps. You can ship raw Ku-band IQ from sentry to base if you want — ~8 Gbps per sentry fits.
- Power over the same trench. Lay a power cable in the same conduit. No batteries, no solar.
- Cheaper than mesh. ~$80 of media converters + a few dollars per metre of outdoor fiber per sentry, vs $500 for a Doodle Labs mesh radio.
- Trivial topology. Star from base. No mesh routing, no neighbor discovery, just IP over Ethernet.
Where the DSP runs — centralised wins
With fiber bandwidth in hand, you can run all signal processing at the base instead of distributing it across edge Jetsons:
| Edge DSP (sentry-side) | Centralised DSP (base-side) | |
|---|---|---|
| Compute location | Jetson Orin Nano per sentry | One big GPU box at base (RTX 4090 / Orin AGX) |
| Data over fiber | Detection JSON only (~kB/s) | Raw IQ (~8 Gbps/sentry) |
| Per-sentry cost | +$249 (Jetson) per sentry | Sentry is just SDR + LNB + media converter (~$1,000) |
| Pipeline complexity | 4 nodes to maintain | One node, one log, one debugger |
| Multistatic fusion | Needs network protocol + clock sync | Trivial — all channels meet in one process |
| Best when | Lots of sentries (10+), thin fiber | Small number of sentries (≤6), short fiber runs |
For the 2–4 sentry minimum-viable build, centralised DSP is the right call. One $2,000 GPU box at base does cross-correlation, CFAR, and triangulation for all channels in a single process. Sentries collapse to dumb digitisers.
System cost — minimum viable
| Configuration | Sentries | Total | Notes |
|---|---|---|---|
| Minimum (detect + localise) | 2 | ~$6,500 | 2 × $1,200 sentry + $2,600 base + 2 × $400 seekers + $500 fiber. Get something working in a week. |
| Recommended (redundant) | 3 | ~$8,200 | 3 sentries, 4 seekers, more fiber. |
| Production fixed-site | 4 | ~$11,200 | 4 sentries, 6 seekers, full perimeter coverage. Cheaper than CAP, longer-range than v1. |
What's inside a sentry box
A sentry is a sealed outdoor enclosure (Pelican 1300 or 1400 class — roughly a shoebox) bolted to a roof, wall, or short post. Inside, in the order the signal travels:
Component breakdown
- Dish + LNB (external, on top of case). A ~45 cm offset dish (like the cheap ones sold for satellite TV) plus a universal Ku LNB ($30–60). The LNB sees 11 GHz Ku and down-converts it to ~1 GHz inside its own metal can, which the SDR can sample directly. The LNB is powered by 13/18 V DC sent up the coax.
- Bias-tee (inside case). A passive component that injects DC onto the coax going to the LNB. ~$30.
- Wideband SDR (inside case). Replaces the KrakenSDR — we need ~250 MHz of bandwidth, not 2 MHz. Options: USRP B205mini (~$1,200, well-supported), BladeRF 2.0 Micro xA9 (~$720), or HackRF One (~$330, BW-limited but functional). Connects to the Jetson via USB 3.
- Jetson Orin Nano dev kit (inside case). The 10 × 10 cm carrier board with the module on top — same hardware as v1. Runs the radar pipeline locally if you do edge DSP, or acts as a thin host streaming IQ over the fiber if you do centralised DSP. You can omit the Jetson entirely in the centralised-DSP build — the SDR streams IQ directly to a small Linux SBC (a $100 Raspberry Pi 5 is enough) which just forwards bytes over fiber.
- GPS HAT + GPS antenna (external puck on top of case). Disciplines the system clock to ~1 µs of GPS time. Same part as v1.
- SFP+ media converter (inside case). Tiny box that takes an RJ45 Ethernet cable on one side and gives you a single-mode fiber connector on the other. ~$40. Pair with another at the base.
- PSU (inside case). A 12 V DC supply rated for ~30 W to power everything. Driven by mains, PoE, or solar + battery.
How many fibers leave the case?
This is the whole reason fiber is so much nicer than mesh radio for stationary sentries: a single 10 Gbps optical link carries every bit the sentry generates, including raw IQ if you want it. At the base, four such fibers (one per sentry in the 4-sentry deployment) terminate in a small SFP+ switch.
What's at the base
- SFP+ switch with one port per sentry — e.g. a MikroTik CRS305-1G-4S+IN (~$150). Aggregates all incoming fibers.
- GPU compute box for centralised DSP — desktop PC with an RTX 4090 / RTX 4060 Ti / Jetson AGX Orin. ~$2,000.
- Operator tablet on Wi-Fi or wired — shows live track + asks for AUTHORIZE.
- Seeker pad — same as CAP. 2–6 launchable interceptors sitting outside ready to fly.
- Optional UPS — the system runs on mains. A small UPS gives 15 minutes of survival through a power cut.
Per-sentry BOM
| Component | Cost | Notes |
|---|---|---|
| Ku-band LNB (universal) | $30–60 | Satellite-TV part. Down-converts 11 GHz → ~1 GHz IF. |
| Bias-tee | ~$30 | Off-the-shelf inline 13/18 V supply. |
| Ku dish (~45 cm offset) | $60–150 | Cheap satellite-TV dish. Two if you want a separate reference dish. |
| Wideband SDR | $330–1,200 | USRP B205mini / BladeRF xA9 / HackRF One. |
| Jetson Orin Nano (edge DSP only) | $249 | Omit for centralised-DSP build; use a Raspberry Pi 5 (~$80) instead just for transport. |
| GPS HAT + antenna | ~$60 | Same as v1. ~1 µs time discipline. |
| SFP+ media converter (per end) | $40 | One at sentry, one at base. |
| PSU + cable glands + 12 V supply | $60 | 30 W is plenty. |
| Pelican 1400 case + mounting hardware | $200 | IP67 sealed; mounts to roof, wall, or post. |
| Per sentry (centralised-DSP build) | ~$1,000–1,500 | Cheapest viable sentry. |
| Per sentry (edge-DSP build) | ~$1,500–2,100 | Adds the Jetson. |
Power — yes, it runs from a 12 V car battery
Everything in a sentry box is 12 V or 5 V native (the SDR + Jetson + media converter all want one of those rails), so a single 12 V DC source feeds the whole thing through a small buck converter. A standard 100 Ah lead-acid car battery (~1,200 Wh) gives a sentry ~40 hours of standalone runtime. Add a 100 W solar panel and a $30 MPPT charge controller and the sentry runs indefinitely.
| Component | Power draw | Voltage rail |
|---|---|---|
| Ku LNB (over coax) | ~5 W | 13/18 V from bias-tee |
| Wideband SDR (B205mini / BladeRF) | 5–8 W | USB 5 V |
| Jetson Orin Nano (edge DSP) | ~10 W avg, ~15 W peak | 12 V DC barrel |
| or Raspberry Pi 5 (centralised DSP) | ~5 W | 5 V USB-C |
| GPS HAT | ~1 W | 5 V GPIO |
| SFP+ media converter | ~2 W | 5 V |
| Sentry total | ~25–30 W | fed from 12 V |
Base station: an SFP+ switch (~10 W) + Jetson AGX Orin as the GPU box (~30 W typical) + tablet (~5 W) + idle seeker pad (0 W) ≈ 50 W total. Two car batteries in parallel give a couple of days. If you choose an RTX 4090 desktop instead of an Orin AGX, the base draws 200–400 W and you'd want a 1,000 Wh+ deep-cycle battery or just plug into mains.
Power options ranked by deployment style
The sentry just needs 12 V at ≥3 A. Anything that produces that works. Pick by mission length:
| Option | Capacity / runtime | Cost | Best for |
|---|---|---|---|
| USB-PD power bank + 12 V trigger cable | 60 Wh / ~2 h | ~$50 | Bench testing, 1-hour proof-of-concept. |
| 12 V router-UPS battery (20,000 mAh) | 74 Wh / ~2.5 h | ~$50 | Same tier — disposable demos. |
| 50 Ah LiFePO4 battery in the Pelican case | 640 Wh / ~21 h | ~$200 | Recommended fast-deploy. Drop in case, no mains, no solar. Swap or recharge at end of day. ~6 kg. |
| Jackery Explorer 300 (293 Wh, 12 V out) | 293 Wh / ~10 h | ~$200 | Pre-packaged "just plug it in" kit. 3 kg. |
| Bluetti AC50S (500 Wh, 12 V out) | 500 Wh / ~16 h | ~$400 | Workday-plus. 6 kg. |
| 100 Ah AGM lead-acid car battery | 1,200 Wh / ~40 h | ~$200 | Cheap multi-day. 25 kg, ugly, works. |
| 100 Ah LiFePO4 | 1,280 Wh / ~42 h | ~$350 | Half the weight of lead-acid (~12 kg), 5–10× the cycle life. |
| Anker 757 PowerHouse (1,229 Wh) | 1,229 Wh / ~40 h | ~$1,000 | Premium consumer "plug-and-play" power. 20 kg. |
| Any of the above + 100 W solar + MPPT | indefinite | +$110 | Permanent installation. Add a 100 W panel ($80) + 20 A MPPT charge controller ($30) and the sentry runs forever in any latitude with 4+ hours of daylight. |
PoE as an alternative — only for ≤100 m
If the sentry is within 100 m of the base, a single Cat6 cable can carry both data and power, eliminating the per-sentry battery entirely:
- PoE++ Type 3 (802.3bt) delivers 51 W at the device — comfortable for the 30 W sentry. ~$80 for an injector at the base.
- The base feeds the injector from its 12 V supply via a small 12 V → 48 V boost converter ($15), or use a 12 V-input PoE injector directly (e.g. Mikrotik RBGPOE-CON-HP, ~$25). PoE specifically uses 48 V because 12 V over Ethernet wire has too much voltage drop.
- At the sentry, a PoE PD module (~$15) extracts the 48 V and outputs clean 12 V. No battery needed at the sentry — base powers everything.
- Distance limit: 100 m. IEEE 802.3 hard limit on Ethernet. PoE extenders exist for 200–300 m but they're hacks (midspan repeaters, additional failure points).
- Bandwidth limit: 1 Gbps on Cat6 — enough for processed detections from edge DSP, not enough for raw 8 Gbps IQ. PoE forces edge DSP (Jetson at the sentry).
Verdict: for short ≤100 m runs with edge DSP, PoE is wonderful — one cable, no per-sentry battery, no solar logistics. For 100 m–2 km runs or centralised DSP, fall back to fiber + per-sentry battery.
Fiber that survives the real world
Fiber for outdoor / vehicle-traffic / rodent-prone runs is a solved problem. Cheapest to most robust:
- Direct-burial fiber (PE-jacketed, gel-filled, water-blocked). Plowed into the ground at 30–60 cm. ~$1/m. Standard telco part.
- Armored fiber (interlocking aluminum or steel armor inside the outer jacket). Rodent-resistant and crush-resistant. Survives a vehicle on dirt or gravel. ~$1.50–4/m. Brand: Corning ALTOS.
- HDPE conduit ("smurf tube" or orange Innerduct) with ordinary outdoor fiber pulled through. ~$0.50/m for conduit + ~$1/m for fiber. Truck-rated when buried 30 cm. Best feature: you can replace the fiber later without re-digging.
- Rigid PVC schedule-40/80 conduit. Hard grey pipe, ~$1.50/m. Essentially indestructible. Slow install. Right answer when fiber crosses driveways or vehicle paths.
- Aerial figure-8 fiber. Self-supporting cable strung on poles 4+ m up. Trucks can't reach it. ~$2/m + pole hardware.
- Tactical fiber (TFOCA-II, mil-spec). Designed to be dragged across the ground, run over by vehicles, rolled up daily. ~$8–20/m. Use for temporary tactical deployments where you want to recover the cable.
For a fixed site: bury direct-burial fiber in orange Innerduct at 30 cm. Where it crosses a roadway, run that section through PVC conduit. Where you can't dig, go aerial on existing poles. Budget ~$1–2/m all-in.
Where to start tomorrow
- Buy one sentry's worth of parts — Ku dish + LNB + USRP B205mini + Raspberry Pi 5 + Pelican 1300 + 100 m of single-mode fiber. ~$1,200.
- Get IQ flowing. Point the dish at the sky, capture 30 s of Ku at 200 MS/s. Verify you see the direct path from a Starlink beam (loud bursts on the spectrogram every few ms).
- Build the reference-channel reconstruction in Python — pull the direct path, use it as a matched-filter reference.
- Add a second sentry. Now you have bistatic range × 2 → drone localisation. This is the minimum viable system.
- Wire in a seeker pad. Reuse the v3 CAP seeker design unchanged.
Playbook
The actual build, broken into atomic tasks (we call them beads). Each bead is small enough to fit in a single focused session — usually 15 min to 2 hr with an AI coding assistant — and has clear, verifiable success criteria. With Claude / Cascade / DeepSeek writing the code, a motivated builder can complete v1 in roughly two focused weekends after parts arrive: one to assemble + bring up the stack, one to tune in the field.
Bead schema
| Field | Meaning |
|---|---|
| ID | Stable identifier like B-040. Use it when chatting with Claude: "Help me with B-040." |
| Title | One-line description. |
| Deps | Beads that must be complete before this one (none = "—"). |
| Success | How you know the bead is done. A specific command output, a measurement, a file existing, etc. |
| Time | Realistic estimate for someone seeing this for the first time, with LLM help. |
Phase totals
| Phase | Beads | Est. time | Output |
|---|---|---|---|
| 0 · Procurement | 3 | 1 wk elapsed (waiting on shipping) | All parts on the workbench. ~2 hr of actual work to place orders. |
| 0.5 · Site survey (run during procurement wait) | 4 | ~3 hr | Picked FM tower verified, planned sites have clean RF + sky view. Surfaces blockers before you've assembled anything. |
| 1 · Enclosure (3D print + post) | 6 | 1 day elapsed (12 hr print) | Two physical cases, ready to populate. ~2 hr of hands-on work, the rest is the printer running. |
| 2 · Hardware assembly per node (×2) | 14 | ~3 hr | Two complete sensor boxes, powered. |
| 3 · Base OS install | 6 | ~2 hr | Both Jetsons booting JetPack from NVMe over Wi-Fi. AI scripts the flashing + first-boot config. |
| 4 · GPS time discipline | 6 | ~1.5 hr | Sub-µs GPS-locked clocks. AI writes the chrony.conf and verifies the PPS. |
| 5 · SDR install + first capture | 4 | ~1 hr | Coherent 5-channel IQ streaming. Mostly running the vendor installer. |
| 6 · CUDA pipeline environment | 6 | ~1 hr | cuFFT + TensorRT verified working with a hello-world kernel the assistant generates. |
| 7 · Mesh networking | 6 | ~2 hr | Two nodes auto-discovering on a Wi-Fi mesh. |
| 8 · Passive radar pipeline | 11 | ~6 hr | End-to-end detection from real RF. The genuinely creative part — but the assistant writes the cuFFT cross-ambiguity, CFAR, and IQ-alignment code. |
| 9 · Status display + I/O | 5 | ~2 hr | OLED, LEDs, button working without a laptop. Pure boilerplate; the assistant generates it. |
| 10 · Operator console (web app) | 9 | ~3 hr | Tablet UI showing live detections. Standard React + Leaflet, the assistant scaffolds it. |
| 11 · Field test | 6 | ~4 hr | Drone fly-by detected by both nodes. Bound by going outside and flying things, not by code. |
| 12 · Iteration & classifier | 5 | ~4 hr | Trained classifier deployed; tuned CFAR. Iteration is the real cost — multiple field-test rounds. |
| Total v1 focused effort | ~91 | ~33 hr (~2 weekends) | v1 complete. Plus ~1 wk of elapsed time waiting for parts. |
| After v1 ships — extensions (Extensions tab) | |||
| 13 · Acoustic mic-array (extension) | 8 | ~1 weekend | 4-mic array on each sentry, drone-acoustic detector, sensor fusion with RF radar. |
| 14 · Long-CPI micro-Doppler confirmation (extension) | 5 | ~3 hr | Pipeline change only. Confirmed targets get a 1–2 s coherent integration pass that resolves blade-flash. |
| 15 · Cell-tower (v1.5) variant migration (extension) | 7 | ~3 weekends | New SDR + antennas + LTE reference-channel software. Same boxes, same pipeline shell, 100× range resolution. |
The beads
| ID | Title | Deps | Success criteria | Time |
|---|---|---|---|---|
| Phase 0 · Procurement | ||||
| B-001 | Order long-lead items first | — | Jetson Orin Nano Super dev kit (×2) and KrakenSDR (×2) ordered. Estimated ship dates noted in your tracker. | 1 hr |
| B-002 | Order remaining BOM | B-001 | Every line item from the BOM tab placed. Total spend matches the grand-total estimate within 10%. | 2 hr |
| B-003 | Inventory check on arrival | B-001, B-002 | All parts arrived, opened, and laid out. Photos taken for reference. Anything missing or damaged → reorder before continuing. | 2 hr |
| Phase 0.5 · Site survey (run in parallel with procurement waiting) | ||||
| B-005 | Pick your FM illuminator | — | Use radio-locator.com or FCC FM Query: list every FM station within 25 km of your planned deploy site. Rank by ERP × line-of-sight quality. Pick top 3 candidates. Need at least one with ≥10 kW ERP and unobstructed line-of-sight. | 30 min |
| B-006 | RTL-SDR site survey of candidate FM tower | B-005 | $20 RTL-SDR + a coat-hanger dipole. Park at planned Site A, tune to candidate FM station. rtl_power -f 88M:108M:50k shows the candidate carrier at ≥ –40 dBm direct-path power. SNR ≥ 30 dB above noise floor in the carrier band. If multiple candidates, pick the strongest. |
1 hr |
| B-007 | RF noise-floor characterisation | B-006 | Record 60 s of FM-band IQ at each planned site. Plot the spectrogram. Confirm: no obvious power-line buzz at 50/60 Hz harmonics in the FM band, no taxi-radio bleed-through, no broadband transient sources. If a site is dirty, pick a different site — don't try to fix it in software. | 1 hr |
| B-008 | GPS sky-view check at both planned sites | — | Open the GPS Status / SkyView app on a phone at each site. Confirm ≥ 6 satellites at > 10° elevation, no major obstructions overhead (dense canopy, building wall directly above). If marginal, plan to put GPS antenna on top of the case with clear sky view. | 30 min |
| Phase 1 · Enclosure | ||||
| B-010 | Generate STL files from OpenSCAD | B-003 | Run openscad -o body.stl -D 'compute_module="jetson_orin_nano"' nomio_node.scad (and similar for lid + 2 trays). Four STL files exist with correct dimensions. |
2 hr |
| B-011 | Print the body shell | B-010 | PETG, 0.2 mm layers, 30% gyroid infill, 3 perimeters. ~6 hr print. Body fits all dry-fit components. | 7 hr (mostly print) |
| B-012 | Print the lid + 2 internal trays | B-010 | ~6 hr combined print. All parts fit dry-fit. | 7 hr (mostly print) |
| B-013 | Heat-set M3 inserts in case | B-011, B-012 | All 14 M3 holes have brass inserts press-fit with a soldering iron at 220 °C. Each insert sits flush ±0.3 mm. | 1 hr |
| B-014 | Install 1/4"-20 brass insert + vent membrane | B-013 | 1/4-20 insert in bottom face accepts a tripod thread snugly. GORE vent membrane bonded over the rear vent hole with double-sided tape. | 30 min |
| B-015 | Repeat for second case | B-014 | Two complete, identical, populated-but-empty enclosures. | 1 day (with overlap) |
| Phase 2 · Hardware assembly (per node × 2) | ||||
| B-020 | Install AX210 Wi-Fi M.2 in dev kit | B-015 | AX210 seated in M.2 Key E slot. Single mounting screw torqued. | 10 min |
| B-021 | Install NVMe SSD in dev kit | B-020 | NVMe seated in M.2 Key M slot. Single mounting screw torqued. | 10 min |
| B-022 | Connect Wi-Fi antennas via MHF4 | B-020 | Both MHF4 connectors clicked onto AX210. Pigtails routed to two small holes drilled in the case sidewall. RP-SMA dipoles screwed on outside. | 30 min |
| B-023 | Stack Uputronics GPS HAT on 40-pin header | B-021 | HAT seated firmly. PPS jumper present (LED on HAT lights up briefly when power applied later). | 15 min |
| B-024 | Wire OLED to I2C pins | B-023 | OLED VCC → 3V3 (pin 1), GND → GND (pin 6), SDA → pin 3 (I2C1_SDA), SCL → pin 5 (I2C1_SCL). Connections verified with multimeter for continuity. | 45 min |
| B-025 | Wire 3 LEDs and button to GPIO | B-024 | Green → GPIO 12, Blue → GPIO 16, Red → GPIO 20 (each via 330 Ω to GND). Button between GPIO 21 and GND. Continuity verified. | 1 hr |
| B-026 | Mount Jetson + HAT on top tray | B-025 | Jetson dev kit secured with 4× M2.5 standoffs. HAT clears tray ceiling. | 20 min |
| B-027 | Mount KrakenSDR on middle tray with thermal pad | B-026 | KrakenSDR secured with 4× M3 bolts. 3 mm thermal pad between SDR top surface and case sidewall. | 30 min |
| B-028 | Install rear-panel SMA bulkheads | B-027 | 3 SMA bulkheads (2× RF, 1× GPS) installed through rear face. Right-angle pigtails to KrakenSDR CH0/CH1 and HAT GPS port. | 45 min |
| B-029 | Slide power bank into bottom tray | B-028 | Anker 737 sits snugly. Friction-fit foam keeps it stable. USB-C ports accessible from rear. | 15 min |
| B-030 | Wire USB-C power and data | B-029 | Power bank → Jetson USB-C PWR. Power bank → KrakenSDR PWR. Jetson USB 3.2 → KrakenSDR DATA. | 15 min |
| B-031 | Install front-panel hardware in lid | B-030 | OLED visible through lid window. 3 LEDs poked through holes. Button accessible. All flush. | 30 min |
| B-032 | Final assembly: lid on, M3 corner bolts | B-031 | Case closed, all 4 M3 corner bolts torqued. Power bank still removable by sliding from rear without opening case. | 15 min |
| B-033 | Repeat for node B | B-032 | Two physically complete, identical sensor nodes. | 3 hr |
| Phase 3 · Base OS install | ||||
| B-040 | Install NVIDIA SDK Manager on host laptop | — | SDK Manager downloaded and installed on Ubuntu 22.04 host (a VM works). Logged in with NVIDIA developer account. | 30 min |
| B-041 | Boot Jetson into recovery mode | B-033, B-040 | Force recovery jumper set, USB-C connected to host. lsusb on host shows "NVIDIA Corp. APX". |
15 min |
| B-042 | Flash JetPack 6 to NVMe via SDK Manager | B-041 | Full JetPack 6.x flash to NVMe completes. Storage device set to NVMe (not SD), not eMMC. Jetson reboots into Ubuntu OEM-config wizard. | 45 min |
| B-043 | First-boot OEM config | B-042 | Username nomio, hostname nomio-a1 for the first node and nomio-a2 for the second. Locale, timezone set. Finished setup brings up Ubuntu desktop. |
15 min |
| B-044 | Enable SSH, copy keys, set static node ID | B-043 | SSH from your laptop to nomio@nomio-a1.local works without a password (key-based auth). /etc/nomio/node.conf contains NODE_ID=A1. |
30 min |
| B-045 | Apt update + install base utils on both nodes | B-044 | sudo apt update && sudo apt upgrade -y succeeds. git tmux htop nvtop python3-pip jq installed. Same on node B. |
45 min |
| Phase 4 · GPS time discipline | ||||
| B-050 | Install gpsd, chrony, jetson-gpio | B-045 | apt install gpsd gpsd-clients chrony python3-jetson.gpio pps-tools succeeds. |
15 min |
| B-051 | Enable UART for HAT NMEA | B-050 | Disable serial console on UART pins, enable raw UART. cat /dev/ttyTHS0 shows raw NMEA strings within ~5 min of having a sky view. |
45 min |
| B-052 | Configure gpsd for Uputronics HAT | B-051 | cgps -s shows live position fix and satellite count ≥ 4. Time UTC matches your phone within seconds. |
30 min |
| B-053 | Configure PPS via GPIO 18 | B-052 | Device tree overlay or pps-gpio module loaded. ppstest /dev/pps0 prints one timestamp per second, with stable cadence. |
1.5 hr |
| B-054 | Configure chrony to discipline clock from PPS | B-053 | chronyc sources -v shows the PPS source as preferred (* marker). Stratum 1. |
45 min |
| B-055 | Verify time accuracy < 10 µs | B-054 | chronyc tracking reports System time offset under 10 µs after 5 minutes of lock. Repeat on node B. |
30 min |
| Phase 5 · SDR install + first IQ capture | ||||
| B-060 | Install KrakenSDR DAQ from official repo | B-055 | Clone krakensdr_doa, follow Linux install. kraken_doa --help prints usage. |
45 min |
| B-061 | Verify lsusb shows 5× RTL2838 + control | B-060 | lsusb | grep RTL lists 5 RTL2838 devices + the control microcontroller. None reset randomly under load. |
15 min |
| B-062 | Run kraken_doa, verify coherent IQ stream | B-061 | Default DAQ pipeline runs without errors. Web UI shows 5 channels with correlated noise floors. | 30 min |
| B-063 | Run KrakenSDR built-in calibration | B-062 | Calibration completes; phase offsets between channels are stable to within ±2°. Repeat on node B. | 30 min |
| Phase 6 · CUDA pipeline environment | ||||
| B-070 | Verify CUDA toolkit | B-045 | nvcc --version shows CUDA 12.x. nvidia-smi shows the iGPU. jtop reports GPU utilization. |
15 min |
| B-071 | Create Python venv at /opt/nomio/venv | B-070 | python3 -m venv --system-site-packages /opt/nomio/venv succeeds. Venv activates cleanly. |
15 min |
| B-072 | Install Python deps | B-071 | pip install cupy-cuda12x numpy scipy pyzmq websockets fastapi uvicorn luma.oled adafruit-circuitpython-rfm9x all succeed without errors. |
30 min |
| B-073 | CuPy self-test: 1M-point complex FFT under 10 ms | B-072 | Run a 5-line Python script that does cupy.fft.fft(cupy.random.random(1_000_000) + 1j*...) and times it. Result < 10 ms after warm-up. |
30 min |
| B-074 | Install TensorRT Python bindings | B-073 | import tensorrt; print(tensorrt.__version__) prints 8.x or 10.x without error. |
30 min |
| B-075 | Run TensorRT example to verify GPU inference | B-074 | NVIDIA's sampleOnnxMNIST or equivalent runs and returns correct classifications. Repeat on node B. |
45 min |
| Phase 7 · Mesh networking | ||||
| B-080 | Install batman-adv kernel module | B-045 | sudo modprobe batman-adv succeeds. lsmod | grep batman shows it loaded. |
30 min |
| B-081 | Bring up bat0 mesh interface, static IP | B-080 | Both nodes have bat0 interface up. Node A = 10.42.0.1/24, Node B = 10.42.0.2/24. |
1 hr |
| B-082 | Verify mesh ping < 10 ms | B-081 | ping 10.42.0.2 from Node A returns < 10 ms RTT consistently. batctl o shows the peer. |
15 min |
| B-083 | Install Avahi, advertise nomio service | B-082 | Each node advertises _nomio-sensor._tcp.local with TXT records (node ID, version). avahi-browse -art from either node sees both. |
45 min |
| B-084 | Configure tablet AP mode (hostapd) | B-083 | Each node has a second virtual Wi-Fi interface acting as an AP, SSID like nomio-a1. Phone or tablet connects, gets DHCP from the node, and pings it. |
1.5 hr |
| B-085 | Generate node identity keys; share public keys | B-082 | Each node has an Ed25519 keypair in /etc/nomio/keys/. Public keys exchanged into known_peers on each node. A signed test message round-trips successfully. |
1 hr |
| Phase 8 · Passive radar pipeline | ||||
| B-100 | Bootstrap nomio-radar repo | B-075 | Git repo created with project layout: nomio_radar/ package, tests/, configs/, pyproject.toml, Makefile. Imports cleanly inside the venv. |
1 hr |
| B-101 | IQ ingest from Kraken DAQ socket | B-100 | Module nomio_radar.ingest connects to KrakenSDR DAQ ZMQ socket and yields 1024-sample IQ buffers per channel. Unit test passes against recorded sample data. |
3 hr |
| B-102 | GPS-disciplined timestamping | B-101, B-055 | Each yielded buffer has a UTC nanosecond timestamp accurate to ±10 µs. Verified by comparing two consecutive timestamps to expected sample-rate spacing. | 2 hr |
| B-103 | Direct-path cross-correlation alignment | B-102 | Function align_channels(ref, surv) finds the integer-sample lag that maximizes |xcorr| between reference and surveillance, returns the lag. Verified on a recorded capture: lag matches expected geometry. |
3 hr |
| B-104 | CLEAN clutter cancellation on GPU | B-103 | CuPy implementation of CLEAN iterates direct-path subtraction. Output surveillance channel has direct-path peak suppressed by > 25 dB. Runs in < 5 ms per buffer. | 1 day |
| B-105 | Cross-ambiguity function on GPU | B-104 | cuFFT-based 2D cross-ambiguity over a 200 range × 64 Doppler bin grid runs in < 50 ms per frame on the Jetson. Output amplitude-squared map. | 1.5 days |
| B-106 | CFAR detector as CUDA kernel | B-105 | Cell-averaging CFAR over the 200×64 cross-ambiguity map. Configurable P_fa. Runs in < 5 ms. Verified on synthetic data: detects injected target, no false alarms above threshold. |
1 day |
| B-107 | Detection serializer (typed JSON) | B-106 | Each detection becomes {node_id, timestamp_ns, range_m, doppler_hz, snr_db, classifier_label, confidence}. Validated against a Pydantic schema. |
2 hr |
| B-108 | Stub classifier (always returns "drone", p=0.8) | B-107 | Placeholder classifier in pipeline. Real model replaces this in B-181. | 30 min |
| B-109 | WebSocket detection broadcaster | B-108 | FastAPI WebSocket endpoint at /ws/detections. Broadcasts each detection JSON. websocat client receives them in real time. |
3 hr |
| B-110 | End-to-end synthetic-data test | B-109 | Replay a recorded IQ file with a synthesized drone-like target. Pipeline produces 1+ detections at the correct range and Doppler. Detection JSON appears on the WebSocket. | 1 day |
| Phase 9 · Status display + I/O | ||||
| B-120 | OLED daemon (luma.oled) | B-024, B-072 | Python script renders the 8-line status frame from the Sensor Node tab. Updates 1 Hz. Reads state from a local UNIX socket fed by other daemons. | 3 hr |
| B-121 | LED state-machine daemon | B-025, B-072 | Driver that observes gpsd, KrakenSDR, mesh, and detections, and lights LEDs accordingly. Verified by toggling each input and watching LEDs match. |
3 hr |
| B-122 | Button handler (short / long press) | B-025, B-072 | Short press = show pairing fingerprint on OLED for 30 s. Long press = clean shutdown via systemctl. Verified manually. |
2 hr |
| B-123 | Wrap each as systemd service | B-120, B-121, B-122 | Three unit files in /etc/systemd/system/. systemctl status nomio-status shows all running. |
1 hr |
| B-124 | Auto-start on boot, dependency order | B-123 | Reboot. Within 60 s of power-on, OLED shows live status, LEDs are correct, GPS lock acquired, mesh joined. | 1 hr |
| Phase 10 · Operator console (web app) | ||||
| B-140 | Bootstrap React + Vite project | B-109 | Static SPA built with Vite, served from FastAPI as static files at /. Loads in browser, shows placeholder layout. |
3 hr |
| B-141 | Detection list view | B-140 | Subscribes to /ws/detections. Live-updating table of recent detections sorted by time. Clicking a row selects it. |
3 hr |
| B-142 | Range-Doppler heatmap (Canvas/WebGL) | B-141 | Server downsamples the cross-ambiguity map to 256×256 px and pushes via WebSocket. Client renders to a canvas at 10 Hz. Selected detection is highlighted. | 2 days |
| B-143 | Map view (MapLibre GL) | B-141 | Map shows both sensor nodes' positions (from GPS), bistatic ellipses for selected detection, and recent track history. Pre-cached offline tiles. | 2 days |
| B-144 | Mesh health panel | B-141 | Header chips show mesh status (✓ both peers up), GPS lock per node, dets/min, battery %. | 3 hr |
| B-145 | BT pairing flow (Web Bluetooth) | B-144 | "Pair new node" flow: tablet scans BT, finds node, displays fingerprint, exchanges mesh key, confirms. Works on Chrome Android. iOS gets a "scan QR code from OLED" fallback. | 1.5 days |
| B-146 | Auto-discovery (mDNS) on join | B-145 | When the tablet's Wi-Fi connects to the node SSID, the app auto-finds the node via mDNS and connects. No manual IP entry. | 3 hr |
| B-147 | Event log view | B-141 | Persistent SQLite log on the node, served via REST. UI shows newest-first list, filterable by level / target / node. | 3 hr |
| B-148 | Polish + responsive layout | B-141, B-142, B-143, B-144, B-147 | Works as a real tablet UI: large touch targets, high-contrast palette, dark mode for outdoor use. Tested on a real tablet, not just the laptop browser. | 1 day |
| Phase 11 · Field test | ||||
| B-160 | Indoor reference-only test | B-110, B-124 | Identify a strong local FM station. Reference channel SNR > 30 dB. KrakenSDR not saturated. Logged spectrum looks like a normal FM broadcast. | 2 hr |
| B-161 | Indoor known-target test (slow car) | B-160 | Park near a road. Pipeline produces a transient detection track when a car drives by, at the expected bistatic range and Doppler. | 2 hr |
| B-162 | Two-site indoor mesh test | B-161, B-085 | Both nodes powered up. Mesh forms. Same target produces detections on both nodes within ±100 ms. Both visible in tablet UI. | 3 hr |
| B-163 | Outdoor single-site drone hover | B-162 | Deploy node A outdoors. Hover the DJI drone at known range (e.g., 200 m). Detection appears at the right bistatic range. SNR > 6 dB. | 3 hr |
| B-164 | Outdoor two-site drone fly-by | B-163 | Deploy both nodes ~50 m apart outdoors. Drone fly-by at varying ranges. Both nodes detect, ranges geometrically consistent. Localization estimate within ~30 m of true position. | 4 hr |
| B-165 | Capture 30 min of mixed-target data | B-164 | Record raw IQ + detection log + GPS for 30 min in a moderately busy outdoor location. Files archived for offline analysis and classifier training. | 1.5 hr |
| Phase 12 · Iteration & classifier | ||||
| B-180 | Tune CFAR thresholds from collected data | B-165 | Replay capture, sweep P_fa from 1e-2 to 1e-6. Choose threshold that gives < 1 false alarm/min and detects the known drone fly-by reliably. |
1 day |
| B-181 | Train micro-Doppler classifier | B-165 | Extract spectrograms around each detection, label by hand (drone / bird / car / clutter), train a small CNN (~100K params) in PyTorch. Test accuracy > 85% on held-out set. | 3 days |
| B-182 | Convert classifier to TensorRT engine | B-181 | PyTorch → ONNX → TensorRT FP16 engine. Inference latency < 2 ms per detection on the Jetson. | 1 day |
| B-183 | Replace stub classifier with real engine | B-182, B-108 | Pipeline now emits real classifier_label + confidence values. UI reflects them. Repeat outdoor fly-by — drone is labelled "drone" with confidence > 0.85. |
4 hr |
| B-184 | Final end-to-end demo + release | B-183 | Tag v1.0 on the repo. Record a 5-minute demo video showing: power-on, GPS lock, mesh forms, drone fly-by, classified detection on tablet. Hand off to the next contributor. |
1 day |
| After v1 ships — extensions (see Extensions tab) | ||||
| Phase 13 · Acoustic mic-array — nighttime / RF-quiet complement | ||||
| B-200 | Order MEMS mics + breakouts | B-184 | 4× Knowles SPH0645LM4H or InvenSense ICS-43434 breakout boards per site (8 total). I²S digital out. ~$5 each from Adafruit / Mouser. | 15 min |
| B-201 | 3D-print mic mount plate | B-200 | OpenSCAD a 10×10 cm plate with mics at the corners, mounting holes for the case side. Print in PETG. ~1 hr print. | 2 hr |
| B-202 | Wire mics to Jetson I²S header | B-201 | 4 mics share BCLK + LRCLK, each on a unique DOUT pin. Use Jetson Orin Nano dev kit pins 12 (BCLK), 35 (LRCLK), 38/40/16/18 (4× DOUT). Verify with arecord -l showing 4 channels. |
1.5 hr |
| B-203 | Acoustic capture daemon | B-202 | nomio-acoustic systemd service captures 16 kHz × 4 channels into a 30 s ring buffer in shared memory. arecord-equivalent test: arecord -D hw:1 -c 4 -r 16000 -f S16_LE writes a clean 4-channel WAV. |
2 hr |
| B-204 | Drone-acoustic detector (harmonic peak picker) | B-203 | 1 s sliding STFT, look for fundamental in 80–200 Hz with at least 3 harmonics above noise. Test with a small drone hovering nearby — detector fires within 2 s of flight start. | 3 hr |
| B-205 | TDOA bearing-of-arrival (GCC-PHAT) | B-204 | Cross-correlate adjacent-mic pairs with phase-transform weighting, derive azimuth + elevation. Bearing accuracy ≤ ±10° against a hand-flown drone at 50 m. | 3 hr |
| B-206 | Acoustic VLM classifier prompt | B-204, B-183 | Render 4-channel spectrogram as a single PNG. Prompt: "Is this the acoustic signature of a small consumer drone? Answer yes/no with confidence." Validate against 20 hand-collected samples (drone, bird, car, lawnmower, ambient). | 2 hr |
| B-207 | Sensor fusion (RF radar × acoustic) | B-205, B-206 | When RF radar bearing and acoustic bearing agree within 10° within 2 s of each other → mark detection as HIGH-CONFIDENCE. Tablet UI shows fused detections in a different colour. | 2 hr |
| Phase 14 · Long-CPI micro-Doppler confirmation | ||||
| B-220 | Add long-CPI confirmation worker | B-184 | When the v1 detector fires, snapshot the IQ buffer and run a 1–2 s coherent integration on just the detection's range bin. Output: a Doppler–time spectrogram zoomed to ±200 Hz around the target's bulk Doppler. | 3 hr |
| B-221 | Render blade-flash spectrogram | B-220 | Save the long-CPI spectrogram as a 256×256 PNG, viridis colour map, log-scale magnitude. The blade-flash modulation lines should be visually unmistakable on a real drone. | 1 hr |
| B-222 | Auto-detect blade-flash modulation | B-220 | Autocorrelate the spectrogram along the time axis at each Doppler bin; look for a periodic peak corresponding to the blade-passage frequency. If detected, attach rotor_rpm_estimate to the detection JSON. |
3 hr |
| B-223 | VLM micro-Doppler classifier prompt | B-221 | Send the spectrogram PNG to the existing VLM with prompt: "Does this micro-Doppler spectrogram show periodic blade-flash modulation lines? If yes, estimate rotor RPM." Validate against drone vs bird vs helicopter recordings. | 2 hr |
| B-224 | Combine bulk + micro-Doppler into final classification | B-222, B-223 | Fuse: fast detector hit + bulk Doppler + (B-222 algorithmic blade-flash detect) + (B-223 VLM blade-flash) → final label with confidence. Field-test classifier accuracy ≥ 90% on drone-vs-bird in known scenarios. | 3 hr |
| Phase 15 · Cell-tower (v1.5) variant migration | ||||
| B-240 | Order wideband SDR + sub-3 GHz antennas | B-184 | USRP B205mini (~$1,200) or BladeRF 2.0 Micro xA9 (~$720) per site. 2× wideband log-periodic / discone (300 MHz – 3 GHz) per site. Long-lead, order early. | 30 min + lead time |
| B-241 | Site survey for cell-tower illumination | B-240 | Use srsRAN cell-search or QCSuper to enumerate visible cell sectors (PCI, EARFCN, RSRP) at each planned site. Confirm ≥ 5 sectors at RSRP ≥ –85 dBm. Pick the strongest band as primary illuminator. |
2 hr |
| B-242 | Implement LTE reference-signal regeneration | B-241 | Generate PSS + SSS + CRS from the 3GPP TS 36.211 spec for the chosen PCI. Use srsRAN or OpenLTE as a reference. Output: synthesised reference IQ that correlates with the live downlink at ≥ 25 dB SNR. |
1 day |
| B-243 | Adapt cuFFT cross-ambiguity for 20 MHz BW | B-242 | FFT plan grows from 200K bins (FM) to 20M bins (LTE 20 MHz). Verify GPU memory fits on the 8 GB Jetson; if not, segment into 2 MHz overlapping sub-bands. Pipeline still hits 5+ Hz update rate. | 1 day |
| B-244 | Multi-illuminator fusion | B-243 | Run cross-ambiguity against each visible cell sector independently. Each gives an independent bistatic ellipse. Two ellipses on one receiver → ambiguous; three–four → unique target localisation from one sentry. | 3 hr |
| B-245 | Field test against cell-tower illumination | B-244 | Drone fly-by detected against LTE downlink. Compare detection range and accuracy vs the v1 FM baseline. Document the trade-offs in a notes file for the next contributor. | 1 day |
| B-246 | Tag v1.5 release | B-245 | Tag v1.5. Update README to document both the FM and the LTE path, including which one to pick based on local RF environment. |
2 hr |
Working with Claude / Cascade on each bead
The intended workflow:
- Open a fresh chat / terminal window for the bead.
- Paste the bead text plus any context Claude needs (current branch, files, errors).
- Let Claude propose a plan, push back on it, then ask it to write code or run commands.
- Verify against the success criterion. If it doesn't match, debug together.
- Commit, mark the bead done, move to the next.
For very small beads (B-060, B-070, B-080), this might be a single message. For larger beads (B-105, B-142, B-181), expect 1–3 days of conversation across many sessions. The ID lets you resume context cleanly: "Continuing on B-105."
What to do when stuck
- Verification fails. Don't move on. The dependencies in later beads assume earlier ones are correct. Debug or ask Claude to help debug.
- You can't make a measurement. Some success criteria need real RF — find a higher floor with sky view, find a stronger FM station, try at night when local interference is lower.
- A part is broken. Reorder. The system is reproducible by design — the BOM lists every part with a canonical source.
- You're going faster than expected. Don't skip — but feel free to batch small beads into one session.