added formulas

This commit is contained in:
2026-06-26 11:21:49 +03:00
parent d707e310dc
commit 70828f693e
6 changed files with 750 additions and 2 deletions
Binary file not shown.
Binary file not shown.
+8 -2
View File
@@ -47,6 +47,9 @@ def link_budget(request: LinkBudgetRequest, db: Session | None = None) -> LinkBu
)
atmospheric_db = atmospheric_loss_between(tx, rx, freq_hz)
active_diffraction_db = diffraction_db
active_atmospheric_db = atmospheric_db
if request.model == "manual":
propagation_db = 0.0
elif request.model == "itm":
@@ -70,6 +73,7 @@ def link_budget(request: LinkBudgetRequest, db: Session | None = None) -> LinkBu
request.frequency_mhz,
).fspl_db
)
active_diffraction_db = propagation_db
elif request.model == "p452":
propagation_db = (
p452_loss(
@@ -91,6 +95,8 @@ def link_budget(request: LinkBudgetRequest, db: Session | None = None) -> LinkBu
request.frequency_mhz,
).fspl_db
)
active_diffraction_db = propagation_db
active_atmospheric_db = 0.0
else:
raise NotImplementedError(f"{request.model} link model is not supported")
@@ -102,9 +108,9 @@ def link_budget(request: LinkBudgetRequest, db: Session | None = None) -> LinkBu
rx_gain_dbi=request.rx.gain_dbi,
sensitivity_dbm=request.rx.sensitivity_dbm,
frequency_mhz=request.frequency_mhz,
diffraction_db=diffraction_db + propagation_db,
diffraction_db=active_diffraction_db,
vegetation_db=vegetation_db,
atmospheric_db=atmospheric_db,
atmospheric_db=active_atmospheric_db,
fresnel_clear=los_result.los_clear,
)
geometric_obstructions = [
+100
View File
@@ -151,3 +151,103 @@ def test_link_viable_depends_on_margin_not_fresnel_quality(monkeypatch) -> None:
assert result.fresnel_quality == "blocked"
assert result.fresnel_clear is False
assert result.link_viable is True
def test_itm_link_budget_does_not_double_count_diffraction(monkeypatch) -> None:
monkeypatch.setattr(link_service, "vegetation_loss_along", lambda *args, **kwargs: 3.0)
monkeypatch.setattr(link_service, "atmospheric_loss_between", lambda *args, **kwargs: 2.0)
monkeypatch.setattr(link_service, "deygout", lambda *args, **kwargs: 99.0)
monkeypatch.setattr(
link_service,
"surface_profile_from_points",
lambda points, *args, **kwargs: SurfaceProfile(
distance_m=points[-1].distance_m,
samples=[
SurfaceSample(
i=index,
lat=point.lat,
lon=point.lon,
distance_m=point.distance_m,
ground_m=0,
building_m=0,
canopy_m=0,
surface_m=0,
)
for index, point in enumerate(points)
],
),
)
request = LinkBudgetRequest(
tx=LinkTx(lat=60.17, lon=24.94, height_agl=30, power_dbm=37, gain_dbi=8),
rx=LinkRx(lat=60.25, lon=25.10, height_agl=2, gain_dbi=2, sensitivity_dbm=-110),
frequency_mhz=433,
model="itm",
include_vegetation=True,
)
base = link_service.manual_link_budget(
request.tx,
request.rx,
request.tx.power_dbm,
request.tx.gain_dbi,
request.rx.gain_dbi,
request.rx.sensitivity_dbm,
request.frequency_mhz,
).fspl_db
monkeypatch.setattr(link_service, "itm_loss", lambda *args, **kwargs: base + 12.0)
result = link_service.link_budget(request)
assert result.diffraction_db == 12.0
assert result.atmospheric_db == 2.0
assert isclose(result.total_loss_db, result.fspl_db + 12.0 + 3.0 + 2.0)
def test_p452_link_budget_does_not_double_count_diffraction_or_atmosphere(monkeypatch) -> None:
monkeypatch.setattr(link_service, "vegetation_loss_along", lambda *args, **kwargs: 3.0)
monkeypatch.setattr(link_service, "atmospheric_loss_between", lambda *args, **kwargs: 99.0)
monkeypatch.setattr(link_service, "deygout", lambda *args, **kwargs: 88.0)
monkeypatch.setattr(
link_service,
"surface_profile_from_points",
lambda points, *args, **kwargs: SurfaceProfile(
distance_m=points[-1].distance_m,
samples=[
SurfaceSample(
i=index,
lat=point.lat,
lon=point.lon,
distance_m=point.distance_m,
ground_m=0,
building_m=0,
canopy_m=0,
surface_m=0,
)
for index, point in enumerate(points)
],
),
)
request = LinkBudgetRequest(
tx=LinkTx(lat=60.17, lon=24.94, height_agl=30, power_dbm=37, gain_dbi=8),
rx=LinkRx(lat=60.25, lon=25.10, height_agl=2, gain_dbi=2, sensitivity_dbm=-110),
frequency_mhz=433,
model="p452",
include_vegetation=True,
)
base = link_service.manual_link_budget(
request.tx,
request.rx,
request.tx.power_dbm,
request.tx.gain_dbi,
request.rx.gain_dbi,
request.rx.sensitivity_dbm,
request.frequency_mhz,
).fspl_db
monkeypatch.setattr(link_service, "p452_loss", lambda *args, **kwargs: base + 14.0)
result = link_service.link_budget(request)
assert result.diffraction_db == 14.0
assert result.atmospheric_db == 0.0
assert isclose(result.total_loss_db, result.fspl_db + 14.0 + 3.0)