Getting Started#
Install#
pyradar v1 release candidates are distributed on GitHub Releases rather than
PyPI because that distribution name is already occupied. Install a downloaded
wheel with:
python -m pip install pyradar-1.0.0rc1-py3-none-any.whl
For a source checkout:
python -m pip install -e ".[examples]"
Python 3.10 through 3.13 are supported.
Define the radar first#
The minimum custom model combines five physical pieces. Positions are metres in FLU and times are seconds.
import numpy as np
from pyradar.base import FMCW, Radar, Sampler, SIMO, Transceivers
waveform = FMCW(
startFrequency=77e9,
slope=40e12,
adcStartTime=4e-6,
rampEndTime=36e-6,
idleTime=8e-6,
)
sampler = Sampler(
numSamples=256,
numLoops=64,
sampleRate=10e6,
)
rx = np.column_stack(
(np.zeros(8), np.arange(8) * 1.95e-3, np.zeros(8))
)
radar = Radar(
waveform=waveform,
sampler=sampler,
transceivers=Transceivers(
txPositions=np.array([[0.0, 0.0, 0.0]]),
rxPositions=rx,
),
mimo=SIMO(numRx=8),
name="lab_ula",
)
The model now derives its axes and limits:
print(radar.rangeResolution, radar.rangeBinSize)
print(radar.velocityResolution, radar.maxUnambiguousVelocity)
print(radar.arrayGeometry, radar.unambiguousFov)
Process one frame#
Describe dimensions at the point where the raw array enters the library:
result = radar.build_pipeline().process(
adc,
dims=("loop", "emission", "rx", "sample"),
timestamp=12.4,
frameId=31,
)
xyzPowerSnrVelocity = result.pointCloud.to_numpy()
The canonical ADC shape is always loop/emission/rx/sample. A missing dimension
is inserted only when the model proves it is a singleton. This avoids silently
swapping receivers and chirps when two axes happen to have equal lengths.
Simulate a modeled target#
The same radar can generate canonical ADC for a point target. MIMO codes, emission timing, bistatic TX/RX geometry, and sampled-band phase all come from the model:
from pyradar.sim import PointTarget
target = PointTarget(
position=np.array([20.0, 3.0, 0.5]),
velocity=np.array([-2.0, 0.0, 0.0]),
rcs=5.0,
)
synthetic = radar.simulate(target, noisePower=1e-4, seed=8)
syntheticResult = radar.process_adc(synthetic)
See Radar-aware simulation for propagation paths, quantization, scene sampling, and optional mesh ray tracing.
Load YAML or JSON#
pyradar.base.Radar.from_config() accepts the same camelCase field names as
the Python constructors:
name: lab_ula
waveform:
startFrequency: 77000000000.0
slope: 40000000000000.0
adcStartTime: 0.000004
rampEndTime: 0.000036
idleTime: 0.000008
sampler:
numSamples: 256
numLoops: 64
sampleRate: 10000000.0
transceivers:
txPositions: [[0.0, 0.0, 0.0]]
rxPositions:
- [0.0, 0.000000, 0.0]
- [0.0, 0.001950, 0.0]
mimo:
type: simo
processing:
fft:
rangeFftSize: 512
dopplerFftSize: 64
rangeWindow: hann
cfar:
method: os
pfa: 0.0001
Dataset adapters#
Readers decode storage layout and create an ADCFrame plus an appropriate radar
profile. Signal processing remains in pyradar.rsp:
from pyradar.utils.io import ColoRadarReader
reader = ColoRadarReader(datasetRoot)
frame = reader.read_frame(0)
result = frame.radar.process_adc(frame)
See Data and licenses for expected local layouts.