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