1 /* Copyright 2022-2025 Luc Maisonobe
2 * Licensed to CS GROUP (CS) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * CS licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.orekit.frames;
18
19 import java.util.ArrayList;
20 import java.util.Collection;
21 import java.util.List;
22
23 import org.hipparchus.util.FastMath;
24 import org.orekit.time.AbsoluteDate;
25 import org.orekit.utils.Constants;
26 import org.orekit.utils.IERSConventions.NutationCorrectionConverter;
27 import org.orekit.utils.SecularAndHarmonic;
28
29 /** This class extends an {@link EOPHistory} for some weeks using fitting.
30 * <p>
31 * The goal of this class is to provide a reasonable prediction of
32 * Earth Orientation Parameters past the last date available in
33 * regular {@link EOPHistory}, which just generated corrections set
34 * to 0 when they have no data.
35 * </p>
36 * <p>
37 * The prediction is based on fitting of last data, with both
38 * {@link SecularAndHarmonic secular (polynomial) and harmonic (periodic)}
39 * terms. The extended entries are generated at one point per day
40 * and are continuous (i.e. no leap seconds are introduced)
41 * </p>
42 * <p>
43 * After construction, the history contains both the initial
44 * raw history and an extension part appended after it.
45 * </p>
46 * @see EOPFitter
47 * @see SecularAndHarmonic
48 * @since 12.0
49 * @author Luc Maisonobe
50 */
51 public class PredictedEOPHistory extends EOPHistory {
52
53 /** Raw EOP history to extend. */
54 private final EOPHistory rawHistory;
55
56 /** Duration of the extension period (s). */
57 private final double extensionDuration;
58
59 /** Fitter for all Earth Orientation Parameters. */
60 private final EOPFitter fitter;
61
62 /** Simple constructor.
63 * @param rawHistory raw EOP history to extend.
64 * @param extensionDuration duration of the extension period (s)
65 * @param fitter fitter for all Earth Orientation Parameters
66 */
67 public PredictedEOPHistory(final EOPHistory rawHistory, final double extensionDuration,
68 final EOPFitter fitter) {
69 super(rawHistory.getConventions(), rawHistory.getInterpolationDegree(),
70 extendHistory(rawHistory, extensionDuration, fitter),
71 rawHistory.isSimpleEop(), rawHistory.getTimeScales());
72 this.rawHistory = rawHistory;
73 this.extensionDuration = extensionDuration;
74 this.fitter = fitter;
75 }
76
77 /** Extends raw history.
78 * @param rawHistory raw EOP history to extend.
79 * @param extensionDuration duration of the extension period (s)
80 * @param fitter fitter for all Earth Orientation Parameters
81 * @return extended history
82 */
83 private static Collection<? extends EOPEntry> extendHistory(final EOPHistory rawHistory,
84 final double extensionDuration,
85 final EOPFitter fitter) {
86
87
88 // fit model
89 final EOPFittedModel model = fitter.fit(rawHistory);
90
91 // create a converter for nutation corrections
92 final NutationCorrectionConverter converter =
93 rawHistory.getConventions().getNutationCorrectionConverter(rawHistory.getTimeScales());
94
95 // generate extension entries
96 final List<EOPEntry> rawEntries = rawHistory.getEntries();
97 final EOPEntry last = rawEntries.get(rawEntries.size() - 1);
98 final int n = (int) FastMath.rint(extensionDuration / Constants.JULIAN_DAY);
99 final List<EOPEntry> entries = new ArrayList<>(rawEntries.size() + n);
100 entries.addAll(rawEntries);
101 for (int i = 0; i < n; ++i) {
102 final AbsoluteDate date = last.getDate().shiftedBy((i + 1) * Constants.JULIAN_DAY);
103 final double dut1 = model.getDUT1().osculatingValue(date);
104 final double lod = -Constants.JULIAN_DAY * model.getDUT1().osculatingDerivative(date);
105 final double xp = model.getXp().osculatingValue(date);
106 final double yp = model.getYp().osculatingValue(date);
107 final double xpRate = model.getXp().osculatingDerivative(date);
108 final double ypRate = model.getYp().osculatingDerivative(date);
109 final double dx = model.getDx().osculatingValue(date);
110 final double dy = model.getDy().osculatingValue(date);
111 final double[] equinox = converter.toEquinox(date, dx, dy);
112 entries.add(new EOPEntry(last.getMjd() + i + 1, dut1, lod, xp, yp, xpRate, ypRate,
113 equinox[0], equinox[1], dx, dy,
114 last.getITRFType(), date));
115 }
116
117 return entries;
118
119 }
120
121 }