InterSatellitesRange.java
- /* Copyright 2002-2019 CS Systèmes d'Information
- * Licensed to CS Systèmes d'Information (CS) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * CS licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package org.orekit.estimation.measurements;
- import java.util.Arrays;
- import java.util.HashMap;
- import java.util.Map;
- import org.hipparchus.analysis.differentiation.DSFactory;
- import org.hipparchus.analysis.differentiation.DerivativeStructure;
- import org.orekit.propagation.SpacecraftState;
- import org.orekit.time.AbsoluteDate;
- import org.orekit.time.FieldAbsoluteDate;
- import org.orekit.utils.Constants;
- import org.orekit.utils.ParameterDriver;
- import org.orekit.utils.TimeStampedFieldPVCoordinates;
- import org.orekit.utils.TimeStampedPVCoordinates;
- /** One-way or two-way range measurements between two satellites.
- * <p>
- * For one-way measurements, a signal is emitted by a remote satellite and received
- * by local satellite. The measurement value is the elapsed time between emission
- * and reception multiplied by c where c is the speed of light.
- * </p>
- * <p>
- * For two-way measurements, a signal is emitted by local satellite, reflected on
- * remote satellite, and received back by local satellite. The measurement value
- * is the elapsed time between emission and reception multiplied by c/2 where c
- * is the speed of light.
- * </p>
- * <p>
- * Since 9.3, this class also uses the clock offsets of both satellites,
- * which manage the value that must be added to each satellite reading of time to
- * compute the real physical date. In this measurement, these offsets have two effects:
- * </p>
- * <ul>
- * <li>as measurement date is evaluated at reception time, the real physical date
- * of the measurement is the observed date to which the local satellite clock
- * offset is subtracted</li>
- * <li>as range is evaluated using the total signal time of flight, for one-way
- * measurements the observed range is the real physical signal time of flight to
- * which (Δtl - Δtr) ⨉ c is added, where Δtl (resp. Δtr) is the clock offset for the
- * local satellite (resp. remote satellite). A similar effect exists in
- * two-way measurements but it is computed as (Δtl - Δtl) ⨉ c / 2 as the local satellite
- * clock is used for both initial emission and final reception and therefore it evaluates
- * to zero.</li>
- * </ul>
- * <p>
- * The motion of both satellites during the signal flight time is
- * taken into account. The date of the measurement corresponds to
- * the reception of the signal by satellite 1.
- * </p>
- * @author Luc Maisonobe
- * @since 9.0
- */
- public class InterSatellitesRange extends AbstractMeasurement<InterSatellitesRange> {
- /** Flag indicating whether it is a two-way measurement. */
- private final boolean twoway;
- /** Simple constructor.
- * @param localIndex index of local satellite propagator
- * (i.e. the satellite which receives the signal and performs
- * the measurement)
- * @param remoteIndex index of remote satellite propagator
- * (i.e. the satellite which simply emits the signal in the one-way
- * case, or reflects the signal in the two-way case)
- * @param twoWay flag indicating whether it is a two-way measurement
- * @param date date of the measurement
- * @param range observed value
- * @param sigma theoretical standard deviation
- * @param baseWeight base weight
- * @deprecated as of 9.3, replaced by {@link #InterSatellitesRange(ObservableSatellite, ObservableSatellite,
- * boolean, AbsoluteDate, double, double, double)}
- */
- @Deprecated
- public InterSatellitesRange(final int localIndex, final int remoteIndex,
- final boolean twoWay,
- final AbsoluteDate date, final double range,
- final double sigma, final double baseWeight) {
- this(new ObservableSatellite(localIndex), new ObservableSatellite(remoteIndex),
- twoWay, date, range, sigma, baseWeight);
- }
- /** Simple constructor.
- * @param local satellite which receives the signal and performs the measurement
- * @param remote satellite which simply emits the signal in the one-way case,
- * or reflects the signal in the two-way case
- * @param twoWay flag indicating whether it is a two-way measurement
- * @param date date of the measurement
- * @param range observed value
- * @param sigma theoretical standard deviation
- * @param baseWeight base weight
- * @since 9.3
- */
- public InterSatellitesRange(final ObservableSatellite local,
- final ObservableSatellite remote,
- final boolean twoWay,
- final AbsoluteDate date, final double range,
- final double sigma, final double baseWeight) {
- super(date, range, sigma, baseWeight, Arrays.asList(local, remote));
- this.twoway = twoWay;
- }
- /** Check if the instance represents a two-way measurement.
- * @return true if the instance represents a two-way measurement
- */
- public boolean isTwoWay() {
- return twoway;
- }
- /** {@inheritDoc} */
- @Override
- protected EstimatedMeasurement<InterSatellitesRange> theoreticalEvaluation(final int iteration,
- final int evaluation,
- final SpacecraftState[] states) {
- // Range derivatives are computed with respect to spacecrafts states in inertial frame
- // ----------------------
- //
- // Parameters:
- // - 0..2 - Position of the receiver satellite in inertial frame
- // - 3..5 - Velocity of the receiver satellite in inertial frame
- // - 6..8 - Position of the remote satellite in inertial frame
- // - 9..11 - Velocity of the remote satellite in inertial frame
- // - 12.. - Measurement parameters: local clock offset, remote clock offset...
- int nbParams = 12;
- final Map<String, Integer> indices = new HashMap<>();
- for (ParameterDriver driver : getParametersDrivers()) {
- if (driver.isSelected()) {
- indices.put(driver.getName(), nbParams++);
- }
- }
- final DSFactory factory = new DSFactory(nbParams, 1);
- // coordinates of both satellites
- final ObservableSatellite local = getSatellites().get(0);
- final SpacecraftState stateL = states[local.getPropagatorIndex()];
- final TimeStampedFieldPVCoordinates<DerivativeStructure> pvaL = getCoordinates(stateL, 0, factory);
- final ObservableSatellite remote = getSatellites().get(1);
- final SpacecraftState stateR = states[remote.getPropagatorIndex()];
- final TimeStampedFieldPVCoordinates<DerivativeStructure> pvaR = getCoordinates(stateR, 6, factory);
- // compute propagation times
- // (if state has already been set up to pre-compensate propagation delay,
- // we will have delta == tauD and transitState will be the same as state)
- // downlink delay
- final DerivativeStructure dtl = local.getClockOffsetDriver().getValue(factory, indices);
- final FieldAbsoluteDate<DerivativeStructure> arrivalDate =
- new FieldAbsoluteDate<DerivativeStructure>(getDate(), dtl.negate());
- final TimeStampedFieldPVCoordinates<DerivativeStructure> s1Downlink =
- pvaL.shiftedBy(arrivalDate.durationFrom(pvaL.getDate()));
- final DerivativeStructure tauD = signalTimeOfFlight(pvaR, s1Downlink.getPosition(), arrivalDate);
- // Transit state
- final double delta = getDate().durationFrom(stateR.getDate());
- final DerivativeStructure deltaMTauD = tauD.negate().add(delta);
- // prepare the evaluation
- final EstimatedMeasurement<InterSatellitesRange> estimated;
- final DerivativeStructure range;
- if (twoway) {
- // Transit state (re)computed with derivative structures
- final TimeStampedFieldPVCoordinates<DerivativeStructure> transitStateDS = pvaR.shiftedBy(deltaMTauD);
- // uplink delay
- final DerivativeStructure tauU = signalTimeOfFlight(pvaL,
- transitStateDS.getPosition(),
- transitStateDS.getDate());
- estimated = new EstimatedMeasurement<>(this, iteration, evaluation,
- new SpacecraftState[] {
- stateL.shiftedBy(deltaMTauD.getValue()),
- stateR.shiftedBy(deltaMTauD.getValue())
- }, new TimeStampedPVCoordinates[] {
- stateL.shiftedBy(delta - tauD.getValue() - tauU.getValue()).getPVCoordinates(),
- stateR.shiftedBy(delta - tauD.getValue()).getPVCoordinates(),
- stateL.shiftedBy(delta).getPVCoordinates()
- });
- // Range value
- range = tauD.add(tauU).multiply(0.5 * Constants.SPEED_OF_LIGHT);
- } else {
- estimated = new EstimatedMeasurement<>(this, iteration, evaluation,
- new SpacecraftState[] {
- stateL.shiftedBy(deltaMTauD.getValue()),
- stateR.shiftedBy(deltaMTauD.getValue())
- }, new TimeStampedPVCoordinates[] {
- stateR.shiftedBy(delta - tauD.getValue()).getPVCoordinates(),
- stateL.shiftedBy(delta).getPVCoordinates()
- });
- // Clock offsets
- final DerivativeStructure dtr = remote.getClockOffsetDriver().getValue(factory, indices);
- // Range value
- range = tauD.add(dtl).subtract(dtr).multiply(Constants.SPEED_OF_LIGHT);
- }
- estimated.setEstimatedValue(range.getValue());
- // Range partial derivatives with respect to states
- final double[] derivatives = range.getAllDerivatives();
- estimated.setStateDerivatives(0, Arrays.copyOfRange(derivatives, 1, 7));
- estimated.setStateDerivatives(1, Arrays.copyOfRange(derivatives, 7, 13));
- return estimated;
- }
- }