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