FieldClockCorrectionsProvider.java

  1. /* Copyright 2022-2025 Luc Maisonobe
  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.propagation.analytical.gnss;

  18. import org.hipparchus.CalculusFieldElement;
  19. import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
  20. import org.hipparchus.util.MathArrays;
  21. import org.orekit.propagation.FieldAdditionalDataProvider;
  22. import org.orekit.propagation.FieldSpacecraftState;
  23. import org.orekit.propagation.analytical.gnss.data.FieldGNSSClockElements;
  24. import org.orekit.time.FieldAbsoluteDate;
  25. import org.orekit.utils.Constants;
  26. import org.orekit.utils.FieldPVCoordinates;

  27. /** Provider for clock corrections as additional states.
  28.  * <p>
  29.  * The value of this additional state is a three elements array containing
  30.  * </p>
  31.  * <ul>
  32.  *   <li>at index 0, the polynomial satellite clock model
  33.  *       Δtₛₐₜ = {@link FieldGNSSClockElements#getAf0() a₀} +
  34.  *               {@link FieldGNSSClockElements#getAf1() a₁} (t - {@link FieldGNSSClockElements#getToc() toc}) +
  35.  *               {@link FieldGNSSClockElements#getAf1() a₂} (t - {@link FieldGNSSClockElements#getToc() toc})²
  36.  *   </li>
  37.  *   <li>at index 1 the relativistic clock correction due to eccentricity</li>
  38.  *   <li>at index 2 the estimated group delay differential {@link FieldGNSSClockElements#getTGD() TGD} for L1-L2 correction</li>
  39.  * </ul>
  40.  *
  41.  * @param <T> type of the field elements
  42.  * @author Luc Maisonobe
  43.  * @since 13.0
  44.  */
  45. public class FieldClockCorrectionsProvider<T extends CalculusFieldElement<T>>
  46.     implements FieldAdditionalDataProvider<T[], T> {

  47.     /** The GPS clock elements. */
  48.     private final FieldGNSSClockElements<T> gnssClk;

  49.     /** Clock reference epoch. */
  50.     private final FieldAbsoluteDate<T> clockRef;

  51.     /** Duration of the GNSS cycle in seconds. */
  52.     private final double cycleDuration;

  53.     /** Simple constructor.
  54.      * @param gnssClk GNSS clock elements
  55.      * @param cycleDuration duration of the GNSS cycle in seconds
  56.      */
  57.     public FieldClockCorrectionsProvider(final FieldGNSSClockElements<T> gnssClk,
  58.                                          final double cycleDuration) {
  59.         this.gnssClk       = gnssClk;
  60.         this.clockRef      = gnssClk.getDate();
  61.         this.cycleDuration = cycleDuration;
  62.     }

  63.     /** {@inheritDoc} */
  64.     @Override
  65.     public String getName() {
  66.         return ClockCorrectionsProvider.CLOCK_CORRECTIONS;
  67.     }

  68.     /**
  69.      * Get the duration from clock Reference epoch.
  70.      * <p>This takes the GNSS week roll-over into account.</p>
  71.      *
  72.      * @param date the considered date
  73.      * @return the duration from clock Reference epoch (s)
  74.      */
  75.     private T getDT(final FieldAbsoluteDate<T> date) {
  76.         // Time from ephemeris reference epoch
  77.         T dt = date.durationFrom(clockRef);
  78.         // Adjusts the time to take roll over week into account
  79.         while (dt.getReal() > 0.5 * cycleDuration) {
  80.             dt = dt.subtract(cycleDuration);
  81.         }
  82.         while (dt.getReal() < -0.5 * cycleDuration) {
  83.             dt = dt.add(cycleDuration);
  84.         }
  85.         // Returns the time from ephemeris reference epoch
  86.         return dt;
  87.     }

  88.     /** {@inheritDoc} */
  89.     @Override
  90.     public T[] getAdditionalData(final FieldSpacecraftState<T> state) {

  91.         // polynomial clock model
  92.         final T  dt    = getDT(state.getDate());
  93.         final T  dtSat = gnssClk.getAf0().add(dt.multiply(gnssClk.getAf1().add(dt.multiply(gnssClk.getAf2()))));

  94.         // relativistic effect due to eccentricity
  95.         final FieldPVCoordinates<T> pv    = state.getPVCoordinates();
  96.         final T                     dtRel = FieldVector3D.dotProduct(pv.getPosition(), pv.getVelocity()).
  97.                                             multiply(-2 / (Constants.SPEED_OF_LIGHT * Constants.SPEED_OF_LIGHT));

  98.         // estimated group delay differential
  99.         final T tg = gnssClk.getTGD();

  100.         final T[] array = MathArrays.buildArray(dt.getField(), 3);
  101.         array[0] = dtSat;
  102.         array[1] = dtRel;
  103.         array[2] = tg;
  104.         return array;
  105.     }

  106. }