3.1. Coordenadas – Perfil y zona Fresnel

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:

Granja2021_LOS.csv

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