Hello,
I need ISS altitude data every 3 minutes for three 90-minute periods. I specifically need altitude above Earth’s surface, not distance from Earth’s center.
Is there a NASA dataset or tool that provides this directly? If not, what is the recommended way to calculate it from ISS position data?
Thank you.
ISS altitude above Earth’s surface at 3-minute intervals
-
davidu2805
- Posts: 1
- Joined: Thu Jul 23, 2026 10:25 pm America/New_York
-
ASDC - rkey
- Posts: 91
- Joined: Thu Dec 12, 2019 1:20 pm America/New_York
- Endorsed: 6 times
Re: ISS altitude above Earth’s surface at 3-minute intervals
Hello @daivdu2805,
We've received the following response from our Subject Matter Expert (SME):
We've received the following response from our Subject Matter Expert (SME):
The best way for the public to get data regarding the ISS trajectory is the Spot The Station website and app. On the Spot The Station page is a heading titled 'International Space Station Trajectory Data" which has links to the most recent predicted trajectory files. All that said, the altitude is generally fairly invariant as we try to keep ISS in as circular an orbit as possible.
The file gives position in EME2000 Cartesian coordinates (X, Y, Z in km). The process is:
This file is exactly that dataset. It is produced by the TOPO office within the NASA Flight Operations Directorate at JSC and is the most authoritative available source of ISS trajectory data. It covers the date range 2026-07-27 through 2026-08-11 at 4-minute intervals.
- Compute geocentric distance r = √(X² + Y² + Z²)
- Compute local WGS84 ellipsoid radius at that position's geocentric latitude
The Python code below implements this exactly, interpolates to 3-minute intervals using a cubic spline, and exports a clean CSV for three 90-minute periods.
- Altitude = r − WGS84 local radius
Code: Select all
import numpy as np
from scipy.interpolate import CubicSpline
from datetime import datetime, timedelta
import pandas as pd
# ─── WGS84 constants ───────────────────────────────────────────────
a = 6378.137 # semi-major axis (km)
b = 6356.7523142 # semi-minor axis (km)
def wgs84_radius(z, r):
"""Local Earth radius at geocentric latitude derived from Z/r."""
sin_lat = z / r
cos_lat = np.sqrt(1 - sin_lat**2)
# WGS84 ellipsoid radius at geocentric latitude
num = (a**2 * cos_lat)**2 + (b**2 * sin_lat)**2
den = (a * cos_lat)**2 + (b * sin_lat)**2
return np.sqrt(num / den)
def altitude_above_surface(x, y, z):
"""Convert EME2000 X,Y,Z (km) to altitude above WGS84 surface (km)."""
r = np.sqrt(x**2 + y**2 + z**2)
R_earth = wgs84_radius(z, r)
return r - R_earth
# ─── Parse the OEM file ────────────────────────────────────────────
def parse_oem(filepath):
times, positions, velocities = [], [], []
with open(filepath, 'r') as f:
for line in f:
line = line.strip()
# Data lines: ISO timestamp followed by 6 floats
parts = line.split()
if len(parts) == 7:
try:
t = datetime.strptime(parts[0], '%Y-%m-%dT%H:%M:%S.%f')
x, y, z = float(parts[1]), float(parts[2]), float(parts[3])
vx, vy, vz = float(parts[4]), float(parts[5]), float(parts[6])
times.append(t)
positions.append([x, y, z])
velocities.append([vx, vy, vz])
except ValueError:
continue
return times, np.array(positions), np.array(velocities)
# ─── Main processing ───────────────────────────────────────────────
times, pos, vel = parse_oem('ISS.OEM_J2K_EPH.txt') # replace with your filename
# Convert times to seconds since epoch for interpolation
t0 = times[0]
t_sec = np.array([(t - t0).total_seconds() for t in times])
# Build cubic spline interpolators for X, Y, Z
cs_x = CubicSpline(t_sec, pos[:, 0])
cs_y = CubicSpline(t_sec, pos[:, 1])
cs_z = CubicSpline(t_sec, pos[:, 2])
# Using first three orbits starting from beginning of file
period_starts = [
datetime(2026, 7, 27, 12, 0, 0), # Period 1 start
datetime(2026, 7, 27, 13, 32, 0), # Period 2 start (~1 orbit later)
datetime(2026, 7, 27, 15, 4, 0), # Period 3 start (~2 orbits later)
]
results = []
for i, start in enumerate(period_starts):
print(f"\n{'='*60}")
print(f" PERIOD {i+1}: Starting {start.isoformat()}")
print(f"{'='*60}")
print(f"{'UTC Time':<30} {'Alt (km)':>10} {'r (km)':>10}")
print(f"{'-'*52}")
current = start
while current <= start + timedelta(minutes=90):
t_s = (current - t0).total_seconds()
if 0 <= t_s <= t_sec[-1]:
x = cs_x(t_s)
y = cs_y(t_s)
z = cs_z(t_s)
r = np.sqrt(x**2 + y**2 + z**2)
alt = altitude_above_surface(x, y, z)
print(f"{current.isoformat():<30} {alt:>10.3f} {r:>10.3f}")
results.append({
'Period': i + 1,
'UTC_Time': current.isoformat(),
'X_km': round(float(x), 3),
'Y_km': round(float(y), 3),
'Z_km': round(float(z), 3),
'Geocentric_Dist_km': round(float(r), 3),
'Alt_Above_Surface_km': round(float(alt), 3)
})
current += timedelta(minutes=3) # 3-minute intervals
df = pd.DataFrame(results)
df.to_csv('ISS_altitude_3min_three_periods.csv', index=False)
print(f"\n✅ Saved {len(df)} records to ISS_altitude_3min_three_periods.csv")Best Regards!Sample file from NASA webpage:
https://nasa-public-data.s3.amazonaws.com/iss-coords/current/ISS_OEM/ISS.OEM_J2K_EPH.txt