From 172ef61c06f329cb023f39fbb8f1eb7cc2e04c10 Mon Sep 17 00:00:00 2001 From: ApsisRS contributors Date: Fri, 2 Oct 2026 01:52:26 +0800 Subject: [PATCH] docs: bilingual comments for the dump examples --- crates/apsis-rs/examples/dump_coverage.rs | 42 ++++++++++++++++++++ crates/apsis-rs/examples/dump_gas.rs | 5 +++ crates/apsis-rs/examples/dump_gas_exact.rs | 4 ++ crates/apsis-rs/examples/dump_geodesy.rs | 6 +++ crates/apsis-rs/examples/dump_iau2000.rs | 29 ++++++++++++++ crates/apsis-rs/examples/dump_kepler.rs | 46 ++++++++++++++++++++++ crates/apsis-rs/examples/dump_link.rs | 16 ++++++++ crates/apsis-rs/examples/dump_orbit.rs | 19 +++++++++ crates/apsis-rs/examples/dump_p839.rs | 4 ++ crates/apsis-rs/examples/dump_rain.rs | 6 +++ crates/apsis-rs/examples/dump_rain_path.rs | 5 +++ crates/apsis-rs/examples/dump_s465.rs | 6 +++ crates/apsis-rs/examples/dump_teme.rs | 8 ++++ crates/apsis-rs/examples/dump_time.rs | 17 ++++++++ crates/apsis-rs/examples/dump_tle.rs | 31 +++++++++++++++ 15 files changed, 244 insertions(+) diff --git a/crates/apsis-rs/examples/dump_coverage.rs b/crates/apsis-rs/examples/dump_coverage.rs index 73eca5f..a8ce8ca 100644 --- a/crates/apsis-rs/examples/dump_coverage.rs +++ b/crates/apsis-rs/examples/dump_coverage.rs @@ -9,6 +9,15 @@ //! higher orbit, where it is large; the equatorial and polar cases; and a //! zero mask, where the footprint reaches the horizon. //! +//! 写出本工作区为一组用例计算的覆盖几何。 +//! +//! 输出是标准输出上的 CSV,带一行表头。它由 +//! `validation/python/constellation/check_coverage.py` 消费,后者从球面三角形 +//! 关系重算相同的量并比较。 +//! +//! 各用例的选取跨越了有意思的几何:低仰角遮蔽的低轨,其覆盖区相对地球很小; +//! 更高的轨道,其覆盖区很大;赤道与极地情形;以及零遮蔽,其覆盖区直到地平。 +//! //! Usage: //! //! ```text @@ -27,15 +36,28 @@ use core::f64::consts::PI; /// The coverage geometry is spherical, so a single radius is used. The /// value comes from the shared constants rather than being repeated, so a /// change to the ellipsoid reaches here. +/// +/// WGS 84 赤道半径,单位为千米。 +/// +/// 覆盖几何是球面的,故只用一个半径。该值来自共享常量而非重复书写,故椭球的 +/// 改动会传到这里。 const BODY_RADIUS_KM: f64 = apsis_core::constant::EARTH_EQUATORIAL_RADIUS; /// One coverage case: an orbital radius and an elevation mask. +/// +/// 一个覆盖用例:一个轨道半径与一个仰角遮蔽。 struct Case { /// A name for the case, so a failure in the report is readable. + /// + /// 用例的名称,使报告中的失败可读。 name: &'static str, /// The geocentric radius of the satellite, in kilometers. + /// + /// 卫星的地心半径,单位为千米。 satellite_radius_km: f64, /// The elevation mask at the ground point, in degrees. + /// + /// 地面点处的仰角遮蔽,单位为度。 elevation_mask_degrees: f64, } @@ -44,6 +66,11 @@ struct Case { /// The satellite radii span a low Earth orbit, two higher altitudes, and a /// geostationary one. The masks span the horizon, a typical station mask, and /// a strict one. +/// +/// 被检查的各用例。 +/// +/// 卫星半径跨越低轨、两个更高高度以及一个地球静止轨道。遮蔽跨越地平、典型 +/// 地面站遮蔽,以及一个严格遮蔽。 const CASES: &[Case] = &[ Case { name: "leo_low_mask", @@ -83,11 +110,19 @@ const CASES: &[Case] = &[ /// is fed back through `earth_central_angle`, so the pair must compose to the /// identity. The angles span zero to a little past the largest footprint the /// cases produce. +/// +/// 一组用于反解关系检查的中心角,单位为度。 +/// +/// 每个都被送入 `elevation_from_central_angle`,其返回的仰角经 +/// `earth_central_angle` 送回,故这一对必须合成为恒等。各角从零到略超过各用例 +/// 所产生的最大覆盖区。 const CENTRAL_ANGLES_DEGREES: &[f64] = &[0.0, 1.0, 5.0, 15.0, 30.0, 45.0, 60.0, 75.0]; fn main() { // The header names every column so that the Python side can read by name // rather than by position. + // + // 表头为每一列命名,使 Python 侧可以按名而非按位置读取。 println!( "case,satellite_radius_km,body_radius_km,elevation_mask_rad,\ nadir_rad,central_rad,slant_range_km,footprint_central_rad,\ @@ -127,6 +162,8 @@ fn main() { // The inverse relation, written with its own header so the Python side // can tell the two blocks apart by the first column. + // + // 反解关系,带上它自己的表头,使 Python 侧可以按第一列区分两个块。 println!(); println!("inverse_central_degrees,elevation_rad,round_trip_central_degrees"); for degrees in CENTRAL_ANGLES_DEGREES { @@ -134,6 +171,9 @@ fn main() { // Use the equatorial radius as the satellite radius for the inverse // check, so the geometry is the degenerate one where the elevation is // always zero. A more useful check uses a satellite altitude. + // + // 反解检查把赤道半径用作卫星半径,故几何是退化的那种,其中仰角恒为零。更 + // 有用的检查要用卫星高度。 let satellite_radius = BODY_RADIUS_KM + 550.0; let Ok(elevation) = elevation_from_central_angle(satellite_radius, BODY_RADIUS_KM, central).ok_or(()) @@ -141,6 +181,8 @@ fn main() { // Beyond the horizon the inverse has no solution, which is // reported as an empty row rather than skipped, so the count of // rows stays fixed. + // + // 在地平之外反解无解,故报告为一个空行而非跳过,使行数保持固定。 println!("{degrees},,"); continue; }; diff --git a/crates/apsis-rs/examples/dump_gas.rs b/crates/apsis-rs/examples/dump_gas.rs index 45be3d1..58a179f 100644 --- a/crates/apsis-rs/examples/dump_gas.rs +++ b/crates/apsis-rs/examples/dump_gas.rs @@ -1,6 +1,8 @@ //! Writes the specific and zenith gaseous attenuation computed by this //! workspace, for cross-checking against ITU-R P.676-12. //! +//! 写出本工作区计算的比与天顶气体衰减,用于对照 ITU-R P.676-12 交叉核对。 +//! //! Usage: //! //! ```text @@ -15,6 +17,9 @@ use apsis_atmosphere::{ /// The frequencies sampled, in gigahertz. They span the oxygen complex near /// 60 GHz, the water vapour lines at 22.235 and 183.31 GHz, and the windows /// between them. +/// +/// 所采样的频率,单位为吉赫兹。它们跨越 60 GHz 附近的氧复合体、22.235 与 +/// 183.31 GHz 的水汽线,以及其间的窗口。 const FREQUENCIES_GHZ: &[f64] = &[ 1.0, 2.0, 4.0, 6.0, 10.0, 12.0, 15.0, 20.0, 22.235, 30.0, 40.0, 50.0, 60.0, 70.0, 100.0, 118.0, 183.0, 300.0, diff --git a/crates/apsis-rs/examples/dump_gas_exact.rs b/crates/apsis-rs/examples/dump_gas_exact.rs index eae3a5d..8db4481 100644 --- a/crates/apsis-rs/examples/dump_gas_exact.rs +++ b/crates/apsis-rs/examples/dump_gas_exact.rs @@ -1,6 +1,8 @@ //! Writes the exact slant path gaseous attenuation computed by this //! workspace, for cross-checking against ITU-R P.676-12. //! +//! 写出本工作区计算的精确斜路径气体衰减,用于对照 ITU-R P.676-12 交叉核对。 +//! //! Usage: //! //! ```text @@ -12,6 +14,8 @@ use apsis_atmosphere::{Atmosphere, slant_path_attenuation_exact}; /// The scenarios sampled, as frequency in gigahertz and elevation in /// degrees. +/// +/// 所采样的场景,以吉赫兹计的频率与以度计的仰角。 const SCENARIOS: &[(f64, f64)] = &[ (12.0, 90.0), (12.0, 30.0), diff --git a/crates/apsis-rs/examples/dump_geodesy.rs b/crates/apsis-rs/examples/dump_geodesy.rs index bc8ffa2..6ae8f74 100644 --- a/crates/apsis-rs/examples/dump_geodesy.rs +++ b/crates/apsis-rs/examples/dump_geodesy.rs @@ -5,6 +5,12 @@ //! by `validation/python/coord/check_geodetic.py`, which recomputes the same //! positions with a reference implementation and compares the two. //! +//! 写出一个大地位置网格,以及本工作区为它们计算的地固直角坐标。 +//! +//! 输出是标准输出上的 CSV,带一行表头。它由 +//! `validation/python/coord/check_geodetic.py` 消费,后者用参考实现重算相同的 +//! 位置并比较二者。 +//! //! Usage: //! //! ```text diff --git a/crates/apsis-rs/examples/dump_iau2000.rs b/crates/apsis-rs/examples/dump_iau2000.rs index bced8e6..5235783 100644 --- a/crates/apsis-rs/examples/dump_iau2000.rs +++ b/crates/apsis-rs/examples/dump_iau2000.rs @@ -1,6 +1,8 @@ //! Writes the IAU 2000/2006 Earth orientation quantities computed by this //! workspace, for cross-checking against ERFA. //! +//! 写出本工作区计算的 IAU 2000/2006 地球定向量,用于对照 ERFA 交叉核对。 +//! //! Usage: //! //! ```text @@ -17,20 +19,31 @@ use apsis_math::Mat3; /// The Modified Julian Dates sampled. They span from 1970 to 2050 so that /// the precession is exercised over a range of a century. +/// +/// 所采样的约化儒略日。它们从 1970 到 2050,使岁差在一个世纪的跨度上被 +/// 检验。 const MJD: &[f64] = &[ 40_587.0, 51_544.5, 53_000.0, 55_000.0, 57_000.0, 58_000.0, 60_000.0, 62_000.0, ]; /// The Terrestrial Time offset from TAI, in seconds. +/// +/// 地球时相对 TAI 的偏移,单位为秒。 const TT_MINUS_TAI: f64 = 32.184; /// The TAI minus UTC offset used for this check, in seconds. It is the value /// in force from 2017 onward. +/// +/// 本检查所用的 TAI 减 UTC 偏移,单位为秒。它是自 2017 年起生效的值。 const TAI_MINUS_UTC: f64 = 37.0; /// Returns the TT Julian date for a Modified Julian Date on the UTC scale. +/// +/// 返回 UTC 时标上某约化儒略日对应的 TT 儒略日。 fn tt_julian_date(utc_mjd: f64) -> f64 { // TAI = UTC + 37, TT = TAI + 32.184, so TT = UTC + 69.184 seconds. + // + // TAI = UTC + 37,TT = TAI + 32.184,故 TT = UTC + 69.184 秒。 utc_mjd + 2_400_000.5 + (TT_MINUS_TAI + TAI_MINUS_UTC) / 86_400.0 } @@ -41,19 +54,27 @@ fn main() { let t = (tt - 2_451_545.0) / 36_525.0; // The obliquity, in radians. + // + // 黄赤交角,单位为弧度。 println!("{mjd},obliquity,0,{:.17e}", mean_obliquity(t)); // The nutation, from the IAU 2000A model. + // + // 章动,取自 IAU 2000A 模型。 let nutation = nutation_2000a(t); println!("{mjd},nutation_longitude_a,0,{:.17e}", nutation.longitude); println!("{mjd},nutation_obliquity_a,0,{:.17e}", nutation.obliquity); // The nutation with the IAU 2006 adjustment. + // + // 施加 IAU 2006 调整后的章动。 let adjusted = nutation_2000a_with_2006_adjustment(t); println!("{mjd},nutation_longitude_06a,0,{:.17e}", adjusted.longitude); println!("{mjd},nutation_obliquity_06a,0,{:.17e}", adjusted.obliquity); // The four precession angles. + // + // 四个岁差角。 let angles = precession_angles(t); println!("{mjd},precession_gamma_bar,0,{:.17e}", angles.gamma_bar); println!("{mjd},precession_phi_bar,0,{:.17e}", angles.phi_bar); @@ -62,6 +83,8 @@ fn main() { // The bias-precession-nutation matrix, which carries the celestial // reference frame to the true equator and equinox of date. + // + // 偏差-岁差-章动矩阵,它把天球参考系带到该日的真赤道与真春分点。 let bpn = bias_precession_nutation_matrix(t); for row in 0..3 { for column in 0..3 { @@ -71,12 +94,16 @@ fn main() { } // Greenwich apparent sidereal time, in radians. + // + // 格林尼治视恒星时,单位为弧度。 println!( "{mjd},gast,0,{:.17e}", greenwich_apparent_sidereal_time(tt, tt) ); // The celestial-to-terrestrial matrix, with zero polar motion. + // + // 天球到地球坐标系矩阵,极移为零。 let matrix = celestial_to_terrestrial_matrix(tt, tt, PolarMotion::NONE); for row in 0..3 { for column in 0..3 { @@ -88,5 +115,7 @@ fn main() { } /// Keeps the matrix type in scope for the documentation build. +/// +/// 为使文档构建保持在作用域内而保留矩阵类型。 #[allow(dead_code)] fn _uses_matrix(_matrix: Mat3) {} diff --git a/crates/apsis-rs/examples/dump_kepler.rs b/crates/apsis-rs/examples/dump_kepler.rs index 0699ae7..39005f8 100644 --- a/crates/apsis-rs/examples/dump_kepler.rs +++ b/crates/apsis-rs/examples/dump_kepler.rs @@ -12,6 +12,16 @@ //! elements, which exercises the vector algebra and the conic section //! relations rather than a single formula. //! +//! 写出本工作区计算的二体换算。 +//! +//! 输出是标准输出上的 CSV,带一行表头。它由 +//! `validation/python/orbit/check_kepler.py` 消费,后者从闭式表达式重算相同的量 +//! 并比较。Python 侧是依据几何而非依据本代码写成的,故转录错误会表现为不一致。 +//! +//! 写出两张表。第一张在一系列轨道上把开普勒根数转成直角坐标状态,这是规划调用方 +//! 所用的路径。第二张往另一方向转并记录所恢复的根数,它检验的是矢量代数与圆锥 +//! 曲线关系,而非单一公式。 +//! //! Usage: //! //! ```text @@ -22,28 +32,48 @@ use apsis_kepler::{GravityParameter, KeplerianElements}; /// The gravitational parameter used throughout, WGS 84. +/// +/// 全程所用的引力参数,WGS 84。 const MU: GravityParameter = GravityParameter::WGS84; /// One orbit to convert, chosen to span the shapes the model must handle. +/// +/// 一个要转换的轨道,其选取跨越该模型必须处理的各形状。 struct Case { /// A name for the case, so a failure in the report is readable. + /// + /// 用例的名称,使报告中的失败可读。 name: &'static str, /// Semi-major axis, in kilometers. + /// + /// 半长轴,单位为千米。 semi_major_axis: f64, /// Eccentricity, dimensionless. + /// + /// 偏心率,无量纲。 eccentricity: f64, /// Inclination, in degrees. + /// + /// 倾角,单位为度。 inclination_deg: f64, /// Right ascension of the ascending node, in degrees. + /// + /// 升交点赤经,单位为度。 right_ascension_deg: f64, /// Argument of perigee, in degrees. + /// + /// 近地点幅角,单位为度。 argument_of_perigee_deg: f64, /// True anomaly, in degrees. + /// + /// 真近点角,单位为度。 true_anomaly_deg: f64, } impl Case { /// Returns the case as elements in the units the crate uses. + /// + /// 以本 crate 所用的单位把该用例返回为根数。 fn elements(&self) -> KeplerianElements { KeplerianElements { semi_major_axis: self.semi_major_axis, @@ -61,6 +91,11 @@ impl Case { /// The set spans a circular orbit, two mildly eccentric ones, a highly /// eccentric one that exercises the near-parabolic branch of the anomaly /// iteration, a retrograde one, and one inclined close to the polar limit. +/// +/// 被转换的各轨道。 +/// +/// 该集合跨越一个圆轨道、两个轻度偏心者、一个检验近点角迭代近抛物线分支的 +/// 高度偏心者、一个逆行轨道,以及一个倾角接近极地极限的轨道。 const CASES: &[Case] = &[ Case { name: "circular_equatorial", @@ -119,10 +154,14 @@ const CASES: &[Case] = &[ ]; /// The geostationary radius, used for a circular orbit at that altitude. +/// +/// 地球静止轨道半径,用于该高度处的圆轨道。 const GEO_RADIUS: f64 = 42_164.0; fn main() { // The first table: elements to a Cartesian state. + // + // 第一张表:根数到直角坐标状态。 println!( "case,semi_major_axis_km,eccentricity,inclination_rad,right_ascension_rad,\ argument_of_perigee_rad,true_anomaly_rad,x_km,y_km,z_km,vx_kms,vy_kms,vz_kms,\ @@ -136,6 +175,8 @@ fn main() { // The specific energy is reported as well, because it is the // quantity the Python side uses to check the speed independently of // the direction. + // + // 比能量也被报告,因为它是 Python 侧用来独立于方向核对速率的量。 let radius = state.position.norm(); let energy = state.velocity.norm_squared() / 2.0 - MU.value() / radius; println!( @@ -160,6 +201,8 @@ fn main() { // A circular orbit at the geostationary radius, whose speed has a closed // form, is included in the same table under its own name. + // + // 地球静止半径处的圆轨道,其速率有闭式,故以它自己的名称纳入同一张表。 let geo = KeplerianElements { semi_major_axis: GEO_RADIUS, eccentricity: 0.0, @@ -192,6 +235,9 @@ fn main() { // The second table: a state back to elements, over a grid of true // anomalies on one orbit. This exercises the vector algebra rather than // the perifocal formulae the first table uses. + // + // 第二张表:在一个轨道的真近点角网格上从状态转回根数。它检验矢量代数,而非 + // 第一张表所用的近焦点公式。 println!(); println!( "true_anomaly_deg,recovered_semi_major_axis_km,recovered_eccentricity,\ diff --git a/crates/apsis-rs/examples/dump_link.rs b/crates/apsis-rs/examples/dump_link.rs index e36e2ca..389b97d 100644 --- a/crates/apsis-rs/examples/dump_link.rs +++ b/crates/apsis-rs/examples/dump_link.rs @@ -5,6 +5,12 @@ //! by `validation/python/link/check_link.py`, which recomputes the same //! quantities from the link equation and compares. //! +//! 写出链路预算输入以及本工作区为它们计算的各数字。 +//! +//! 输出是标准输出上的 CSV,带一行表头。它由 +//! `validation/python/link/check_link.py` 消费,后者从链路方程重算相同的量并 +//! 比较。 +//! //! Usage: //! //! ```text @@ -19,6 +25,11 @@ use apsis_rf::{Decibel, Gain, Power}; /// /// The unit of each field is in its name: powers and gains in decibels, /// temperature in kelvin, and everything else in SI base units. +/// +/// 一个链路场景,命名使各字段在每次使用时保持可读。 +/// +/// 每个字段的单位在其名称中:功率与增益以分贝计,温度以开尔文计,其余以 SI +/// 基本单位计。 struct Scenario { transmit_dbw: f64, transmit_dbi: f64, @@ -33,6 +44,9 @@ struct Scenario { /// The scenarios checked. They cover a Ku band downlink, an S band link, a /// wideband Ka link, and an L band link with a warmer receiver. +/// +/// 被检查的各场景。它们覆盖 Ku 频段下行、S 频段链路、宽带 Ka 链路,以及一个 +/// 接收机更热的 L 频段链路。 const SCENARIOS: &[Scenario] = &[ Scenario { transmit_dbw: 10.0, @@ -130,6 +144,8 @@ fn main() { let cn = budget.carrier_to_noise().map(|value| value.db()); // The energy per bit ratio is reported at a fixed data rate equal to // the bandwidth, which makes it the carrier to noise ratio. + // + // 每比特能量比在等于带宽的固定数据速率下报告,这使它即为载噪比。 let ebn0 = budget .energy_per_bit_over_noise(bandwidth) .map(|value| value.db()); diff --git a/crates/apsis-rs/examples/dump_orbit.rs b/crates/apsis-rs/examples/dump_orbit.rs index c2e885c..5d2abfa 100644 --- a/crates/apsis-rs/examples/dump_orbit.rs +++ b/crates/apsis-rs/examples/dump_orbit.rs @@ -6,6 +6,12 @@ //! which propagates the same element sets with the reference implementation //! and compares. //! +//! 为一组根数集与时刻写出传播后的状态。 +//! +//! 输出是标准输出上的 CSV,表头命名根数集下标、距历元的分钟数,以及位置与速度 +//! 分量。它由 `validation/python/orbit/check_sgp4.py` 消费,后者用参考实现传播 +//! 相同的根数集并比较。 +//! //! Usage: //! //! ```text @@ -19,24 +25,35 @@ use apsis_tle::TwoLineElement; /// The element sets used by the cross-check. They are the historical test /// cases distributed with the SGP4 reference implementation, which cover /// low, medium, and high eccentricity and the deep space branch. +/// +/// 交叉核对所用的各根数集。它们是随 SGP4 参考实现分发的历史测试用例,覆盖低、 +/// 中、高偏心率以及深空分支。 const ELEMENT_SETS: &[&str] = &[ // International Space Station, near circular low Earth orbit. + // + // 国际空间站,近圆形低轨。 concat!( "1 25544U 98067A 08264.51782528 -.00002182 00000-0 -11606-4 0 2927\r\n", "2 25544 51.6416 247.4627 0006703 130.5360 325.0288 15.72125391563537\r\n", ), // A highly eccentric orbit, which exercises the eccentric anomaly // iteration and the drag terms away from circular motion. + // + // 一个高度偏心的轨道,它检验偏近点角迭代以及远离圆运动时的阻力项。 concat!( "1 00005U 58002B 00179.78495062 .00000023 00000-0 28098-4 0 4753\r\n", "2 00005 34.2682 348.7242 1859667 331.7664 19.3264 10.82419157413667\r\n", ), // A geostationary transfer orbit with a low perigee. + // + // 一个近地点很低的地球静止转移轨道。 concat!( "1 27651U 03004A 06185.99374200 .00000109 00000-0 19909-4 0 445\r\n", "2 27651 7.1743 182.9443 7867251 269.0386 18.6601 1.03461646 9884\r\n", ), // A deep space orbit, whose period exceeds 225 minutes. + // + // 一个深空轨道,其周期超过 225 分钟。 concat!( "1 09880U 77021A 06174.85710247 .00000090 00000-0 10000-3 0 7322\r\n", "2 09880 64.1526 313.1296 6546925 103.4683 305.3980 2.00754276 13047\r\n", @@ -44,6 +61,8 @@ const ELEMENT_SETS: &[&str] = &[ ]; /// The times to sample, in minutes from the element epoch. +/// +/// 要采样的时刻,以距根数历元的分钟数计。 const TIMES_MINUTES: &[f64] = &[ 0.0, 1.0, 60.0, 360.0, 720.0, 1_440.0, 2_880.0, 10_080.0, -1_440.0, ]; diff --git a/crates/apsis-rs/examples/dump_p839.rs b/crates/apsis-rs/examples/dump_p839.rs index 7888b48..2fc8c23 100644 --- a/crates/apsis-rs/examples/dump_p839.rs +++ b/crates/apsis-rs/examples/dump_p839.rs @@ -1,6 +1,8 @@ //! Writes the rain height computed by this workspace, for cross-checking //! against ITU-R P.839-4. //! +//! 写出本工作区计算的雨顶高度,用于对照 ITU-R P.839-4 交叉核对。 +//! //! Usage: //! //! ```text @@ -11,6 +13,8 @@ use apsis_atmosphere::{rain_height, zero_isotherm_height}; /// The locations sampled, as latitude and longitude in degrees. +/// +/// 所采样的位置,以度计的纬度与经度。 const POINTS: &[(f64, f64)] = &[ (0.0, 0.0), (45.0, 0.0), diff --git a/crates/apsis-rs/examples/dump_rain.rs b/crates/apsis-rs/examples/dump_rain.rs index 61ecdb1..d948d25 100644 --- a/crates/apsis-rs/examples/dump_rain.rs +++ b/crates/apsis-rs/examples/dump_rain.rs @@ -1,6 +1,8 @@ //! Writes the P.838-3 rain coefficients computed by this workspace, for //! cross-checking against ITU-R P.838-3. //! +//! 写出本工作区计算的 P.838-3 降雨系数,用于对照 ITU-R P.838-3 交叉核对。 +//! //! Usage: //! //! ```text @@ -11,6 +13,8 @@ use apsis_atmosphere::rain_coefficients; /// The frequencies sampled, in gigahertz. +/// +/// 所采样的频率,单位为吉赫兹。 const FREQUENCIES_GHZ: &[f64] = &[ 1.0, 2.0, 4.0, 6.0, 8.0, 10.0, 12.0, 15.0, 20.0, 22.0, 25.0, 30.0, 40.0, 50.0, 60.0, 70.0, 100.0, @@ -21,6 +25,8 @@ fn main() { for &frequency in FREQUENCIES_GHZ { // A horizontal path, which removes the elevation dependence and // isolates the coefficient curves. + // + // 水平路径,它去除仰角依赖并分离出各系数曲线。 for &(elevation_degrees, polarisation_degrees) in &[(90.0_f64, 0.0_f64), (90.0, 90.0), (30.0, 0.0), (30.0, 45.0)] { diff --git a/crates/apsis-rs/examples/dump_rain_path.rs b/crates/apsis-rs/examples/dump_rain_path.rs index bda3fff..dc3b443 100644 --- a/crates/apsis-rs/examples/dump_rain_path.rs +++ b/crates/apsis-rs/examples/dump_rain_path.rs @@ -1,6 +1,8 @@ //! Writes rain path attenuation computed by this workspace, for //! cross-checking the ITU-R P.618-13 slant path method. //! +//! 写出本工作区计算的降雨路径衰减,用于交叉核对 ITU-R P.618-13 斜路径方法。 +//! //! Usage: //! //! ```text @@ -13,6 +15,9 @@ use apsis_atmosphere::{DEFAULT_RAIN_HEIGHT_KM, rain_attenuation}; /// The scenarios sampled. Each is a rain rate in millimeters per hour, a /// frequency in gigahertz, an elevation in degrees, and a latitude in /// degrees. The station height is zero and the rain height is the default. +/// +/// 所采样的场景。每个都是以毫米每小时计的降雨率、以吉赫兹计的频率、以度计的 +/// 仰角,以及以度计的纬度。站高为零,雨顶高度为缺省值。 const SCENARIOS: &[(f64, f64, f64, f64)] = &[ (20.0, 12.0, 30.0, 45.0), (20.0, 12.0, 10.0, 45.0), diff --git a/crates/apsis-rs/examples/dump_s465.rs b/crates/apsis-rs/examples/dump_s465.rs index 073685c..14d1191 100644 --- a/crates/apsis-rs/examples/dump_s465.rs +++ b/crates/apsis-rs/examples/dump_s465.rs @@ -1,6 +1,8 @@ //! Writes the ITU-R S.465 reference pattern computed by this workspace, for //! cross-checking against the recommendation. //! +//! 写出本工作区计算的 ITU-R S.465 参考方向图,用于对照该建议书交叉核对。 +//! //! Usage: //! //! ```text @@ -11,9 +13,13 @@ use apsis_antenna::{main_lobe_break_angle, reference_pattern_gain, reference_peak_gain}; /// The antenna sizes sampled, as diameter to wavelength ratios. +/// +/// 所采样的天线尺寸,以口径与波长之比表示。 const RATIOS: &[f64] = &[50.0, 100.0, 200.0]; /// The off-axis angles sampled, in degrees. +/// +/// 所采样的偏轴角,单位为度。 const ANGLES_DEGREES: &[f64] = &[0.1, 0.5, 1.0, 5.0, 20.0, 36.0, 48.0, 90.0]; fn main() { diff --git a/crates/apsis-rs/examples/dump_teme.rs b/crates/apsis-rs/examples/dump_teme.rs index db4affb..bd52901 100644 --- a/crates/apsis-rs/examples/dump_teme.rs +++ b/crates/apsis-rs/examples/dump_teme.rs @@ -1,6 +1,8 @@ //! Writes the TEME to Earth-fixed transformation computed by this workspace, //! for cross-checking against astropy. //! +//! 写出本工作区计算的 TEME 到地固坐标变换,用于对照 astropy 交叉核对。 +//! //! Usage: //! //! ```text @@ -12,6 +14,8 @@ use apsis_frames::iau2000::{PolarMotion, teme_to_terrestrial_matrix}; /// The samples, as a UTC Modified Julian Date and a TEME position in /// kilometers. +/// +/// 各样本,为一个 UTC 约化儒略日与一个以千米计的 TEME 位置。 const SAMPLES: &[(f64, [f64; 3])] = &[ (60_481.5, [7_000.0, 1_000.0, 2_000.0]), (51_544.5, [7_000.0, -3_000.0, 1_000.0]), @@ -28,6 +32,10 @@ fn main() { // is used directly here and the check tolerates that difference. // The Julian date is split into a whole number of days and a // fraction, which preserves more of the day than a single value. + // + // 该变换需要 UT1 时间,因为是地球自转在带动坐标系。UT1 与 UTC 相差不到 + // 0.9 秒,即 0.0037 度的转动,故此处直接使用 UTC 值,而检查容忍该差异。儒略日 + // 被拆成整数天数与零头,这比单个值保留更多当日信息。 let matrix = teme_to_terrestrial_matrix(2_400_000.5, utc_mjd, PolarMotion::NONE); let vector = apsis_math::Vec3::new(position[0], position[1], position[2]); let result = matrix * vector; diff --git a/crates/apsis-rs/examples/dump_time.rs b/crates/apsis-rs/examples/dump_time.rs index a036bb8..dd0a49e 100644 --- a/crates/apsis-rs/examples/dump_time.rs +++ b/crates/apsis-rs/examples/dump_time.rs @@ -10,6 +10,15 @@ //! Julian Date near 60 000 to better than about 40 microseconds. The two //! parts let the checker compare instants to well below a microsecond. //! +//! 写出闰秒偏移以及本工作区在一系列瞬时上计算的时标换算。 +//! +//! 输出是标准输出上的 CSV,带一行表头。它由 +//! `validation/python/time/check_time.py` 消费,后者用参考实现重算每个瞬时。 +//! +//! TAI 瞬时按两部分写出,一个整数约化儒略日与一天的零头,因为单个 `f64` 无法 +//! 把接近 60 000 的约化儒略日保持到优于约 40 微秒。两部分使检查器能把瞬时比较 +//! 到远低于一微秒。 +//! //! Usage: //! //! ```text @@ -21,6 +30,8 @@ use apsis_leap::{LEAP_SECONDS, tai_minus_utc_at_mjd}; use apsis_time::{Calendar, Epoch, TT_MINUS_TAI, TimeScale}; /// Splits a Modified Julian Date into its integer day and its fraction. +/// +/// 把约化儒略日拆为其整数日与零头。 fn split(mjd: f64) -> (i64, f64) { let day = mjd.floor(); (day as i64, mjd - day) @@ -51,6 +62,8 @@ fn main() { // Sample every leap second boundary at several times of day, so that // the step behaviour and the interior of each interval are covered. + // + // 在一天中的若干时刻对每个闰秒边界采样,使阶跃行为与每个区间的内部都被覆盖。 for entry in LEAP_SECONDS { for (hour, minute, second) in [(0, 0, 0.0), (6, 0, 0.0), (12, 0, 0.0), (18, 0, 0.0)] { let calendar = Calendar::new(entry.year, entry.month, entry.day, hour, minute, second); @@ -61,6 +74,8 @@ fn main() { } // The last second before a leap second and the first second after it. + // + // 闰秒前的最后一秒与其后的第一秒。 for (year, month, day, hour, minute, second) in [ (2016, 12, 31, 23, 59, 59.0), (2017, 1, 1, 0, 0, 0.0), @@ -76,5 +91,7 @@ fn main() { // The Terrestrial Time offset is a defining constant, written here so // that the checker can verify it without recomputing the calendar. + // + // 地球时偏移是一个定义常量,写在这里使检查器无需重算日历即可核验它。 println!("# tt_minus_tai_seconds={TT_MINUS_TAI:.3}"); } diff --git a/crates/apsis-rs/examples/dump_tle.rs b/crates/apsis-rs/examples/dump_tle.rs index 289e6db..5958067 100644 --- a/crates/apsis-rs/examples/dump_tle.rs +++ b/crates/apsis-rs/examples/dump_tle.rs @@ -11,6 +11,15 @@ //! eccentricity, a retrograde inclination, a negative drag term, and a century //! rollover in the two digit epoch year. //! +//! 写出本工作区从两行集解析出的根数字段。 +//! +//! 输出是标准输出上的 CSV,带一行表头。它由 +//! `validation/python/orbit/check_tle.py` 消费,后者用一个独立的、按列索引的 +//! 读取器重新解析相同的集合、比较每个字段,并重算每行对十取模的校验和。 +//! +//! 各集合包括随 SGP4 参考实现分发的历史测试用例,以及检验格式各角落的合成用例: +//! 偏心率带隐含前导零的圆轨道、逆行倾角、负阻力项,以及两位历元年份的世纪翻转。 +//! //! Usage: //! //! ```text @@ -22,10 +31,16 @@ use apsis_time::TimeScale; use apsis_tle::{Classification, TwoLineElement, line_checksum}; /// One element set to parse, with a name for the report. +/// +/// 一个要解析的根数集,带一个用于报告的名称。 struct Sample { /// A name for the sample, so a failure in the report is readable. + /// + /// 样本的名称,使报告中的失败可读。 name: &'static str, /// The two lines of the set, without a trailing carriage return. + /// + /// 该集合的两行,不带尾随回车。 lines: [&'static str; 2], } @@ -43,6 +58,12 @@ const fn sample(name: &'static str, first: &'static str, second: &'static str) - /// the format: an implied leading zero in the eccentricity, a retrograde /// inclination, a negative first derivative of the mean motion, a century /// rollover in the two digit epoch year, and a name line. +/// +/// 被解析的各根数集。 +/// +/// 前四个是随 SGP4 参考实现分发的历史测试用例。其余是合成的,覆盖格式的边缘: +/// 偏心率带隐含前导零、逆行倾角、平运动一阶导数为负、两位历元年份的世纪翻转, +/// 以及一个名称行。 const SAMPLES: &[Sample] = &[ sample( "vanguard_1", @@ -77,6 +98,8 @@ const SAMPLES: &[Sample] = &[ sample( // A two digit year of 99 must expand to 1999, the last year of the // twentieth century branch of the convention. + // + // 两位年份 99 必须展开为 1999,即该约定二十世纪分支的最后一年。 "two_digit_year_1999", "1 10000U 99001A 99365.00000000 .00000000 00000-0 00000-0 0 05", "2 10000 45.0000 10.0000 0001000 0.0000 0.0000 14.00000000 09", @@ -93,6 +116,11 @@ const SAMPLES: &[Sample] = &[ /// The epoch field of an element set stores the day of the year and its /// fraction, so the year and month are combined back into a day of year /// before the fraction of the day is added. +/// +/// 返回某日历日期在该年中的第几天,以小数表示。 +/// +/// 根数集的历元字段保存一年中的第几天及其零头,故年与月先合回一年中的第几天, +/// 再加上当日的零头。 fn day_of_year_fraction(year: i32, month: u32, day: u32) -> f64 { use apsis_time::days_in_month; let mut total = 0_u32; @@ -123,6 +151,9 @@ fn main() { // The epoch is stored as a Modified Julian Date; the calendar form // is written so the reader can compare the year and the day of year // against the two digit year and fraction the line encodes. + // + // 历元存为约化儒略日;写出日历形式,使读者可以把年与一年中的第几天对照该行 + // 所编码的两位年份与零头。 let calendar = element .epoch .calendar(TimeScale::Utc)