range_doppler_peaks — RANGEDOPPLER process op

Data kinds: image2dtable

Call: import rangedoppler; rangedoppler.range_doppler_peaks(rdmap, range_bin_m=1.0, velocity_bin_ms=1.0, n_peaks=1, min_fraction=0.1, doppler_shifted=True) (or opsrangedoppler.get("range_doppler_peaks"))

Usage

Detections from a range-Doppler map: bin indices back to metres and m/s.

Finds strict local maxima of the 2-D magnitude map — greater than all eight

neighbours, cyclically along the Doppler axis (velocity really is

periodic in the FFT: the fastest receding bin is adjacent to the fastest

approaching one) and openly along the range axis (a cell in the first or

last range bin competes only against the neighbours that exist, so a target

in the last bin is a detection, not a discard) — keeps those at least

*min_fraction* of the global maximum, and returns the strongest *n_peaks*.

Range bin 0 is reported like any other. In a real receiver it is the

transmitter-leakage / DC bin rather than a target, but suppressing it here

would be a silent policy applied to somebody else's data; threshold it

yourself if you want it gone.

Index -> physical value, closed form and the exact inverse of

:func:fmcw_beat_simulate:

• `range_m = j * range_bin_m, with range_bin_m = c*f_s/(2*S*N_s)`

from :func:fmcw_design;

• `velocity_ms = (i - n_doppler//2) * velocity_bin_ms` when

*doppler_shifted* (the layout :func:range_doppler_map produces), or

`i wrapped into [-N_c/2, N_c/2)` when the map is unshifted.

The bin widths are required parameters with placeholder defaults of 1.0,

which means the default output is in bins, not metres. That is deliberate:

inventing a default waveform here would let a caller read metres off a map

that was never that waveform's.

Returns a `dict with peaks` (a list of per-detection dicts holding

`range_m, velocity_ms, magnitude, range_bin, doppler_bin`),

`n_found, max_magnitude and noise_floor` (the median of the map).

Raises `ValueError`: a non-2-D, complex, negative, or non-finite map; a

map whose maximum is 0 (an all-zero map has no cell to detect and returning

cell (0,0) — which is what `argmax` does — would be a fabricated

detection); a non-positive bin width; *n_peaks* < 1; a *min_fraction*

outside `[0, 1]`.

Detailed usage guide

fmcw_range_doppler family guide

References (sample data, literature)

• Sample-data catalog (download URLs / licences) — 2-D uses skimage.data (BSD/public domain) plus synthetic images; 3-D lists download URLs for real data sources (Stanford, PDS, …).

• Operator provenance and references — the sources of the research/methods this op family came from.

• The canonical algorithm (author, year) and its uses are named in the family usage guide above.

Runnable examples (verified samples that actually call this op)

fmcw_range_dopplerpy -3.11 examples/fmcw_range_doppler.py

Ops the type connects to (they accept table as input)

Same category (process)

fmcw_window_apply · range_doppler_map · fmcw_range_profile


*Provenance: rangedoppler.py — RANGEDOPPLER operator registry. This per-op note is generated by tools/opdocs.py md (do not hand-edit).*

© 2026 Kazufumi Furuse — Fullseye operator documentation. Licensed under Apache-2.0.