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.Field;
23 import org.hipparchus.CalculusFieldElement;
24 import org.hipparchus.analysis.differentiation.Gradient;
25 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
26 import org.hipparchus.geometry.euclidean.threed.Vector3D;
27 import org.orekit.attitudes.InertialProvider;
28 import org.orekit.estimation.measurements.EstimatedMeasurement;
29 import org.orekit.estimation.measurements.EstimationModifier;
30 import org.orekit.estimation.measurements.GroundStation;
31 import org.orekit.estimation.measurements.TurnAroundRange;
32 import org.orekit.models.earth.troposphere.DiscreteTroposphericModel;
33 import org.orekit.propagation.FieldSpacecraftState;
34 import org.orekit.propagation.SpacecraftState;
35 import org.orekit.utils.Differentiation;
36 import org.orekit.utils.ParameterDriver;
37 import org.orekit.utils.ParameterFunction;
38
39
40
41
42
43
44
45
46
47
48
49 public class TurnAroundRangeTroposphericDelayModifier implements EstimationModifier<TurnAroundRange> {
50
51
52 private final DiscreteTroposphericModel tropoModel;
53
54
55
56
57
58 public TurnAroundRangeTroposphericDelayModifier(final DiscreteTroposphericModel model) {
59 tropoModel = model;
60 }
61
62
63
64
65
66
67 private double rangeErrorTroposphericModel(final GroundStation station, final SpacecraftState state) {
68
69 final Vector3D position = state.getPVCoordinates().getPosition();
70
71
72 final double elevation = station.getBaseFrame().getElevation(position,
73 state.getFrame(),
74 state.getDate());
75
76
77 if (elevation > 0) {
78
79 final double delay = tropoModel.pathDelay(elevation, station.getBaseFrame().getPoint(), tropoModel.getParameters(), state.getDate());
80
81 return delay;
82 }
83
84 return 0;
85 }
86
87
88
89
90
91
92
93
94 private <T extends CalculusFieldElement<T>> T rangeErrorTroposphericModel(final GroundStation station,
95 final FieldSpacecraftState<T> state,
96 final T[] parameters) {
97
98 final Field<T> field = state.getDate().getField();
99 final T zero = field.getZero();
100
101
102 final FieldVector3D<T> position = state.getPVCoordinates().getPosition();
103 final T dsElevation = station.getBaseFrame().getElevation(position,
104 state.getFrame(),
105 state.getDate());
106
107
108 if (dsElevation.getReal() > 0) {
109
110 final T delay = tropoModel.pathDelay(dsElevation, station.getBaseFrame().getPoint(field), parameters, state.getDate());
111
112 return delay;
113 }
114
115 return zero;
116 }
117
118
119
120
121
122
123
124
125 private double[][] rangeErrorJacobianState(final double[] derivatives) {
126 final double[][] finiteDifferencesJacobian = new double[1][6];
127 System.arraycopy(derivatives, 0, finiteDifferencesJacobian[0], 0, 6);
128 return finiteDifferencesJacobian;
129 }
130
131
132
133
134
135
136
137
138
139 private double rangeErrorParameterDerivative(final GroundStation station,
140 final ParameterDriver driver,
141 final SpacecraftState state) {
142
143 final ParameterFunction rangeError = new ParameterFunction() {
144
145 @Override
146 public double value(final ParameterDriver parameterDriver) {
147 return rangeErrorTroposphericModel(station, state);
148 }
149 };
150
151 final ParameterFunction rangeErrorDerivative = Differentiation.differentiate(rangeError, 3, 10.0 * driver.getScale());
152
153 return rangeErrorDerivative.value(driver);
154
155 }
156
157
158
159
160
161
162
163
164 private double[] rangeErrorParameterDerivative(final double[] derivatives, final int freeStateParameters) {
165
166
167 final int dim = derivatives.length - freeStateParameters;
168 final double[] rangeError = new double[dim];
169
170 for (int i = 0; i < dim; i++) {
171 rangeError[i] = derivatives[freeStateParameters + i];
172 }
173
174 return rangeError;
175 }
176
177
178 @Override
179 public List<ParameterDriver> getParametersDrivers() {
180 return tropoModel.getParametersDrivers();
181 }
182
183
184 @Override
185 public void modify(final EstimatedMeasurement<TurnAroundRange> estimated) {
186 final TurnAroundRange measurement = estimated.getObservedMeasurement();
187 final GroundStation primaryStation = measurement.getPrimaryStation();
188 final GroundStation secondaryStation = measurement.getSecondaryStation();
189 final SpacecraftState state = estimated.getStates()[0];
190
191 final double[] oldValue = estimated.getEstimatedValue();
192
193
194 final TroposphericGradientConverter converter =
195 new TroposphericGradientConverter(state, 6, new InertialProvider(state.getFrame()));
196 final FieldSpacecraftState<Gradient> gState = converter.getState(tropoModel);
197 final Gradient[] gParameters = converter.getParameters(gState, tropoModel);
198 final Gradient primaryGDelay = rangeErrorTroposphericModel(primaryStation, gState, gParameters);
199 final Gradient secondaryGDelay = rangeErrorTroposphericModel(secondaryStation, gState, gParameters);
200 final double[] primaryDerivatives = primaryGDelay.getGradient();
201 final double[] secondaryDerivatives = secondaryGDelay.getGradient();
202
203 final double[][] primaryDjac = rangeErrorJacobianState(primaryDerivatives);
204 final double[][] secondaryDjac = rangeErrorJacobianState(secondaryDerivatives);
205 final double[][] stateDerivatives = estimated.getStateDerivatives(0);
206 for (int irow = 0; irow < stateDerivatives.length; ++irow) {
207 for (int jcol = 0; jcol < stateDerivatives[0].length; ++jcol) {
208 stateDerivatives[irow][jcol] += primaryDjac[irow][jcol] + secondaryDjac[irow][jcol];
209 }
210 }
211 estimated.setStateDerivatives(0, stateDerivatives);
212
213 int indexPrimary = 0;
214 for (final ParameterDriver driver : getParametersDrivers()) {
215 if (driver.isSelected()) {
216
217 double parameterDerivative = estimated.getParameterDerivatives(driver)[0];
218 final double[] derivatives = rangeErrorParameterDerivative(primaryDerivatives, converter.getFreeStateParameters());
219 parameterDerivative += derivatives[indexPrimary];
220 estimated.setParameterDerivatives(driver, parameterDerivative);
221 indexPrimary += 1;
222 }
223
224 }
225
226 int indexSecondary = 0;
227 for (final ParameterDriver driver : getParametersDrivers()) {
228 if (driver.isSelected()) {
229
230 double parameterDerivative = estimated.getParameterDerivatives(driver)[0];
231 final double[] derivatives = rangeErrorParameterDerivative(secondaryDerivatives, converter.getFreeStateParameters());
232 parameterDerivative += derivatives[indexSecondary];
233 estimated.setParameterDerivatives(driver, parameterDerivative);
234 indexSecondary += 1;
235 }
236
237 }
238
239
240 for (final ParameterDriver driver : Arrays.asList(primaryStation.getClockOffsetDriver(),
241 primaryStation.getEastOffsetDriver(),
242 primaryStation.getNorthOffsetDriver(),
243 primaryStation.getZenithOffsetDriver())) {
244 if (driver.isSelected()) {
245 double parameterDerivative = estimated.getParameterDerivatives(driver)[0];
246 parameterDerivative += rangeErrorParameterDerivative(primaryStation, driver, state);
247 estimated.setParameterDerivatives(driver, parameterDerivative);
248 }
249 }
250
251
252 for (final ParameterDriver driver : Arrays.asList(secondaryStation.getEastOffsetDriver(),
253 secondaryStation.getNorthOffsetDriver(),
254 secondaryStation.getZenithOffsetDriver())) {
255 if (driver.isSelected()) {
256 double parameterDerivative = estimated.getParameterDerivatives(driver)[0];
257 parameterDerivative += rangeErrorParameterDerivative(secondaryStation, driver, state);
258 estimated.setParameterDerivatives(driver, parameterDerivative);
259 }
260 }
261
262
263
264 final double[] newValue = oldValue.clone();
265 newValue[0] = newValue[0] + primaryGDelay.getReal() + secondaryGDelay.getReal();
266 estimated.setEstimatedValue(newValue);
267
268 }
269
270 }