1   /* Copyright 2002-2022 CS GROUP
2    * Licensed to CS GROUP (CS) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * CS licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *   http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.orekit.propagation.events;
18  
19  import org.hipparchus.geometry.euclidean.threed.Line;
20  import org.hipparchus.geometry.euclidean.threed.Vector3D;
21  import org.hipparchus.ode.events.Action;
22  import org.hipparchus.util.FastMath;
23  import org.junit.Assert;
24  import org.junit.Before;
25  import org.junit.Test;
26  import org.orekit.Utils;
27  import org.orekit.bodies.OneAxisEllipsoid;
28  import org.orekit.frames.Frame;
29  import org.orekit.frames.FramesFactory;
30  import org.orekit.frames.TopocentricFrame;
31  import org.orekit.orbits.CircularOrbit;
32  import org.orekit.orbits.PositionAngle;
33  import org.orekit.propagation.Propagator;
34  import org.orekit.propagation.SpacecraftState;
35  import org.orekit.propagation.analytical.KeplerianPropagator;
36  import org.orekit.propagation.events.handlers.EventHandler;
37  import org.orekit.time.AbsoluteDate;
38  import org.orekit.time.TimeScale;
39  import org.orekit.time.TimeScalesFactory;
40  import org.orekit.utils.Constants;
41  import org.orekit.utils.IERSConventions;
42  
43  public class InterSatDirectViewDetectorTest {
44  
45      @Test
46      public void testFormationFlying() {
47          final OneAxisEllipsoid earth = new OneAxisEllipsoid(Constants.WGS84_EARTH_EQUATORIAL_RADIUS,
48                                                              Constants.WGS84_EARTH_FLATTENING,
49                                                              FramesFactory.getITRF(IERSConventions.IERS_2010, true));
50          final TimeScale utc = TimeScalesFactory.getUTC();
51          final CircularOrbit o1 = new CircularOrbit(7200000.0, 1.0e-3, 2.0e-4,
52                                                     FastMath.toRadians(98.7), FastMath.toRadians(134.0),
53                                                     FastMath.toRadians(21.0), PositionAngle.MEAN, FramesFactory.getGCRF(),
54                                                     new AbsoluteDate("2003-02-14T01:02:03.000", utc),
55                                                     Constants.EIGEN5C_EARTH_MU);
56          final CircularOrbit o2 = new CircularOrbit(o1.getA(), 2.0e-4, 1.0e-3,
57                                                     o1.getI() + 1.0e-6, o1.getRightAscensionOfAscendingNode() - 3.5e-7,
58                                                     o1.getAlphaM() + 2.2e-6, PositionAngle.MEAN, o1.getFrame(),
59                                                     o1.getDate(),
60                                                     Constants.EIGEN5C_EARTH_MU);
61          Assert.assertEquals(o1.getKeplerianPeriod(), o2.getKeplerianPeriod(), 1.0e-10);
62          final Propagator p = new KeplerianPropagator(o1);
63          final EventsLogger logger = new EventsLogger();
64          p.addEventDetector(logger.monitorDetector(new InterSatDirectViewDetector(earth, o2).
65                                                    withMaxCheck(60.0)));
66          p.setStepHandler(10.0, state -> {
67              Vector3D pos1 = state.getPVCoordinates().getPosition();
68              Vector3D pos2 = o2.getPVCoordinates(state.getDate(), state.getFrame()).getPosition();
69              Assert.assertTrue(Vector3D.distance(pos1, pos2) >  8100.0);
70              Assert.assertTrue(Vector3D.distance(pos1, pos2) < 16400.0);
71          });
72          p.propagate(o1.getDate().shiftedBy(o1.getKeplerianPeriod()));
73          Assert.assertEquals(0, logger.getLoggedEvents().size());
74      }
75  
76      @Test
77      public void testLeoMeo() {
78          OneAxisEllipsoid earth = new OneAxisEllipsoid(Constants.WGS84_EARTH_EQUATORIAL_RADIUS,
79                                                        Constants.WGS84_EARTH_FLATTENING,
80                                                        FramesFactory.getITRF(IERSConventions.IERS_2010, true));
81          TimeScale utc = TimeScalesFactory.getUTC();
82          CircularOrbit o1 = new CircularOrbit(7200000.0, 1.0e-3, 2.0e-4,
83                                               FastMath.toRadians(50.0), FastMath.toRadians(134.0),
84                                               FastMath.toRadians(21.0), PositionAngle.MEAN, FramesFactory.getGCRF(),
85                                               new AbsoluteDate("2003-02-14T01:02:03.000", utc),
86                                               Constants.EIGEN5C_EARTH_MU);
87          final CircularOrbit o2 = new CircularOrbit(29600000.0, 2.0e-4, 1.0e-3,
88                                                     FastMath.toRadians(56.0), FastMath.toRadians(111.0),
89                                                     o1.getAlphaM() + 2.2e-6, PositionAngle.MEAN, o1.getFrame(),
90                                                     o1.getDate(),
91                                                     Constants.EIGEN5C_EARTH_MU);
92  
93          // LEO as primary, MEO as secondary
94          Propagator pA = new KeplerianPropagator(o1);
95          EventsLogger loggerA = new EventsLogger();
96          pA.addEventDetector(loggerA.monitorDetector(new InterSatDirectViewDetector(earth, o2).
97                                                    withMaxCheck(10.0).
98                                                    withHandler(new GrazingHandler())));
99          pA.propagate(o1.getDate().shiftedBy(4 * o1.getKeplerianPeriod()));
100         Assert.assertEquals(7, loggerA.getLoggedEvents().size());
101 
102         // LEO as secondary, MEO as primary
103         Propagator pB = new KeplerianPropagator(o2);
104         EventsLogger loggerB = new EventsLogger();
105         pB.addEventDetector(loggerB.monitorDetector(new InterSatDirectViewDetector(earth, o1).
106                                                   withMaxCheck(10.0).
107                                                   withHandler(new GrazingHandler())));
108         pB.propagate(o1.getDate().shiftedBy(4 * o1.getKeplerianPeriod()));
109         Assert.assertEquals(7, loggerB.getLoggedEvents().size());
110 
111     }
112 
113     private static class GrazingHandler implements EventHandler<InterSatDirectViewDetector> {
114         public Action eventOccurred(SpacecraftState s, InterSatDirectViewDetector detector, boolean increasing) {
115             // just before increasing events and just after decreasing events,
116             // the primary/secondary line intersects Earth limb
117             final OneAxisEllipsoid earth       = detector.getCentralBody();
118             final Frame            frame       = earth.getBodyFrame();
119             final double           dt          = increasing ? -1.0e-8 : +1.0e-8;
120             final AbsoluteDate     grazingDate = s.getDate().shiftedBy(dt);
121             final Vector3D pPrimary = s.shiftedBy(dt).
122                                      getPVCoordinates(frame).
123                                      getPosition();
124             final Vector3D psecondary  = detector.getSecondary().getPVCoordinates(grazingDate, frame).
125                                      getPosition();
126             final Vector3D grazing = earth.getCartesianIntersectionPoint(new Line(pPrimary,  psecondary, 1.0),
127                                                                          pPrimary, frame, grazingDate);
128             final TopocentricFrame topo = new TopocentricFrame(earth, earth.transform(grazing, frame, grazingDate),
129                                                                "grazing");
130             Assert.assertEquals(  0.0, FastMath.toDegrees(topo.getElevation(pPrimary, frame, grazingDate)), 2.0e-4);
131             Assert.assertEquals(  0.0, FastMath.toDegrees(topo.getElevation(psecondary,  frame, grazingDate)), 2.0e-4);
132             Assert.assertEquals(180.0,
133                                 FastMath.abs(FastMath.toDegrees(topo.getAzimuth(psecondary,  frame, grazingDate) -
134                                                                 topo.getAzimuth(pPrimary, frame, grazingDate))),
135                                 6.0e-14);
136             return Action.CONTINUE;
137         }
138     }
139 
140     @Before
141     public void setUp() {
142         Utils.setDataRoot("regular-data");
143     }
144 
145 }
146