1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.estimation.measurements.gnss;
18
19 import java.util.Collections;
20 import java.util.List;
21
22 import org.hipparchus.geometry.euclidean.threed.Rotation;
23 import org.hipparchus.geometry.euclidean.threed.Vector3D;
24 import org.hipparchus.util.FastMath;
25 import org.hipparchus.util.MathUtils;
26 import org.orekit.estimation.measurements.EstimatedMeasurementBase;
27 import org.orekit.estimation.measurements.EstimationModifier;
28 import org.orekit.estimation.measurements.ObservedMeasurement;
29 import org.orekit.utils.ParameterDriver;
30 import org.orekit.utils.TimeStampedPVCoordinates;
31
32
33
34
35
36
37
38 public abstract class AbstractWindUp<T extends ObservedMeasurement<T>> implements EstimationModifier<T> {
39
40
41 private final Dipole emitter;
42
43
44 private final Dipole receiver;
45
46
47 private double angularWindUp;
48
49
50
51
52
53 protected AbstractWindUp(final Dipole emitter, final Dipole receiver) {
54 this.emitter = emitter;
55 this.receiver = receiver;
56 angularWindUp = 0.0;
57 }
58
59
60 @Override
61 public String getEffectName() {
62 return "wind-up";
63 }
64
65
66
67
68
69
70 @Override
71 public List<ParameterDriver> getParametersDrivers() {
72 return Collections.emptyList();
73 }
74
75
76
77
78
79 protected abstract Rotation emitterToInert(EstimatedMeasurementBase<T> estimated);
80
81
82
83
84
85 protected abstract Rotation receiverToInert(EstimatedMeasurementBase<T> estimated);
86
87
88
89
90
91
92
93 public void cacheAngularWindUp(final TimeStampedPVCoordinates[] participants,
94 final Rotation receiverToInert, final Rotation emitterToInert) {
95
96
97 final Vector3D los = participants[1].getPosition().subtract(participants[0].getPosition()).normalize();
98
99
100 final Vector3D iReceiver = receiverToInert.applyTo(receiver.getPrimary());
101 final Vector3D jReceiver = receiverToInert.applyTo(receiver.getSecondary());
102 final Vector3D dReceiver = new Vector3D(1.0, iReceiver, -Vector3D.dotProduct(iReceiver, los), los).
103 add(Vector3D.crossProduct(los, jReceiver));
104
105
106 final Vector3D iEmitter = emitterToInert.applyTo(emitter.getPrimary());
107 final Vector3D jEmitter = emitterToInert.applyTo(emitter.getSecondary());
108 final Vector3D dEmitter = new Vector3D(1.0, iEmitter, -Vector3D.dotProduct(iEmitter, los), los).
109 subtract(Vector3D.crossProduct(los, jEmitter));
110
111
112 final double correction = FastMath.copySign(Vector3D.angle(dEmitter, dReceiver),
113 Vector3D.dotProduct(los, Vector3D.crossProduct(dEmitter, dReceiver)));
114
115
116
117
118 angularWindUp = MathUtils.normalizeAngle(correction, angularWindUp);
119
120 }
121
122
123
124
125
126 public double getAngularWindUp() {
127 return angularWindUp;
128 }
129
130
131 @Override
132 public void modifyWithoutDerivatives(final EstimatedMeasurementBase<T> estimated) {
133
134
135 final TimeStampedPVCoordinates[] participants = estimated.getParticipants();
136 final Rotation receiverToInert = receiverToInert(estimated);
137 final Rotation emitterToInert = emitterToInert(estimated);
138 cacheAngularWindUp(participants, receiverToInert, emitterToInert);
139
140
141 estimated.modifyEstimatedValue(this, estimated.getEstimatedValue()[0] + angularWindUp / MathUtils.TWO_PI);
142
143 }
144
145 }