mirror of
https://github.com/pablorevilla-meshtastic/meshview.git
synced 2026-03-04 23:27:46 +01:00
Updating anb fixing errors
This commit is contained in:
@@ -1,22 +1,29 @@
|
||||
import math
|
||||
from functools import lru_cache
|
||||
from typing import List, Tuple
|
||||
|
||||
from pyitm.itm import ITM
|
||||
try:
|
||||
from pyitm import itm
|
||||
|
||||
# ----------------------------
|
||||
# Config defaults (tune later)
|
||||
# ----------------------------
|
||||
DEFAULT_CLIMATE = 5 # Continental temperate
|
||||
DEFAULT_GROUND = 0.005 # Average ground conductivity
|
||||
DEFAULT_RELIABILITY = 0.5 # Median
|
||||
ITM_AVAILABLE = True
|
||||
except Exception:
|
||||
itm = None
|
||||
ITM_AVAILABLE = False
|
||||
|
||||
DEFAULT_CLIMATE = 5 # Continental temperate
|
||||
DEFAULT_GROUND = 0.005 # Average ground conductivity
|
||||
DEFAULT_EPS_DIELECT = 15.0
|
||||
DEFAULT_DELTA_H = 90.0
|
||||
DEFAULT_RELIABILITY = 0.5
|
||||
DEFAULT_MIN_DBM = -130.0
|
||||
DEFAULT_MAX_DBM = -80.0
|
||||
DEFAULT_THRESHOLD_DBM = -120.0
|
||||
EARTH_RADIUS_KM = 6371.0
|
||||
BEARING_STEP_DEG = 5
|
||||
|
||||
|
||||
def destination_point(lat, lon, bearing_deg, distance_km):
|
||||
"""
|
||||
Compute lat/lon from start point, bearing, distance
|
||||
"""
|
||||
def destination_point(
|
||||
lat: float, lon: float, bearing_deg: float, distance_km: float
|
||||
) -> tuple[float, float]:
|
||||
lat1 = math.radians(lat)
|
||||
lon1 = math.radians(lon)
|
||||
bearing = math.radians(bearing_deg)
|
||||
@@ -24,13 +31,12 @@ def destination_point(lat, lon, bearing_deg, distance_km):
|
||||
d = distance_km / EARTH_RADIUS_KM
|
||||
|
||||
lat2 = math.asin(
|
||||
math.sin(lat1) * math.cos(d)
|
||||
+ math.cos(lat1) * math.sin(d) * math.cos(bearing)
|
||||
math.sin(lat1) * math.cos(d) + math.cos(lat1) * math.sin(d) * math.cos(bearing)
|
||||
)
|
||||
|
||||
lon2 = lon1 + math.atan2(
|
||||
math.sin(bearing) * math.sin(d) * math.cos(lat1),
|
||||
math.cos(d) - math.sin(lat1) * math.sin(lat2)
|
||||
math.cos(d) - math.sin(lat1) * math.sin(lat2),
|
||||
)
|
||||
|
||||
return math.degrees(lat2), math.degrees(lon2)
|
||||
@@ -47,37 +53,94 @@ def compute_coverage(
|
||||
radius_km: float,
|
||||
step_km: float,
|
||||
reliability: float,
|
||||
) -> List[Tuple[float, float, float]]:
|
||||
"""
|
||||
Returns list of (lat, lon, rx_dbm)
|
||||
Uses ITM area mode (no terrain profile)
|
||||
"""
|
||||
|
||||
itm = ITM(
|
||||
climate=DEFAULT_CLIMATE,
|
||||
ground_conductivity=DEFAULT_GROUND,
|
||||
refractivity=301, # standard atmosphere
|
||||
freq_mhz=freq_mhz,
|
||||
tx_height_m=tx_height_m,
|
||||
rx_height_m=rx_height_m,
|
||||
polarization=1, # vertical
|
||||
reliability=reliability,
|
||||
)
|
||||
) -> list[tuple[float, float, float]]:
|
||||
if not ITM_AVAILABLE:
|
||||
return []
|
||||
|
||||
points = []
|
||||
|
||||
distance = step_km
|
||||
distance = max(step_km, 1.0)
|
||||
while distance <= radius_km:
|
||||
for bearing in range(0, 360, 5):
|
||||
for bearing in range(0, 360, BEARING_STEP_DEG):
|
||||
rx_lat, rx_lon = destination_point(lat, lon, bearing, distance)
|
||||
|
||||
# ITM returns path loss (dB)
|
||||
loss_db = itm.path_loss(distance_km=distance)
|
||||
|
||||
try:
|
||||
loss_db, _ = itm.area(
|
||||
ModVar=2,
|
||||
deltaH=DEFAULT_DELTA_H,
|
||||
tht_m=tx_height_m,
|
||||
rht_m=rx_height_m,
|
||||
dist_km=distance,
|
||||
TSiteCriteria=0,
|
||||
RSiteCriteria=0,
|
||||
eps_dielect=DEFAULT_EPS_DIELECT,
|
||||
sgm_conductivity=DEFAULT_GROUND,
|
||||
eno_ns_surfref=301,
|
||||
frq_mhz=freq_mhz,
|
||||
radio_climate=DEFAULT_CLIMATE,
|
||||
pol=1,
|
||||
pctTime=reliability,
|
||||
pctLoc=0.5,
|
||||
pctConf=0.5,
|
||||
)
|
||||
except itm.InputError:
|
||||
continue
|
||||
rx_dbm = tx_dbm - loss_db
|
||||
|
||||
points.append((rx_lat, rx_lon, rx_dbm))
|
||||
|
||||
distance += step_km
|
||||
|
||||
return points
|
||||
|
||||
|
||||
@lru_cache(maxsize=512)
|
||||
def compute_perimeter(
|
||||
lat: float,
|
||||
lon: float,
|
||||
freq_mhz: float,
|
||||
tx_dbm: float,
|
||||
tx_height_m: float,
|
||||
rx_height_m: float,
|
||||
radius_km: float,
|
||||
step_km: float,
|
||||
reliability: float,
|
||||
threshold_dbm: float,
|
||||
) -> list[tuple[float, float]]:
|
||||
if not ITM_AVAILABLE:
|
||||
return []
|
||||
|
||||
perimeter = []
|
||||
distance = max(step_km, 1.0)
|
||||
for bearing in range(0, 360, BEARING_STEP_DEG):
|
||||
last_point = None
|
||||
dist = distance
|
||||
while dist <= radius_km:
|
||||
try:
|
||||
loss_db, _ = itm.area(
|
||||
ModVar=2,
|
||||
deltaH=DEFAULT_DELTA_H,
|
||||
tht_m=tx_height_m,
|
||||
rht_m=rx_height_m,
|
||||
dist_km=dist,
|
||||
TSiteCriteria=0,
|
||||
RSiteCriteria=0,
|
||||
eps_dielect=DEFAULT_EPS_DIELECT,
|
||||
sgm_conductivity=DEFAULT_GROUND,
|
||||
eno_ns_surfref=301,
|
||||
frq_mhz=freq_mhz,
|
||||
radio_climate=DEFAULT_CLIMATE,
|
||||
pol=1,
|
||||
pctTime=reliability,
|
||||
pctLoc=0.5,
|
||||
pctConf=0.5,
|
||||
)
|
||||
except itm.InputError:
|
||||
dist += step_km
|
||||
continue
|
||||
|
||||
rx_dbm = tx_dbm - loss_db
|
||||
if rx_dbm >= threshold_dbm:
|
||||
last_point = destination_point(lat, lon, bearing, dist)
|
||||
dist += step_km
|
||||
|
||||
if last_point:
|
||||
perimeter.append(last_point)
|
||||
|
||||
return perimeter
|
||||
|
||||
Reference in New Issue
Block a user