1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.files.ccsds.ndm.adm.apm;
18
19 import java.util.Arrays;
20
21 import org.hipparchus.analysis.differentiation.UnivariateDerivative1;
22 import org.hipparchus.complex.Quaternion;
23 import org.hipparchus.geometry.euclidean.threed.FieldRotation;
24 import org.hipparchus.geometry.euclidean.threed.Rotation;
25 import org.hipparchus.geometry.euclidean.threed.Vector3D;
26 import org.orekit.attitudes.Attitude;
27 import org.orekit.errors.OrekitException;
28 import org.orekit.errors.OrekitMessages;
29 import org.orekit.files.ccsds.ndm.adm.AttitudeEndoints;
30 import org.orekit.files.ccsds.section.Section;
31 import org.orekit.frames.Frame;
32 import org.orekit.time.AbsoluteDate;
33 import org.orekit.utils.PVCoordinatesProvider;
34 import org.orekit.utils.TimeStampedAngularCoordinates;
35
36
37
38
39
40
41 public class ApmQuaternion implements Section {
42
43
44 private AbsoluteDate epoch;
45
46
47 private final AttitudeEndoints endpoints;
48
49
50 private double[] q;
51
52
53 private double[] qDot;
54
55
56
57 public ApmQuaternion() {
58 endpoints = new AttitudeEndoints();
59 q = new double[4];
60 qDot = new double[4];
61 Arrays.fill(q, Double.NaN);
62 Arrays.fill(qDot, Double.NaN);
63 }
64
65
66 @Override
67 public void validate(final double version) {
68 endpoints.checkMandatoryEntriesExceptExternalFrame(ApmQuaternionKey.Q_FRAME_A,
69 ApmQuaternionKey.Q_FRAME_B,
70 ApmQuaternionKey.Q_DIR);
71 endpoints.checkExternalFrame(ApmQuaternionKey.Q_FRAME_A, ApmQuaternionKey.Q_FRAME_B);
72 if (Double.isNaN(q[0] + q[1] + q[2] + q[3])) {
73 throw new OrekitException(OrekitMessages.UNINITIALIZED_VALUE_FOR_KEY, "Q{C|1|2|3}");
74 }
75 }
76
77
78
79
80
81 public AbsoluteDate getEpoch() {
82 return epoch;
83 }
84
85
86
87
88
89 public void setEpoch(final AbsoluteDate epoch) {
90 this.epoch = epoch;
91 }
92
93
94
95
96 public AttitudeEndoints getEndpoints() {
97 return endpoints;
98 }
99
100
101
102
103
104 public Quaternion getQuaternion() {
105 return new Quaternion(q[0], q[1], q[2], q[3]);
106 }
107
108
109
110
111
112
113 public void setQ(final int index, final double value) {
114 this.q[index] = value;
115 }
116
117
118
119
120
121 public Quaternion getQuaternionDot() {
122 return new Quaternion(qDot[0], qDot[1], qDot[2], qDot[3]);
123 }
124
125
126
127
128
129
130 public void setQDot(final int index, final double derivative) {
131 this.qDot[index] = derivative;
132 }
133
134
135
136
137 public boolean hasRates() {
138 return !Double.isNaN(qDot[0] + qDot[1] + qDot[2] + qDot[3]);
139 }
140
141
142
143
144
145
146
147
148
149 public Attitude getAttitude(final Frame frame, final PVCoordinatesProvider pvProvider) {
150
151 if (Double.isNaN(qDot[0])) {
152
153 final Rotation r = new Rotation(q[0], q[1], q[2], q[3], true);
154
155
156 return endpoints.build(frame, pvProvider,
157 new TimeStampedAngularCoordinates(epoch, r, Vector3D.ZERO, Vector3D.ZERO));
158
159 } else {
160
161 final UnivariateDerivative1 q0 = new UnivariateDerivative1(q[0], qDot[0]);
162 final UnivariateDerivative1 q1 = new UnivariateDerivative1(q[1], qDot[1]);
163 final UnivariateDerivative1 q2 = new UnivariateDerivative1(q[2], qDot[2]);
164 final UnivariateDerivative1 q3 = new UnivariateDerivative1(q[3], qDot[3]);
165 final FieldRotation<UnivariateDerivative1> rd = new FieldRotation<>(q0, q1, q2, q3, true);
166
167
168 return endpoints.build(frame, pvProvider, new TimeStampedAngularCoordinates(epoch, rd));
169 }
170
171 }
172
173 }