1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.forces.radiation;
18
19 import org.hipparchus.CalculusFieldElement;
20 import org.hipparchus.Field;
21 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
22 import org.hipparchus.geometry.euclidean.threed.Vector3D;
23 import org.hipparchus.ode.events.Action;
24 import org.hipparchus.util.FastMath;
25 import org.orekit.propagation.events.CylindricalShadowEclipseDetector;
26 import org.orekit.propagation.events.EventDetector;
27 import org.orekit.propagation.events.FieldCylindricalShadowEclipseDetector;
28 import org.orekit.propagation.events.FieldEventDetector;
29 import org.orekit.utils.ExtendedPositionProvider;
30
31 import java.util.ArrayList;
32 import java.util.List;
33
34
35
36
37
38
39
40
41
42
43
44 public class CylindricallyShadowedLightFluxModel extends AbstractLightFluxModel {
45
46
47
48
49 private static final double CYLINDRICAL_ECLIPSE_MAX_CHECK = 100;
50
51
52
53
54 private static final double CYLINDRICAL_ECLIPSE_THRESHOLD = 1e-7;
55
56
57
58 private final double occultingBodyRadius;
59
60
61 private final double kRef;
62
63
64
65
66
67
68
69 public CylindricallyShadowedLightFluxModel(final double kRef, final ExtendedPositionProvider occultedBody,
70 final double occultingBodyRadius) {
71 super(occultedBody);
72 this.kRef = kRef;
73 this.occultingBodyRadius = occultingBodyRadius;
74 }
75
76
77
78
79
80
81 public CylindricallyShadowedLightFluxModel(final ExtendedPositionProvider occultedBody,
82 final double occultingBodyRadius) {
83 this(4.56e-6 * FastMath.pow(149597870000.0, 2), occultedBody, occultingBodyRadius);
84 }
85
86
87
88
89
90 public double getOccultingBodyRadius() {
91 return occultingBodyRadius;
92 }
93
94
95 @Override
96 protected Vector3D getUnoccultedFluxVector(final Vector3D relativePosition) {
97 final double squaredRadius = relativePosition.getNormSq();
98 final double factor = kRef / (squaredRadius * FastMath.sqrt(squaredRadius));
99 return relativePosition.scalarMultiply(factor);
100 }
101
102
103 @Override
104 protected <T extends CalculusFieldElement<T>> FieldVector3D<T> getUnoccultedFluxVector(final FieldVector3D<T> relativePosition) {
105 final T squaredRadius = relativePosition.getNormSq();
106 final T factor = (squaredRadius.multiply(squaredRadius.sqrt())).reciprocal().multiply(kRef);
107 return relativePosition.scalarMultiply(factor);
108 }
109
110
111 @Override
112 protected double getLightingRatio(final Vector3D position, final Vector3D occultedBodyPosition) {
113 final Vector3D occultedBodyDirection = occultedBodyPosition.normalize();
114 final double dotProduct = position.dotProduct(occultedBodyDirection);
115 if (dotProduct < 0.) {
116 final double distanceToCylinderAxis = (position.subtract(occultedBodyDirection.scalarMultiply(dotProduct))).getNorm();
117 if (distanceToCylinderAxis <= occultingBodyRadius) {
118 return 0.;
119 }
120 }
121 return 1.;
122 }
123
124
125 @Override
126 protected <T extends CalculusFieldElement<T>> T getLightingRatio(final FieldVector3D<T> position,
127 final FieldVector3D<T> occultedBodyPosition) {
128 final Field<T> field = position.getX().getField();
129 final FieldVector3D<T> occultedBodyDirection = occultedBodyPosition.normalize();
130 final T dotProduct = position.dotProduct(occultedBodyDirection);
131 if (dotProduct.getReal() < 0.) {
132 final T distanceToCylinderAxis = (position.subtract(occultedBodyDirection.scalarMultiply(dotProduct))).getNorm();
133 if (distanceToCylinderAxis.getReal() <= occultingBodyRadius) {
134 return field.getZero();
135 }
136 }
137 return field.getOne();
138 }
139
140
141
142 @Override
143 public List<EventDetector> getEclipseConditionsDetector() {
144 final List<EventDetector> detectors = new ArrayList<>();
145 detectors.add(createCylindricalShadowEclipseDetector()
146 .withThreshold(CYLINDRICAL_ECLIPSE_THRESHOLD).withMaxCheck(CYLINDRICAL_ECLIPSE_MAX_CHECK));
147 return detectors;
148 }
149
150
151
152
153
154 private CylindricalShadowEclipseDetector createCylindricalShadowEclipseDetector() {
155 return new CylindricalShadowEclipseDetector(getOccultedBody(), getOccultingBodyRadius(),
156 (state, detector, increasing) -> Action.RESET_DERIVATIVES);
157 }
158
159
160 @Override
161 public <T extends CalculusFieldElement<T>> List<FieldEventDetector<T>> getFieldEclipseConditionsDetector(final Field<T> field) {
162 final List<FieldEventDetector<T>> detectors = new ArrayList<>();
163 final T threshold = field.getZero().newInstance(CYLINDRICAL_ECLIPSE_THRESHOLD);
164 detectors.add(createFieldCylindricalShadowEclipseDetector(field)
165 .withThreshold(threshold).withMaxCheck(CYLINDRICAL_ECLIPSE_MAX_CHECK));
166 return detectors;
167 }
168
169
170
171
172
173
174
175 private <T extends CalculusFieldElement<T>> FieldCylindricalShadowEclipseDetector<T> createFieldCylindricalShadowEclipseDetector(final Field<T> field) {
176 final T occultingBodyRadiusAsField = field.getZero().newInstance(getOccultingBodyRadius());
177 return new FieldCylindricalShadowEclipseDetector<>(getOccultedBody(), occultingBodyRadiusAsField,
178 (state, detector, increasing) -> Action.RESET_DERIVATIVES);
179 }
180 }