1 /* Copyright 2002-2024 CS GROUP
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.models.earth.troposphere;
18
19 import java.util.ArrayList;
20 import java.util.List;
21
22 import org.hipparchus.CalculusFieldElement;
23 import org.hipparchus.util.MathArrays;
24 import org.orekit.annotation.DefaultDataContext;
25 import org.orekit.bodies.FieldGeodeticPoint;
26 import org.orekit.bodies.GeodeticPoint;
27 import org.orekit.models.earth.weather.FieldPressureTemperatureHumidity;
28 import org.orekit.models.earth.weather.PressureTemperatureHumidity;
29 import org.orekit.time.AbsoluteDate;
30 import org.orekit.time.FieldAbsoluteDate;
31 import org.orekit.time.TimeScale;
32 import org.orekit.time.TimeScalesFactory;
33 import org.orekit.utils.FieldTrackingCoordinates;
34 import org.orekit.utils.ParameterDriver;
35 import org.orekit.utils.TimeSpanMap;
36 import org.orekit.utils.TimeSpanMap.Span;
37 import org.orekit.utils.TrackingCoordinates;
38
39 /**
40 * Time span estimated tropospheric model.
41 * <p>
42 * This class is closely related to {@link org.orekit.models.earth.troposphere EstimatedModel} class.<br>
43 * The difference is that it has a {@link TimeSpanMap} of {@link EstimatedModel} objects as attribute. <br>
44 * The idea behind this model is to allow the user to design a tropospheric model that can see its physical parameters
45 * (total zenith delay) change with time, at dates chosen by the user. <br>
46 * </p>
47 * @author Bryan Cazabonne
48 * @since 10.2
49 */
50 public class TimeSpanEstimatedModel implements TroposphericModel {
51
52 /** Prefix for dates before in the tropospheric parameter drivers' name. */
53 public static final String DATE_BEFORE = " - Before ";
54
55 /** Prefix for dates after in the tropospheric parameter drivers' name. */
56 public static final String DATE_AFTER = " - After ";
57
58 /** Time scale for transition dates. */
59 private final TimeScale timeScale;
60
61 /** It contains all the models use for the whole period of measurements. */
62 private final TimeSpanMap<EstimatedModel> troposphericModelMap;
63
64 /**
65 * Constructor with default UTC time scale.
66 * @param model the initial model which going to be used for all the models initialization.
67 */
68 @DefaultDataContext
69 public TimeSpanEstimatedModel(final EstimatedModel model) {
70 this(model, TimeScalesFactory.getUTC());
71 }
72
73 /**
74 * Constructor with default UTC time scale.
75 * @param model the initial model which going to be used for all the models initialization.
76 * @param timeScale timeScale Time scale used for the default names of the tropospheric parameter drivers
77 */
78 public TimeSpanEstimatedModel(final EstimatedModel model, final TimeScale timeScale) {
79 this.troposphericModelMap = new TimeSpanMap<>(model);
80 this.timeScale = timeScale;
81 }
82
83 /** {@inheritDoc}
84 * <p>
85 * All the parameter drivers of all Estimated models are returned in an array.
86 * Models are ordered chronologically.
87 * </p>
88 */
89 @Override
90 public List<ParameterDriver> getParametersDrivers() {
91
92 // Get all transitions from the TimeSpanMap
93 final List<ParameterDriver> listTroposphericParameterDrivers = new ArrayList<>();
94
95 // Loop on the spans
96 for (Span<EstimatedModel> span = getFirstSpan(); span != null; span = span.next()) {
97 // Add all the parameter drivers of each span
98 for (ParameterDriver tropoDriver : span.getData().getParametersDrivers()) {
99 // Add the driver only if the name does not exist already
100 if (!findByName(listTroposphericParameterDrivers, tropoDriver.getName())) {
101 listTroposphericParameterDrivers.add(tropoDriver);
102 }
103 }
104 }
105
106 // Return an array of parameter drivers with no duplicated name
107 return listTroposphericParameterDrivers;
108
109 }
110
111 /** Add an EstimatedTroposphericModel entry valid before a limit date.<br>
112 * Using <code>addTroposphericValidBefore(entry, t)</code> will make <code>entry</code>
113 * valid in ]-∞, t[ (note the open bracket).
114 * @param model EstimatedTroposphericModel entry
115 * @param latestValidityDate date before which the entry is valid
116 * (must be different from <b>all</b> dates already used for transitions)
117 */
118 public void addTroposphericModelValidBefore(final EstimatedModel model, final AbsoluteDate latestValidityDate) {
119 troposphericModelMap.addValidBefore(changeTroposphericParameterDriversNames(model,
120 latestValidityDate,
121 DATE_BEFORE),
122 latestValidityDate, false);
123 }
124
125 /** Add a EstimatedTroposphericModel entry valid after a limit date.<br>
126 * Using <code>addTroposphericModelValidAfter(entry, t)</code> will make <code>entry</code>
127 * valid in [t, +∞[ (note the closed bracket).
128 * @param model EstimatedTroposphericModel entry
129 * @param earliestValidityDate date after which the entry is valid
130 * (must be different from <b>all</b> dates already used for transitions)
131 */
132 public void addTroposphericModelValidAfter(final EstimatedModel model, final AbsoluteDate earliestValidityDate) {
133 troposphericModelMap.addValidAfter(changeTroposphericParameterDriversNames(model,
134 earliestValidityDate,
135 DATE_AFTER),
136 earliestValidityDate, false);
137 }
138
139 /** Get the {@link EstimatedModel} model valid at a date.
140 * @param date the date of validity
141 * @return the EstimatedTroposphericModel model valid at date
142 */
143 public EstimatedModel getTroposphericModel(final AbsoluteDate date) {
144 return troposphericModelMap.get(date);
145 }
146
147 /** Get the first {@link Span time span} of the tropospheric model time span map.
148 * @return the first {@link Span time span} of the tropospheric model time span map
149 * @since 11.1
150 */
151 public Span<EstimatedModel> getFirstSpan() {
152 return troposphericModelMap.getFirstSpan();
153 }
154
155 /** Extract the proper parameter drivers' values from the array in input of the
156 * {@link #pathDelay(TrackingCoordinates, GeodeticPoint, PressureTemperatureHumidity, double[], AbsoluteDate) pathDelay} method.
157 * Parameters are filtered given an input date.
158 * @param parameters the input parameters array
159 * @param date the date
160 * @return the parameters given the date
161 */
162 public double[] extractParameters(final double[] parameters, final AbsoluteDate date) {
163
164 // Get the tropospheric parameter drivers of the date
165 final List<ParameterDriver> troposphericParameterDriver = getTroposphericModel(date).getParametersDrivers();
166
167 // Find out the indexes of the parameters in the whole array of parameters
168 final List<ParameterDriver> allTroposphericParameters = getParametersDrivers();
169 final double[] outParameters = new double[troposphericParameterDriver.size()];
170 int index = 0;
171 for (int i = 0; i < allTroposphericParameters.size(); i++) {
172 final String driverName = allTroposphericParameters.get(i).getName();
173 for (ParameterDriver tropoDriver : troposphericParameterDriver) {
174 if (tropoDriver.getName().equals(driverName)) {
175 outParameters[index++] = parameters[i];
176 }
177 }
178 }
179 return outParameters;
180 }
181
182 /** Extract the proper parameter drivers' values from the array in input of the
183 * {@link #pathDelay(TrackingCoordinates, GeodeticPoint, PressureTemperatureHumidity, double[], AbsoluteDate) pathDelay} method.
184 * Parameters are filtered given an input date.
185 * @param parameters the input parameters array
186 * @param date the date
187 * @param <T> extends CalculusFieldElements
188 * @return the parameters given the date
189 */
190 public <T extends CalculusFieldElement<T>> T[] extractParameters(final T[] parameters,
191 final FieldAbsoluteDate<T> date) {
192
193 // Get the tropospheric parameter drivers of the date
194 final List<ParameterDriver> troposphericParameterDriver = getTroposphericModel(date.toAbsoluteDate()).getParametersDrivers();
195
196 // Find out the indexes of the parameters in the whole array of parameters
197 final List<ParameterDriver> allTroposphericParameters = getParametersDrivers();
198 final T[] outParameters = MathArrays.buildArray(date.getField(), troposphericParameterDriver.size());
199 int index = 0;
200 for (int i = 0; i < allTroposphericParameters.size(); i++) {
201 final String driverName = allTroposphericParameters.get(i).getName();
202 for (ParameterDriver tropoDriver : troposphericParameterDriver) {
203 if (tropoDriver.getName().equals(driverName)) {
204 outParameters[index++] = parameters[i];
205 }
206 }
207 }
208 return outParameters;
209 }
210
211 /** {@inheritDoc} */
212 @Override
213 public TroposphericDelay pathDelay(final TrackingCoordinates trackingCoordinates,
214 final GeodeticPoint point,
215 final PressureTemperatureHumidity weather,
216 final double[] parameters, final AbsoluteDate date) {
217 // Extract the proper parameters valid at date from the input array
218 final double[] extractedParameters = extractParameters(parameters, date);
219 // Compute and return the path delay
220 return getTroposphericModel(date).pathDelay(trackingCoordinates, point, weather,
221 extractedParameters, date);
222 }
223
224 /** {@inheritDoc} */
225 @Override
226 public <T extends CalculusFieldElement<T>> FieldTroposphericDelay<T> pathDelay(final FieldTrackingCoordinates<T> trackingCoordinates,
227 final FieldGeodeticPoint<T> point,
228 final FieldPressureTemperatureHumidity<T> weather,
229 final T[] parameters, final FieldAbsoluteDate<T> date) {
230 // Extract the proper parameters valid at date from the input array
231 final T[] extractedParameters = extractParameters(parameters, date);
232 // Compute and return the path delay
233 return getTroposphericModel(date.toAbsoluteDate()).pathDelay(trackingCoordinates, point, weather,
234 extractedParameters, date);
235 }
236
237 /** Find if a parameter driver with a given name already exists in a list of parameter drivers.
238 * @param driversList the list of parameter drivers
239 * @param name the parameter driver's name to filter with
240 * @return true if the name was found, false otherwise
241 */
242 private boolean findByName(final List<ParameterDriver> driversList, final String name) {
243 for (final ParameterDriver driver : driversList) {
244 if (driver.getName().equals(name)) {
245 return true;
246 }
247 }
248 return false;
249 }
250
251 /** Change the parameter drivers names of a {@link EstimatedModel} model, if needed.
252 * <p>
253 * This is done to avoid that several parameter drivers have the same name.<br>
254 * It is done only if the user hasn't modify the EstimatedTroposphericModel parameter drivers default names.
255 * </p>
256 * @param troposphericModel the EstimatedTroposphericModel model
257 * @param date the date used in the parameter driver's name
258 * @param datePrefix the date prefix used in the parameter driver's name
259 * @return the EstimatedTroposphericModel with its drivers' names changed
260 */
261 private EstimatedModel changeTroposphericParameterDriversNames(final EstimatedModel troposphericModel,
262 final AbsoluteDate date,
263 final String datePrefix) {
264 // Loop on the parameter drivers of the EstimatedTroposphericModel model
265 for (ParameterDriver driver: troposphericModel.getParametersDrivers()) {
266 final String driverName = driver.getName();
267
268 // If the name is the default name for EstimatedTroposphericModel parameter drivers
269 // Modify the name to add the prefix and the date
270 if (driverName.equals(EstimatedModel.TOTAL_ZENITH_DELAY)) {
271 driver.setName(driverName + datePrefix + date.toString(timeScale));
272 }
273 }
274 return troposphericModel;
275 }
276
277 }