Why We Chose Radar Over Lidar for Presence Detection

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.

The 24 GHz radar floods a wide 120-degree cone instead of a single ray, sees through dark and soft cover, and reports presence across the whole room at low power.

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 FMCW signal chain: a frequency ramp is transmitted, the delayed echo is mixed down to a beat frequency, and an FFT turns that into a per-gate energy array.

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) m

One quirk bit us: the stream reports 32 gates, but only 16 expose configurable thresholds. The math explains why we trust the 16:

Each 70 cm distance gate holds one reflected-energy value. A person at 4.2 m lights up a single gate; the rest stay near the clutter floor.| | Gates | Reach (70 cm each) | Notes |

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.

The two-stage front end: always-on radar handles presence and wakes the camera only when something is there, and the vision model owns the human-versus-dog call.

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.

Read more