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