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