1   /* Copyright 2002-2024 CS GROUP
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  
19  import java.util.Arrays;
20  
21  import org.hipparchus.analysis.differentiation.Gradient;
22  import org.orekit.estimation.measurements.EstimatedMeasurement;
23  import org.orekit.estimation.measurements.EstimatedMeasurementBase;
24  import org.orekit.estimation.measurements.ObservableSatellite;
25  import org.orekit.propagation.SpacecraftState;
26  import org.orekit.time.AbsoluteDate;
27  import org.orekit.utils.Constants;
28  import org.orekit.utils.ParameterDriver;
29  import org.orekit.utils.TimeSpanMap.Span;
30  import org.orekit.utils.TimeStampedPVCoordinates;
31  
32  /** Phase measurement between two satellites.
33   * <p>
34   * The measurement is considered to be a signal emitted from
35   * a remote satellite and received by a local satellite.
36   * Its value is the number of cycles between emission and reception.
37   * The motion of both spacecraft during the signal flight time
38   * are taken into account. The date of the measurement corresponds to the
39   * reception on ground of the emitted signal.
40   * </p>
41   * @author Bryan Cazabonne
42   * @since 10.3
43   */
44  public class InterSatellitesPhase extends AbstractInterSatellitesMeasurement<InterSatellitesPhase> {
45  
46      /** Type of the measurement. */
47      public static final String MEASUREMENT_TYPE = "InterSatellitesPhase";
48  
49      /** Name for ambiguity driver.
50       * @deprecated as of 12.1 not used anymore
51       */
52      @Deprecated
53      public static final String AMBIGUITY_NAME = "ambiguity";
54  
55      /** Driver for ambiguity. */
56      private final AmbiguityDriver ambiguityDriver;
57  
58      /** Wavelength of the phase observed value [m]. */
59      private final double wavelength;
60  
61      /** Constructor.
62       * @param local satellite which receives the signal and performs the measurement
63       * @param remote remote satellite which simply emits the signal
64       * @param date date of the measurement
65       * @param phase observed value (cycles)
66       * @param wavelength phase observed value wavelength (m)
67       * @param sigma theoretical standard deviation
68       * @param baseWeight base weight
69       * @deprecated as of 12.1, replaced by {@link #InterSatellitesPhase(ObservableSatellite,
70       * ObservableSatellite, AbsoluteDate, double, double, double, double,
71       * AmbiguityCache)}
72       */
73      @Deprecated
74      public InterSatellitesPhase(final ObservableSatellite local,
75                                  final ObservableSatellite remote,
76                                  final AbsoluteDate date, final double phase,
77                                  final double wavelength, final double sigma,
78                                  final double baseWeight) {
79          this(local, remote, date, phase, wavelength, sigma, baseWeight,
80               AmbiguityCache.DEFAULT_CACHE);
81      }
82  
83      /** Constructor.
84       * @param local satellite which receives the signal and performs the measurement
85       * @param remote remote satellite which simply emits the signal
86       * @param date date of the measurement
87       * @param phase observed value (cycles)
88       * @param wavelength phase observed value wavelength (m)
89       * @param sigma theoretical standard deviation
90       * @param baseWeight base weight
91       * @param cache from which ambiguity drive should come
92       * @since 12.1
93       */
94      public InterSatellitesPhase(final ObservableSatellite local,
95                                  final ObservableSatellite remote,
96                                  final AbsoluteDate date, final double phase,
97                                  final double wavelength, final double sigma,
98                                  final double baseWeight,
99                                  final AmbiguityCache cache) {
100         // Call to super constructor
101         super(date, phase, sigma, baseWeight, local, remote);
102 
103         // Initialize phase ambiguity driver
104         ambiguityDriver = cache.getAmbiguity(remote.getName(), local.getName(), wavelength);
105 
106         // Add parameter drivers
107         addParameterDriver(ambiguityDriver);
108 
109         // Initialize fields
110         this.wavelength = wavelength;
111     }
112 
113     /** Get the wavelength.
114      * @return wavelength (m)
115      */
116     public double getWavelength() {
117         return wavelength;
118     }
119 
120     /** Get the driver for phase ambiguity.
121      * @return the driver for phase ambiguity
122      */
123     public ParameterDriver getAmbiguityDriver() {
124         return ambiguityDriver;
125     }
126 
127     /** {@inheritDoc} */
128     @Override
129     protected EstimatedMeasurementBase<InterSatellitesPhase> theoreticalEvaluationWithoutDerivatives(final int iteration,
130                                                                                                      final int evaluation,
131                                                                                                      final SpacecraftState[] states) {
132 
133         final OnBoardCommonParametersWithoutDerivatives common = computeCommonParametersWithout(states, false);
134 
135         // prepare the evaluation
136         final EstimatedMeasurementBase<InterSatellitesPhase> estimatedPhase =
137                         new EstimatedMeasurementBase<>(this, iteration, evaluation,
138                                                        new SpacecraftState[] {
139                                                            common.getState(),
140                                                            states[1]
141                                                        }, new TimeStampedPVCoordinates[] {
142                                                            common.getRemotePV(),
143                                                            common.getTransitPV()
144                                                        });
145 
146         // Phase value
147         final double cOverLambda = Constants.SPEED_OF_LIGHT / wavelength;
148         final double ambiguity   = ambiguityDriver.getValue(common.getState().getDate());
149         final double phase       = (common.getTauD() + common.getLocalOffset() - common.getRemoteOffset()) * cOverLambda +
150                                    ambiguity;
151 
152         estimatedPhase.setEstimatedValue(phase);
153 
154         // Return the estimated measurement
155         return estimatedPhase;
156 
157     }
158 
159     /** {@inheritDoc} */
160     @Override
161     protected EstimatedMeasurement<InterSatellitesPhase> theoreticalEvaluation(final int iteration,
162                                                                                final int evaluation,
163                                                                                final SpacecraftState[] states) {
164 
165         final OnBoardCommonParametersWithDerivatives common = computeCommonParametersWith(states, false);
166 
167        // prepare the evaluation
168         final EstimatedMeasurement<InterSatellitesPhase> estimatedPhase =
169                         new EstimatedMeasurement<>(this, iteration, evaluation,
170                                                    new SpacecraftState[] {
171                                                        common.getState(),
172                                                        states[1]
173                                                    }, new TimeStampedPVCoordinates[] {
174                                                        common.getRemotePV().toTimeStampedPVCoordinates(),
175                                                        common.getTransitPV().toTimeStampedPVCoordinates()
176                                                    });
177 
178         // Phase value
179         final double   cOverLambda = Constants.SPEED_OF_LIGHT / wavelength;
180         final Gradient ambiguity   = ambiguityDriver.getValue(common.getTauD().getFreeParameters(), common.getIndices(),
181                                                               common.getState().getDate());
182         final Gradient phase       = common.getTauD().add(common.getLocalOffset()).subtract(common.getRemoteOffset()).
183                                      multiply(cOverLambda).
184                                      add(ambiguity);
185 
186         estimatedPhase.setEstimatedValue(phase.getValue());
187 
188         // Range first order derivatives with respect to states
189         final double[] derivatives = phase.getGradient();
190         estimatedPhase.setStateDerivatives(0, Arrays.copyOfRange(derivatives, 0,  6));
191         estimatedPhase.setStateDerivatives(1, Arrays.copyOfRange(derivatives, 6, 12));
192 
193         // Set first order derivatives with respect to parameters
194         for (final ParameterDriver driver : getParametersDrivers()) {
195             for (Span<String> span = driver.getNamesSpanMap().getFirstSpan(); span != null; span = span.next()) {
196 
197                 final Integer index = common.getIndices().get(span.getData());
198                 if (index != null) {
199                     estimatedPhase.setParameterDerivatives(driver, span.getStart(), derivatives[index]);
200                 }
201             }
202         }
203 
204         // Return the estimated measurement
205         return estimatedPhase;
206 
207     }
208 
209 }