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 @Override
69 public String getEffectName() {
70 return "ionosphere";
71 }
72
73
74
75
76
77
78 private double phaseErrorIonosphericModel(final GroundStation station,
79 final SpacecraftState state) {
80
81
82 final TopocentricFrame baseFrame = station.getBaseFrame();
83 final double wavelength = Constants.SPEED_OF_LIGHT / frequency;
84
85 final double delay = ionoModel.pathDelay(state, baseFrame, frequency, ionoModel.getParameters(state.getDate()));
86 return delay / wavelength;
87 }
88
89
90
91
92
93
94
95
96 private <T extends CalculusFieldElement<T>> T phaseErrorIonosphericModel(final GroundStation station,
97 final FieldSpacecraftState<T> state,
98 final T[] parameters) {
99
100
101 final TopocentricFrame baseFrame = station.getBaseFrame();
102 final double wavelength = Constants.SPEED_OF_LIGHT / frequency;
103
104 final T delay = ionoModel.pathDelay(state, baseFrame, frequency, parameters);
105 return delay.divide(wavelength);
106 }
107
108
109
110
111
112
113
114
115
116 private double[][] phaseErrorJacobianState(final double[] derivatives, final int freeStateParameters) {
117 final double[][] finiteDifferencesJacobian = new double[1][6];
118 System.arraycopy(derivatives, 0, finiteDifferencesJacobian[0], 0, freeStateParameters);
119 return finiteDifferencesJacobian;
120 }
121
122
123
124
125
126
127
128
129
130 private double phaseErrorParameterDerivative(final GroundStation station,
131 final ParameterDriver driver,
132 final SpacecraftState state) {
133 final ParameterFunction phaseError = (parameterDriver, date) -> phaseErrorIonosphericModel(station, state);
134 final ParameterFunction phaseErrorDerivative =
135 Differentiation.differentiate(phaseError, 3, 10.0 * driver.getScale());
136 return phaseErrorDerivative.value(driver, state.getDate());
137
138 }
139
140
141
142
143
144
145
146
147 private double[] phaseErrorParameterDerivative(final double[] derivatives, final int freeStateParameters) {
148
149
150 return Arrays.copyOfRange(derivatives, freeStateParameters, derivatives.length);
151 }
152
153
154 @Override
155 public List<ParameterDriver> getParametersDrivers() {
156 return ionoModel.getParametersDrivers();
157 }
158
159 @Override
160 public void modifyWithoutDerivatives(final EstimatedMeasurementBase<Phase> estimated) {
161
162 final Phase measurement = estimated.getObservedMeasurement();
163 final GroundStation station = measurement.getStation();
164 final SpacecraftState state = estimated.getStates()[0];
165
166
167
168 final double[] newValue = estimated.getEstimatedValue();
169 final double delay = phaseErrorIonosphericModel(station, state);
170 newValue[0] = newValue[0] - delay;
171 estimated.modifyEstimatedValue(this, newValue);
172
173 }
174
175 @Override
176 public void modify(final EstimatedMeasurement<Phase> estimated) {
177
178 final Phase measurement = estimated.getObservedMeasurement();
179 final GroundStation station = measurement.getStation();
180 final SpacecraftState state = estimated.getStates()[0];
181
182
183 final ModifierGradientConverter converter =
184 new ModifierGradientConverter(state, 6, new FrameAlignedProvider(state.getFrame()));
185 final FieldSpacecraftState<Gradient> gState = converter.getState(ionoModel);
186 final Gradient[] gParameters = converter.getParametersAtStateDate(gState, ionoModel);
187 final Gradient gDelay = phaseErrorIonosphericModel(station, gState, gParameters);
188 final double[] derivatives = gDelay.getGradient();
189
190
191 final double[][] djac = phaseErrorJacobianState(derivatives, converter.getFreeStateParameters());
192 final double[][] stateDerivatives = estimated.getStateDerivatives(0);
193 for (int irow = 0; irow < stateDerivatives.length; ++irow) {
194 for (int jcol = 0; jcol < stateDerivatives[0].length; ++jcol) {
195 stateDerivatives[irow][jcol] -= djac[irow][jcol];
196 }
197 }
198 estimated.setStateDerivatives(0, stateDerivatives);
199
200
201 int index = 0;
202 for (final ParameterDriver driver : getParametersDrivers()) {
203 if (driver.isSelected()) {
204 for (Span<String> span = driver.getNamesSpanMap().getFirstSpan(); span != null; span = span.next()) {
205
206 double parameterDerivative = estimated.getParameterDerivatives(driver, span.getStart())[0];
207 final double[] dDelaydP = phaseErrorParameterDerivative(derivatives, converter.getFreeStateParameters());
208 parameterDerivative -= dDelaydP[index];
209 estimated.setParameterDerivatives(driver, span.getStart(), parameterDerivative);
210 index = index + 1;
211 }
212 }
213
214 }
215
216
217 for (final ParameterDriver driver : Arrays.asList(station.getClockOffsetDriver(),
218 station.getEastOffsetDriver(),
219 station.getNorthOffsetDriver(),
220 station.getZenithOffsetDriver())) {
221 if (driver.isSelected()) {
222 for (Span<String> span = driver.getNamesSpanMap().getFirstSpan(); span != null; span = span.next()) {
223
224 double parameterDerivative = estimated.getParameterDerivatives(driver, span.getStart())[0];
225 parameterDerivative -= phaseErrorParameterDerivative(station, driver, state);
226 estimated.setParameterDerivatives(driver, span.getStart(), parameterDerivative);
227 }
228 }
229 }
230
231
232 modifyWithoutDerivatives(estimated);
233
234 }
235
236 }
237