Real-time 3D mission tracker for NASA's Artemis II lunar flyby, built with React + Three.js using GCRS/BCRS/ICRS reference frames, ephemeris data from JPL Horizons and SPICE DE440, and a registered celestial sky map.
Launched: April 1, 2026 · Orion capsule: Integrity · JPL Horizons / NAIF ID: -1024
| Earth View | Flyby View |
|---|---|
![]() |
![]() |
![]() |
![]() |
About this README
This README defines the coordinate frames, time conventions, data products, and texture-registration assumptions used by the viewer.
The application renders Earth, Moon, Sun, the Artemis II spacecraft, mission trajectory, a celestial background map, and orientation helpers. It also renders Mercury, Venus, Mars, Jupiter, and Saturn from the same inertial ephemeris pipeline.
The technical contract covers:
- frame origin and handedness
- inertial and body-fixed orientation
- time conventions
- ephemeris provenance
- texture registration
- camera reporting in the selected frame
The default public deployment target is GitHub Pages at:
https://pzarzycki.github.io/artemis-2/
For local development, the app runs at:
http://localhost:5173/- server bind:
0.0.0.0:5173
Large star-map EXR files are kept in Git LFS.
- asset directory:
public/starmaps/ - supported resolutions:
4k,8k,16k - default runtime selection:
4k
After cloning, fetch the required sky maps with Git LFS:
git lfs pullTo refresh or regenerate the local star-map set manually, use:
uv run python scripts/download_starmaps.py 4kGitHub Actions checks out the same LFS assets before the Docker build, so image builds do not depend on downloading these files from NASA during CI.
The scene scale is:
1 Three.js unit = 1 km
The rendering requires:
- one inertial world frame,
- one time convention,
- one body-fixed orientation convention for Earth,
- one body-fixed orientation convention for Moon,
- textures registered to those body-fixed frames,
- every state vector labeled by origin, axes, units, and time scale.
The renderer uses WebGL through Three.js / React Three Fiber.
Project-wide render convention:
- right-handed
+X= red+Y= green+Z= blue+Zis the app-wide up direction
Camera convention:
- an unrotated camera looks along
-Z - this project explicitly sets the camera up vector to
(0, 0, 1) - local
+Xis camera-right - local
+Yis camera-up - local
-Zis the viewing axis
Presentation rule:
- the selected Cartesian frame is mapped directly into the render world without handedness flips or hidden axis swaps
- any helper indicator shown in the app must respect that same right-handed
Z-upconvention - camera position and world-space camera orientation vectors are reported in the selected scene frame
- the camera panel reports orientation primarily as
RA/Decangles of the corresponding world-space direction vectors - those
RA/Decvalues are expressed in decimal degrees in the selected inertial frame
- IERS Conventions / reference-system material: https://iers-conventions.obspm.fr/conventions_material.php
- IERS TN36 Chapter 2, for ICRS / BCRS / GCRS definitions: https://iers-conventions.obspm.fr/content/chapter2/tn36_c2.pdf
- NAIF SPICE documentation for
J2000practical use and its alignment withICRF: https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/ug/msopck.html - JPL Horizons manual: https://ssd.jpl.nasa.gov/horizons/manual.html
- NAIF generic kernels / DE440: https://naif.jpl.nasa.gov/naif/data_generic.html
- NASA SVS CGI Moon Kit: https://svs.gsfc.nasa.gov/4720
- NASA Science, Artemis II lunar science operations: https://science.nasa.gov/solar-system/nasas-artemis-ii-lunar-science-operations-to-inform-future-missions/
- NASA SVS Deep Star Maps 2020: https://svs.gsfc.nasa.gov/4851
The default scene is an Earth-centered inertial Cartesian frame aligned with practical J2000/ICRF axes:
- origin: Earth center of mass
+X: practicalJ2000x-axis+Y: practicalJ2000y-axis+Z: north celestial pole- handedness: right-handed
- units: kilometers
In the renderer, this frame is mapped directly into the Three.js world without handedness flips or hidden axis swaps. The app UI label GCRS is used in this practical sense: Earth-centered, inertial, and J2000/ICRF-aligned for ephemeris work.
Earth stays at (0, 0, 0) in this mode. Earth rotation is applied separately through the Earth body-fixed frame:
+Z: terrestrial north pole+X: equator / Greenwich meridian intersection+Y: equator /90°E
The stored Earth orientation quantity is gmstRad, derived from the SPICE J2000 -> IAU_EARTH transform and applied as a rotation about inertial +Z. At dataset start (JD 2461131.5, i.e. 2026-04-01 00:00:00 UTC), gmstRad = 3.29775608 rad, so the Greenwich meridian points at inertial right ascension 188.947505°.
The app's geographic readouts are spherical rather than geodetic:
- latitude from the equator
- east-positive longitude from
atan2(y, x)in Earth-fixed coordinates - altitude above a fixed spherical Earth radius
That is sufficient for visualization, but it is not a WGS84 geodetic model.
The Sun state used by the default scene is:
- Sun center relative to Earth center
- expressed in the same Earth-centered practical
J2000/ICRFinertial frame - units in kilometers
Source:
- SPICE
DE440 - Sun relative to Earth center in the practical
J2000/ICRF-aligned inertial frame
The same Sun vector drives:
- main directional light
- visible Sun marker
- day/night illumination direction on Earth and Moon
The night-sky background uses a celestial map aligned with the same inertial axes as the rest of the scene.
Source:
- NASA SVS Deep Star Maps 2020 celestial map
NASA states that this map uses:
- plate carrée projection
- celestial
ICRF/J2000geocentric right ascension and declination - map center at
0hright ascension - right ascension increasing to the left
App mapping rule:
- world
+X=RA 0h,Dec 0° - world
+Y=RA 6h,Dec 0° - world
+Z= north celestial pole
Because the NASA map has right ascension increasing to the left, the sky texture must be mirrored horizontally when applied to the inside of the sphere so that increasing right ascension matches the app's right-handed +X/+Y/+Z convention.
The Moon state used by the default scene is:
- Moon center relative to Earth center
- expressed in the same Earth-centered practical
J2000/ICRFinertial frame - units in kilometers
Source:
- local SPICE computation via
spkez(MOON, et, "J2000", "NONE", EARTH)
Moon position is not fetched from Horizons.
Validation:
- Moon state vectors were cross-checked against JPL Horizons with agreement of about
0.002 kmat the checked epoch
Moon rotation is independent of the translational Moon position. The app uses the standard lunar body-fixed frame:
- IAU lunar pole and prime meridian convention via SPICE
IAU_MOONbody-fixed frame - computed locally via
pxform("J2000", "IAU_MOON", et)
Moon body-fixed convention used by this project:
- right-handed
+Z: lunar north pole+X: lunar prime meridian on the equator+Y: equator /90°E
In the renderer, the Moon body frame is separated from the sphere-mesh correction used to map the equirectangular texture onto Three.js SphereGeometry. That keeps the displayed local axes tied to the physical lunar frame rather than to the mesh's native +Y pole.
The Moon texture is treated as:
- equirectangular longitude-latitude map
- north at top
- south at bottom
- longitude
0°aligned with the lunar prime meridian
The NASA SVS CGI Moon Kit page states that the published Moon map is centered on 0° longitude, which is the required cartographic condition for this frame.
The spacecraft trajectory used by the default scene is:
- spacecraft relative to Earth geocenter
- expressed in practical
J2000/ICRF-aligned coordinates - position in km
- velocity in km/s
Source:
- JPL Horizons REST API (
https://ssd.jpl.nasa.gov/api/horizons.api)
The documented target is COMMAND = -1024, which is the Horizons / NAIF identifier for Artemis II. Horizons also resolves Artemis II, and may accept mission aliases such as Integrity and EM-2.
Trajectory coverage: data starts after ICPS separation, about 3h 24m 39s after launch (2026-Apr-1 @ 22:35:12 UTC), i.e. from approximately 2026-Apr-2 @ 01:59:51 UTC.
Horizons vectors are used as geocentric inertial spacecraft states in the same practical J2000/ICRF-aligned frame used elsewhere in the app.
The app does not include an authoritative spacecraft attitude product. Spacecraft orientation is shown as a visual flight cue:
- point the model approximately along the velocity vector
This orientation is illustrative and not the official Orion attitude history.
BCRS is the barycentric scene mode:
- origin at the Solar System barycenter
- axes aligned with the
ICRS
In BCRS mode, Earth uses its barycentric position from ephemeris data, and Moon/spacecraft positions are shifted from geocentric vectors by Earth's barycentric offset:
Moon_BCRS(t) = Earth_BCRS(t) + Moon_geocentric(t)SC_BCRS(t) = Earth_BCRS(t) + SC_geocentric(t)
Body rotation models do not change in barycentric mode. Earth texture still means Earth-fixed longitude, and Moon texture still means Moon-fixed longitude.
Frames used by the application:
- app render world: right-handed,
+Zup - practical geocentric inertial frame (
GCRSin the UI): right-handed, Earth-centered,J2000/ICRF-aligned - practical barycentric inertial frame (
BCRSin the UI): right-handed, Solar System barycenter origin,J2000/ICRF-aligned - Earth body-fixed frame: right-handed, rotating with Earth
- Moon body-fixed frame: right-handed, rotating with Moon
- mean ecliptic-of-J2000 helper frame: right-handed, obtained from the equatorial frame by rotation about
+Xby the obliquity
The UI uses UTC for mission timestamps and labels.
Horizons vector epochs are reported in JDTDB, and this project converts them to a UTC-facing Julian-date grid in trajectory.json (timeScale: UTC).
Trajectory start JD 2461132.583227 corresponds to about 2026-04-02T01:59:51 UTC in the app's UTC-facing timeline.
In the SPICE generation path, each UTC sample instant is converted explicitly to SPICE ephemeris time before evaluating the Earth, Moon, and Sun states. Trajectory samples from Horizons are then mapped to the app's UTC-facing timeline.
Earth orientation is a separate timing problem from inertial state-vector evaluation. In physical terms, Earth longitude belongs to Earth rotation time (UT1 / sidereal angle), not to the dynamical ephemeris time scale.
The Earth texture stack is treated as a single registered cartographic product:
- day map
- night map
- clouds
- normal map
- specular map
All of them must share:
- the same projection
- the same zero meridian
- the same north-up orientation
Assumptions:
- equirectangular Earth maps
- prime meridian at the horizontal center of the map
- map center aligned to body
+X
The renderer applies the body-frame rotation separately from the sphere-mesh correction that maps cartographic north from Three.js local +Y to body +Z.
Moon texture assumptions:
- equirectangular
- north-up
0°longitude correctly centered- normal map aligned to the exact same grid as the color map
The Moon texture registration is better documented than the Earth texture registration because the NASA SVS CGI Moon Kit explicitly states the 0°-centered cartographic condition.
The application uses the following local-axis conventions:
| Object | Local frame to use | +X |
+Y |
+Z |
Why |
|---|---|---|---|---|---|
| Earth | Earth body-fixed (IAU_EARTH / ECEF-like) |
Greenwich meridian on equator | 90°E on equator |
terrestrial north pole | Standard terrestrial convention; directly compatible with longitude mapping and Earth rotation |
| Moon | Lunar body-fixed (IAU_MOON) |
lunar prime meridian on equator | 90°E lunar longitude |
lunar north pole | Standard IAU/NAIF/SPICE cartographic frame |
| Spacecraft | Visual flight frame (not mission attitude) | prograde (v) |
z × x |
orbit normal (r × v) |
Keeps orientation cues physically interpretable for visualization |
For Earth, local +Z stays aligned with inertial world +Z, while local +X/+Y rotate with Earth rotation.
ephemeris.json contains:
moonPos...: Moon relative to Earth center, inertial geocentric framesunPos...: Sun relative to Earth center, inertial geocentric framemercuryPos...,venusPos...,marsPos...,jupiterPos...,saturnPos...: planetary relative-to-Earth inertial vectors used for scene placementearthPosBCRS: Earth relative to Solar System barycenter, barycentric inertial framegmstRador equivalent Earth orientation quantity: Earth rotation for Earth-fixed longitude mappingmoonOrientation: Moon pole and prime meridian orientation
trajectory.json contains:
- spacecraft position relative to Earth center
- spacecraft velocity relative to Earth center
- epoch tags associated with the declared ephemeris time convention
- mission phase metadata for UI annotation
BCRSmode applies Earth's barycentric translation and keeps Moon/spacecraft offsets from geocentric states.- Earth geographic outputs are spherical, not geodetic.



