AbstractOneWayGNSSMeasurement.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.estimation.measurements.gnss;

  18. import java.util.Collections;

  19. import org.hipparchus.analysis.differentiation.Gradient;
  20. import org.orekit.estimation.measurements.ObservableSatellite;
  21. import org.orekit.estimation.measurements.ObservedMeasurement;
  22. import org.orekit.estimation.measurements.QuadraticClockModel;
  23. import org.orekit.propagation.SpacecraftState;
  24. import org.orekit.time.AbsoluteDate;
  25. import org.orekit.utils.FieldPVCoordinatesProvider;
  26. import org.orekit.utils.PVCoordinatesProvider;
  27. import org.orekit.utils.TimeStampedFieldPVCoordinates;
  28. import org.orekit.utils.TimeStampedPVCoordinates;

  29. /** Base class for one-way GNSS measurement.
  30.  * <p>
  31.  * This class can be used in precise orbit determination applications
  32.  * for modeling a range measurement between a GNSS satellite (emitter)
  33.  * and a LEO satellite (receiver).
  34.  * </p>
  35.  * <p>
  36.  * The one-way GNSS range measurement assumes knowledge of the orbit and
  37.  * the clock offset of the emitting GNSS satellite. For instance, it is
  38.  * possible to use a SP3 file or a GNSS navigation message to recover
  39.  * the satellite's orbit and clock.
  40.  * </p>
  41.  * <p>
  42.  * This class is very similar to {@link AbstractInterSatellitesMeasurement} measurement
  43.  * class. However, using the one-way GNSS range measurement, the orbit and clock
  44.  * of the emitting GNSS satellite are <b>NOT</b> estimated simultaneously with
  45.  * LEO satellite coordinates.
  46.  * </p>
  47.  *
  48.  * @param <T> type of the measurement
  49.  * @author Luc Maisonobe
  50.  * @since 12.1
  51.  */
  52. public abstract class AbstractOneWayGNSSMeasurement<T extends ObservedMeasurement<T>>
  53.     extends AbstractOnBoardMeasurement<T> {

  54.     /** Emitting satellite. */
  55.     private final PVCoordinatesProvider remotePV;

  56.     /** Clock offset of the emitting satellite. */
  57.     private final QuadraticClockModel remoteClock;

  58.     /** Simple constructor.
  59.      * @param remotePV provider for GNSS satellite which simply emits the signal
  60.      * @param remoteClock clock offset of the GNSS satellite
  61.      * @param date date of the measurement
  62.      * @param range observed value
  63.      * @param sigma theoretical standard deviation
  64.      * @param baseWeight base weight
  65.      * @param local satellite which receives the signal and perform the measurement
  66.      */
  67.     public AbstractOneWayGNSSMeasurement(final PVCoordinatesProvider remotePV,
  68.                                          final QuadraticClockModel remoteClock,
  69.                                          final AbsoluteDate date,
  70.                                          final double range, final double sigma,
  71.                                          final double baseWeight, final ObservableSatellite local) {
  72.         // Call super constructor
  73.         super(date, range, sigma, baseWeight, Collections.singletonList(local));
  74.         // The local satellite clock offset affects the measurement
  75.         addParameterDriver(local.getClockOffsetDriver());
  76.         addParameterDriver(local.getClockDriftDriver());
  77.         addParameterDriver(local.getClockAccelerationDriver());
  78.         // Initialise fields
  79.         this.remotePV    = remotePV;
  80.         this.remoteClock = remoteClock;
  81.     }

  82.     /** {@inheritDoc} */
  83.     @Override
  84.     protected PVCoordinatesProvider getRemotePV(final SpacecraftState[] states) {
  85.         return remotePV;
  86.     }

  87.     /** {@inheritDoc} */
  88.     @Override
  89.     protected QuadraticClockModel getRemoteClock() {
  90.         return remoteClock;
  91.     }

  92.     /** {@inheritDoc} */
  93.     @Override
  94.     protected FieldPVCoordinatesProvider<Gradient> getRemotePV(final SpacecraftState[] states,
  95.                                                                final int freeParameters) {
  96.         // convert the PVCoordinatesProvider to a FieldPVCoordinatesProvider<Gradient>
  97.         return (date, frame) -> {

  98.             // apply the raw (no derivatives) remote provider
  99.             final AbsoluteDate             dateBase = date.toAbsoluteDate();
  100.             final TimeStampedPVCoordinates pvBase   = remotePV.getPVCoordinates(dateBase, frame);
  101.             final TimeStampedFieldPVCoordinates<Gradient> pvWithoutDerivatives =
  102.                 new TimeStampedFieldPVCoordinates<>(date.getField(), pvBase);

  103.             // add derivatives, using a trick: we shift the date by 0, with derivatives
  104.             final Gradient zeroWithDerivatives = date.durationFrom(dateBase);
  105.             return pvWithoutDerivatives.shiftedBy(zeroWithDerivatives);

  106.         };
  107.     }

  108. }