Files
rfcp/backend/app/services/indoor_service.py

83 lines
2.6 KiB
Python

import math
class IndoorService:
"""ITU-R P.2109 building entry loss model"""
# Building Entry Loss (BEL) by construction type at 2 GHz
# Format: (median_loss_dB, std_dev_dB)
BUILDING_TYPES = {
"none": (0.0, 0.0), # Outdoor only
"light": (8.0, 4.0), # Wood frame, large windows
"medium": (15.0, 6.0), # Brick, standard windows
"heavy": (22.0, 8.0), # Concrete, small windows
"basement": (30.0, 10.0), # Underground
"vehicle": (6.0, 3.0), # Inside car
"train": (20.0, 5.0), # Inside train
}
# Frequency correction factor (dB per octave above 2 GHz)
FREQ_CORRECTION = 2.5
def calculate_indoor_loss(
self,
frequency_mhz: float,
building_type: str = "medium",
floor_number: int = 0,
depth_m: float = 0.0,
) -> float:
"""
Calculate building entry/indoor penetration loss
Args:
frequency_mhz: Frequency in MHz
building_type: Type of building construction
floor_number: Floor number (0=ground, negative=basement)
depth_m: Distance from exterior wall in meters
Returns:
Loss in dB
"""
if building_type == "none":
return 0.0
base_loss, _ = self.BUILDING_TYPES.get(building_type, (15.0, 6.0))
# Frequency correction
freq_ghz = frequency_mhz / 1000
if freq_ghz > 2.0:
octaves = math.log2(freq_ghz / 2.0)
freq_correction = self.FREQ_CORRECTION * octaves
else:
freq_correction = 0.0
# Floor correction (higher floors = less loss due to better angle)
if floor_number > 0:
floor_correction = -1.5 * min(floor_number, 10)
elif floor_number < 0:
# Basement - additional loss
floor_correction = 5.0 * abs(floor_number)
else:
floor_correction = 0.0
# Depth correction (signal attenuates inside building)
# Approximately 0.5 dB per meter for first 10m
depth_correction = 0.5 * min(depth_m, 20)
total_loss = base_loss + freq_correction + floor_correction + depth_correction
return max(0.0, min(total_loss, 50.0)) # Clamp 0-50 dB
def calculate_outdoor_to_indoor_coverage(
self,
outdoor_rsrp: float,
building_type: str,
frequency_mhz: float,
) -> float:
"""Calculate expected indoor RSRP from outdoor signal"""
indoor_loss = self.calculate_indoor_loss(frequency_mhz, building_type)
return outdoor_rsrp - indoor_loss
indoor_service = IndoorService()