コード例 #1
0
    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)
コード例 #2
0
    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)
コード例 #3
0
    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))
コード例 #4
0
    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)
コード例 #5
0
    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
コード例 #6
0
    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)
コード例 #7
0
    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)
コード例 #8
0
    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)
コード例 #9
0
    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)
コード例 #10
0
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)