Satellite-Local Coordinate Frames for Maneuvers¶
When you schedule an impulsive burn or a continuous thrust arc in satkit, you
specify the delta-v as a 3-vector plus a reference frame. The frame tells
satkit how to interpret the components of the vector relative to the
satellite's instantaneous state at the burn time.
satkit supports four frames for maneuvers:
| Frame | Axis definition | Best used for |
|---|---|---|
GCRF |
Inertial Earth-centred Cartesian | Burns specified in inertial axes |
RTN (a.k.a. RSW, RIC) |
Radial / Tangential / Normal (tied to position) | CCSDS OEM covariance, relative motion, radial/cross-track components |
NTW |
Normal / Tangent / Cross-track (tied to velocity) | Prograde/retrograde burns, Hohmann transfers |
LVLH |
Local Vertical / Local Horizontal (nadir-pointing) | Porting crewed-spaceflight / GN&C code |
For circular orbits the three non-inertial frames all boil down to the same three directions. For eccentric orbits they differ in subtle but physically meaningful ways, and choosing the wrong frame will give you a measurably wrong answer. This guide explains the differences.
The orbital plane and the three natural directions¶
Every satellite orbit lies (instantaneously) in a plane determined by the position vector \(\vec{r}\) and the velocity vector \(\vec{v}\). The angular momentum \(\vec{h} = \vec{r} \times \vec{v}\) is perpendicular to that plane. This gives us three natural directions:
- Radial — along \(\hat{r}\), outward from Earth's centre
- Tangent — along \(\hat{v}\), the direction of motion
- Cross-track — along \(\hat{h}\), out of the orbital plane
The three non-inertial frames all use some permutation and sign of these three directions, but they do not all use the same "in-plane prograde" axis. That's where the subtlety lives.
On a circular orbit (\(\gamma = 0\)) all three frames coincide up to sign conventions — RTN's radial is LVLH's \(-\hat{z}\), NTW's tangent is RTN's \(\hat{I}\), and so on. The axes overlap in the figure above. The difference only appears on eccentric orbits.
The flight-path angle¶
For a circular orbit, the position vector \(\vec{r}\) and velocity vector \(\vec{v}\) are exactly perpendicular — the satellite moves along the circumference. For an eccentric orbit, \(\vec{r}\) and \(\vec{v}\) are only perpendicular at perigee and apogee. At all other points the velocity has a radial component, and the angle between \(\vec{v}\) and the local "horizontal" (perpendicular to \(\vec{r}\)) is called the flight-path angle \(\gamma\):
where \(e\) is eccentricity and \(\nu\) is true anomaly. For a low-eccentricity LEO (\(e \sim 0.001\)) the flight-path angle is tiny (~0.06°) and the distinction below doesn't matter in practice. For a GTO (\(e = 0.73\)) at mid-anomaly the flight-path angle can reach ~45° and the distinction matters a lot.
On the eccentric orbit (\(e = 0.3\), \(\nu = 60°\)) above, RTN's \(\hat{T}\) and NTW's \(\hat{T}\) are no longer the same direction — they differ by the flight-path angle \(\gamma \approx 12.7°\). Likewise RTN's radial \(\hat{R}\) and NTW's in-plane-normal \(\hat{N}\) differ by the same angle. This is the geometric origin of every issue in the rest of this guide.
RTN (RSW / RIC) — position-tied¶
R = r̂ (radial, outward)
T = ĥ × r̂ (tangential / in-track, perpendicular to R in the orbit plane)
N = ĥ (normal / cross-track, along angular momentum)
The tangential (T) axis is perpendicular to the position vector, not to the velocity vector. For a circular orbit these are the same thing, but for an eccentric orbit at non-apsidal anomaly they differ by \(\gamma\). Two other common names for this same frame:
- RSW — Vallado's convention (R, S=Ŵ×R̂, W=ĥ). The prevailing name in astrodynamics textbooks.
- RIC — older NASA usage (Radial / In-track / Cross-track), common in Clohessy-Wiltshire relative-motion literature.
satkit's canonical name is RTN (matching the CCSDS OEM/OMM/ODM
convention); Frame::RSW and Frame::RIC are provided as compile-time
aliases so code can spell the frame whichever way matches the source
it's transcribing from. In Python, sk.frame.RSW and sk.frame.RIC are
class-level aliases that compare equal to sk.frame.RTN, so
sk.frame.RSW == sk.frame.RTN is True.
When to use RTN for maneuvers:
- You're reading or generating CCSDS OEM / OMM / ODM messages, whose covariance and delta-v blocks are standardised on the RTN frame.
- You want to specify burn components in the "radial / along-track / cross-track" basis that's conventional for relative motion (Clohessy-Wiltshire, Hill's equations — these papers usually write it as RIC).
- You're translating formulas from Vallado (written as RSW) or the CCSDS spec (written as RTN).
Covariance convention in satkit
satkit's state-vector uncertainty API — SatState.set_pos_uncertainty
and set_vel_uncertainty — accepts any of GCRF, LVLH, RTN, or
NTW via a frame parameter. Pass frame=sk.frame.RTN if you're
loading covariance values from a CCSDS OEM file (or use the
equivalent sk.frame.RIC / sk.frame.RSW aliases), or
frame=sk.frame.LVLH if you're thinking in nadir/along-track/
cross-track sigmas.
When not to use RTN:
- You want "10 m/s along velocity" to mean exactly that, for an eccentric orbit. A RTN +T burn of 10 m/s only increases \(|\vec{v}|\) by \(10\cos\gamma\), not by 10. Use NTW instead.
NTW — velocity-tied¶
T = v̂ (tangent, along velocity)
W = ĥ (cross-track, along angular momentum — same as RTN's N)
N = T̂ × Ŵ (in-plane normal to velocity)
The tangent (T) axis is parallel to the velocity vector always, regardless of eccentricity. That's what makes NTW the natural frame for "thrust along velocity" scenarios.
The N axis is perpendicular to velocity in the orbit plane. For a circular orbit N coincides with the outward radial direction; for an eccentric orbit N leans off-radial by the flight-path angle.
When to use NTW for maneuvers:
- Prograde / retrograde burns — a pure +T burn of magnitude \(\Delta v\) adds exactly \(\Delta v\) to \(|\vec{v}|\). This is the only frame for which that's true.
- Hohmann transfers, bi-elliptic transfers, station-keeping burns — any burn whose intent is "add energy to the orbit along the current velocity direction".
- Electric propulsion mission profiles with a long tangential thrust arc.
- Eccentric transfer orbits (GTO, lunar transfer) where the flight-path angle matters.
This is the frame described in Vallado §3.3 (eq 3-31).
LVLH — body-pointing¶
z = −r̂ (nadir; points toward Earth's centre)
y = −ĥ (opposite angular momentum)
x = ŷ × ẑ = ĥ × r̂ (completes the right-handed system)
The classical Local Vertical / Local Horizontal frame, used by the ISS and most crewed / Earth-pointing vehicles for attitude control. The distinguishing feature is that z points down — the frame assumes you want the satellite pointing at Earth.
Geometrically LVLH spans the same orbital plane as RTN. The axes are just relabeled and sign-flipped:
- LVLH \(+\hat{x}\) = RTN \(+\hat{T}\) (tangential; perpendicular to R, not V)
- LVLH \(-\hat{z}\) = RTN \(+\hat{R}\) (radial outward)
- LVLH \(-\hat{y}\) = RTN \(+\hat{N}\) (cross-track)
So LVLH has the same "in-track is not quite velocity" caveat as RTN for eccentric orbits.
When to use LVLH for maneuvers:
- You're translating GN&C code originally written in LVLH body-frame conventions.
- You think in "nadir / in-track / out-of-plane" rather than "radial / tangential / normal".
For everything else, RTN or NTW will be more natural.
The key distinction, in numbers¶
Consider an eccentric orbit with semi-major axis \(a = 8000\) km, eccentricity \(e = 0.3\), at true anomaly \(\nu = 60°\). The flight-path angle at this point is \(\gamma \approx 12.7°\). Apply a 10 m/s delta-v in each frame with the "prograde-like" component equal to 10 m/s:
| Frame | Specification | \(\Delta |\vec{v}|\) actually added |
|---|---|---|
| NTW | (0, 10, 0) — +T | 10.000 m/s (exact) |
| RTN | (0, 10, 0) — +T (tangential) | 9.755 m/s |
| LVLH | (10, 0, 0) — +x | 9.755 m/s (same as RTN +T) |
The loss of 0.245 m/s in the RTN / LVLH case is exactly \(10(1 - \cos\gamma)\). For a high-precision Hohmann transfer injection burn, a quarter-meter-per-second error is a lot. This is why NTW is the right choice when you care about "energy added along velocity".
The figure above shows a velocity-space view of the same eccentric state. The black arrow is the current velocity \(\vec{v}\); the orange and blue arrows are two hypothetical 1.5 km/s \(\Delta v\) burns (exaggerated from 10 m/s for visibility) specified in NTW and RTN respectively. Both burns have the same nominal magnitude, but the NTW burn points along \(\vec{v}\) while the RTN burn points perpendicular to the position vector — and those are not the same direction on an eccentric orbit. The dotted circles show the resulting \(|\vec{v}|\) after each burn; the NTW circle is farther from the origin, meaning it added more speed.
Cheat sheet¶
- "I want to add 10 m/s prograde on any orbit" → NTW, or
sat.add_prograde(time, 10.0)(Python) /ImpulsiveManeuver::prograde(Rust). These helpers pick NTW for you. - "I want a radial-out burn of 1 m/s" → NTW +N
(
sat.add_radial(time, 1.0)), or RTN +R if you want strict outward-r. - "I want a cross-track burn of 0.5 m/s" → NTW +W or RTN +N — they're the same axis.
- "I'm porting code from CCSDS OEM that uses RTN" → RTN
(
frame.RTNin Python;Frame::RTNin Rust). - "I'm porting code from Vallado that uses RSW" → use
frame.RSW/Frame::RSW— it's an alias for the same frame as RTN. - "I'm porting code from the Clohessy-Wiltshire / relative-motion
literature that uses RIC" → use
frame.RIC/Frame::RIC— also an alias for the same frame. - "My delta-v vector is already in ECI / J2000 inertial" → GCRF.
- "I'm porting GN&C code written in LVLH" → LVLH.
Summary table¶
| Property | GCRF | RTN / RSW / RIC | NTW | LVLH |
|---|---|---|---|---|
| Inertial? | Yes | No | No | No |
| Prograde axis parallel to \(\hat{v}\)? | — | Only if \(\gamma = 0\) | Always | Only if \(\gamma = 0\) |
| Cross-track axis | — | \(+\hat{h}\) | \(+\hat{h}\) | \(-\hat{h}\) |
| Radial-out axis | — | \(+\hat{R}\) | \(+\hat{N}\) (only on circular) | \(-\hat{z}\) |
satkit covariance uncertainty API |
Yes | Yes | Yes | Yes |
| CCSDS OEM covariance convention | No | Yes (as RTN) | No | No |
| Natural for prograde burns | No | Only on circular | Yes | Only on circular |
| Natural for crewed-flight GN&C | No | No | No | Yes |
Reference¶
- Vallado, D., Fundamentals of Astrodynamics and Applications, 4th ed., §3.3 — definitions of RSW and NTW frames.
- CCSDS 502.0-B-3, Orbit Data Messages, Annex C — RTN frame in CCSDS OEM/OMM messages.
- Montenbruck, O. and Gill, E., Satellite Orbits, §2.4 — LVLH frame definitions and relative motion.