1 /* Copyright 2002-2025 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.files.sinex;
18
19 import java.util.ArrayList;
20 import java.util.HashMap;
21 import java.util.List;
22 import java.util.Map;
23
24 import org.hipparchus.geometry.euclidean.threed.Vector3D;
25 import org.orekit.errors.OrekitException;
26 import org.orekit.errors.OrekitMessages;
27 import org.orekit.gnss.GnssSignal;
28 import org.orekit.models.earth.displacement.PsdCorrection;
29 import org.orekit.time.AbsoluteDate;
30 import org.orekit.utils.TimeSpanMap;
31
32 /**
33 * Station model.
34 * <p>
35 * Since Orekit 11.1, this class handles multiple site antenna
36 * eccentricity.
37 * The {@link #getEccentricities(AbsoluteDate)} method can be
38 * used to access the site antenna eccentricity values for a
39 * given epoch.
40 * </p>
41 * @author Bryan Cazabonne
42 * @since 10.3
43 */
44 public class Station {
45
46 /** Site code. */
47 private String siteCode;
48
49 /** DOMES number. */
50 private String domes;
51
52 /** Start of validity. */
53 private AbsoluteDate validFrom;
54
55 /** End of validity. */
56 private AbsoluteDate validUntil;
57
58 /** Eccentricity reference system. */
59 private ReferenceSystem eccRefSystem;
60
61 /** TimeSpanMap of site antenna eccentricities. */
62 private final TimeSpanMap<Vector3D> eccentricitiesTimeSpanMap;
63
64 /** Antenna key.
65 * @since 13.0
66 */
67 private final TimeSpanMap<AntennaKey> antennaKeysMap;
68
69 /** Phase centers.
70 * @since 13.0
71 */
72 private final TimeSpanMap<Map<GnssSignal, Vector3D>> phaseCentersMap;
73
74 /** Post-Seismic Deformation.
75 * @since 12.0
76 */
77 private final TimeSpanMap<List<PsdCorrection>> psdMap;
78
79 /** Station position. */
80 private Vector3D position;
81
82 /** Station velocity. */
83 private Vector3D velocity;
84
85 /** Coordinates reference epoch. */
86 private AbsoluteDate epoch;
87
88 /**
89 * Constructor.
90 */
91 public Station() {
92 this.eccentricitiesTimeSpanMap = new TimeSpanMap<>(null);
93 this.antennaKeysMap = new TimeSpanMap<>(null);
94 this.phaseCentersMap = new TimeSpanMap<>(null);
95 this.psdMap = new TimeSpanMap<>(null);
96 this.position = Vector3D.ZERO;
97 this.velocity = Vector3D.ZERO;
98 }
99
100 /**
101 * Get the site code (station identifier).
102 * @return the site code
103 */
104 public String getSiteCode() {
105 return siteCode;
106 }
107
108 /**
109 * Set the site code (station identifier).
110 * @param siteCode the site code to set
111 */
112 public void setSiteCode(final String siteCode) {
113 this.siteCode = siteCode;
114 }
115
116 /**
117 * Get the site DOMES number.
118 * @return the DOMES number
119 */
120 public String getDomes() {
121 return domes;
122 }
123
124 /**
125 * Set the DOMES number.
126 * @param domes the DOMES number to set
127 */
128 public void setDomes(final String domes) {
129 this.domes = domes;
130 }
131
132 /**
133 * Get start of validity.
134 * @return start of validity
135 */
136 public AbsoluteDate getValidFrom() {
137 return validFrom;
138 }
139
140 /**
141 * Set the start of validity.
142 * @param validFrom the start of validity to set
143 */
144 public void setValidFrom(final AbsoluteDate validFrom) {
145 this.validFrom = validFrom;
146 }
147
148 /**
149 * Get end of validity.
150 * @return end of validity
151 */
152 public AbsoluteDate getValidUntil() {
153 return validUntil;
154 }
155
156 /**
157 * Set the end of validity.
158 * @param validUntil the end of validity to set
159 */
160 public void setValidUntil(final AbsoluteDate validUntil) {
161 this.validUntil = validUntil;
162 }
163
164 /**
165 * Get the reference system used to define the eccentricity vector (local or cartesian).
166 * @return the reference system used to define the eccentricity vector
167 */
168 public ReferenceSystem getEccRefSystem() {
169 return eccRefSystem;
170 }
171
172 /**
173 * Set the reference system used to define the eccentricity vector (local or cartesian).
174 * @param eccRefSystem the reference system used to define the eccentricity vector
175 */
176 public void setEccRefSystem(final ReferenceSystem eccRefSystem) {
177 this.eccRefSystem = eccRefSystem;
178 }
179
180 /**
181 * Get the station antenna eccentricities for the given epoch.
182 * <p>
183 * Vector convention: X-Y-Z or UP-NORTH-EAST.
184 * See {@link #getEccRefSystem()} method.
185 * <p>
186 * If there is no eccentricity values for the given epoch, an
187 * exception is thrown.
188 * @param date epoch
189 * @return station antenna eccentricities (m)
190 * @since 11.1
191 */
192 public Vector3D getEccentricities(final AbsoluteDate date) {
193 final Vector3D eccAtEpoch = eccentricitiesTimeSpanMap.get(date);
194 // If the entry is null, there is no valid eccentricity values for the input epoch
195 if (eccAtEpoch == null) {
196 // Throw an exception
197 throw new OrekitException(OrekitMessages.MISSING_STATION_DATA_FOR_EPOCH, date);
198 }
199 return eccAtEpoch;
200 }
201
202 /**
203 * Get the TimeSpanMap of site antenna eccentricities.
204 * @return the TimeSpanMap of site antenna eccentricities
205 * @since 11.1
206 */
207 public TimeSpanMap<Vector3D> getEccentricitiesTimeSpanMap() {
208 return eccentricitiesTimeSpanMap;
209 }
210
211 /** Add a station eccentricity vector entry valid before a limit date.<br>
212 * Using <code>addStationEccentricitiesValidBefore(entry, t)</code> will make <code>entry</code>
213 * valid in ]-∞, t[ (note the open bracket).
214 * @param entry station eccentricity vector entry
215 * @param latestValidityDate date before which the entry is valid
216 * (must be different from <b>all</b> dates already used for transitions)
217 * @since 11.1
218 */
219 public void addStationEccentricitiesValidBefore(final Vector3D entry, final AbsoluteDate latestValidityDate) {
220 eccentricitiesTimeSpanMap.addValidBefore(entry, latestValidityDate, false);
221 }
222
223 /** Get the TimeSpanMap of Post-Seismic Deformation.
224 * @return the TimeSpanMap of Post-Seismic Deformation
225 * @since 12.1
226 */
227 public TimeSpanMap<List<PsdCorrection>> getPsdTimeSpanMap() {
228 return psdMap;
229 }
230
231 /** Add a Post-Seismic Deformation entry valid after a limit date.<br>
232 * Using {@code addPsdCorrectionValidAfter(entry, t)} will make {@code entry}
233 * valid in [t, +∞[ (note the closed bracket).
234 * @param entry Post-Seismic Deformation entry
235 * @param earliestValidityDate date after which the entry is valid
236 * (must be different from <b>all</b> dates already used for transitions)
237 * @since 12.1
238 */
239 public void addPsdCorrectionValidAfter(final PsdCorrection entry, final AbsoluteDate earliestValidityDate) {
240
241 // get the list of corrections active just after earthquake date
242 List<PsdCorrection> corrections = psdMap.get(earliestValidityDate.shiftedBy(1.0e-3));
243
244 if (corrections == null ||
245 earliestValidityDate.durationFrom(corrections.get(0).getEarthquakeDate()) > 1.0e-3) {
246 // either this is the first earthquake we consider or
247 // this earthquake is after another one already considered
248 // we need to create a new list of corrections for this new earthquake
249 corrections = new ArrayList<>();
250 psdMap.addValidAfter(corrections, earliestValidityDate, false);
251 }
252
253 // add the entry to the current list
254 corrections.add(entry);
255
256 }
257
258 /**
259 * Get the antenna key for the given epoch.
260 * If there is no antenna keys for the given epoch, an
261 * exception is thrown.
262 * @param date epoch
263 * @return antenna key
264 * @since 13.0
265 */
266 public AntennaKey getAntennaKey(final AbsoluteDate date) {
267 final AntennaKey keyAtEpoch = antennaKeysMap.get(date);
268 // If the entry is null, there is no valid type for the input epoch
269 if (keyAtEpoch == null) {
270 // Throw an exception
271 throw new OrekitException(OrekitMessages.MISSING_STATION_DATA_FOR_EPOCH, date);
272 }
273 return keyAtEpoch;
274 }
275
276 /**
277 * Get the TimeSpanMap of site antenna type.
278 * @return the TimeSpanMap of site antenna type
279 * @since 12.0
280 */
281 public TimeSpanMap<AntennaKey> getAntennaKeyTimeSpanMap() {
282 return antennaKeysMap;
283 }
284
285 /** Add a antenna key entry valid before a limit date.<br>
286 * Using <code>addAntennaKeyValidBefore(entry, t)</code> will make <code>entry</code>
287 * valid in ]-∞, t[ (note the open bracket).
288 * @param entry antenna key entry
289 * @param latestValidityDate date before which the entry is valid
290 * (must be different from <b>all</b> dates already used for transitions)
291 * @since 12.0
292 */
293 public void addAntennaKeyValidBefore(final AntennaKey entry, final AbsoluteDate latestValidityDate) {
294 antennaKeysMap.addValidBefore(entry, latestValidityDate, false);
295 }
296
297 /**
298 * Get the TimeSpanMap of phase centers.
299 * @return the TimeSpanMap of phase centers
300 * @since 13.0
301 */
302 public TimeSpanMap<Map<GnssSignal, Vector3D>> getPhaseCentersMap() {
303 return phaseCentersMap;
304 }
305
306 /**
307 * Get the phase centers for the given epoch.
308 * If there is no phase centers for the given epoch, an
309 * exception is thrown.
310 * @param date epoch
311 * @return phase centers
312 * @since 13.0
313 */
314 public Map<GnssSignal, Vector3D> getPhaseCenters(final AbsoluteDate date) {
315 final Map<GnssSignal, Vector3D> phaseCentersAtEpoch = phaseCentersMap.get(date);
316 // If the entry is null, there is no valid key for the input epoch
317 if (phaseCentersAtEpoch == null) {
318 // Throw an exception
319 throw new OrekitException(OrekitMessages.MISSING_STATION_DATA_FOR_EPOCH, date);
320 }
321 return phaseCentersAtEpoch;
322 }
323
324 /**
325 * Get the station position.
326 * @return the station position (m)
327 */
328 public Vector3D getPosition() {
329 return position;
330 }
331
332 /**
333 * Set the station position.
334 * @param position the position to set
335 */
336 public void setPosition(final Vector3D position) {
337 this.position = position;
338 }
339
340 /**
341 * Get the station velocity.
342 * @return the station velocity (m/s)
343 */
344 public Vector3D getVelocity() {
345 return velocity;
346 }
347
348 /**
349 * Set the station velocity.
350 * @param velocity the velocity to set
351 */
352 public void setVelocity(final Vector3D velocity) {
353 this.velocity = velocity;
354 }
355
356 /**
357 * Get the coordinates reference epoch.
358 * @return the coordinates reference epoch
359 */
360 public AbsoluteDate getEpoch() {
361 return epoch;
362 }
363
364 /**
365 * Set the coordinates reference epoch.
366 * @param epoch the epoch to set
367 */
368 public void setEpoch(final AbsoluteDate epoch) {
369 this.epoch = epoch;
370 }
371
372 /** Eccentricity reference system. */
373 public enum ReferenceSystem {
374
375 /** Local reference system Up, North, East. */
376 UNE("UNE"),
377
378 /** Cartesian reference system X, Y, Z. */
379 XYZ("XYZ");
380
381 /** Codes map. */
382 private static final Map<String, ReferenceSystem> CODES_MAP = new HashMap<>();
383 static {
384 for (final ReferenceSystem type : values()) {
385 CODES_MAP.put(type.getName(), type);
386 }
387 }
388
389 /** Name used to define the reference system in SINEX file. */
390 private final String name;
391
392 /**
393 * Constructor.
394 * @param name name used to define the reference system in SINEX file
395 */
396 ReferenceSystem(final String name) {
397 this.name = name;
398 }
399
400 /**
401 * Get the name used to define the reference system in SINEX file.
402 * @return the name
403 */
404 public String getName() {
405 return name;
406 }
407
408 /**
409 * Get the eccentricity reference system corresponding to the given value.
410 * @param value given value
411 * @return the corresponding eccentricity reference system
412 */
413 public static ReferenceSystem getEccRefSystem(final String value) {
414 return CODES_MAP.get(value);
415 }
416
417 }
418
419 }
420