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