Significant PV Discrepancy in KeplerianOrbit Conversion (Orekit 12.0.1) vs. STK (J2000, Two-Body) for Non-Zero RAAN
Hello Orekit Community,
I am experiencing a significant discrepancy when converting Keplerian orbital elements to inertial PV coordinates (EME2000/J2000) using Orekit 12.0.1 compared to the results obtained from STK using the same elements and the Two-Body propagator with the J2000 coordinate system.
Problem Description:
The discrepancy primarily occurs when the Right Ascension of the Ascending Node (RAAN) is non-zero.
- When RAAN = 0: The initial PV coordinates (position [x, y, z] and velocity [vx, vy, vz]) calculated by Orekit’s
KeplerianOrbit.getPVCoordinates()
at the epoch are very close to the values reported by STK for the same epoch. - When RAAN != 0: The initial PV coordinates calculated by Orekit show a large difference compared to STK, specifically in the y and z components of the position vector (and potentially velocity). The x component remains relatively close.
This suggests the issue might stem from how the rotation associated with RAAN (and potentially inclination) is handled during the conversion from Keplerian elements to Cartesian PV coordinates in Orekit, compared to STK’s implementation, even when both are using the standard J2000/EME2000 frame and a simple Two-Body model.
Minimal Reproducible Example (MCVE):
Here is a simple Java code snippet using Orekit 12.0.1 demonstrating the calculation for a non-zero RAAN case:
import org.hipparchus.geometry.euclidean.threed.Vector3D;
import org.orekit.data.DataContext;
import org.orekit.data.DirectoryCrawler;
import org.orekit.frames.Frame; // Added import
import org.orekit.frames.FramesFactory;
import org.orekit.orbits.KeplerianOrbit;
import org.orekit.orbits.PositionAngleType;
import org.orekit.time.AbsoluteDate;
import org.orekit.time.TimeScalesFactory;
import org.orekit.utils.Constants;
import org.orekit.utils.PVCoordinates;
import java.io.File;
public class TestPVDiscrepancy {
public static void main(String[] args) {
// --- Orekit Initialization ---
File orekitData = new File("/path/to/my/orekit-data");
if (!orekitData.exists()) {
System.err.println("Error: orekit-data directory not found at " + orekitData.getAbsolutePath());
return;
}
DataContext.getDefault().getDataProvidersManager().addProvider(new DirectoryCrawler(orekitData));
// --- Input Keplerian Elements (Identical to STK Input) ---
double semiMajorAxis = 6878.14 * 1000; // meters (approx. 500 km altitude)
double eccentricity = 0.001; // Near-circular
double inclination = 45.0; // degrees
double raan = 36.0; // degrees (Non-zero RAAN case)
double argumentOfPerigee = 0.0; // degrees
double trueAnomaly = 0.0; // degrees (Initial position at ascending node)
AbsoluteDate epoch = new AbsoluteDate(2025, 1, 1, 4, 0, 0.0, TimeScalesFactory.getUTC());
// --- Reference Frame ---
Frame inertialFrame = FramesFactory.getEME2000(); // Using EME2000 (J2000 equivalent)
try {
// --- Create KeplerianOrbit object ---
KeplerianOrbit orbit = new KeplerianOrbit(
semiMajorAxis,
eccentricity,
Math.toRadians(inclination),
Math.toRadians(raan),
Math.toRadians(argumentOfPerigee),
Math.toRadians(trueAnomaly),
PositionAngleType.TRUE, // Using true anomaly
inertialFrame,
epoch,
Constants.WGS84_EARTH_MU
);
// --- Get PV Coordinates directly from the Orbit object at epoch ---
PVCoordinates pvOrekit = orbit.getPVCoordinates(inertialFrame); // Gets PV at orbit's epoch
// --- Output Orekit Results ---
Vector3D posOrekit = pvOrekit.getPosition();
Vector3D velOrekit = pvOrekit.getVelocity();
System.out.println("--- Orekit 12.0.1 Results (EME2000) ---");
System.out.println("Epoch: " + epoch);
System.out.println("Input RAAN (deg): " + raan);
System.out.println("Calculated Position (m): " + posOrekit);
System.out.println(" X: " + posOrekit.getX());
System.out.println(" Y: " + posOrekit.getY());
System.out.println(" Z: " + posOrekit.getZ());
System.out.println("Calculated Velocity (m/s): " + velOrekit);
System.out.println(" Vx: " + velOrekit.getX());
System.out.println(" Vy: " + velOrekit.getY());
System.out.println(" Vz: " + velOrekit.getZ());
// --- STK Comparison Results (Manual Input Required) ---
System.out.println("\\n--- STK Results (J2000, Two-Body) ---");
System.out.println("Epoch: " + epoch + " (Please verify time matches)");
System.out.println("Input RAAN (deg): " + raan);
double stk_x = 5564529.722;
double stk_y = 4042867.492 ;
double stk_z = -1.348 ;
double stk_vx = -3164.004 ;
double stk_vy = 4354.879 ;
double stk_vz = 5382.927;
System.out.println("Reported Position (m): X=" + stk_x + ", Y=" + stk_y + ", Z=" + stk_z);
System.out.println("Reported Velocity (m/s): Vx=" + stk_vx + ", Vy=" + stk_vy + ", Vz=" + stk_vz);
// --- Calculate Differences ---
System.out.println("\\n--- Differences (Orekit - STK) ---");
System.out.println(" Delta X (m): " + (posOrekit.getX() - stk_x));
System.out.println(" Delta Y (m): " + (posOrekit.getY() - stk_y)); // Expected to be large
System.out.println(" Delta Z (m): " + (posOrekit.getZ() - stk_z)); // Expected to be large
System.out.println(" Delta Vx (m/s): " + (velOrekit.getX() - stk_vx));
System.out.println(" Delta Vy (m/s): " + (velOrekit.getY() - stk_vy)); // Potentially large
System.out.println(" Delta Vz (m/s): " + (velOrekit.getZ() - stk_vz)); // Potentially large
} catch (Exception e) {
e.printStackTrace();
}
}
}
- Orekit Version: 12.0.1
- Java Version:JDK 21
- Operating System: Windows 11
- STK Version: 11