class TestLinks(TestCase): def setUp(self) -> None: # Configure a 2x2 link scenario antennas = UniformArray(IdealAntenna(), 5e-3, [2, 1, 1]) self.tx_device = SimulatedDevice(antennas=antennas) self.rx_device = SimulatedDevice(antennas=antennas) scenario = Scenario() scenario.add_device(self.tx_device) scenario.add_device(self.rx_device) # Define a transmit operation on the first device self.tx_operator = Modem() self.tx_operator.precoding[0] = SpatialMultiplexing() self.tx_operator.device = self.tx_device # Define a receive operation on the second device self.rx_operator = Modem() self.rx_operator.precoding[0] = SpatialMultiplexing() self.rx_operator.device = self.rx_device self.rx_operator.reference_transmitter = self.tx_operator self.ber = BitErrorEvaluator(self.tx_operator, self.rx_operator) def __propagate(self, channel: Channel) -> None: """Helper function to propagate a signal from transmitter to receiver. Args: channel (Channel): The channel over which to propagate the signal from transmitter to receiver. """ _ = self.tx_operator.transmit() tx_signals = self.tx_device.transmit() rx_signals, _, channel_state = channel.propagate(tx_signals) self.rx_device.receive( np.array([[rx_signals, channel_state]], dtype=object)) _ = self.rx_operator.receive() def test_ideal_channel_psk_qam(self) -> None: """Verify a valid MIMO link over an ideal channel with PSK/QAM modulation""" self.tx_operator.waveform_generator = WaveformGeneratorPskQam( oversampling_factor=8) self.rx_operator.waveform_generator = WaveformGeneratorPskQam( oversampling_factor=8) self.__propagate(Channel(self.tx_device, self.rx_device)) self.assertEqual(0, self.ber.evaluate().to_scalar())
def __init__(self, max_range: float) -> None: """ Args: max_range (float): Maximally detectable range in m. """ self.__sampling_rate = None self.max_range = max_range Modem.__init__(self) Radar.__init__(self)
def receive(self) -> Tuple[Signal, Symbols, np.ndarray, RadarCube]: # There must be a recent transmission being cached in order to correlate if self.__transmission is None: raise RuntimeError( "Receiving from a matched filter joint must be preceeded by a transmission" ) # Receive information _, symbols, bits = Modem.receive(self) # Re-sample communication waveform signal = self._receiver.signal.resample(self.sampling_rate) resolution = self.range_resolution num_propagated_samples = int(2 * self.max_range / resolution) # Append additional samples if the signal is too short required_num_received_samples = self.__transmission.num_samples + num_propagated_samples if signal.num_samples < required_num_received_samples: signal.append_samples( Signal( np.zeros( (1, required_num_received_samples - signal.num_samples), dtype=complex), self.sampling_rate, signal.carrier_frequency)) # Remove possible overhead samples if signal is too long # resampled_signal.samples = resampled_signal.samples[:, :num_samples] correlation = abs( correlate( signal.samples, self.__transmission.samples, mode='valid', method='fft').flatten()) / self.__transmission.num_samples lags = correlation_lags(signal.num_samples, self.__transmission.num_samples, mode='valid') # Append zeros for correct depth estimation #num_appended_zeros = max(0, num_samples - resampled_signal.num_samples) #correlation = np.append(correlation, np.zeros(num_appended_zeros)) angle_bins = np.array([0.]) velocity_bins = np.array([0.]) range_bins = .5 * lags * resolution cube_data = np.array([[correlation]], dtype=float) cube = RadarCube(cube_data, angle_bins, velocity_bins, range_bins) return signal, symbols, bits, cube
def setUp(self) -> None: # Configure a 2x2 link scenario antennas = UniformArray(IdealAntenna(), 5e-3, [2, 1, 1]) self.tx_device = SimulatedDevice(antennas=antennas) self.rx_device = SimulatedDevice(antennas=antennas) scenario = Scenario() scenario.add_device(self.tx_device) scenario.add_device(self.rx_device) # Define a transmit operation on the first device self.tx_operator = Modem() self.tx_operator.precoding[0] = SpatialMultiplexing() self.tx_operator.device = self.tx_device # Define a receive operation on the second device self.rx_operator = Modem() self.rx_operator.precoding[0] = SpatialMultiplexing() self.rx_operator.device = self.rx_device self.rx_operator.reference_transmitter = self.tx_operator self.ber = BitErrorEvaluator(self.tx_operator, self.rx_operator)
def modem(self, handle: Modem) -> None: """Modify the modem this generator is attached to. Args: handle (Modem): Handle to a modem. Raises: RuntimeError: If the `modem` does not reference this generator. """ if handle.waveform_generator is not self: handle.waveform_generator = self self.__modem = handle
import matplotlib.pyplot as plt from hermespy.simulation import SimulatedDevice from hermespy.modem import Modem, WaveformGeneratorPskQam operator = Modem() operator.waveform_generator = WaveformGeneratorPskQam(oversampling_factor=8) operator.device = SimulatedDevice() signal, _, _ = operator.transmit() signal.plot() plt.show()
waveform_generator.num_preamble_symbols = 128 waveform_generator.num_data_symbols = 1024 waveform_generator.modulation_order = 4 waveform_generator.synchronization = PskQamCorrelationSynchronization() waveform_generator.channel_estimation = PskQamLeastSquaresChannelEstimation() waveform_generator.channel_equalization = PskQamZeroForcingChannelEqualization() device.sampling_rate = waveform_generator.sampling_rate source = StreamBitsSource(os.path.join(os.path.dirname(__file__), '../resources/leena.raw')) leena_num_bits = 512 * 512 * 8 image_buffer = np.zeros((512, 512), dtype=np.uint8) image_buffer[0, 0] = 255 # Add a modem at the simulated device modem = Modem() modem.device = device modem.bits_source = source modem.waveform_generator = waveform_generator # Compute number of required frames bits_per_frame = modem.num_data_bits_per_frame byte_per_frame = int(bits_per_frame / 8) num_frames = int(leena_num_bits / bits_per_frame) plt.ion() fig, axes = plt.subplots() image = axes.imshow(image_buffer) for f in range(num_frames):
import matplotlib.pyplot as plt # Import required HermesPy modules from hermespy.channel import Channel from hermespy.simulation import Simulation from hermespy.modem import Modem, WaveformGeneratorPskQam, BitErrorEvaluator # Create a new HermesPy simulation scenario simulation = Simulation() # Create device device = simulation.scenario.new_device() # Configure device operator operator = Modem() operator.waveform_generator = WaveformGeneratorPskQam(oversampling_factor=8) operator.device = device # Configure Monte Carlo simulation simulation.add_evaluator(BitErrorEvaluator(operator, operator)) simulation.new_dimension('snr', [10, 4, 2, 1, 0.5]) simulation.num_samples = 1000 # Launch simulation campaign result = simulation.run() # Visualize results result.plot() plt.show()
import matplotlib.pyplot as plt # Import required HermesPy modules from hermespy.channel import Channel from hermespy.simulation import SimulatedDevice from hermespy.modem import Modem, WaveformGeneratorPskQam, BitErrorEvaluator from hermespy.simulation.analog_digital_converter import AnalogDigitalConverter, GainControlType # Create two simulated devices acting as source and sink tx_device = SimulatedDevice() rx_device = SimulatedDevice() rx_device.analog_digital_converter = AnalogDigitalConverter(num_quantization_bits=10) # Define a transmit operation on the first device tx_operator = Modem() tx_operator.waveform_generator = WaveformGeneratorPskQam(oversampling_factor=8) tx_operator.device = tx_device # Define a receive operation on the second device rx_operator = Modem() rx_operator.waveform_generator = WaveformGeneratorPskQam(oversampling_factor=8) rx_operator.device = rx_device # Simulate a channel between the two devices channel = Channel(tx_operator.device, rx_operator.device) # Simulate the signal transmission over the channel tx_signal, _, tx_bits = tx_operator.transmit() rx_signal, _, channel_state = channel.propagate(tx_signal) rx_device.receive(rx_signal) _, rx_symbols, rx_bits = rx_operator.receive()