AbstractDualFrequencyCombination.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.SatelliteSystem;

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

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

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

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

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

  54.     /**
  55.      * Combines observation data using a dual frequency combination of measurements.
  56.      * @param od1 first observation data to combined
  57.      * @param od2 second observation data to combined
  58.      * @return a combined observation data
  59.      */
  60.     public CombinedObservationData combine(final ObservationData od1, final ObservationData od2) {

  61.         // Observation types
  62.         final ObservationType obsType1 = od1.getObservationType();
  63.         final ObservationType obsType2 = od2.getObservationType();

  64.         // Frequencies
  65.         final Frequency freq1 = obsType1.getFrequency(system);
  66.         final Frequency freq2 = obsType2.getFrequency(system);
  67.         // Check if the combination of measurements if performed for two different frequencies
  68.         if (freq1 == freq2) {
  69.             throw new OrekitException(OrekitMessages.INCOMPATIBLE_FREQUENCIES_FOR_COMBINATION_OF_MEASUREMENTS,
  70.                                       freq1, freq2, getName());
  71.         }

  72.         // Measurements types
  73.         final MeasurementType measType1 = obsType1.getMeasurementType();
  74.         final MeasurementType measType2 = obsType2.getMeasurementType();

  75.         // Check if measurement types are the same
  76.         if (measType1 != measType2) {
  77.             // If the measurement types are differents, an exception is thrown
  78.             throw new OrekitException(OrekitMessages.INVALID_MEASUREMENT_TYPES_FOR_COMBINATION_OF_MEASUREMENTS,
  79.                                       measType1, measType2, getName());
  80.         }

  81.         // Combined value
  82.         final double combinedValue = getCombinedValue(od1.getValue(), freq1, od2.getValue(), freq2);

  83.         // Combined frequency
  84.         final double combinedFrequency = getCombinedFrequency(freq1, freq2);

  85.         // Combined observation data
  86.         return new CombinedObservationData(type, measType1, combinedValue, combinedFrequency, Arrays.asList(od1, od2));

  87.     }

  88.     /** {@inheritDoc} */
  89.     @Override
  90.     public CombinedObservationDataSet combine(final ObservationDataSet observations) {

  91.         // Initialize list of measurements
  92.         final List<ObservationData> pseudoRanges = new ArrayList<>();
  93.         final List<ObservationData> phases       = new ArrayList<>();

  94.         // Loop on observation data to fill lists
  95.         for (final ObservationData od : observations.getObservationData()) {
  96.             if (!Double.isNaN(od.getValue())) {
  97.                 if (od.getObservationType().getMeasurementType() == MeasurementType.PSEUDO_RANGE) {
  98.                     pseudoRanges.add(od);
  99.                 } else if (od.getObservationType().getMeasurementType() == MeasurementType.CARRIER_PHASE) {
  100.                     phases.add(od);
  101.                 }
  102.             }
  103.         }

  104.         // Initialize list of combined observation data
  105.         final List<CombinedObservationData> combined = new ArrayList<>();
  106.         // Combine pseudo-ranges
  107.         for (int i = 0; i < pseudoRanges.size() - 1; i++) {
  108.             for (int j = 1; j < pseudoRanges.size(); j++) {
  109.                 final boolean combine = isCombinationPossible(pseudoRanges.get(i), pseudoRanges.get(j));
  110.                 if (combine) {
  111.                     combined.add(combine(pseudoRanges.get(i), pseudoRanges.get(j)));
  112.                 }
  113.             }
  114.         }
  115.         // Combine carrier-phases
  116.         for (int i = 0; i < phases.size() - 1; i++) {
  117.             for (int j = 1; j < phases.size(); j++) {
  118.                 final boolean combine = isCombinationPossible(phases.get(i), phases.get(j));
  119.                 if (combine) {
  120.                     combined.add(combine(phases.get(i), phases.get(j)));
  121.                 }
  122.             }
  123.         }

  124.         return new CombinedObservationDataSet(observations.getHeader(), observations.getSatelliteSystem(),
  125.                                               observations.getPrnNumber(), observations.getDate(),
  126.                                               observations.getRcvrClkOffset(), combined);
  127.     }

  128.     /**
  129.      * Get the combined observed value of two measurements.
  130.      * @param obs1 observed value of the first measurement
  131.      * @param f1 frequency of the first measurement
  132.      * @param obs2 observed value of the second measurement
  133.      * @param f2 frequency of the second measurement
  134.      * @return combined observed value
  135.      */
  136.     protected abstract double getCombinedValue(double obs1, Frequency f1, double obs2, Frequency f2);

  137.     /**
  138.      * Get the combined frequency of two measurements.
  139.      * @param f1 frequency of the first measurement
  140.      * @param f2 frequency of the second measurement
  141.      * @return combined frequency in MHz
  142.      */
  143.     protected abstract double getCombinedFrequency(Frequency f1, Frequency f2);

  144.     /**
  145.      * Verifies if two observation data can be combine.
  146.      * @param data1 first observation data
  147.      * @param data2 second observation data
  148.      * @return true if observation data can be combined
  149.      */
  150.     private boolean isCombinationPossible(final ObservationData data1, final ObservationData data2) {
  151.         // Observation types
  152.         final ObservationType obsType1 = data1.getObservationType();
  153.         final ObservationType obsType2 = data2.getObservationType();
  154.         // Dual-frequency combination is possible only if observation code is the same and data frequencies are different
  155.         return (obsType1.getFrequency(system) != obsType2.getFrequency(system)) &&
  156.                         (obsType1.getSignalCode() == obsType2.getSignalCode());
  157.     }

  158. }