1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.gnss.attitude;
18
19 import java.util.HashMap;
20 import java.util.Map;
21 import java.util.SortedSet;
22 import java.util.TreeSet;
23
24 import org.hipparchus.Field;
25 import org.hipparchus.CalculusFieldElement;
26 import org.orekit.attitudes.Attitude;
27 import org.orekit.attitudes.FieldAttitude;
28 import org.orekit.frames.Frame;
29 import org.orekit.time.AbsoluteDate;
30 import org.orekit.time.ChronologicalComparator;
31 import org.orekit.time.FieldAbsoluteDate;
32 import org.orekit.time.TimeStamped;
33 import org.orekit.utils.ExtendedPositionProvider;
34 import org.orekit.utils.FieldPVCoordinatesProvider;
35 import org.orekit.utils.PVCoordinatesProvider;
36 import org.orekit.utils.TimeStampedAngularCoordinates;
37 import org.orekit.utils.TimeStampedFieldAngularCoordinates;
38
39
40
41
42
43
44
45 abstract class AbstractGNSSAttitudeProvider implements GNSSAttitudeProvider {
46
47
48 private final AbsoluteDate validityStart;
49
50
51 private final AbsoluteDate validityEnd;
52
53
54 private final ExtendedPositionProvider sun;
55
56
57 private final Frame inertialFrame;
58
59
60 private final SortedSet<TimeStamped> turns;
61
62
63 private final Map<Field<? extends CalculusFieldElement<?>>, SortedSet<TimeStamped>> fieldTurns;
64
65
66
67
68
69
70
71 protected AbstractGNSSAttitudeProvider(final AbsoluteDate validityStart,
72 final AbsoluteDate validityEnd,
73 final ExtendedPositionProvider sun,
74 final Frame inertialFrame) {
75 this.validityStart = validityStart;
76 this.validityEnd = validityEnd;
77 this.sun = sun;
78 this.inertialFrame = inertialFrame;
79 this.turns = new TreeSet<>(new ChronologicalComparator());
80 this.fieldTurns = new HashMap<>();
81 }
82
83
84 @Override
85 public AbsoluteDate validityStart() {
86 return validityStart;
87 }
88
89
90 @Override
91 public AbsoluteDate validityEnd() {
92 return validityEnd;
93 }
94
95
96 @Override
97 public Attitude getAttitude(final PVCoordinatesProvider pvProv,
98 final AbsoluteDate date,
99 final Frame frame) {
100
101
102 final TurnSpan turnSpan = getTurnSpan(date);
103 final GNSSAttitudeContext context = new GNSSAttitudeContext(date, sun, pvProv, inertialFrame, turnSpan);
104 final TimeStampedAngularCoordinates corrected = correctedYaw(context);
105 if (turnSpan == null && context.getTurnSpan() != null) {
106
107 turns.add(context.getTurnSpan());
108 }
109
110 return new Attitude(inertialFrame, corrected).withReferenceFrame(frame);
111
112 }
113
114
115 @Override
116 public <T extends CalculusFieldElement<T>> FieldAttitude<T> getAttitude(final FieldPVCoordinatesProvider<T> pvProv,
117 final FieldAbsoluteDate<T> date,
118 final Frame frame) {
119
120
121 final FieldTurnSpan<T> turnSpan = getTurnSpan(date);
122 final GNSSFieldAttitudeContext<T> context = new GNSSFieldAttitudeContext<>(date, sun, pvProv, inertialFrame, turnSpan);
123 final TimeStampedFieldAngularCoordinates<T> corrected = correctedYaw(context);
124 if (turnSpan == null && context.getTurnSpan() != null) {
125
126 fieldTurns.get(date.getField()).add(context.getTurnSpan());
127 }
128
129 return new FieldAttitude<>(inertialFrame, corrected).withReferenceFrame(frame);
130
131 }
132
133
134
135
136
137 private TurnSpan getTurnSpan(final AbsoluteDate date) {
138
139
140
141 final SortedSet<TimeStamped> after = turns.tailSet(date);
142 if (!after.isEmpty()) {
143 final TurnSpan ts = (TurnSpan) after.first();
144 if (ts.inTurnTimeRange(date)) {
145 return ts;
146 }
147 }
148
149
150 return null;
151
152 }
153
154
155
156
157
158
159 private <T extends CalculusFieldElement<T>> FieldTurnSpan<T> getTurnSpan(final FieldAbsoluteDate<T> date) {
160
161 final SortedSet<TimeStamped> sortedSet = fieldTurns.computeIfAbsent(date.getField(),
162 k -> new TreeSet<>(new ChronologicalComparator()));
163
164
165
166
167 final AbsoluteDate dateDouble = date.toAbsoluteDate();
168 final SortedSet<TimeStamped> after = sortedSet.tailSet(dateDouble);
169 if (!after.isEmpty()) {
170 @SuppressWarnings("unchecked")
171 final FieldTurnSpan<T> ts = (FieldTurnSpan<T>) after.first();
172 if (ts.inTurnTimeRange(dateDouble)) {
173 return ts;
174 }
175 }
176
177
178 return null;
179
180 }
181
182
183
184
185
186 protected ExtendedPositionProvider getSun() {
187 return sun;
188 }
189
190
191
192
193 protected Frame getInertialFrame() {
194 return inertialFrame;
195 }
196
197
198
199
200
201
202 protected abstract TimeStampedAngularCoordinates correctedYaw(GNSSAttitudeContext context);
203
204
205
206
207
208
209 protected abstract <T extends CalculusFieldElement<T>> TimeStampedFieldAngularCoordinates<T>
210 correctedYaw(GNSSFieldAttitudeContext<T> context);
211
212 }