Source code for UMi_pathloss_model

# Henry Brice 2022-04-25

from math import log10,hypot
from numpy.linalg import norm

[docs]class UMi_streetcanyon_pathloss: ''' Urban microcell dual-slope pathloss model, from 3GPP standard 36.873, Table 7.2-1. The model is defined in 36873-c70.doc from https://portal.3gpp.org/desktopmodules/Specifications/SpecificationDetails.aspx?specificationId=2574. This code covers the cases 3D-UMi LOS and NLOS. 3D-UMi = three-dimensional urban street canyon model. LOS = line-of-sight. NLOS = non-line-of-sight. '''
[docs] def __init__(s,fc_GHz=3.5,h_UT=2.0,h_BS=10.0,LOS=True): ''' Initialize a pathloss model instance. Parameters ---------- fc_GHz : float Centre frequency in GigaHertz (default 3.5). h_UT : float Height of User Terminal (=UE) in metres (default 2). h_BS : float Height of Base Station in metres (default 10 for UMi). LOS: bool Whether line-of-sight model is to be used (default True). ''' s.fc=fc_GHz # GHz s.log10fc=log10(s.fc) s.h_UT=h_UT s.h_BS=h_BS s.LOS=LOS s.c=3e8 # Adjustment for effective antenna height, 1.0 in LOS for UMa. # Same for UMi, assuming the effective antenna environment height is 1m. s.h_E=1.0 # Note 1. This is the same for UMi and UMa. s.dBP=4.0*(s.h_BS-s.h_E)*(s.h_UT-s.h_E)*s.fc*1e9/s.c # This is used in the LOS models for both UMI and UMa... # next line is a better way s.a=9.0*log10(s.dBP**2+(s.h_BS-s.h_UT)**2) s.a=18.0*log10(hypot(s.dBP,s.h_BS-s.h_UT)) # pre-compute constants to speed up calls... # LOS Model same for UMi and NLOS... s.const_close=28.0+20.0*s.log10fc s.const_far =28.0+20.0*s.log10fc-s.a
[docs] def __call__(s,xyz_cell,xyz_UE): ''' Return the pathloss between 3-dimensional positions xyz_cell and xyz_UE (in metres). Note that the distances, building heights, etc. are not checked to ensure that this pathloss model is actually applicable. ''' # TODO: could we usefully vectorize this, so that xyz_cell,xyz_UE have shape (n,3) to compute n pathlosses at once? d3D_m=norm(xyz_cell-xyz_UE) if d3D_m<s.dBP: PL3D_UMi_LOS=s.const_close+22.0*log10(d3D_m) # Same as for UMa else: PL3D_UMi_LOS=s.const_far +40.0*log10(d3D_m) if s.LOS: return PL3D_UMi_LOS PL3D_UMi_NLOS=36.7*log10(d3D_m)+22.7+26*log10(s.fc)-0.3*(s.h_UT-1.5) return max(PL3D_UMi_NLOS,PL3D_UMi_LOS)
[docs]def plot(): ' Plot the pathloss model predictions, as a self-test. ' import numpy as np import matplotlib.pyplot as plt from fig_timestamp import fig_timestamp fig=plt.figure(figsize=(8,6)) ax=fig.add_subplot() ax.grid(color='gray',alpha=0.7,lw=0.5) d=np.linspace(1,5000,100) PL=UMi_streetcanyon_pathloss(fc_GHz=1.8,h_UT=1.5,h_BS=17.5,LOS=False) NLOS=np.array([PL(0,di) for di in d]) ax.plot(d,NLOS,lw=2,label='NLOS ($\sigma=4$)') ax.fill_between(d,NLOS-4.0,NLOS+4.0,alpha=0.2) # sigma_{SF}=4 for NLOS case PL=UMi_streetcanyon_pathloss(fc_GHz=1.8,h_UT=1.5,h_BS=17.5,LOS=True) LOS=np.array([PL(0,di) for di in d]) ax.plot(d,LOS,lw=2,label='LOS ($\sigma=3$)') # or semilogx ax.fill_between(d,LOS-3.0,LOS+3.0,alpha=0.2) # sigma_{SF}=3 for LOS case ax.set_xlabel('distance (metres)') ax.set_ylabel('pathloss (dB)') ax.set_xlim(np.min(d),np.max(d)) ax.set_ylim(40) ax.legend() ax.set_title('3GPP UMi street-canyon pathloss models') fig.tight_layout() fig_timestamp(fig,rotation=0,fontsize=6,author='Keith Briggs') fnbase='img/UMi_pathloss_model_01' fig.savefig(f'{fnbase}.png') print(f'eog {fnbase}.png &') fig.savefig(f'{fnbase}.pdf') print(f'evince {fnbase}.pdf &')
if __name__=='__main__': # simple self-test plot()