---
name: radar-signal-processing
description: Parse raw radar I/Q captures (CW or FMCW mmWave) and produce a cleaned 1-D slow-time signal ready for motion or vital-signs analysis. Use when Claude needs to read interleaved I/Q binary, do a Range FFT on FMCW chirps, remove static clutter, pick a subject range bin, extract phase with unwrapping, or debug why a radar pipeline is returning garbage. Not for pulse/UWB range gating, MIMO beamforming, or Doppler-only gesture radar.
---

# Radar Signal Processing

Get from a raw binary I/Q capture to a clean 1-D phase trace that downstream vital-signs / motion analysis can consume.

## Pipeline (do every step in order)

1. **Parse binary I/Q to complex samples.** Use the JSON/YAML sidecar to determine format — never assume. See [references/iq-formats.md](references/iq-formats.md).
2. **(FMCW only) Range FFT across fast time** → 2-D range matrix. CW skips this step.
3. **Remove static clutter.** Subtract the temporal mean:
   - CW: `iq -= iq.mean()`
   - FMCW: `R -= R.mean(axis=0, keepdims=True)` on the range matrix
4. **(FMCW only) Pick the subject range bin.** See [references/range-bin.md](references/range-bin.md).
5. **Extract phase with unwrap:**
   ```python
   phase = np.unwrap(np.angle(iq_or_bin))
   phase -= phase.mean()
   ```
6. **If `fs >= 500 Hz` and downstream needs sub-Hz filtering, decimate first:**
   ```python
   from scipy.signal import decimate
   phase_ds = decimate(phase, q=int(fs/50), ftype='iir', zero_phase=True)
   fs_new = fs / int(fs/50)   # ~50 Hz target
   ```

## Critical rules

| rule | why (short) |
|---|---|
| Use **phase**, not magnitude | 1 mm motion at 24 GHz ≈ 1 rad; magnitude is ~40 dB worse SNR |
| Clutter removal goes **before** `np.angle` | DC offset anchors phase off zero, eats the unwrap budget |
| **Never** design a 0.1 Hz filter against a 2 kHz signal | SciPy biquad silently NaNs; decimate to ~50 Hz first |
| **Never** `argmax(magnitude)` across all range bins | DC bin (bin 0) and static reflectors dominate — restrict to a physical subject-range window |

## When things go wrong

If the output is garbage, walk through [references/debugging.md](references/debugging.md) in order — it's fast and catches most ingestion/SNR bugs.

## Not in scope

Pulse/UWB time-of-flight, MIMO angle-of-arrival, Doppler-only gesture radar.
