1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
//! Canonical physical and unit constants shared by the core crates.
//!
//! Values with different standards or parity sources are intentionally named
//! distinctly in [`models`] or [`astro`] instead of being silently unified.
/// Unit-conversion constants.
pub mod units {
/// Meters per kilometer.
pub const M_PER_KM: f64 = 1_000.0;
/// Millimeters per meter.
pub const MM_PER_M: f64 = 1_000.0;
/// Kilometers to meters.
pub const KM_TO_M: f64 = M_PER_KM;
/// Microseconds to seconds.
pub const US_TO_S: f64 = 1.0e-6;
/// Microseconds per second.
pub const MICROSECONDS_PER_SECOND_I64: i64 = 1_000_000;
/// Microseconds per second, floating point. Used where a microsecond count
/// is divided or multiplied as an `f64`; kept distinct from [`US_TO_S`] so
/// the divide-by-`1_000_000.0` operation order is preserved bit-for-bit.
pub const MICROSECONDS_PER_SECOND: f64 = 1_000_000.0;
/// Nanoseconds to seconds.
pub const NS_TO_S: f64 = 1.0e-9;
/// Degrees to radians.
pub const DEG_TO_RAD: f64 = std::f64::consts::PI / 180.0;
/// Radians to degrees.
pub const RAD_TO_DEG: f64 = 180.0 / std::f64::consts::PI;
/// Degrees in one semicircle.
pub const DEGREES_PER_SEMICIRCLE: f64 = 180.0;
/// Degrees in one full circle.
pub const DEGREES_PER_CIRCLE: f64 = 360.0;
/// Arcseconds to radians.
#[allow(clippy::excessive_precision)]
pub const ARCSEC_TO_RAD: f64 = 4.848_136_811_095_359_935_899_141e-6;
}
/// Topocentric look-angle geometry tolerances.
pub mod geometry {
/// Squared horizontal fraction of the unit line of sight below which the
/// topocentric azimuth is degenerate and is defined to be `0.0`.
///
/// At (and arbitrarily near) the observer's zenith the east and north
/// components of the line of sight collapse to pure rounding residuals, so
/// `atan2(east, north)` carries no real bearing information. Following
/// RTKLIB's `satazel` (which sets `az = 0` when the squared horizontal
/// projection of the unit line-of-sight vector is `< 1e-12`), azimuth is
/// pinned to `0.0` inside this threshold rather than returning rounding
/// noise. The comparison is made in squared form
/// (`east^2 + north^2 < AZIMUTH_ZENITH_EPS * range^2`) so it is scale free
/// regardless of the units the line of sight is expressed in.
pub const AZIMUTH_ZENITH_EPS: f64 = 1e-12;
}
/// Time-scale and Julian-date constants.
pub mod time {
use super::units::MICROSECONDS_PER_SECOND_I64;
/// Seconds per civil minute.
pub const SECONDS_PER_MINUTE: f64 = 60.0;
/// Seconds per civil hour.
pub const SECONDS_PER_HOUR: f64 = 3_600.0;
/// Seconds per civil day.
pub const SECONDS_PER_DAY: f64 = 86_400.0;
/// Seconds per civil day, integer form for calendar arithmetic.
pub const SECONDS_PER_DAY_I64: i64 = 86_400;
/// Microseconds per civil day.
pub const MICROSECONDS_PER_DAY_I64: i64 = SECONDS_PER_DAY_I64 * MICROSECONDS_PER_SECOND_I64;
/// Seconds per GNSS week.
pub const SECONDS_PER_WEEK: f64 = 604_800.0;
/// Julian Date of the J2000 epoch.
pub const J2000_JD: f64 = 2_451_545.0;
/// Days per Julian year.
pub const DAYS_PER_JULIAN_YEAR: f64 = 365.25;
/// Days per Julian century.
pub const DAYS_PER_JULIAN_CENTURY: f64 = 36_525.0;
/// TT - TAI, seconds.
pub const TT_MINUS_TAI_S: f64 = 32.184;
/// GPS/Galileo/QZSS system time minus TAI, seconds.
pub const GPST_MINUS_TAI_S: f64 = 19.0;
/// BeiDou time minus TAI, seconds.
pub const BDT_MINUS_TAI_S: f64 = 33.0;
}
/// WGS84 Earth constants.
pub mod earth {
use super::units::M_PER_KM;
/// WGS84 geocentric gravitational constant (km^3/s^2).
pub const GM_EARTH_KM3_S2: f64 = 398_600.441_8;
/// WGS84 geocentric gravitational constant (m^3/s^2).
pub const GM_EARTH_M3_S2: f64 = GM_EARTH_KM3_S2 * 1.0e9;
/// WGS84 Earth equatorial radius (km).
pub const WGS84_A_KM: f64 = 6_378.137;
/// WGS84 Earth equatorial radius (m).
pub const WGS84_A_M: f64 = WGS84_A_KM * M_PER_KM;
/// Mean Earth radius used by spherical shell propagation and conical
/// shadow (eclipse) models (km).
pub const MEAN_EARTH_RADIUS_KM: f64 = 6_371.0;
/// Mean Earth radius used by spherical shell propagation and conical
/// shadow (eclipse) models (m).
pub const MEAN_EARTH_RADIUS_M: f64 = MEAN_EARTH_RADIUS_KM * M_PER_KM;
/// WGS84 flattening.
pub const WGS84_F: f64 = 1.0 / 298.257_223_563;
/// WGS84 first eccentricity squared.
pub const WGS84_E2: f64 = 2.0 * WGS84_F - WGS84_F * WGS84_F;
/// WGS84 Earth rotation rate used by GNSS Sagnac/transport terms (rad/s).
pub const OMEGA_E_DOT_RAD_S: f64 = 7.292_115_146_7e-5;
/// Earth's J2 coefficient used by the core force models.
pub const J2_EARTH: f64 = 1.082_626_68e-3;
}
/// Universal physical constants.
pub mod physics {
/// Speed of light in vacuum (m/s), exact by SI definition (and the value
/// IS-GPS-200 fixes for GNSS ranging).
pub const SPEED_OF_LIGHT_M_S: f64 = 299_792_458.0;
}
/// Astronomical constants.
pub mod astro {
/// Astronomical unit in kilometers, matching Skyfield's AU convention.
pub const AU_KM: f64 = 149_597_870.700;
/// Astronomical unit in meters, matching [`AU_KM`].
pub const AU_M: f64 = AU_KM * 1_000.0;
/// Solar gravitational parameter (km^3/s^2), IAU 2015 Resolution B3.
pub const GM_SUN_KM3_S2: f64 = 132_712_440_041.939_38;
/// AU value used by the Montenbruck-Gill analytic Sun/Moon series.
pub const MONTENBRUCK_AU_M: f64 = 149_597_870_691.0;
/// Solar photosphere radius (km), used by conical eclipse-shadow geometry.
pub const SOLAR_RADIUS_KM: f64 = 696_340.0;
/// Mean lunar radius (km), used by almanac eclipse geometry.
pub const MOON_RADIUS_KM: f64 = 1_737.4;
}
/// Model-specific constants that intentionally differ from WGS84.
pub mod models {
pub mod pz90 {
/// Geocentric gravitational constant (m^3/s^2), PZ-90.11.
pub const GM_M3_S2: f64 = 3.986_004_4e14;
/// Second zonal harmonic of the geopotential, PZ-90.11.
pub const J2: f64 = 1.082_625_7e-3;
/// Earth rotation rate (rad/s), PZ-90.11.
pub const OMEGA_E_RAD_S: f64 = 7.292_115e-5;
/// Earth equatorial radius (m), PZ-90.11.
pub const A_M: f64 = 6_378_136.0;
}
pub mod iers {
/// Earth radius used by the Dehant solid Earth tide formulation (m).
pub const SOLID_TIDE_EARTH_RADIUS_M: f64 = 6_378_136.6;
}
pub mod proj {
/// PROJ-pinned WGS84 semi-major axis (m).
pub const WGS84_A_M: f64 = f64::from_bits(0x4158_54a6_4000_0000);
/// PROJ-pinned WGS84 semi-minor axis (m).
pub const WGS84_B_M: f64 = f64::from_bits(0x4158_3fc4_141c_97d0);
/// PROJ-pinned first eccentricity squared.
pub const WGS84_ES: f64 = f64::from_bits(0x3f7b_6b90_f1fe_94f0);
/// PROJ-pinned second eccentricity squared.
pub const WGS84_E2S: f64 = f64::from_bits(0x3f7b_9adf_e197_dcd1);
/// PROJ-pinned radian-to-degree multiplier.
pub const RAD_TO_DEG: f64 = f64::from_bits(0x404c_a5dc_1a63_c1f8);
/// PROJ-pinned half-pi value.
pub const HALF_PI: f64 = f64::from_bits(0x3ff9_21fb_5444_2d18);
}
pub mod broadcast {
/// GPS broadcast gravitational constant (m^3/s^2), IS-GPS-200.
pub const GPS_GM_M3_S2: f64 = 3.986_005_0e14;
/// GPS/Galileo broadcast Earth rotation rate (rad/s).
pub const GPS_GALILEO_OMEGA_E_RAD_S: f64 = 7.292_115_146_7e-5;
/// GPS broadcast relativistic clock constant (s/sqrt(m)).
pub const GPS_DTR_F: f64 = -0.000_000_000_444_280_763_339_306;
/// Galileo broadcast gravitational constant (m^3/s^2).
pub const GALILEO_GM_M3_S2: f64 = 3.986_004_418e14;
/// Galileo/BeiDou broadcast relativistic clock constant (s/sqrt(m)).
pub const GALILEO_BEIDOU_DTR_F: f64 = -0.000_000_000_444_280_730_904_397_75;
/// BeiDou broadcast Earth rotation rate (rad/s).
pub const BEIDOU_OMEGA_E_RAD_S: f64 = 7.292_115e-5;
}
}
/// Canonical Earth gravity-model constants: the (mu, Re, J2) triple in km units,
/// used together by the two-body + J2 force model. Geodetic code instead uses the
/// WGS84 ellipsoid parameters (earth::WGS84_A_KM with WGS84_E2/WGS84_F); RE_EARTH
/// and WGS84_A_KM share a numeric value but name distinct concepts (gravity
/// reference radius vs ellipsoid semi-major axis).
pub const MU_EARTH: f64 = earth::GM_EARTH_KM3_S2;
/// Earth reference equatorial radius for the gravity model (km).
pub const RE_EARTH: f64 = earth::WGS84_A_KM;
/// Earth J2 zonal harmonic for the gravity model.
pub const J2_EARTH: f64 = earth::J2_EARTH;