Commit 25072c50 authored by JRock007's avatar JRock007
Browse files

Remove Python code attempt for channel generation

parent c7ea443a
import numpy as np
from channelgain_Winner import channelgain_Winner
from generateChannel import generateChannel
# Parameters you can change
N_user_General = 2 # Number of users
N_canaux_General = 4 # Number of channels
distances_General = np.array([200, 400]) # Distance between each user and the base station
# Parameters you can change sometimes
Wmodel = "B1"
CModel = "ETU" # "extended typical urban"
Antenna_gain = 10 # Antenna gain in dB
Noise_fig = 2 # Noise figure
Nth = -121.44 # Thermal noise
# Parameters you do no have to change
frequency = 2 * 10**9
Nb_sub = 12 # Number of subcarriers per ressource block
Ts = 1 / 15000 # Time symbol in LTE
fs = Nb_sub * N_canaux_General / Ts # Sampling frequency in Hz, here case of LTE with 2048 subC (only 1200 subcarriers are used)
duration = 2 * Ts # Duration of the simulation in s
fd = 0 # Dopler frequency
# Bandwidth of one channel
B_c = Nb_sub / Ts
C_k_General = 10**6 * np.array([0.5, 0.6, 0.7, 0.8, 0.9, 1, 1.1, 1.2, 1.3, 1.4, 1.5])
N_C_k_k = len(C_k_General)
N_user = N_user_General
N_canaux = N_canaux_General
distances = distances_General[:N_user]
################
# COMPUTATIONS #
################
# Computation of the channel gains
PL = channelgain_Winner(Wmodel, distances_General, frequency)
g_moy = pow(10, (Antenna_gain - PL) / 10)
# We now compute the channel gain per user per subcarrier
H_u = np.zeros((N_user_General, int(fs * Ts)))
for j in range(N_user_General):
hMatrix, H = generateChannel(CModel, fs, duration, fd, Ts)
H_norm = abs(H[0, :])
H_u[j, :] = g_moy[j] * H_norm
# The channel coefficient g is the average of the channel coefficients in
# every channel (12 subcarriers)
g = np.zeros((len(H_u), int(len(H_u[1]) / Nb_sub)))
for j in range(N_canaux_General):
for k in range(N_user_General):
H_tmp = H_u[k, (j - 1) * Nb_sub + 1:j * Nb_sub]
g[k, j] = H_tmp.prod() ** (1 / Nb_sub)
# Noise
N_dB = Nth + Noise_fig + 10 * np.log10(B_c)
N = pow(10, N_dB / 10)
print(g)
print(N)
import numpy as np
def channelgain_Winner(model, distance, frequency):
"""
This function computes the channel gain (dB) for one user with
the winner 2 channel model and the B1 scenario
Available channel models:
- B1 : Urban Micro-cell
- B2 : Bad Urban Micro-cell
- B3 : Indoor hotspot
- B5a : Stationary feeder [B5a, B5c, B5f]
- C1 : Sub-urban Macro-cell
- C2 : Urban Macro-cell
- C3 : Bad urban macro-cell
- D1 : Rural macro-cell
Inputs:
model : Path loss model, can be 'B1', 'B2','B3','B5a', 'B5c', 'B5f', 'C1','C2','C3' and 'D1'
distance : Distances between the base station and the mobiles (meters)
frequency : Carrier frequency(Hz)
Outputs:
PL: pathloss in dB
Based Winner II Channel Models, Winner II D1.1.2 V1.2
https://cept.org/files/8339/winner2%20-%20final%20report.pdf
Inspired by the official matlab code of the Winner II project:
http://projects.celtic-initiative.org/winner+/phase_2_model.html
Ported to Python by:
Author: Jean-Romain Garnier
Email: jean-romain.garnier@supelec.fr
Website: jean-romain.com
Original Matlab code by:
Author: Rémi BONNEFOI
SCEE Research Team - CentraleSupélec - Campus de Rennes
Avenue de la Boulaie 35576 Rennes CEDEX CS 47601 FRANCE
Email: remi.bonnefoi@centralesupelec.fr
Website: remibonnefoi.wordpress.com
Sep. 2015; Last revision: 10/04/2019
"""
# Parameters
c = 3 * 10**8
# Make sure distance is an numpy array
distance = np.array(distance)
# Computation of the LOS probability
if model == "B1":
hbs = 10
hms = 1.5
streetwidth = 20
# Probability of LOS
Plos = np.minimum(18 / distance, 1) * (1 - np.exp(-distance / 36)) + np.exp(-distance / 36)
prob = np.random.uniform(low=0, high=1, size=len(distance))
# Choose between LOS and NLOS
LOS = prob < Plos
elif model == "B2":
hbs = 10
hms = 1.5
streetwidth = 20
LOS = [False] * len(distance)
elif model == "B3":
Plos = np.exp(-(distance - 10) / 45)
prob = np.random.uniform(low=0, high=1, size=len(distance))
LOS = (prob < Plos) | (distance < 10)
elif model in ["B5a", "B5f", "B5c"]:
hbs = 10
hms = 5
streetwidth = 20
LOS = [True] * len(distance)
elif model == "C1":
hbs = 25
hms = 1.5
Plos = np.exp(-(distance / 200))
prob = np.random.uniform(low=0, high=1, size=len(distance))
LOS = prob < Plos
elif model == "C2":
hbs = 25
hms = 1.5
# probability of LOS
Plos = np.minimum(18 / distance, 1) * (1 - np.exp(-distance / 63)) + np.exp(-distance / 63)
prob = np.random.uniform(low=0, high=1, size=len(distance))
# choose between LOS and NLOS
LOS = prob < Plos
elif model == "C3":
hbs = 25
hms = 1.5
# Probability of LOS
LOS = [False] * len(distance)
elif model == "D1":
hbs = 32
hms = 1.5
# Probability of LOS:
Plos = np.exp(-(distance / 1000))
prob = np.random.uniform(low=0, high=1, size=len(distance))
# Choose between LOS and NLOS
LOS = prob < Plos
else:
print("Channel model unknown or not implemented")
return None
# Computation of the pathloss
if model in ["B1", "B2", "B5c"]:
d1 = np.ones(len(distance))
while np.all(d1 < 10):
d2 = distance * np.random.rand(len(distance)) + 10 + streetwidth / 2
d1 = np.sqrt(np.abs(distance**2 - d2**2))
d1[LOS] = distance[LOS] # Replace values in d1 where LOS is True
# Compute path loss
# LOS case
d_bp = 4 * (hbs - 1) * (hms - 1) * frequency / c
supd_bp = d1 > d_bp
PLlos = 22.7 * np.log10(d1) + 41 + 20 * np.log10(frequency / (5 * 10**9))
PLlos[supd_bp] = 40 * np.log10(d1[supd_bp]) + 9.45 - 17.3 * np.log10(hbs - 1) - 17.3 * np.log10(hms - 1) + 2.7 * np.log10(frequency / (5 * 10**9))
n1 = np.maximum(2.8 - 0.0024 * d1, 1.84)
n2 = np.maximum(2.8 - 0.0024 * d2, 1.84)
PL = np.zeros(len(distance))
# Shadowing
Sh = np.random.normal(loc=0, scale=4, size=len(distance))
Sh[LOS] = np.random.normal(loc=0, scale=3, size=len(distance[LOS]))
for i in range(len(distance)):
if LOS[i]:
PL[i] = PLlos[i]
else:
# NLOS case
if d2[i] < d_bp:
PLlos2 = 22.7 * np.log10(d2[i]) + 41 + 20 * np.log10(frequency / (5 * 10**9))
else:
PLlos2 = 40 * np.log10(d2[i]) + 9.45 - 17.3 * np.log10(hbs - 1) - 17.3 * np.log10(hms - 1) + 2.7 * np.log10(frequency / (5 * 10**9))
PL1 = PLlos[i] + 20 - 12.5 * n1[i] + 10 * n1[i] * np.log10(d2[i]) + 3 * np.log10(frequency / (5 * 10**9))
PL2 = PLlos2 + 20 - 12.5 * n2[i] + 10 * n2[i] * np.log10(d1[i]) + 3 * np.log10(frequency / (5 * 10**9))
PL[i] = min(PL1, PL2)
elif model == "B3":
A_LOS = 13.9
B_LOS = 64.4
C_LOS = 20
A_NLOS = 37.8
B_NLOS = 36.5
C_NLOS = 23
PL = A_NLOS * np.log10(distance) + B_NLOS + C_NLOS * np.log10(frequency / (5 * 10**9))
PL[LOS] = A_LOS * np.log10(distance[LOS]) + B_LOS + C_LOS * np.log10(frequency / (5 * 10**9))
Sh = np.random.normal(loc=0, scale=4, size=len(distance))
Sh[LOS] = np.random.normal(loc=0, scale=3, size=len(distance[LOS]))
elif model == "B5a":
A_LOS = 23.5
B_LOS = 42.5
C_LOS = 20
PL = A_LOS * np.log10(distance) + B_LOS + C_LOS * np.log10(frequency / (5 * 10**9))
Sh = np.random.normal(loc=0, scale=4, size=len(distance))
elif model == "B5f":
A_NLOS = 23.5
B_NLOS = 42.5
C_NLOS = 20
PL = A_NLOS * np.log10(distance) + B_NLOS + C_NLOS * np.log10(frequency / (5 * 10**9))
Sh = np.random.normal(loc=0, scale=8, size=len(distance))
elif model == "C1":
d_bp = 4 * hbs * hms * frequency / c
supd_bp = distance > d_bp
# Pathloss
PL = (44.9 - 6.55 * np.log10(hbs)) * np.log10(distance) + 31.46 + 5.83 * np.log10(hbs) + 23 * np.log10(frequency / (5 * 10**9))
PL[LOS] = 23.8 * np.log10(distance[LOS]) + 41.2 + 20 * np.log10(frequency / (5 * 10**9))
PL[LOS & supd_bp] = 40 * np.log10(distance[LOS & supd_bp]) + 11.65 - 16.2 * np.log10(hbs * hms) + 3.8 * np.log10(frequency / (5 * 10**9))
Sh = np.random.normal(loc=0, scale=8, size=len(distance))
Sh[LOS] = np.random.normal(loc=0, scale=4, size=len(distance[LOS]))
Sh[LOS & supd_bp] = np.random.normal(loc=0, scale=6, size=len(distance[LOS & supd_bp]))
elif model in ["C2", "C3"]:
d_bp = 4 * (hbs - 1) * (hms - 1) * frequency / c
supd_bp = distance > d_bp
# Pathloss
PL = (44.9 - 6.55 * np.log10(hbs)) * np.log10(distance) + 34.46 + 5.83 * np.log10(hbs) + 23 * np.log10(frequency / (5 * 10**9))
PL[LOS] = 26 * np.log10(distance[LOS]) + 39 + 20 * np.log10(frequency / (5 * 10**9))
PL[LOS & supd_bp] = 40 * np.log10(distance[LOS & supd_bp]) + 13.47 - 14 * np.log10(hbs * hms) + 6 * np.log10(frequency / (5 * 10**9))
Sh = np.random.normal(loc=0, scale=8, size=len(distance))
Sh[LOS] = np.random.normal(loc=0, scale=4, size=len(distance[LOS]))
Sh[LOS & supd_bp] = np.random.normal(loc=0, scale=6, size=len(distance[LOS & supd_bp]))
elif model == "D1":
d_bp = 4 * hbs * hms * frequency / c
supd_bp = distance > d_bp
# Pathloss
PL = 25.1 * np.log10(distance) + 55.4 - 0.13 * np.log10(hbs - 25) * np.log10(distance / 100) + 21.3 * np.log10(frequency / (5 * 10**9))
PL[LOS] = 21.5 * np.log10(distance[LOS]) + 44.2 + 20 * np.log10(frequency / (5 * 10**9))
PL[LOS & supd_bp] = 40 * np.log10(distance[LOS & supd_bp]) + 10.5 - 18.5 * np.log10(hbs * hms) + 1.5 * np.log10(frequency / (5 * 10**9))
Sh = np.random.normal(loc=0, scale=8, size=len(distance))
Sh[LOS] = np.random.normal(loc=0, scale=4, size=len(distance[LOS]))
Sh[LOS & supd_bp] = np.random.normal(loc=0, scale=6, size=len(distance[LOS & supd_bp]))
else:
print("Channel model unknown or not implemented")
return None
return PL + Sh
import numpy as np
def generateChannel(model, fs, timeSpan, fd, Ts):
"""
Generate Random Channel Impulse Response Based on tapped
delay line models, taking into account time variation caused by Doppler
effect.
Available channel models and their abbreviations
- Pedestrian A & B ["PedA", "PedB"]
- Vehicular A & B ["VehA", "VehB"]
- Hilly Terrain ["HT"]
- Typical Urban ["TU"]
- Rural Area ["RA"]
- Ext Ped.A, Veh.A, TU ["EPA", "EVA", "ETU"]
- Indoor Office A & B ["IOA", "IOB"]
Inputs :
model : Channel model abbriviation from list above
fs : Sampling frequency (Hz)
timeSpan : Time length of the channel response to generate (s)
fd : Doppler frequency (Hz)
Ts : Time-Symbol (s) - used to know how many coeffs to compute
Outputs :
hMatrix : Matrix of channel time responses. Each line corresponds
to the reponse on one Ts. If Ts = timespan, hMatrix has
only one line
H : Matrix of channel frequency responses. Each line
corresponds to the frequency response of the channel
during one Ts
Based on Dr. Vincent Savaux's PhD. Thesis, section 1.4, "Simulation of
the transmission channel":
"Vincent Savaux. Contribution a l’estimation de canal multi-trajets
dans un contexte de modulation OFDM. Other. Supelec, 2013. French."
See at : https://goo.gl/b23Tob
Ported to Python by:
Author: Jean-Romain Garnier
Email: jean-romain.garnier@supelec.fr
Website: jean-romain.com
Original Matlab code by:
Author: Quentin BODINIER
SCEE Research Team - CentraleSupélec - Campus de Rennes
Avenue de la Boulaie 35576 Rennes CEDEX CS 47601 FRANCE
Email: quentin.bodinier@supelec.fr
Website: quentinbodinier.wordpress.com
Sep. 2015; Last revision: 10/04/2019
"""
# Doppler models = Jakes (0) or Flat (1)
if model == "PedA":
delays = 10**-9 * np.array([0, 110, 190, 410])
powers = 10**(1 / 10 * np.array([0, -9.7, -19.2, -22.8]))
doppler = [0] * 4
elif model == "PedB":
delays = 10**-9 * np.array([0, 200, 800, 1200, 2300, 3700])
powers = 10**(1 / 10 * np.array([0, -0.9, -4.9, -8.0, -7.8, -23.9]))
doppler = [0] * 6
elif model == "VehA":
delays = 10**-9 * np.array([0, 310, 710, 1090, 1730, 2510])
powers = 10**(1 / 10 * np.array([0, -1, -9, -10, -15, -20]))
doppler = [0] * 6
elif model == "EVA":
delays = 10**-9 * np.array([0, 30, 150, 310, 370, 710, 1090, 1730, 2510])
powers = 10**(1 / 10 * np.array([0, -1.5, -1.4, -3.6, -0.6, -9.1, -7.0, -12.0, -16.9]))
doppler = [0] * 9
elif model == "EPA":
delays = 10**-9 * np.array([0, 30, 70, 90, 110, 190, 410])
powers = 10**(1 / 10 * np.array([0, -1, -2, -3, -8, -17.2, -20.8]))
doppler = [0] * 7
elif model == "TU":
delays = 10**-9 * np.array([0, 50, 120, 200, 230, 500, 1600, 2300, 5000])
powers = 10**(1 / 10 * np.array([-1, -1, -1, 0, 0, 0, -3, -5, -7]))
doppler = [0] * 9
elif model == "VehB":
delays = 10**-9 * np.array([0, 300, 8900, 12900, 17100, 20000])
powers = 10**(1 / 10 * np.array([-2.5, 0, -12.8, -10.0, -25.2, -16]))
doppler = [0] * 6
elif model == "HT":
delays = 10**-9 * np.array([0, 356, 441, 528, 546, 609, 625, 842, 916, 941, 15000, 16172, 16492, 16876, 16882, 16978, 17615, 17827, 17849, 18016])
powers = 10**(1 / 10 * np.array([-3.6, -8.9, -10.2, -11.5, -11.8, -12.7, -13.0, -16.2, -17.3, -17.7, -17.6, -22.7, -24.1, -25.8, -25.8, -26.2, -29.0, -29.9, -30.0, -30.7]))
doppler = [0] * 20
elif model == "ETU":
delays = 10**-9 * np.array([0, 217, 512, 514, 517, 674, 882, 1230, 1287, 1311, 1349, 1533, 1535, 1622, 1818, 1836, 1884, 1943, 2048, 2140])
powers = 10**(1 / 10 * np.array([-5.7, -7.6, -10.1, -10.2, -10.2, -11.5, -13.4, -16.3, -16.9, -17.1, -17.4, -19.0, -19.0, -19.8, -21.5, -21.6, -22.1, -22.6, -23.5, -24.30]))
doppler = [0] * 20
elif model == "RA":
delays = 10**-9 * np.array([0, 42, 101, 129, 149, 245, 312, 410, 469, 528])
powers = 10**(1 / 10 * np.array([-5.2, -6.4, -8.4, -9.3, -10, -13.1, -15.3, -18.5, -20.4, -22.4]))
doppler = [0] * 10
elif model == "IOA":
delays = 10**-9 * np.array([0, 50, 110, 170, 290, 310])
powers = 10**(1 / 10 * np.array([0, -3, -10, -18, -26, -32]))
doppler = [1] * 6
elif model == "IOB":
delays = 10**-9 * np.array([0, 100, 200, 300, 500, 700])
powers = 10**(1 / 10 * np.array([0, -3.6, -7.2, -10.8, -18.0, -25.2]))
doppler = [1] * 6
else:
print("Channel model unknown")
return None
# Time vector definition
t = np.arange(0, timeSpan + 1 / fs, 1 / fs)
# Return error if timeSpan is too small
if max(t) < Ts:
print("Provided timeSpan should be higher than Ts")
return None
# Number of symbols that the signal will spread
Nsymbols = int(np.floor(timeSpan / Ts))
# Frequency vector
f = np.arange(-1 / (2 * Ts), 1 / (2 * Ts), 1 / (Ts * Nsymbols))
# Random coeffs generation
coeffMatrix = 1 / np.sqrt(2) * (np.random.randn(Nsymbols, len(delays)) + 1j * np.random.randn(Nsymbols, len(delays)))
for i in range(Nsymbols):
coeffMatrix[i, :] = np.multiply(np.sqrt(powers), coeffMatrix[i, :]) # Element-wise multiplication
coeffMatrix[i, :] = np.multiply(1 / np.sqrt(np.var(coeffMatrix[i, :])), coeffMatrix[i, :])
H = np.fft.fft(coeffMatrix)
# Doppler spectrum definition
fOI = np.where(abs(f) < fd - 0.00001)
S_Jakes = np.zeros(f.shape)
S_flat = np.zeros(f.shape)
if fd != 0:
S_Jakes[fOI] = 1 / (np.pi * fd * np.sqrt(1 - (f[fOI] / fd)**2))
S_flat[fOI] = 1 / (2 * fd)
S_Jakes = np.transpose(np.sqrt(S_Jakes))
S_flat = np.transpose(np.sqrt(S_flat))
if fd == 0:
S_Jakes[int(np.ceil(len(f) / 2)) - 1] = 1
S_flat[int(np.ceil(len(f) / 2)) - 1] = 1
S = [S_Jakes, S_flat]
# Doppler application
for i in range(len(delays)):
H[:, i] = np.multiply(S[doppler[i]], H[:, i])
cMtxPostDoppler = np.fft.ifft(H)
# Building of the channel time response matrix
ind = np.zeros(len(delays), dtype=int)
for i in range(len(delays)):
ind[i] = np.argmin(abs(t - delays[i]))
hMatrix = np.zeros((Nsymbols, int(np.floor(Ts * fs))), dtype="complex128")
for n in range(Nsymbols):
hMatrix[n, ind] += cMtxPostDoppler[n, :]
hMatrix[n, :] /= np.linalg.norm(hMatrix[n, :])
H = np.transpose(np.fft.fft(np.transpose(hMatrix)))
return hMatrix, H
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment