AbstractDualFrequencyCombination.java
- /* Copyright 2002-2025 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.gnss;
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.List;
- import org.orekit.errors.OrekitException;
- import org.orekit.errors.OrekitMessages;
- import org.orekit.files.rinex.observation.ObservationData;
- import org.orekit.files.rinex.observation.ObservationDataSet;
- import org.orekit.gnss.GnssSignal;
- import org.orekit.gnss.MeasurementType;
- import org.orekit.gnss.ObservationType;
- import org.orekit.gnss.SatelliteSystem;
- import org.orekit.utils.Constants;
- /** Base class for dual frequency combination of measurements.
- * @author Bryan Cazabonne
- * @since 10.1
- */
- public abstract class AbstractDualFrequencyCombination implements MeasurementCombination {
- /** Type of combination of measurements. */
- private final CombinationType type;
- /** Satellite system used for the combination. */
- private final SatelliteSystem system;
- /**
- * Constructor.
- * @param type combination of measurements type
- * @param system satellite system
- */
- protected AbstractDualFrequencyCombination(final CombinationType type, final SatelliteSystem system) {
- this.type = type;
- this.system = system;
- }
- /** {@inheritDoc} */
- @Override
- public String getName() {
- return type.getName();
- }
- /**
- * Combines observation data using a dual frequency combination of measurements.
- * @param od1 first observation data to combined
- * @param od2 second observation data to combined
- * @return a combined observation data
- */
- public CombinedObservationData combine(final ObservationData od1, final ObservationData od2) {
- // Observation types
- final ObservationType obsType1 = od1.getObservationType();
- final ObservationType obsType2 = od2.getObservationType();
- // Frequencies
- final GnssSignal signal1 = obsType1.getSignal(system);
- final GnssSignal signal2 = obsType2.getSignal(system);
- // Check if the combination of measurements if performed for two different frequencies
- if (signal1 == signal2) {
- throw new OrekitException(OrekitMessages.INCOMPATIBLE_FREQUENCIES_FOR_COMBINATION_OF_MEASUREMENTS,
- signal1.getFrequency(), signal2.getFrequency(), getName());
- }
- // Measurements types
- final MeasurementType measType1 = obsType1.getMeasurementType();
- final MeasurementType measType2 = obsType2.getMeasurementType();
- // Check if measurement types are the same
- if (measType1 != measType2) {
- // If the measurement types are differents, an exception is thrown
- throw new OrekitException(OrekitMessages.INVALID_MEASUREMENT_TYPES_FOR_COMBINATION_OF_MEASUREMENTS,
- measType1, measType2, getName());
- }
- // Combined frequency
- final double combinedFrequency = getCombinedFrequency(signal1, signal2);
- // Combined value
- final double combinedValue;
- if (obsType1.getMeasurementType() == MeasurementType.CARRIER_PHASE && !Double.isNaN(combinedFrequency)) {
- // Transform from cycle to meters measurements
- final double obs1Meters = od1.getValue() * signal1.getWavelength();
- final double obs2Meters = od2.getValue() * signal2.getWavelength();
- // Calculate the combined value and convert it in cycles using the combined frequency
- combinedValue = getCombinedValue(obs1Meters, signal1, obs2Meters, signal2) * combinedFrequency / Constants.SPEED_OF_LIGHT;
- } else {
- combinedValue = getCombinedValue(od1.getValue(), signal1, od2.getValue(), signal2);
- }
- // Combined observation data
- return new CombinedObservationData(combinedValue, combinedFrequency, type, measType1, Arrays.asList(od1, od2));
- }
- /** {@inheritDoc} */
- @Override
- public CombinedObservationDataSet combine(final ObservationDataSet observations) {
- // Initialize list of measurements
- final List<ObservationData> pseudoRanges = new ArrayList<>();
- final List<ObservationData> phases = new ArrayList<>();
- // Loop on observation data to fill lists
- for (final ObservationData od : observations.getObservationData()) {
- if (!Double.isNaN(od.getValue())) {
- if (od.getObservationType().getMeasurementType() == MeasurementType.PSEUDO_RANGE) {
- pseudoRanges.add(od);
- } else if (od.getObservationType().getMeasurementType() == MeasurementType.CARRIER_PHASE) {
- phases.add(od);
- }
- }
- }
- // Initialize list of combined observation data
- final List<CombinedObservationData> combined = new ArrayList<>();
- // Combine pseudo-ranges
- for (int i = 0; i < pseudoRanges.size() - 1; i++) {
- for (int j = 1; j < pseudoRanges.size(); j++) {
- final boolean combine = isCombinationPossible(pseudoRanges.get(i), pseudoRanges.get(j));
- if (combine) {
- combined.add(combine(pseudoRanges.get(i), pseudoRanges.get(j)));
- }
- }
- }
- // Combine carrier-phases
- for (int i = 0; i < phases.size() - 1; i++) {
- for (int j = 1; j < phases.size(); j++) {
- final boolean combine = isCombinationPossible(phases.get(i), phases.get(j));
- if (combine) {
- combined.add(combine(phases.get(i), phases.get(j)));
- }
- }
- }
- return new CombinedObservationDataSet(observations.getSatellite().getSystem(),
- observations.getSatellite().getPRN(),
- observations.getDate(),
- observations.getRcvrClkOffset(), combined);
- }
- /**
- * Get the combined observed value of two measurements.
- *
- * @param obs1 observed value of the first measurement
- * @param s1 frequency of the first measurement
- * @param obs2 observed value of the second measurement
- * @param s2 frequency of the second measurement
- * @return combined observed value
- */
- protected abstract double getCombinedValue(double obs1, GnssSignal s1, double obs2, GnssSignal s2);
- /**
- * Get the combined frequency of two measurements.
- *
- * @param s1 frequency of the first measurement
- * @param s2 frequency of the second measurement
- * @return combined frequency in Hz
- */
- protected abstract double getCombinedFrequency(GnssSignal s1, GnssSignal s2);
- /**
- * Verifies if two observation data can be combined.
- * @param data1 first observation data
- * @param data2 second observation data
- * @return true if observation data can be combined
- */
- private boolean isCombinationPossible(final ObservationData data1, final ObservationData data2) {
- // Observation types
- final ObservationType obsType1 = data1.getObservationType();
- final ObservationType obsType2 = data2.getObservationType();
- // Dual-frequency combination is possible only if observation code is the same and data frequencies are different
- return obsType1.getSignal(system) != obsType2.getSignal(system) &&
- obsType1.getSignalCode() == obsType2.getSignalCode();
- }
- }