AR for satellites: sky-direction overlays and az-el math
Augmented reality for the sky. LaunchDetect's mobile app puts ISS, Starlink, and Hubble into your viewfinder. This week is the math + code that powers it.
Tonight at sunset, where in the sky should you look to see the ISS? Could your phone show you?
Augmented reality answers exactly that. Point your phone at the sky; the ISS appears as a moving dot at the right pixel. This week you'll build the math — and connect it to traditions older than the ISS.
Learning objectives
- Compute azimuth and elevation from observer to satellite
- Project that direction into a smartphone camera frame
- Use device orientation sensors to align the overlay
- Build a working AR overlay for satellite spotting
Primer
Augmented reality for satellite spotting: point your phone at the sky and see exactly where the ISS is, where Starlink trains are about to streak, where a recent SpaceX upper stage is decaying. LaunchDetect's mobile app ships this as a core feature; this week you build the math and the code that powers it.
The geometry
From any observer on Earth, a celestial object's position is described by two angles: azimuth (compass direction, 0° = north, increasing clockwise) and elevation (degrees above the horizontal). Week 9 covered how to compute these from an observer's lat/lon and a satellite's ephemeris.
AR is the inverse problem: given the satellite's azimuth and elevation right now, where should the satellite's icon appear in the camera's viewport? Three coordinate systems involved:
- Earth frame — the satellite's position relative to true north and the local horizontal.
- Phone frame — the phone's current orientation in space (which way is it pointing? how tilted?).
- Camera frame — the camera's pixel grid, where (0, 0) is one corner and (W, H) is the opposite.
DeviceOrientation API
The browser's DeviceOrientation API tells you the phone's orientation:
- alpha — rotation around the vertical (Z) axis, 0–360°. Approximately the compass direction the phone's back is pointing (subject to calibration).
- beta — rotation around the X axis (front-back tilt), -180° to 180°. Phone flat on table = 0°; phone vertical, screen toward user = 90°.
- gamma — rotation around the Y axis (left-right tilt), -90° to 90°.
window.addEventListener('deviceorientation', (event) => {
const alpha = event.alpha; // compass, 0–360
const beta = event.beta; // tilt forward/back
const gamma = event.gamma; // tilt left/right
updateOverlay(alpha, beta, gamma);
});
iOS quirk: Apple requires user permission via DeviceOrientationEvent.requestPermission(). Without that gesture, no events fire. Build the UX accordingly.
Magnetic vs true north
The DeviceOrientation alpha is referenced to magnetic north, not true north. The two differ by the local magnetic declination, which varies from ~0° in much of South America to ~20°+ at high latitudes and can flip sign over a few hundred kilometers. To overlay satellite positions accurately, convert from true north (what skyfield gives you) to magnetic north (what alpha gives you) using a magnetic declination model — the World Magnetic Model (WMM) or its successor IGRF.
JavaScript libraries: geomagnetism on npm wraps WMM and gives declination for a (lat, lon, date) in milliseconds.
Projecting to the viewport
Given the phone's orientation and the satellite's (azimuth_true, elevation), compute the angular offset between the camera's center direction and the satellite's direction. If that offset is within the camera's field of view (typically ~67° horizontal, ~52° vertical for a modern smartphone), place the icon at the corresponding pixel.
// Pseudocode
const dAz = satAzimuth - phoneAzimuth; // wrapped to [-180, 180]
const dEl = satElevation - phoneElevation;
const fovH = 67, fovV = 52;
if (Math.abs(dAz) < fovH/2 && Math.abs(dEl) < fovV/2) {
const x = (W/2) + (dAz / (fovH/2)) * (W/2);
const y = (H/2) - (dEl / (fovV/2)) * (H/2);
placeIcon(x, y);
}
WebXR vs CSS-3D vs DIY
Three implementation approaches:
- DIY (recommended for satellites) — use DeviceOrientation + raw camera
<video>stream + CSS-positioned icons. ~100 lines of code, works on every modern browser. - WebXR — the standardized AR API. More capable but limited browser support (Chrome Android, Safari iOS still rolling out).
- CSS 3D transforms — for simple overlays, CSS
transform: translate3d(...)on iconlets is enough and works universally.
The lab
You'll build a minimal browser-based AR satellite spotter: request DeviceOrientation permission, get the user's GPS lat/lon, compute the ISS's current azimuth and elevation with satellite.js, convert to magnetic-north reference, project onto the camera viewport, and overlay a moving dot. By the end you'll have the same core experience as LaunchDetect's mobile AR feature, in 200 lines of vanilla JavaScript.
Connecting to Hawaiʻi: Wayfinding and the sky overhead
Polynesian wayfinders read the sky by knowing dozens of stars and their rising/setting positions on the horizon. AR satellite-spotting apps work on the same principle: convert a celestial object's altitude and azimuth into a pixel position on your screen. The math is more recent; the spatial-thinking habit is ancient. Many young Hawaiian wayfinders today carry both the traditional knowledge and the modern tools.
Hands-on lab: AR satellite spotter (browser)
Build a browser-based AR demo using the device orientation API. Show a moving dot at the correct azimuth/elevation for the ISS overlaid on the camera view.
Quiz — click an answer to check it
No grade, no shame. Tap any option; you'll see if it's right plus the answer if not. The point is to notice what you already know and what's still settling.
- alpha (compass), beta (front-back tilt), gamma (left-right tilt)
- GPS only
- Time only
- Camera frame only
- True north (or convert from magnetic via declination)
- Always magnetic north
- User's facing direction
- GPS heading
- Vertical position of the satellite icon in the viewport
- It's the only useful angle
- It's irrelevant
- Just for naming
- ~60-70 degrees horizontal
- ~10 degrees
- ~120 degrees always
- ~180 degrees
- WebXR is more capable but limited browser support; CSS-3D is universal and good for simple overlays
- WebXR is universal
- CSS-3D doesn't exist
- Same thing
Reflection
Take five minutes with this. Write your answer somewhere. Carry it into next week.