1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.orekit.bodies;
19
20 import org.hipparchus.CalculusFieldElement;
21 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
22 import org.hipparchus.geometry.euclidean.threed.Vector3D;
23 import org.hipparchus.util.FastMath;
24 import org.hipparchus.util.FieldSinCos;
25 import org.hipparchus.util.SinCos;
26 import org.orekit.annotation.DefaultDataContext;
27 import org.orekit.data.DataContext;
28 import org.orekit.frames.Frame;
29 import org.orekit.frames.FieldStaticTransform;
30 import org.orekit.frames.StaticTransform;
31 import org.orekit.time.AbsoluteDate;
32 import org.orekit.time.FieldAbsoluteDate;
33 import org.orekit.time.TimeScale;
34 import org.orekit.utils.ExtendedPositionProvider;
35
36
37
38
39
40
41
42
43
44 public class AnalyticalSolarPositionProvider implements ExtendedPositionProvider {
45
46
47 private static final SinCos SIN_COS_ECLIPTIC_ANGLE_EME2000 = FastMath.sinCos(FastMath.toRadians(23.43929111));
48
49
50 private static final double INTERMEDIATE_ANGLE = FastMath.toRadians(282.9400);
51
52
53 private final Frame eme2000;
54
55
56 private final TimeScale timeScale;
57
58
59
60
61
62 public AnalyticalSolarPositionProvider(final DataContext dataContext) {
63 this.eme2000 = dataContext.getFrames().getEME2000();
64 this.timeScale = dataContext.getTimeScales().getUTC();
65 }
66
67
68
69
70 @DefaultDataContext
71 public AnalyticalSolarPositionProvider() {
72 this(DataContext.getDefault());
73 }
74
75
76 @Override
77 public Vector3D getPosition(final AbsoluteDate date, final Frame frame) {
78 final Vector3D eme2000Position = getEME2000Position(date);
79 if (frame.equals(eme2000)) {
80 return eme2000Position;
81 } else {
82 final StaticTransform transform = eme2000.getStaticTransformTo(frame, date);
83 return transform.transformPosition(eme2000Position);
84 }
85 }
86
87
88
89
90
91
92 private Vector3D getEME2000Position(final AbsoluteDate date) {
93 final double tt = (date.getJD(timeScale) - 2451545.0) / 36525.0;
94 final double M = FastMath.toRadians(357.5256 + 35999.049 * tt);
95 final SinCos sinCosM = FastMath.sinCos(M);
96 final SinCos sinCos2M = FastMath.sinCos(2 * M);
97 final double r = (149.619 - 2.499 * sinCosM.cos() - 0.021 * sinCos2M.cos()) * 1.0e9;
98 final double lambda = INTERMEDIATE_ANGLE + M + FastMath.toRadians(6892.0 * sinCosM.sin() + 72.0 * sinCos2M.sin()) / 3600.0;
99 final SinCos sinCosLambda = FastMath.sinCos(lambda);
100 return new Vector3D(r * sinCosLambda.cos(), r * sinCosLambda.sin() * SIN_COS_ECLIPTIC_ANGLE_EME2000.cos(),
101 r * sinCosLambda.sin() * SIN_COS_ECLIPTIC_ANGLE_EME2000.sin());
102 }
103
104
105 @Override
106 public <T extends CalculusFieldElement<T>> FieldVector3D<T> getPosition(final FieldAbsoluteDate<T> date,
107 final Frame frame) {
108 final FieldVector3D<T> eme2000Position = getFieldEME2000Position(date);
109 if (frame.equals(eme2000)) {
110 return eme2000Position;
111 } else {
112 final FieldStaticTransform<T> transform = eme2000.getStaticTransformTo(frame, date);
113 return transform.transformPosition(eme2000Position);
114 }
115 }
116
117
118
119
120
121
122
123 private <T extends CalculusFieldElement<T>> FieldVector3D<T> getFieldEME2000Position(final FieldAbsoluteDate<T> date) {
124 final T tt = date.getJD(timeScale).subtract(2451545.0).divide(36525.0);
125 final T M = FastMath.toRadians(tt.multiply(35999.049).add(357.5256));
126 final FieldSinCos<T> sinCosM = FastMath.sinCos(M);
127 final FieldSinCos<T> sinCos2M = FastMath.sinCos(M.multiply(2));
128 final T r = (sinCosM.cos().multiply(-2.499).subtract(sinCos2M.cos().multiply(0.021)).add(149.619)).multiply(1.0e9);
129 final T lambda = M.add(INTERMEDIATE_ANGLE).add(FastMath.toRadians(
130 sinCosM.sin().multiply(6892.0).add(sinCos2M.sin().multiply(72.0)).divide(3600.0)));
131 final FieldSinCos<T> sinCosLambda = FastMath.sinCos(lambda);
132 return new FieldVector3D<>(r.multiply(sinCosLambda.cos()),
133 r.multiply(sinCosLambda.sin()).multiply(SIN_COS_ECLIPTIC_ANGLE_EME2000.cos()),
134 r.multiply(sinCosLambda.sin()).multiply(SIN_COS_ECLIPTIC_ANGLE_EME2000.sin()));
135 }
136 }