Jammer Models

This module provides classes for simulating one or multiple jammers. They are meant to be used to simulate jammers in the context of OFDM-based communication.

The main way of functioning is the following:

1. Build a communication pipeline between “regular” UEs and BSs.
2. Instantiate an additional channel model between the jammers and the BSs.
3. Instantiate a jammer, using the channel created in step 2.
4. Add the jammer to the communication pipeline, right after the channel between the UEs and the BSs like so:
>>> y = channel([x, no])
>>> y_jammed = jammer([y, rho])

The module consists of two main classes: OFDMJammer and TimeDomainOFDMJammer. The former is to be used for simulations solely in the frequency domain, while the latter is to be used for simulations in the time domain.

TimeDomainOFDMJammer can hence be used to jammers which violate the OFDM assumptions, i.e. not sending a cyclic prefix. The simulation is much slower, however.

OFDMJammer currently has much more functionality implemented, and can i.e. be used to simulate learning/smart jammers.

class pyjama.jammer.OFDMJammer(*args, **kwargs)[source]

Used to simulate a jammer in the frequency domain only (i.e. sending a cyclic prefix). The jammer signal is generated through the given (Jammer-BS) channel model.

It can be trained, and support several other functionalities, which are described in the following.

Jamming Types

Jamming types refer to which resource elements are jammed. This can additionally be modified by the shape of \(\rho\) (see below). The following jamming types are supported:

  • Barrage Jamming: All resource elements are jammed.

  • Pilot Jamming: Only pilot resource elements are jammed.

  • Data Jamming: Only data resource elements are jammed.

  • Non-Silent Jamming: Only non-silent resource elements are jammed. This is similar to pilot jamming, but does not jam the “silent” pilot symbols where jammer usually is estimated.

The power of the symbols sent by the jammer will be scaled so that the mean power of each resource element over the whole resource grid is equal to \(\rho\).

Sparse Jamming

Sparse jamming refers to the fact that only a fraction of the resource elements are jammed. This is controlled by the parameters density_symbols and density_subcarriers. A value of 1.0 means that all resource elements are jammed, while a value of 0.0 means that no resource elements are jammed.

This is done by nulling said percentage of rows or columns of the resource grid. Hence, it is meant to be understood not as an exact number of resource elements, but rounded to the next integer.

Sparsity is ill-defined for non-barrage jammers. For example, pilots might not be evenly distributed. It would then not be clear what sparsity means. Hence, sparsity is only supported for barrage jammers.

Jamming Power & Jamming Pattern

The jamming power is controlled by the parameter \(\rho\). It is given for every call of the jammer, and can be thought of as the square of coefficients which the jammer symbols are multiplied by. It might be a single value, or a tensor of shape broadcastable to [batch_size, num_tx, num_tx_ant, num_ofdm_symbols, fft_size], where num_tx and num_tx_ant are the number of jammers and their antennas, respectively.

One can hence e.g. jam only a part of the resource grid by using passing in a tensor of shape [num_ofdm_symbols, fft_size], where several resource elements are zero, or regulate the power of different jammers by passing in a tensor of shape [num_tx, 1, 1, 1], with different values for each jammer.

Different Sampling Methods

The jammers can be thought of as UEs, which sample their symbols \(x\) somehow with power \(E[|x|^2] = 1\). These symbols are then scaled by \(\sqrt{\rho}\), possibly nulled (see above) and sent through the jammer channel. The result is then added to the received signal.

The interface of this class accepts a number of strings for predefined sampling methods. Alternatively, a constellation which is randomly sampled or a callable which acts as sampling function can be passed in. See documentation of the input parameter sampler for the specific types.

Training

In general, the jammer can be trained by setting trainable=True. Weights (i.e. coefficients of the sampled jammer symbols) can then be learned.

As parameters to an instance of this class, one can pass a mask, a constraint and a boolean constraint_integrated. The mask is a boolean tensor of shape broadcastable to [num_tx, num_tx_ant, num_ofdm_symbols, fft_size]. If True, the corresponding weight is trainable. If False, the weight is held constant at 1.0.

To all trainable weights, a constraint is applied. By default, this constrains the mean power of those weights to be \(\leq 1.0\).

This constraint can either be applied after each step of the optimizer, or part of the calculation itself. This is controlled by the boolean constraint_integrated. Empirically speaking, the former might help breaking out of local minima (as the optimizer just takes a step in direction of the unconstrained optimum, the constraint is just applied afterwards) while the latter helps with convergence (as the constraint is reflected in the gradient).

Parameters
  • channel_model (ChannelModel) – Instance of sionna.channel.ChannelModel.Channel between jammer(s) and BS(s).

  • rg (ResourceGrid) – Instance of sionna.ofdm.ResourceGrid. Resource grid of the OFDM system.

  • num_tx (int) – Number of jammers.

  • num_tx_ant (int) – Number of antennas of each jammer.

  • jamming_type (str) – One of [“barrage”, “pilot”, “data”, “non_silent”].

  • density_symbols (float) – Fraction of symbol times which are jammed. Must be in between 0 and 1.

  • density_subcarriers (float) – Fraction of subcarriers which are jammed. Must be in between 0 and 1.

  • normalize_channel (bool) – Whether to normalize the channel. If True, the channel is normalized so that for each link the mean energy of each channel coefficient is 1.0. (this is just for the channel coefficients).

  • return_channel (bool) – Whether to return the jammer channel frequency response should be returned in addition to the jammed signal.

  • sampler (str, instance of Constellation, or callable) – If str, one of [“uniform”, “gaussian”]. If instance of Constellation, the constellation is sampled randomly. If callable, the callable is used as sampling function. It should have signature (shape, dtype) -> tf.Tensor. In the first two cases, the mean energy of the sampled symbols is 1.0. In the last case, the caller is responsible for the energy of the sampled symbols.

  • trainable (bool) – Whether the jammer weights are trainable.

  • trainable_mask (None, or tensor broadcastable to [num_tx, num_tx_ant, num_ofdm_symbols, fft_size]) – If None, all weights are trainable. If tensor, only weights where the mask is True are trainable.

  • training_constraint (None, callable or instance of tf.keras.constraints.Constraint) – Constraint to be applied to the trainable weights. If None, no constraint is applied. The callable should take a tensor as argument and return a tensor of the same shape.

  • constraint_integrated (bool) – If True, the constraint is integrated into the network. If False, the constraint is applied after each optimization step.

  • dtype (tf.complex) – Data type of the jammer symbols. Defaults to tf.complex64.

Input
  • y ([batch_size, num_rx, num_rx_ant, num_ofdm_symbols, fft_size], tf.complex) – Unjammed signal. Shape

  • rho (broadcastable to [batch_size, num_tx, num_tx_ant, num_ofdm_symbols, fft_size], tf.float) – Power of jammer signal. See section “Jamming Power & Jamming Pattern” above for details.

Output
  • (y_jammed, h_freq_jammer) or y_jammed (Tuple or Tensor)

  • y_jammed ([batch_size, num_rx, num_rx_ant, num_ofdm_symbols, fft_size], tf.complex) – Input signal with jammer interference added.

  • h_freq_jammer ([batch_size, num_rx, num_rx_ant, num_tx, num_tx_ant, num_ofdm_symbols, fft_size], tf.complex) – Frequency response of jammer channel. Only returned if return_channel is True.

class pyjama.jammer.TimeDomainOFDMJammer(*args, **kwargs)[source]

This class is meant ot simulate jammers in the time domain channel. It is much slower than OFDMJammer, but can be used to simulate jammers which violate the OFDM assumptions, i.e. not sending a cyclic prefix. It thus functions similarily to OFDMJammer, with the following differences:

  • Some functionality is not supported, such as learning jammer weights. This might be implemented in the future.

  • The input signal is assumed to be in the time domain. The output can be chosen to be in the time domain or frequency domain using the parameter return_domain.

  • Cyclic prefix will or will not be sent depending on the parameter send_cyclic_prefix.

Parameters
  • channel_model (ChannelModel) – Instance of sionna.channel.ChannelModel.Channel between jammer(s) and BS(s).

  • rg (ResourceGrid) – Instance of sionna.ofdm.ResourceGrid. Resource grid of the OFDM system.

  • num_tx (int) – Number of jammers.

  • num_tx_ant (int) – Number of antennas of each jammer.

  • send_cyclic_prefix (bool) – If true, the jammer adheres to the OFDM assumptions and sends a cyclic prefix. If false, the jammer sends randomly sampled symbols instead.

  • normalize_channel (bool) – Whether to normalize the channel. If True, the channel is normalized so that for each link the mean energy of each channel coefficient is 1.0.

  • return_channel (bool) – If true,