IGSUtils.java

  1. /* Copyright 2002-2024 Thales Alenia Space
  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.gnss;

  18. import org.orekit.annotation.DefaultDataContext;
  19. import org.orekit.data.DataContext;
  20. import org.orekit.errors.OrekitException;
  21. import org.orekit.errors.OrekitMessages;
  22. import org.orekit.frames.Frame;
  23. import org.orekit.frames.Frames;
  24. import org.orekit.frames.ITRFVersion;
  25. import org.orekit.frames.Predefined;
  26. import org.orekit.frames.VersionedITRF;
  27. import org.orekit.utils.IERSConventions;

  28. import java.util.Locale;
  29. import java.util.regex.Matcher;
  30. import java.util.regex.Pattern;

  31. /** Utility for IGS files.
  32.  * @author Luc Maisonobe
  33.  * @since 12.1
  34.  *
  35.  */
  36. public class IGSUtils {

  37.     /** Pattern for frame names with year.
  38.      * @since 12.1
  39.      */
  40.     private static final Pattern EARTH_FRAME_WITH_YEAR = Pattern.compile("(?:IER|ITR|ITRF|IGS|IGb|SLR)([0-9]{2})");

  41.     /** Pattern for GCRF inertial frame.
  42.      * @since 12.1
  43.      */
  44.     private static final Pattern GCRF_FRAME = Pattern.compile(" *GCRF *");

  45.     /** Pattern for EME2000 inertial frame.
  46.      * @since 12.1
  47.      */
  48.     private static final Pattern EME2000_FRAME = Pattern.compile("EME(?:00|2K)");

  49.     /** Private constructor for a utility class.
  50.      */
  51.     private IGSUtils() {
  52.         // nothing to do
  53.     }

  54.     /** Default string to {@link Frame} conversion for {@link org.orekit.files.sp3.SP3Parser}
  55.      * or {@link org.orekit.files.rinex.clock.RinexClockParser}.
  56.      *
  57.      * <p>
  58.      * This method uses the {@link DataContext#getDefault() default data context}.
  59.      * If the frame names has a form like IGS##, or ITR##, or ITRF##, or SLR##,
  60.      * where ## is a two digits number, then this number will be used to build the
  61.      * appropriate {@link ITRFVersion}. Otherwise (for example if name is
  62.      * UNDEF or WGS84), then a default {@link
  63.      * org.orekit.frames.Frames#getITRF(IERSConventions, boolean) ITRF}
  64.      * will be created.
  65.      * </p>
  66.      *
  67.      * @param name of the frame.
  68.      * @return ITRF based on 2010 conventions,
  69.      * with tidal effects considered during EOP interpolation
  70.      * @since 12.1
  71.      */
  72.     @DefaultDataContext
  73.     public static Frame guessFrame(final String name) {
  74.         return guessFrame(DataContext.getDefault().getFrames(), name);
  75.     }

  76.     /** Default string to {@link Frame} conversion for {@link org.orekit.files.sp3.SP3Parser}
  77.      * or {@link org.orekit.files.rinex.clock.RinexClockParser}.
  78.      *
  79.      * <p>
  80.      * Various frame names are supported:
  81.      * </p>
  82.      * <ul>
  83.      *     <li>IGS##, or ITR##, or ITRF##, or SLR##,
  84.      *      where ## is a two digits number, then this number will be used to build the
  85.      *      appropriate {@link ITRFVersion}</li>
  86.      *     <li>GCRF (left or right justified) for GCRF inertial frame</li>
  87.      *     <li>EME00 or EME2K for EME2000 inertial frame</li>
  88.      *     <li>for all other names (for example if name is UNDEF or WGS84),
  89.      *     then a default {@link org.orekit.frames.Frames#getITRF(IERSConventions, boolean) ITRF}
  90.      *     frame will be selected</li>
  91.      * </ul>
  92.      * <p>
  93.      * Note that using inertial frames in classical products like SP3 files is non-standard,
  94.      * it is supported by Orekit, but may not be supported by other programs, so they should
  95.      * be used with caution when writing files.
  96.      * </p>
  97.      *
  98.      * @param frames frames factory
  99.      * @param name of the frame.
  100.      * @return guessed frame
  101.      * @since 12.1
  102.      */
  103.     public static Frame guessFrame(final Frames frames, final String name) {
  104.         final Matcher earthMatcher = EARTH_FRAME_WITH_YEAR.matcher(name);
  105.         if (earthMatcher.matches()) {
  106.             // this is a frame of the form IGS14, or ITR20, or SLR08, or similar
  107.             final int yy = Integer.parseInt(earthMatcher.group(1));
  108.             final ITRFVersion itrfVersion = ITRFVersion.getITRFVersion(yy);
  109.             final IERSConventions conventions =
  110.                 itrfVersion.getYear() < 2003 ?
  111.                 IERSConventions.IERS_1996 :
  112.                 (itrfVersion.getYear() < 2010 ? IERSConventions.IERS_2003 : IERSConventions.IERS_2010);
  113.             return frames.getITRF(itrfVersion, conventions, false);
  114.         } else {
  115.             final Matcher gcrfMatcher = GCRF_FRAME.matcher(name);
  116.             if (gcrfMatcher.matches()) {
  117.                 // inertial GCRF frame
  118.                 return frames.getGCRF();
  119.             } else {
  120.                 final Matcher eme2000Matcher = EME2000_FRAME.matcher(name);
  121.                 if (eme2000Matcher.matches()) {
  122.                     // inertial EME2000 frame
  123.                     return frames.getEME2000();
  124.                 } else {
  125.                     // unknown frame 'maybe UNDEF or WGS84
  126.                     // we use a default ITRF
  127.                     return frames.getITRF(IERSConventions.IERS_2010, false);
  128.                 }
  129.             }
  130.         }
  131.     }

  132.     /** Guess a frame name.
  133.      * <p>
  134.      * If the frame is not compatible with {@link #guessFrame(Frames, String)},
  135.      * an exception will be triggered
  136.      * </p>
  137.      * @param frame frame from which we want the name
  138.      * @return name compatible with {@link #guessFrame(Frames, String)}
  139.      * @since 12.1
  140.      */
  141.     public static String frameName(final Frame frame) {
  142.         if (frame instanceof VersionedITRF) {
  143.             final int yy = ((VersionedITRF) frame).getITRFVersion().getYear() % 100;
  144.             return String.format(Locale.US, "IGS%02d", yy);
  145.         } else if (Predefined.GCRF.getName().equals(frame.getName())) {
  146.             return "GCRF";
  147.         } else if (Predefined.EME2000.getName().equals(frame.getName())) {
  148.             return "EME2K";
  149.         } else {
  150.             throw new OrekitException(OrekitMessages.FRAME_NOT_ALLOWED, frame.getName());
  151.         }
  152.     }

  153. }