Carry every body's IAU rotational elements, read from NAIF's kernel of the 2015 report

bodies.json now holds, for 33 of the 38 bodies, the pole right ascension and declination and the
prime meridian W of the IAU WGCCRE 2015 report (Archinal et al. 2018), with their rates and the
periodic terms. They are read from NAIF's pck00011.tpc, which carries the report in a form a
program can read, periodic terms and their angles included. Hyperion (chaotic), Nereid, Eris,
Haumea and Makemake have no model in the report.

The parser, src/app/shared/astro/rotational-elements.ts, sits beside the other source readers so
the unit suite covers it. It reads data blocks only where \begindata stands alone on a line, as
the kernel's own prose mentions the token mid-sentence. It reads the Fortran exponent (the Moon's
-1.4D-12 d² term) and the degree-2 angles of the Mars system, where Phobos's tidal acceleration
lives. NAIF numbers a small body 2 000 000 past its catalogue number, so Ceres is 2000001.

Periodic terms under 0.01 degrees are left out. 0.01 degrees moves a point by 0.11 px on the
largest body ever drawn (Jupiter at 641 px of radius). That drops 32 terms:
- Mercury: 4 (0.0011 degrees and less)
- the Moon: 8 of 13 (0.0072 and less)
- Mars: 13 (0.00024 and less); its three 0.42-1.59 degree long-period terms stay
- Phobos: 1 (0.0063)
- Jupiter: 5 (0.0022 and less)
- Europa: 1 (0.009)
Kept, among others: Mimas's 44.85-degree libration, Triton's 32-degree precession, Miranda's 4.4
and Phobos's 1.14-degree libration.

build.ts now checks the elements against Horizons on the real catalogue:
- Every body but those five carries elements, and they do not.
- The IAU day, 360 over W's rate, is within 1e-4 of Horizons' period. Measured: at most 1.8e-5
  (Jupiter). Neptune gets a 0.01 ceiling: 0.89 per cent, because the report takes Karkoschka's
  15.9663 h where Horizons keeps Voyager's 16.11.
- The spin axis, the pole turned end for end where W runs backwards, is within 0.1 degrees of
  Horizons' obliquity. Measured: at most 0.058 (Venus, 177.358 against 177.3); Uranus 97.771,
  Pluto 119.610, Earth 23.435.
Full npm run etl passes. Three mutants each fail it on the named check:
- W's sign dropped: "Venus's IAU spin axis is 2.642 degrees".
- Ceres looked up by catalogue number: "Body ceres has no IAU rotational elements".
- W's rate read per century: "Mercury's IAU day ... 3.65e+4".

Nothing is drawn from these yet.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-24 22:46:14 +02:00
co-authored by Claude Opus 5.5
parent ab7d454db1
commit 1c86584642
7 changed files with 1531 additions and 38 deletions
+30
View File
@@ -86,4 +86,34 @@ export interface BodyRecord {
*/
rotationPeriodHours?: number;
obliquityDeg?: number;
/**
* Where the body's pole points and which way its prime meridian faces at any date, from the IAU
* WGCCRE 2015 report (Archinal et al. 2018) as NAIF's `pck00011.tpc` carries it. Where present
* it alone sets how the body is drawn, and the ETL checks the period and obliquity above against
* it. Absent where the report gives none: Hyperion tumbles, and Nereid, Eris, Haumea and
* Makemake have no model.
*/
rotationalElements?: RotationalElements;
}
/**
* The IAU's rotational elements for one body: polynomials in time, plus periodic terms.
*
* The pole's right ascension and declination are in degrees in the ICRF, `[c0, c1, c2]` for
* `c0 + c1 T + c2 T²`, T in Julian centuries from J2000.0 TDB. The prime meridian W is the angle
* along the body's equator, anticlockwise seen from above that pole, from where the equator rises
* through the ICRF equator to the body's longitude 0, `c0 + c1 d + c2 d²` with d in days. A
* negative rate turns the body clockwise about the pole the IAU names: Venus, Uranus and its
* moons, Triton.
*/
export interface RotationalElements {
poleRaDeg: number[];
poleDecDeg: number[];
primeMeridianDeg: number[];
/**
* Each adds `ra sin θ` to the right ascension, `dec cos θ` to the declination and `pm sin θ` to
* W, θ being `angleDeg[0] + angleDeg[1] T + angleDeg[2] T²`. The smallest are left out; see
* `parsePckRotationalElements`.
*/
terms?: Array<{ angleDeg: number[]; ra: number; dec: number; pm: number }>;
}