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