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.ExtendedPVCoordinatesProvider;
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 ExtendedPVCoordinatesProvider sun;
55
56
57 private final Frame inertialFrame;
58
59
60 private final SortedSet<TimeStamped> turns;
61
62
63 private final transient 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 ExtendedPVCoordinatesProvider 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 SortedSet<TimeStamped> sortedSet = fieldTurns.get(date.getField());
162 if (sortedSet == null) {
163
164 sortedSet = new TreeSet<>(new ChronologicalComparator());
165 fieldTurns.put(date.getField(), sortedSet);
166 }
167
168
169
170 final AbsoluteDate dateDouble = date.toAbsoluteDate();
171 final SortedSet<TimeStamped> after = sortedSet.tailSet(dateDouble);
172 if (!after.isEmpty()) {
173 @SuppressWarnings("unchecked")
174 final FieldTurnSpan<T> ts = (FieldTurnSpan<T>) after.first();
175 if (ts.inTurnTimeRange(dateDouble)) {
176 return ts;
177 }
178 }
179
180
181 return null;
182
183 }
184
185
186
187
188
189 protected ExtendedPVCoordinatesProvider getSun() {
190 return sun;
191 }
192
193
194
195
196 protected Frame getInertialFrame() {
197 return inertialFrame;
198 }
199
200
201
202
203
204
205 protected abstract TimeStampedAngularCoordinates correctedYaw(GNSSAttitudeContext context);
206
207
208
209
210
211
212 protected abstract <T extends CalculusFieldElement<T>> TimeStampedFieldAngularCoordinates<T>
213 correctedYaw(GNSSFieldAttitudeContext<T> context);
214
215 }