Radar and waveforms

How a Radar record describes the carrier, waveform, antenna array, pose and polarization, and how FMCW, OFDM and pulsed waveforms map to cube axes.

A Radar is one immutable record that describes the instrument: its carrier, its waveform, its antenna array, its receiver chain and where it sits in the world. This page explains each part and the conventions behind it. For every field, see the Radar API.

Units#

All fields are SI: metres, seconds, hertz, watts or decibels where the name says so. Two places read vendor units, and both say so in their names:

  • Radar.from_dict(...) and Radar.from_json(...) read the flat FMCW configuration format: slope in MHz/µs, sample rate in ksps, times in µs, power in dBm, antenna positions in half wavelengths. See Load a radar configuration file.
  • Fmcw.from_ti(...) takes the same vendor units as keyword arguments whose names carry the unit, such as slope_mhz_per_us.

power is the transmit power in dBm on every route. Radar.transmit_power_watts gives it in watts.

The record is immutable#

A radar never changes after construction. radar.replace(**fields) returns a new radar with some fields changed, and radar.to(device) returns a copy on another device. This means a radar held by a closure or a result cannot change underneath it, and a simulation call cannot leave state on it.

radar_far = radar.replace(position=(0.0, 0.0, 2.0))
radar_noisy = radar.replace(noise=Noise(figure=12.0), seed=7)

Pose and the radar frame#

The radar has a local frame like a camera:

  • position is the array origin in world coordinates, default (0, 0, 0).
  • look_at is a world point on the boresight, default (0, 0, -1). The boresight is the radar's local -z axis.
  • up is a world vector that fixes the roll, default (0, 1, 0). It is the local +y axis after orthogonalization.
  • Local +x completes a right-handed frame.

look_at must differ from position, and up must not be parallel to the view direction. The pose is a host declaration: passing a tensor that carries a gradient raises an error instead of silently detaching it. To differentiate antenna positions, see Differentiability.

Antenna array#

tx and rx are sequences of (x, y, z) element positions in the radar's local frame. antenna_unit says how to read them:

  • "m" (default): metres.
  • "half_wavelength": multiples of half the carrier wavelength, the usual way a MIMO layout is written. from_dict sets this unit.

num_tx and num_rx are the element counts. With FMCW, the transmitters fire in time-division multiplexing (TDM): each chirp slot belongs to one transmitter, so the virtual array has num_tx * num_rx pairs and the velocity ambiguity shrinks by a factor of num_tx.

Polarization#

Channel projects the transmitted field onto a polarization vector. polarization accepts:

  • "up" (default): the pose's own up axis, which is always transverse to the boresight.
  • "right": the pose's local +x axis.
  • A world vector. A vector parallel to the boresight radiates nothing and is refused at construction.

Antenna pattern#

pattern is the element gain pattern applied to every round trip. The default is Pattern.isotropic(), which applies no gain. Pattern.dipole() is a half-wave dipole cut, and Pattern.separable(...) and Pattern.table(...) take a measured pattern. See Use antenna patterns.

Waveforms#

waveform is one of three records. The waveform sets the slow-time and fast-time axes of the cube.

WaveformRecordSlow axisFast axisCube content
FMCWFmcwchirprange_bin (default) or sampleDe-chirped beat signal, as a range spectrum or as ADC samples
OFDMOfdmsymbolsubcarrierChannel frequency response per symbol and subcarrier
PulsedPulsedpulsesampleReceived baseband pulse train in the range gate (matched-filter input)

The full cube is [frame, tx, rx, slow, fast] for every waveform.

FMCW#

An FMCW frame is chirps_per_frame chirps. Each chirp ramps at slope (Hz/s) for ramp_end seconds after an idle time, and the ADC takes samples_per_chirp samples at sample_rate starting adc_start seconds into the ramp. The chirp period is idle + ramp_end.

output picks what the fast axis holds:

  • "spectrum" (default): the normalized range spectrum. The fast axis is range_bin, and its bin size is c · sample_rate / (2 · slope · samples_per_chirp) metres. A static scene uses an exact closed form (Dirichlet kernel) for each row instead of synthesizing samples.
  • "beat": the time-domain ADC samples. The fast axis is sample. Use it when you need raw samples or a custom range transform.

Derived quantities, all available on result.axes after a run:

QuantityFormula
Range binc · fs / (2 · S · N), with fs the sample rate, S the slope and N the samples per chirp
Slot periodchirp_period · num_tx
Maximum unambiguous speedλ / (4 · chirp_period · num_tx)

OFDM#

An Ofdm waveform is a grid of num_symbols symbols by num_subcarriers subcarriers with spacing subcarrier_spacing. The cube is the channel frequency response that per-subcarrier equalization leaves, not a time-domain waveform. Subcarrier n is at carrier + n · subcarrier_spacing.

  • Range resolution: c / (2 · num_subcarriers · subcarrier_spacing).
  • Symbol period: 1 / subcarrier_spacing + cyclic_prefix. It is the slow-time sample period.
  • max_expected_delay is the longest round-trip delay you configure the radar for. It must be shorter than cyclic_prefix.

OFDM synthesis is narrowband: the material and antenna response is evaluated at the carrier and held across the band, and only the propagation delay depends on frequency.

Pulsed#

A Pulsed waveform is num_pulses pulses at a pulse repetition interval pri. pulse_kind is "rect" or "lfm" (linear frequency modulation). The receiver samples num_samples samples at sample_rate starting at range_gate_start.

  • Range resolution: c / (2 · bandwidth) for LFM, c · pulse_width / 2 for a rectangular pulse. For a rectangular pulse, set bandwidth to 1 / pulse_width.
  • The pulse must be shorter than pri, and the range gate must fit inside one pri.
  • max_expected_delay_rate bounds the delay rate you expect. Over the coherent processing interval the delay must not walk more than one range cell.

The matched filter is processing, not synthesis: range_profile correlates the train against the analytic pulse replica. See Use OFDM and pulsed waveforms.

Phasor conventions#

Radar records the phase convention of every cube as data, so processing never infers it from a method name.

  • Time dependence is exp(+j·2π·f·t) for every waveform.
  • OFDM and pulsed cubes use Channel's propagation phasor exp(-j·k·d).
  • The FMCW beat cube is the conjugate, conj(exp(-j·k·d)), because de-chirping multiplies by the conjugate of the transmitted chirp.

range_doppler_map reconciles the two, so for every waveform a positive Doppler bin is a closing target.