SingleLineBlockPredicate.java

  1. /* Copyright 2022-2025 Luc Maisonobe
  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. import org.hipparchus.geometry.euclidean.threed.Vector3D;
  19. import org.orekit.errors.OrekitException;
  20. import org.orekit.errors.OrekitMessages;
  21. import org.orekit.files.sinex.Station.ReferenceSystem;
  22. import org.orekit.gnss.GnssSignal;
  23. import org.orekit.gnss.PredefinedGnssSignal;
  24. import org.orekit.gnss.SatInSystem;
  25. import org.orekit.gnss.SatelliteSystem;
  26. import org.orekit.time.AbsoluteDate;

  27. import java.util.function.Predicate;

  28. /** Predicates for blocks containing a single type of lines.
  29.  * @author Luc Maisonobe
  30.  * @since 13.0
  31.  */
  32. enum SingleLineBlockPredicate implements Predicate<SinexParseInfo> {

  33.     /** Predicate for SITE/ID block content. */
  34.     SITE_ID {
  35.         /** {@inheritDoc} */
  36.         @Override
  37.         public void parse(final SinexParseInfo parseInfo) {
  38.             // read site id. data
  39.             final Station station = new Station();
  40.             station.setSiteCode(parseInfo.parseString(1, 4));
  41.             station.setDomes(parseInfo.parseString(9, 9));
  42.             parseInfo.addStation(station);
  43.         }
  44.     },

  45.     /** Predicate for SITE/ANTENNA block content. */
  46.     SITE_ANTENNA {
  47.         /** {@inheritDoc} */
  48.         @Override
  49.         public void parse(final SinexParseInfo parseInfo) {

  50.             // read antenna type data
  51.             final Station station = parseInfo.getCurrentLineStation(1);

  52.             // validity range
  53.             final AbsoluteDate start = parseInfo.getCurrentLineStartDate();
  54.             final AbsoluteDate end   = parseInfo.getCurrentLineEndDate();

  55.             // antenna key
  56.             final AntennaKey key = new AntennaKey(parseInfo.parseString(42, 16),
  57.                                                   parseInfo.parseString(58,  4),
  58.                                                   parseInfo.parseString(63,  5));

  59.             // special implementation for the first entry
  60.             if (station.getAntennaKeyTimeSpanMap().getSpansNumber() == 1) {
  61.                 // we want null values outside validity limits of the station
  62.                 station.addAntennaKeyValidBefore(key, end);
  63.                 station.addAntennaKeyValidBefore(null, start);
  64.             } else {
  65.                 station.addAntennaKeyValidBefore(key, end);
  66.             }

  67.         }
  68.     },

  69.     /** Predicate for SITE/ECCENTRICITY block content. */
  70.     SITE_ECCENTRICITY {
  71.         /** {@inheritDoc} */
  72.         @Override
  73.         public void parse(final SinexParseInfo parseInfo) {

  74.             // read antenna eccentricities data
  75.             final Station station = parseInfo.getCurrentLineStation(1);

  76.             // validity range
  77.             final AbsoluteDate start = parseInfo.getCurrentLineStartDate();
  78.             final AbsoluteDate end = parseInfo.getCurrentLineEndDate();

  79.             // reference system UNE or XYZ
  80.             station.setEccRefSystem(ReferenceSystem.getEccRefSystem(parseInfo.parseString(42, 3)));

  81.             // eccentricity vector
  82.             final Vector3D eccStation = new Vector3D(parseInfo.parseDouble(46, 8),
  83.                                                      parseInfo.parseDouble(55, 8),
  84.                                                      parseInfo.parseDouble(64, 8));

  85.             // special implementation for the first entry
  86.             if (station.getEccentricitiesTimeSpanMap().getSpansNumber() == 1) {
  87.                 // we want null values outside validity limits of the station
  88.                 station.addStationEccentricitiesValidBefore(eccStation, end);
  89.                 station.addStationEccentricitiesValidBefore(null, start);
  90.             } else {
  91.                 station.addStationEccentricitiesValidBefore(eccStation, end);
  92.             }

  93.         }
  94.     },

  95.     /** Predicate for SOLUTION/EPOCHS block content. */
  96.     SOLUTION_EPOCHS {
  97.         /** {@inheritDoc} */
  98.         @Override
  99.         public void parse(final SinexParseInfo parseInfo) {

  100.             // station
  101.             final Station station = parseInfo.getCurrentLineStation(1);

  102.             // validity range
  103.             station.setValidFrom(parseInfo.getCurrentLineStartDate());
  104.             station.setValidUntil(parseInfo.getCurrentLineEndDate());

  105.         }
  106.     },

  107.     /** Predicate for SITE/GPS_PHASE_CENTER block content. */
  108.     SITE_GPS_PHASE_CENTER {
  109.         /** {@inheritDoc} */
  110.         @Override
  111.         public void parse(final SinexParseInfo parseInfo) {

  112.             // antenna key
  113.             final AntennaKey key = new AntennaKey(parseInfo.parseString(1, 16),
  114.                                                   parseInfo.parseString(17, 4),
  115.                                                   parseInfo.parseString(22, 5));

  116.             // phase center for first signal in current line
  117.             final Vector3D phaseCenter1 = new Vector3D(parseInfo.parseDouble(28, 6),
  118.                                                        parseInfo.parseDouble(35, 6),
  119.                                                        parseInfo.parseDouble(42, 6));
  120.             parseInfo.addStationPhaseCenter(key, phaseCenter1, GPS_SIGNALS);

  121.             // phase center for second signal in current line
  122.             final Vector3D phaseCenter2 = new Vector3D(parseInfo.parseDouble(49, 6),
  123.                                                        parseInfo.parseDouble(56, 6),
  124.                                                        parseInfo.parseDouble(63, 6));
  125.             parseInfo.addStationPhaseCenter(key, phaseCenter2, GPS_SIGNALS);

  126.         }
  127.     },

  128.     /** Predicate for SITE/GAL_PHASE_CENTER block content. */
  129.     SITE_GAL_PHASE_CENTER {
  130.         /** {@inheritDoc} */
  131.         @Override
  132.         public void parse(final SinexParseInfo parseInfo) {

  133.             // antenna key
  134.             final AntennaKey key = new AntennaKey(parseInfo.parseString(1, 16),
  135.                                                   parseInfo.parseString(17, 4),
  136.                                                   parseInfo.parseString(22, 5));

  137.             // phase center for first signal in current line
  138.             final Vector3D phaseCenter1 = new Vector3D(parseInfo.parseDouble(28, 6),
  139.                                                        parseInfo.parseDouble(35, 6),
  140.                                                        parseInfo.parseDouble(42, 6));
  141.             parseInfo.addStationPhaseCenter(key, phaseCenter1, GALILEO_SIGNALS);

  142.             if (!parseInfo.parseString(49, 6).trim().isEmpty()) {
  143.                 // phase center for second signal in current line
  144.                 final Vector3D phaseCenter2 = new Vector3D(parseInfo.parseDouble(49, 6),
  145.                                                            parseInfo.parseDouble(56, 6),
  146.                                                            parseInfo.parseDouble(63, 6));
  147.                 parseInfo.addStationPhaseCenter(key, phaseCenter2, GALILEO_SIGNALS);
  148.             }

  149.         }
  150.     },

  151.     /** Predicate for SATELLITE/PHASE_CENTER block content. */
  152.     SATELLITE_PHASE_CENTER {
  153.         /** {@inheritDoc} */
  154.         @Override
  155.         public void parse(final SinexParseInfo parseInfo) {

  156.             // satellite id
  157.             final SatInSystem satInSystem = new SatInSystem(parseInfo.parseString(1, 4));

  158.             // first signal in current line
  159.             final GnssSignal signal1     = decode(satInSystem.getSystem(), parseInfo.parseInt(6, 1), parseInfo);
  160.             // beware! the fields are in order Z, X, Y in the file
  161.             final Vector3D   phaseCenter1 = new Vector3D(parseInfo.parseDouble(15, 6),
  162.                                                          parseInfo.parseDouble(22, 6),
  163.                                                          parseInfo.parseDouble( 8, 6));
  164.             parseInfo.addSatellitePhaseCenter(satInSystem, signal1, phaseCenter1);

  165.             if (!parseInfo.parseString(31, 6).trim().isEmpty()) {
  166.                 // second signal in current line
  167.                 final GnssSignal signal2      = decode(satInSystem.getSystem(), parseInfo.parseInt(29, 1), parseInfo);
  168.                 // beware! the fields are in order Z, X, Y in the file
  169.                 final Vector3D   phaseCenter2 = new Vector3D(parseInfo.parseDouble(38, 6),
  170.                                                              parseInfo.parseDouble(45, 6),
  171.                                                              parseInfo.parseDouble(31, 6));
  172.                 parseInfo.addSatellitePhaseCenter(satInSystem, signal2, phaseCenter2);
  173.             }

  174.         }

  175.         /** Decode GNSS signal.
  176.          * @param system satellite system
  177.          * @param code frequency code
  178.          * @param parseInfo holder for parse info
  179.          * @return GNSS signal
  180.          */
  181.         private GnssSignal decode(final SatelliteSystem system, final int code, final SinexParseInfo parseInfo) {
  182.             if (system == SatelliteSystem.GPS) {
  183.                 if (code == 1) {
  184.                     return PredefinedGnssSignal.G01;
  185.                 } else if (code == 2) {
  186.                     return PredefinedGnssSignal.G02;
  187.                 } else if (code == 5) {
  188.                     return PredefinedGnssSignal.G05;
  189.                 }
  190.             } else if (system == SatelliteSystem.GALILEO) {
  191.                 if (code == 1) {
  192.                     return PredefinedGnssSignal.E01;
  193.                 } else if (code == 5) {
  194.                     return PredefinedGnssSignal.E05;
  195.                 } else if (code == 6) {
  196.                     return PredefinedGnssSignal.E06;
  197.                 } else if (code == 7) {
  198.                     return PredefinedGnssSignal.E07;
  199.                 } else if (code == 8) {
  200.                     return PredefinedGnssSignal.E08;
  201.                 }
  202.             } else if (system == SatelliteSystem.GLONASS) {
  203.                 if (code == 1) {
  204.                     // here, the SINEX specification lists L1 frequency, R01 is the closest one
  205.                     return PredefinedGnssSignal.R01;
  206.                 } else if (code == 2) {
  207.                     // here, the SINEX specification lists L2 frequency, R02 is the closest one
  208.                     return PredefinedGnssSignal.R02;
  209.                 } else if (code == 5) {
  210.                     // here, the SINEX specification lists L5 frequency, R03 is the closest one
  211.                     return PredefinedGnssSignal.R03;
  212.                 }
  213.             } else if (system == SatelliteSystem.QZSS) {
  214.                 // this is not in the SINEX specification, but some files use it
  215.                 if (code == 1) {
  216.                     return PredefinedGnssSignal.J01;
  217.                 } else if (code == 2) {
  218.                     return PredefinedGnssSignal.J02;
  219.                 } else if (code == 5) {
  220.                     return PredefinedGnssSignal.J05;
  221.                 }
  222.             }
  223.             throw new OrekitException(OrekitMessages.UNKNOWN_GNSS_FREQUENCY,
  224.                                       system, code, parseInfo.getLineNumber(), parseInfo.getName());
  225.         }

  226.     };

  227.     /** Signals used for SITE/GPS_PHASE_CENTER. */
  228.     private static final PredefinedGnssSignal[] GPS_SIGNALS =
  229.         new PredefinedGnssSignal[] {
  230.             PredefinedGnssSignal.G01, PredefinedGnssSignal.G02
  231.         };

  232.     /** Signals used for SITE/GAL_PHASE_CENTER. */
  233.     private static final PredefinedGnssSignal[] GALILEO_SIGNALS =
  234.         new PredefinedGnssSignal[] {
  235.             PredefinedGnssSignal.E01, PredefinedGnssSignal.E05,
  236.             PredefinedGnssSignal.E06, PredefinedGnssSignal.E07,
  237.             PredefinedGnssSignal.E08
  238.         };

  239.     /** {@inheritDoc} */
  240.     @Override
  241.     public boolean test(final SinexParseInfo parseInfo) {
  242.         if (parseInfo.getLine().charAt(0) != '-') {
  243.             parse(parseInfo);
  244.             return true;
  245.         } else {
  246.             return false;
  247.         }
  248.     }

  249.     /** Parse one line.
  250.      * @param parseInfo container for parse info
  251.      */
  252.     protected abstract void parse(SinexParseInfo parseInfo);

  253. }