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.hipparchus.geometry.euclidean.threed.Vector3D;
23 import org.orekit.attitudes.Attitude;
24 import org.orekit.attitudes.AttitudeBuilder;
25 import org.orekit.attitudes.FieldAttitude;
26 import org.orekit.errors.OrekitException;
27 import org.orekit.errors.OrekitMessages;
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 FrameFacade frameA;
64
65
66 private FrameFacade frameB;
67
68
69 private Boolean a2b;
70
71
72
73
74
75
76
77
78 public AttitudeEndpoints() {
79
80 }
81
82
83
84
85
86 private void checkNotNull(final Object field, final Enum<?> key) {
87 if (field == null) {
88 throw new OrekitException(OrekitMessages.UNINITIALIZED_VALUE_FOR_KEY, key.name());
89 }
90 }
91
92
93
94
95 public void checkExternalFrame(final Enum<?> aKey, final Enum<?> bKey) {
96 checkNotNull(frameA, aKey);
97 checkNotNull(frameB, bKey);
98 if (frameA.asSpacecraftBodyFrame() != null && frameB.asSpacecraftBodyFrame() != null) {
99
100 throw new OrekitException(OrekitMessages.CCSDS_INVALID_FRAME, frameB.getName());
101 }
102 }
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117 public void checkMandatoryEntriesExceptExternalFrame(final double version,
118 final Enum<?> aKey, final Enum<?> bKey,
119 final Enum<?> dirKey) {
120
121 if (frameA == null) {
122 if (frameB == null || frameB.asSpacecraftBodyFrame() == null) {
123 throw new OrekitException(OrekitMessages.UNINITIALIZED_VALUE_FOR_KEY, aKey.name());
124 }
125 } else if (frameA.asSpacecraftBodyFrame() == null) {
126 if (frameB == null) {
127 throw new OrekitException(OrekitMessages.UNINITIALIZED_VALUE_FOR_KEY, bKey.name());
128 } else if (frameB.asSpacecraftBodyFrame() == null) {
129
130 throw new OrekitException(OrekitMessages.CCSDS_INVALID_FRAME, frameB.getName());
131 }
132 }
133
134 if (version < 2.0) {
135
136 checkNotNull(a2b, dirKey);
137 } else if (!isA2b()) {
138
139 throw new OrekitException(OrekitMessages.CCSDS_KEYWORD_NOT_ALLOWED_IN_VERSION,
140 dirKey, version);
141 }
142
143 }
144
145
146
147
148 public void setFrameA(final FrameFacade frameA) {
149 this.frameA = frameA;
150 }
151
152
153
154
155 public FrameFacade getFrameA() {
156 return frameA;
157 }
158
159
160
161
162 public void setFrameB(final FrameFacade frameB) {
163 this.frameB = frameB;
164 }
165
166
167
168
169 public FrameFacade getFrameB() {
170 return frameB;
171 }
172
173
174
175
176
177 public void setA2b(final boolean a2b) {
178 this.a2b = a2b;
179 }
180
181
182
183
184 public boolean isA2b() {
185 return a2b == null ? true : a2b;
186 }
187
188
189
190
191 public FrameFacade getExternalFrame() {
192 return frameA.asSpacecraftBodyFrame() == null ? frameA : frameB;
193 }
194
195
196
197
198 public FrameFacade getSpacecraftBodyFrame() {
199 return frameA.asSpacecraftBodyFrame() == null ? frameB : frameA;
200 }
201
202
203
204
205
206
207
208
209
210
211 public boolean isExternal2SpacecraftBody() {
212 return isA2b() ^ frameB.asSpacecraftBodyFrame() == null;
213 }
214
215
216
217
218
219
220
221
222
223 public boolean isCompatibleWith(final AttitudeEndpoints other) {
224 return frameA.getName().equals(other.frameA.getName()) &&
225 frameB.getName().equals(other.frameB.getName()) &&
226 a2b.equals(other.a2b);
227 }
228
229
230 @Override
231 public Attitude build(final Frame frame, final PVCoordinatesProvider pvProv,
232 final TimeStampedAngularCoordinates rawAttitude) {
233
234
235 final TimeStampedAngularCoordinates att =
236 isExternal2SpacecraftBody() ? rawAttitude : rawAttitude.revert();
237
238 final FrameFacade external = getExternalFrame();
239 final OrbitRelativeFrame orf = external.asOrbitRelativeFrame();
240 if (orf != null) {
241
242 if (orf.getLofType() == null) {
243 throw new OrekitException(OrekitMessages.UNSUPPORTED_LOCAL_ORBITAL_FRAME, external.getName());
244 }
245
246
247 final PVCoordinates pv = pvProv.getPVCoordinates(rawAttitude.getDate(), frame);
248 final AngularCoordinates frame2Lof =
249 orf.isQuasiInertial() ?
250 new AngularCoordinates(orf.getLofType().rotationFromInertial(pv), Vector3D.ZERO) :
251 orf.getLofType().transformFromInertial(att.getDate(), pv).getAngular();
252
253
254 return new Attitude(frame, att.addOffset(frame2Lof));
255
256 } else {
257
258 if (external.asFrame() == null) {
259
260 throw new OrekitException(OrekitMessages.CCSDS_INVALID_FRAME, external.getName());
261 }
262 final Attitude attitude = new Attitude(external.asFrame(), att);
263 return frame == null ? attitude : attitude.withReferenceFrame(frame);
264 }
265
266 }
267
268
269 @Override
270 public <T extends CalculusFieldElement<T>>
271 FieldAttitude<T> build(final Frame frame, final FieldPVCoordinatesProvider<T> pvProv,
272 final TimeStampedFieldAngularCoordinates<T> rawAttitude) {
273
274
275 final TimeStampedFieldAngularCoordinates<T> att =
276 isExternal2SpacecraftBody() ? rawAttitude : rawAttitude.revert();
277
278 final FrameFacade external = getExternalFrame();
279 final OrbitRelativeFrame orf = external.asOrbitRelativeFrame();
280 if (orf != null) {
281
282 if (orf.getLofType() == null) {
283 throw new OrekitException(OrekitMessages.UNSUPPORTED_LOCAL_ORBITAL_FRAME, external.getName());
284 }
285
286
287 final FieldPVCoordinates<T> pv = pvProv.getPVCoordinates(rawAttitude.getDate(), frame);
288 final Field<T> field = rawAttitude.getDate().getField();
289 final FieldAngularCoordinates<T> referenceToLof =
290 orf.isQuasiInertial() ?
291 new FieldAngularCoordinates<>(orf.getLofType().rotationFromInertial(field, pv),
292 FieldVector3D.getZero(field)) :
293 orf.getLofType().transformFromInertial(att.getDate(), pv).getAngular();
294
295
296 return new FieldAttitude<>(frame, att.addOffset(referenceToLof));
297
298 } else {
299
300 if (external.asFrame() == null) {
301
302 throw new OrekitException(OrekitMessages.CCSDS_INVALID_FRAME, external.getName());
303 }
304 final FieldAttitude<T> attitude = new FieldAttitude<>(external.asFrame(), att);
305 return frame == null ? attitude : attitude.withReferenceFrame(frame);
306 }
307
308 }
309
310
311 @Override
312 public String toString() {
313 return frameA.getName() + (isA2b() ? " → " : " ← ") + frameB.getName();
314 }
315
316 }