SIMO, TDM, BPM, and DDM#
Each MIMO strategy receives canonical ADC and returns decoded virtual channels.
It owns both channelMap and slow-time timing, so downstream code does not need
hardware branches.
Virtual channels#
For far-field monostatic MIMO, the phase centre for TX \(i\) and RX \(j\) is
channelMap defines which (txId, rxId) pair occupies each decoded channel.
Geometry is built from this map rather than assuming TX-major ordering elsewhere.
SIMO#
SIMO has one transmitter and one emission per loop. Decoding removes only the singleton emission axis:
mimo = SIMO(numRx=4)
TDM#
TDM records one emission per active TX in every loop. txOrder is the physical
TX id fired at each emission index and may be arbitrary:
mimo = TDM(numTx=3, numRx=4, txOrder=(2, 0, 1))
A moving target accumulates extra phase because TX channels are sampled at different times. If channel \(m\) was emitted at offset \(\tau_m\) and the shifted Doppler bin corresponds to \(f_D\), the library applies
Offsets come from emissionTimeOffsets when supplied; otherwise they are derived
from emission index and chirp interval. Compensation therefore follows real TX
timing and does not assume an ascending TX id.
The ordinary TDM velocity limit is based on one full emission cycle. When
Calibration.overlapPairs contains repeated phase centres, the model-aware
pipeline evaluates Doppler candidates separated by the slow-time PRF. Each
candidate is corrected with the real TX timestamps, and the candidate minimizing
calibrated overlap-channel phase error supplies point-cloud radial velocity and
the final DoA correction. Candidates are limited to the raw chirp-rate Nyquist
interval. If overlap energy is zero, order zero is retained rather than guessed.
This behavior is controlled by PointCloudConfig.unwrapTdmVelocity. The selected
integer alias order is recorded in FrameResult.metadata["dopplerAmbiguityOrder"].
BPM#
Two-TX BPM uses two coded emissions. With the default Hadamard matrix,
mimo = BPM(numRx=4)
The code matrix is validated as invertible. The target should not change materially over the two coded chirps.
DDM#
DDM transmits all configured TX channels in one emission using slow-time linear phase codes
where dopplerOffsets[i] is \(q_i\) in cycles per raw chirp. Codes must be
orthogonal over codeLength. The decoder correlates each complete code period:
mimo = DDM(
numTx=4,
numRx=4,
dopplerOffsets=(0.0, 0.25, 0.5, 0.75),
codeLength=4,
)
The number of raw loops must be divisible by codeLength, and the target is
assumed approximately constant during one code block.
Numerical contract#
All four decoders accept (loop, emission, rx, ...); wrong emission or RX sizes
raise ValueError. Synthetic noiseless encode/decode tests require relative error
below \(10^{-6}\).