npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

sgp4.gl

v0.1.5-beta

Published

High-performance SGP4 GPU/WebGPU/WebGL WASM wrapper.

Downloads

370

Readme

sgp4.gl

sgp4.gl, developed by Kayhan Space Corp., is a GPU-accelerated variant of the SGP4 propagator designed to speed up satellite visualizations. By harnessing WebGPU with a WebGL fallback, it enables efficient batch propagation that makes rendering large constellations and dynamic orbital scenes smooth and responsive. The library supports both JavaScript objects and optimized typed arrays for flexible integration, while built-in benchmarks provide insight into performance gains across different methods. Its register-once architecture further optimizes repeated propagations, making it especially useful for interactive visualization tools and real-time orbital displays.

Accuracy notice

sgp4.gl is currently in beta and has not yet undergone the same level of accuracy testing as the CPU-based SGP4 variant. While it delivers substantial performance improvements for rendering and exploration, it should be used strictly for visualization purposes. Regardless of any discrepancies introduced by sgp4.gl, SGP4 and TLEs themselves in general are not suitable for high-precision analysis or operational decision-making. For those cases, we strongly recommend relying on Owner/Operator or Special Perturbations (SP) ephemerides instead.

Useful links

npm | https://www.npmjs.com/package/sgp4.gl

Repo | https://github.com/Kayhan-Space/sgp4gl

Lightweight Demo | https://sgp4gl-demo.vercel.app/lightweight

Cesium 3D visualization | https://sgp4gl-demo.vercel.app

Cesium 3D visualization repo | https://github.com/Kayhan-Space/sgp4gl-demo

TLEs | https://www.satcat.com

Kayhan Space | https://www.kayhan.space

Building the module

To install, build, and run the demo...

npm  install
npm  run  build

Running the demo locally

npx  serve  .

What is SGP4?

SGP4 stands for Simplified General Perturbations 4 and is arguably the most widely used propagator for simulating earth satellite orbits. This module is my personal project to produce implementations in multiple languages. There is an official government document released decades ago that describes the theory and the software. That document is known as Spacetrack Report #3. In 2006 researchers at the Center for Space Standards and Innovation (CSSI) published a detailed study of the algorithm and more modern software implementations. In addition to the paper they also released the software. Most importantly they produced an extensive set of test cases that cover multiple orbit regimes, potential singularities, and other tricky orbits.

Available Methods

Traditional Object-based API

const results = await propagator.propagate_batch(gpuConsts, times);
// Returns: Array<{position: [x, y, z], velocity: [vx, vy, vz]}>

Optimized Float32Array API

const resultArray = await propagator.propagate_batch_f32(gpuConsts, times);
// Returns: Float32Array with layout [x1, y1, z1, vx1, vy1, vz1, x2, y2, z2, ...]
// Each satellite uses 6 consecutive values: [x, y, z, vx, vy, vz]

Register-Once Pattern (Useful for globe views)

// Register constellation once (this consumes the gpuConsts array)
const constSetId = propagator.register_const_set(gpuConsts);

// Propagate many times with different time arrays
const times1 = new Float64Array([0, 10, 20]); // minutes since epoch
const results1 = await propagator.propagate_registered_f32(constSetId, times1);

const times2 = new Float64Array([30, 40, 50]);
const results2 = await propagator.propagate_registered_f32(constSetId, times2);

// Cleanup when done
propagator.unregister_const_set(constSetId);

Performance Benefits

The optimized methods provide significant performance improvements:

| Method | Memory Usage | Performance | Best For | | ----------------- | -------------------- | ---------------- | --------------------------------- | | Object-based | ~48 bytes/satellite | Baseline | Simple single-shot propagations | | Float32Array | ~24 bytes/satellite | 2–5× faster | Batch processing | | Register-Once | Minimal overhead | 5–10× faster | Real-time tracking, animation |

Register-Once Pattern Benefits

  • Zero Serialization: Constants stored in WASM, no boundary crossing
  • Minimal Memory: Constants registered once, reused many times
  • Ultra-Fast: Perfect for real-time tracking (50+ updates/second)
  • Flexible: Same constellation, different times per propagation
  • Optimal Performance: Takes ownership for zero-copy efficiency

Important Notes

  • register_const_set() consumes the constants array for optimal performance
  • If you need the constants elsewhere, create them separately before registration
  • Use unregister_const_set() to free memory when done with a constellation

Usage Example

import wasmInit, {
  WasmElements,
  WasmConstants,
  WasmGpuConsts,
  GpuPropagator,
} from "./pkg/sgp4.js";

// Initialize WASM
await wasmInit();

// Parse TLE data for constellation
const satellites = [
  {
    name: "ISS",
    line1: "1 25544U 98067A 25253.41957898 .00007229 00000-0 13349-3 0 9991",
    line2:
      "2 25544 51.6328 244.6218 0004204 323.0394 37.0305 15.50221013528382",
  },
  // ... more satellites
];

// Create GPU constants

const elements = satellites.map((sat) =>
  WasmElements.from_tle(
    new TextEncoder().encode(sat.name),
    new TextEncoder().encode(sat.line1),
    new TextEncoder().encode(sat.line2)
  )
);

const constants = elements.map((el) => WasmConstants.from_elements(el));
const gpuConsts = constants.map((c) => WasmGpuConsts.from_constants(c));

// Create GPU propagator
const propagator = await GpuPropagator.new_for_web();

// Register constellation for repeated use
const constSetId = propagator.register_const_set(gpuConsts);
console.log(`Registered ${gpuConsts.length} satellites with ID: ${constSetId}`);

// Real-time tracking loop

for (let t = 0; t < 3600; t += 60) {
  // Every minute for 1 hour
  const times = new Float64Array(gpuConsts.length);
  times.fill(t); // All satellites at time t
  const results = await propagator.propagate_registered_f32(constSetId, times);

  // Process results - results is Float32Array with [x,y,z,vx,vy,vz,...]
  for (let i = 0; i < gpuConsts.length; i++) {
    const offset = i * 6;

    const position = [
      results[offset],
      results[offset + 1],
      results[offset + 2],
    ];

    const velocity = [
      results[offset + 3],
      results[offset + 4],
      results[offset + 5],
    ];

    console.log(`${satellites[i].name}: ${position} km, ${velocity} km/s`);
  }
}

// Cleanup when done
propagator.unregister_const_set(constSetId);

Data Layout

For N satellites, the typed arrays contain N × 6 values:

[sat0_x, sat0_y, sat0_z, sat0_vx, sat0_vy, sat0_vz,
sat1_x, sat1_y, sat1_z, sat1_vx, sat1_vy, sat1_vz,
...
satN_x, satN_y, satN_z, satN_vx, satN_vy, satN_vz]

Access pattern for satellite i:

const offset = i * 6;

const position = [results[offset], results[offset + 1], results[offset + 2]];

const velocity = [
  results[offset + 3],
  results[offset + 4],
  results[offset + 5],
];

Browser Compatibility

  • WebGPU: Chrome, Edge, Firefox (only on https), Safari (latest iOS)