Observar el perfil del terreno en una ruta, y estimar la primera zona de Fresnel permite revisar algunas situaciones donde se presente bloqueo, dispersión, difracción de la señal en el enlace.
Los datos del perfil se obtienen del proceso anterior desde el siguiente archivo:

En el proceso se añade al perfil la altura de las antenas en los dispositivos, la altura de la vegetación promedio y se genera la gráfica mostrada.
punto,altitud,altitud_gps,dist_Gw03,latitud,longitud,utm_este,utm_norte,utm_zLetra,utm_zNum,vegetacion,alt_antena
Gw03,65.0,68.3,0.0,-2.140439491218423,-79.96247385948875,615377.0,9763377.0,M,17,65.0,73.0
LOS01,64.0,66.16,24.74,-2.140222431275481,-79.96252795441376,615371.0,9763401.0,M,17,64.0,65.0
LOS02,59.0,66.16,75.93,-2.139770213855424,-79.96262716484223,615360.0,9763451.0,M,17,59.0,60.0
LOS03,58.0,66.16,99.64,-2.139553123308579,-79.96263630222327,615359.0,9763475.0,M,17,59.5,59.0
...
El resultado se guarda en un archivo.csv y en la gráfica.png
Instrucciones en Python
# Procesa perfiles y Zona Fresnel
# girni-fiec-espol Revisión: 20220724
# http://blog.espol.edu.ec/girni/
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import os
# INGRESO
archivocsv = 'Granja2021_LOS.csv'
carp_coord = 'coordenadas'
carpeta_rsm = 'resultado_LOS'
LineaObs = 'LOS'
segmentos = ['Gw03','LOS']
# Fresnel, selecciona dispositivo
analiza_punto = 'LOS09'
# vegetacion
plantas_entre = [0, 0] #[90,250]
plantas_altura = 1.6
# antenas
alturaGw = 8
alturapunto = 1
# parametros Fresnel
nFres = 1
freq = 915 # 915MHz
# Gráficas
muestras = 41 # resolución
guarda = True
# PROCEDIMIENTO
procesoCompleto = 0
# ruta de archivo
if len(carp_coord)>0:
carp_coord = carp_coord+'/'
archivo_ruta = carp_coord + archivocsv
if os.path.exists(archivo_ruta):
puntostodos = pd.read_csv(archivo_ruta,
index_col='punto')
procesoCompleto = 1
if procesoCompleto == 1:
# busca gateway
Gw_nombre = '';
for unpunto in puntostodos.index:
if unpunto.startswith('Gw'):
Gw_nombre = unpunto
if len(Gw_nombre)>0:
procesoCompleto = 2
if procesoCompleto == 2:
#ordena por distancia
puntostodos = puntostodos.sort_values(by=['dist_'+Gw_nombre])
puntostodos['enruta']=0
for unpunto in puntostodos.index:
for elemento in segmentos:
if unpunto.startswith(elemento):
puntostodos.loc[[unpunto],['enruta']] = 1
puntos = puntostodos[puntostodos['enruta']==1].copy()
procesoCompleto = 3
if procesoCompleto == 3:
# busca gateway y ubicación de punto observado
i_punto = -1 ; i_Gw=-1
i=0
for unpunto in puntos.index:
if unpunto.startswith('Gw'):
i_Gw = i
if unpunto==analiza_punto:
i_punto = i
i = i+1
if i_punto>=0 and i_Gw>=0:
procesoCompleto = 4
if procesoCompleto ==4:
# plantación sector
puntos['vegetacion'] = puntos['altitud']
for unpunto in puntos.index:
dist_punto = puntos['dist_'+Gw_nombre][unpunto]
envegetacion = (dist_punto>=np.min(plantas_entre))
envegetacion = envegetacion and (dist_punto<=np.max(plantas_entre))
if envegetacion:
puntos.at[unpunto,'vegetacion'] = puntos['altitud'][unpunto] + plantas_altura
# añade alturas de antenas
puntos['alt_antena'] = puntos['altitud'] + alturapunto
puntos.at[Gw_nombre,'alt_antena'] = puntos['altitud'][Gw_nombre] + alturaGw
procesoCompleto = 5
if procesoCompleto == 5:
# lambda Fresnel
lamb = 300/freq #300e6(m/s)/(freq*1e6)
# Zona de Fresnel
xi = puntos['dist_'+Gw_nombre]
yi_ant = puntos['alt_antena']
if i_punto>0:
# linea directa
dy = yi_ant[i_punto]-yi_ant[i_Gw]
dx = xi[i_punto]-xi[i_Gw]
m = dy/dx
alpha = np.arctan(m)
yi_f = lambda x: m*x + yi_ant[i_Gw]
xi_D = np.linspace(xi[i_Gw],xi[i_punto],
muestras)
yi_D = yi_f(xi_D)
dist_D = np.sqrt(dx**2+dy**2)
# zona Fresnel 1
F1_up = np.zeros(len(xi_D))
F1_down = np.zeros(len(xi_D))
for i in range(0,len(xi_D),1):
d1 = xi_D[i]/np.cos(alpha)
d2 = dist_D-d1
F1 = np.sqrt(np.abs(nFres*lamb*d1*d2)/(d1+d2))
xiu = xi_D[i]-F1*np.sin(np.abs(alpha))
d1_u = xiu
d2_u = dist_D-d1_u
xid = xi_D[i]+F1*np.sin(np.abs(alpha))
d1_d = xid
d2_d = dist_D-d1_d
# Fresnel, formula
Fup = np.sqrt(np.abs(nFres*lamb*d1_u*d2_u)/(d1_u+d2_u))
Fdown = np.sqrt(np.abs(nFres*lamb*d1_d*d2_d)/(d1_d+d2_d))
# Linea directa +/- Fresnel
F1_up[i] = yi_D[i] + Fup*np.cos(alpha)
F1_down[i] = yi_D[i] - Fdown*np.cos(alpha)
procesoCompleto = 6
# SALIDA
if procesoCompleto == 6:
print(puntos)
# guarda el reporte en csv
unreporte = carpeta_rsm+'/perfil_'+LineaObs+'.csv'
if os.path.exists(carpeta_rsm):
puntos.to_csv(unreporte)
else:
print('no existe carpeta:',carpeta_rsm)
else:
print('proceso completado hasta:', procesoCompleto)
print('Revisar errores en proceso:', procesoCompleto+1)
print(' Procesos:')
print('1: abrir archivo de datos ',archivocsv )
print('2: encontrar gateway con nombre Gw##')
print('3: ordenar tabla por distancias al gateway')
print('4: encontrar punto a analizar:',analiza_punto)
print('5: añadir altura de antenas y plantas')
print('6: calcular zona de fresnel')
if procesoCompleto == 6:
# GRAFICA
figura,(grafica1,grafica2) = plt.subplots(2,1)
# vegetacion
con_veget = np.array(puntos['vegetacion']-puntos['altitud'])
xiv = np.array(puntos['dist_'+Gw_nombre])[con_veget>0]
perfil = np.array(puntos['altitud'])[con_veget>0]
vegetacion = np.array(puntos['vegetacion'])[con_veget>0]
grafica1.fill_between(xiv,perfil,vegetacion,
color='lightgreen')
# perfil
grafica1.plot(puntos['dist_'+Gw_nombre],
puntos['altitud'],label='Perfil',
color='brown')
# antenas
grafica1.scatter(puntos['dist_'+Gw_nombre],
puntos['alt_antena'],
color='blue')
# etiquetas y lineas enlace
xigw = puntos['dist_'+Gw_nombre][Gw_nombre]
yigw = puntos['alt_antena'][Gw_nombre]
for unpunto in puntos.index:
xip = puntos['dist_'+Gw_nombre][unpunto]
yip = puntos['alt_antena'][unpunto]
grafica1.annotate(unpunto,(xip,yip),
rotation=45)
grafica1.plot((xigw,xip),(yigw,yip),
color = 'green',
linestyle='dotted')
untitulo = 'Ruta: '+LineaObs
untitulo = untitulo + ', Antena: Gw '+str(alturaGw)
untitulo = untitulo + 'm Dispositivo '+str(alturapunto)
untitulo = untitulo + 'm'
grafica1.set_title(untitulo)
grafica1.set_ylabel('altura')
grafica1.legend()
grafica1.grid(True,linestyle='dotted',
axis='x',which='both')
# plt.axis('equal')
grafica2.fill_between(xiv,perfil,vegetacion,
color='lightgreen')
# perfil
grafica2.plot(puntos['dist_'+Gw_nombre],
puntos['altitud'],
color='brown')
# antenas
grafica2.scatter(puntos['dist_'+Gw_nombre],
puntos['alt_antena'],
color='blue')
# etiquetas y lineas enlace
xigw = puntos['dist_'+Gw_nombre][Gw_nombre]
yigw = puntos['alt_antena'][Gw_nombre]
for unpunto in puntos.index:
if unpunto in [Gw_nombre, analiza_punto]:
xip = puntos['dist_'+Gw_nombre][unpunto]
yip = puntos['alt_antena'][unpunto]
grafica2.annotate(unpunto,(xip,yip),
rotation=45)
if i_punto>0:
# Fresnel
grafica2.plot(xi_D,yi_D,
label='linea enlace',
color='orange',
linestyle = 'dashed')
grafica2.plot(xi_D,F1_down,
label='Fresnel1',color='orange')
grafica2.plot(xi_D,F1_up,
color='orange')
grafica2.set_xlabel('distancia')
grafica2.set_ylabel('altura')
grafica2.legend()
grafica2.grid(True,linestyle='dotted',
axis='x',which='both')
# plt.axis('equal')
unarchivo = carpeta_rsm+'/perfil_'+LineaObs+'.png'
if (guarda==True) and os.path.exists(carpeta_rsm):
plt.savefig(unarchivo)
plt.show()
Referencia: https://es.wikipedia.org/wiki/Zona_de_Fresnel