Skip to content

About

🛰️ Zero-dependency, fully offline real-time satellite tracker & ground-track visualizer with a hand-written SGP4 propagator. 纯2D/离线/手写轨道力学。

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

🛰️ OrbitScope

Zero-dependency · fully offline · real-time satellite orbit tracker & ground-track visualizer

🌐 Language / 語言:简体中文 | 繁體中文 | English

type deps license sgp4


🎉 Introduction

OrbitScope is a real-time satellite tracker that works the moment you open the web page. Everything — parsing NORAD two-line element sets (TLE), SGP4 orbit propagation, coordinate transforms and map rendering — runs locally in your browser. There is no online map service, no backend, nothing to install, and it works fully offline, even with your network cable unplugged.

  • 🧭 The problem it solves: most satellite trackers lean on online tile maps, a WebGL engine or a backend API. They are heavy, require a connection, and often upload your observing location. OrbitScope shrinks the whole experience into a single web page built on raw Canvas and hand-written orbital mechanics — small enough to run offline by double-clicking a file.
  • ✨ What makes it different:
    • A hand-written SGP4 propagator (near-earth branch, WGS-72 constants, TEME frame), checked point-by-point against the public-domain reference implementation — worst-case position error ≈ 0.7 mm, not an opaque library call;
    • A bundled offline data pack: a TLE snapshot of 15 representative satellites (ISS, China's Tiangong, Hubble, Fengyun-3D, DAMPE, HXMT, …) plus 125 vector land polygons, so opening via file:// just works;
    • An observer-centric view: azimuth / elevation / slant range for any location, an overhead sky radar and 48-hour pass prediction (rise → culmination → set);
    • A time machine: 1×–1800× speed, pause, single-step and "return to now", so you can watch orbital precession and the day/night terminator evolve.
  • 💡 Inspiration: a trending 3D online-globe satellite visualizer inspired the goal of "letting anyone watch a satellite pass overhead". OrbitScope deliberately takes the opposite technical route — pure 2D, zero dependencies, offline-first — and adds the practical piece that project lacked: observer pass prediction. All orbital math is independently implemented from the public Space-Track Report #3 / Vallado public-domain algorithms; no third-party project code was copied.

✨ Features

  • 🛰️ Hand-written SGP4 propagation — the complete near-earth branch (J2/J3/J4 perturbations, B* atmospheric drag), producing TEME position and velocity with sub-millimetre agreement versus the public-domain reference.
  • 📡 Robust TLE parser — fixed-column decoding, compressed scientific-notation expansion, two-digit epoch-year rollover and per-line checksum validation; accepts 2-line/3-line formats and many satellites at once.
  • 🌍 Complete coordinate pipeline — Julian date → GMST sidereal time → TEME→ECEF (including the Earth-rotation velocity term) → Bowring-iterated geodetic lat/lon/altitude → ENU topocentric azimuth / elevation / range.
  • 🗺️ Dependency-free Canvas world map — bundled simplified vector coastlines, graticule, tropics/polar circles and a day/night terminator, seamlessly wrapped horizontally; drag to pan, scroll to zoom.
  • 🛰️ Live positions, one-orbit ground tracks and coverage-footprint ellipses, colour-coded by station / science / weather / Earth-observation; visible satellites glow with a halo.
  • 🧭 Observer panel — 10 city presets (defaults to Hefei), one-click browser geolocation and manual coordinates.
  • 📡 Overhead sky radar — a polar plot showing every satellite currently above your horizon with its azimuth and altitude.
  • 🌅 Pass prediction — for the selected satellite, predicts the next rise time, peak elevation and set time within 48 hours.
  • ⏱️ Time engine — play/pause, 1×/10×/60×/300×/1800× speed, ±1-minute stepping and one-click return to the real current time.
  • 📋 Satellite list — search by name or catalog number, a "visible only" filter and live sorting by current elevation.
  • ➕ Custom TLE — paste any TLE to track it; optionally refresh online from Celestrak (automatically falls back to the bundled snapshot on failure).
  • 🌐 One-click Chinese/English interface; documentation in Simplified Chinese, Traditional Chinese and English.
  • 🔒 Privacy-friendly — all computation stays on your machine; by default no network request is ever made.

🚀 Quick start

📦 Requirements

Item Requirement
Runtime Any modern browser (recent Chrome / Edge / Firefox / Safari)
Node.js Only needed for tests or the local server, ≥ 16 recommended (not needed to run the app)
Network ❌ Not required — fully offline by default
Package install ❌ Zero runtime npm dependencies — no npm install needed

🖱️ Option 1 — just double-click (easiest)

After downloading or cloning, double-click index.html to open it in your browser. The data is bundled, so it works with no connection.

git clone https://github.com/gitstq/orbitscope.git
# then open orbitscope/index.html in a browser

🧑‍💻 Option 2 — local static server (recommended)

cd orbitscope
npm run serve        # equivalent to: node tools/serve.mjs (port 8080)
# open http://localhost:8080

Pick a different port:

node tools/serve.mjs 3000

Why ship a server at all? A few browsers restrict ES Modules over file://. A local server guarantees a consistent experience. No bundler is involved.

✅ Run the tests

npm test

This runs the SGP4 numerical-conformance suite, the coordinate-math suite and an end-to-end pipeline check over every bundled satellite. Expected output:

SGP4 conformance: 20 points checked, 0 failures
  worst position error: 7.143e-7 km (tol 0.001)
coords: 29 checks, 0 failures
pipeline: 15 satellites validated, 0 failures
PASS

📖 Usage guide

🧭 1. Set your observer location

  • Choose a city preset in the "Observer location" panel, or enter decimal degrees manually in Lat / Lon (north/east positive).
  • "Locate" calls the browser geolocation API (used locally only, never uploaded).
  • The white bullseye on the map marks the observer; the sky radar, elevation values and pass predictions are all relative to it.

🛰️ 2. Select and track a satellite

  • Option A: click a satellite dot directly on the map.
  • Option B: click an entry in the satellite list; search by name or NORAD catalog number, and tick "Visible only" to hide everything below the horizon.
  • Once selected you get a gold dashed ground track (half an orbit each way), a dotted coverage-footprint ellipse and a detail panel (lat/lon, altitude, speed, period, inclination, azimuth/elevation/range to you, and the next pass).

⏱️ 3. Control time

Control Effect
⏸ / ▶ Pause / resume the simulated clock
« / » Step back / forward by 1 minute
1×–1800× Time multiplier (at 1800×, one real second ≈ 30 simulated minutes)
Now Jump the simulation back to the real current time

At high speed you can clearly see each orbit drift westward (precession + Earth rotation) and watch satellites cross the day/night terminator.

📡 4. Reading the sky radar and passes

  • The radar is polar: north (N) is at the top, rings map elevation 0°→90° from edge to centre, and the centre is your zenith.
  • Only satellites with elevation > 0° (above the horizon) appear; the header shows how many are visible now.
  • "Next pass" shows rise → culmination (elevation) → set in local time; if no pass occurs within 48 h you are told so explicitly.

➕ 5. Add your own TLE

Click "+ Custom TLE" in the top-right and paste a 2-line or 3-line element set (several at once is fine):

ISS (ZARYA)
1 25544U 98067A   26242.62751382  .00005530  00000+0  10868-3 0  9998
2 25544  51.6315 291.6521 0005038  90.5345 269.6220 15.48940460583296
  • Targets with bad checksums, or deep-space objects (period ≥ 225 min, e.g. geostationary), are skipped automatically.
  • "Update online" fetches the stations / science / weather groups from Celestrak to replace the bundled snapshot; when offline it keeps the bundled data and tells you.

🧩 6. Embedding the math in your own project

The orbital-math layer is fully decoupled from the UI and reusable in the browser or in Node (ESM):

import { parseTleText } from './src/tle.js';
import { initSatellite, propagate, minutesSinceEpoch } from './src/sgp4.js';
import { julianDate, gmst, temeToEcef, ecefToGeodetic } from './src/coords.js';

const [el] = parseTleText(TLE_STRING);
const sat = initSatellite(el);
const when = new Date();
const { position, velocity } = propagate(sat, minutesSinceEpoch(sat, when)); // TEME, km / km·s⁻¹
const gst = gmst(julianDate(when));
const { lat, lon, alt } = ecefToGeodetic(temeToEcef(position, gst));         // geodetic
console.log(lat.toFixed(2), lon.toFixed(2), alt.toFixed(1));

🖼️ Screenshots

Drop a screenshot/GIF here (suggested path assets/screenshot.png): the world-map view, the sky radar and the custom-TLE dialog.


💡 Design notes & roadmap

🧠 Why these choices

  • Hand-write SGP4 instead of importing a library? Zero dependencies and auditability come first. Orbital propagation is the heart of the product; writing it ourselves means owning every perturbation step and locking it with sub-millimetre regression against a public-domain reference — no opaque library or version drift.
  • 2D Canvas instead of a 3D globe? An equirectangular projection expresses ground tracks, coverage and the terminator with the simplest possible math, renders smoothly as a single file, and runs on old or GPU-less devices. A 3D mode is an optional future enhancement.
  • Bundle the data? TLEs and coastlines are tiny (a few KB snapshot, ~68 KB simplified land). Bundling is what makes "double-click, works offline" true; online refresh is an enhancement, not a requirement.
  • Reference frames: propagation uses the historic WGS-72 constants (as SGP4 is defined); the display-layer geodetic conversion uses WGS-84 — the standard industry combination.

🗺️ Architecture

TLE text ──► tle.js parse/validate ──► sgp4.js propagation (TEME)
                                              │
                                              ▼
                    coords.js: GMST → ECEF → geodetic → ENU look-angles
                                              │
              ┌───────────────────────────────┼───────────────────────────────┐
              ▼                               ▼                               ▼
      app.js world map                 sky radar / pass prediction      satellite list / details

🛤️ Roadmap

  • Deep-space SGP4 branch (period ≥ 225 min) for geostationary / Molniya orbits
  • Visual-magnitude (stellar magnitude) estimates and "naked-eye friendly" flags
  • Manage and compare multiple observer ground stations
  • Optional WebGL 3D globe as progressive enhancement (the zero-dependency 2D path stays intact)
  • Favourite satellites / observers with localStorage persistence
  • More bundled groups (navigation constellations, Starlink batches) and more languages (JA / KO / ES)

🙋 How to contribute

New city presets, TLE edge cases, coordinate/SGP4 regression vectors, accessibility improvements and translations are all welcome — see CONTRIBUTING.md.


📦 Build & deployment

OrbitScope is a pure front-end static tool (not a compiled executable), so no platform binaries are released — any static host works.

📁 Direct distribution

The folder itself is the artifact: copy index.html, styles.css and src/ anywhere. There is no build step.

🌐 Static hosting (GitHub Pages / Netlify / Vercel / Nginx)

  • GitHub Pages: Settings → Pages → select the root of the main branch. No build command; output directory /.
  • Nginx: place the folder under root; make sure .js is served as Content-Type: text/javascript (default on modern Nginx).
  • Any object storage: upload all files with read-only access and set index.html as the default document.

🐳 Minimal local container (optional)

docker run --rm -p 8080:80 -v "$PWD":/usr/share/nginx/html:ro nginx:alpine
# open http://localhost:8080

🧵 Compatibility

  • Recommended: Chrome / Edge / Firefox / Safari from the last ~2 years (ES2020 + Canvas 2D required).
  • ES Modules are used, so open via a modern browser or a same-origin static server.
  • Below 980 px viewport width the layout automatically stacks vertically for tablets/phones.

❓ FAQ

Q: Why is a satellite a few kilometres off compared to another site? A: Almost always a stale TLE. A TLE is a fitted initial condition and drifts noticeably after ~2 weeks — refresh online or paste a newer one. The detail panel flags epochs older than 14 days.

Q: Why can't I add a geostationary satellite? A: The current build focuses on near-earth orbits (period < 225 min); the deep-space branch is on the roadmap. Such objects are skipped safely rather than computed incorrectly.

Q: Does it need a network or upload my location? A: It is offline with zero network requests by default; your observer location lives only in page memory. Only when you actively press "Update online" / "Locate" does it contact Celestrak / the browser geolocation service.

Q: A blank screen when opened via file://? A: A few browsers restrict local ES Modules — use npm run serve or any static server instead.


🤝 Contributing

Issues, PRs and translations are welcome! Read CONTRIBUTING.md first. Commit messages follow the Angular convention:

feat: a new feature
fix: a bug fix
docs: documentation only
refactor: refactor with no behaviour change
test: tests
chore: build / tooling

Hard rule: after touching orbital math, npm test must stay green, and no runtime third-party dependency may be introduced (the zero-dependency promise stands).


📄 License

Released under the MIT License — free to use, modify and commercialise, provided the copyright and permission notice is retained.

Third-party data / theory credits:

  • Land outline derived from world-atlas (BSD-3-Clause); underlying geometry from Natural Earth (public domain).
  • Bundled TLE data from Celestrak (redistributing US Space Force 18 SDS element sets).
  • SGP4 theory is the public-domain NORAD standard (Space-Track Report #3; Vallado et al., 2006); the code is an independent hand implementation.

⭐ If OrbitScope is useful to you, a Star helps others find the satellites passing overhead too.

About

🛰️ Zero-dependency, fully offline real-time satellite tracker & ground-track visualizer with a hand-written SGP4 propagator. 纯2D/离线/手写轨道力学。

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages