def setUp(self) -> None: self.carrier_frequency = 10e9 self.sampling_rate = 1e3 self.frequency = .25 * self.sampling_rate self.array_dimensions = (30, 30, 1) self.antenna_spacing = .5 * speed_of_light / self.carrier_frequency self.antennas = UniformArray(IdealAntenna(), self.antenna_spacing, self.array_dimensions) self.simulation = Simulation() self.device_a = self.simulation.scenario.new_device() self.device_b = self.simulation.scenario.new_device() self.device_a.antennas = self.antennas self.device_b.antennas = UniformArray(IdealAntenna(), self.antenna_spacing, [1, 1, 1]) self.device_a.position = np.array([0., 0., 0.]) self.device_b.position = np.array([0., 0., 100.]) self.device_a.orientation = np.array([0., 0., 0.]) self.device_b.orientation = np.array([0., 0., 0.]) self.device_a.carrier_frequency = self.carrier_frequency self.device_b.carrier_frequency = self.carrier_frequency self.channel = RuralMacrocellsLineOfSight() self.simulation.scenario.set_channel(self.device_a, self.device_b, self.channel) self.channel.set_seed(123456)
def setUp(self) -> None: self.antenna = Mock() self.antenna.polarization.return_value = np.array([2**-.5, 2**-.5]) self.carrier_frequency = 1e-9 self.wavelength = self.carrier_frequency / speed_of_light self.spacing = .5 * self.wavelength self.dimensions = (10, 9, 8) self.array = UniformArray(self.antenna, self.spacing, self.dimensions)
def test_spatial_properties(self) -> None: """Direction of arrival estimation should result in the correct angle estimation of impinging devices""" self.channel.num_clusters = 1 self.transmitter.antennas = UniformArray( IdealAntenna(), .5 * speed_of_light / self.carrier_frequency, (1, )) self.transmitter.orientation = np.zeros(3, dtype=float) self.receiver.position = np.zeros(3, dtype=float) self.receiver.antennas = UniformArray( IdealAntenna(), .5 * speed_of_light / self.carrier_frequency, (8, 8)) angle_candidates = [ (.25 * pi, 0), (.25 * pi, .25 * pi), (.25 * pi, .5 * pi), (.5 * pi, 0), (.5 * pi, .25 * pi), (.5 * pi, .5 * pi), ] range = 1e3 steering_codebook = np.empty((8**2, len(angle_candidates)), dtype=complex) for a, (zenith, azimuth) in enumerate(angle_candidates): steering_codebook[:, a] = self.receiver.antennas.spherical_response( self.carrier_frequency, azimuth, zenith) probing_signal = Signal(np.exp(2j * pi * .25 * np.arange(100)), sampling_rate=1e3, carrier_frequency=self.carrier_frequency) for a, (zenith, azimuth) in enumerate(angle_candidates): self.channel.set_seed(1) self.transmitter.position = range * np.array([ cos(azimuth) * sin(zenith), sin(azimuth) * sin(zenith), cos(zenith) ], dtype=float) received_signal, _, _ = self.channel.propagate(probing_signal) beamformer = np.linalg.norm( steering_codebook.T.conj() @ received_signal[0].samples, 2, axis=1, keepdims=False) self.assertEqual(a, np.argmax(beamformer))
def test_num_streams(self) -> None: """Number of streams property should return proper number of streams.""" self.device.antennas = UniformArray(IdealAntenna(), spacing=1., dimensions=(3, )) self.assertEqual(3, self.modem.num_streams) self.device.antennas = UniformArray(IdealAntenna(), spacing=1., dimensions=(2, )) self.assertEqual(2, self.modem.num_streams)
def setUp(self) -> None: self.rng = default_rng(42) self.random_node = Mock() self.random_node._rng = self.rng self.carrier_frequency = 1e9 self.antennas = UniformArray(IdealAntenna(), 1, (1, )) self.receiver = Mock() self.receiver.position = np.array([100., 0., 0.]) self.receiver.antennas = self.antennas self.receiver.orientation = np.array([0, 0, 0]) self.receiver.velocity = np.array([0., 0., 0.], dtype=float) self.receiver.carrier_frequency = self.carrier_frequency self.transmitter = Mock() self.transmitter.position = np.array([-100., 0., 0.]) self.transmitter.orientation = np.array([0, 0, 0]) self.transmitter.antennas = self.antennas self.transmitter.velocity = np.array([0., 0., 0.], dtype=float) self.transmitter.carrier_frequency = 1e9 self.channel = StreetCanyonNoLineOfSight(receiver=self.receiver, transmitter=self.transmitter) self.channel.random_mother = self.random_node
def setUp(self) -> None: self.rng = np.random.default_rng(42) self.operator = Mock() self.operator.device = Mock() self.operator.device.antennas = UniformArray(IdealAntenna(), .01, (5, 1, 1)) self.beamformer = ConventionalBeamformer(operator=self.operator)
def setUp(self) -> None: self.seed = 12345 self.num_clusters = 3 self.delay_spread_mean = -7.49 self.delay_spread_std = 0.55 self.delay_scaling = 3.8 self.carrier_frequency = 1e9 self.antennas = UniformArray( IdealAntenna(), .5 * speed_of_light / self.carrier_frequency, (2, 2)) self.receiver = Mock() self.receiver.num_antennas = self.antennas.num_antennas self.receiver.antennas = self.antennas self.receiver.position = np.array([100., 0., 0.]) self.receiver.orientation = np.array([0., 0., 0.]) self.receiver.antenna_positions = np.array([[100., 0., 0.]], dtype=float) self.receiver.velocity = np.zeros(3, dtype=float) self.receiver.carrier_frequency = self.carrier_frequency self.transmitter = Mock() self.transmitter.num_antennas = self.antennas.num_antennas self.transmitter.antennas = self.antennas self.transmitter.position = np.array([-100., 0., 0.]) self.transmitter.orientation = np.array([0., 0., pi]) self.transmitter.antenna_positions = np.array([[-100., 0., 0.]], dtype=float) self.transmitter.velocity = np.array([0., 0., 0.], dtype=float) self.transmitter.carrier_frequency = self.carrier_frequency self.channel = ClusterDelayLine( delay_spread_mean=self.delay_spread_mean, delay_spread_std=self.delay_spread_std, delay_scaling=self.delay_scaling, num_clusters=self.num_clusters, receiver=self.receiver, transmitter=self.transmitter, seed=1234)
def setUp(self) -> None: self.simulation = Simulation() self.device = self.simulation.scenario.new_device() self.device.carrier_frequency = 1e8 self.device.antennas = UniformArray(IdealAntenna(), .5 * speed_of_light / self.device.carrier_frequency, (3, 3)) self.waveform = FMCW() self.beamformer = ConventionalBeamformer() self.radar = Radar() self.radar.waveform = self.waveform self.radar.transmit_beamformer = self.beamformer self.radar.receive_beamformer = self.beamformer self.radar.device = self.device self.device.sampling_rate = self.radar.sampling_rate self.channel = RadarChannel(target_range=.5*self.waveform.max_range, radar_cross_section=1.) self.simulation.scenario.set_channel(self.device, self.device, self.channel)
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)
class TestUniformArray(TestCase): """Test the Uniform array model.""" def setUp(self) -> None: self.antenna = Mock() self.antenna.polarization.return_value = np.array([2**-.5, 2**-.5]) self.carrier_frequency = 1e-9 self.wavelength = self.carrier_frequency / speed_of_light self.spacing = .5 * self.wavelength self.dimensions = (10, 9, 8) self.array = UniformArray(self.antenna, self.spacing, self.dimensions) def test_spacing_setget(self) -> None: """Spacing property getter should return setter argument.""" spacing = 1.234 self.array.spacing = spacing self.assertEqual(spacing, self.array.spacing) def test_spacing_validation(self) -> None: """Spacing property setter should raise ValueError on invalid arguments.""" with self.assertRaises(ValueError): self.array.spacing = -1. with self.assertRaises(ValueError): self.array.spacing = 0. def test_num_antennas(self) -> None: """The number of antennas property should report the correct antenna count.""" self.assertEqual(720, self.array.num_antennas) def test_dimensions_setget(self) -> None: """The dimensions property getter should return the proper antenna count.""" self.array.dimensions = 1 self.assertCountEqual((1, 1, 1), self.array.dimensions) self.array.dimensions = (1, 2) self.assertCountEqual((1, 2, 1), self.array.dimensions) self.array.dimensions = (1, 2, 3) self.assertCountEqual((1, 2, 3), self.array.dimensions) def test_dimensions_validation(self) -> None: """The dimensions property setter should raise a ValueError on invalid arguments.""" with self.assertRaises(ValueError): self.array.dimensions = (1, 2, 3, 4) with self.assertRaises(ValueError): self.array.dimensions = (1, 2, -1) def test_topology(self) -> None: dimensions = 5 spacing = 1. expected_topology = np.zeros((dimensions, 3), dtype=float) expected_topology[:, 0] = spacing * np.arange(dimensions) self.array.dimensions = dimensions self.array.spacing = spacing assert_array_equal(expected_topology, self.array.topology) def test_polarization(self) -> None: """The polarization should compute the correct polarization array.""" polarization = self.array.polarization(0., 0.) self.assertCountEqual((10 * 9 * 8, 2), polarization.shape) self.assertTrue(np.any(polarization == 2**-.5)) def test_plot_topology(self) -> None: """Calling the plot routine should return a figure object.""" self.assertIsInstance(self.array.plot_topology(), plt.Figure) def test_cartesian_response(self) -> None: """Cartesian response function should generate a proper sensor array response vector.""" front_target_position = np.array([100, 0, 0]) back_target_position = -front_target_position front_array_response = self.array.cartesian_response( self.carrier_frequency, front_target_position) back_array_response = self.array.cartesian_response( self.carrier_frequency, back_target_position) assert_array_almost_equal(front_array_response, back_array_response) def test_cartesian_response_validation(self) -> None: """Cartesian response function should raise a ValueError on invalid arguments.""" with self.assertRaises(ValueError): _ = self.array.cartesian_response(self.carrier_frequency, np.array([1, 2, 3, 4])) def test_horizontal_response(self) -> None: """Horizontal response function should generate a proper sensor array response vector.""" elevation = 0 azimuth = .25 * pi front_array_response = self.array.horizontal_response( self.carrier_frequency, azimuth, elevation) back_array_response = self.array.horizontal_response( self.carrier_frequency, azimuth - pi, elevation - pi) assert_array_almost_equal(front_array_response, back_array_response) def test_spherical_response(self) -> None: """Spherical response function should generate a proper sensor array response vector.""" zenith = 0 azimuth = .25 * pi front_array_response = self.array.spherical_response( self.carrier_frequency, azimuth, zenith) back_array_response = self.array.spherical_response( self.carrier_frequency, azimuth - pi, zenith - pi) assert_array_almost_equal(front_array_response, back_array_response)