CPF parser ignores direction flag - causing an exception later
The Problem
Tested with Orekit 12.0.1.
As described in the forum, the CPF parser (org.orekit.files.ilrs.CPFParser:470
) ignores the direction flag of position lines - index 1 in the generated array:
/** Position values. */
TEN("10") {
/** {@inheritDoc} */
@Override
public void parse(final String line, final ParseInfo pi) {
// Data contained in the line
final String[] values = SEPARATOR.split(line);
// Epoch
final int mjd = Integer.parseInt(values[2]);
The direction flag is ignored for the other implemented line type parser (20), too.
The possible directional flag values are, according to the CPF documentation (page 15):
Common epoch (0):
instantaneous vector between geocenter and target, without light-time iteration. This epoch is the same as found in the corresponding old TIV format.
Transmit (1):
position vector contains light-time iterated travel time from the geocenter to the target at the transmit epoch.
Receive (2):
position vector contains light-time iterated travel time from the target to the geocenter at the receive epoch.
(The sign of each element is opposite to that of the transmit vector.)
For objects on the moon (apollo11, apollo 15 luna17 and luna21 on https://edc.dgfi.tum.de/pub/slr/cpf_predicts_v2/current) the inbound and outbound position vectors are given for the same time:
H1 CPF 2 OPA 2024 01 03 18 003 1 apollo11 OPA_ELP96
H2 100 100 0 2024 1 4 0 0 0 2024 1 8 23 45 0 900 0 1 0 0 0 3
H9
10 1 60313 0.0 0 16126075.681 398785441.280 -26042850.417
10 2 60313 0.0 0 -16202176.985 -398701851.546 26035563.466
30 1 -741. -40216. 3643. 26.9
10 1 60313 900.0 0 41473086.247 396893016.626 -26449307.496
10 2 60313 900.0 0 -41543554.533 -396804772.095 26442015.393
30 1 -3370. -40078. 3646. 26.9
The outcome
This causes an exception when interpolating between the points, because the time difference is zero:
Exception in thread "main" org.hipparchus.exception.MathIllegalArgumentException: duplicated abscissa 0 causes division by zero
at org.hipparchus.analysis.interpolation.HermiteInterpolator.addSamplePoint(HermiteInterpolator.java:113)
at org.orekit.utils.TimeStampedPVCoordinatesHermiteInterpolator.lambda$interpolate$0(TimeStampedPVCoordinatesHermiteInterpolator.java:148)
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1655)
at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:658)
at org.orekit.utils.TimeStampedPVCoordinatesHermiteInterpolator.interpolate(TimeStampedPVCoordinatesHermiteInterpolator.java:146)
at org.orekit.utils.TimeStampedPVCoordinatesHermiteInterpolator.interpolate(TimeStampedPVCoordinatesHermiteInterpolator.java:39)
at org.orekit.time.AbstractTimeInterpolator.interpolate(AbstractTimeInterpolator.java:91)
at org.orekit.files.general.EphemerisSegmentPropagator.getPVCoordinates(EphemerisSegmentPropagator.java:115)
Test-code
This exception can be generated with this code snippet:
CPF cpfFile = new CPFParser().parse(new DataSource("satellite.cpf", new DataSource.ReaderOpener()
{
@Override
public Reader openOnce() throws IOException
{
return new StringReader("H1 CPF 2 OPA 2024 01 03 18 003 1 apollo11 OPA_ELP96\n"
+ "H2 100 100 0 2024 1 4 0 0 0 2024 1 8 23 45 0 900 0 1 0 0 0 3\n"
+ "H9\n"
+ "10 1 60313 0.0 0 16126075.681 398785441.280 -26042850.417\n"
+ "10 2 60313 0.0 0 -16202176.985 -398701851.546 26035563.466\n"
+ "30 1 -741. -40216. 3643. 26.9\n"
+ "10 1 60313 900.0 0 41473086.247 396893016.626 -26449307.496\n"
+ "10 2 60313 900.0 0 -41543554.533 -396804772.095 26442015.393\n"
+ "30 1 -3370. -40078. 3646. 26.9\n"
+ "10 1 60313 1800.0 0 66644291.059 393390899.000 -26855631.271\n"
+ "10 2 60313 1800.0 0 -66708842.979 -393298378.023 26848334.019\n"
+ "30 1 -5984. -39769. 3648. 26.9\n"
+ "10 1 60313 2700.0 0 91537552.217 388293816.394 -27261819.596\n"
+ "10 2 60313 2700.0 0 -91595929.760 -388197414.474 27254517.199\n"
+ "30 1 -8572. -39289. 3651. 26.8\n"
+ "10 1 60313 3600.0 0 116051895.405 381622972.022 -27667870.319\n"
+ "10 2 60313 3600.0 0 -116103866.930 -381523100.119 27660562.779\n"
+ "30 1 -11123. -38641. 3653. 26.8\n"
+ "10 1 60313 4500.0 0 140087920.030 373405955.825 -28073781.283\n"
+ "10 2 60313 4500.0 0 -140133281.178 -373303038.613 28066468.603\n"
+ "30 1 -13625. -37827. 3656. 26.8\n"
+ "10 1 60313 5400.0 0 163548202.818 363676629.997 -28479550.326\n"
+ "10 2 60313 5400.0 0 -163586777.325 -363571104.045 28472232.508\n"
+ "30 1 -16069. -36852. 3658. 26.8\n"
+ "99");
}
}));
for (CPFEphemeris ephemerisEntry : cpfFile.getSatellites().values()) {
ephemerisEntry.getPropagator().getPVCoordinates(ephemerisEntry.getStart(), FramesFactory.getITRF(IERSConventions.IERS_2010, true));
}
Solution
Ignore lines with direction flag value = 2 solves this issue. Probably it should be configurable which direction should be parsed?