AbstractSingleFrequencyCombination.java

  1. /* Copyright 2002-2020 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.gnss.CombinedObservationData;
  24. import org.orekit.gnss.CombinedObservationDataSet;
  25. import org.orekit.gnss.Frequency;
  26. import org.orekit.gnss.MeasurementType;
  27. import org.orekit.gnss.ObservationData;
  28. import org.orekit.gnss.ObservationDataSet;
  29. import org.orekit.gnss.ObservationType;
  30. import org.orekit.gnss.RinexHeader;
  31. import org.orekit.gnss.SatelliteSystem;

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

  37.     /** Type of combination of measurements. */
  38.     private final CombinationType type;

  39.     /** Satellite system used for the combination. */
  40.     private final SatelliteSystem system;

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

  50.     /** {@inheritDoc} */
  51.     @Override
  52.     public String getName() {
  53.         return type.getName();
  54.     }

  55.     /** {@inheritDoc} */
  56.     @Override
  57.     public CombinedObservationDataSet combine(final ObservationDataSet observations) {

  58.         // Rinex file header
  59.         final RinexHeader header = observations.getHeader();
  60.         // Rinex version to integer
  61.         final int version = (int) header.getRinexVersion();

  62.         // Initialize list of measurements
  63.         final List<ObservationData> pseudoRanges = new ArrayList<>();
  64.         final List<ObservationData> phases       = new ArrayList<>();

  65.         // Loop on observation data to fill lists
  66.         for (final ObservationData od : observations.getObservationData()) {
  67.             if (!Double.isNaN(od.getValue())) {
  68.                 if (od.getObservationType().getMeasurementType() == MeasurementType.PSEUDO_RANGE) {
  69.                     pseudoRanges.add(od);
  70.                 } else if (od.getObservationType().getMeasurementType() == MeasurementType.CARRIER_PHASE) {
  71.                     phases.add(od);
  72.                 }
  73.             }
  74.         }

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

  77.         for (int i = 0; i < phases.size(); i++) {
  78.             for (int j = 0; j < pseudoRanges.size(); j++) {
  79.                 final boolean combine = isCombinationPossible(version, phases.get(i), pseudoRanges.get(j));
  80.                 if (combine) {
  81.                     combined.add(combine(phases.get(i), pseudoRanges.get(j)));
  82.                 }
  83.             }
  84.         }

  85.         return new CombinedObservationDataSet(observations.getHeader(), observations.getSatelliteSystem(),
  86.                                               observations.getPrnNumber(), observations.getDate(),
  87.                                               observations.getRcvrClkOffset(), combined);
  88.     }

  89.     /**
  90.      * Combines observation data using a single frequency combination of measurements.
  91.      * @param phase phase measurement
  92.      * @param pseudoRange pseudoRange measurement
  93.      * @return a combined observation data
  94.      */
  95.     public CombinedObservationData combine(final ObservationData phase, final ObservationData pseudoRange) {

  96.         // Observation types
  97.         final ObservationType obsType1 = phase.getObservationType();
  98.         final ObservationType obsType2 = pseudoRange.getObservationType();

  99.         // Frequencies
  100.         final Frequency freq1 = obsType1.getFrequency(system);
  101.         final Frequency freq2 = obsType2.getFrequency(system);
  102.         // Check if the combination of measurements if performed for two different frequencies
  103.         if (freq1 != freq2) {
  104.             throw new OrekitException(OrekitMessages.INCOMPATIBLE_FREQUENCIES_FOR_COMBINATION_OF_MEASUREMENTS,
  105.                                       freq1, freq2, getName());
  106.         }

  107.         // Measurements types
  108.         final MeasurementType measType1 = obsType1.getMeasurementType();
  109.         final MeasurementType measType2 = obsType2.getMeasurementType();

  110.         // Check if measurement types are the same
  111.         if (measType1 == measType2) {
  112.             // If the measurement types are the same, an exception is thrown
  113.             throw new OrekitException(OrekitMessages.INVALID_MEASUREMENT_TYPES_FOR_COMBINATION_OF_MEASUREMENTS,
  114.                                       measType1, measType2, getName());
  115.         }

  116.         // Frequency
  117.         final double f = freq1.getMHzFrequency();

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

  120.         // Combined observation data
  121.         return new CombinedObservationData(CombinationType.PHASE_MINUS_CODE, MeasurementType.COMBINED_RANGE_PHASE,
  122.                                            combinedValue, f, Arrays.asList(phase, pseudoRange));
  123.     }

  124.     /**
  125.      * Get the combined observed value of two measurements.
  126.      * @param phase observed value of the phase measurement
  127.      * @param pseudoRange observed value of the range measurement
  128.      * @return combined observed value
  129.      */
  130.     protected abstract double getCombinedValue(double phase, double pseudoRange);

  131.     /**
  132.      * Verifies if two observation data can be combine.
  133.      * @param version Rinex file version (integer part)
  134.      * @param phase phase measurement
  135.      * @param pseudoRange pseudoRange measurement
  136.      * @return true if observation data can be combined
  137.      */
  138.     private boolean isCombinationPossible(final int version, final ObservationData phase, final ObservationData pseudoRange) {
  139.         // Observation types
  140.         final ObservationType obsType1 = phase.getObservationType();
  141.         final ObservationType obsType2 = pseudoRange.getObservationType();
  142.         // Single-frequency combination is possible only if data frequencies are the same
  143.         if (obsType1.getFrequency(system) == obsType2.getFrequency(system)) {
  144.             // Switch on Rinex version
  145.             switch (version) {
  146.                 case 2 : return true;
  147.                 case 3 : return obsType1.getSignalCode() == obsType2.getSignalCode();
  148.                 default: return false;
  149.             }
  150.         } else {
  151.             // False because observation data have different frequency
  152.             return false;
  153.         }
  154.     }

  155. }