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