1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.attitudes;
18
19 import org.hipparchus.CalculusFieldElement;
20 import org.hipparchus.Field;
21 import org.hipparchus.analysis.differentiation.FieldUnivariateDerivative2;
22 import org.hipparchus.analysis.differentiation.UnivariateDerivative2;
23 import org.hipparchus.analysis.differentiation.UnivariateDerivative2Field;
24 import org.hipparchus.geometry.euclidean.threed.FieldRotation;
25 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
26 import org.hipparchus.geometry.euclidean.threed.Rotation;
27 import org.hipparchus.geometry.euclidean.threed.RotationConvention;
28 import org.hipparchus.geometry.euclidean.threed.Vector3D;
29 import org.orekit.annotation.DefaultDataContext;
30 import org.orekit.bodies.OneAxisEllipsoid;
31 import org.orekit.errors.OrekitException;
32 import org.orekit.errors.OrekitMessages;
33 import org.orekit.frames.Frame;
34 import org.orekit.frames.FramesFactory;
35 import org.orekit.time.AbsoluteDate;
36 import org.orekit.time.FieldAbsoluteDate;
37 import org.orekit.utils.AngularCoordinates;
38 import org.orekit.utils.ExtendedPositionProvider;
39 import org.orekit.utils.FieldAngularCoordinates;
40 import org.orekit.utils.FieldPVCoordinatesProvider;
41 import org.orekit.utils.PVCoordinatesProvider;
42 import org.orekit.utils.TimeStampedFieldPVCoordinates;
43 import org.orekit.utils.TimeStampedPVCoordinates;
44
45 import java.util.HashMap;
46 import java.util.Map;
47
48
49
50
51
52
53 public class AlignedAndConstrained implements AttitudeProvider
54 {
55
56
57 private final FieldVector3D<UnivariateDerivative2> primarySat;
58
59
60 private final TargetProvider primaryTarget;
61
62
63 private final FieldVector3D<UnivariateDerivative2> secondarySat;
64
65
66 private final TargetProvider secondaryTarget;
67
68
69 private final ExtendedPositionProvider sun;
70
71
72 private final OneAxisEllipsoid earth;
73
74
75 private final Frame inertialFrame;
76
77
78 private final transient Map<Field<? extends CalculusFieldElement<?>>, Cache<? extends CalculusFieldElement<?>>>
79 cachedSatelliteVectors;
80
81
82
83
84
85
86
87
88
89
90
91
92 public AlignedAndConstrained(final Vector3D primarySat, final TargetProvider primaryTarget,
93 final Vector3D secondarySat, final TargetProvider secondaryTarget,
94 final Frame inertialFrame, final ExtendedPositionProvider sun,
95 final OneAxisEllipsoid earth) {
96 if (!inertialFrame.isPseudoInertial()) {
97 throw new OrekitException(OrekitMessages.NON_PSEUDO_INERTIAL_FRAME, inertialFrame.getName());
98 }
99 this.primarySat = new FieldVector3D<>(UnivariateDerivative2Field.getInstance(), primarySat);
100 this.primaryTarget = primaryTarget;
101 this.secondarySat = new FieldVector3D<>(UnivariateDerivative2Field.getInstance(), secondarySat);
102 this.secondaryTarget = secondaryTarget;
103 this.inertialFrame = inertialFrame;
104 this.sun = sun;
105 this.earth = earth;
106 this.cachedSatelliteVectors = new HashMap<>();
107 }
108
109
110
111
112
113
114
115
116
117
118 @DefaultDataContext
119 public AlignedAndConstrained(final Vector3D primarySat, final TargetProvider primaryTarget,
120 final Vector3D secondarySat, final TargetProvider secondaryTarget,
121 final ExtendedPositionProvider sun,
122 final OneAxisEllipsoid earth)
123 {
124 this(primarySat, primaryTarget, secondarySat, secondaryTarget, FramesFactory.getGCRF(), sun, earth);
125 }
126
127
128 @Override
129 public Rotation getAttitudeRotation(final PVCoordinatesProvider pvProv, final AbsoluteDate date, final Frame frame) {
130 final TimeStampedPVCoordinates satPV = pvProv.getPVCoordinates(date, inertialFrame);
131
132
133 final Vector3D primaryDirection = primaryTarget.getTargetDirection(sun, earth, satPV, inertialFrame);
134 final Vector3D secondaryDirection = secondaryTarget.getTargetDirection(sun, earth, satPV, inertialFrame);
135
136
137 final Rotation rotation = new Rotation(primaryDirection, secondaryDirection, primarySat.toVector3D(),
138 secondarySat.toVector3D());
139 if (inertialFrame != frame) {
140
141 final Rotation prepended = frame.getStaticTransformTo(inertialFrame, date).getRotation();
142 return rotation.compose(prepended, RotationConvention.VECTOR_OPERATOR);
143 }
144 return rotation;
145 }
146
147
148 @Override
149 public Attitude getAttitude(final PVCoordinatesProvider pvProv,
150 final AbsoluteDate date,
151 final Frame frame)
152 {
153 final TimeStampedPVCoordinates satPV = pvProv.getPVCoordinates(date, inertialFrame);
154
155
156 final FieldVector3D<UnivariateDerivative2> primaryDirection = primaryTarget.getDerivative2TargetDirection(sun,
157 earth, satPV, inertialFrame);
158 final FieldVector3D<UnivariateDerivative2> secondaryDirection = secondaryTarget.getDerivative2TargetDirection(sun,
159 earth, satPV, inertialFrame);
160
161
162 final FieldRotation<UnivariateDerivative2> inertToSatRotation =
163 new FieldRotation<>(primaryDirection, secondaryDirection, primarySat, secondarySat);
164
165
166 final AngularCoordinates angularCoordinates = new AngularCoordinates(inertToSatRotation);
167 final Attitude attitude = new Attitude(date, inertialFrame, angularCoordinates);
168 return attitude.withReferenceFrame(frame);
169 }
170
171
172 @Override
173 public <T extends CalculusFieldElement<T>> FieldRotation<T> getAttitudeRotation(final FieldPVCoordinatesProvider<T> pvProv,
174 final FieldAbsoluteDate<T> date,
175 final Frame frame) {
176 final TimeStampedFieldPVCoordinates<T> satPV = pvProv.getPVCoordinates(date, inertialFrame);
177
178
179 final FieldVector3D<T> primaryDirection = primaryTarget.getTargetDirection(sun, earth, satPV, inertialFrame);
180 final FieldVector3D<T> secondaryDirection = secondaryTarget.getTargetDirection(sun, earth, satPV, inertialFrame);
181
182
183 final Field<T> field = date.getField();
184 final FieldRotation<T> rotation = new FieldRotation<>(primaryDirection, secondaryDirection,
185 new FieldVector3D<>(field, primarySat.toVector3D()), new FieldVector3D<>(field, secondarySat.toVector3D()));
186 if (inertialFrame != frame) {
187
188 final FieldRotation<T> prepended = frame.getStaticTransformTo(inertialFrame, date).getRotation();
189 return rotation.compose(prepended, RotationConvention.VECTOR_OPERATOR);
190 }
191 return rotation;
192 }
193
194
195 @Override
196 public <T extends CalculusFieldElement<T>> FieldAttitude<T> getAttitude(final FieldPVCoordinatesProvider<T> pvProv,
197 final FieldAbsoluteDate<T> date,
198 final Frame frame)
199 {
200
201 @SuppressWarnings("unchecked")
202 final Cache<T> satVectors =
203 (Cache<T>) cachedSatelliteVectors.computeIfAbsent(date.getField(),
204 f -> new Cache<>(date.getField(), primarySat, secondarySat));
205
206 final TimeStampedFieldPVCoordinates<T> satPV = pvProv.getPVCoordinates(date, inertialFrame);
207
208
209 final FieldVector3D<FieldUnivariateDerivative2<T>> primaryDirection = primaryTarget.getDerivative2TargetDirection(sun,
210 earth, satPV, inertialFrame);
211 final FieldVector3D<FieldUnivariateDerivative2<T>> secondaryDirection = secondaryTarget.getDerivative2TargetDirection(sun,
212 earth, satPV, inertialFrame);
213
214
215 final FieldRotation<FieldUnivariateDerivative2<T>> inertToSatRotation =
216 new FieldRotation<>(primaryDirection, secondaryDirection, satVectors.primarySat, satVectors.secondarySat);
217
218
219 final FieldAngularCoordinates<T> angularCoordinates = new FieldAngularCoordinates<>(inertToSatRotation);
220 final FieldAttitude<T> attitude = new FieldAttitude<>(date, inertialFrame, angularCoordinates);
221 return attitude.withReferenceFrame(frame);
222 }
223
224
225 private static class Cache<T extends CalculusFieldElement<T>> {
226
227
228 private final FieldVector3D<FieldUnivariateDerivative2<T>> primarySat;
229
230
231 private final FieldVector3D<FieldUnivariateDerivative2<T>> secondarySat;
232
233
234
235
236
237
238 Cache(final Field<T> field,
239 final FieldVector3D<UnivariateDerivative2> primarySat,
240 final FieldVector3D<UnivariateDerivative2> secondarySat) {
241 final FieldUnivariateDerivative2<T> zero =
242 new FieldUnivariateDerivative2<>(field.getZero(), field.getZero(), field.getZero());
243 this.primarySat = new FieldVector3D<>(zero.newInstance(primarySat.getX().getValue()),
244 zero.newInstance(primarySat.getY().getValue()),
245 zero.newInstance(primarySat.getZ().getValue()));
246 this.secondarySat = new FieldVector3D<>(zero.newInstance(secondarySat.getX().getValue()),
247 zero.newInstance(secondarySat.getY().getValue()),
248 zero.newInstance(secondarySat.getZ().getValue()));
249 }
250
251 }
252
253 }