1   /* Copyright 2002-2025 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  
19  import org.hipparchus.util.ArithmeticUtils;
20  import org.hipparchus.util.MathArrays;
21  import org.orekit.gnss.GnssSignal;
22  import org.orekit.gnss.MeasurementType;
23  import org.orekit.gnss.SatelliteSystem;
24  
25  /**
26   * Ionosphere-free combination.
27   * <p>
28   * This combination removes the first order (up to 99.9%)
29   * ionospheric effect.
30   * </p>
31   * <pre>
32   *             f1² * m1 - f2² * m2
33   *    mIF =  -----------------------
34   *                  f1² - f2²
35   * </pre>
36   * With:
37   * <ul>
38   * <li>mIF: Ionosphere-free measurement.</li>
39   * <li>f1 : Frequency of the first measurement.</li>
40   * <li>m1 : First measurement.</li>
41   * <li>f2 : Frequency of the second measurement.</li>
42   * <li>m1 : Second measurement.</li>
43   * </ul>
44   * <p>
45   * Ionosphere-free combination is a dual frequency combination.
46   * The two measurements shall have different frequencies but they must have the same {@link MeasurementType}.
47   * </p>
48   * @author Bryan Cazabonne
49   * @since 10.1
50   */
51  public class IonosphereFreeCombination extends AbstractDualFrequencyCombination {
52  
53      /**
54       * Package private constructor for the factory.
55       * @param system satellite system for which the combination is applied
56       */
57      IonosphereFreeCombination(final SatelliteSystem system) {
58          super(CombinationType.IONO_FREE, system);
59      }
60  
61      /** {@inheritDoc} */
62      @Override
63      protected double getCombinedValue(final double obs1, final GnssSignal s1,
64                                        final double obs2, final GnssSignal s2) {
65          // Get the ration f/f0
66          final double ratioF1   = s1.getRatio();
67          final double ratioF2   = s2.getRatio();
68          final double ratioF1Sq = ratioF1 * ratioF1;
69          final double ratioF2Sq = ratioF2 * ratioF2;
70          // Perform combination
71          return MathArrays.linearCombination(ratioF1Sq, obs1, -ratioF2Sq, obs2) / (ratioF1Sq - ratioF2Sq);
72      }
73  
74      /** {@inheritDoc} */
75      @Override
76      protected double getCombinedFrequency(final GnssSignal s1, final GnssSignal s2) {
77          // Get the ratios f/f0
78          final double ratioF1   = s1.getRatio();
79          final double ratioF2   = s2.getRatio();
80          // Get the integer part of the ratios
81          final int ratioF1Int = (int) ratioF1;
82          final int ratioF2Int = (int) ratioF2;
83          // Multiplication factor used to compute the combined frequency
84          final int k = (ratioF1 - ratioF1Int > 0.0 || ratioF2 - ratioF2Int > 0.0) ? 1 : ArithmeticUtils.gcd(ratioF1Int, ratioF2Int);
85          // Combined frequency
86          return MathArrays.linearCombination(ratioF1, ratioF1, -ratioF2, ratioF2) * (GnssSignal.F0 / k);
87      }
88  
89  }