1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.estimation.measurements.gnss;
18
19 import java.util.Arrays;
20 import java.util.Collections;
21 import java.util.HashMap;
22 import java.util.Map;
23
24 import org.hipparchus.analysis.differentiation.Gradient;
25 import org.hipparchus.analysis.differentiation.GradientField;
26 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
27 import org.orekit.estimation.measurements.AbstractMeasurement;
28 import org.orekit.estimation.measurements.EstimatedMeasurement;
29 import org.orekit.estimation.measurements.GroundStation;
30 import org.orekit.estimation.measurements.ObservableSatellite;
31 import org.orekit.frames.FieldTransform;
32 import org.orekit.propagation.SpacecraftState;
33 import org.orekit.time.AbsoluteDate;
34 import org.orekit.time.FieldAbsoluteDate;
35 import org.orekit.utils.Constants;
36 import org.orekit.utils.ParameterDriver;
37 import org.orekit.utils.TimeStampedFieldPVCoordinates;
38 import org.orekit.utils.TimeStampedPVCoordinates;
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55 public class Phase extends AbstractMeasurement<Phase> {
56
57
58 public static final String AMBIGUITY_NAME = "ambiguity";
59
60
61 private final ParameterDriver ambiguityDriver;
62
63
64 private final GroundStation station;
65
66
67 private final double wavelength;
68
69
70
71
72
73
74
75
76
77
78
79 public Phase(final GroundStation station, final AbsoluteDate date,
80 final double phase, final double wavelength, final double sigma,
81 final double baseWeight, final ObservableSatellite satellite) {
82 super(date, phase, sigma, baseWeight, Collections.singletonList(satellite));
83 ambiguityDriver = new ParameterDriver(AMBIGUITY_NAME,
84 0.0, 1.0,
85 Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY);
86 addParameterDriver(ambiguityDriver);
87 addParameterDriver(satellite.getClockOffsetDriver());
88 addParameterDriver(station.getClockOffsetDriver());
89 addParameterDriver(station.getEastOffsetDriver());
90 addParameterDriver(station.getNorthOffsetDriver());
91 addParameterDriver(station.getZenithOffsetDriver());
92 addParameterDriver(station.getPrimeMeridianOffsetDriver());
93 addParameterDriver(station.getPrimeMeridianDriftDriver());
94 addParameterDriver(station.getPolarOffsetXDriver());
95 addParameterDriver(station.getPolarDriftXDriver());
96 addParameterDriver(station.getPolarOffsetYDriver());
97 addParameterDriver(station.getPolarDriftYDriver());
98 this.station = station;
99 this.wavelength = wavelength;
100 }
101
102
103
104
105 public GroundStation getStation() {
106 return station;
107 }
108
109
110
111
112 public double getWavelength() {
113 return wavelength;
114 }
115
116
117
118
119
120 public ParameterDriver getAmbiguityDriver() {
121 return ambiguityDriver;
122 }
123
124
125 @Override
126 protected EstimatedMeasurement<Phase> theoreticalEvaluation(final int iteration,
127 final int evaluation,
128 final SpacecraftState[] states) {
129
130 final SpacecraftState state = states[0];
131
132
133
134
135
136
137
138
139
140 int nbParams = 6;
141 final Map<String, Integer> indices = new HashMap<>();
142 for (ParameterDriver driver : getParametersDrivers()) {
143 if (driver.isSelected()) {
144 indices.put(driver.getName(), nbParams++);
145 }
146 }
147 final FieldVector3D<Gradient> zero = FieldVector3D.getZero(GradientField.getField(nbParams));
148
149
150 final TimeStampedFieldPVCoordinates<Gradient> pvaDS = getCoordinates(state, 0, nbParams);
151
152
153
154 final FieldTransform<Gradient> offsetToInertialDownlink =
155 station.getOffsetToInertial(state.getFrame(), getDate(), nbParams, indices);
156 final FieldAbsoluteDate<Gradient> downlinkDateDS =
157 offsetToInertialDownlink.getFieldDate();
158
159
160 final TimeStampedFieldPVCoordinates<Gradient> stationDownlink =
161 offsetToInertialDownlink.transformPVCoordinates(new TimeStampedFieldPVCoordinates<>(downlinkDateDS,
162 zero, zero, zero));
163
164
165
166
167
168
169 final Gradient tauD = signalTimeOfFlight(pvaDS, stationDownlink.getPosition(), downlinkDateDS);
170
171
172 final Gradient delta = downlinkDateDS.durationFrom(state.getDate());
173 final Gradient deltaMTauD = tauD.negate().add(delta);
174 final SpacecraftState transitState = state.shiftedBy(deltaMTauD.getValue());
175 final TimeStampedFieldPVCoordinates<Gradient> transitStateDS = pvaDS.shiftedBy(deltaMTauD);
176
177
178 final EstimatedMeasurement<Phase> estimated =
179 new EstimatedMeasurement<Phase>(this, iteration, evaluation,
180 new SpacecraftState[] {
181 transitState
182 }, new TimeStampedPVCoordinates[] {
183 transitStateDS.toTimeStampedPVCoordinates(),
184 stationDownlink.toTimeStampedPVCoordinates()
185 });
186
187
188 final ObservableSatellite satellite = getSatellites().get(0);
189 final Gradient dts = satellite.getClockOffsetDriver().getValue(nbParams, indices);
190 final Gradient dtg = station.getClockOffsetDriver().getValue(nbParams, indices);
191
192
193 final double cOverLambda = Constants.SPEED_OF_LIGHT / wavelength;
194 final Gradient ambiguity = ambiguityDriver.getValue(nbParams, indices);
195 final Gradient phase = tauD.add(dtg).subtract(dts).multiply(cOverLambda).add(ambiguity);
196
197 estimated.setEstimatedValue(phase.getValue());
198
199
200 final double[] derivatives = phase.getGradient();
201 estimated.setStateDerivatives(0, Arrays.copyOfRange(derivatives, 0, 6));
202
203
204
205 for (final ParameterDriver driver : getParametersDrivers()) {
206 final Integer index = indices.get(driver.getName());
207 if (index != null) {
208 estimated.setParameterDerivatives(driver, derivatives[index]);
209 }
210 }
211
212 return estimated;
213
214 }
215
216 }