The archived satellite table the moons are read from gives older node
periods than JPL's current one for Miranda (17.727 years against URA182's
17.787), Ganymede (132.654 against 137.812), Callisto (338.82 against
577.264) and Titan (704.60 against 687.370), and 74ea1d6 turned the IAU's
poles after those older rates, taking them for the right ones. They were
not: fitted to Horizons' osculating elements on Uranus's equator over
1601-2399, Miranda's node turns 2023.97 degrees a century (rms 0.04),
against the current table's 2023.95, the IAU's U11 2024.22 and the row's
2030.80. That commit moved Miranda's axis from 0.38 to 2.36 degrees of
Horizons' orbit normal. Mimas's node, 0.986 years in both tables, now takes
the IAU's S3, 36505.5 degrees a century, 1.2 from a Horizons fit where
the row's is 4.5.
The ETL spec carries the node period (nodePeriodYears), and the periapsis
keeps the row's longitude rate: the row gives the longitude's rate (Callisto
68.7 degrees a century, the current table 67.2), so the argument takes up
the change. On the row's argument Callisto's periapsis moved 44 degrees by
2100 and it strayed 0.71 degrees from Horizons over 1950-2100.
Worst angle from Horizons' osculating orbit normal (ICRF), HEAD then now:
- Miranda, 1601-2399: drawn orbit 2.11 -> 0.12, axis 2.36 -> 0.34.
- Mimas, 1750-2249: orbit 0.33 -> 0.11, axis 0.65 -> 0.40.
- Ganymede, 1600-2199: orbit 0.17 -> 0.11, axis 0.13 -> 0.01.
- Callisto, 1600-2199: orbit 0.53 -> 0.20, axis 0.02 -> 0.03.
- Titan, 1750-2249: orbit 0.048 -> 0.052.
Against the 1950-2100 Horizons tracks the ETL checks: Callisto 0.19 -> 0.08,
Miranda 1.73 -> 1.62, Ganymede 0.30 -> 0.29, Mimas 7.43 -> 7.42, Titan 0.06.
lockedToOrbit now barely moves the IAU's node terms: Miranda's U11 to
-2023.95, Ganymede's J5 to 261.23 (262.1), Mimas's S3 not at all, and
Callisto's J6, 3.1 per cent from its new node rate, to 62.36 (64.3), which
takes Callisto's axis from 0.56 to 0.22 degrees of its drawn orbit.
With the drawn rates right, leaving every node term at the IAU's rate no
longer failed the ETL (Mimas used to), nor did a 1 per cent tolerance, the
node's angle without its harmonics, or the older node periods. The axis
ceiling is now 0.25 degrees for Europa (0.13 measured), Ganymede (0.16),
Callisto (0.22), Rhea (0.17), Miranda (0.23) and Triton (0.15), and
Callisto's track ceiling 0.15 (0.08). Guarded mutants, each through the
solar ETL on the real catalogue and then the suite on the bodies.json it
wrote:
- node terms left at the IAU's rates: ETL "europa's spin axis leans up to
0.33"; suite fails only 'turns the poles of Europa, Ganymede, Callisto,
Rhea, Miranda and Triton round with their drawn nodes'.
- tolerance 1 per cent: ETL, Callisto 0.33; the same test, alone.
- harmonics dropped: ETL, Triton 0.29 (the suite's three dates miss it).
- the archived node periods: ETL, Callisto's track 0.19; the suite fails
that test and 'draws Miranda's orbit, and turns its axis, where Horizons
has its orbit in 1601 and 2390' (orbit 2.02, axis 2.36 at 1601).
- the row's argument kept: ETL, Callisto's track 0.71.
The docs that called the IAU's rates the wrong ones are corrected
(lockedToOrbit, the axis ceiling in build.ts, whose Titan node now turns
in 687 years), and the README and BodyRecord doc no longer say every
locked moon's node terms are re-rated: only those within 5 per cent of a
multiple of the node's rate, never the Moon's or Phobos's, and not the
circles Ariel's, Umbriel's, Titania's and Oberon's poles go round on
(0.36 to 0.50 degrees off their orbits). The README also names the five
bodies the IAU's elements do not turn. Unit suite 866 passed.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
141 lines
6.9 KiB
TypeScript
141 lines
6.9 KiB
TypeScript
/**
|
|
* Keplerian orbital elements at a reference epoch. Positions are derived client-side by
|
|
* propagating these elements forward/backward from `epochJd` (see `shared/astro/kepler.ts`),
|
|
* rather than fetching per-frame positions.
|
|
*/
|
|
export interface OrbitalElements {
|
|
semiMajorAxisAu: number;
|
|
eccentricity: number;
|
|
inclinationDeg: number;
|
|
longitudeOfAscendingNodeDeg: number;
|
|
argumentOfPeriapsisDeg: number;
|
|
meanAnomalyAtEpochDeg: number;
|
|
epochJd: number;
|
|
}
|
|
|
|
/**
|
|
* How a body's mean elements move away from their epoch, per day.
|
|
*
|
|
* Mean elements rather than one osculating set, because the map's clock runs decades in minutes.
|
|
* An osculating orbit is exact at its instant and drifts from then on: fed to Kepler with a mass
|
|
* ratio, the Moon's went round in 27.70 days instead of 27.32 and was 66 degrees out after a year.
|
|
* A mean set carries its own measured motion, and the slow turning of its node and periapsis, so
|
|
* it holds for as long as its source was fit over.
|
|
*/
|
|
export interface MeanElementRates {
|
|
/**
|
|
* How fast the body goes round in space, in degrees per day: the rate of its mean longitude.
|
|
* 360 over this is its sidereal period.
|
|
*/
|
|
meanMotionDegPerDay: number;
|
|
longitudeOfAscendingNodeDegPerDay: number;
|
|
argumentOfPeriapsisDegPerDay: number;
|
|
semiMajorAxisAuPerDay?: number;
|
|
eccentricityPerDay?: number;
|
|
inclinationDegPerDay?: number;
|
|
/**
|
|
* Standish's extra terms in the mean anomaly of Jupiter and beyond, `b T² + c cos(f T) +
|
|
* s sin(f T)` degrees, with T in Julian centuries from the epoch and f in degrees per century:
|
|
* the great-inequality wobble his 3000 BC to AD 3000 fit needs on top of its linear rates.
|
|
*/
|
|
meanAnomalyTerms?: { b: number; c: number; s: number; f: number };
|
|
}
|
|
|
|
/**
|
|
* A solar-system planet, moon, or dwarf planet: JPL mean orbital elements, and JPL Horizons
|
|
* physical data. `systemStarId` links back to the HYG star index (the Sun, see `SUN_STAR_ID`).
|
|
*/
|
|
export interface BodyRecord {
|
|
id: string;
|
|
systemStarId: number;
|
|
name: string;
|
|
kind: 'planet' | 'moon' | 'dwarf';
|
|
/** Mean radius: for a triaxial body, the radius of the sphere of its volume, which is how it is drawn. */
|
|
radiusKm: number;
|
|
/**
|
|
* A triaxial body's three semi-axes, in km, largest first, where its shape is too far from a
|
|
* sphere for one radius to say it: Haumea's 1161 x 852 x 513 (Ortiz et al. 2017), whose mean
|
|
* radius is 798.
|
|
*/
|
|
semiAxesKm?: readonly [number, number, number];
|
|
/** Mean elements at `orbit.epochJd`, moving at `rates`. */
|
|
orbit: OrbitalElements;
|
|
rates: MeanElementRates;
|
|
/**
|
|
* The pole of the plane a moon's elements are measured against, where that is its local
|
|
* Laplace plane or, for Uranus's and Pluto's moons, the planet's equator: right ascension and
|
|
* declination in the ICRF. The node is then counted from where that plane crosses the ICRF
|
|
* equator. Absent means the J2000 ecliptic, as for the planets and the Moon.
|
|
*/
|
|
laplacePole?: { raDeg: number; decDeg: number };
|
|
/** Where the elements come from and the span they hold over, as the card prints it. */
|
|
orbitSource: string;
|
|
/**
|
|
* The eccentricity the card prints, where it is not the orbit's own: Hyperion's row in the table
|
|
* its orbit is drawn from gives 0.0232, under a quarter of the 0.105 JPL's current table (SAT441)
|
|
* and Horizons (0.074 to 0.132 from 1980 to 2100) give. The older row still places Hyperion
|
|
* nearer where Horizons has it than the same row with 0.105 does, so the orbit keeps it.
|
|
*/
|
|
measuredEccentricity?: number;
|
|
/**
|
|
* For `kind: 'moon'`, the `id` of the planet it orbits — its `orbit` is expressed
|
|
* relative to that planet, not heliocentrically. Undefined for planets/dwarfs.
|
|
*/
|
|
parentBodyId?: string;
|
|
/**
|
|
* For a moon heavy enough that it and its planet go round a point outside the planet — Charon,
|
|
* an eighth of Pluto's mass, puts it 2 100 km from Pluto's centre, 900 km above its surface —
|
|
* the moon's mass over the planet's, from the GMs on their Horizons pages. The planet's own
|
|
* elements then place that barycentre, as Standish's "Pluto" does, and both bodies are drawn
|
|
* going round it. Absent for every other moon.
|
|
*/
|
|
massRatio?: number;
|
|
/**
|
|
* How the body turns on its own axis: the sidereal rotation period in hours, negative where
|
|
* Horizons gives a negative rate (Venus, Uranus), and the tilt of that axis from its orbital
|
|
* plane — which past 90 degrees already says the turn is retrograde.
|
|
*
|
|
* For a locked moon the period is its orbit's, from the mean motion that carries it round. Where
|
|
* the source states none, or one a later measurement overturns, it is the one the body's ETL spec
|
|
* carries: Nereid's K2 light curve, Eris's lock to Dysnomia. Absent only for Hyperion, which
|
|
* tumbles — the view leaves it still rather than spinning it at an invented rate.
|
|
*/
|
|
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, but that a locked
|
|
* moon's W, and its pole's terms that turn within 5 per cent of a multiple of its node's rate, turn
|
|
* at its drawn orbit's rates and Iapetus's pole goes round with its orbit's, so they keep their
|
|
* faces to their planets, and their poles round their orbits', over the clock's AD 1 to 3000 (see
|
|
* `lockedToOrbit` in the ETL). The Moon's and Phobos's, whose W has a quadratic, are the IAU's
|
|
* whole, and so are the terms Ariel's, Umbriel's, Titania's and Oberon's poles go round on, which
|
|
* turn at none of their nodes' multiples. 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 }>;
|
|
}
|