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.RangeRate;
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.Differentiation;
34 import org.orekit.utils.ParameterDriver;
35 import org.orekit.utils.ParameterFunction;
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 public class RangeRateIonosphericDelayModifier implements EstimationModifier<RangeRate> {
52
53
54 private final IonosphericModel ionoModel;
55
56
57 private final double frequency;
58
59
60 private final double fTwoWay;
61
62
63
64
65
66
67
68 public RangeRateIonosphericDelayModifier(final IonosphericModel model,
69 final double freq, final boolean twoWay) {
70 ionoModel = model;
71 frequency = freq;
72
73 if (twoWay) {
74 fTwoWay = 2.;
75 } else {
76 fTwoWay = 1.;
77 }
78 }
79
80
81
82
83
84
85 private double rangeRateErrorIonosphericModel(final GroundStation station, final SpacecraftState state) {
86 final double dt = 10;
87
88 final TopocentricFrame baseFrame = station.getBaseFrame();
89
90 final double delay1 = ionoModel.pathDelay(state, baseFrame, frequency, ionoModel.getParameters());
91
92 final SpacecraftState state2 = state.shiftedBy(dt);
93
94 final double delay2 = ionoModel.pathDelay(state2, baseFrame, frequency, ionoModel.getParameters());
95
96 return fTwoWay * (delay2 - delay1) / dt;
97 }
98
99
100
101
102
103
104
105
106 private <T extends CalculusFieldElement<T>> T rangeRateErrorIonosphericModel(final GroundStation station,
107 final FieldSpacecraftState<T> state,
108 final T[] parameters) {
109 final double dt = 10;
110
111 final TopocentricFrame baseFrame = station.getBaseFrame();
112
113 final T delay1 = ionoModel.pathDelay(state, baseFrame, frequency, parameters);
114
115 final FieldSpacecraftState<T> state2 = state.shiftedBy(dt);
116
117 final T delay2 = ionoModel.pathDelay(state2, baseFrame, frequency, parameters);
118
119 return delay2.subtract(delay1).divide(dt).multiply(fTwoWay);
120 }
121
122
123
124
125
126
127
128
129 private double[][] rangeRateErrorJacobianState(final double[] derivatives) {
130 final double[][] finiteDifferencesJacobian = new double[1][6];
131 System.arraycopy(derivatives, 0, finiteDifferencesJacobian[0], 0, 6);
132 return finiteDifferencesJacobian;
133 }
134
135
136
137
138
139
140
141
142 private double rangeRateErrorParameterDerivative(final GroundStation station,
143 final ParameterDriver driver,
144 final SpacecraftState state) {
145
146 final ParameterFunction rangeError = new ParameterFunction() {
147
148 @Override
149 public double value(final ParameterDriver parameterDriver) {
150 return rangeRateErrorIonosphericModel(station, state);
151 }
152 };
153
154 final ParameterFunction rangeErrorDerivative =
155 Differentiation.differentiate(rangeError, 3, 10.0 * driver.getScale());
156
157 return rangeErrorDerivative.value(driver);
158
159 }
160
161
162
163
164
165
166
167
168 private double[] rangeRateErrorParameterDerivative(final double[] derivatives, final int freeStateParameters) {
169
170
171 final int dim = derivatives.length - freeStateParameters;
172 final double[] rangeError = new double[dim];
173
174 for (int i = 0; i < dim; i++) {
175 rangeError[i] = derivatives[freeStateParameters + i];
176 }
177
178 return rangeError;
179 }
180
181
182 @Override
183 public List<ParameterDriver> getParametersDrivers() {
184 return ionoModel.getParametersDrivers();
185 }
186
187
188 @Override
189 public void modify(final EstimatedMeasurement<RangeRate> estimated) {
190
191 final RangeRate measurement = estimated.getObservedMeasurement();
192 final GroundStation station = measurement.getStation();
193 final SpacecraftState state = estimated.getStates()[0];
194
195 final double[] oldValue = estimated.getEstimatedValue();
196
197
198 final IonosphericGradientConverter converter =
199 new IonosphericGradientConverter(state, 6, new InertialProvider(state.getFrame()));
200 final FieldSpacecraftState<Gradient> gState = converter.getState(ionoModel);
201 final Gradient[] gParameters = converter.getParameters(gState, ionoModel);
202 final Gradient gDelay = rangeRateErrorIonosphericModel(station, gState, gParameters);
203 final double[] derivatives = gDelay.getGradient();
204
205
206 final double[][] djac = rangeRateErrorJacobianState(derivatives);
207 final double[][] stateDerivatives = estimated.getStateDerivatives(0);
208 for (int irow = 0; irow < stateDerivatives.length; ++irow) {
209 for (int jcol = 0; jcol < stateDerivatives[0].length; ++jcol) {
210 stateDerivatives[irow][jcol] += djac[irow][jcol];
211 }
212 }
213 estimated.setStateDerivatives(0, stateDerivatives);
214
215 int index = 0;
216 for (final ParameterDriver driver : getParametersDrivers()) {
217 if (driver.isSelected()) {
218
219 double parameterDerivative = estimated.getParameterDerivatives(driver)[0];
220 final double[] dDelaydP = rangeRateErrorParameterDerivative(derivatives, converter.getFreeStateParameters());
221 parameterDerivative += dDelaydP[index];
222 estimated.setParameterDerivatives(driver, parameterDerivative);
223 index = index + 1;
224 }
225
226 }
227
228 for (final ParameterDriver driver : Arrays.asList(station.getClockOffsetDriver(),
229 station.getEastOffsetDriver(),
230 station.getNorthOffsetDriver(),
231 station.getZenithOffsetDriver())) {
232 if (driver.isSelected()) {
233
234 double parameterDerivative = estimated.getParameterDerivatives(driver)[0];
235 parameterDerivative += rangeRateErrorParameterDerivative(station, driver, state);
236 estimated.setParameterDerivatives(driver, parameterDerivative);
237 }
238 }
239
240
241
242 final double[] newValue = oldValue.clone();
243 newValue[0] = newValue[0] + gDelay.getValue();
244 estimated.setEstimatedValue(newValue);
245
246 }
247
248 }