Why We Chose Radar Over Lidar for Presence Detection
Presence detection sounds solved—motion sensors have shipped for decades. But a real living-space sensor must spot a person sitting dead still, ignore furniture, work in the dark, and not confuse the dog for a human. Our first trigger, a single-channel time-of-flight lidar, failed nearly all of these. Here's why we switched to a 24 GHz FMCW radar, what it measures, and where we drew an honest line.
Why the Lidar Trigger Fell Short
A single-channel lidar measures one thing superbly: the distance to the nearest opaque surface along one narrow line. It fires a pulse, times the round trip, returns a number. Precise—but two assumptions broke immediately.
First, one ray can't cover a room: a pencil beam sees only the line it points at. Second, and worse, distance doesn't imply presence—a wall, a chair, and a standing person all return the same reading, so the lidar fired a target every frame whether the room held a person or just a sofa. For a trigger meant to wake an expensive system only when it matters, that is worse than useless.
| Property | Single-channel lidar | 24 GHz FMCW radar |
|---|---|---|
| Coverage | One narrow ray | ~120° cone (±60° H/V) |
| Measures | Distance to nearest surface | Reflected energy per distance gate |
| Output | One number | Array of gates, refreshed continuously |
| Sees in the dark | Yes | Yes |
| Through soft cover / smoke | No | Yes |
| Tells alive from static | No | Yes (energy changes over time) |
| Power | Low | Low, always-on |
The Radar Approach at a Glance
The radar inverts almost every lidar property. It floods a 120° cone instead of one ray, sweeps a frequency ramp instead of timing a pulse, and produces an array of reflected-energy values—one per distance gate—refreshed continuously. From that array it does the one thing lidar never could: separate a living target from static clutter by watching how energy changes over time.

From Chirp to Distance: How FMCW Sees Range
FMCW means frequency-modulated continuous wave. Instead of a pulse, the radar sends a tone whose frequency ramps upward—a chirp. The echo was sent a moment earlier, at a lower frequency, so mixing it against the current transmit signal yields a single beat tone proportional to distance: near targets give low beats, far targets high ones.
An FFT over the beat signal pulls layered tones apart. Each bin maps to a beat frequency, hence a range, so each bin becomes a distance gate. The firmware stores the magnitude squared of each bin—its reflected energy. One chirp yields a full range profile in a single shot.
beat frequency: f_b = (2 * R * S) / c
range from beat: R = (f_b * c) / (2 * S)
R = target range (m)
f_b = beat frequency (Hz)
S = chirp slope (Hz/s) = bandwidth / chirp time
c = speed of light (3e8 m/s)
The Energy Array and Its Distance Gates
The output is a range profile: one reflected-energy value per gate. Each gate spans ~70 cm, fixed by the sweep bandwidth—not tunable. The raw value is magnitude-squared; we convert it to dB for thresholding:
range_resolution = c / (2 * bandwidth) # ~0.6 m for this part, ~70 cm/gate
energy_db = 10 * log10(magnitude_sq) # 0..95 dB scale
gate 0 -> 0.0 - 0.7 m
gate 1 -> 0.7 - 1.4 m
gate n -> (n * 0.7) - ((n+1) * 0.7) mOne quirk bit us: the stream reports 32 gates, but only 16 expose configurable thresholds. The math explains why we trust the 16:

Takeaway: the array reports energy per distance shell, not a list of target positions.
Detecting Life, Not Just Surfaces
This is why we switched. The radar tells living from static not by how much energy returns but by how it changes. A wall and a person can return nearly identical energy—in our logs, empty and occupied rooms summed to almost the same total. The difference is behaviour: a wall is flat frame to frame; a person, even sitting still, modulates their gate through gross motion and the small periodic push of breathing. The trigger logic looks for that signature:
for each gate:
if energy_db < threshold[gate]: # below clutter floor
continue # ignore (furniture, walls)
delta = abs(energy[t] - energy[t-1])
if delta > motion_thresh: # large change
flag = MOTION
elif periodic(energy_window, 0.1..0.5 Hz): # breathing band
flag = MICRO_MOTION # stationary person -> PRESENT
else:
flag = STATIC # same energy, no wobble -> ignore
present = any(flag in {MOTION, MICRO_MOTION})Calibration keeps it honest: an auto-threshold pass measures each gate's baseline clutter in an empty room and sets the bar a margin above it. The failure modes are specific—a shimmering reflector (a blind in HVAC airflow, a swaying curtain) can fake the change, and a saturating reflector can mask a target behind it. Per-gate calibration and range masking exist to manage both.
What Reflected Magnitude Does and Does Not Tell You
It is tempting to read gate magnitude as target size. The basis is real—a body's reflectivity is its radar cross-section, and bigger usually means larger. But gate energy is RCS distorted by distance, angle, and clutter, so a near small target can out-reflect a far large one. At 70 cm resolution a person or dog fills just one or two gates, so you can't count gates for size. Material barely helps either: at 24 GHz the body's water content dominates over fur and clothing. Magnitude is a weak, confounded size hint at best.
The Human-versus-Dog Experiment
We logged engineering-mode frames for people and a stand-in dog and studied the gate energies over time. Two results were clean; one was not:
| Comparison | Signal | Verdict |
|---|---|---|
| Occupied vs empty | Near-gate energy high, distance locked < 1.4 m vs drifting > 2.5 m | Clean |
| Walking vs standing | Sawtooth in distance/energy vs flat plateau | Clean |
| Human vs dog | Both a high, stable plateau at close range; only marginal tells | Weak |
Our honest reading: a model trained on these energy sequences might beat chance in a fixed setup, but it would break on size overlap, distance changes, and a new room.
Letting Radar Trigger and Vision Decide
The architecture falls straight out of the radar's limits. Radar does what it's great at—wide presence, coarse distance, living-vs-static—always on and cheap. When it sees life, it wakes the vision model, which owns the human-vs-dog call. The radar never vetoes on its own weak guess; any ambiguity defers to vision.

What We Took Away
The real shift was deciding what to ask of each sensor. Lidar gave a precise distance to one point and no idea if it was alive; radar gave a wide cone, a per-gate energy profile, and a real line between a breathing person and a static wall. We gained presence, coarse localization, and living-target detection—not a species classifier. The moment we stopped pretending magnitude could separate a dog from a person, the design got simpler and more honest: radar triggers, vision decides.