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 }