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.frames;
18  
19  
20  import java.io.ByteArrayInputStream;
21  import java.io.ByteArrayOutputStream;
22  import java.io.IOException;
23  import java.io.ObjectInputStream;
24  import java.io.ObjectOutputStream;
25  
26  import org.hipparchus.CalculusFieldElement;
27  import org.hipparchus.geometry.euclidean.threed.Rotation;
28  import org.hipparchus.geometry.euclidean.threed.RotationConvention;
29  import org.hipparchus.geometry.euclidean.threed.Vector3D;
30  import org.hipparchus.util.FastMath;
31  import org.junit.Assert;
32  import org.junit.Test;
33  import org.orekit.errors.OrekitException;
34  import org.orekit.errors.OrekitMessages;
35  import org.orekit.time.AbsoluteDate;
36  import org.orekit.time.FieldAbsoluteDate;
37  import org.orekit.utils.AngularDerivativesFilter;
38  import org.orekit.utils.CartesianDerivativesFilter;
39  
40  
41  public class ShiftingTransformProviderTest {
42  
43      @Test
44      public void testCacheHitForward() {
45  
46          AbsoluteDate t0 = AbsoluteDate.GALILEO_EPOCH;
47          CirclingProvider referenceProvider = new CirclingProvider(t0, 0.2);
48          CirclingProvider rawProvider = new CirclingProvider(t0, 0.2);
49          ShiftingTransformProvider shiftingProvider =
50                  new ShiftingTransformProvider(rawProvider,
51                                                CartesianDerivativesFilter.USE_PVA,
52                                                AngularDerivativesFilter.USE_RRA,
53                                                5, 0.8, 10, 60.0, 60.0);
54          Assert.assertEquals(5,   shiftingProvider.getGridPoints());
55          Assert.assertEquals(0.8, shiftingProvider.getStep(), 1.0e-15);
56  
57          for (double dt = 0.8; dt <= 1.0; dt += 0.001) {
58              Transform reference = referenceProvider.getTransform(t0.shiftedBy(dt));
59              Transform interpolated = shiftingProvider.getTransform(t0.shiftedBy(dt));
60              Transform error = new Transform(reference.getDate(), reference, interpolated.getInverse());
61  
62              Assert.assertEquals(0.0, error.getCartesian().getPosition().getNorm(),           1.1e-5);
63              Assert.assertEquals(0.0, error.getCartesian().getVelocity().getNorm(),           1.6e-4);
64              Assert.assertEquals(0.0, error.getCartesian().getAcceleration().getNorm(),       1.6e-3);
65              Assert.assertEquals(0.0, error.getAngular().getRotation().getAngle(),            4.2e-16);
66              Assert.assertEquals(0.0, error.getAngular().getRotationRate().getNorm(),         1.2e-16);
67              Assert.assertEquals(0.0, error.getAngular().getRotationAcceleration().getNorm(), 7.1e-30);
68  
69          }
70          Assert.assertEquals(8,   rawProvider.getCount());
71          Assert.assertEquals(200, referenceProvider.getCount());
72  
73      }
74  
75      @Test
76      public void testCacheHitBackward() {
77  
78          AbsoluteDate t0 = AbsoluteDate.GALILEO_EPOCH;
79          CirclingProvider referenceProvider = new CirclingProvider(t0, 0.2);
80          CirclingProvider rawProvider = new CirclingProvider(t0, 0.2);
81          ShiftingTransformProvider shiftingProvider =
82                  new ShiftingTransformProvider(rawProvider,
83                                                CartesianDerivativesFilter.USE_PVA,
84                                                AngularDerivativesFilter.USE_RRA,
85                                                5, 0.8, 10, 60.0, 60.0);
86          Assert.assertEquals(5,   shiftingProvider.getGridPoints());
87          Assert.assertEquals(0.8, shiftingProvider.getStep(), 1.0e-15);
88  
89          for (double dt = 1.0; dt >= 0.8; dt -= 0.001) {
90              Transform reference = referenceProvider.getTransform(t0.shiftedBy(dt));
91              Transform interpolated = shiftingProvider.getTransform(t0.shiftedBy(dt));
92              Transform error = new Transform(reference.getDate(), reference, interpolated.getInverse());
93  
94              Assert.assertEquals(0.0, error.getCartesian().getPosition().getNorm(),           1.1e-5);
95              Assert.assertEquals(0.0, error.getCartesian().getVelocity().getNorm(),           1.6e-4);
96              Assert.assertEquals(0.0, error.getCartesian().getAcceleration().getNorm(),       1.6e-3);
97              Assert.assertEquals(0.0, error.getAngular().getRotation().getAngle(),            4.2e-16);
98              Assert.assertEquals(0.0, error.getAngular().getRotationRate().getNorm(),         2.3e-16);
99              Assert.assertEquals(0.0, error.getAngular().getRotationAcceleration().getNorm(), 7.1e-30);
100 
101         }
102         Assert.assertEquals(10,   rawProvider.getCount());
103         Assert.assertEquals(200, referenceProvider.getCount());
104 
105     }
106 
107     @Test(expected=OrekitException.class)
108     public void testForwardException() {
109         ShiftingTransformProvider shiftingProvider =
110                 new ShiftingTransformProvider(new TransformProvider() {
111                     private static final long serialVersionUID = -3126512810306982868L;
112                     public Transform getTransform(AbsoluteDate date) {
113                         throw new OrekitException(OrekitMessages.INTERNAL_ERROR);
114                     }
115                     public <T extends CalculusFieldElement<T>> FieldTransform<T> getTransform(final FieldAbsoluteDate<T> date) {
116                         throw new UnsupportedOperationException("never called in this test");
117                     }
118                 },
119                 CartesianDerivativesFilter.USE_PVA,
120                 AngularDerivativesFilter.USE_RRA,
121                 5, 0.8, 10, 60.0, 60.0);
122         shiftingProvider.getTransform(AbsoluteDate.J2000_EPOCH);
123     }
124 
125     @Test
126     public void testSerialization() throws IOException, ClassNotFoundException {
127 
128         AbsoluteDate t0 = AbsoluteDate.GALILEO_EPOCH;
129         CirclingProvider rawProvider = new CirclingProvider(t0, 0.2);
130         ShiftingTransformProvider shiftingProvider =
131                 new ShiftingTransformProvider(rawProvider,
132                                               CartesianDerivativesFilter.USE_PVA,
133                                               AngularDerivativesFilter.USE_RRA,
134                                               5, 0.8, 10, 60.0, 60.0);
135 
136         for (double dt = 0.1; dt <= 3.1; dt += 0.001) {
137             shiftingProvider.getTransform(t0.shiftedBy(dt));
138         }
139         Assert.assertEquals(12, rawProvider.getCount());
140 
141         ByteArrayOutputStream bos = new ByteArrayOutputStream();
142         ObjectOutputStream    oos = new ObjectOutputStream(bos);
143         oos.writeObject(shiftingProvider);
144 
145         Assert.assertTrue(bos.size () >  650);
146         Assert.assertTrue(bos.size () <  750);
147 
148         ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
149         ObjectInputStream ois = new ObjectInputStream(bis);
150         ShiftingTransformProvider deserialized =
151                 (ShiftingTransformProvider) ois.readObject();
152         Assert.assertEquals(0, ((CirclingProvider) deserialized.getRawProvider()).getCount());
153         for (double dt = 0.1; dt <= 3.1; dt += 0.001) {
154             Transform t1 = shiftingProvider.getTransform(t0.shiftedBy(dt));
155             Transform t2 = deserialized.getTransform(t0.shiftedBy(dt));
156             Transform error = new Transform(t1.getDate(), t1, t2.getInverse());
157             // both interpolators should give the same results
158             Assert.assertEquals(0.0, error.getCartesian().getPosition().getNorm(),   1.0e-15);
159             Assert.assertEquals(0.0, error.getCartesian().getVelocity().getNorm(),   1.0e-15);
160             Assert.assertEquals(0.0, error.getAngular().getRotation().getAngle(),    1.0e-15);
161             Assert.assertEquals(0.0, error.getAngular().getRotationRate().getNorm(), 1.0e-15);
162         }
163 
164         // the original interpolator should not have triggered any new calls
165         Assert.assertEquals(12, rawProvider.getCount());
166 
167         // the deserialized interpolator should have triggered new calls
168         Assert.assertEquals(12, ((CirclingProvider) deserialized.getRawProvider()).getCount());
169 
170     }
171 
172     private static class CirclingProvider implements TransformProvider {
173 
174         private static final long serialVersionUID = 473784183299281612L;
175         private int count;
176         private final AbsoluteDate t0;
177         private final double omega;
178 
179         public CirclingProvider(final AbsoluteDate t0, final double omega) {
180             this.count = 0;
181             this.t0    = t0;
182             this.omega = omega;
183         }
184 
185         public Transform getTransform(final AbsoluteDate date) {
186             // the following transform corresponds to a frame moving along the circle r = 1
187             // with its x axis always pointing to the reference frame center
188             ++count;
189             final double dt = date.durationFrom(t0);
190             final double cos = FastMath.cos(omega * dt);
191             final double sin = FastMath.sin(omega * dt);
192             return new Transform(date,
193                                  new Transform(date,
194                                                new Vector3D(-cos, -sin, 0),
195                                                new Vector3D(omega * sin, -omega * cos, 0),
196                                                new Vector3D(omega * omega * cos, omega * omega * sin, 0)),
197                                  new Transform(date,
198                                                new Rotation(Vector3D.PLUS_K,
199                                                             FastMath.PI - omega * dt,
200                                                             RotationConvention.VECTOR_OPERATOR),
201                                                new Vector3D(omega, Vector3D.PLUS_K)));
202         }
203 
204         public <T extends CalculusFieldElement<T>> FieldTransform<T> getTransform(final FieldAbsoluteDate<T> date) {
205             throw new UnsupportedOperationException("never called in this test");
206         }
207 
208         public int getCount() {
209             return count;
210         }
211 
212         private Object readResolve() {
213             count = 0;
214             return this;
215         }
216     }
217 
218 }