1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.estimation.measurements;
18
19 import java.util.Arrays;
20
21 import org.hipparchus.analysis.differentiation.Gradient;
22 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
23 import org.hipparchus.geometry.euclidean.threed.Vector3D;
24 import org.orekit.frames.FieldTransform;
25 import org.orekit.frames.Transform;
26 import org.orekit.propagation.SpacecraftState;
27 import org.orekit.time.AbsoluteDate;
28 import org.orekit.time.FieldAbsoluteDate;
29 import org.orekit.utils.ParameterDriver;
30 import org.orekit.utils.TimeSpanMap.Span;
31 import org.orekit.utils.TimeStampedFieldPVCoordinates;
32 import org.orekit.utils.TimeStampedPVCoordinates;
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56 public class BistaticRangeRate extends GroundReceiverMeasurement<BistaticRangeRate> {
57
58
59 public static final String MEASUREMENT_TYPE = "BistaticRangeRate";
60
61
62 private final GroundStation emitter;
63
64
65
66
67
68
69
70
71
72
73 public BistaticRangeRate(final GroundStation emitter, final GroundStation receiver,
74 final AbsoluteDate date, final double rangeRate, final double sigma,
75 final double baseWeight, final ObservableSatellite satellite) {
76 super(receiver, true, date, rangeRate, sigma, baseWeight, satellite);
77
78
79 addParameterDriver(emitter.getEastOffsetDriver());
80 addParameterDriver(emitter.getNorthOffsetDriver());
81 addParameterDriver(emitter.getZenithOffsetDriver());
82 addParameterDriver(emitter.getPrimeMeridianOffsetDriver());
83 addParameterDriver(emitter.getPrimeMeridianDriftDriver());
84 addParameterDriver(emitter.getPolarOffsetXDriver());
85 addParameterDriver(emitter.getPolarDriftXDriver());
86 addParameterDriver(emitter.getPolarOffsetYDriver());
87 addParameterDriver(emitter.getPolarDriftYDriver());
88
89 this.emitter = emitter;
90
91 }
92
93
94
95
96 public GroundStation getEmitterStation() {
97 return emitter;
98 }
99
100
101
102
103 public GroundStation getReceiverStation() {
104 return getStation();
105 }
106
107
108 @Override
109 protected EstimatedMeasurementBase<BistaticRangeRate> theoreticalEvaluationWithoutDerivatives(final int iteration,
110 final int evaluation,
111 final SpacecraftState[] states) {
112 final GroundReceiverCommonParametersWithoutDerivatives common = computeCommonParametersWithout(states[0]);
113 final TimeStampedPVCoordinates transitPV = common.getTransitPV();
114 final AbsoluteDate transitDate = transitPV.getDate();
115
116
117 final Transform emitterToInertial =
118 getEmitterStation().getOffsetToInertial(common.getState().getFrame(), transitDate, true);
119 final TimeStampedPVCoordinates emitterApprox =
120 emitterToInertial.transformPVCoordinates(new TimeStampedPVCoordinates(transitDate,
121 Vector3D.ZERO, Vector3D.ZERO, Vector3D.ZERO));
122
123
124 final double tauU = signalTimeOfFlightAdjustableEmitter(emitterApprox, transitPV.getPosition(), transitDate,
125 common.getState().getFrame());
126
127
128 final TimeStampedPVCoordinates emitterPV = emitterApprox.shiftedBy(-tauU);
129
130
131 final EstimatedMeasurementBase<BistaticRangeRate> estimated =
132 new EstimatedMeasurementBase<>(this,
133 iteration, evaluation,
134 new SpacecraftState[] {
135 common.getTransitState()
136 },
137 new TimeStampedPVCoordinates[] {
138 common.getStationDownlink(),
139 transitPV,
140 emitterPV
141 });
142
143
144 final Vector3D receiverDirection = common.getStationDownlink().getPosition()
145 .subtract(transitPV.getPosition()).normalize();
146 final Vector3D emitterDirection = emitterPV.getPosition()
147 .subtract(transitPV.getPosition()).normalize();
148
149 final Vector3D receiverVelocity = common.getStationDownlink().getVelocity()
150 .subtract(transitPV.getVelocity());
151 final Vector3D emitterVelocity = emitterPV.getVelocity()
152 .subtract(transitPV.getVelocity());
153
154
155 final double rangeRate = Vector3D.dotProduct(receiverDirection, receiverVelocity) +
156 Vector3D.dotProduct(emitterDirection, emitterVelocity);
157 estimated.setEstimatedValue(rangeRate);
158
159 return estimated;
160
161 }
162
163
164 @Override
165 protected EstimatedMeasurement<BistaticRangeRate> theoreticalEvaluation(final int iteration,
166 final int evaluation,
167 final SpacecraftState[] states) {
168
169 final SpacecraftState state = states[0];
170
171
172
173
174
175
176
177
178
179 final GroundReceiverCommonParametersWithDerivatives common = computeCommonParametersWithDerivatives(state);
180 final int nbParams = common.getTauD().getFreeParameters();
181 final TimeStampedFieldPVCoordinates<Gradient> transitPV = common.getTransitPV();
182 final FieldAbsoluteDate<Gradient> transitDate = transitPV.getDate();
183
184
185 final FieldVector3D<Gradient> zero = FieldVector3D.getZero(common.getTauD().getField());
186 final FieldTransform<Gradient> emitterToInertial =
187 getEmitterStation().getOffsetToInertial(state.getFrame(), transitDate, nbParams, common.getIndices());
188 final TimeStampedFieldPVCoordinates<Gradient> emitterApprox =
189 emitterToInertial.transformPVCoordinates(new TimeStampedFieldPVCoordinates<>(transitDate,
190 zero, zero, zero));
191
192
193 final Gradient tauU = signalTimeOfFlightAdjustableEmitter(emitterApprox, transitPV.getPosition(), transitPV.getDate(),
194 state.getFrame());
195
196
197 final TimeStampedFieldPVCoordinates<Gradient> emitterPV = emitterApprox.shiftedBy(tauU.negate());
198
199
200 final EstimatedMeasurement<BistaticRangeRate> estimated = new EstimatedMeasurement<>(this,
201 iteration, evaluation,
202 new SpacecraftState[] {
203 common.getTransitState()
204 },
205 new TimeStampedPVCoordinates[] {
206 common.getStationDownlink().toTimeStampedPVCoordinates(),
207 common.getTransitPV().toTimeStampedPVCoordinates(),
208 emitterPV.toTimeStampedPVCoordinates()
209 });
210
211
212 final FieldVector3D<Gradient> receiverDirection = common.getStationDownlink().getPosition()
213 .subtract(transitPV.getPosition()).normalize();
214 final FieldVector3D<Gradient> emitterDirection = emitterPV.getPosition()
215 .subtract(transitPV.getPosition()).normalize();
216
217 final FieldVector3D<Gradient> receiverVelocity = common.getStationDownlink().getVelocity()
218 .subtract(transitPV.getVelocity());
219 final FieldVector3D<Gradient> emitterVelocity = emitterPV.getVelocity()
220 .subtract(transitPV.getVelocity());
221
222
223 final Gradient rangeRate = FieldVector3D.dotProduct(receiverDirection, receiverVelocity)
224 .add(FieldVector3D.dotProduct(emitterDirection, emitterVelocity));
225 estimated.setEstimatedValue(rangeRate.getValue());
226
227
228 final double[] derivatives = rangeRate.getGradient();
229 estimated.setStateDerivatives(0, Arrays.copyOfRange(derivatives, 0, 6));
230
231
232 for (final ParameterDriver driver : getParametersDrivers()) {
233 for (Span<String> span = driver.getNamesSpanMap().getFirstSpan(); span != null; span = span.next()) {
234 final Integer index = common.getIndices().get(span.getData());
235 if (index != null) {
236 estimated.setParameterDerivatives(driver, span.getStart(), derivatives[index]);
237 }
238 }
239 }
240
241 return estimated;
242
243 }
244
245 }