Eccentricity check in TLE constructor provokes failure in TLE fitting
I am working on generating TLE for a satellite based on the state vector at launcher separation.
I running into the error below when running the code below.
This is actually due to merge request !51 (merged) (which was actually done by me): !51 (5f66e223)
The eccentricity has now a range check [0.0, 1.0] since !51 (merged), because I was thinking that an orbit using the SGP4 model cannot be a hyperbolic trajectory. In this case, the FiniteDifferencePropagatorConverter
tries orbits which are actually hyperbolic.
I tried running the same code using Orekit 10.1, and in this case it works fine and provides a TLE which is consistent with the state vector at separation.
The fix could be straightforward: removing the range check on the eccentricity. However, I would like to have other opinions here, because I don't really know how FiniteDifferencePropagatorConverter
works.
org.orekit.errors.OrekitException: invalid TLE parameter eccentricity: 1.15 not in range [0, 1] at org.orekit.propagation.analytical.tle.TLE.checkParameterRangeInclusive(TLE.java:833) at org.orekit.propagation.analytical.tle.TLE.(TLE.java:373) at org.orekit.propagation.conversion.TLEPropagatorBuilder.buildPropagator(TLEPropagatorBuilder.java:164) at org.orekit.propagation.conversion.FiniteDifferencePropagatorConverter$ObjectiveFunction.value(FiniteDifferencePropagatorConverter.java:67) at org.orekit.propagation.conversion.FiniteDifferencePropagatorConverter$ObjectiveFunctionJacobian.value(FiniteDifferencePropagatorConverter.java:101) at org.hipparchus.optim.nonlinear.vector.leastsquares.LeastSquaresFactory$LocalLeastSquaresProblem.evaluate(LeastSquaresFactory.java:440) at org.hipparchus.optim.nonlinear.vector.leastsquares.LeastSquaresAdapter.evaluate(LeastSquaresAdapter.java:68) at org.hipparchus.optim.nonlinear.vector.leastsquares.LeastSquaresFactory$1.evaluate(LeastSquaresFactory.java:201) at org.hipparchus.optim.nonlinear.vector.leastsquares.LevenbergMarquardtOptimizer.optimize(LevenbergMarquardtOptimizer.java:450) at org.orekit.propagation.conversion.AbstractPropagatorConverter.fit(AbstractPropagatorConverter.java:347) at org.orekit.propagation.conversion.AbstractPropagatorConverter.adapt(AbstractPropagatorConverter.java:317) at org.orekit.propagation.conversion.AbstractPropagatorConverter.convert(AbstractPropagatorConverter.java:184) at org.orekit.propagation.analytical.tle.TLEFittingIssue.test(TLEFittingIssue.java:80)
Here is the code (simplified a little bit, and ported from Python). The code is also available in my branch yzokras/orekit@8fe8186b
package org.orekit.propagation.analytical.tle;
import java.util.ArrayList;
import org.junit.Test;
import org.orekit.Utils;
import org.orekit.frames.Frame;
import org.orekit.frames.FramesFactory;
import org.orekit.orbits.CartesianOrbit;
import org.orekit.orbits.PositionAngle;
import org.orekit.propagation.SpacecraftState;
import org.orekit.propagation.analytical.KeplerianPropagator;
import org.orekit.propagation.conversion.FiniteDifferencePropagatorConverter;
import org.orekit.propagation.conversion.TLEPropagatorBuilder;
import org.orekit.time.AbsoluteDate;
import org.orekit.time.TimeScale;
import org.orekit.time.TimeScalesFactory;
import org.orekit.utils.Constants;
import org.orekit.utils.IERSConventions;
import org.orekit.utils.PVCoordinates;
import org.hipparchus.geometry.euclidean.threed.Vector3D;
import org.hipparchus.util.FastMath;
public class TLEFittingIssue {
@Test
public void test() {
Utils.setDataRoot("regular-data");
int satellite_number = 99999;
char classification = 'U';
int launch_year = 2020;
int launch_number = 1;
String launch_piece = "a";
int ephemeris_type = 0;
int element_number = 1;
int revolution_number = 1;
double mean_motion_first_derivative = 0.0;
double mean_motion_second_derivative = 0.0;
double b_star_first_guess = 1e-5;
TimeScale utc = TimeScalesFactory.getUTC();
Frame itrf = FramesFactory.getITRF(IERSConventions.IERS_2010, true);
Frame gcrf = FramesFactory.getGCRF();
AbsoluteDate launchDate = new AbsoluteDate(2020, 9, 28, 11, 20, 32.0, utc);
AbsoluteDate separationDate = launchDate.shiftedBy(12340.0);
Frame launchFrame = itrf.getFrozenFrame(gcrf, launchDate, "launchFrame");
Vector3D pos_init = new Vector3D(6048.107, 3025.385, 1585.042).scalarMultiply(1e3);
Vector3D vel_init = new Vector3D(-1.068882, -1.694130, 7.304083).scalarMultiply(1e3);
PVCoordinates pvInit = new PVCoordinates(pos_init, vel_init);
CartesianOrbit initialOrbit = new CartesianOrbit(pvInit, launchFrame, separationDate,
Constants.EIGEN5C_EARTH_MU);
KeplerianPropagator propagator = new KeplerianPropagator(initialOrbit);
ArrayList<SpacecraftState> states_list = new ArrayList<SpacecraftState>();
double dt = 60.0;
AbsoluteDate date_current = separationDate;
while (date_current.compareTo(separationDate.shiftedBy(24 * 3600.0)) <= 0) {
states_list.add(propagator.propagate(date_current));
date_current = date_current.shiftedBy(dt);
}
TLE tle_first_guess = new TLE(satellite_number, classification, launch_year, launch_number, launch_piece,
ephemeris_type, element_number, initialOrbit.getDate(), initialOrbit.getKeplerianMeanMotion(),
mean_motion_first_derivative, mean_motion_second_derivative, initialOrbit.getE(), initialOrbit.getI(),
0.0, 0.0, 0.0, revolution_number, b_star_first_guess);
double threshold = 1.0;
TLEPropagatorBuilder tle_builder = new TLEPropagatorBuilder(tle_first_guess, PositionAngle.MEAN, 1.0);
FiniteDifferencePropagatorConverter fitter = new FiniteDifferencePropagatorConverter(tle_builder, threshold,
10000);
fitter.convert(states_list, false, "BSTAR");
TLEPropagator tle_propagator = (TLEPropagator) fitter.getAdaptedPropagator();
TLE tle_fitted = tle_propagator.getTLE();
}
}