summaryrefslogtreecommitdiff
path: root/pathloss/pathloss-func.py
blob: a9e9a65293cbc82486aaf8ae75a16963f88fc611 (plain)
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
103
104
105
106
107
108
109
110
111
112
# pathloss-func.py

# (C) 2016 by Harald Welte <laforge@gnumonks.org>
# All Rights Reserved
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

from Gnumeric import GnumericError, GnumericErrorVALUE
import Gnumeric
import string
import math

def lambda_by_mhz(freq_mhz):
    return 300/freq_mhz

def func_fsl(freq_mhz, dist_m):
    '@FUNCTION=PATHLOSS_FREESPACE\n'\
    '@SYNTAX=pathloss_freespace(freq_mhz, dist_m)\n'\
    '@DESCRIPTION=Compute Free Space Path Loss (in dB)\n'\
    '@SEEALSO=pathloss_egli,pathloss_hata\n'

    wavelen = lambda_by_mhz(freq_mhz)

    return -20 * math.log10(wavelen / (4*3.1416*dist_m))

def hata_ch(envi, freq_mhz, rx_ant_m):
    logfreq = math.log10(freq_mhz)
    ch = 0
    if envi == 'city_small' or envi == 'city_medium':
        ch = 0.8 + (1.1 * logfreq - 0.7)*rx_ant_m - (1.56 * logfreq)
    elif envi == 'city_large':
        if freq_mhz < 200:
            ch = 8.29 * math.pow(math.log10(1.54*rx_ant_m), 2) - 1.1
        elif freq_mhz > 200:
            ch = 3.2 * math.pow(math.log10(11.75*rx_ant_m), 2) - 4.97
    return ch

def hata_cm(envi, freq_mhz):
    logfreq = math.log10(freq_mhz)
    att = 0
    if freq_mhz <= 1500:
        if envi == 'open_area' or envi == 'rural':
            # https://en.wikipedia.org/wiki/Hata_model_for_open_areas
            att = -4.78 * math.pow(logfreq, 2) + 18.33 * logfreq - 40.94
        elif envi == 'suburban':
            # https://en.wikipedia.org/wiki/Hata_model_for_suburban_areas
            att = -2 * math.pow(logfreq/28, 2) - 5.4
    else:
        if envi == 'city_large':
            att = 3
        else:
            att = 0
    return att

def func_hata(envi, freq_mhz, dist_m, bts_ant_m, ms_ant_m):
    '@FUNCTION=PATHLOSS_HATA\n'\
    '@SYNTAX=pathloss_hata(environment, freq_mhz, dist_m, bts_ant_m, ms_ant_m)\n'\
    '@DESCRIPTION=Compute Path Loss (in dB) as per Hata Model\n'\
    '@SEEALSO=pathloss_freespace,pathloss_hata\n'

    # FIXME: valid for 150MHz - 2GHz, MS 1-10m, BS 30-200m, dist # 1-10km
    environs = ('open_area', 'rural', 'suburban', 'city_small',
                'city_medium', 'city_large')
    if not envi in environs:
        raise GnumericError,GnumericErrorVALUE

    # http://morse.colorado.edu/~tlen5510/text/classwebch3.html
    if freq_mhz <= 1500:
        c0 = 69.55
        cf = 26.16
    else:
        c0 = 46.3
        cf = 33.9

    # https://en.wikipedia.org/wiki/Hata_model_for_urban_areas
    hata = c0 + cf * math.log10(freq_mhz)
    hata -= 13.82 * math.log10(bts_ant_m)
    hata -= hata_ch(envi, freq_mhz, ms_ant_m)
    hata += (44.9 - 6.55 * math.log10(bts_ant_m)) * math.log10(dist_m/1000)
    # subtract correction for open_area / suburban
    hata += hata_cm(envi, freq_mhz)

    return hata

def func_egli(freq_mhz, dist_m, tx_ant_m, rx_ant_m):
    '@FUNCTION=PATHLOSS_EGLI\n'\
    '@SYNTAX=pathloss_egli(freq_mhz, dist_m, tx_ant_m, rx_ant_m)\n'\
    '@DESCRIPTION=Compute Path Loss (in dB) as per Egli Model\n'\
    '@SEEALSO=foo\n'

    # https://en.wikipedia.org/wiki/Egli_model
    att = -20 * math.log10(rx_ant_m*tx_ant_m / (dist_m*dist_m))
    att += 20 * math.log10(freq_mhz/40)

    return att

pathlossfunc_functions = {
    'pathloss_freespace': ('ff', 'freq_mhz, dist_m', func_fsl),
    'pathloss_egli': ('ffff', 'freq_mhz, dist_m, tx_ant_m, rx_ant_m', func_egli),
    'pathloss_hata': ('sffff', 'environ, freq_mhz, dist_m, bts_ant_m, ms_ant_m', func_hata),
}
personal git repositories of Harald Welte. Your mileage may vary