SingleFrequencyHatchFilter.java

  1. /* Copyright 2002-2024 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.filtering;

  18. import java.util.HashMap;
  19. import java.util.Map;

  20. import org.hipparchus.util.FastMath;
  21. import org.orekit.files.rinex.observation.ObservationData;
  22. import org.orekit.gnss.MeasurementType;

  23. /**
  24.  * Single frequency Hatch filter.
  25.  * <p>
  26.  * The single frequency Hatch Filter is used to smooth the
  27.  * pseudo-range measurement using either a Doppler measurement
  28.  * or a carrier phase measurement.
  29.  * </p>
  30.  * @see "Subirana, J. S., Hernandez-Pajares, M., and José Miguel Juan Zornoza. (2013).
  31.  *       GNSS Data Processing: Fundamentals and Algorithms. European Space Agency."
  32.  *
  33.  * @see "Zhou, Z., and Li, B. (2017). Optimal Doppler-aided smoothing strategy for GNSS navigation.
  34.  *       GPS solutions, 21(1), 197-210."
  35.  *
  36.  * @author Louis Aucouturier
  37.  * @since 11.2
  38.  */
  39. public class SingleFrequencyHatchFilter extends HatchFilter {

  40.     /** Interval time between two measurements. */
  41.     private final double integrationTime;

  42.     /** Wavelength of the Doppler measurements. */
  43.     private final double wavelength;

  44.     /** Type of the smoothing measurement. */
  45.     private final SmoothingMeasurement smoothing;

  46.     /**
  47.      * Constructor for the Single Frequency Hatch Filter.
  48.      * <p>
  49.      * The threshold parameter corresponds to the maximum difference between
  50.      * non-smoothed and smoothed pseudo range value, above which the filter
  51.      * is reset.
  52.      * </p>
  53.      * @param initCode        initial code measurement
  54.      * @param initSmoothing   initial smoothing measurement
  55.      * @param type            type of the smoothing measurement (CARRIER_PHASE or DOPPLER)
  56.      * @param wavelength      measurement value wavelength (m)
  57.      * @param threshold       threshold for loss of lock detection
  58.      *                        (represents the maximum difference between smoothed
  59.      *                        and measured values for loss of lock detection)
  60.      * @param N               window size of the Hatch Filter
  61.      * @param integrationTime time interval between two measurements (s)
  62.      */
  63.     public SingleFrequencyHatchFilter(final ObservationData initCode, final ObservationData initSmoothing,
  64.                                       final MeasurementType type, final double wavelength,
  65.                                       final double threshold, final int N,
  66.                                       final double integrationTime) {
  67.         super(threshold, N);
  68.         this.wavelength      = wavelength;
  69.         this.integrationTime = integrationTime;
  70.         this.smoothing       = SmoothingMeasurement.getSmoothingMeasurement(type);
  71.         updatePreviousSmoothedCode(initCode.getValue());
  72.         updatePreviousSmoothingValue(smoothing.getSmoothingValue(wavelength, integrationTime, initSmoothing.getValue()));
  73.         addToSmoothedCodeHistory(initCode.getValue());
  74.         addToCodeHistory(initCode.getValue());
  75.     }

  76.     /**
  77.      * This method filters the provided data given the state of the filter.
  78.      * @param codeData      input code observation data
  79.      * @param smoothingData input smoothing observation data
  80.      * @return the smoothed observation data
  81.      * */
  82.     public ObservationData filterData(final ObservationData codeData, final ObservationData smoothingData) {

  83.         // Current code value
  84.         final double code = codeData.getValue();
  85.         addToCodeHistory(code);

  86.         // Current smoothing value
  87.         // smoothed_code = w * code + (1 - w) * (previous_smoothed_code + (smoothing_value - previous_smoothing_value))
  88.         final double smoothingValue = smoothing.getSmoothingValue(wavelength, integrationTime, smoothingData.getValue());

  89.         // Check for carrier phase cycle slip
  90.         final boolean cycleSlip = FastMath.floorMod(smoothingData.getLossOfLockIndicator(), 2) != 0;

  91.         // Computes the smoothed code value and store the smoothing
  92.         // value for the next iteration (will be used as "previous_smoothing_value")
  93.         double smoothedValue = smoothedCode(code, smoothingValue);
  94.         updatePreviousSmoothingValue(smoothingValue * smoothing.getSign());

  95.         // Check the smoothed value for loss or lock or filter resetting
  96.         smoothedValue = checkValidData(code, smoothedValue, cycleSlip);
  97.         addToSmoothedCodeHistory(smoothedValue);
  98.         updatePreviousSmoothedCode(smoothedValue);

  99.         // Return the smoothed observed data
  100.         return new ObservationData(codeData.getObservationType(), smoothedValue,
  101.                                    codeData.getLossOfLockIndicator(), codeData.getSignalStrength());

  102.     }

  103.     /** Smoothing measurement. */
  104.     private enum SmoothingMeasurement {

  105.         /** Carrier-phase measurement. */
  106.         CARRIER_PHASE(MeasurementType.CARRIER_PHASE) {

  107.             /** {@inheritDoc} */
  108.             @Override
  109.             public double getSmoothingValue(final double lambda, final double time, final double value) {
  110.                 return lambda * value;
  111.             }

  112.             /** {@inheritDoc} */
  113.             @Override
  114.             public int getSign() {
  115.                 return 1;
  116.             }

  117.         },

  118.         /** Doppler measurement. */
  119.         DOPPLER(MeasurementType.DOPPLER) {

  120.             /** {@inheritDoc} */
  121.             @Override
  122.             public double getSmoothingValue(final  double lambda, final  double time, final double value) {
  123.                 return 0.5 * time * lambda * value;
  124.             }

  125.             /** {@inheritDoc} */
  126.             @Override
  127.             public int getSign() {
  128.                 return -1;
  129.             }

  130.         };

  131.         /** Parsing map. */
  132.         private static final Map<MeasurementType, SmoothingMeasurement> KEYS_MAP = new HashMap<>();
  133.         static {
  134.             for (final SmoothingMeasurement measurement : values()) {
  135.                 KEYS_MAP.put(measurement.getType(), measurement);
  136.             }
  137.         }

  138.         /** Measurement type. */
  139.         private final MeasurementType type;

  140.         /**
  141.          * Constructor.
  142.          * @param type measurement type
  143.          */
  144.         SmoothingMeasurement(final MeasurementType type) {
  145.             this.type = type;
  146.         }

  147.         /**
  148.          * Get the smoothing value of the measurement.
  149.          * @param lambda measurement wavelength (m)
  150.          * @param time time interval between two measurements (s)
  151.          * @param value measurement value (not the smoothing value!)
  152.          * @return the smoothing value used to smooth the pseudo-range measurement
  153.          */
  154.         public abstract double getSmoothingValue(double lambda, double time, double value);

  155.         /**
  156.          * Get the sign for the "previous_smoothing_value".
  157.          * @return the sign for the "previous_smoothing_value"
  158.          */
  159.         public abstract int getSign();

  160.         /**
  161.          * Get the smoothing measurement corresponding to the input type.
  162.          * @param type measurment type
  163.          * @return the corresponding smoothing measurement
  164.          */
  165.         public static SmoothingMeasurement getSmoothingMeasurement(final MeasurementType type) {
  166.             return KEYS_MAP.get(type);
  167.         }

  168.         /**
  169.          * Get the measurement type.
  170.          * @return the measurement type
  171.          */
  172.         public MeasurementType getType() {
  173.             return type;
  174.         }

  175.     }

  176. }