1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.estimation.measurements.modifiers;
18
19 import java.util.Arrays;
20 import java.util.List;
21
22 import org.hipparchus.CalculusFieldElement;
23 import org.hipparchus.Field;
24 import org.hipparchus.analysis.differentiation.Gradient;
25 import org.orekit.attitudes.FrameAlignedProvider;
26 import org.orekit.estimation.measurements.EstimatedMeasurement;
27 import org.orekit.estimation.measurements.EstimatedMeasurementBase;
28 import org.orekit.estimation.measurements.EstimationModifier;
29 import org.orekit.estimation.measurements.GroundStation;
30 import org.orekit.estimation.measurements.gnss.Phase;
31 import org.orekit.models.earth.troposphere.TroposphericModel;
32 import org.orekit.propagation.FieldSpacecraftState;
33 import org.orekit.propagation.SpacecraftState;
34 import org.orekit.utils.Differentiation;
35 import org.orekit.utils.FieldTrackingCoordinates;
36 import org.orekit.utils.ParameterDriver;
37 import org.orekit.utils.ParameterFunction;
38 import org.orekit.utils.TimeSpanMap.Span;
39 import org.orekit.utils.TrackingCoordinates;
40
41
42
43
44
45
46
47
48
49 public class PhaseTroposphericDelayModifier implements EstimationModifier<Phase> {
50
51
52 private final TroposphericModel tropoModel;
53
54
55
56
57
58
59 @Deprecated
60 public PhaseTroposphericDelayModifier(final org.orekit.models.earth.troposphere.DiscreteTroposphericModel model) {
61 this(new org.orekit.models.earth.troposphere.TroposphericModelAdapter(model));
62 }
63
64
65
66
67
68
69 public PhaseTroposphericDelayModifier(final TroposphericModel model) {
70 tropoModel = model;
71 }
72
73
74
75
76
77
78
79 private double phaseErrorTroposphericModel(final GroundStation station, final SpacecraftState state, final double wavelength) {
80
81
82 final TrackingCoordinates trackingCoordinates =
83 station.getBaseFrame().getTrackingCoordinates(state.getPosition(), state.getFrame(), state.getDate());
84
85
86 if (trackingCoordinates.getElevation() > 0) {
87
88 final double delay = tropoModel.pathDelay(trackingCoordinates,
89 station.getOffsetGeodeticPoint(state.getDate()),
90 station.getPressureTemperatureHumidity(state.getDate()),
91 tropoModel.getParameters(state.getDate()), state.getDate()).
92 getDelay();
93
94 return delay / wavelength;
95 }
96
97 return 0;
98 }
99
100
101
102
103
104
105
106
107
108 private <T extends CalculusFieldElement<T>> T phaseErrorTroposphericModel(final GroundStation station,
109 final FieldSpacecraftState<T> state,
110 final T[] parameters, final double wavelength) {
111
112
113 final Field<T> field = state.getDate().getField();
114 final T zero = field.getZero();
115
116
117 final FieldTrackingCoordinates<T> trackingCoordinates =
118 station.getBaseFrame().getTrackingCoordinates(state.getPosition(), state.getFrame(), state.getDate());
119
120
121
122 if (trackingCoordinates.getElevation().getReal() > 0) {
123
124 final T delay = tropoModel.pathDelay(trackingCoordinates,
125 station.getOffsetGeodeticPoint(state.getDate()),
126 station.getPressureTemperatureHumidity(state.getDate()),
127 parameters, state.getDate()).
128 getDelay();
129
130 return delay.divide(wavelength);
131 }
132
133 return zero;
134 }
135
136
137
138
139
140
141
142
143 private double[][] phaseErrorJacobianState(final double[] derivatives) {
144 final double[][] finiteDifferencesJacobian = new double[1][6];
145 System.arraycopy(derivatives, 0, finiteDifferencesJacobian[0], 0, 6);
146 return finiteDifferencesJacobian;
147 }
148
149
150
151
152
153
154
155
156
157 private double phaseErrorParameterDerivative(final GroundStation station,
158 final ParameterDriver driver,
159 final SpacecraftState state,
160 final double wavelength) {
161 final ParameterFunction rangeError = (parameterDriver, date) -> phaseErrorTroposphericModel(station, state, wavelength);
162 final ParameterFunction phaseErrorDerivative =
163 Differentiation.differentiate(rangeError, 3, 10.0 * driver.getScale());
164 return phaseErrorDerivative.value(driver, state.getDate());
165
166 }
167
168
169
170
171
172
173
174
175 private double[] phaseErrorParameterDerivative(final double[] derivatives, final int freeStateParameters) {
176
177
178 return Arrays.copyOfRange(derivatives, freeStateParameters, derivatives.length);
179 }
180
181
182 @Override
183 public List<ParameterDriver> getParametersDrivers() {
184 return tropoModel.getParametersDrivers();
185 }
186
187
188 @Override
189 public void modifyWithoutDerivatives(final EstimatedMeasurementBase<Phase> estimated) {
190
191 final Phase measurement = estimated.getObservedMeasurement();
192 final GroundStation station = measurement.getStation();
193 final SpacecraftState state = estimated.getStates()[0];
194
195
196
197 final double[] newValue = estimated.getEstimatedValue();
198 final double delay = phaseErrorTroposphericModel(station, state, measurement.getWavelength());
199 newValue[0] = newValue[0] + delay;
200 estimated.modifyEstimatedValue(this, newValue);
201
202 }
203
204
205 @Override
206 public void modify(final EstimatedMeasurement<Phase> estimated) {
207 final Phase measurement = estimated.getObservedMeasurement();
208 final GroundStation station = measurement.getStation();
209 final SpacecraftState state = estimated.getStates()[0];
210
211
212 final ModifierGradientConverter converter = new ModifierGradientConverter(state, 6, new FrameAlignedProvider(state.getFrame()));
213 final FieldSpacecraftState<Gradient> gState = converter.getState(tropoModel);
214 final Gradient[] gParameters = converter.getParametersAtStateDate(gState, tropoModel);
215 final Gradient gDelay = phaseErrorTroposphericModel(station, gState, gParameters, measurement.getWavelength());
216 final double[] derivatives = gDelay.getGradient();
217
218
219 final double[][] djac = phaseErrorJacobianState(derivatives);
220 final double[][] stateDerivatives = estimated.getStateDerivatives(0);
221 for (int irow = 0; irow < stateDerivatives.length; ++irow) {
222 for (int jcol = 0; jcol < stateDerivatives[0].length; ++jcol) {
223 stateDerivatives[irow][jcol] += djac[irow][jcol];
224 }
225 }
226 estimated.setStateDerivatives(0, stateDerivatives);
227
228
229
230 int index = 0;
231 for (final ParameterDriver driver : getParametersDrivers()) {
232 if (driver.isSelected()) {
233 for (Span<String> span = driver.getNamesSpanMap().getFirstSpan(); span != null; span = span.next()) {
234
235
236 double parameterDerivative = estimated.getParameterDerivatives(driver, span.getStart())[0];
237 final double[] dDelaydP = phaseErrorParameterDerivative(derivatives, converter.getFreeStateParameters());
238 parameterDerivative += dDelaydP[index];
239 estimated.setParameterDerivatives(driver, span.getStart(), parameterDerivative);
240 index = index + 1;
241 }
242 }
243 }
244
245
246 for (final ParameterDriver driver : Arrays.asList(station.getClockOffsetDriver(),
247 station.getEastOffsetDriver(),
248 station.getNorthOffsetDriver(),
249 station.getZenithOffsetDriver())) {
250 if (driver.isSelected()) {
251 for (Span<String> span = driver.getNamesSpanMap().getFirstSpan(); span != null; span = span.next()) {
252
253 double parameterDerivative = estimated.getParameterDerivatives(driver, span.getStart())[0];
254 parameterDerivative += phaseErrorParameterDerivative(station, driver, state, measurement.getWavelength());
255 estimated.setParameterDerivatives(driver, span.getStart(), parameterDerivative);
256 }
257 }
258 }
259
260
261 modifyWithoutDerivatives(estimated);
262
263 }
264
265 }
266