use rfconversions::frequency::frequency_to_wavelength;
use std::f64::consts::PI;
#[doc(alias = "FSPL")]
#[doc(alias = "free space path loss")]
pub struct PathLoss {
pub frequency: f64,
pub distance: f64,
}
impl PathLoss {
#[doc(alias = "FSPL")]
#[must_use]
pub fn calculate(&self) -> f64 {
let wavelength: f64 = frequency_to_wavelength(self.frequency);
let distance_wavelength_ratio: f64 = self.distance / wavelength;
let free_space_path_loss: f64 = 20.0 * f64::log10(4.0 * PI * distance_wavelength_ratio);
free_space_path_loss
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn short_range_indoors() {
let base: f64 = 10.0;
let frequency: f64 = 60.0 * base.powf(9.0);
let distance: f64 = 5.0 * base.powf(1.0);
let free_space_path_loss: f64 = PathLoss {
frequency,
distance,
}
.calculate();
let rounded_to_4_decimal_places: f64 = (free_space_path_loss * 10000.0).round() / 10000.0;
assert_eq!(101.9902, rounded_to_4_decimal_places);
}
#[test]
fn leo_starlink_min() {
let base: f64 = 10.0;
let frequency: f64 = 14.0 * base.powf(9.0);
let distance: f64 = 340.0 * base.powf(3.0);
let free_space_path_loss: f64 = PathLoss {
frequency,
distance,
}
.calculate();
let rounded_to_4_decimal_places: f64 = (free_space_path_loss * 10000.0).round() / 10000.0;
assert_eq!(165.9999, rounded_to_4_decimal_places);
}
#[test]
fn meo_o3b_uplink() {
let base: f64 = 10.0;
let frequency: f64 = 28.0 * base.powf(9.0);
let distance: f64 = 8.062 * base.powf(6.0);
let free_space_path_loss: f64 = PathLoss {
frequency,
distance,
}
.calculate();
assert_eq!(199.51979972506842, free_space_path_loss);
}
#[test]
fn geo_galileo() {
let base: f64 = 10.0;
let frequency: f64 = 28.0 * base.powf(9.0);
let distance: f64 = 35.786 * base.powf(6.0);
let free_space_path_loss: f64 = PathLoss {
frequency,
distance,
}
.calculate();
assert_eq!(212.46520700065133, free_space_path_loss);
}
}