AbstractSingleFrequencyCombination.java

  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.estimation.measurements.gnss;

  18. import java.util.ArrayList;
  19. import java.util.Arrays;
  20. import java.util.List;

  21. import org.orekit.errors.OrekitException;
  22. import org.orekit.errors.OrekitMessages;
  23. import org.orekit.files.rinex.observation.ObservationData;
  24. import org.orekit.files.rinex.observation.ObservationDataSet;
  25. import org.orekit.gnss.GnssSignal;
  26. import org.orekit.gnss.MeasurementType;
  27. import org.orekit.gnss.ObservationType;
  28. import org.orekit.gnss.SatelliteSystem;

  29. /** Base class for single frequency combination of measurements.
  30.  * @author Bryan Cazabonne
  31.  * @since 10.1
  32.  */
  33. public abstract class AbstractSingleFrequencyCombination implements MeasurementCombination {

  34.     /** Type of combination of measurements. */
  35.     private final CombinationType type;

  36.     /** Satellite system used for the combination. */
  37.     private final SatelliteSystem system;

  38.     /**
  39.      * Constructor.
  40.      * @param type combination of measurements type
  41.      * @param system satellite system
  42.      */
  43.     protected AbstractSingleFrequencyCombination(final CombinationType type, final SatelliteSystem system) {
  44.         this.type   = type;
  45.         this.system = system;
  46.     }

  47.     /** {@inheritDoc} */
  48.     @Override
  49.     public String getName() {
  50.         return type.getName();
  51.     }

  52.     /** {@inheritDoc} */
  53.     @Override
  54.     public CombinedObservationDataSet combine(final ObservationDataSet observations) {

  55.         // Initialize list of measurements
  56.         final List<ObservationData> pseudoRanges = new ArrayList<>();
  57.         final List<ObservationData> phases       = new ArrayList<>();

  58.         // Loop on observation data to fill lists
  59.         for (final ObservationData od : observations.getObservationData()) {
  60.             if (!Double.isNaN(od.getValue())) {
  61.                 if (od.getObservationType().getMeasurementType() == MeasurementType.PSEUDO_RANGE) {
  62.                     pseudoRanges.add(od);
  63.                 } else if (od.getObservationType().getMeasurementType() == MeasurementType.CARRIER_PHASE) {
  64.                     phases.add(od);
  65.                 }
  66.             }
  67.         }

  68.         // Initialize list of combined observation data
  69.         final List<CombinedObservationData> combined = new ArrayList<>();

  70.         for (final ObservationData phase : phases) {
  71.             for (final ObservationData pseudoRange : pseudoRanges) {
  72.                 // Single-frequency combination is possible only if data frequencies are the same
  73.                 if (phase.getObservationType().getSignal(system) == pseudoRange.getObservationType().getSignal(system) &&
  74.                     phase.getObservationType().getSignalCode()      == pseudoRange.getObservationType().getSignalCode()) {
  75.                     combined.add(combine(phase, pseudoRange));
  76.                 }
  77.             }
  78.         }

  79.         return new CombinedObservationDataSet(observations.getSatellite().getSystem(),
  80.                                               observations.getSatellite().getPRN(),
  81.                                               observations.getDate(),
  82.                                               observations.getRcvrClkOffset(), combined);
  83.     }

  84.     /**
  85.      * Combines observation data using a single frequency combination of measurements.
  86.      * @param phase phase measurement
  87.      * @param pseudoRange pseudoRange measurement
  88.      * @return a combined observation data
  89.      */
  90.     public CombinedObservationData combine(final ObservationData phase, final ObservationData pseudoRange) {

  91.         // Observation types
  92.         final ObservationType obsType1 = phase.getObservationType();
  93.         final ObservationType obsType2 = pseudoRange.getObservationType();

  94.         // Frequencies
  95.         final GnssSignal freq1 = obsType1.getSignal(system);
  96.         final GnssSignal freq2 = obsType2.getSignal(system);
  97.         // Check if the combination of measurements if performed for two different frequencies
  98.         if (freq1 != freq2) {
  99.             throw new OrekitException(OrekitMessages.INCOMPATIBLE_FREQUENCIES_FOR_COMBINATION_OF_MEASUREMENTS,
  100.                                       freq1, freq2, getName());
  101.         }

  102.         // Measurements types
  103.         final MeasurementType measType1 = obsType1.getMeasurementType();
  104.         final MeasurementType measType2 = obsType2.getMeasurementType();

  105.         // Check if measurement types are the same
  106.         if (measType1 == measType2) {
  107.             // If the measurement types are the same, an exception is thrown
  108.             throw new OrekitException(OrekitMessages.INVALID_MEASUREMENT_TYPES_FOR_COMBINATION_OF_MEASUREMENTS,
  109.                                       measType1, measType2, getName());
  110.         }

  111.         // Frequency
  112.         final double f = freq1.getFrequency();

  113.         // Combined value
  114.         final double combinedValue = getCombinedValue(phase.getValue(), pseudoRange.getValue());

  115.         // Combined observation data
  116.         return new CombinedObservationData(combinedValue, f,
  117.                                            CombinationType.PHASE_MINUS_CODE, MeasurementType.COMBINED_RANGE_PHASE,
  118.                                            Arrays.asList(phase, pseudoRange));
  119.     }

  120.     /**
  121.      * Get the combined observed value of two measurements.
  122.      * @param phase observed value of the phase measurement
  123.      * @param pseudoRange observed value of the range measurement
  124.      * @return combined observed value
  125.      */
  126.     protected abstract double getCombinedValue(double phase, double pseudoRange);

  127. }