Waveforms

The Fmcw, Ofdm and Pulsed waveform records, their fields, units, defaults and derived properties, and Fmcw.from_ti for vendor units.

A waveform record sets the timing of one frame and the slow-time and fast-time axes of the cube. All three are frozen dataclasses in SI units and are passed to Radar(waveform=...).

from witwin.radar import Fmcw, Ofdm, Pulsed

The physics behind each waveform is on Radar and waveforms.

RecordkindCube axes after frame
Fmcw"fmcw"tx, rx, chirp, range_bin or sample
Ofdm"ofdm"tx, rx, symbol, subcarrier
Pulsed"pulsed"tx, rx, pulse, sample

Fmcw#

class Fmcw(slope, sample_rate, samples_per_chirp, chirps_per_frame, adc_start, idle, ramp_end, output='spectrum')

One FMCW chirp and its ADC window. With several transmitters, the chirps are shared in time-division multiplexing.

slopefloatrequired

Chirp slope, Hz/s. 60.012e12 is 60.012 MHz/µs.

sample_ratefloatrequired

ADC sample rate, samples/s.

samples_per_chirpintrequired

ADC samples per chirp. The length of the fast axis.

chirps_per_frameintrequired

Chirps per frame. The length of the slow axis.

adc_startfloatrequired

ADC start time after the ramp starts, s.

idlefloatrequired

Idle time before each ramp, s.

ramp_endfloatrequired

Ramp duration, s.

outputstrdefault 'spectrum'

"spectrum" returns the normalized range spectrum (fast axis range_bin). "beat" returns the time-domain ADC samples (fast axis sample).

Raises ValueError if sample_rate or ramp_end is not positive, samples_per_chirp or chirps_per_frame is not a positive int, slope or adc_start is not finite, idle is negative, or output is not "spectrum" or "beat".

PropertyReturns
kind"fmcw" (class attribute).
chirp_periodidle + ramp_end, s.
bandwidthSampling bandwidth a thermal-noise stage integrates over, Hz. Equal to sample_rate.
fmcw = Fmcw(slope=60.012e12, sample_rate=4.4e6, samples_per_chirp=256, chirps_per_frame=128,
            adc_start=6e-6, idle=7e-6, ramp_end=65e-6)
print(fmcw.chirp_period)   # 7.2e-05

Fmcw.from_ti#

Fmcw.from_ti(*, slope_mhz_per_us, sample_rate_ksps, samples_per_chirp, chirps_per_frame,
             adc_start_us, idle_us, ramp_end_us, output='spectrum') -> Fmcw

Build from the units a TI-style configuration file uses. Each argument name carries its unit.

fmcw = Fmcw.from_ti(slope_mhz_per_us=60.012, sample_rate_ksps=4400, samples_per_chirp=256,
                    chirps_per_frame=128, adc_start_us=6, idle_us=7, ramp_end_us=65)

Returns Fmcw in SI units.

Fmcw.to_spec#

Fmcw.to_spec(*, carrier, num_tx=1, num_rx=1, offset=0.0) -> FmcwSpec

The SI synthesis spec. You rarely need it; Radar.waveform_spec() calls it with the radar's own carrier and array. See Synthesis.

Ofdm#

class Ofdm(subcarrier_spacing, num_subcarriers, cyclic_prefix, num_symbols, max_expected_delay,
           subcarrier_origin='f_ref_at_n0')

One OFDM symbol grid. The cube is the channel frequency response per symbol and subcarrier.

subcarrier_spacingfloatrequired

Subcarrier spacing, Hz.

num_subcarriersintrequired

Number of subcarriers. The length of the fast axis.

cyclic_prefixfloatrequired

Cyclic prefix duration, s.

num_symbolsintrequired

Symbols per frame. The length of the slow axis.

max_expected_delayfloatrequired

Longest round-trip delay the radar is configured for, s. Must be shorter than cyclic_prefix.

subcarrier_originstrdefault 'f_ref_at_n0'

Where subcarrier 0 sits. The only value pins subcarrier 0 to the carrier, so subcarrier n is at carrier + n · subcarrier_spacing.

PropertyReturns
kind"ofdm" (class attribute).
bandwidthOccupied band, num_subcarriers · subcarrier_spacing, Hz.
sample_rateSample rate of the symbol grid, Hz. Equal to bandwidth.

Raises ValueError if subcarrier_spacing or cyclic_prefix is not positive, num_subcarriers or num_symbols is not a positive int, or max_expected_delay is negative.

ofdm = Ofdm(subcarrier_spacing=120e3, num_subcarriers=256, cyclic_prefix=0.6e-6,
            num_symbols=32, max_expected_delay=0.1e-6)

Ofdm.to_spec(*, carrier, offset=0.0) -> OfdmSpec returns the SI synthesis spec.

Pulsed#

class Pulsed(pulse_kind, pulse_width, bandwidth, pri, num_pulses, sample_rate, num_samples,
             range_gate_start, max_expected_delay_rate=0.0, pulse_normalization='unit_energy')

One pulse train and its range gate. The cube is the received baseband train, which is the matched-filter input.

pulse_kindstrrequired

"rect" for a rectangular pulse or "lfm" for a linear frequency-modulated pulse.

pulse_widthfloatrequired

Pulse duration, s.

bandwidthfloatrequired

LFM sweep bandwidth, Hz. For "rect", set it to 1 / pulse_width.

prifloatrequired

Pulse repetition interval, s.

num_pulsesintrequired

Pulses per frame. The length of the slow axis.

sample_ratefloatrequired

Receiver sample rate, samples/s.

num_samplesintrequired

Samples in the range gate. The length of the fast axis.

range_gate_startfloatrequired

Delay at which the range gate opens, s.

max_expected_delay_ratefloatdefault 0.0

Configured bound on the round-trip delay rate, s/s. Used to check that the echo does not migrate more than one range cell over the frame.

pulse_normalizationstrdefault 'unit_energy'

Pulse energy normalization. The only value is unit energy.

PropertyReturns
kind"pulsed" (class attribute).

Raises ValueError if pulse_width, bandwidth, pri or sample_rate is not positive, num_pulses or num_samples is not a positive int, or range_gate_start or max_expected_delay_rate is negative.

pulsed = Pulsed(pulse_kind="lfm", pulse_width=1e-6, bandwidth=150e6, pri=50e-6, num_pulses=16,
                sample_rate=300e6, num_samples=512, range_gate_start=0.0)

Pulsed.to_spec(*, carrier, offset=0.0) -> PulsedSpec returns the SI synthesis spec. The spec checks the pulse against the PRI and the range gate; see Use OFDM and pulsed waveforms.