SingleFrequencyHatchFilter.java
- /* Copyright 2002-2024 CS GROUP
- * Licensed to CS GROUP (CS) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * CS licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package org.orekit.estimation.measurements.filtering;
- import java.util.HashMap;
- import java.util.Map;
- import org.hipparchus.util.FastMath;
- import org.orekit.files.rinex.observation.ObservationData;
- import org.orekit.gnss.MeasurementType;
- /**
- * Single frequency Hatch filter.
- * <p>
- * The single frequency Hatch Filter is used to smooth the
- * pseudo-range measurement using either a Doppler measurement
- * or a carrier phase measurement.
- * </p>
- * @see "Subirana, J. S., Hernandez-Pajares, M., and José Miguel Juan Zornoza. (2013).
- * GNSS Data Processing: Fundamentals and Algorithms. European Space Agency."
- *
- * @see "Zhou, Z., and Li, B. (2017). Optimal Doppler-aided smoothing strategy for GNSS navigation.
- * GPS solutions, 21(1), 197-210."
- *
- * @author Louis Aucouturier
- * @since 11.2
- */
- public class SingleFrequencyHatchFilter extends HatchFilter {
- /** Interval time between two measurements. */
- private final double integrationTime;
- /** Wavelength of the Doppler measurements. */
- private final double wavelength;
- /** Type of the smoothing measurement. */
- private final SmoothingMeasurement smoothing;
- /**
- * Constructor for the Single Frequency Hatch Filter.
- * <p>
- * The threshold parameter corresponds to the maximum difference between
- * non-smoothed and smoothed pseudo range value, above which the filter
- * is reset.
- * </p>
- * @param initCode initial code measurement
- * @param initSmoothing initial smoothing measurement
- * @param type type of the smoothing measurement (CARRIER_PHASE or DOPPLER)
- * @param wavelength measurement value wavelength (m)
- * @param threshold threshold for loss of lock detection
- * (represents the maximum difference between smoothed
- * and measured values for loss of lock detection)
- * @param N window size of the Hatch Filter
- * @param integrationTime time interval between two measurements (s)
- */
- public SingleFrequencyHatchFilter(final ObservationData initCode, final ObservationData initSmoothing,
- final MeasurementType type, final double wavelength,
- final double threshold, final int N,
- final double integrationTime) {
- super(threshold, N);
- this.wavelength = wavelength;
- this.integrationTime = integrationTime;
- this.smoothing = SmoothingMeasurement.getSmoothingMeasurement(type);
- updatePreviousSmoothedCode(initCode.getValue());
- updatePreviousSmoothingValue(smoothing.getSmoothingValue(wavelength, integrationTime, initSmoothing.getValue()));
- addToSmoothedCodeHistory(initCode.getValue());
- addToCodeHistory(initCode.getValue());
- }
- /**
- * This method filters the provided data given the state of the filter.
- * @param codeData input code observation data
- * @param smoothingData input smoothing observation data
- * @return the smoothed observation data
- * */
- public ObservationData filterData(final ObservationData codeData, final ObservationData smoothingData) {
- // Current code value
- final double code = codeData.getValue();
- addToCodeHistory(code);
- // Current smoothing value
- // smoothed_code = w * code + (1 - w) * (previous_smoothed_code + (smoothing_value - previous_smoothing_value))
- final double smoothingValue = smoothing.getSmoothingValue(wavelength, integrationTime, smoothingData.getValue());
- // Check for carrier phase cycle slip
- final boolean cycleSlip = FastMath.floorMod(smoothingData.getLossOfLockIndicator(), 2) != 0;
- // Computes the smoothed code value and store the smoothing
- // value for the next iteration (will be used as "previous_smoothing_value")
- double smoothedValue = smoothedCode(code, smoothingValue);
- updatePreviousSmoothingValue(smoothingValue * smoothing.getSign());
- // Check the smoothed value for loss or lock or filter resetting
- smoothedValue = checkValidData(code, smoothedValue, cycleSlip);
- addToSmoothedCodeHistory(smoothedValue);
- updatePreviousSmoothedCode(smoothedValue);
- // Return the smoothed observed data
- return new ObservationData(codeData.getObservationType(), smoothedValue,
- codeData.getLossOfLockIndicator(), codeData.getSignalStrength());
- }
- /** Smoothing measurement. */
- private enum SmoothingMeasurement {
- /** Carrier-phase measurement. */
- CARRIER_PHASE(MeasurementType.CARRIER_PHASE) {
- /** {@inheritDoc} */
- @Override
- public double getSmoothingValue(final double lambda, final double time, final double value) {
- return lambda * value;
- }
- /** {@inheritDoc} */
- @Override
- public int getSign() {
- return 1;
- }
- },
- /** Doppler measurement. */
- DOPPLER(MeasurementType.DOPPLER) {
- /** {@inheritDoc} */
- @Override
- public double getSmoothingValue(final double lambda, final double time, final double value) {
- return 0.5 * time * lambda * value;
- }
- /** {@inheritDoc} */
- @Override
- public int getSign() {
- return -1;
- }
- };
- /** Parsing map. */
- private static final Map<MeasurementType, SmoothingMeasurement> KEYS_MAP = new HashMap<>();
- static {
- for (final SmoothingMeasurement measurement : values()) {
- KEYS_MAP.put(measurement.getType(), measurement);
- }
- }
- /** Measurement type. */
- private final MeasurementType type;
- /**
- * Constructor.
- * @param type measurement type
- */
- SmoothingMeasurement(final MeasurementType type) {
- this.type = type;
- }
- /**
- * Get the smoothing value of the measurement.
- * @param lambda measurement wavelength (m)
- * @param time time interval between two measurements (s)
- * @param value measurement value (not the smoothing value!)
- * @return the smoothing value used to smooth the pseudo-range measurement
- */
- public abstract double getSmoothingValue(double lambda, double time, double value);
- /**
- * Get the sign for the "previous_smoothing_value".
- * @return the sign for the "previous_smoothing_value"
- */
- public abstract int getSign();
- /**
- * Get the smoothing measurement corresponding to the input type.
- * @param type measurment type
- * @return the corresponding smoothing measurement
- */
- public static SmoothingMeasurement getSmoothingMeasurement(final MeasurementType type) {
- return KEYS_MAP.get(type);
- }
- /**
- * Get the measurement type.
- * @return the measurement type
- */
- public MeasurementType getType() {
- return type;
- }
- }
- }