Load a radar configuration file

Build a Radar from the flat FMCW configuration format with Radar.from_dict or Radar.from_json, and add a receiver chain, pose or pattern in the same call.

Many mmWave tools describe an FMCW radar as one flat mapping in the units a TI radar configuration file uses. Radar.from_dict reads that mapping, and Radar.from_json reads it from a JSON file. Use this page to load such a file and to know exactly which keys it accepts.

Load a mapping#

from witwin.radar import Noise, Radar
 
CONFIG = {
    "num_tx": 3, "num_rx": 4, "fc": 77e9, "slope": 60.012, "adc_samples": 256,
    "adc_start_time": 6, "sample_rate": 4400, "idle_time": 7, "ramp_end_time": 65,
    "chirp_per_frame": 128, "power": 15,
    "tx_loc": [[0, 0, 0], [4, 0, 0], [2, 1, 0]],
    "rx_loc": [[-6, 0, 0], [-5, 0, 0], [-4, 0, 0], [-3, 0, 0]],
}
radar = Radar.from_dict(CONFIG, noise=Noise(figure=10.0), seed=1, position=(0.0, 1.0, 0.0), look_at=(0.0, 1.0, -1.0))

Keyword arguments after the mapping are Radar fields in SI units. They override what the mapping produced, so you attach a receiver chain, a pose, a seed or a device without editing the file.

To read the same mapping from a file:

radar = Radar.from_json("configs/iwr1843.json", noise=Noise(figure=10.0))

Required keys#

KeyUnitBecomes
num_txcountMust equal the length of tx_loc
num_rxcountMust equal the length of rx_loc
fcHzRadar.carrier
slopeMHz/µsFmcw.slope (Hz/s)
adc_samplescountFmcw.samples_per_chirp
adc_start_timeµsFmcw.adc_start (s)
sample_ratekspsFmcw.sample_rate (Hz)
idle_timeµsFmcw.idle (s)
ramp_end_timeµsFmcw.ramp_end (s)
chirp_per_framecountFmcw.chirps_per_frame
powerdBmRadar.power
tx_lochalf wavelengthsRadar.tx, with antenna_unit="half_wavelength"
rx_lochalf wavelengthsRadar.rx

Optional keys#

KeyMeaning
output_domain"spectrum" (default) or "beat". Becomes Fmcw.output
antenna_patternAn element pattern, in one of the two forms below

A separable pattern gives one cut per axis:

"antenna_pattern": {
  "kind": "separable",
  "x_angles_deg": [-90, -45, 0, 45, 90], "x_values": [0.0, 0.6, 1.0, 0.6, 0.0],
  "y_angles_deg": [-90, -45, 0, 45, 90], "y_values": [0.0, 0.7, 1.0, 0.7, 0.0]
}

A map gives the gain on a full grid. values holds one row per y_angles_deg sample, and each row holds one value per x_angles_deg sample:

"antenna_pattern": {
  "kind": "map",
  "x_angles_deg": [-60, 0, 60], "y_angles_deg": [-60, 0, 60],
  "values": [[0.2, 0.5, 0.2], [0.5, 1.0, 0.5], [0.2, 0.5, 0.2]]
}

If kind is missing, a block with values is read as a map and any other block as separable. Gains are linear power gains normalized to at most 1, and angles are in degrees; see Use antenna patterns.

Refused keys#

Any other key raises ValueError that names it. This includes processing settings that older configuration files carried, such as frame_per_second, num_doppler_bins, num_range_bins and num_angle_bins. Frame times are the times argument of simulate, and bin counts follow from the waveform. Remove those keys before loading.

Non-FMCW radars#

The flat format describes FMCW only. For an OFDM or pulsed radar, build the Radar directly, or pass waveform=Ofdm(...) as an override. See Use OFDM and pulsed waveforms.

Typed construction#

The same radar without a mapping, using Fmcw.from_ti for the vendor units and metres for the antennas:

from witwin.radar import Fmcw, Radar
 
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)
radar = Radar(
    carrier=77e9, waveform=fmcw, power=15.0, antenna_unit="half_wavelength",
    tx=[(0, 0, 0), (4, 0, 0), (2, 1, 0)],
    rx=[(-6, 0, 0), (-5, 0, 0), (-4, 0, 0), (-3, 0, 0)],
)