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