1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.geometry.fov;
18
19 import org.hipparchus.geometry.euclidean.threed.Vector3D;
20 import org.hipparchus.random.RandomGenerator;
21 import org.hipparchus.random.UnitSphereRandomVectorGenerator;
22 import org.hipparchus.util.FastMath;
23 import org.junit.jupiter.api.AfterEach;
24 import org.junit.jupiter.api.Assertions;
25 import org.junit.jupiter.api.BeforeEach;
26 import org.orekit.Utils;
27 import org.orekit.attitudes.AttitudeProvider;
28 import org.orekit.bodies.GeodeticPoint;
29 import org.orekit.bodies.OneAxisEllipsoid;
30 import org.orekit.errors.OrekitException;
31 import org.orekit.errors.OrekitMessages;
32 import org.orekit.frames.FramesFactory;
33 import org.orekit.frames.TopocentricFrame;
34 import org.orekit.frames.Transform;
35 import org.orekit.orbits.KeplerianOrbit;
36 import org.orekit.orbits.Orbit;
37 import org.orekit.propagation.Propagator;
38 import org.orekit.propagation.SpacecraftState;
39 import org.orekit.propagation.analytical.KeplerianPropagator;
40 import org.orekit.propagation.events.VisibilityTrigger;
41 import org.orekit.time.AbsoluteDate;
42 import org.orekit.utils.Constants;
43 import org.orekit.utils.IERSConventions;
44 import org.orekit.utils.PVCoordinates;
45
46 import java.util.List;
47
48 public abstract class AbstractSmoothFieldOfViewTest {
49
50 protected void doTestFOVAwayFromEarth(final SmoothFieldOfView fov, final AttitudeProvider attitude,
51 final Vector3D expectedCenter) {
52 Assertions.assertEquals(0.0, Vector3D.distance(expectedCenter, fov.getCenter()), 1.0e-15);
53 Propagator propagator = new KeplerianPropagator(orbit);
54 propagator.setAttitudeProvider(attitude);
55 SpacecraftState state = propagator.propagate(orbit.getDate().shiftedBy(1000.0));
56 Transform inertToBody = state.getFrame().getTransformTo(earth.getBodyFrame(), state.getDate());
57 Transform fovToBody = new Transform(state.getDate(),
58 state.toTransform().getInverse(),
59 inertToBody);
60 List<List<GeodeticPoint>> footprint = fov.getFootprint(fovToBody, earth, FastMath.toRadians(0.1));
61 Assertions.assertTrue(footprint.isEmpty());
62 }
63
64 protected void doTestNoFootprintInside(final SmoothFieldOfView fov, final Transform fovToBody) {
65 try {
66 fov.getFootprint(fovToBody, earth, FastMath.toRadians(0.1));
67 Assertions.fail("an exception should have been thrown");
68 } catch (OrekitException oe) {
69 Assertions.assertEquals(OrekitMessages.POINT_INSIDE_ELLIPSOID, oe.getSpecifier());
70 }
71 }
72
73 protected void doTestFootprint(final SmoothFieldOfView fov, final AttitudeProvider attitude,
74 final double expectedMinOffset, final double expectedMaxOffset,
75 final double expectedMinElevation, final double expectedMaxElevation,
76 final double expectedMinDist, final double expectedMaxDist) {
77
78 Propagator propagator = new KeplerianPropagator(orbit);
79 propagator.setAttitudeProvider(attitude);
80 SpacecraftState state = propagator.propagate(orbit.getDate().shiftedBy(1000.0));
81 Transform inertToBody = state.getFrame().getTransformTo(earth.getBodyFrame(), state.getDate());
82 Transform fovToBody = new Transform(state.getDate(),
83 state.toTransform().getInverse(),
84 inertToBody);
85 List<List<GeodeticPoint>> footprint = fov.getFootprint(fovToBody, earth, FastMath.toRadians(0.1));
86 Vector3D subSat = earth.projectToGround(state.getPosition(earth.getBodyFrame()),
87 state.getDate(), earth.getBodyFrame());
88 Assertions.assertEquals(1, footprint.size());
89 List<GeodeticPoint> loop = footprint.get(0);
90 double minOffset = Double.POSITIVE_INFINITY;
91 double maxOffset = 0;
92 double minEl = Double.POSITIVE_INFINITY;
93 double maxEl = 0;
94 double minDist = Double.POSITIVE_INFINITY;
95 double maxDist = 0;
96 for (int i = 0; i < loop.size(); ++i) {
97
98 Assertions.assertEquals(0.0, loop.get(i).getAltitude(), 9.0e-9);
99
100 Vector3D los = fovToBody.getStaticInverse().transformPosition(earth.transform(loop.get(i)));
101 double offset = Vector3D.angle(fov.getCenter(), los);
102 minOffset = FastMath.min(minOffset, offset);
103 maxOffset = FastMath.max(maxOffset, offset);
104
105 TopocentricFrame topo = new TopocentricFrame(earth, loop.get(i), "onFootprint");
106 final double elevation = topo.getTrackingCoordinates(state.getPosition(),
107 state.getFrame(),
108 state.getDate()).
109 getElevation();
110 if (elevation > 0.001) {
111 Assertions.assertEquals(-fov.getMargin(),
112 fov.offsetFromBoundary(los, 0.0, VisibilityTrigger.VISIBLE_ONLY_WHEN_FULLY_IN_FOV),
113 2.0e-10);
114 Assertions.assertEquals(0.1 - fov.getMargin(),
115 fov.offsetFromBoundary(los, 0.1, VisibilityTrigger.VISIBLE_ONLY_WHEN_FULLY_IN_FOV),
116 2.0e-10);
117 Assertions.assertEquals(-0.1 - fov.getMargin(),
118 fov.offsetFromBoundary(los, 0.1, VisibilityTrigger.VISIBLE_AS_SOON_AS_PARTIALLY_IN_FOV),
119 2.0e-10);
120 }
121 minEl = FastMath.min(minEl, elevation);
122 maxEl = FastMath.max(maxEl, elevation);
123 final double dist = Vector3D.distance(subSat, earth.transform(loop.get(i)));
124 minDist = FastMath.min(minDist, dist);
125 maxDist = FastMath.max(maxDist, dist);
126
127 }
128
129 Assertions.assertEquals(expectedMinOffset, FastMath.toDegrees(minOffset), 0.001);
130 Assertions.assertEquals(expectedMaxOffset, FastMath.toDegrees(maxOffset), 0.001);
131 Assertions.assertEquals(expectedMinElevation, FastMath.toDegrees(minEl), 0.001);
132 Assertions.assertEquals(expectedMaxElevation, FastMath.toDegrees(maxEl), 0.001);
133 Assertions.assertEquals(expectedMinDist, minDist, 1.0);
134 Assertions.assertEquals(expectedMaxDist, maxDist, 1.0);
135
136 }
137
138 protected void doTestBoundary(final SmoothFieldOfView fov, final RandomGenerator random,
139 final double tol) {
140 UnitSphereRandomVectorGenerator spGenerator = new UnitSphereRandomVectorGenerator(3, random);
141 for (int i = 0; i < 1000; ++i) {
142 Vector3D queryLOS = new Vector3D(spGenerator.nextVector());
143 Vector3D closest = fov.projectToBoundary(queryLOS);
144 Assertions.assertEquals(-fov.getMargin(),
145 fov.offsetFromBoundary(closest, 0, VisibilityTrigger.VISIBLE_ONLY_WHEN_FULLY_IN_FOV),
146 tol);
147 }
148 }
149
150 @BeforeEach
151 public void setUp() {
152 Utils.setDataRoot("regular-data");
153 earth = new OneAxisEllipsoid(Constants.WGS84_EARTH_EQUATORIAL_RADIUS,
154 Constants.WGS84_EARTH_FLATTENING,
155 FramesFactory.getITRF(IERSConventions.IERS_2010, true));
156 orbit = new KeplerianOrbit(new PVCoordinates(new Vector3D(7.0e6, 1.0e6, 4.0e6),
157 new Vector3D(-500.0, 8000.0, 1000.0)),
158 FramesFactory.getEME2000(), AbsoluteDate.J2000_EPOCH,
159 Constants.EIGEN5C_EARTH_MU);
160 }
161
162 @AfterEach
163 public void tearDown() {
164 earth = null;
165 orbit = null;
166 }
167
168 protected OneAxisEllipsoid earth;
169 protected Orbit orbit;
170
171 }