Communication#

The communication package contains a propgramming framework for simulating and evaluating communication systems on the physical layer. It is primarily comprised of Modem implementations and associated Communication Waveforms:

classDiagram class CommunicationWaveform { <<Abstract>> %%+int oversampling_factor %%+int modulation_order %%+int num_data_symbols* %%+int samples_per_frame* %%+float frame_duration %%+float symbol_duration* %%+float bit_energy* %%+float symbol_energy* %%+float power* +map(numpy.ndarray) Symbols* +unmap(Symbols) np.ndarray* +place(Symbols) Symbols* +pick(StatedSymbols) StatedSymbols* +modulate(Symbols) np.ndarray* +demodulate(np.ndarray) Symbols* } class BaseModem { <<Abstract>> +CommunicationWaveform waveform +EncoderManager encoder_manager +SymbolPredocding Precoding +Device transmitting_device* +Device receiving_device* } class TransmittingModem { +Device transmitting_device +None receiving_device +BitsSource bits_source +TransmitStreamCoding transmit_stream_coding #CommunicationTransmission _transmit() } class ReceivingModem { +None transmitting_device +Device receiving_device +BitsSink bits_sink +ReceiveStreamCoding receive_stream_coding #CommunicationReception _receive(Signal) } class SimplexLink class DuplexModem class CommunicationTransmission { +List[CommunicationTransmissionFrame] frames +int num_frames +bits numpy.ndarray +symbols Symbols } class CommunicationReception { +List[CommunicationReceptionFrame] frames +int num_frames +encoded_bits numpy.ndarray +bits numpy.ndarray +symbols Symbols +equalized_symbols Symbols } BaseModem --* CommunicationWaveform TransmittingModem --|> BaseModem TransmittingModem --> CommunicationTransmission : create ReceivingModem --|> BaseModem ReceivingModem --> CommunicationReception : create SimplexLink --|> TransmittingModem SimplexLink --|> ReceivingModem DuplexModem --|> TransmittingModem DuplexModem --|> ReceivingModem link CommunicationWaveform "modem.waveform.html" link BaseModem "modem.modem.BaseModem.html" link TransmittingModem "modem.modem.TransmittingModem.html" link ReceivingModem "modem.modem.ReceivingModem.html" link SimplexLink "modem.modem.SimplexLink.html" link DuplexModem "modem.modem.DuplexModem.html" link CommunicationTransmission "modem.modem.CommunicationTransmission.html" link CommunicationReception "modem.modem.CommunicationReception.html"

Modems implement a customizable signal processing pipeline for both transmitting and receiving communication devices, as well as a SimplexLink for unidirectional communication links and a DuplexModem for bidirectional communication links. They can be configured in terms of their bit generation and the forward error correction codings applied to the bits, the precoding applied to communication symbols, and, most importantly, the communication waveform used to transmit and receive commuication symbols. The waveform offers additional specific configuration options for synchronization, channel estimation and channel equalization. The following waveform types are currently supported:

Waveform

Synchronization

Channel Estimation

Channel Equalization

Root Raised Cosine

Yes

Yes

Yes

Raised Cosine

Yes

Yes

Yes

Rectangular

Yes

Yes

Yes

FMCW

Yes

Yes

Yes

OFDM

Yes

Yes

Yes

Chirp FSK

Yes

No

No

Out of the box, the communication package provides a number of evaluators to estimate common performance metrics of communication systems:

Performance Indicator

Performance Indicator

Bit Error Rate

Errors comparing two bit streams

Block Error Rate

Errors comparing two bit streams divided into blocks

Frame Error Rate

Errors comparing two bit streams divided into frames

Throughput

Rate of correct frames multiplied by the frame bit rate

Setting up a simulation evaluating the performance of a communication system requires adding modems to devices and configuring the respective waveform:

 1# Create a new simulation
 2simulation = Simulation()
 3
 4# Add two dedicated devices to the simulation
 5tx_device = simulation.new_device()
 6rx_device = simulation.new_device()
 7
 8# Specifiy the channel instance linking the two devices
 9simulation.set_channel(tx_device, rx_device, MultipathFading5GTDL())
10
11# Define a simplex communication link between the two devices
12link = SimplexLink(tx_device, rx_device)
13
14# Configure the waveform to be transmitted over the link
15link.waveform = RootRaisedCosineWaveform(symbol_rate=1e6, oversampling_factor=8,
16                                         num_preamble_symbols=10, num_data_symbols=100,
17                                         roll_off=.9)
18link.waveform.channel_estimation = SingleCarrierLeastSquaresChannelEstimation()
19link.waveform.channel_equalization = SingleCarrierZeroForcingChannelEqualization()

Afterwards, evaluators can be added freely and the simulation can be run:

1# Add a bit error rate evaluation to the simulation
2ber = BitErrorEvaluator(link, link)
3ber.evaluate().plot()
4
5# Iterate over the receiving device's SNR and estimate the respective bit error rates
6simulation.new_dimension('snr', dB(20, 16, 12, 8, 4, 0), rx_device)
7simulation.add_evaluator(ber)
8
9result = simulation.run()

In the case of hardware evaluations, the waveform and modem configuartions remain the same, however, the devices are replaced by hardware devices initialized from a hardware loop:

 1# Create a new hardware loop
 2hardware_scenario = PhysicalScenarioDummy(seed=42)
 3hardware_loop = HardwareLoop[PhysicalScenarioDummy, PhysicalDeviceDummy](hardware_scenario)
 4
 5# Add two dedicated devices to the hardware loop, this could be, for example, two USRPs
 6tx_device = hardware_loop.new_device(carrier_frequency=1e9)
 7rx_device = hardware_loop.new_device(carrier_frequency=1e9)
 8
 9# Specifiy the channel instance linking the two devices
10# Only available for PhysicalScenarioDummy, which is a simulation of hardware behaviour
11hardware_scenario.set_channel(tx_device, rx_device, MultipathFading5GTDL())
12
13# Define a simplex communication link between the two devices
14link = SimplexLink(tx_device, rx_device)
15
16# Configure the waveform to be transmitted over the link
17link.waveform = RootRaisedCosineWaveform(symbol_rate=1e6, oversampling_factor=8,
18                                         num_preamble_symbols=10, num_data_symbols=100,
19                                         roll_off=.9)
20link.waveform.channel_estimation = SingleCarrierLeastSquaresChannelEstimation()
21link.waveform.channel_equalization = SingleCarrierZeroForcingChannelEqualization()

Then, similarly to the simulation, evaluators can be added and the loop can be run. Additionally, visualizers plotting information generated by the communication system can be added to supervise the evaluation:

 1# Add a bit error rate evaluation to the hardware loop
 2ber = BitErrorEvaluator(link, link)
 3hardware_loop.add_evaluator(ber)
 4
 5# Add some runtime visualizations to the hardware loop
 6hardware_loop.add_plot(DeviceTransmissionPlot(tx_device, 'Tx Signal'))
 7hardware_loop.add_plot(DeviceReceptionPlot(rx_device, 'Rx Signal'))
 8hardware_loop.add_plot(ReceivedConstellationPlot(link, 'Rx Constellation'))
 9
10# Iterate over the receiving device's SNR and estimate the respective bit error rates
11hardware_loop.new_dimension('carrier_frequency', [1e9, 10e9, 100e9], tx_device, rx_device)
12hardware_loop.num_drops = 10
13
14hardware_loop.results_dir = hardware_loop.default_results_dir()
15hardware_loop.run()