import math def friis_equation_with_ground_presence(h1, h2, d, freq, er=18): c = 299.972458 * 10**6 # Speed of light in m/s lambda_ = c / (freq * 10**6) # Wavelength in meters phi = math.atan((h1 + h2) / d) direct_wave = math.sqrt((h1 - h2) ** 2 + d ** 2) refl_wave = math.sqrt(d ** 2 + (h1 + h2) ** 2) gamma = (er * math.sin(phi) - math.sqrt(er - math.cos(phi) ** 2)) / (er * math.sin(phi) + math.sqrt(er - math.cos(phi) ** 2)) length_diff = refl_wave - direct_wave cos_phase_diff = math.cos(length_diff * 2 * math.pi / lambda_) * math.copysign(1, gamma) total_received_energy = ((lambda_ ** 2) / ((4 * math.pi * direct_wave) ** 2) + cos_phase_diff * ((lambda_ ** 2) / ((4 * math.pi * refl_wave) ** 2) * abs(gamma))) return 10 * math.log10(total_received_energy) def get_two_ray_ground_reflection_propagation_model_range(path_loss, freq, hTx, hRx): er = 18 for di in range(1, 200001): pr = friis_equation_with_ground_presence(hTx, hRx, di, freq, er) if pr < -path_loss: return di return 0 def get_log_normal_shadowing_propagation_model_range(path_loss): range_dict = {'min': 0, 'max': 0} PL0 = 71.84 n = 2.16 d0 = 15 std = 8.13 if path_loss < PL0: range_dict['min'] = 1 range_dict['max'] = 15 return range_dict range_dict['max'] = d0 * 10**((path_loss - PL0) / (10 * n)) range_dict['min'] = d0 * 10**((path_loss - std - PL0) / (10 * n)) if path_loss > PL0 + std else 1 return range_dict def get_nist_pap02_task6_propagation_model_range(path_loss, environment): range_dict = {'min': 0, 'max': 0} config_map = { 'Home': {'PL0': 12.5, 'n0': 4.2, 'd1': 11, 'n1': 7.6, 'variance': 3}, 'Office': {'PL0': 26.8, 'n0': 4.2, 'd1': 10, 'n1': 8.7, 'variance': 3.7}, 'Industrial': {'PL0': 29.4, 'n0': 3.4, 'd1': 1, 'n1': 3.4, 'variance': 6.3} } config = config_map.get(environment) if not config: return range_dict PL0, n0, d1, n1, variance = config.values() estim_dist = 10**((path_loss - PL0) / (10 * n0)) if path_loss - PL0 < 0: return range_dict PL1 = 10 * n0 * math.log10(d1) if estim_dist > d1: range_dict['max'] = d1 * 10**((path_loss - PL0 - PL1) / (10 * n1)) range_dict['min'] = d1 if path_loss - variance - PL0 - PL1 < 0 else \ d1 * 10**((path_loss - (3 * variance) - PL0 - PL1) / (10 * n1)) else: range_dict['max'] = 10**((path_loss - PL0) / (10 * n0)) range_dict['min'] = 0 if path_loss - variance - PL0 < 0 else \ 10**((path_loss - (3 * variance) - PL0) / (10 * n0)) return range_dict def calculate_distance_range(sensitivity, tx_power, tx_ant_gain, rx_ant_gain,enviroment): freq = 2440 # MHz hTx, hRx = 1, 1 # Heights in meters distance_min, distance_max = 0,0 if enviroment == "Outdoor": margin_min,margin_max = 15,20 # Margin set at default for the estimator pass_loss_min = tx_power + tx_ant_gain + rx_ant_gain - (sensitivity + margin_max ) pass_loss_max = tx_power + tx_ant_gain + rx_ant_gain - (sensitivity + margin_min ) distance_min = get_two_ray_ground_reflection_propagation_model_range(pass_loss_min, freq, hTx, hRx) distance_max = get_two_ray_ground_reflection_propagation_model_range(pass_loss_max, freq, hTx, hRx) return distance_min, distance_max elif enviroment == "Industrial": margin = 7 # default settings for this model range_min = 15 # range_max = 140 # pass_loss = tx_power + tx_ant_gain + rx_ant_gain - (sensitivity + margin) distance_dict = get_log_normal_shadowing_propagation_model_range(pass_loss) distance_min = distance_dict['min'] distance_max = distance_dict['max'] elif (enviroment == "Office") or (enviroment =="Home"): margin = 0 # default settings for this model range_min = 5 # range_max = 45 # pass_loss = tx_power + tx_ant_gain + rx_ant_gain - (sensitivity + margin) distance_dict = get_nist_pap02_task6_propagation_model_range(pass_loss,enviroment) distance_min = distance_dict['min'] distance_max = distance_dict['max'] if (distance_min < range_min): distance_min = range_min if (distance_min > range_max): distance_min =range_max if (distance_max >range_max): distance_max = range_max return distance_min, distance_max # Given cases: input: sensitivity / tx_power / tx_ant_gain / rx_ant_gain min_dis_val, max_dis_val = calculate_distance_range(-79,0,10,10,"Outdoor") print(f"Range_estimator result: Outdoor case: {min_dis_val}, {max_dis_val}") min_dis_val, max_dis_val = calculate_distance_range(-79,0,10,10,"Industrial") print(f"Range_estimator result: Industrial case: {min_dis_val}, {max_dis_val}") min_dis_val, max_dis_val = calculate_distance_range(-79,0,10,10,"Office") print(f"Range_estimator result: Office case: {min_dis_val}, {max_dis_val}") min_dis_val, max_dis_val = calculate_distance_range(-79,0,10,10,"Home") print(f"Range_estimator result: Home case: {min_dis_val}, {max_dis_val}")