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.Field;
23 import org.hipparchus.CalculusFieldElement;
24 import org.hipparchus.analysis.differentiation.Gradient;
25 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
26 import org.hipparchus.geometry.euclidean.threed.Vector3D;
27 import org.orekit.attitudes.InertialProvider;
28 import org.orekit.estimation.measurements.EstimatedMeasurement;
29 import org.orekit.estimation.measurements.EstimationModifier;
30 import org.orekit.estimation.measurements.GroundStation;
31 import org.orekit.estimation.measurements.gnss.Phase;
32 import org.orekit.models.earth.troposphere.DiscreteTroposphericModel;
33 import org.orekit.propagation.FieldSpacecraftState;
34 import org.orekit.propagation.SpacecraftState;
35 import org.orekit.utils.Differentiation;
36 import org.orekit.utils.ParameterDriver;
37 import org.orekit.utils.ParameterFunction;
38
39
40
41
42
43
44
45
46
47 public class PhaseTroposphericDelayModifier implements EstimationModifier<Phase> {
48
49
50 private final DiscreteTroposphericModel tropoModel;
51
52
53
54
55
56 public PhaseTroposphericDelayModifier(final DiscreteTroposphericModel model) {
57 tropoModel = model;
58 }
59
60
61
62
63
64
65
66 private double phaseErrorTroposphericModel(final GroundStation station, final SpacecraftState state, final double wavelength) {
67
68 final Vector3D position = state.getPVCoordinates().getPosition();
69
70
71 final double elevation = station.getBaseFrame().getElevation(position,
72 state.getFrame(),
73 state.getDate());
74
75
76 if (elevation > 0) {
77
78 final double delay = tropoModel.pathDelay(elevation, station.getBaseFrame().getPoint(), tropoModel.getParameters(), state.getDate());
79
80 return delay / wavelength;
81 }
82
83 return 0;
84 }
85
86
87
88
89
90
91
92
93
94 private <T extends CalculusFieldElement<T>> T phaseErrorTroposphericModel(final GroundStation station,
95 final FieldSpacecraftState<T> state,
96 final T[] parameters, final double wavelength) {
97
98
99 final Field<T> field = state.getDate().getField();
100 final T zero = field.getZero();
101
102
103 final FieldVector3D<T> position = state.getPVCoordinates().getPosition();
104 final T elevation = station.getBaseFrame().getElevation(position,
105 state.getFrame(),
106 state.getDate());
107
108
109
110 if (elevation.getReal() > 0) {
111
112 final T delay = tropoModel.pathDelay(elevation, station.getBaseFrame().getPoint(field), parameters, state.getDate());
113
114 return delay.divide(wavelength);
115 }
116
117 return zero;
118 }
119
120
121
122
123
124
125
126
127 private double[][] phaseErrorJacobianState(final double[] derivatives) {
128 final double[][] finiteDifferencesJacobian = new double[1][6];
129 System.arraycopy(derivatives, 0, finiteDifferencesJacobian[0], 0, 6);
130 return finiteDifferencesJacobian;
131 }
132
133
134
135
136
137
138
139
140
141 private double phaseErrorParameterDerivative(final GroundStation station,
142 final ParameterDriver driver,
143 final SpacecraftState state,
144 final double wavelength) {
145 final ParameterFunction rangeError = parameterDriver -> phaseErrorTroposphericModel(station, state, wavelength);
146 final ParameterFunction phaseErrorDerivative =
147 Differentiation.differentiate(rangeError, 3, 10.0 * driver.getScale());
148 return phaseErrorDerivative.value(driver);
149
150 }
151
152
153
154
155
156
157
158
159 private double[] phaseErrorParameterDerivative(final double[] derivatives, final int freeStateParameters) {
160
161
162 final int dim = derivatives.length - freeStateParameters;
163 final double[] rangeError = new double[dim];
164
165 for (int i = 0; i < dim; i++) {
166 rangeError[i] = derivatives[freeStateParameters + i];
167 }
168
169 return rangeError;
170 }
171
172
173 @Override
174 public List<ParameterDriver> getParametersDrivers() {
175 return tropoModel.getParametersDrivers();
176 }
177
178
179 @Override
180 public void modify(final EstimatedMeasurement<Phase> estimated) {
181 final Phase measurement = estimated.getObservedMeasurement();
182 final GroundStation station = measurement.getStation();
183 final SpacecraftState state = estimated.getStates()[0];
184
185
186 final double[] oldValue = estimated.getEstimatedValue();
187
188
189 final TroposphericGradientConverter converter = new TroposphericGradientConverter(state, 6, new InertialProvider(state.getFrame()));
190 final FieldSpacecraftState<Gradient> gState = converter.getState(tropoModel);
191 final Gradient[] gParameters = converter.getParameters(gState, tropoModel);
192 final Gradient gDelay = phaseErrorTroposphericModel(station, gState, gParameters, measurement.getWavelength());
193 final double[] derivatives = gDelay.getGradient();
194
195
196 final double[][] djac = phaseErrorJacobianState(derivatives);
197 final double[][] stateDerivatives = estimated.getStateDerivatives(0);
198 for (int irow = 0; irow < stateDerivatives.length; ++irow) {
199 for (int jcol = 0; jcol < stateDerivatives[0].length; ++jcol) {
200 stateDerivatives[irow][jcol] += djac[irow][jcol];
201 }
202 }
203 estimated.setStateDerivatives(0, stateDerivatives);
204
205
206
207 int index = 0;
208 for (final ParameterDriver driver : getParametersDrivers()) {
209 if (driver.isSelected()) {
210
211 double parameterDerivative = estimated.getParameterDerivatives(driver)[0];
212 final double[] dDelaydP = phaseErrorParameterDerivative(derivatives, converter.getFreeStateParameters());
213 parameterDerivative += dDelaydP[index];
214 estimated.setParameterDerivatives(driver, parameterDerivative);
215 index = index + 1;
216 }
217 }
218
219
220 for (final ParameterDriver driver : Arrays.asList(station.getClockOffsetDriver(),
221 station.getEastOffsetDriver(),
222 station.getNorthOffsetDriver(),
223 station.getZenithOffsetDriver())) {
224 if (driver.isSelected()) {
225
226 double parameterDerivative = estimated.getParameterDerivatives(driver)[0];
227 parameterDerivative += phaseErrorParameterDerivative(station, driver, state, measurement.getWavelength());
228 estimated.setParameterDerivatives(driver, parameterDerivative);
229 }
230 }
231
232
233
234 final double[] newValue = oldValue.clone();
235 newValue[0] = newValue[0] + gDelay.getReal();
236 estimated.setEstimatedValue(newValue);
237 }
238
239 }
240