From 3c432b9112d8f22a824044c15c30621b2b91ed3c Mon Sep 17 00:00:00 2001 From: ApsisRS contributors Date: Fri, 2 Oct 2026 01:29:47 +0800 Subject: [PATCH] docs: bilingual comments for the link budget and antenna patterns --- crates/rf/apsis-antenna/src/pattern.rs | 102 +++++++++++++++++++++++++ crates/rf/apsis-link/src/budget.rs | 93 ++++++++++++++++++++++ 2 files changed, 195 insertions(+) diff --git a/crates/rf/apsis-antenna/src/pattern.rs b/crates/rf/apsis-antenna/src/pattern.rs index dc463d4..bc8ecdd 100644 --- a/crates/rf/apsis-antenna/src/pattern.rs +++ b/crates/rf/apsis-antenna/src/pattern.rs @@ -32,6 +32,26 @@ use core::f64::consts::PI; /// /// Returns `None` when the peak gain has no decibel form, or when the beam /// width or floor is not positive and finite. +/// +/// 返回给定峰值增益与半功率波束宽度时,天线在偏离视轴某角度处的增益。 +/// +/// 这是若干干扰评估所用的角平方模型,以半功率波束宽度表达,使任何天线 +/// 都能由链路预算手头的两个数描述。以分贝计, +/// +/// ```text +/// G(theta) = G_peak - min(12 (theta / theta_0)^2, G_floor) +/// ``` +/// +/// 其中 `theta_0` 是半功率波束宽度,`G_floor` 是所要降到的旁瓣电平, +/// 相对峰值以分贝计。角平方律来自均匀照射孔径 Airy 图案的首项,直到 +/// 第一旁瓣都是良好近似。 +/// +/// 系数十二的选取使衰减在 `theta_0 / 2` 处达到三分贝,这正是半功率 +/// 波束宽度的定义。在建议书适用之处,应改用取自建议书的图案:ITU-R +/// S.465 图案见 [`reference_pattern_gain`](crate::reference_pattern_gain), +/// 它在主瓣上以及旁瓣区的形状上都与本模型不同。 +/// +/// 峰值增益没有分贝形式,或波束宽度、底限非正且非有限时返回 `None`。 pub fn off_axis_attenuation( peak: Gain, beam_width: f64, @@ -82,6 +102,33 @@ pub fn off_axis_attenuation( /// /// Source: ITU, *Radio Regulations*, Appendix 8, which reproduces the /// reference pattern of ITU-R Recommendation S.465. +/// +/// 返回天线在偏离视轴某角度处不得超出的增益,相对各向同性辐射体以分贝 +/// 计。 +/// +/// 这是《无线电规则》附录 8 的参考方向图,用于检查地球站是否满足保护 +/// 邻近卫星的偏轴发射限值。该方向图是分段的: +/// +/// ```text +/// for D/lambda >= 100: +/// G = 29 - 25 log10(theta) for 1 <= theta < 36 degrees +/// G = -10 for 36 <= theta <= 180 degrees +/// for D/lambda < 100: +/// G = 32 - 25 log10(theta) for 1 <= theta < 48 degrees +/// G = -10 for 48 <= theta <= 180 degrees +/// G = 32 - 25 log10(48) for theta < 1 degree +/// ``` +/// +/// 角度以弧度计,口径与波长之比决定适用哪一支,因为小天线主瓣更宽, +/// 故须受控的角度范围也更大。 +/// +/// 本函数返回限值,即允许的最大增益。当实际偏轴增益不高于它时天线即 +/// 合规。 +/// +/// 角度为负、比值为非正,或角度非有限时返回 `None`。 +/// +/// 出处:ITU,*Radio Regulations*,附录 8,其中再现了 ITU-R 建议书 +/// S.465 的参考方向图。 pub fn mask_gain(diameter_over_wavelength: f64, off_axis_angle: f64) -> Option { if !diameter_over_wavelength.is_finite() || diameter_over_wavelength <= 0.0 { return None; @@ -93,6 +140,7 @@ pub fn mask_gain(diameter_over_wavelength: f64, off_axis_angle: f64) -> Option= 100.0; // The break point is where the pattern reaches its floor, and the cap // angle is where the falling branch begins. + // 折点是方向图到达其底限之处,封顶角是下降支开始之处。 let (cap_angle, floor_angle) = if large_aperture { (1.0_f64.to_radians(), 36.0_f64.to_radians()) } else { @@ -103,6 +151,7 @@ pub fn mask_gain(diameter_over_wavelength: f64, off_axis_angle: f64) -> Option Option Option { match self { Self::Parabolic { @@ -156,6 +230,8 @@ impl Pattern { /// Returns the half power beam width of this pattern at the given /// wavelength, in radians. + /// + /// 返回本方向图在给定波长处的半功率波束宽度,单位为弧度。 pub fn beam_width(self, wavelength: f64) -> Option { match self { Self::Parabolic { @@ -177,6 +253,11 @@ impl Pattern { /// /// This is the form a link budget needs: the two numbers that describe the /// beam, plus the model that gives the gain at any angle from boresight. +/// +/// 由峰值增益与半功率波束宽度构造的增益方向图。 +/// +/// 这是链路预算所需的形式:描述波束的两个数,加上给出偏离视轴任意角度 +/// 处增益的模型。 #[derive(Debug, Clone, Copy, PartialEq)] pub struct ElementPattern { /// The peak gain on boresight. @@ -184,12 +265,16 @@ pub struct ElementPattern { /// The half power beam width, in radians. pub beam_width: f64, /// The sidelobe floor, in decibels below the peak. + /// + /// 旁瓣底限,相对峰值以分贝计。 pub floor_db: f64, } impl Default for ElementPattern { /// Returns a pattern for an isotropic antenna, with a floor that makes /// the attenuation zero in every direction. + /// + /// 返回各向同性天线的方向图,其底限使各方向的衰减为零。 fn default() -> Self { Self { peak: Gain::ISOTROPIC, @@ -205,6 +290,11 @@ impl ElementPattern { /// The sidelobe floor is set to the value of the Radio Regulations /// reference pattern, 32 decibels below the peak, which is a common /// worst case for a small Earth station. + /// + /// 由峰值增益与半功率波束宽度创建方向图。 + /// + /// 旁瓣底限被设为《无线电规则》参考方向图的值,即相对峰值低 + /// 32 分贝,这是小型地球站常见的坏情形。 pub const fn new(peak: Gain, beam_width: f64) -> Self { Self { peak, @@ -216,6 +306,10 @@ impl ElementPattern { /// Creates a pattern from a parabolic aperture at a wavelength. /// /// Returns `None` when the aperture or wavelength is not usable. + /// + /// 由某波长处的抛物面孔径创建方向图。 + /// + /// 孔径或波长不可用时返回 `None`。 pub fn from_parabolic(aperture: ParabolicAperture, wavelength: f64) -> Option { Some(Self { peak: aperture.peak_gain(wavelength)?, @@ -225,6 +319,8 @@ impl ElementPattern { } /// Returns this pattern with a different sidelobe floor. + /// + /// 返回本方向图的一个具有不同旁瓣底限的副本。 pub const fn with_floor(mut self, floor_db: f64) -> Self { self.floor_db = floor_db; self @@ -234,6 +330,10 @@ impl ElementPattern { /// /// Returns `None` when the pattern is not usable or the angle is not /// finite. + /// + /// 返回偏离视轴某角度处的增益。 + /// + /// 方向图不可用或角度非有限时返回 `None`。 pub fn gain_at(self, off_axis_angle: f64) -> Option { let attenuation = off_axis_attenuation(self.peak, self.beam_width, off_axis_angle, self.floor_db)?; @@ -242,6 +342,8 @@ impl ElementPattern { /// Returns `true` when the beam width and floor describe a usable /// pattern. + /// + /// 当波束宽度与底限描述一个可用方向图时返回 `true`。 pub fn is_valid(self) -> bool { self.peak.dbi().is_some() && self.beam_width.is_finite() diff --git a/crates/rf/apsis-link/src/budget.rs b/crates/rf/apsis-link/src/budget.rs index a15654c..72a4573 100644 --- a/crates/rf/apsis-link/src/budget.rs +++ b/crates/rf/apsis-link/src/budget.rs @@ -6,11 +6,17 @@ use apsis_rf::{Decibel, Gain, Power, free_space_path_loss, wavelength}; /// The geometric part of a link: how far apart the terminals are and at what /// frequency they operate. +/// +/// 链路的几何部分:两端相距多远,以及在什么频率上工作。 #[derive(Debug, Clone, Copy, PartialEq)] pub struct LinkGeometry { /// The distance between the terminals, in meters. + /// + /// 两端之间的距离,单位为米。 pub distance: f64, /// The carrier frequency, in hertz. + /// + /// 载波频率,单位为赫兹。 pub frequency: f64, } @@ -18,11 +24,17 @@ impl LinkGeometry { /// Returns the free space path loss for this geometry. /// /// Returns `None` when the distance or frequency is not usable. + /// + /// 返回该几何的自由空间路径损耗。 + /// + /// 距离或频率不可用时返回 `None`。 pub fn path_loss(self) -> Option { free_space_path_loss(self.distance, self.frequency) } /// Returns `true` when the geometry is usable. + /// + /// 当该几何可用时返回 `true`。 pub fn is_valid(self) -> bool { self.distance.is_finite() && self.distance > 0.0 @@ -36,25 +48,46 @@ impl LinkGeometry { /// The losses are given as positive decibel values that are subtracted, /// which is the convention in link budgets: a three decibel loss is entered /// as three decibels, not as minus three. +/// +/// 无线电链路一个方向的完整链路预算。 +/// +/// 各损耗以被减去的正分贝值给出,这是链路预算中的约定:三分贝的损耗记 +/// 为三,而非负三。 #[derive(Debug, Clone, Copy, PartialEq)] pub struct LinkBudget { /// The power delivered to the transmit antenna, in watts. + /// + /// 送到发射天线的功率,单位为瓦特。 pub transmit_power: Power, /// The transmit antenna gain on the relevant path. + /// + /// 相关路径上的发射天线增益。 pub transmit_gain: Gain, /// Every loss between the transmitter and the transmit antenna, as a /// positive decibel value. + /// + /// 发射机与发射天线之间的每一项损耗,为正分贝值。 pub transmit_loss: Decibel, /// The receive antenna gain on the relevant path. + /// + /// 相关路径上的接收天线增益。 pub receive_gain: Gain, /// Every loss between the receive antenna and the receiver input, as a /// positive decibel value. + /// + /// 接收天线与接收机输入之间的每一项损耗,为正分贝值。 pub receive_loss: Decibel, /// The system noise temperature referred to the receiver input. + /// + /// 折算到接收机输入端的系统噪声温度。 pub system_temperature: NoiseTemperature, /// The receiver noise bandwidth, in hertz. + /// + /// 接收机噪声带宽,单位为赫兹。 pub bandwidth: f64, /// The distance and frequency of the link. + /// + /// 链路的距离与频率。 pub geometry: LinkGeometry, } @@ -102,6 +135,13 @@ impl LinkBudget { /// rather than of the receiver. /// /// Returns `None` when the system temperature is not usable. + /// + /// 返回接收机输入端的噪声功率密度,单位为瓦特每赫兹。 + /// + /// 这是 `k T`,即把噪声温度换算为单位带宽的功率。它不依赖于接收机 + /// 带宽,这正是载噪密度比成为链路属性而非接收机属性的原因。 + /// + /// 系统温度不可用时返回 `None`。 pub fn noise_density(&self) -> Option { if !self.system_temperature.is_valid() { return None; @@ -127,6 +167,7 @@ impl LinkBudget { } // The ratio is a power ratio, and the numerator and denominator // carry different bandwidths, so the ratio is formed directly. + // 该比值是功率比,且分子与分母带有不同的带宽,故直接构成该比。 let ratio = carrier.watts() / density; Decibel::from_ratio(ratio) } @@ -156,6 +197,13 @@ impl LinkBudget { /// /// Returns `None` when the data rate is not positive, or when the /// carrier to noise density ratio is not usable. + /// + /// 返回某数据速率下每比特能量与噪声密度之比。 + /// + /// 它是载噪密度比减去数据速率,因为每比特能量是载波功率除以比特 + /// 速率。 + /// + /// 数据速率非正,或载噪密度比不可用时返回 `None`。 pub fn energy_per_bit_over_noise(&self, data_rate: f64) -> Option { if !data_rate.is_finite() || data_rate <= 0.0 { return None; @@ -172,6 +220,13 @@ impl LinkBudget { /// Earth, the Sun, or a rain cell in the beam. /// /// Returns `None` when the added temperature is not usable. + /// + /// 返回接收天线看到给定温度的噪声源所引起的系统噪声上升。 + /// + /// 天线噪声按功率加到系统温度上,在温度上即求和。这是用于计入波束中 + /// 的地球、太阳或雨胞的形式。 + /// + /// 所加温度不可用时返回 `None`。 pub fn with_added_noise(&self, added: NoiseTemperature) -> Option { if !added.is_valid() { return None; @@ -185,11 +240,17 @@ impl LinkBudget { /// Returns the wavelength of the carrier, in meters. /// /// Returns `None` when the frequency is not usable. + /// + /// 返回载波的波长,单位为米。 + /// + /// 频率不可用时返回 `None`。 pub fn carrier_wavelength(&self) -> Option { wavelength(self.geometry.frequency) } /// Returns `true` when every input describes a usable link. + /// + /// 当每个输入都描述一条可用链路时返回 `true`。 pub fn is_valid(&self) -> bool { self.transmit_power.is_valid() && self.transmit_gain.dbi().is_some() @@ -204,11 +265,17 @@ impl LinkBudget { } /// The result of comparing a link against a requirement. +/// +/// 把链路与某项要求比较所得的结果。 #[derive(Debug, Clone, Copy, PartialEq)] pub struct LinkMargin { /// The ratio the link achieves, in decibels. + /// + /// 该链路所达到的比,单位为分贝。 pub achieved: Decibel, /// The ratio the link requires, in decibels. + /// + /// 该链路所要求的比,单位为分贝。 pub required: Decibel, } @@ -217,11 +284,17 @@ impl LinkMargin { /// /// A positive margin means the link closes with room to spare; a /// negative margin means it does not. + /// + /// 返回余量,单位为分贝。 + /// + /// 正余量意味着链路闭合并有余,负余量意味着不能闭合。 pub fn margin(self) -> Decibel { self.achieved - self.required } /// Returns `true` when the margin is not negative. + /// + /// 当余量非负时返回 `true`。 pub fn closes(self) -> bool { self.margin().db() >= 0.0 } @@ -230,6 +303,10 @@ impl LinkMargin { /// Returns the margin between an achieved ratio and a required one. /// /// This is the comparison that decides whether a link closes. +/// +/// 返回所达到的比与所要求的比之间的余量。 +/// +/// 这一比较决定链路是否闭合。 pub fn link_margin(achieved: Decibel, required: Decibel) -> LinkMargin { LinkMargin { achieved, required } } @@ -240,6 +317,12 @@ pub fn link_margin(achieved: Decibel, required: Decibel) -> LinkMargin { /// [`LinkBudget::carrier_to_noise_density`]. /// /// Returns `None` when the budget is not usable. +/// +/// 返回某预算的载噪密度比。 +/// +/// 这是 [`LinkBudget::carrier_to_noise_density`] 的自由函数形式。 +/// +/// 预算不可用时返回 `None`。 pub fn carrier_to_noise_density(budget: &LinkBudget) -> Option { budget.carrier_to_noise_density() } @@ -256,6 +339,16 @@ pub fn carrier_to_noise_density(budget: &LinkBudget) -> Option { /// the logarithm of the temperature, which is the form usually quoted. /// /// Returns `None` when the gain or temperature is not usable. +/// +/// 返回接收链路的增益与系统温度之比,单位为每开尔文。 +/// +/// 该品质因数写作 `G / T`,是比较接收站的标准方式。它把接收天线增益与 +/// 系统噪声温度结合起来,故天线更大、接收机更安静的站得分更高。 +/// +/// 以分贝表示时,`G / T` 是接收增益(以 dBi 计)减去温度的十倍对数, +/// 这是通常引用的形式。 +/// +/// 增益或温度不可用时返回 `None`。 pub fn gain_to_temperature(gain: Gain, temperature: NoiseTemperature) -> Option { if !temperature.is_valid() || temperature.kelvin() <= 0.0 { return None;