1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.attitudes;
18
19 import java.util.ArrayList;
20 import java.util.List;
21
22 import org.hipparchus.CalculusFieldElement;
23 import org.hipparchus.geometry.euclidean.threed.FieldLine;
24 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
25 import org.hipparchus.geometry.euclidean.threed.Line;
26 import org.hipparchus.geometry.euclidean.threed.Vector3D;
27 import org.orekit.bodies.BodyShape;
28 import org.orekit.bodies.FieldGeodeticPoint;
29 import org.orekit.bodies.GeodeticPoint;
30 import org.orekit.errors.OrekitException;
31 import org.orekit.errors.OrekitMessages;
32 import org.orekit.frames.FieldTransform;
33 import org.orekit.frames.Frame;
34 import org.orekit.frames.Transform;
35 import org.orekit.time.AbsoluteDate;
36 import org.orekit.time.FieldAbsoluteDate;
37 import org.orekit.utils.CartesianDerivativesFilter;
38 import org.orekit.utils.Constants;
39 import org.orekit.utils.FieldPVCoordinatesProvider;
40 import org.orekit.utils.PVCoordinatesProvider;
41 import org.orekit.utils.TimeStampedFieldPVCoordinates;
42 import org.orekit.utils.TimeStampedPVCoordinates;
43
44
45
46
47
48
49
50
51
52
53
54 public class LofOffsetPointing extends GroundPointing {
55
56
57 private final AttitudeProvider attitudeLaw;
58
59
60 private final BodyShape shape;
61
62
63 private final Vector3D satPointingVector;
64
65
66
67
68
69
70
71
72 public LofOffsetPointing(final Frame inertialFrame, final BodyShape shape,
73 final AttitudeProvider attLaw, final Vector3D satPointingVector) {
74 super(inertialFrame, shape.getBodyFrame());
75 this.shape = shape;
76 this.attitudeLaw = attLaw;
77 this.satPointingVector = satPointingVector;
78 }
79
80
81 @Override
82 public Attitude getAttitude(final PVCoordinatesProvider pvProv,
83 final AbsoluteDate date, final Frame frame) {
84 return attitudeLaw.getAttitude(pvProv, date, frame);
85 }
86
87
88 @Override
89 public <T extends CalculusFieldElement<T>> FieldAttitude<T> getAttitude(final FieldPVCoordinatesProvider<T> pvProv,
90 final FieldAbsoluteDate<T> date, final Frame frame) {
91 return attitudeLaw.getAttitude(pvProv, date, frame);
92 }
93
94
95 public TimeStampedPVCoordinates getTargetPV(final PVCoordinatesProvider pvProv,
96 final AbsoluteDate date, final Frame frame) {
97
98
99 final double h = 0.1;
100 final List<TimeStampedPVCoordinates> sample = new ArrayList<>();
101 Transform centralRefToBody = null;
102 for (int i = -1; i < 2; ++i) {
103
104 final AbsoluteDate shifted = date.shiftedBy(i * h);
105
106
107 final Transform refToSc =
108 new Transform(shifted,
109 new Transform(shifted, pvProv.getPVCoordinates(shifted, frame).negate()),
110 new Transform(shifted, attitudeLaw.getAttitude(pvProv, shifted, frame).getOrientation()));
111
112
113 final Transform refToBody = frame.getTransformTo(shape.getBodyFrame(), shifted);
114 if (i == 0) {
115 centralRefToBody = refToBody;
116 }
117
118 sample.add(losIntersectionWithBody(new Transform(shifted, refToSc.getInverse(), refToBody)));
119
120 }
121
122
123 final TimeStampedPVCoordinates targetBody =
124 TimeStampedPVCoordinates.interpolate(date, CartesianDerivativesFilter.USE_P, sample);
125
126
127 return centralRefToBody.getInverse().transformPVCoordinates(targetBody);
128
129 }
130
131
132 public <T extends CalculusFieldElement<T>> TimeStampedFieldPVCoordinates<T> getTargetPV(final FieldPVCoordinatesProvider<T> pvProv,
133 final FieldAbsoluteDate<T> date,
134 final Frame frame) {
135
136
137 final double h = 0.1;
138 final List<TimeStampedFieldPVCoordinates<T>> sample = new ArrayList<>();
139 FieldTransform<T> centralRefToBody = null;
140 for (int i = -1; i < 2; ++i) {
141
142 final FieldAbsoluteDate<T> shifted = date.shiftedBy(i * h);
143
144
145 final FieldTransform<T> refToSc =
146 new FieldTransform<>(shifted,
147 new FieldTransform<>(shifted, pvProv.getPVCoordinates(shifted, frame).negate()),
148 new FieldTransform<>(shifted, attitudeLaw.getAttitude(pvProv, shifted, frame).getOrientation()));
149
150
151 final FieldTransform<T> refToBody = frame.getTransformTo(shape.getBodyFrame(), shifted);
152 if (i == 0) {
153 centralRefToBody = refToBody;
154 }
155
156 sample.add(losIntersectionWithBody(new FieldTransform<>(shifted, refToSc.getInverse(), refToBody)));
157
158 }
159
160
161 final TimeStampedFieldPVCoordinates<T> targetBody =
162 TimeStampedFieldPVCoordinates.interpolate(date, CartesianDerivativesFilter.USE_P, sample);
163
164
165 return centralRefToBody.getInverse().transformPVCoordinates(targetBody);
166
167 }
168
169
170
171
172
173 private TimeStampedPVCoordinates losIntersectionWithBody(final Transform scToBody) {
174
175
176 final Vector3D pointingBodyFrame = scToBody.transformVector(satPointingVector);
177 final Vector3D pBodyFrame = scToBody.transformPosition(Vector3D.ZERO);
178
179
180
181 final Line pointingLine = new Line(pBodyFrame,
182 pBodyFrame.add(Constants.WGS84_EARTH_EQUATORIAL_RADIUS,
183 pointingBodyFrame),
184 1.0e-10);
185
186
187 final GeodeticPoint gpIntersection =
188 shape.getIntersectionPoint(pointingLine, pBodyFrame, shape.getBodyFrame(), scToBody.getDate());
189 final Vector3D pIntersection =
190 (gpIntersection == null) ? null : shape.transform(gpIntersection);
191
192
193 if (pIntersection == null ||
194 Vector3D.dotProduct(pIntersection.subtract(pBodyFrame), pointingBodyFrame) < 0) {
195 throw new OrekitException(OrekitMessages.ATTITUDE_POINTING_LAW_DOES_NOT_POINT_TO_GROUND);
196 }
197
198 return new TimeStampedPVCoordinates(scToBody.getDate(),
199 pIntersection, Vector3D.ZERO, Vector3D.ZERO);
200
201 }
202
203
204
205
206
207
208 private <T extends CalculusFieldElement<T>> TimeStampedFieldPVCoordinates<T> losIntersectionWithBody(final FieldTransform<T> scToBody) {
209
210
211 final FieldVector3D<T> pointingBodyFrame = scToBody.transformVector(satPointingVector);
212 final FieldVector3D<T> pBodyFrame = scToBody.transformPosition(Vector3D.ZERO);
213
214
215
216 final FieldLine<T> pointingLine = new FieldLine<>(pBodyFrame,
217 pBodyFrame.add(Constants.WGS84_EARTH_EQUATORIAL_RADIUS,
218 pointingBodyFrame),
219 1.0e-10);
220
221
222 final FieldGeodeticPoint<T> gpIntersection =
223 shape.getIntersectionPoint(pointingLine, pBodyFrame, shape.getBodyFrame(), scToBody.getFieldDate());
224 final FieldVector3D<T> pIntersection =
225 (gpIntersection == null) ? null : shape.transform(gpIntersection);
226
227
228 if (pIntersection == null ||
229 FieldVector3D.dotProduct(pIntersection.subtract(pBodyFrame), pointingBodyFrame).getReal() < 0) {
230 throw new OrekitException(OrekitMessages.ATTITUDE_POINTING_LAW_DOES_NOT_POINT_TO_GROUND);
231 }
232
233 final FieldVector3D<T> zero = FieldVector3D.getZero(scToBody.getFieldDate().getField());
234 return new TimeStampedFieldPVCoordinates<>(scToBody.getDate(),
235 pIntersection, zero, zero);
236
237 }
238
239 }