uma_pathloss.py 2.9 KB
Newer Older
 Lukas Eller's avatar
Lukas Eller committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
import numpy as np
from scipy.constants import speed_of_light


class AntennaPattern:
    def __init__(self, A_m=30, theta_3=65):
        self._A_m = A_m
        self._theta_3 = theta_3

    def __call__(self, theta):
        pattern = 12 * (theta / self._theta_3) ** 2
        return -np.minimum(pattern, self._A_m)


class PathlossModel:
    @staticmethod
    def getLOSpathloss(d3d, d2d, dbp, fc, h_b, h_t):
        PL1 = 28 + 22 * np.log10(d3d) + 20 * np.log10(fc)
        PL2 = (
            28
            + 40 * np.log10(d3d)
            + 20 * np.log10(fc)
            - 9 * np.log10(dbp ** 2 + (h_b - h_t) ** 2)
        )
        PL = np.zeros((d3d.shape))
        PL = PL2  # Default pathloss
        PL[(np.greater_equal(d2d, 10) & np.less_equal(d2d, dbp))] = PL1[
            (np.greater_equal(d2d, 10) & np.less_equal(d2d, dbp))
        ]  # Overwrite if distance is greater than 10 meters or smaller than dbp

        return PL

    @staticmethod
    def getNLOSpathloss(
        street_width, average_building_height, bs_height, ue_height, d3d, f_ghz
    ):
        pathlossdB = (
            161.04
            - 7.1 * np.log10(street_width)
            + 7.5 * np.log10(average_building_height)
            - (24.37 - 3.7 * (average_building_height / bs_height) ** 2)
            * np.log10(bs_height)
            + (43.42 - 3.1 * np.log10(bs_height)) * (np.log10(d3d) - 3)
            + 20 * np.log10(f_ghz)
            - (3.2 * (np.log10(17.625)) ** 2 - 4.97)
            - 0.6 * (ue_height - 1.5)
        )

        return pathlossdB

    @staticmethod
    def pathlos_36873(h_b, h_ue, f_ghz, street_w, building_h, d2d):
        h_e = h_b - h_ue
        d3d = np.sqrt(d2d ** 2 + h_e ** 2)

        dbp = 4 * h_b * h_ue * f_ghz * 10e8 / speed_of_light

        nlos_pathloss = PathlossModel.getNLOSpathloss(
            street_w, building_h, h_b, h_ue, d3d, f_ghz
        )

        los_pathloss = PathlossModel.getLOSpathloss(d3d, d2d, dbp, f_ghz, h_b, h_ue)

        return np.maximum(nlos_pathloss, los_pathloss)

    @staticmethod
    def pathlos_36873(h_b, h_ue, f_ghz, street_w, building_h, d2d, use_los=False):

        h_e = h_b - h_ue
        d3d = np.sqrt(d2d ** 2 + h_e ** 2)

        dbp = 4 * h_b * h_ue * f_ghz * 10e8 / speed_of_light

        nlos_pathloss = PathlossModel.getNLOSpathloss(
            street_w, building_h, h_b, h_ue, d3d, f_ghz
        )

        los_pathloss = PathlossModel.getLOSpathloss(d3d, d2d, dbp, f_ghz, h_b, h_ue)

        if use_los:
            return los_pathloss

        return np.maximum(nlos_pathloss, los_pathloss)

    def __call__(
        self,
        distance_2D,
        h_bs,
        use_los=False,
        street_width=10,
        building_height=25,
        frequency=None,
    ):
        return self.pathlos_36873(
            h_bs,
            2,
            frequency,
            street_width,
            building_height,
            distance_2D,
            use_los=use_los,
        )