Part VII: Health, Biosignals, and Wearable AI
Chapter 33: Continuous and Contactless Health Monitoring

Contactless vitals: mmWave radar for heart/respiration/sleep apnea

"I never touch my patient. I read the tenths of a millimeter their chest confesses to the antenna, and I try very hard not to mistake a fidget for a heartbeat."

A Discreet AI Agent

The big picture

Every other sensor in this part touches the body: an electrode on the chest, a photodiode against the wrist, a cuff around the arm. Millimeter-wave radar breaks that contract. It transmits a faint radio chirp, listens for the echo bouncing off the skin of the chest, and reads the vital signs out of how far that skin moved between one echo and the next. Breathing moves the chest wall by several millimeters; the mechanical recoil of each heartbeat moves it by a few tenths of a millimeter. A 60 GHz radar can resolve both because its wavelength is only five millimeters, so a fraction-of-a-millimeter motion is a large, measurable swing in the phase of the returned signal. The payoff is monitoring with nothing worn and nothing charged: an apnea count from a bedside puck, a respiration rate for a sleeping infant, a heart rate for a burn patient whose skin cannot bear adhesive. The cost is that the useful signal is a sub-millimeter displacement buried under body sway, bed motion, and the breathing of the person in the next bed. This section is about how to pull the vitals out anyway.

This section assumes you understand the phase of a complex signal and the range-versus-Doppler picture of a frequency-modulated continuous-wave (FMCW) radar from Chapter 44, and the broader idea of sensing bodies through radio reflections from Chapter 47. Here we specialize that machinery to a single, tiny, quasi-periodic target: the moving chest wall. We also lean on the spectral and time-frequency tools of Chapter 7, because separating a heartbeat from a breath is fundamentally a question of frequency bands.

From chirp to chest displacement

An FMCW radar sweeps a chirp across a bandwidth \(B\) and mixes each echo with the transmitted sweep. The mixed "beat" tone tells you range: a reflector at distance \(R\) produces a beat frequency proportional to \(R\), so an FFT across one chirp sorts the scene into range bins of width \(\Delta R = c/(2B)\). For \(B = 4\) GHz that is about 3.75 cm, coarse enough that the whole torso lives in one or two bins. Range alone cannot see a heartbeat; a 0.3 mm motion is a thousandth of a bin. The vital signs live not in the magnitude of a bin but in the phase of the complex value in the bin that contains the chest.

Chest displacement \(d(t)\) changes the round-trip path by \(2d(t)\), which rotates the bin's phase by

$$\phi(t) = \frac{4\pi\,d(t)}{\lambda},$$

where \(\lambda\) is the carrier wavelength. At 60 GHz, \(\lambda \approx 5\) mm, so a 0.3 mm heartbeat swing produces \(\Delta\phi = 4\pi(0.3)/5 \approx 0.75\) radian: a comfortably large, easily digitized rotation. This is the core reason mmWave beats lower-frequency radar for vitals: shorter wavelength turns the same tiny motion into more phase. To recover \(d(t)\) you select the chest range bin (the strong, slowly modulated reflector at torso distance), take the arctangent of its imaginary-over-real parts across successive chirps, and unwrap the result. That unwrapped phase, sampled once per chirp at the frame rate (tens of hertz), is your raw vital-signs waveform.

Key insight

mmWave vitals sensing is not object detection; it is phase interferometry on one range bin. The radar never "sees" a heart. It measures the sub-millimeter travel of a reflecting surface, and every downstream algorithm operates on a single one-dimensional phase signal \(\phi(t)\), not on an image. Get the bin selection and the phase unwrapping right and the rest is one-dimensional signal processing; get them wrong and no neural network downstream can recover the vitals, because the information was destroyed at the arctangent.

Separating breath, beat, and apnea

The unwrapped phase is a superposition. Respiration dominates: it swings the chest 4 to 12 mm at 0.1 to 0.5 Hz (6 to 30 breaths per minute), producing a phase excursion an order of magnitude larger than the cardiac component riding on top of it at 0.8 to 2 Hz (roughly 50 to 120 beats per minute). The naive move is two band-pass filters, one per band, and an FFT to read the peak frequency of each. That works in a still, cooperative subject and fails in three characteristic ways. First, respiration is not a pure tone; its second and third harmonics (0.4 to 1.5 Hz) fall squarely inside the cardiac band and masquerade as heartbeats. Second, large body motion swamps everything, so you must gate on stillness or model the motion explicitly. Third, the heartbeat band is weak enough that a plain FFT peak is often a harmonic, not the fundamental, which is why robust pipelines favor autocorrelation, cepstral, or template methods that reward the true periodicity over a single spectral bin.

Sleep apnea is the clinically important payoff and, conveniently, the easiest of the three targets. An apnea is a cessation or steep reduction of the respiratory swing lasting at least ten seconds; a hypopnea is a partial reduction. Because respiration is the strong component, a well-conditioned phase signal makes apneas visible as flat, low-variance stretches in the respiration band. Detecting them reduces to the interval-event problem from Chapter 28: track the envelope of the respiration-band signal, threshold on a sustained amplitude drop, enforce the ten-second minimum, and count events per hour to estimate an apnea-hypopnea index. The delicate part is not detection but not being fooled: a subject who simply rolls over also produces a flat respiration trace, so motion gating and posture context are what separate a real apnea from a quiet turn.

Practical example: the bedside sleep puck

A consumer sleep company ships a nightstand device built on a Texas Instruments IWR6843 60 GHz radar to estimate a nightly apnea-hypopnea index without a worn sensor. Their first build ran two band-pass filters and reported a heart rate that tracked polysomnography to within a couple of beats per minute in the lab, then drifted badly at home. The culprit was a partner sharing the bed: a second respiration source leaking through a side lobe pulled the cardiac estimate toward a respiration harmonic. The fix was range-and-angle gating. With a two-transmit, four-receive antenna array they estimated the angle of each reflector, isolated the target sleeper to a small range-angle cell, and rejected energy from the partner's cell entirely. For apnea, they abandoned heart rate as the headline and scored respiration pauses directly, merging sub-ten-second gaps and discarding motion epochs flagged by a whole-body Doppler energy channel. Agreement with the clinical apnea-hypopnea index rose from unusable to within a few events per hour, the threshold that matters for screening referrals.

A minimal extraction pipeline

The code below simulates the phase signal from a still subject and recovers respiration and heart rate, so you can see the whole chain end to end without hardware. It builds a chest displacement of a strong 0.25 Hz breath plus a weak 1.1 Hz heartbeat, converts displacement to phase at 60 GHz, then band-separates and reads each rate from a windowed FFT. The point it makes is the one the two-filter section warns about: the cardiac peak is real but small, and the choice of band edges is what keeps a respiration harmonic from stealing it.

import numpy as np
from scipy.signal import butter, filtfilt

fs, T = 20.0, 60.0                      # 20 Hz frame rate, 60 s window
t = np.arange(0, T, 1/fs)
lam = 3e8 / 60e9                        # 60 GHz wavelength = 5 mm
d = 4e-3*np.sin(2*np.pi*0.25*t) + 0.3e-3*np.sin(2*np.pi*1.10*t)  # metres
phase = 4*np.pi*d/lam                   # radar phase; add noise the real world has
phase += np.random.default_rng(0).normal(0, 0.02, t.size)

def band_rate(x, lo, hi, fs, fmin, fmax):
    b, a = butter(4, [lo, hi], btype="band", fs=fs)
    y = filtfilt(b, a, x)
    f = np.fft.rfftfreq(y.size, 1/fs)
    P = np.abs(np.fft.rfft(y * np.hanning(y.size)))**2
    m = (f >= fmin) & (f <= fmax)       # search only the physiological band
    return f[m][np.argmax(P[m])] * 60   # cycles/min

resp = band_rate(phase, 0.1, 0.6, fs, 0.1, 0.5)   # breaths/min
hr   = band_rate(phase, 0.8, 2.0, fs, 0.8, 2.0)   # beats/min
print(f"respiration = {resp:.1f} br/min,  heart rate = {hr:.1f} bpm")
A complete simulated mmWave vitals chain: displacement to phase to band-separated rate. It recovers about 15 br/min and 66 bpm, matching the injected 0.25 Hz and 1.1 Hz. Widen the cardiac band down to 0.6 Hz and the respiration second harmonic at 0.5 Hz begins to compete, which is exactly the harmonic-confusion failure the two-filter approach suffers on real data.

Library shortcut

Writing the full front end yourself (chirp deramping, range FFT, bin selection, phase unwrapping, DC removal, clutter suppression, band separation) is roughly 300 lines and a great deal of constant-tuning. Texas Instruments' mmwave SDK vital-signs lab and the open OpenRadar Python package collapse the raw-ADC-to-phase path to a handful of calls (range_processing then a phase-and-unwrap helper on the selected bin), and expose the range-Doppler cube so you can drop straight into your own estimator. Reach for them for the plumbing that every radar shares; keep the band edges, the motion gate, and the apnea thresholds under your own control, because those encode the physiology and the deployment that no SDK can guess.

Why this is still a research problem

Respiration from mmWave is effectively solved for a still subject; heart rate is usable but fragile; heart-rate variability and any beat-to-beat timing are at the edge of what phase interferometry can deliver, because the cardiac displacement is small and its shape is not a clean impulse. Three hard problems define the frontier. Motion robustness: real subjects move, and separating a heartbeat from residual body sway is unsolved in general. Multi-person scenes: two sleepers, or a patient and a caregiver, require range-angle separation and still leak. And validation: an estimate that agrees with a chest belt in a lab can fail silently at home, so leakage-safe, subject-disjoint evaluation across postures and distances (the discipline of Chapter 5) is non-negotiable before any clinical claim.

Research frontier

The current direction is to stop hand-crafting the band separation and learn it. Deep models map the range-Doppler-time cube (or the raw phase) directly to vital signs, trained against a synchronized reference such as an ECG or a chest belt. Google's Nest Hub uses the low-power Soli 60 GHz radar for contactless "Sleep Sensing," estimating breathing and detecting cough and motion at the bedside without a camera or a worn device, and cleared US FDA 510(k) review as a sleep-disturbance assessment aid, an existence proof that radar vitals can pass a regulatory bar. On the open-research side, mmWave heart-rate networks trained on public sets such as the University of Glasgow radar respiration data and TI-captured cardiac datasets now recover heart rate within a few beats per minute at rest, though beat-to-beat variability under motion remains open. The unifying theme with Chapter 44 is that the learned model still consumes the same phase physics; it replaces the fragile filter bank, not the interferometry.

Exercise

Extend the simulation above into a small robustness study. (1) Add a slow 0.03 Hz body-sway term of amplitude 2 mm to the displacement and re-estimate both rates; report which one degrades and why. (2) Insert a 12-second apnea by zeroing the respiration component over one interval, build an envelope of the respiration-band signal, and write a detector that flags sustained amplitude drops with the correct ten-second minimum; measure onset latency. (3) Sweep the carrier from 24 GHz to 77 GHz and plot the cardiac phase amplitude versus frequency; explain the trend from the \(\phi = 4\pi d/\lambda\) relation and state one practical cost of going higher.

Self-check

  1. Why do the vital signs live in the phase of a range bin rather than in its magnitude, and what does raising the carrier frequency do to the recoverable heartbeat signal?
  2. You band-pass the phase from 0.6 to 2.0 Hz and read heart rate as the FFT peak. On a real recording it lands near 30 bpm. What physiological signal has your estimator most likely locked onto, and how would you fix it?
  3. Respiration rate from mmWave is far more reliable than heart-rate variability. Give the two physical reasons rooted in the size and shape of the chest displacement.

What's Next

In Section 33.5, we keep the no-contact promise but swap radio for light: camera-based remote photoplethysmography reads the pulse from the faint color changes of the skin. It is even less obtrusive than a radar puck and raises a sharper question, because a camera that measures your heart rate has also recorded your face, so the section confronts the privacy tradeoffs head on.