1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.files.ccsds.ndm.adm;
18
19 import org.hipparchus.CalculusFieldElement;
20 import org.hipparchus.Field;
21 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
22 import org.orekit.attitudes.Attitude;
23 import org.orekit.attitudes.AttitudeBuilder;
24 import org.orekit.attitudes.FieldAttitude;
25 import org.orekit.errors.OrekitException;
26 import org.orekit.errors.OrekitMessages;
27 import org.orekit.files.ccsds.definitions.CcsdsFrameMapper;
28 import org.orekit.files.ccsds.definitions.FrameFacade;
29 import org.orekit.files.ccsds.definitions.OrbitRelativeFrame;
30 import org.orekit.frames.Frame;
31 import org.orekit.utils.AngularCoordinates;
32 import org.orekit.utils.FieldAngularCoordinates;
33 import org.orekit.utils.FieldPVCoordinates;
34 import org.orekit.utils.FieldPVCoordinatesProvider;
35 import org.orekit.utils.PVCoordinates;
36 import org.orekit.utils.PVCoordinatesProvider;
37 import org.orekit.utils.TimeStampedAngularCoordinates;
38 import org.orekit.utils.TimeStampedFieldAngularCoordinates;
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54 public class AttitudeEndpoints implements AttitudeBuilder {
55
56
57 public static final String A2B = "A2B";
58
59
60 public static final String B2A = "B2A";
61
62
63 private final CcsdsFrameMapper frameMapper;
64
65
66 private FrameFacade frameA;
67
68
69 private FrameFacade frameB;
70
71
72 private Boolean a2b;
73
74
75
76
77
78
79
80 public AttitudeEndpoints(final CcsdsFrameMapper frameMapper) {
81 this.frameMapper = frameMapper;
82 }
83
84
85
86
87
88 private void checkNotNull(final Object field, final Enum<?> key) {
89 if (field == null) {
90 throw new OrekitException(OrekitMessages.UNINITIALIZED_VALUE_FOR_KEY, key.name());
91 }
92 }
93
94
95
96
97 public void checkExternalFrame(final Enum<?> aKey, final Enum<?> bKey) {
98 checkNotNull(frameA, aKey);
99 checkNotNull(frameB, bKey);
100 if (frameA.asSpacecraftBodyFrame() != null && frameB.asSpacecraftBodyFrame() != null) {
101
102 throw new OrekitException(OrekitMessages.CCSDS_INVALID_FRAME, frameB.getName());
103 }
104 }
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119 public void checkMandatoryEntriesExceptExternalFrame(final double version,
120 final Enum<?> aKey, final Enum<?> bKey,
121 final Enum<?> dirKey) {
122
123 if (frameA == null) {
124 if (frameB == null || frameB.asSpacecraftBodyFrame() == null) {
125 throw new OrekitException(OrekitMessages.UNINITIALIZED_VALUE_FOR_KEY, aKey.name());
126 }
127 } else if (frameA.asSpacecraftBodyFrame() == null) {
128 if (frameB == null) {
129 throw new OrekitException(OrekitMessages.UNINITIALIZED_VALUE_FOR_KEY, bKey.name());
130 } else if (frameB.asSpacecraftBodyFrame() == null) {
131
132 throw new OrekitException(OrekitMessages.CCSDS_INVALID_FRAME, frameB.getName());
133 }
134 }
135
136 if (version < 2.0) {
137
138 checkNotNull(a2b, dirKey);
139 } else if (!isA2b()) {
140
141 throw new OrekitException(OrekitMessages.CCSDS_KEYWORD_NOT_ALLOWED_IN_VERSION,
142 dirKey, version);
143 }
144
145 }
146
147
148
149
150 public void setFrameA(final FrameFacade frameA) {
151 this.frameA = frameA;
152 }
153
154
155
156
157 public FrameFacade getFrameA() {
158 return frameA;
159 }
160
161
162
163
164 public void setFrameB(final FrameFacade frameB) {
165 this.frameB = frameB;
166 }
167
168
169
170
171 public FrameFacade getFrameB() {
172 return frameB;
173 }
174
175
176
177
178
179 public void setA2b(final boolean a2b) {
180 this.a2b = a2b;
181 }
182
183
184
185
186 public boolean isA2b() {
187 return a2b == null ? true : a2b;
188 }
189
190
191
192
193
194 public FrameFacade getExternalFrame() {
195 return frameA.asSpacecraftBodyFrame() == null ? frameA : frameB;
196 }
197
198
199
200
201
202
203
204 public CcsdsFrameMapper getFrameMapper() {
205 return frameMapper;
206 }
207
208
209
210
211
212
213
214
215 public Frame getExternal() {
216
217 return getFrameMapper().buildCcsdsFrame(getExternalFrame(), null);
218 }
219
220
221
222
223 public FrameFacade getSpacecraftBodyFrame() {
224 return frameA.asSpacecraftBodyFrame() == null ? frameB : frameA;
225 }
226
227
228
229
230
231
232
233
234
235
236 public boolean isExternal2SpacecraftBody() {
237 return isA2b() ^ frameB.asSpacecraftBodyFrame() == null;
238 }
239
240
241
242
243
244
245
246
247
248 public boolean isCompatibleWith(final AttitudeEndpoints other) {
249 return frameA.getName().equals(other.frameA.getName()) &&
250 frameB.getName().equals(other.frameB.getName()) &&
251 a2b.equals(other.a2b);
252 }
253
254
255 @Override
256 public Attitude build(final Frame frame, final PVCoordinatesProvider pvProv,
257 final TimeStampedAngularCoordinates rawAttitude) {
258
259
260 final TimeStampedAngularCoordinates att =
261 isExternal2SpacecraftBody() ? rawAttitude : rawAttitude.revert();
262
263 final FrameFacade external = getExternalFrame();
264 final OrbitRelativeFrame orf = external.asOrbitRelativeFrame();
265 if (orf != null) {
266
267 if (orf.getLofType() == null) {
268 throw new OrekitException(OrekitMessages.UNSUPPORTED_LOCAL_ORBITAL_FRAME, external.getName());
269 }
270
271
272 final PVCoordinates pv = pvProv.getPVCoordinates(rawAttitude.getDate(), frame);
273 final AngularCoordinates frame2Lof =
274 orf.isQuasiInertial() ?
275 new AngularCoordinates(orf.getLofType().rotationFromInertial(pv)) :
276 orf.getLofType().transformFromInertial(att.getDate(), pv).getAngular();
277
278
279 return new Attitude(frame, att.addOffset(frame2Lof));
280
281 } else {
282
283 if (external.asFrame() == null) {
284
285 throw new OrekitException(OrekitMessages.CCSDS_INVALID_FRAME, external.getName());
286 }
287 final Attitude attitude = new Attitude(external.asFrame(), att);
288 return frame == null ? attitude : attitude.withReferenceFrame(frame);
289 }
290
291 }
292
293
294 @Override
295 public <T extends CalculusFieldElement<T>>
296 FieldAttitude<T> build(final Frame frame, final FieldPVCoordinatesProvider<T> pvProv,
297 final TimeStampedFieldAngularCoordinates<T> rawAttitude) {
298
299
300 final TimeStampedFieldAngularCoordinates<T> att =
301 isExternal2SpacecraftBody() ? rawAttitude : rawAttitude.revert();
302
303 final FrameFacade external = getExternalFrame();
304 final OrbitRelativeFrame orf = external.asOrbitRelativeFrame();
305 if (orf != null) {
306
307 if (orf.getLofType() == null) {
308 throw new OrekitException(OrekitMessages.UNSUPPORTED_LOCAL_ORBITAL_FRAME, external.getName());
309 }
310
311
312 final FieldPVCoordinates<T> pv = pvProv.getPVCoordinates(rawAttitude.getDate(), frame);
313 final Field<T> field = rawAttitude.getDate().getField();
314 final FieldAngularCoordinates<T> referenceToLof =
315 orf.isQuasiInertial() ?
316 new FieldAngularCoordinates<>(orf.getLofType().rotationFromInertial(field, pv),
317 FieldVector3D.getZero(field)) :
318 orf.getLofType().transformFromInertial(att.getDate(), pv).getAngular();
319
320
321 return new FieldAttitude<>(frame, att.addOffset(referenceToLof));
322
323 } else {
324
325 if (external.asFrame() == null) {
326
327 throw new OrekitException(OrekitMessages.CCSDS_INVALID_FRAME, external.getName());
328 }
329 final FieldAttitude<T> attitude = new FieldAttitude<>(external.asFrame(), att);
330 return frame == null ? attitude : attitude.withReferenceFrame(frame);
331 }
332
333 }
334
335
336 @Override
337 public String toString() {
338 return frameA.getName() + (isA2b() ? " → " : " ← ") + frameB.getName();
339 }
340
341 }