Spaces:
Sleeping
Sleeping
Commit
·
5c35a76
1
Parent(s):
894b4f1
Subindo arquivos
Browse files- README.md +51 -6
- app.py +205 -0
- requirements.txt +6 -0
README.md
CHANGED
@@ -1,13 +1,58 @@
|
|
1 |
---
|
2 |
-
title: Rf
|
3 |
-
emoji:
|
4 |
-
colorFrom:
|
5 |
-
colorTo:
|
6 |
sdk: gradio
|
7 |
-
sdk_version: 4.
|
8 |
app_file: app.py
|
9 |
pinned: false
|
10 |
license: ecl-2.0
|
11 |
---
|
12 |
|
13 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
---
|
2 |
+
title: Rf-Radioenlace
|
3 |
+
emoji: 📡〰️〰️📡
|
4 |
+
colorFrom: blue
|
5 |
+
colorTo: cyan
|
6 |
sdk: gradio
|
7 |
+
sdk_version: 4.12.0
|
8 |
app_file: app.py
|
9 |
pinned: false
|
10 |
license: ecl-2.0
|
11 |
---
|
12 |
|
13 |
+
## Informação
|
14 |
+
|
15 |
+
Este projeto permite calcular a linha de visada e perda de propagação entre dois pontos, além de fornecer o Link Budget e os diagramas de Fresnel. Os usuários podem interagir com um mapa, ajustar as coordenadas (manualmente) dos sites e visualizar os resultados dos cálculos.
|
16 |
+
|
17 |
+
## Modelos de Propagação
|
18 |
+
|
19 |
+
**Okumura-Hata-Davidson:**
|
20 |
+
Este modelo é uma extensão do modelo Okumura-Hata, desenvolvido principalmente para ambientes urbanos. Ele não é especificamente projetado para condições de linha de visada e é mais adequado para predições em macrocélulas com distâncias acima de 1 km. Portanto, não é a melhor escolha para cenários LOS.
|
21 |
+
|
22 |
+
**ITU-R P.1546:**
|
23 |
+
Este modelo é destinado a predições ponto-área para serviços terrestres na faixa de frequência de 30 MHz a 4000 MHz. Embora possa ser usado em várias condições, incluindo percursos sobre terra e mar, ele não é otimizado especificamente para condições de linha de visada.
|
24 |
+
|
25 |
+
**ITU-R 525/526:**
|
26 |
+
- **ITU-R P.525** fornece cálculos de atenuação em espaço livre, aplicáveis em condições de linha de visada.
|
27 |
+
- **ITU-R P.526** trata da propagação por difração, relevante quando há obstruções no caminho (modelo Deygout).
|
28 |
+
|
29 |
+
O ITU-R P.525 é mais apropriado para condições LOS.
|
30 |
+
|
31 |
+
**Longley-Rice (ITM - Irregular Terrain Model):**
|
32 |
+
Este modelo pode ser aplicado a uma variedade de problemas de engenharia e leva em conta características do terreno. Embora possa ser usado em condições LOS, ele é mais conhecido por sua capacidade de modelar propagação em terrenos irregulares.
|
33 |
+
|
34 |
+
## Referências Teóricas
|
35 |
+
|
36 |
+
[1] Botelho, Alberto Leonardo Penteado; 2019. Propagation Models Comparison by Propagation Features. SET INTERNATIONAL JOURNAL OF BROADCAST ENGINEERING. ISSN Print: 2446-9246 ISSN Online: 2446-9432. doi: 10.18580/setijbe.2019.8. Web Link: [http://dx.doi.org/10.18580/setijbe.2019.8](http://dx.doi.org/10.18580/setijbe.2019.8) [Link](https://www.set.org.br/ijbe/ed5/artigo8.pdf)
|
37 |
+
|
38 |
+
[2] Fratu, Octavia, Martian, Alexandru, Lazaridis, Pavlos, Zaharis, Zaharias D. and Kasampalis, Stylianos (2015) Comparative study of Radio Mobile and ICS Telecom propagation prediction models for DVB-T. In: IEEE BMSB 2015 International Conference, 17th - 19th June 2015, Ghent, Belgium [Link](https://eprints.hud.ac.uk/id/eprint/25670/1/MM-15-102.pdf)
|
39 |
+
|
40 |
+
## A fazer
|
41 |
+
- Capturar automaticamente as coordenadas movendo os marcadores
|
42 |
+
- Verificar modelos de propagação e cálculo
|
43 |
+
- Verificar outros cálculos e diagramas úteis
|
44 |
+
|
45 |
+
## Informação adicional
|
46 |
+
|
47 |
+
- Developed by Ramon Mayor Martins, Ph.D. (2024)
|
48 |
+
- E-mail: rmayormartins at: gmail.com
|
49 |
+
- Homepage: [https://rmayormartins.github.io/](https://rmayormartins.github.io/)
|
50 |
+
- Twitter: [@rmayormartins](https://twitter.com/rmayormartins)
|
51 |
+
- GitHub: [https://github.com/rmayormartins](https://github.com/rmayormartins)
|
52 |
+
|
53 |
+
Check out the configuration reference at [https://huggingface.co/docs/hub/spaces-config-reference](https://huggingface.co/docs/hub/spaces-config-reference)
|
54 |
+
|
55 |
+
## Agradecimento especial
|
56 |
+
|
57 |
+
Instituto Federal de Santa Catarina, Câmpus São José, Área de Telecomunicações [https://ifsc.edu.br/](https://ifsc.edu.br/)
|
58 |
+
A futura Engenheira de Telecomunicações, Jéssica Gomes Carrico
|
app.py
ADDED
@@ -0,0 +1,205 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import folium
|
3 |
+
from geopy.distance import geodesic
|
4 |
+
import numpy as np
|
5 |
+
import matplotlib.pyplot as plt
|
6 |
+
import matplotlib.figure as Figure
|
7 |
+
from IPython.display import display, Javascript
|
8 |
+
|
9 |
+
#
|
10 |
+
def calculate_line_of_sight(site1, site2):
|
11 |
+
distance = geodesic(site1[:2], site2[:2]).km
|
12 |
+
return distance
|
13 |
+
|
14 |
+
#
|
15 |
+
def calculate_propagation_loss(distance, frequency, model):
|
16 |
+
if model == "Okumura-Hata-Davidson":
|
17 |
+
loss = 69.55 + 26.16 * np.log10(frequency) - 13.82 * np.log10(30) + (44.9 - 6.55 * np.log10(30)) * np.log10(distance)
|
18 |
+
elif model == "ITU-R P.1546":
|
19 |
+
loss = 20 * np.log10(distance) + 20 * np.log10(frequency) + 92.45
|
20 |
+
elif model == "ITU-R 525/526":
|
21 |
+
loss = 20 * np.log10(distance * 1e3) + 20 * np.log10(frequency) + 92.45
|
22 |
+
elif model == "Longley Rice":
|
23 |
+
loss = 32.45 + 20 * np.log10(distance) + 20 * np.log10(frequency)
|
24 |
+
else:
|
25 |
+
loss = None
|
26 |
+
return loss
|
27 |
+
|
28 |
+
#
|
29 |
+
def calculate_link_budget(tx_power, rx_sensitivity, propagation_loss):
|
30 |
+
return tx_power - propagation_loss - rx_sensitivity
|
31 |
+
|
32 |
+
#
|
33 |
+
def create_map():
|
34 |
+
m = folium.Map(location=[-27.595, -48.558], zoom_start=15, width='100%', height='400px')
|
35 |
+
site1 = folium.Marker(location=[-27.5968, -48.5686], tooltip='Site 1', draggable=True, icon=folium.Icon(color='red'))
|
36 |
+
site2 = folium.Marker(location=[-27.5970, -48.5613], tooltip='Site 2', draggable=True, icon=folium.Icon(color='blue'))
|
37 |
+
site1.add_to(m)
|
38 |
+
site2.add_to(m)
|
39 |
+
folium.LatLngPopup().add_to(m)
|
40 |
+
return m._repr_html_()
|
41 |
+
|
42 |
+
#
|
43 |
+
def draw_fresnel(site1, site2, distance):
|
44 |
+
frequency = 2400 #
|
45 |
+
wavelength = 300 / frequency #
|
46 |
+
d1 = np.linspace(0, distance, 500)
|
47 |
+
r1 = np.sqrt((wavelength * d1 * (distance - d1)) / distance)
|
48 |
+
r2 = np.sqrt((2 * wavelength * d1 * (distance - d1)) / distance)
|
49 |
+
r3 = np.sqrt((3 * wavelength * d1 * (distance - d1)) / distance)
|
50 |
+
r4 = np.sqrt((4 * wavelength * d1 * (distance - d1)) / distance)
|
51 |
+
|
52 |
+
fig, ax = plt.subplots()
|
53 |
+
ax.plot(d1, r1, label='1ª Zona de Fresnel')
|
54 |
+
ax.plot(d1, r2, label='2ª Zona de Fresnel', linestyle='--')
|
55 |
+
ax.plot(d1, r3, label='3ª Zona de Fresnel', linestyle=':')
|
56 |
+
ax.plot(d1, r4, label='4ª Zona de Fresnel', linestyle='-.')
|
57 |
+
ax.fill_between(d1, 0, r1, color='lightblue', alpha=0.5)
|
58 |
+
ax.set_title('Diagrama de Fresnel')
|
59 |
+
ax.set_xlabel('Distância (km)')
|
60 |
+
ax.set_ylabel('Raio da Zona de Fresnel (m)')
|
61 |
+
ax.legend()
|
62 |
+
ax.grid(True)
|
63 |
+
return fig
|
64 |
+
|
65 |
+
#
|
66 |
+
def draw_line_of_sight(site1, site2, distance, site1_height, site2_height):
|
67 |
+
d1 = np.linspace(0, distance, 500)
|
68 |
+
|
69 |
+
#
|
70 |
+
los = np.linspace(site1_height, site2_height, 500)
|
71 |
+
|
72 |
+
fig, ax = plt.subplots()
|
73 |
+
ax.plot(d1, los, label='Linha de Visada', color='magenta')
|
74 |
+
ax.set_title('Linha de Visada')
|
75 |
+
ax.set_xlabel('Distância (km)')
|
76 |
+
ax.set_ylabel('Elevação (m)')
|
77 |
+
ax.legend()
|
78 |
+
ax.grid(True)
|
79 |
+
return fig
|
80 |
+
|
81 |
+
#
|
82 |
+
def interactive_propagation_map(site1_coords, site2_coords, site1_height, site2_height, frequency, model, tx_power1, rx_sensitivity1, tx_power2, rx_sensitivity2):
|
83 |
+
try:
|
84 |
+
site1_lat, site1_lon = map(float, site1_coords.split(','))
|
85 |
+
site2_lat, site2_lon = map(float, site2_coords.split(','))
|
86 |
+
except ValueError:
|
87 |
+
return "Erro: Coordenadas inválidas.", "Erro: Coordenadas inválidas.", "Erro: Coordenadas inválidas.", None, None, None
|
88 |
+
|
89 |
+
site1 = (site1_lat, site1_lon, site1_height)
|
90 |
+
site2 = (site2_lat, site2_lon, site2_height)
|
91 |
+
|
92 |
+
#
|
93 |
+
distance = calculate_line_of_sight(site1, site2)
|
94 |
+
|
95 |
+
#
|
96 |
+
propagation_loss = calculate_propagation_loss(distance, frequency, model)
|
97 |
+
|
98 |
+
#
|
99 |
+
link_budget1 = calculate_link_budget(tx_power1, rx_sensitivity2, propagation_loss)
|
100 |
+
link_budget2 = calculate_link_budget(tx_power2, rx_sensitivity1, propagation_loss)
|
101 |
+
|
102 |
+
#
|
103 |
+
m = folium.Map(location=[(site1_lat + site2_lat) / 2, (site1_lon + site2_lon) / 2], zoom_start=15, width='100%', height='400px')
|
104 |
+
folium.Marker(location=[site1_lat, site1_lon], popup='Site 1 Coordenadas: {:.6f}, {:.6f}'.format(site1_lat, site1_lon), tooltip='Site 1', draggable=True, icon=folium.Icon(color='red')).add_to(m)
|
105 |
+
folium.Marker(location=[site2_lat, site2_lon], popup='Site 2 Coordenadas: {:.6f}, {:.6f}'.format(site2_lat, site2_lon), tooltip='Site 2', draggable=True, icon=folium.Icon(color='blue')).add_to(m)
|
106 |
+
folium.PolyLine(locations=[[site1_lat, site1_lon], [site2_lat, site2_lon]], color='blue', weight=2.5).add_to(m)
|
107 |
+
m.add_child(folium.LatLngPopup())
|
108 |
+
|
109 |
+
map_html = m._repr_html_()
|
110 |
+
|
111 |
+
#
|
112 |
+
fresnel_plot = draw_fresnel(site1, site2, distance)
|
113 |
+
|
114 |
+
#
|
115 |
+
los_plot = draw_line_of_sight(site1, site2, distance, site1_height, site2_height)
|
116 |
+
|
117 |
+
return map_html, f"Distância: {distance:.2f} km", f"Perda de propagação: {propagation_loss:.2f} dB", fresnel_plot, f"Orçamento de enlace (Site 1 -> Site 2): {link_budget1:.2f} dB", f"Orçamento de enlace (Site 2 -> Site 1): {link_budget2:.2f} dB", los_plot
|
118 |
+
|
119 |
+
with gr.Blocks() as interface:
|
120 |
+
with gr.Row():
|
121 |
+
with gr.Column(scale=1):
|
122 |
+
gr.Markdown("### Mapa")
|
123 |
+
map_display = gr.HTML(create_map(), label="Clique no mapa para marcar os sites e arraste os marcadores para ajustar a posição. Copie e cole as coordenadas nos campos abaixo.")
|
124 |
+
with gr.Column(scale=1):
|
125 |
+
gr.Markdown("### Coordenadas")
|
126 |
+
site1_coords = gr.Textbox(label="Coordenadas do Site 1", placeholder="-27.5968, -48.5686", value="-27.5968, -48.5686")
|
127 |
+
site2_coords = gr.Textbox(label="Coordenadas do Site 2", placeholder="-27.5970, -48.5613", value="-27.5970, -48.5613")
|
128 |
+
site1_height = gr.Number(label="Altura do Site 1 (m)", value=30)
|
129 |
+
site2_height = gr.Number(label="Altura do Site 2 (m)", value=30)
|
130 |
+
|
131 |
+
with gr.Row():
|
132 |
+
with gr.Column(scale=1):
|
133 |
+
gr.Markdown("### Modelo de Propagação")
|
134 |
+
frequency = gr.Slider(minimum=30, maximum=3000, label="Frequência (MHz)")
|
135 |
+
model = gr.Radio(choices=["Okumura-Hata-Davidson", "ITU-R P.1546", "ITU-R 525/526", "Longley Rice"], label="Modelo de Propagação")
|
136 |
+
with gr.Column(scale=1):
|
137 |
+
gr.Markdown("### Link Budget")
|
138 |
+
tx_power1 = gr.Number(label="Potência Tx do Site 1 (dBm)", value=20)
|
139 |
+
rx_sensitivity1 = gr.Number(label="Sensibilidade Rx do Site 1 (dBm)", value=-90)
|
140 |
+
tx_power2 = gr.Number(label="Potência Tx do Site 2 (dBm)", value=20)
|
141 |
+
rx_sensitivity2 = gr.Number(label="Sensibilidade Rx do Site 2 (dBm)", value=-90)
|
142 |
+
|
143 |
+
with gr.Row():
|
144 |
+
calculate_button = gr.Button("Calcular")
|
145 |
+
|
146 |
+
gr.Markdown("### Resultados:")
|
147 |
+
|
148 |
+
with gr.Row():
|
149 |
+
with gr.Column(scale=1):
|
150 |
+
distance_output = gr.Textbox(label="Distância", interactive=False)
|
151 |
+
loss_output = gr.Textbox(label="Perda de Propagação", interactive=False)
|
152 |
+
with gr.Column(scale=1):
|
153 |
+
link_budget1_output = gr.Textbox(label="Link Budget (Site 1 -> Site 2)", interactive=False)
|
154 |
+
link_budget2_output = gr.Textbox(label="Link Budget (Site 2 -> Site 1)", interactive=False)
|
155 |
+
|
156 |
+
with gr.Row():
|
157 |
+
with gr.Column(scale=1):
|
158 |
+
fresnel_plot = gr.Plot(label="Diagrama de Fresnel")
|
159 |
+
with gr.Column(scale=1):
|
160 |
+
terrain_plot = gr.Plot(label="Linha de Visada")
|
161 |
+
|
162 |
+
calculate_button.click(fn=interactive_propagation_map, inputs=[site1_coords, site2_coords, site1_height, site2_height, frequency, model, tx_power1, rx_sensitivity1, tx_power2, rx_sensitivity2], outputs=[map_display, distance_output, loss_output, fresnel_plot, link_budget1_output, link_budget2_output, terrain_plot])
|
163 |
+
|
164 |
+
#
|
165 |
+
interface.launch(share=True)
|
166 |
+
|
167 |
+
#Campo do Javascript (arrumar!)
|
168 |
+
display(Javascript('''
|
169 |
+
document.addEventListener('DOMContentLoaded', function() {
|
170 |
+
var iframe = document.querySelector('iframe');
|
171 |
+
iframe.addEventListener('load', function() {
|
172 |
+
var iframeDocument = iframe.contentDocument || iframe.contentWindow.document;
|
173 |
+
|
174 |
+
function addDragEndListener(marker, siteLabel) {
|
175 |
+
marker.on('moveend', function(e) {
|
176 |
+
var lat = e.target.getLatLng().lat.toFixed(6);
|
177 |
+
var lon = e.target.getLatLng().lng.toFixed(6);
|
178 |
+
var popupContent = siteLabel + ' Coordenadas: ' + lat + ',' + lon;
|
179 |
+
marker.bindPopup(popupContent).openPopup();
|
180 |
+
console.log(popupContent);
|
181 |
+
});
|
182 |
+
// Atualizar o popup imediatamente com a posição inicial
|
183 |
+
var lat = marker.getLatLng().lat.toFixed(6);
|
184 |
+
var lon = marker.getLatLng().lng.toFixed(6);
|
185 |
+
var popupContent = siteLabel + ' Coordenadas: ' + lat + ',' + lon;
|
186 |
+
marker.bindPopup(popupContent).openPopup();
|
187 |
+
console.log(popupContent);
|
188 |
+
}
|
189 |
+
|
190 |
+
var markers = iframeDocument.querySelectorAll('.leaflet-marker-icon');
|
191 |
+
console.log('Markers found:', markers.length);
|
192 |
+
var siteLabels = ['Site 1', 'Site 2'];
|
193 |
+
|
194 |
+
markers.forEach((marker, index) => {
|
195 |
+
console.log('Adding event listener to marker', index);
|
196 |
+
addDragEndListener(marker, siteLabels[index]);
|
197 |
+
});
|
198 |
+
});
|
199 |
+
});
|
200 |
+
'''))
|
201 |
+
|
202 |
+
#Pra manter celula ativa.
|
203 |
+
import time
|
204 |
+
while True:
|
205 |
+
time.sleep(1)
|
requirements.txt
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
gradio
|
2 |
+
folium==0.12.1
|
3 |
+
geopy==2.2.0
|
4 |
+
numpy==1.21.2
|
5 |
+
matplotlib==3.4.3
|
6 |
+
|