Files
SPLAT-Parallel-with-Rust/MANUAL.md
T
cescobar 9d7d3bac45 Commit inicial: splat-rs — fork/port a Rust de SPLAT!
Fork de SPLAT! (John A. Magliacane, KD2BD, 2002-2014), bajo GPLv2 heredada
del original. El núcleo de cálculo de propagación (ITWOM v3.0, Sid Shumate)
se mantiene sin modificar en cpp/itwom3.0.cpp, llamado vía FFI. El resto
del pipeline (lectura de formatos SPLAT!, reportes, mapas, KML, gnuplot)
se reescribió en Rust, con paralelización nativa vía rayon reemplazando
el paralelismo por múltiples procesos del original. Validado contra el
corpus golden de SPLAT! con drift < 0.02 dB en cálculos ITWOM.
2026-08-23 01:50:41 -05:00

566 lines
19 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# splat-rs — Manual del Usuario
**splat-rs** es un port en Rust de SPLAT! (Signal Propagation, Loss, And Terrain
analysis tool) con paralelización nativa, salidas en español y una nueva
funcionalidad de tabla de intensidad de campo.
Compatible con los formatos `.qth`, `.lrp`, `.az`, `.el`, `.udt`, `.cities` y
`.sdf[.bz2]` del SPLAT! 1.4.x original. Validado contra el corpus golden de
SPLAT! con drift inferior a 0.02 dB en cálculos ITWOM.
---
## 1. Inicio rápido
```bash
# Análisis de enlace TX → RX
splat-rs -t txenlace.qth -r rxenlace.qth -d sdf/
# Cobertura completa de un sitio
splat-rs -t tx_site.qth -d sdf/ -L 10 -R 80
# Tabla de intensidad de campo (alternativa al script perfiles.sh)
splat-rs -t tx_site.qth -d sdf/ --sft atenuaciones.txt --sft-max-km 150
```
Salidas en `--out-dir` (default: directorio actual):
| Archivo | Cuándo se genera |
|---|---|
| `<TX>-site_report.txt` | si **no** hay `-r` |
| `<TX>-to-<RX>.txt` | si hay `-r` (path report) |
| `coverage.ppm`/`.png`/`.kml` | si **no** está `--no-map` |
| `<archivo>.txt` + `.csv` | si está `--sft <archivo>` |
| `splat.gp` + `*.gp` | si está `-h/-H/-p/-e/-l <archivo>` |
---
## 2. Construcción
```bash
cd splat-rs
cargo build --release
# Binario: ./target/release/splat-rs
```
Requiere:
- Rust ≥ 1.80 (probado con 1.92)
- `libbz2.so` accesible (sistema o miniconda)
- `gnuplot` (opcional, para renderizar los `.gp`)
- `convert` de ImageMagick (opcional, para PPM → PNG transparente)
Para ejecutar con libbz2 desde miniconda:
```bash
LD_LIBRARY_PATH=$HOME/miniconda3/lib ./target/release/splat-rs ...
```
---
## 3. Formatos de entrada
### `.qth` — Sitio (TX o RX)
Cuatro líneas:
```
Nombre del sitio
-1 -01 -23.54 ; latitud (DMS o decimal)
79 27 31.21 ; longitud (DMS o decimal, positiva = oeste)
14 m ; altura antena AGL (metros con 'm', si no = pies)
```
### `.lrp` — Parámetros Longley-Rice
Una constante numérica por línea, comentarios con `;`:
```
15.000 ; Constante dieléctrica de la Tierra
0.005 ; Conductividad (S/m)
301.00 ; Refracción atmosférica (N-units)
426 ; Frecuencia (MHz)
5 ; Clima radioeléctrico (1-7)
1 ; Polarización (0=H, 1=V)
0.50 ; Fracción de situaciones
0.50 ; Fracción de tiempo
2000 ; ERP en watts (línea 9, opcional)
```
Climas: `1`=Ecuatorial, `2`=Subtropical Continental, `3`=Subtropical Marítimo,
`4`=Desértico, `5`=Templado Continental, `6`=Templado Marítimo (tierra),
`7`=Templado Marítimo (mar).
### `.az` — Patrón azimutal de antena (autodetectado al lado del `.qth` del TX)
```
345.0 ; rotación en grados (clockwise desde el norte verdadero)
0 0.49 ; az amplitud (0..1)
1 0.50
2 0.51
...
```
### `.el` — Patrón vertical de antena
```
8.0 345.0 ; tilt mecánico, azimuth del tilt
-10 0.04
-9.5 0.06
...
```
Usa `--no-pattern` para ignorar archivos `.az`/`.el` aun si existen.
### `.udt` — Terreno definido por usuario
CSV de obstáculos puntuales:
```
; Edificios y antenas en Quevedo
-1.0250, 79.4587, 50 m
-1.0260, 79.4590, 80 m
```
Cada feature se "pinta" en un radio de ~5 píxeles (~465 m a 1200 ppd) sobre el DEM.
El máximo entre la base SDF y el UDT prevalece.
### `.cities` o `-s <file>` — Sitios de interés
CSV `name, lat, lon`:
```
Quito, -0.18, 78.47
Guayaquil, -2 10 0, 79 53 0
```
### `.sdf[.bz2]` — Datos de elevación digital
Archivos SPLAT! estándar. Nombres `minlat:maxlat:minlon:maxlon.sdf.bz2` cubriendo
× 1° cada uno. Carpeta vía `-d sdf/`. Soporta tanto 3 arc-sec (1200 ppd) como
1 arc-sec (3600 ppd, modo HD).
---
## 4. Referencia de banderas
### Entrada
| Bandera | Descripción |
|---|---|
| `-t, --tx FILE` | TX `.qth` (obligatorio) |
| `-r, --rx FILE` | RX `.qth` (opcional; si está → path report; si no → site report) |
| `-d, --sdf DIR` | Directorio con tiles `.sdf[.bz2]` (obligatorio) |
| `--lrp FILE` | `.lrp` (default: `splat.lrp` junto al TX) |
| `--erp WATTS` | Override del ERP del `.lrp` |
| `-s, --cities FILE` | Archivo de sitios; repetible |
| `--udt FILE` | Terreno definido por usuario; repetible |
### Modelo y geometría
| Bandera | Descripción | Default |
|---|---|---|
| `--olditm` | Usa Longley-Rice clásico en vez de ITWOM v3.0 | off (ITWOM) |
| `-L, --rx-altitude-m M` | Altura RX AGL para sweep de cobertura | 10 m |
| `-R, --range-km KM` | Radio de cobertura | 40 km |
| `--metric` | Unidades métricas en reportes | true |
| `--gc M` | Altura de clutter (obstáculos urbanos) | 0 |
| `--fz F` | Clearance Fresnel (`F` ∈ [0,1]) | 0.6 (60%) |
| `--no-pattern` | Ignora `.az`/`.el` autodetectados | off |
### Salidas — gráficas (cada una toma un nombre de archivo)
| Bandera | Genera | Equivale a SPLAT |
|---|---|---|
| `-h FILE` | Gráfico de alturas (perfil + LOS + curvatura + Fresnel) | `-h` |
| `-H FILE` | Versión normalizada del anterior | `-H` |
| `-p FILE` | Perfil del terreno (elevación vs distancia) | `-p` |
| `-e FILE` | Perfil de ángulo de elevación | `-e` |
| `-l FILE` | Gráfico de pérdida del trayecto | `-l` |
| `--plot-format FMT` | Tipo de salida gnuplot (png, svg, ps...) | — |
> **Convención `-h`/`-H`**: el plot de alturas usa el marco de **tierra
> aplanada (4/3)**: el perfil del terreno se eleva por
> `d·(D-d)/(2·R')` para que la LOS sea una recta y la zona de Fresnel se
> dibuje como su geometría natural debajo. Si el terreno aparente toca la
> Fresnel en el gráfico, es una obstrucción real — convención estándar en
> ingeniería de RF (ATDI, Pathloss, etc.). Además se superpone una
> **referencia de curvatura** (parábola en el mismo eje Y, anclada al
> fondo del plot) cuyo peak coincide con el terreno más bajo y endpoints
> sit en `min(terreno)max_drop`. La magnitud del hump es D²/(8·R'):
> ~150 m para D=100 km, ~180 m para D=110 km. Si quieres ver el perfil
> geográfico crudo (sin corrección de curvatura), usa `-p`.
> **Auto-render**: si `gnuplot` está en el PATH, splat-rs lo invoca automáticamente
> tras escribir los `.gp` y produce directamente el PNG/SVG/PS. Cada flag escribe
> a su propio subdirectorio (`h-<stem>/`, `p-<stem>/`, etc.) para que no colisionen
> al pedir varios plots a la vez:
>
> ```bash
> splat-rs -t tx.qth -r rx.qth -d sdf/ --no-map \
> -h alturas.png -p terreno.png -e elevacion.png
> # → out_dir/h-alturas/alturas.png
> # → out_dir/p-terreno/terreno.png
> # → out_dir/e-elevacion/elevacion.png
> ```
>
> Si no hay `gnuplot`, splat-rs deja los `.gp` para que el usuario los renderice
> manualmente (`cd subdir && gnuplot splat.gp`).
### Salidas — mapa de cobertura (sweep 360°)
| Bandera | Descripción |
|---|---|
| `-c, --los-coverage` | Modo LOS (sin ITWOM, ~75× más rápido) |
| `--no-map` | No generar mapa (solo reporte) |
| `--no-kml` | No generar KML |
| `--no-link-line` | Omitir línea TX→RX en KML |
| `--max-loss-db DB` | Umbral de pérdida (mayor → blanco transparente). FM: 110-120, UHF: 125-135, microondas: 160+ |
| `--min-loss-db DB` | Pérdida mínima (mapea al color más fuerte) |
> **Leyenda automática**: cada vez que se genera un mapa de cobertura, splat-rs
> también escribe `legend.svg` (con texto) y `legend.ppm` (barra de colores
> sola) que muestran el mapeo color↔pérdida↔intensidad de campo del run.
### Tabla de intensidad de campo (`-sft`)
| Bandera | Descripción |
|---|---|
| `--sft FILE` | Genera tabla en `<FILE>` (texto) y `<FILE>.csv` |
| `--sft-max-km KM` | Extiende a `KM` (default 90; pasos de 10 km después de 90) |
| `--sft-azimuths LISTA` | Azimuts custom CSV (default: 0,30,60,...,330) |
| `--sft-distances LISTA` | Distancias custom CSV (override total) |
### Sistema
| Bandera | Descripción | Default |
|---|---|---|
| `--threads N` | Hilos para rayon (0 = todos los cores) | 0 |
| `--out-dir DIR` | Directorio de salida | `.` |
| `--help` | Ayuda completa | — |
| `-V, --version` | Versión | — |
---
## 5. Flujos de trabajo comunes
### 5.1 Análisis rápido de sitio (qué tan elevada está la antena vs el terreno)
```bash
splat-rs -t mi_sitio.qth -d sdf/ --no-map
```
Genera `mi_sitio-site_report.txt` con: ubicación, elevación del terreno,
altura de la antena, **HAAT** (altura sobre terreno promedio según FCC
Part 73.313(d)) y promedios de terreno en 8 azimuts cardinales.
### 5.2 Estudio de enlace punto-a-punto
```bash
splat-rs -t tx.qth -r rx.qth -d sdf/ --no-map -h alturas.png
```
Genera:
- Path report en español con pérdida ITWOM, modo de propagación, análisis de
obstrucciones y zonas de Fresnel
- `alturas.png` (vía `gnuplot splat.gp`) con perfil + LOS + curvatura 4/3 +
Fresnel del 60% y 100%
### 5.3 Mapa de cobertura ITWOM completo (lento pero preciso)
```bash
splat-rs -t tx.qth -d sdf/ -L 10 -R 80 \
--max-loss-db 120 \
-s ciudades.cities --out-dir cobertura/
```
Genera en `cobertura/`:
- `coverage.ppm` (raster PPM puro)
- `coverage.png` (con blanco → transparente)
- `coverage.kml` (Google Earth con TX, ciudades y línea de enlace)
- `<TX>-site_report.txt`
Tiempo típico: ~2-4 min en 16 cores para 80 km de radio.
### 5.4 Mapa LOS rápido (bosquejo previo)
```bash
splat-rs -t tx.qth -d sdf/ -L 10 -R 80 -c
```
Mismo formato de salidas pero **~75× más rápido** (sin llamadas a ITWOM).
Útil para identificar primero qué zonas tienen línea de vista antes de hacer
el sweep ITWOM completo. Tiempo típico: 1-3 s.
### 5.5 Tabla de intensidad de campo (alternativa a `perfiles.sh`)
**Default**: 12 azimuts × 13 distancias (540 km en pasos de 5, luego 50/60/70/80/90):
```bash
splat-rs -t tx.qth -d sdf/ --olditm --no-map --sft atenuaciones.txt
```
**Extendida hasta 150 km**:
```bash
splat-rs -t tx.qth -d sdf/ --olditm --no-map \
--sft atenuaciones.txt --sft-max-km 150
```
**Grid completamente personalizado** (8 cardinales × distancias específicas):
```bash
splat-rs -t tx.qth -d sdf/ --olditm --no-map \
--sft puntos.txt \
--sft-azimuths 0,45,90,135,180,225,270,315 \
--sft-distances 1,2,5,10,20,50,100,150,200
```
Salida en `atenuaciones.txt`:
```
# Tabla de intensidad de campo (dBµV/m) — splat-rs
# TX: Cerro Cochabamba @ (-1.6986, 79.1072), 91.5 MHz, ERP 2000 W, modelo LongleyRice
Dist/Az 0° 30° 60° 90° 120° ...
5 km 95.08 69.96 43.30 35.89 35.82 ...
10 km 24.62 47.60 30.73 33.41 13.03 ...
...
```
Y CSV `atenuaciones.csv` para Excel/LibreOffice. Si necesitas decimal coma
para `es_EC`:
```bash
sed 's/\./,/g' atenuaciones.csv > atenuaciones-es.csv
```
Tiempo típico: **<10 ms** por tabla (compute) más 6-7 s de carga SDF (una vez).
### 5.6 Estudio con patrón de antena directiva
Si junto al `.qth` del TX están `<base>.az` y `<base>.el`, splat-rs los detecta
automáticamente y aplica el patrón en la pérdida y la tabla SFT:
```bash
ls
# tx_site.qth tx_site.az tx_site.el splat.lrp
splat-rs -t tx_site.qth -d sdf/ --sft tabla.txt
# stderr: "Patrón de antena cargado (rotación 345.0°, tilt 8.0°)"
```
El reporte incluye `Patrón de antena de TX hacia RX: 0.562 (-5.00 dB)` cuando
hay `-r`.
### 5.7 Override de ERP para análisis A/B
```bash
splat-rs -t tx.qth -r rx.qth -d sdf/ --erp 2000 --no-map
splat-rs -t tx.qth -r rx.qth -d sdf/ --erp 5000 --no-map # comparar
```
### 5.8 UDT — terreno con edificios sintéticos
```bash
cat > obstaculos.udt <<EOF
; Torre de transmisión vecina
-1.0245, 79.4593, 50 m
EOF
splat-rs -t tx.qth -r rx.qth -d sdf/ --udt obstaculos.udt --no-map
```
El reporte detectará obstrucciones en cada UDT y recomendará la altura mínima
de antena RX para librar terreno y zonas de Fresnel.
---
## 6. Salidas explicadas
### Path report (`<TX>-to-<RX>.txt`)
Bloques en orden:
1. **Sitio transmisor**: nombre, ubicación DMS, elevación, altura antena, HAAT,
distancia, azimut, ángulo elevación al RX
2. **Sitio receptor**: idem desde el RX
3. **Parámetros del modelo**: dieléctrica, conductividad, refracción, frecuencia,
clima, polarización, fracciones, ERP/EIRP (si está en `.lrp`)
4. **Resumen del enlace**: pérdida en espacio libre, pérdida ITWOM (o LR),
atenuación por terreno, modo de propagación (LDV / horizonte simple /
horizonte doble + difracción/troposcatter)
5. **Análisis de obstrucciones**: lista de cada punto bloqueante y recomendaciones
de altura para librar LOS / 60% Fresnel / Fresnel completa
### Site report (`<TX>-site_report.txt`)
Cuando solo se da `-t`. Estructura:
- Sitio (DMS), elevación del terreno, altura de la antena
- HAAT (altura sobre promedio del terreno)
- Promedio del terreno en 8 azimuts (0°, 45°, 90°, ..., 315°) entre 2 y 10 millas
### Coverage map
- **`coverage.ppm`**: raster PPM/P6, dimensiones automáticas según los radiales
- **`coverage.png`**: misma imagen con `convert -transparent white` si está
ImageMagick disponible
- **`coverage.kml`**: Google Earth con `GroundOverlay` apuntando al PNG, línea
amarilla TX→RX (si hay -r), Placemarks para TX/RX/ciudades
- **`legend.svg`**: leyenda con barra de colores y dos ejes:
pérdida en dB a la izquierda, intensidad de campo (dBµV/m) a la derecha.
Calculada con la frecuencia y ERP del `.lrp`. Renderiza en cualquier navegador
o se convierte con `convert legend.svg legend.png`.
- **`legend.ppm`**: solo la barra de color (sin texto), 30×280 px. Útil para
componer con el mapa via `convert +append coverage.png legend.ppm composite.png`
o similar.
### Tabla SFT
- **`<archivo>`**: tabla de texto formateada con encabezado descriptivo
- **`<archivo>.csv`**: para importar en hojas de cálculo
### Gráficos gnuplot
Cada vez que se pide `-h/-H/-p/-e/-l`, se genera un set en el subdirectorio:
- `splat.gp`: orquestador (set title/xlabel/ylabel + plot)
- `profile.gp`: terreno
- `reference.gp`: línea de vista
- `curvature.gp`: curvatura 4/3 Tierra
- `fresnel.gp`, `fresnel_pt_6.gp`: zonas de Fresnel (cuando aplica)
Para renderizar: `cd subdir && gnuplot splat.gp` produce el archivo de imagen.
---
## 7. Rendimiento
### Hardware típico (16 cores)
| Operación | Tiempo |
|---|---|
| Carga 54 tiles SDF (Ecuador completo) | 6-7 s |
| Path report TX↔RX (1 enlace) | <1 s |
| Site report (HAAT + 8 radiales) | <1 s |
| Tabla SFT 12×13 | 1-2 ms |
| Tabla SFT 12×19 (hasta 150 km) | 2-3 ms |
| Mapa LOS coverage 80 km | 1-3 s |
| Mapa ITWOM coverage 40 km | 1-2 min |
| Mapa ITWOM coverage 80 km | 3-5 min |
Speedup típico paralelo / secuencial: 10-12× (eficiencia 65-75% de los 16 cores).
### Comparación con SPLAT! original (single-thread)
| | SPLAT! v1.4.2 | splat-rs |
|---|---|---|
| Mapa ITWOM 40 km | ~25 min | ~2 min (12.5× más rápido) |
| Tabla SFT (`perfiles.sh`) | ~30 min | ~7 s (260× más rápido) |
| Path report único | ~2 s | <1 s |
---
## 8. Diagnóstico de problemas
### "El TX (X, Y) no está cubierto por los tiles SDF de ..."
El TX cae fuera de los tiles cargados. Verifica los nombres de archivo en
`sdf/`: deben tener formato `minlat:maxlat:minlon:maxlon.sdf.bz2` y cubrir
el rango de coordenadas del TX/RX.
### Mapa de cobertura completamente blanco
`--max-loss-db` demasiado bajo para el escenario:
- Microondas en LOS limpio: pérdida 100-130 dB → `--max-loss-db 130` o más
- Microondas con obstrucciones: hasta 180 dB → `--max-loss-db 180`
### Patrón de antena no aplicado
splat-rs busca `<base>.az` y `<base>.el` donde `<base>` es el nombre del `.qth`
sin extensión. Si tu antena se llama `tx.qth`, debe haber `tx.az` / `tx.el` en
el mismo directorio. Verifica con `--no-pattern` para forzar isotrópica y
comparar.
### Aliasing radial visible en mapa de cobertura
Es inherente al método radial-sweep. Mitigaciones:
- Subir umbral con `--max-loss-db` para mostrar solo cobertura útil
- Usar HD mode (DEM 1 arc-sec, ppd=3600) — 9× más lento pero menos artifacts
- El renderer ya aplica supercover 2×2 + dilatación; resta es físicamente irreducible
### `gnuplot: not found` al pedir `-h/-H/-p/-e/-l`
splat-rs solo escribe los `.gp` data y orquestador. Para rasterizar necesitas
`gnuplot` instalado:
```bash
sudo apt install gnuplot
```
### Ejecución más lenta de lo esperado
Verifica que rayon esté usando todos los cores:
```bash
splat-rs ... 2>&1 | head -1
# "Hilos disponibles: 16 (de 16 lógicos)"
```
Si aparece menos, usa `--threads N` para forzar.
---
## 9. Diferencias con SPLAT! original
### Mejoras
- **Reentrancia thread-safe**: `static → thread_local` en ITWOM permite N hilos sin contención
- **Paralelización nativa**: rayon distribuye radiales/SFT-celdas entre todos los cores
- **Carga DEM única**: vs SPLAT que recarga en cada invocación
- **Salida en español** (homologada por Charles)
- **Sintaxis CLI compatible** + extensiones (`--sft`, `--threads`, `--max-loss-db`)
- **CSV de la tabla SFT** además del texto
- **Mensajes de error útiles** con contexto
### No implementado
- `-ano` / `-ani`: input/output alfanumérico (uso poco común)
- `-b`: archivos de fronteras cartográficas (overlay PPM)
- `-dbm`: paleta dBm en vez de dBµV/m (existe en código pero no expuesto en CLI)
- `-geo`: archivo georreferencia Xastir (formato muy específico)
- `-log`: registro del comando (uso `>&2` redirect en shell)
- `-ngs`: topografía gris como blanco (escala de grises)
- `-sc`: contornos suaves (paleta lineal vs cuantizada)
- `-db`: contornos por encima de un umbral
- `-nf`: omitir Fresnel en height plot (siempre se grafica)
### Drift numérico
- ITWOM path loss: ±0.02 dB vs SPLAT golden (floating-point con `-ffast-math` activado en C++ original)
- HAAT: ±0.1 m por sampling de los 8 radiales
- Ángulos: bit-idénticos (mismo radio terrestre 20902230.97 ft)
---
## 10. Estructura del proyecto
```
splat-rs/
├── Cargo.toml
├── MANUAL.md # este archivo
├── build.rs # compila itwom + linkea libbz2
├── cpp/
│ ├── itwom3.0.cpp # vendored, static→thread_local
│ └── itwom_ffi.cpp # C ABI wrapper (refs → pointers)
└── src/
├── lib.rs # mod tree
├── itwom.rs # FFI seguro a ITWOM/Longley-Rice
├── sdf.rs # loader .sdf[.bz2] + DemTileSet indexado
├── qth.rs # parser .qth (DMS o decimal)
├── lrp.rs # parser .lrp (tolerante a prosa)
├── pat.rs # parser .az/.el + AntennaPattern
├── udt.rs # parser .udt + DemWithUdt overlay
├── cities.rs # parser .cities
├── geo.rs # Distance, Azimuth, step_great_circle
├── radial.rs # compute_radial + plot_lr_map_parallel
├── coverage.rs # CoverageMap + rasterize_line + fill_holes
├── ppm.rs # writer PPM con paleta signal-strength
├── kml.rs # writer KML GroundOverlay + LineString
├── gnuplot.rs # writers .gp (perfil/altura/elevación)
├── report.rs # PathReport + SiteReport + ObstructionAnalysis
├── sft.rs # Strength Field Table (paralelo)
├── types.rs # Site, Config
└── bin/
├── splat-rs.rs # CLI principal
└── bench.rs # microbenchmark ser vs par
```
26 tests unitarios + 4 ignored (end-to-end con DEM real).
---
## 11. Créditos
- **SPLAT!** original: John A. Magliacane, KD2BD (20022014)
- **ITWOM v3.0**: Sid Shumate (2010)
- **Adaptación al español + variante 1.4.2-Charles**: Ing. Charles Escobar
- **Port a Rust + paralelización**: 2026
Bajo licencia GPLv2 (heredada del SPLAT! original).