AbstractOnBoardMeasurement.java

  1. /* Copyright 2002-2024 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 org.hipparchus.analysis.differentiation.Gradient;
  19. import org.hipparchus.analysis.differentiation.GradientField;
  20. import org.orekit.estimation.measurements.AbstractMeasurement;
  21. import org.orekit.estimation.measurements.ObservableSatellite;
  22. import org.orekit.estimation.measurements.ObservedMeasurement;
  23. import org.orekit.estimation.measurements.QuadraticClockModel;
  24. import org.orekit.estimation.measurements.QuadraticFieldClockModel;
  25. import org.orekit.propagation.SpacecraftState;
  26. import org.orekit.time.AbsoluteDate;
  27. import org.orekit.time.ClockOffset;
  28. import org.orekit.time.FieldAbsoluteDate;
  29. import org.orekit.time.FieldClockOffset;
  30. import org.orekit.utils.FieldPVCoordinatesProvider;
  31. import org.orekit.utils.PVCoordinatesProvider;
  32. import org.orekit.utils.ParameterDriver;
  33. import org.orekit.utils.TimeSpanMap.Span;
  34. import org.orekit.utils.TimeStampedFieldPVCoordinates;
  35. import org.orekit.utils.TimeStampedPVCoordinates;

  36. import java.util.HashMap;
  37. import java.util.List;
  38. import java.util.Map;

  39. /** Base class modeling a measurement where receiver is a satellite.
  40.  * @param <T> type of the measurement
  41.  * @author Luc Maisonobe
  42.  * @since 12.1
  43.  */
  44. public abstract class AbstractOnBoardMeasurement<T extends ObservedMeasurement<T>> extends AbstractMeasurement<T> {

  45.     /** Constructor.
  46.      * @param date date of the measurement
  47.      * @param observed observed value
  48.      * @param sigma theoretical standard deviation
  49.      * @param baseWeight base weight
  50.      * @param satellites satellites related to this measurement
  51.      */
  52.     public AbstractOnBoardMeasurement(final AbsoluteDate date, final double observed,
  53.                                       final double sigma, final double baseWeight,
  54.                                       final List<ObservableSatellite> satellites) {
  55.         // Call to super constructor
  56.         super(date, observed, sigma, baseWeight, satellites);

  57.         // Add parameter drivers
  58.         satellites.forEach(s -> {
  59.             addParameterDriver(s.getClockOffsetDriver());
  60.             addParameterDriver(s.getClockDriftDriver());
  61.             addParameterDriver(s.getClockAccelerationDriver());
  62.         });

  63.     }

  64.     /** Get emitting satellite clock provider.
  65.      * @return emitting satellite clock provider
  66.      */
  67.     protected abstract QuadraticClockModel getRemoteClock();

  68.     /** Get emitting satellite position/velocity provider.
  69.      * @param states states of all spacecraft involved in the measurement
  70.      * @return emitting satellite position/velocity provider
  71.      */
  72.     protected abstract PVCoordinatesProvider getRemotePV(SpacecraftState[] states);

  73.     /** Get emitting satellite position/velocity provider.
  74.      * @param states states of all spacecraft involved in the measurement
  75.      * @param freeParameters total number of free parameters in the gradient
  76.      * @return emitting satellite position/velocity provider
  77.      */
  78.     protected abstract FieldPVCoordinatesProvider<Gradient> getRemotePV(SpacecraftState[] states,
  79.                                                                         int freeParameters);

  80.     /** Get emitting satellite clock provider.
  81.      * @param freeParameters total number of free parameters in the gradient
  82.      * @param indices indices of the differentiation parameters in derivatives computations,
  83.      * must be span name and not driver name
  84.      * @return emitting satellite clock provider
  85.      */
  86.     protected QuadraticFieldClockModel<Gradient> getRemoteClock(final int freeParameters,
  87.                                                                 final Map<String, Integer> indices) {
  88.         return getRemoteClock().toGradientModel(freeParameters, indices, getDate());
  89.     }

  90.     /** Compute common estimation parameters.
  91.      * @param states states of all spacecraft involved in the measurement
  92.      * @param clockOffsetAlreadyApplied if true, the specified {@code date} is as read
  93.      * by the receiver clock (i.e. clock offset <em>not</em> compensated), if false,
  94.      * the specified {@code date} was already compensated and is a physical absolute date
  95.      * @return common parameters
  96.      */
  97.     protected OnBoardCommonParametersWithoutDerivatives computeCommonParametersWithout(final SpacecraftState[] states,
  98.                                                                                        final boolean clockOffsetAlreadyApplied) {

  99.         // local and remote satellites
  100.         final TimeStampedPVCoordinates pvaLocal         = states[0].getPVCoordinates();
  101.         final ClockOffset              localClock       = getSatellites().
  102.                                                           get(0).
  103.                                                           getQuadraticClockModel().
  104.             getOffset(getDate());
  105.         final double                   localClockOffset = localClock.getOffset();
  106.         final double                   localClockRate   = localClock.getRate();
  107.         final PVCoordinatesProvider    remotePV         = getRemotePV(states);

  108.         // take clock offset into account
  109.         final AbsoluteDate arrivalDate = clockOffsetAlreadyApplied ? getDate() : getDate().shiftedBy(-localClockOffset);

  110.         // Downlink delay
  111.         final double deltaT = arrivalDate.durationFrom(states[0]);
  112.         final TimeStampedPVCoordinates pvaDownlink = pvaLocal.shiftedBy(deltaT);
  113.         final double tauD = signalTimeOfFlight(remotePV, arrivalDate, pvaDownlink.getPosition(),
  114.                                                arrivalDate, states[0].getFrame());

  115.         // Remote satellite at signal emission
  116.         final AbsoluteDate        emissionDate      = arrivalDate.shiftedBy(-tauD);
  117.         final ClockOffset         remoteClock       = getRemoteClock().getOffset(emissionDate);
  118.         final double              remoteClockOffset = remoteClock.getOffset();
  119.         final double              remoteClockRate   = remoteClock.getRate();
  120.         return new OnBoardCommonParametersWithoutDerivatives(states[0],
  121.                                                              localClockOffset, localClockRate,
  122.                                                              remoteClockOffset, remoteClockRate,
  123.                                                              tauD, pvaDownlink,
  124.                                                              remotePV.getPVCoordinates(emissionDate, states[0].getFrame()));

  125.     }

  126.     /** Compute common estimation parameters.
  127.      * @param states states of all spacecraft involved in the measurement
  128.      * @param clockOffsetAlreadyApplied if true, the specified {@code date} is as read
  129.      * by the receiver clock (i.e. clock offset <em>not</em> compensated), if false,
  130.      * the specified {@code date} was already compensated and is a physical absolute date
  131.      * @return common parameters
  132.      */
  133.     protected OnBoardCommonParametersWithDerivatives computeCommonParametersWith(final SpacecraftState[] states,
  134.                                                                                  final boolean clockOffsetAlreadyApplied) {

  135.         // measurement derivatives are computed with respect to spacecraft state in inertial frame
  136.         // Parameters:
  137.         //  - 6k..6k+2 - Position of spacecraft k (counting k from 0 to nbSat-1) in inertial frame
  138.         //  - 6k+3..6k+5 - Velocity of spacecraft k (counting k from 0 to nbSat-1) in inertial frame
  139.         //  - 6nbSat..n - measurements parameters (clock offset, etc)
  140.         int nbEstimatedParams = 6 * states.length;
  141.         final Map<String, Integer> parameterIndices = new HashMap<>();
  142.         for (ParameterDriver measurementDriver : getParametersDrivers()) {
  143.             if (measurementDriver.isSelected()) {
  144.                 for (Span<String> span = measurementDriver.getNamesSpanMap().getFirstSpan(); span != null; span = span.next()) {
  145.                     parameterIndices.put(span.getData(), nbEstimatedParams++);
  146.                 }
  147.             }
  148.         }
  149.         final FieldAbsoluteDate<Gradient> gDate = new FieldAbsoluteDate<>(GradientField.getField(nbEstimatedParams),
  150.                                                                           getDate());

  151.         // local and remote satellites
  152.         final TimeStampedFieldPVCoordinates<Gradient> pvaLocal         = getCoordinates(states[0], 0, nbEstimatedParams);
  153.         final QuadraticFieldClockModel<Gradient>      localClock       = getSatellites().get(0).getQuadraticClockModel().
  154.                                                                          toGradientModel(nbEstimatedParams, parameterIndices, getDate());
  155.         final FieldClockOffset<Gradient>              localClockOffset = localClock.getOffset(gDate);
  156.         final FieldPVCoordinatesProvider<Gradient>    remotePV         = getRemotePV(states, nbEstimatedParams);

  157.         // take clock offset into account
  158.         final FieldAbsoluteDate<Gradient> arrivalDate = clockOffsetAlreadyApplied ?
  159.                                                         gDate : gDate.shiftedBy(localClockOffset.getOffset().negate());

  160.         // Downlink delay
  161.         final Gradient deltaT = arrivalDate.durationFrom(states[0].getDate());
  162.         final TimeStampedFieldPVCoordinates<Gradient> pvaDownlink = pvaLocal.shiftedBy(deltaT);
  163.         final Gradient tauD = signalTimeOfFlight(remotePV, arrivalDate,
  164.                                                  pvaDownlink.getPosition(), arrivalDate,
  165.                                                  states[0].getFrame());

  166.         // Remote satellite at signal emission
  167.         final FieldAbsoluteDate<Gradient>        emissionDate      = arrivalDate.shiftedBy(tauD.negate());
  168.         final QuadraticFieldClockModel<Gradient> remoteClock       = getRemoteClock(nbEstimatedParams, parameterIndices);
  169.         final FieldClockOffset<Gradient>         remoteClockOffset = remoteClock.getOffset(emissionDate);
  170.         return new OnBoardCommonParametersWithDerivatives(states[0], parameterIndices,
  171.                                                           localClockOffset.getOffset(), localClockOffset.getRate(),
  172.                                                           remoteClockOffset.getOffset(), remoteClockOffset.getRate(),
  173.                                                           tauD, pvaDownlink,
  174.                                                           remotePV.getPVCoordinates(emissionDate, states[0].getFrame()));

  175.     }

  176. }