1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.frames;
18
19 import org.hipparchus.random.RandomGenerator;
20 import org.hipparchus.random.Well19937a;
21 import org.junit.jupiter.api.AfterEach;
22 import org.junit.jupiter.api.Assertions;
23 import org.junit.jupiter.api.BeforeEach;
24 import org.junit.jupiter.api.Test;
25 import org.orekit.Utils;
26 import org.orekit.time.AbsoluteDate;
27 import org.orekit.utils.Constants;
28 import org.orekit.utils.IERSConventions;
29
30 import java.util.ArrayList;
31 import java.util.List;
32 import java.util.concurrent.Callable;
33 import java.util.concurrent.ExecutionException;
34 import java.util.concurrent.ExecutorService;
35 import java.util.concurrent.Executors;
36 import java.util.concurrent.Future;
37
38 public class CachedTransformProviderTest {
39
40 private Frame inertialFrame;
41 private CountingFrame earth1;
42 private CountingFrame earth2;
43
44 @Test
45 public void testSingleThread() {
46 final CachedTransformProvider cachedTransformProvider = buildCache(20);
47 Assertions.assertSame(earth1, cachedTransformProvider.getOrigin());
48 Assertions.assertSame(inertialFrame, cachedTransformProvider.getDestination());
49 Assertions.assertEquals(20, cachedTransformProvider.getCacheSize());
50 final List<AbsoluteDate> dates = generateDates(new Well19937a(0x03fb4b0832dadcbe2L), 50, 5);
51 for (final AbsoluteDate date : dates) {
52 final Transform transform1 = cachedTransformProvider.getTransform(date);
53 final Transform transform2 = earth2.getTransformTo(inertialFrame, date);
54 final Transform backAndForth = new Transform(date, transform1, transform2.getInverse());
55 Assertions.assertEquals(0.0, backAndForth.getRotation().getAngle(), 3.0e-15);
56 }
57 Assertions.assertEquals(10, earth1.count);
58 Assertions.assertEquals(dates.size(), earth2.count);
59 }
60
61 @Test
62 public void testSingleThreadKinematic() {
63 final CachedTransformProvider cachedTransformProvider = buildCache(20);
64 Assertions.assertSame(earth1, cachedTransformProvider.getOrigin());
65 Assertions.assertSame(inertialFrame, cachedTransformProvider.getDestination());
66 Assertions.assertEquals(20, cachedTransformProvider.getCacheSize());
67 final List<AbsoluteDate> dates = generateDates(new Well19937a(0x03fb4b0832dadcbe2L), 50, 5);
68 for (final AbsoluteDate date : dates) {
69 final KinematicTransform transform1 = cachedTransformProvider.getKinematicTransform(date);
70 final KinematicTransform transform2 = earth2.getKinematicTransformTo(inertialFrame, date);
71 final KinematicTransform backAndForth = KinematicTransform.compose(date, transform1, transform2.getInverse());
72 Assertions.assertEquals(0.0, backAndForth.getRotation().getAngle(), 3.0e-15);
73 }
74 Assertions.assertEquals(10, earth1.count);
75 Assertions.assertEquals(dates.size(), earth2.count);
76 }
77
78 @Test
79 public void testSingleThreadStatic() {
80 final CachedTransformProvider cachedTransformProvider = buildCache(20);
81 Assertions.assertSame(earth1, cachedTransformProvider.getOrigin());
82 Assertions.assertSame(inertialFrame, cachedTransformProvider.getDestination());
83 Assertions.assertEquals(20, cachedTransformProvider.getCacheSize());
84 final List<AbsoluteDate> dates = generateDates(new Well19937a(0x03fb4b0832dadcbe2L), 50, 5);
85 for (final AbsoluteDate date : dates) {
86 final StaticTransform transform1 = cachedTransformProvider.getStaticTransform(date);
87 final StaticTransform transform2 = earth2.getStaticTransformTo(inertialFrame, date);
88 final StaticTransform backAndForth = StaticTransform.compose(date, transform1, transform2.getInverse());
89 Assertions.assertEquals(0.0, backAndForth.getRotation().getAngle(), 3.0e-15);
90 }
91 Assertions.assertEquals(10, earth1.count);
92 Assertions.assertEquals(dates.size(), earth2.count);
93 }
94
95 @Test
96 public void testMultiThread() throws InterruptedException, ExecutionException {
97 final CachedTransformProvider cachedTransformProvider = buildCache(30);
98 Assertions.assertEquals(30, cachedTransformProvider.getCacheSize());
99 final List<AbsoluteDate> dates = generateDates(new Well19937a(0x7d63ba984c6ae29eL), 300, 10);
100 final List<Callable<Transform>> tasks = new ArrayList<>();
101 for (final AbsoluteDate date : dates) {
102 tasks.add(() -> cachedTransformProvider.getTransform(date));
103 }
104 ExecutorService executorService = Executors.newFixedThreadPool(8);
105 final List<Future<Transform>> futures = executorService.invokeAll(tasks);
106 for (int i = 0; i < dates.size(); i++) {
107 final Transform transform1 = futures.get(i).get();
108 final Transform transform2 = earth2.getTransformTo(inertialFrame, dates.get(i));
109 final Transform backAndForth = new Transform(dates.get(i), transform1, transform2.getInverse());
110 Assertions.assertEquals(0.0, backAndForth.getRotation().getAngle(), 1.0e-14);
111 }
112 Assertions.assertTrue(earth1.count < 50, "this test may randomly fail due to multi-threading non-determinism");
113 Assertions.assertEquals(dates.size(), earth2.count);
114 }
115
116 @Test
117 public void testExhaust() {
118 final RandomGenerator random = new Well19937a(0x3b18a628c1a8b5e9L);
119 final CachedTransformProvider cachedTransformProvider = buildCache(20);
120 final List<AbsoluteDate> dates = generateDates(random,
121 10 * cachedTransformProvider.getCacheSize(),
122 50 * cachedTransformProvider.getCacheSize());
123
124
125 final List<Transform> firstBatch = new ArrayList<>();
126 for (int i = 0; i < cachedTransformProvider.getCacheSize(); i++) {
127 firstBatch.add(cachedTransformProvider.getTransform(dates.get(i)));
128 }
129 for (int i = 0; i < 1000; i++) {
130
131 final int k = random.nextInt(firstBatch.size());
132 Assertions.assertSame(firstBatch.get(k), cachedTransformProvider.getTransform(dates.get(k)));
133 }
134 final Transform t14 = cachedTransformProvider.getTransform(dates.get(14));
135
136
137 for (int i = 0; i < dates.size(); i++) {
138 Assertions.assertNotNull(cachedTransformProvider.getTransform(dates.get(dates.size() - 1 - i)));
139 Assertions.assertNotNull(cachedTransformProvider.getTransform(dates.get(14)));
140 }
141
142 for (int i = 0; i < 100; i++) {
143
144
145 final int k = random.nextInt(firstBatch.size());
146 final Transform t = cachedTransformProvider.getTransform(dates.get(k));
147 final Transform backAndForth = new Transform(dates.get(k), firstBatch.get(k), t.getInverse());
148 if (k != 14) {
149 Assertions.assertNotSame(firstBatch.get(k), t);
150 }
151 Assertions.assertEquals(0.0, backAndForth.getRotation().getAngle(), 1.0e-20);
152 Assertions.assertEquals(0.0, backAndForth.getCartesian().getPosition().getNorm(), 1.0e-20);
153 }
154
155
156 Assertions.assertSame(t14, cachedTransformProvider.getTransform(dates.get(14)));
157
158 }
159
160 @Test
161 public void testExhaustKinematic() {
162 final RandomGenerator random = new Well19937a(0x3b18a628c1a8b5e9L);
163 final CachedTransformProvider cachedTransformProvider = buildCache(20);
164 final List<AbsoluteDate> dates = generateDates(random,
165 10 * cachedTransformProvider.getCacheSize(),
166 50 * cachedTransformProvider.getCacheSize());
167
168
169 final List<KinematicTransform> firstBatch = new ArrayList<>();
170 for (int i = 0; i < cachedTransformProvider.getCacheSize(); i++) {
171 firstBatch.add(cachedTransformProvider.getKinematicTransform(dates.get(i)));
172 }
173 for (int i = 0; i < 1000; i++) {
174
175 final int k = random.nextInt(firstBatch.size());
176 Assertions.assertSame(firstBatch.get(k), cachedTransformProvider.getKinematicTransform(dates.get(k)));
177 }
178 final KinematicTransform t14 = cachedTransformProvider.getKinematicTransform(dates.get(14));
179
180
181 for (int i = 0; i < dates.size(); i++) {
182 Assertions.assertNotNull(cachedTransformProvider.getKinematicTransform(dates.get(dates.size() - 1 - i)));
183 Assertions.assertNotNull(cachedTransformProvider.getKinematicTransform(dates.get(14)));
184 }
185
186 for (int i = 0; i < 100; i++) {
187
188
189 final int k = random.nextInt(firstBatch.size());
190 final KinematicTransform t = cachedTransformProvider.getTransform(dates.get(k));
191 final KinematicTransform backAndForth = KinematicTransform.compose(dates.get(k), firstBatch.get(k), t.getInverse());
192 if (k != 14) {
193 Assertions.assertNotSame(firstBatch.get(k), t);
194 }
195 Assertions.assertEquals(0.0, backAndForth.getRotation().getAngle(), 1.0e-20);
196 Assertions.assertEquals(0.0, backAndForth.getTranslation().getNorm(), 1.0e-20);
197 }
198
199
200 Assertions.assertSame(t14, cachedTransformProvider.getKinematicTransform(dates.get(14)));
201
202 }
203
204 @Test
205 public void testExhaustStatic() {
206 final RandomGenerator random = new Well19937a(0x3b18a628c1a8b5e9L);
207 final CachedTransformProvider cachedTransformProvider = buildCache(20);
208 final List<AbsoluteDate> dates = generateDates(random,
209 10 * cachedTransformProvider.getCacheSize(),
210 50 * cachedTransformProvider.getCacheSize());
211
212
213 final List<StaticTransform> firstBatch = new ArrayList<>();
214 for (int i = 0; i < cachedTransformProvider.getCacheSize(); i++) {
215 firstBatch.add(cachedTransformProvider.getStaticTransform(dates.get(i)));
216 }
217 for (int i = 0; i < 1000; i++) {
218
219 final int k = random.nextInt(firstBatch.size());
220 Assertions.assertSame(firstBatch.get(k), cachedTransformProvider.getStaticTransform(dates.get(k)));
221 }
222 final StaticTransform t14 = cachedTransformProvider.getStaticTransform(dates.get(14));
223
224
225 for (int i = 0; i < dates.size(); i++) {
226 Assertions.assertNotNull(cachedTransformProvider.getStaticTransform(dates.get(dates.size() - 1 - i)));
227 Assertions.assertNotNull(cachedTransformProvider.getStaticTransform(dates.get(14)));
228 }
229
230 for (int i = 0; i < 100; i++) {
231
232
233 final int k = random.nextInt(firstBatch.size());
234 final StaticTransform t = cachedTransformProvider.getTransform(dates.get(k));
235 final StaticTransform backAndForth = StaticTransform.compose(dates.get(k), firstBatch.get(k), t.getInverse());
236 if (k != 14) {
237 Assertions.assertNotSame(firstBatch.get(k), t);
238 }
239 Assertions.assertEquals(0.0, backAndForth.getRotation().getAngle(), 1.0e-20);
240 Assertions.assertEquals(0.0, backAndForth.getTranslation().getNorm(), 1.0e-20);
241 }
242
243
244 Assertions.assertSame(t14, cachedTransformProvider.getStaticTransform(dates.get(14)));
245
246 }
247
248 private CachedTransformProvider buildCache(final int size) {
249 return new CachedTransformProvider(earth1, inertialFrame,
250 d -> earth1.getTransformTo(inertialFrame, d),
251 d -> earth1.getKinematicTransformTo(inertialFrame, d),
252 d -> earth1.getStaticTransformTo(inertialFrame, d),
253 size);
254
255 }
256
257 private List<AbsoluteDate> generateDates(final RandomGenerator random, final int total, final int history) {
258 final List<AbsoluteDate> dates = new ArrayList<>(total);
259 for (int i = 0; i < total; i++) {
260 final int index = i - random.nextInt(history);
261 final AbsoluteDate date = index < 0 || index >= dates.size() ?
262 AbsoluteDate.ARBITRARY_EPOCH.shiftedBy(Constants.JULIAN_DAY * random.nextDouble()) :
263 dates.get(index);
264 dates.add(date);
265 }
266 return dates;
267 }
268
269 @BeforeEach
270 public void setUp() {
271 Utils.setDataRoot("regular-data");
272 final Frame earthFrame = FramesFactory.getITRF(IERSConventions.IERS_2010, false);
273 this.inertialFrame = FramesFactory.getEME2000();
274 this.earth1 = new CountingFrame(earthFrame);
275 this.earth2 = new CountingFrame(earthFrame);
276 }
277
278 @AfterEach
279 public void tearDown() {
280 inertialFrame = null;
281 earth1 = null;
282 earth2 = null;
283 }
284
285
286 private static class CountingFrame extends Frame {
287 int count;
288
289 CountingFrame(final Frame frame) {
290 super(frame, Transform.IDENTITY, "counting", false);
291 count = 0;
292 }
293
294 public Transform getTransformTo(final Frame destination, final AbsoluteDate date) {
295 ++count;
296 return super.getTransformTo(destination, date);
297 }
298
299 public KinematicTransform getKinematicTransformTo(final Frame destination, final AbsoluteDate date) {
300 ++count;
301 return super.getKinematicTransformTo(destination, date);
302 }
303
304 public StaticTransform getStaticTransformTo(final Frame destination, final AbsoluteDate date) {
305 ++count;
306 return super.getStaticTransformTo(destination, date);
307 }
308
309 }
310
311 }