InterSatellitesRange.java

  1. /* Copyright 2002-2018 CS Systèmes d'Information
  2.  * Licensed to CS Systèmes d'Information (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;

  18. import java.util.Arrays;

  19. import org.hipparchus.Field;
  20. import org.hipparchus.analysis.differentiation.DSFactory;
  21. import org.hipparchus.analysis.differentiation.DerivativeStructure;
  22. import org.orekit.errors.OrekitException;
  23. import org.orekit.propagation.SpacecraftState;
  24. import org.orekit.time.AbsoluteDate;
  25. import org.orekit.time.FieldAbsoluteDate;
  26. import org.orekit.utils.Constants;
  27. import org.orekit.utils.TimeStampedFieldPVCoordinates;
  28. import org.orekit.utils.TimeStampedPVCoordinates;

  29. /** One-way or two-way range measurements between two satellites.
  30.  * <p>
  31.  * Satellite 1 is always considered to be the satellite that receives the
  32.  * signal and computes the measurement.
  33.  * </p>
  34.  * <p>
  35.  * For one-way measurements, a signal is emitted by satellite 2 and received
  36.  * by satellite 1. The measurement value is the elapsed time between emission
  37.  * and reception divided by c were c is the speed of light.
  38.  * </p>
  39.  * <p>
  40.  * For two-way measurements, a signal is emitted by satellite 1, reflected on
  41.  * satellite 2, and received back by satellite 1 again. The measurement value
  42.  * is the elapsed time between emission and reception divided by 2c were c is
  43.  * the speed of light.
  44.  * </p>
  45.  * <p>
  46.  * The motion of both satellites during the signal flight time is
  47.  * taken into account. The date of the measurement corresponds to
  48.  * the reception of the signal by satellite 1.
  49.  * </p>
  50.  * @author Luc Maisonobe
  51.  * @since 9.0
  52.  */
  53. public class InterSatellitesRange extends AbstractMeasurement<InterSatellitesRange> {

  54.     /** Flag indicating whether it is a two-way measurement. */
  55.     private final boolean twoway;

  56.     /** Simple constructor.
  57.      * @param satellite1Index index of satellite 1 propagator
  58.      * (i.e. the satellite which receives the signal and performs
  59.      * the measurement)
  60.      * @param satellite2Index index of satellite 2 propagator
  61.      * (i.e. the satellite which simply emits the signal in the one-way
  62.      * case, or reflects the signal in the two-way case)
  63.      * @param twoWay flag indicating whether it is a two-way measurement
  64.      * @param date date of the measurement
  65.      * @param range observed value
  66.      * @param sigma theoretical standard deviation
  67.      * @param baseWeight base weight
  68.      * @exception OrekitException if a {@link org.orekit.utils.ParameterDriver}
  69.      * name conflict occurs
  70.      */
  71.     public InterSatellitesRange(final int satellite1Index, final int satellite2Index,
  72.                                 final boolean twoWay,
  73.                                 final AbsoluteDate date, final double range,
  74.                                 final double sigma, final double baseWeight)
  75.         throws OrekitException {
  76.         super(date, range, sigma, baseWeight, Arrays.asList(satellite1Index, satellite2Index));
  77.         this.twoway = twoWay;
  78.     }

  79.     /** Check if the instance represents a two-way measurement.
  80.      * @return true if the instance represents a two-way measurement
  81.      */
  82.     public boolean isTwoWay() {
  83.         return twoway;
  84.     }

  85.     /** {@inheritDoc} */
  86.     @Override
  87.     protected EstimatedMeasurement<InterSatellitesRange> theoreticalEvaluation(final int iteration,
  88.                                                                                final int evaluation,
  89.                                                                                final SpacecraftState[] states)
  90.         throws OrekitException {

  91.         // Range derivatives are computed with respect to spacecrafts states in inertial frame
  92.         // ----------------------
  93.         //
  94.         // Parameters:
  95.         //  - 0..2  - Position of the satellite 1 in inertial frame
  96.         //  - 3..5  - Velocity of the satellite 1 in inertial frame
  97.         //  - 6..8  - Position of the satellite 2 in inertial frame
  98.         //  - 9..11 - Velocity of the satellite 2 in inertial frame
  99.         final int nbParams = 12;
  100.         final DSFactory                          factory = new DSFactory(nbParams, 1);
  101.         final Field<DerivativeStructure>         field   = factory.getDerivativeField();

  102.         // coordinates of both satellites
  103.         final SpacecraftState state1 = states[getPropagatorsIndices().get(0)];
  104.         final TimeStampedFieldPVCoordinates<DerivativeStructure> pva1 = getCoordinates(state1, 0, factory);
  105.         final SpacecraftState state2 = states[getPropagatorsIndices().get(1)];
  106.         final TimeStampedFieldPVCoordinates<DerivativeStructure> pva2 = getCoordinates(state2, 6, factory);

  107.         // compute propagation times
  108.         // (if state has already been set up to pre-compensate propagation delay,
  109.         //  we will have delta == tauD and transitState will be the same as state)

  110.         // downlink delay
  111.         final FieldAbsoluteDate<DerivativeStructure> arrivalDate = new FieldAbsoluteDate<>(field, getDate());
  112.         final TimeStampedFieldPVCoordinates<DerivativeStructure> s1Downlink =
  113.                         pva1.shiftedBy(arrivalDate.durationFrom(pva1.getDate()));
  114.         final DerivativeStructure tauD = signalTimeOfFlight(pva2, s1Downlink.getPosition(), arrivalDate);

  115.         // Transit state
  116.         final double              delta      = getDate().durationFrom(state2.getDate());
  117.         final DerivativeStructure deltaMTauD = tauD.negate().add(delta);

  118.         // prepare the evaluation
  119.         final EstimatedMeasurement<InterSatellitesRange> estimated;

  120.         final DerivativeStructure range;
  121.         if (twoway) {
  122.             // Transit state (re)computed with derivative structures
  123.             final TimeStampedFieldPVCoordinates<DerivativeStructure> transitStateDS = pva2.shiftedBy(deltaMTauD);

  124.             // uplink delay
  125.             final DerivativeStructure tauU = signalTimeOfFlight(pva1,
  126.                                                                 transitStateDS.getPosition(),
  127.                                                                 transitStateDS.getDate());
  128.             estimated = new EstimatedMeasurement<>(this, iteration, evaluation,
  129.                                                    new SpacecraftState[] {
  130.                                                        state1.shiftedBy(deltaMTauD.getValue()),
  131.                                                        state2.shiftedBy(deltaMTauD.getValue())
  132.                                                    }, new TimeStampedPVCoordinates[] {
  133.                                                        state1.shiftedBy(delta - tauD.getValue() - tauU.getValue()).getPVCoordinates(),
  134.                                                        state2.shiftedBy(delta - tauD.getValue()).getPVCoordinates(),
  135.                                                        state1.shiftedBy(delta).getPVCoordinates()
  136.                                                    });

  137.             // Range value
  138.             range  = tauD.add(tauU).multiply(0.5 * Constants.SPEED_OF_LIGHT);

  139.         } else {

  140.             estimated = new EstimatedMeasurement<>(this, iteration, evaluation,
  141.                                                    new SpacecraftState[] {
  142.                                                        state1.shiftedBy(deltaMTauD.getValue()),
  143.                                                        state2.shiftedBy(deltaMTauD.getValue())
  144.                                                    }, new TimeStampedPVCoordinates[] {
  145.                                                        state2.shiftedBy(delta - tauD.getValue()).getPVCoordinates(),
  146.                                                        state1.shiftedBy(delta).getPVCoordinates()
  147.                                                    });

  148.             // Range value
  149.             range  = tauD.multiply(Constants.SPEED_OF_LIGHT);

  150.         }
  151.         estimated.setEstimatedValue(range.getValue());

  152.         // Range partial derivatives with respect to states
  153.         final double[] derivatives = range.getAllDerivatives();
  154.         estimated.setStateDerivatives(0, Arrays.copyOfRange(derivatives, 1,  7));
  155.         estimated.setStateDerivatives(1, Arrays.copyOfRange(derivatives, 7, 13));

  156.         return estimated;

  157.     }

  158. }