ofdm_to_delay_doppler_channel#

sionna.phy.channel.ofdm_to_delay_doppler_channel(h_f: torch.Tensor, l_min: int = 0, l_max: int | None = None) → torch.Tensor[source]#

Compute the delay-Doppler channel from a channel frequency response on a complete OFDM time-frequency grid

Given a channel frequency response \(\hat{h}_{b,n}\), the delay-Doppler channel is computed as

\[\tilde{h}_{q,\ell} = \frac{1}{NS}\sum_{b=0}^{S-1}\sum_{n=0}^{N-1} \hat{h}_{b,n} e^{j\frac{2\pi n\ell}{N}} e^{-j\frac{2\pi bq}{S}},\]

for \(\ell=L_\text{min},\ldots,L_\text{max}\), where \(N\) is fft_size, \(S\) is num_time_steps, \(b\) is the time-step index, \(n\) is the frequency-bin index after undoing the centered subcarrier ordering, \(q\) is the Doppler-bin index, and \(\ell\) is the time-lag index. If l_max is None, \(L_\text{max}=L_\text{min}+N-1\).

Parameters:
  • h_f (torch.Tensor) – Channel frequency responses on a complete, uniformly spaced OFDM frequency grid in centered subcarrier order, shape […, num_time_steps, fft_size]

  • l_min (int) – Smallest time-lag for the discrete complex-baseband channel impulse response (\(L_{\text{min}}\)). Defaults to 0.

  • l_max (int | None) – Largest time-lag for the discrete complex-baseband channel impulse response (\(L_{\text{max}}\)). If None, all fft_size lags starting at l_min are returned. Defaults to None.

Outputs:

h_dd – […, num_doppler_bins, num_time_lags], torch.complex. Delay-Doppler channel with centered Doppler-bin ordering, where num_doppler_bins = num_time_steps. If l_max is None, num_time_lags = fft_size; otherwise, num_time_lags = l_max-l_min+1.

Notes

This function is the composition of ofdm_to_time_channel() and time_to_doppler_channel(). The OFDM input must contain a complete, uniformly spaced DFT grid.

A path with a delay and a Doppler shift on the grid appears in a single bin equal to its path coefficient. The channel energy is preserved, \(\sum_{q,\ell}|\tilde{h}_{q,\ell}|^2 = \frac{1}{NS}\sum_{b=0}^{S-1}\sum_{n=0}^{N-1}|\hat{h}_{b,n}|^2\), if all fft_size lags are returned. Selecting fewer lags can only reduce the energy.

The delay of time lag \(\ell\) is \(\ell/W\), where \(W\) is the bandwidth, and the frequency of each Doppler bin is obtained from time_frequency_vector().

Examples

import matplotlib.pyplot as plt
import torch
from sionna.phy import PI
from sionna.phy.channel import (cir_to_ofdm_channel,
    ofdm_to_delay_doppler_channel, subcarrier_frequencies)
from sionna.phy.isac import plot_delay_doppler

# OFDM sensing waveform with one channel observation per OFDM symbol
fft_size = 256
subcarrier_spacing = 30e3
num_time_steps = 128
bandwidth = fft_size*subcarrier_spacing
observation_spacing = 1/subcarrier_spacing

# Two targets, each with a delay, a Doppler shift, and a path gain
delays = torch.tensor([1.2e-6, 3.0e-6])
dopplers = torch.tensor([3.5e3, -9.0e3])
gains = torch.tensor([1., 0.5])

# Time-varying path coefficients a_m(t) = g_m e^{j2 pi nu_m t}
t = torch.arange(num_time_steps)*observation_spacing
a = gains[:, None]*torch.polar(torch.ones(2, num_time_steps),
                               2*PI*dopplers[:, None]*t)
a = a.reshape(1, 1, 1, 1, 1, 2, num_time_steps)
tau = delays.reshape(1, 1, 1, 2)

# Compute the OFDM channel and convert it to the delay-Doppler domain
frequencies = subcarrier_frequencies(fft_size, subcarrier_spacing)
h_f = cir_to_ofdm_channel(frequencies, a, tau)
h_dd = ofdm_to_delay_doppler_channel(h_f).squeeze()

# Show the delay-Doppler map around the targets. The sample rates
# turn the lag and Doppler bin indices into delays and frequencies.
num_lags = 40
fig, ax = plot_delay_doppler(
    h_dd[:, :num_lags].abs().square(),
    fast_time_sample_rate=bandwidth,
    slow_time_sample_rate=1/observation_spacing)
ax.scatter(delays*1e6, dopplers/1e3, marker="x", c="red",
           label="Target")
ax.legend()
plt.show()
../../../../_images/ofdm_to_delay_doppler_channel.png

Fig. 23 Delay-Doppler channel of two targets. The peaks coincide with the target delays and Doppler shifts.#