Quick Start
This tutorial covers the basic usage of the library:
- Parse the orbital elements;
- Propagate satellite orbit for a given date and get basic coordinates;
- Transform the coordinates into different coordinate frames, such as Look Angles (azimuth, elevation, range) for a given observer.
For this tutorial it is assumed that you are familiar with the basics of orbital mechanics (what is SGP4) and the concept of different orbital coordinate systems (Earth-Centered Inertial, Earth-Centered Fixed etc).
Otherwise, please first refer to the following:
- TS Kelso's Columns for Satellite Times, specifically:
- Orbital Propagation
- Orbital Coordinate Systems
- Wikipedia: Simplified Perturbations Model
Key concepts
-
Orbital elements formats:
- Two-Line Element Set (TLE) is an old established format of orbital elements, that usually consists of - funny enough - three lines of text. This is because the first line contains satellite identifiers, and only the following two - hence the "Two-Line" - contain actual parameters of its orbit. It has multiple issues which led to the introduction of OMM.
- Orbit Mean-Elements Message (OMM) - is a new format of orbital elements. It has no issues of its predecessor, it's more universal and is human-readable.
The library supports both TLE and OMM formats of orbital elements, although for new apps, we recommend using OMM. For the OMM format, the library supports JSON flavour only.
-
SatRec- is an object that you will get by parsing TLE or OMM. It is complex, but for this tutorial you don't need to do anything with it except passing around to library functions and accessing theerrorproperty. -
Coordinate frames: This tutorial uses Earth-Centered Inertial (ECI) and Earth-Centered Fixed (ECF) coordinate frames, but you don't need to know exactly how they work. The final step of the tutorial is getting Look Angles of a satellite: its azimuth and elevation in the sky. The other coordinate frames are used only in coordinate transform steps to arrive to Look Angles.
Get orbital elements
It all starts from orbital elements. Use your favourite source to obtain them; we test this library using the following sources:
- Celestrak
- Space-Track - full database available but requires free registration
How to obtain OMM as JSON from Celestrak and Space-Track
To obtain OMM as JSON from Celestrak, select "JSON" option at the top of "Current GP Element Sets" page or follow this link where it will be already selected.
Space-Track doesn't expose the JSON format in their UI, so to get JSON encoded OMM, on "Recent ELSETs" page, from "Current Catalog Files", copy a URL for the needed category and change the ending part of the URL from /format/xml to be /format/json. If you just need full catalog in JSON format, simply download this link (you have to be logged in).
Initialize a SatRec
A SatRec is a container object that holds the information about the satellite orbit, needed for the SGP4. For this tutorial you can treat it as a black box, except for the error property, which is covered later.
import { json2satrec } from 'satellite.js';
// Sample OMM
const omm = {
"OBJECT_NAME": "HELIOS 2A",
"OBJECT_ID": "2004-049A",
"EPOCH": "2025-03-26T05:19:34.116960",
"MEAN_MOTION": 15.00555103,
"ECCENTRICITY": 0.000583,
"INCLINATION": 98.3164,
"RA_OF_ASC_NODE": 103.8411,
"ARG_OF_PERICENTER": 20.5667,
"MEAN_ANOMALY": 339.5789,
"EPHEMERIS_TYPE": 0,
"CLASSIFICATION_TYPE": "U",
"NORAD_CAT_ID": 28492,
"ELEMENT_SET_NO": 999,
"REV_AT_EPOCH": 8655,
"BSTAR": 0.00048021,
"MEAN_MOTION_DOT": 0.00005995,
"MEAN_MOTION_DDOT": 0
};
const satrec = json2satrec(omm);
import { twoline2satrec } from 'satellite.js';
// Sample TLE
const tleLine1 = '1 25544U 98067A 19156.50900463 .00003075 00000-0 59442-4 0 9992',
tleLine2 = '2 25544 51.6433 59.2583 0008217 16.4489 347.6017 15.51174618173442';
const satrec = twoline2satrec(tleLine1, tleLine2);
Calculate ECI state vector
Given a SatRec instance and a moment of time, you can calculate the state vector of the satellite, comprising of position and velocity, in Earth-Centered Inertial (ECI) frame.
The units of measurement are as follows:
- Position vectors, ranges and heights are in km
- Velocity vectors are in km/s
- Angles are measured in radians
ECI frame is the base frame for all further coordinate transforms.
import { propagate, SatRecError } from 'satellite.js';
// you can propagate using a JS Date...
const date = new Date();
const state = propagate(satrec, date);
// If the result is `null`, it means that the propagation failed;
// consult `satrec.error` property for a specific reason.
if (state === null) {
switch (satrec.error) {
// all possible values are listed in SatRecError enum:
case SatRecError.Decayed:
console.log('The satellite has decayed')
// ...
}
throw new Error("Couldn't propagate the satellite");
}
// Otherwise, the result is a pair of ECI coordinates, along with mean elements.
const positionEci = state.position,
velocityEci = state.velocity;
Internally propagate converts the date to minutes since epoch and then calls sgp4, however you can call sgp4 directly as well:
import { sgp4 } from 'satellite.js';
const minutesSinceEpoch = 60;
const state = sgp4(satrec, minutesSinceEpoch);
For a full catalog propagation run at a given date, there will always be some errored satellites, so you need to handle that case. In practice, if you're propagating many satellites, for example to visualise the sky, you can simply filter out errored states by !state condition.
The error property of a SatRec instance is updated every time it is passed to a propagate or sgp4 function. This way, it may error at one moment of time, but propagate successfully for another.
Transform the state vector
You can transform the basic ECI position and velocity into:
- Earth-Centered Fixed (ECF) coordinates
- Geodetic coordinates: longitude, latitude, height
- Look Angles for an observer: elevation, azimuth, range
For some of the coordinate transforms you will need GMST (see Wiki: Sidereal time).
import {
gstime,
degreesToRadians, radiansToDegrees, degreesLong, degreesLat,
eciToEcf,
geodeticToEcf,
eciToGeodetic,
ecfToLookAngles
} from 'satellite.js';
const gmst = gstime(new Date());
// Set the Observer at 122.03 West by 36.96 North, in RADIANS
// height is in kilometers, as mentioned
const observerGeodetic = {
longitude: degreesToRadians(-122.0308),
latitude: degreesToRadians(36.9613422),
height: 0.370
};
// You can get ECF, Geodetic, and Look Angles
const positionEcf = eciToEcf(positionEci, gmst),
velocityEcf = eciToEcf(velocityEci, gmst),
observerEcf = geodeticToEcf(observerGeodetic),
positionGd = eciToGeodetic(positionEci, gmst),
lookAngles = ecfToLookAngles(observerGeodetic, positionEcf);
// The coordinates are all stored in key-value pairs.
// ECI and ECF are accessed by `x`, `y`, `z` properties.
const satelliteX = positionEci.x,
satelliteY = positionEci.y,
satelliteZ = positionEci.z;
// Look Angles may be accessed by `azimuth`, `elevation`, `rangeSat` properties.
const azimuth = lookAngles.azimuth,
elevation = lookAngles.elevation,
rangeSat = lookAngles.rangeSat;
// As azimuth and elevation are in radians, they may be converted to degrees:
const azimuthDegrees = radiansToDegrees(azimuth);
const elevationDegrees = radiansToDegrees(elevation);
// Geodetic coords are accessed via `longitude`, `latitude`, `height`.
const longitude = positionGd.longitude,
latitude = positionGd.latitude,
height = positionGd.height;
// Convert the RADIANS to DEGREES.
const longitudeDeg = degreesLong(longitude),
latitudeDeg = degreesLat(latitude);
Next steps
Now that you know how to calculate satellite position in different coordinate frames, you can:
- Learn more about Coordinate Transforms: all available frame conversions and angle helpers
- Determine if a satellite is in sunlight or shadow: Sun & Shadow
- Calculate frequency shift for radio communication: Doppler Factor
- Propagate tens of thousands of satellites faster with a performance-tailored Bulk Propagation API