1   /* Copyright 2022-2025 Luc Maisonobe
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.orbits;
18  
19  import java.util.List;
20  
21  import org.hipparchus.util.FastMath;
22  import org.hipparchus.util.MathUtils;
23  import org.junit.jupiter.api.Assertions;
24  import org.junit.jupiter.api.BeforeEach;
25  import org.junit.jupiter.api.Test;
26  import org.orekit.Utils;
27  import org.orekit.errors.OrekitException;
28  import org.orekit.errors.OrekitMessages;
29  import org.orekit.frames.FramesFactory;
30  import org.orekit.orbits.WalkerConstellation.Pattern;
31  import org.orekit.time.AbsoluteDate;
32  import org.orekit.utils.Constants;
33  
34  public class WalkerConstellationTest {
35  
36      @Test
37      public void testContainer() {
38          final WalkerConstellation w = new WalkerConstellation(60, 15, 1);
39          Assertions.assertEquals(60, w.getT());
40          Assertions.assertEquals(15, w.getP());
41          Assertions.assertEquals( 1, w.getF());
42          Assertions.assertEquals(Pattern.DELTA, w.getPattern());
43      }
44      @Test
45      public void testInconsistentPlanes() {
46          try {
47              new WalkerConstellation(60, 14, 1);
48              Assertions.fail("an exception should have been thrown");
49          } catch (OrekitException oe) {
50              Assertions.assertEquals(OrekitMessages.WALKER_INCONSISTENT_PLANES, oe.getSpecifier());
51              Assertions.assertEquals(14, ((Integer) oe.getParts()[0]).intValue());
52              Assertions.assertEquals(60, ((Integer) oe.getParts()[1]).intValue());
53          }
54      }
55  
56      @Test
57      public void testDeltaRegularPhasing() {
58          final CircularOrbit reference = new CircularOrbit(29600000.0, 1.0e-3, 1.2e-4,
59                                                            FastMath.toRadians(56.0), FastMath.toRadians(0),
60                                                            FastMath.toRadians(0), PositionAngleType.MEAN,
61                                                            FramesFactory.getEME2000(),
62                                                            AbsoluteDate.J2000_EPOCH,
63                                                            Constants.EIGEN5C_EARTH_MU);
64          final WalkerConstellation w = new WalkerConstellation(24, 3, 1);
65          final List<List<WalkerConstellationSlot<CircularOrbit>>> all = w.buildRegularSlots(reference);
66          Assertions.assertEquals(3, all.size());
67          for (int i = 0; i < 3; ++i) {
68              final List<WalkerConstellationSlot<CircularOrbit>> l = all.get(i);
69              Assertions.assertEquals(8, l.size());
70              for (int j = 0; j < 8; ++j) {
71                  final WalkerConstellationSlot<CircularOrbit> s = l.get(j);
72                  Assertions.assertSame(w, s.getConstellation());
73                  Assertions.assertEquals(i, s.getPlane());
74                  Assertions.assertEquals(j, s.getSatellite(), 1.0e-15);
75                  final CircularOrbit c = s.getOrbit();
76                  Assertions.assertEquals(reference.getA(),          c.getA(),          4.0e-8);
77                  Assertions.assertEquals(reference.getCircularEx(), c.getCircularEx(), 1.0e-15);
78                  Assertions.assertEquals(reference.getCircularEy(), c.getCircularEy(), 1.0e-15);
79                  Assertions.assertEquals(FastMath.toDegrees(reference.getI()),
80                                          FastMath.toDegrees(c.getI()),
81                                          1.0e-14);
82                  Assertions.assertEquals(i * 120.0,
83                                          FastMath.toDegrees(MathUtils.normalizeAngle(c.getRightAscensionOfAscendingNode(),
84                                                                                      FastMath.PI)),
85                                          9.0e-14);
86                  Assertions.assertEquals(i * 15.0 + j * 45.0,
87                                          FastMath.toDegrees(
88                                              MathUtils.normalizeAngle(c.getAlphaM(), FastMath.PI)),
89                                          6.0e-14);
90              }
91          }
92      }
93  
94      @Test
95      public void testDeltaInOrbitSpares() {
96          final CircularOrbit reference = new CircularOrbit(29600000.0, 1.0e-3, 1.2e-4,
97                                                            FastMath.toRadians(56.0), FastMath.toRadians(0),
98                                                            FastMath.toRadians(0), PositionAngleType.MEAN,
99                                                            FramesFactory.getEME2000(),
100                                                           AbsoluteDate.J2000_EPOCH,
101                                                           Constants.EIGEN5C_EARTH_MU);
102         final WalkerConstellation w = new WalkerConstellation(24, 3, 1);
103         final List<List<WalkerConstellationSlot<CircularOrbit>>> regular = w.buildRegularSlots(reference);
104         Assertions.assertEquals(3, regular.size());
105         final WalkerConstellationSlot<CircularOrbit> slot00 = regular.get(0).get(0);
106 
107         final WalkerConstellationSlot<CircularOrbit> spare0 = w.buildSlot(slot00, 0, 4.5);
108         Assertions.assertEquals(0,   spare0.getPlane());
109         Assertions.assertEquals(4.5, spare0.getSatellite(), 1.0e-15);
110         Assertions.assertEquals(reference.getA(),          spare0.getOrbit().getA(),          4.0e-8);
111         Assertions.assertEquals(reference.getCircularEx(), spare0.getOrbit().getCircularEx(), 1.0e-15);
112         Assertions.assertEquals(reference.getCircularEy(), spare0.getOrbit().getCircularEy(), 1.0e-15);
113         Assertions.assertEquals(FastMath.toDegrees(reference.getI()),
114                                 FastMath.toDegrees(spare0.getOrbit().getI()),
115                                 1.0e-14);
116         Assertions.assertEquals(0.0,
117                                 FastMath.toDegrees(MathUtils.normalizeAngle(spare0.getOrbit().getRightAscensionOfAscendingNode(),
118                                                                             FastMath.PI)),
119                                 9.0e-14);
120         Assertions.assertEquals(202.5,
121                                 FastMath.toDegrees(MathUtils.normalizeAngle(spare0.getOrbit().getAlphaM(), FastMath.PI)),
122                                 6.0e-14);
123 
124         final WalkerConstellationSlot<CircularOrbit> spare1 = w.buildSlot(slot00, 1, 3.5);
125         Assertions.assertEquals(1,   spare1.getPlane());
126         Assertions.assertEquals(3.5, spare1.getSatellite(), 1.0e-15);
127         Assertions.assertEquals(reference.getA(),          spare1.getOrbit().getA(),          4.0e-8);
128         Assertions.assertEquals(reference.getCircularEx(), spare1.getOrbit().getCircularEx(), 1.0e-15);
129         Assertions.assertEquals(reference.getCircularEy(), spare1.getOrbit().getCircularEy(), 1.0e-15);
130         Assertions.assertEquals(FastMath.toDegrees(reference.getI()),
131                                 FastMath.toDegrees(spare1.getOrbit().getI()),
132                                 1.0e-14);
133         Assertions.assertEquals(120.0,
134                                 FastMath.toDegrees(MathUtils.normalizeAngle(spare1.getOrbit().getRightAscensionOfAscendingNode(),
135                                                                             FastMath.PI)),
136                                 9.0e-14);
137         Assertions.assertEquals(172.5,
138                                 FastMath.toDegrees(MathUtils.normalizeAngle(spare1.getOrbit().getAlphaM(), FastMath.PI)),
139                                 6.0e-14);
140 
141         final WalkerConstellationSlot<CircularOrbit> spare2 = w.buildSlot(slot00, 2, 1.5);
142         Assertions.assertEquals(2,   spare2.getPlane());
143         Assertions.assertEquals(1.5, spare2.getSatellite(), 1.0e-15);
144         Assertions.assertEquals(reference.getA(),          spare2.getOrbit().getA(),          4.0e-8);
145         Assertions.assertEquals(reference.getCircularEx(), spare2.getOrbit().getCircularEx(), 1.0e-15);
146         Assertions.assertEquals(reference.getCircularEy(), spare2.getOrbit().getCircularEy(), 1.0e-15);
147         Assertions.assertEquals(FastMath.toDegrees(reference.getI()),
148                                 FastMath.toDegrees(spare2.getOrbit().getI()),
149                                 1.0e-14);
150         Assertions.assertEquals(240.0,
151                                 FastMath.toDegrees(MathUtils.normalizeAngle(spare2.getOrbit().getRightAscensionOfAscendingNode(),
152                                                                             FastMath.PI)),
153                                 9.0e-14);
154         Assertions.assertEquals(97.5,
155                                 FastMath.toDegrees(MathUtils.normalizeAngle(spare2.getOrbit().getAlphaM(), FastMath.PI)),
156                                 6.0e-14);
157     }
158 
159     @Test
160     public void testStarRegularPhasing() {
161         final CircularOrbit reference = new CircularOrbit(7200000.0, -5.0e-4, 1.2e-3,
162                                                           FastMath.toRadians(98.7), FastMath.toRadians(0.),
163                                                           FastMath.toRadians(0.0), PositionAngleType.MEAN,
164                                                           FramesFactory.getEME2000(),
165                                                           AbsoluteDate.J2000_EPOCH,
166                                                           Constants.EIGEN5C_EARTH_MU);
167         final WalkerConstellation w = new WalkerConstellation(24, 3, 1, Pattern.STAR);
168         final List<List<WalkerConstellationSlot<CircularOrbit>>> all = w.buildRegularSlots(reference);
169         Assertions.assertEquals(3, all.size());
170         for (int i = 0; i < 3; ++i) {
171             final List<WalkerConstellationSlot<CircularOrbit>> l = all.get(i);
172             Assertions.assertEquals(8, l.size());
173             for (int j = 0; j < 8; ++j) {
174                 final WalkerConstellationSlot<CircularOrbit> s = l.get(j);
175                 Assertions.assertSame(w, s.getConstellation());
176                 Assertions.assertEquals(i, s.getPlane());
177                 Assertions.assertEquals(j, s.getSatellite(), 1.0e-15);
178                 final CircularOrbit c = s.getOrbit();
179                 Assertions.assertEquals(reference.getA(),          c.getA(),          4.0e-8);
180                 Assertions.assertEquals(reference.getCircularEx(), c.getCircularEx(), 1.0e-15);
181                 Assertions.assertEquals(reference.getCircularEy(), c.getCircularEy(), 1.0e-15);
182                 Assertions.assertEquals(FastMath.toDegrees(reference.getI()),
183                                         FastMath.toDegrees(c.getI()),
184                                         1.0e-14);
185                 Assertions.assertEquals(i * 60.0,
186                                         FastMath.toDegrees(MathUtils.normalizeAngle(c.getRightAscensionOfAscendingNode(),
187                                                                                     FastMath.PI)),
188                                         9.0e-14);
189                 Assertions.assertEquals(i * 15.0 + j * 45.0,
190                                         FastMath.toDegrees(
191                                             MathUtils.normalizeAngle(c.getAlphaM(), FastMath.PI)),
192                                         6.e-13);
193             }
194         }
195     }
196 
197     @Test
198     public void testStarInOrbitSpares() {
199         final CircularOrbit reference = new CircularOrbit(7200000.0, -5.0e-4, 1.2e-3,
200                                                           FastMath.toRadians(98.7), FastMath.toRadians(0.),
201                                                           FastMath.toRadians(0.0), PositionAngleType.MEAN,
202                                                           FramesFactory.getEME2000(),
203                                                           AbsoluteDate.J2000_EPOCH,
204                                                           Constants.EIGEN5C_EARTH_MU);
205         final WalkerConstellation w = new WalkerConstellation(24, 3, 1, Pattern.STAR);
206         final List<List<WalkerConstellationSlot<CircularOrbit>>> regular = w.buildRegularSlots(reference);
207         Assertions.assertEquals(3, regular.size());
208         final WalkerConstellationSlot<CircularOrbit> slot00 = regular.get(0).get(0);
209 
210         final WalkerConstellationSlot<CircularOrbit> spare0 = w.buildSlot(slot00, 0, 4.5);
211         Assertions.assertEquals(0,   spare0.getPlane());
212         Assertions.assertEquals(4.5, spare0.getSatellite(), 1.0e-15);
213         Assertions.assertEquals(reference.getA(),          spare0.getOrbit().getA(),          4.0e-8);
214         Assertions.assertEquals(reference.getCircularEx(), spare0.getOrbit().getCircularEx(), 1.0e-15);
215         Assertions.assertEquals(reference.getCircularEy(), spare0.getOrbit().getCircularEy(), 1.0e-15);
216         Assertions.assertEquals(FastMath.toDegrees(reference.getI()),
217                                 FastMath.toDegrees(spare0.getOrbit().getI()),
218                                 1.0e-14);
219         Assertions.assertEquals(0.0,
220                                 FastMath.toDegrees(MathUtils.normalizeAngle(spare0.getOrbit().getRightAscensionOfAscendingNode(),
221                                                                             FastMath.PI)),
222                                 9.0e-14);
223         Assertions.assertEquals(202.5,
224                                 FastMath.toDegrees(MathUtils.normalizeAngle(spare0.getOrbit().getAlphaM(), FastMath.PI)),
225                                 6.0e-14);
226 
227         final WalkerConstellationSlot<CircularOrbit> spare1 = w.buildSlot(slot00, 1, 3.5);
228         Assertions.assertEquals(1,   spare1.getPlane());
229         Assertions.assertEquals(3.5, spare1.getSatellite(), 1.0e-15);
230         Assertions.assertEquals(reference.getA(),          spare1.getOrbit().getA(),          4.0e-8);
231         Assertions.assertEquals(reference.getCircularEx(), spare1.getOrbit().getCircularEx(), 1.0e-15);
232         Assertions.assertEquals(reference.getCircularEy(), spare1.getOrbit().getCircularEy(), 1.0e-15);
233         Assertions.assertEquals(FastMath.toDegrees(reference.getI()),
234                                 FastMath.toDegrees(spare1.getOrbit().getI()),
235                                 1.0e-14);
236         Assertions.assertEquals(60.0,
237                                 FastMath.toDegrees(MathUtils.normalizeAngle(spare1.getOrbit().getRightAscensionOfAscendingNode(),
238                                                                             FastMath.PI)),
239                                 9.0e-14);
240         Assertions.assertEquals(172.5,
241                                 FastMath.toDegrees(MathUtils.normalizeAngle(spare1.getOrbit().getAlphaM(), FastMath.PI)),
242                                 6.0e-14);
243 
244         final WalkerConstellationSlot<CircularOrbit> spare2 = w.buildSlot(slot00, 2, 1.5);
245         Assertions.assertEquals(2,   spare2.getPlane());
246         Assertions.assertEquals(1.5, spare2.getSatellite(), 1.0e-15);
247         Assertions.assertEquals(reference.getA(),          spare2.getOrbit().getA(),          4.0e-8);
248         Assertions.assertEquals(reference.getCircularEx(), spare2.getOrbit().getCircularEx(), 1.0e-15);
249         Assertions.assertEquals(reference.getCircularEy(), spare2.getOrbit().getCircularEy(), 1.0e-15);
250         Assertions.assertEquals(FastMath.toDegrees(reference.getI()),
251                                 FastMath.toDegrees(spare2.getOrbit().getI()),
252                                 1.0e-14);
253         Assertions.assertEquals(120.0,
254                                 FastMath.toDegrees(MathUtils.normalizeAngle(spare2.getOrbit().getRightAscensionOfAscendingNode(),
255                                                                             FastMath.PI)),
256                                 9.0e-14);
257         Assertions.assertEquals(97.5,
258                                 FastMath.toDegrees(MathUtils.normalizeAngle(spare2.getOrbit().getAlphaM(), FastMath.PI)),
259                                 6.0e-14);
260     }
261 
262     @BeforeEach
263     public void setUp() {
264         Utils.setDataRoot("regular-data");
265     }
266 }