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 InterpolatingTransformProviderTest {
42  
43      @Test
44      public void testCacheHitWithDerivatives() {
45  
46          AbsoluteDate t0 = AbsoluteDate.GALILEO_EPOCH;
47          CirclingProvider referenceProvider = new CirclingProvider(t0, 0.2);
48          CirclingProvider rawProvider = new CirclingProvider(t0, 0.2);
49          InterpolatingTransformProvider interpolatingProvider =
50                  new InterpolatingTransformProvider(rawProvider,
51                                                     CartesianDerivativesFilter.USE_PVA,
52                                                     AngularDerivativesFilter.USE_RR,
53                                                     5, 0.8, 10, 60.0, 60.0);
54  
55          for (double dt = 0.1; dt <= 3.1; dt += 0.001) {
56              Transform reference = referenceProvider.getTransform(t0.shiftedBy(dt));
57              Transform interpolated = interpolatingProvider.getTransform(t0.shiftedBy(dt));
58              Transform error = new Transform(reference.getDate(), reference, interpolated.getInverse());
59              Assert.assertEquals(0.0, error.getCartesian().getPosition().getNorm(),           7.0e-15);
60              Assert.assertEquals(0.0, error.getCartesian().getVelocity().getNorm(),           3.0e-14);
61              Assert.assertEquals(0.0, error.getAngular().getRotation().getAngle(),            1.3e-15);
62              Assert.assertEquals(0.0, error.getAngular().getRotationRate().getNorm(),         2.2e-15);
63              Assert.assertEquals(0.0, error.getAngular().getRotationAcceleration().getNorm(), 1.2e-14);
64  
65          }
66          Assert.assertEquals(10,   rawProvider.getCount());
67          Assert.assertEquals(3001, referenceProvider.getCount());
68  
69      }
70  
71      @Test
72      public void testCacheHitWithoutDerivatives() {
73  
74          AbsoluteDate t0 = AbsoluteDate.GALILEO_EPOCH;
75          CirclingProvider referenceProvider = new CirclingProvider(t0, 0.2);
76          CirclingProvider rawProvider = new CirclingProvider(t0, 0.2);
77          InterpolatingTransformProvider interpolatingProvider =
78                  new InterpolatingTransformProvider(rawProvider,
79                                                     CartesianDerivativesFilter.USE_P,
80                                                     AngularDerivativesFilter.USE_R,
81                                                     5, 0.8, 10, 60.0, 60.0);
82  
83          for (double dt = 0.1; dt <= 3.1; dt += 0.001) {
84              Transform reference = referenceProvider.getTransform(t0.shiftedBy(dt));
85              Transform interpolated = interpolatingProvider.getTransform(t0.shiftedBy(dt));
86              Transform error = new Transform(reference.getDate(), reference, interpolated.getInverse());
87              Assert.assertEquals(0.0, error.getCartesian().getPosition().getNorm(),   1.3e-6);
88              Assert.assertEquals(0.0, error.getCartesian().getVelocity().getNorm(),   7.0e-6);
89              Assert.assertEquals(0.0, error.getAngular().getRotation().getAngle(),    2.0e-15);
90              Assert.assertEquals(0.0, error.getAngular().getRotationRate().getNorm(), 2.0e-15);
91  
92          }
93          Assert.assertEquals(10,   rawProvider.getCount());
94          Assert.assertEquals(3001, referenceProvider.getCount());
95  
96      }
97  
98      @Test(expected=OrekitException.class)
99      public void testForwardException() {
100         InterpolatingTransformProvider interpolatingProvider =
101                 new InterpolatingTransformProvider(new TransformProvider() {
102                     private static final long serialVersionUID = -3126512810306982868L;
103                     public Transform getTransform(AbsoluteDate date) {
104                         throw new OrekitException(OrekitMessages.INTERNAL_ERROR);
105                     }
106                     public <T extends CalculusFieldElement<T>> FieldTransform<T> getTransform(final FieldAbsoluteDate<T> date) {
107                         throw new UnsupportedOperationException("never called in this test");
108                     }
109                 },
110                 CartesianDerivativesFilter.USE_PVA,
111                 AngularDerivativesFilter.USE_RRA,
112                 5, 0.8, 10, 60.0, 60.0);
113         interpolatingProvider.getTransform(AbsoluteDate.J2000_EPOCH);
114     }
115 
116     @Test
117     public void testSerialization() throws IOException, ClassNotFoundException {
118 
119         AbsoluteDate t0 = AbsoluteDate.GALILEO_EPOCH;
120         CirclingProvider rawProvider = new CirclingProvider(t0, 0.2);
121         InterpolatingTransformProvider interpolatingProvider =
122                 new InterpolatingTransformProvider(rawProvider,
123                                                    CartesianDerivativesFilter.USE_PVA,
124                                                    AngularDerivativesFilter.USE_RRA,
125                                                    5, 0.8, 10, 60.0, 60.0);
126 
127         for (double dt = 0.1; dt <= 3.1; dt += 0.001) {
128             interpolatingProvider.getTransform(t0.shiftedBy(dt));
129         }
130         Assert.assertEquals(10, rawProvider.getCount());
131 
132         ByteArrayOutputStream bos = new ByteArrayOutputStream();
133         ObjectOutputStream    oos = new ObjectOutputStream(bos);
134         oos.writeObject(interpolatingProvider);
135 
136         Assert.assertTrue(bos.size () >  450);
137         Assert.assertTrue(bos.size () <  550);
138 
139         ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
140         ObjectInputStream ois = new ObjectInputStream(bis);
141         InterpolatingTransformProvider deserialized =
142                 (InterpolatingTransformProvider) ois.readObject();
143         Assert.assertEquals(0, ((CirclingProvider) deserialized.getRawProvider()).getCount());
144         for (double dt = 0.1; dt <= 3.1; dt += 0.001) {
145             Transform t1 = interpolatingProvider.getTransform(t0.shiftedBy(dt));
146             Transform t2 = deserialized.getTransform(t0.shiftedBy(dt));
147             Transform error = new Transform(t1.getDate(), t1, t2.getInverse());
148             // both interpolators should give the same results
149             Assert.assertEquals(0.0, error.getCartesian().getPosition().getNorm(),   1.0e-15);
150             Assert.assertEquals(0.0, error.getCartesian().getVelocity().getNorm(),   1.0e-15);
151             Assert.assertEquals(0.0, error.getAngular().getRotation().getAngle(),    1.0e-15);
152             Assert.assertEquals(0.0, error.getAngular().getRotationRate().getNorm(), 1.0e-15);
153         }
154 
155         // the original interpolator should not have triggered any new calls
156         Assert.assertEquals(10, rawProvider.getCount());
157 
158         // the deserialized interpolator should have triggered new calls
159         Assert.assertEquals(10, ((CirclingProvider) deserialized.getRawProvider()).getCount());
160 
161     }
162 
163     private static class CirclingProvider implements TransformProvider {
164 
165         private static final long serialVersionUID = 473784183299281612L;
166         private int count;
167         private final AbsoluteDate t0;
168         private final double omega;
169 
170         public CirclingProvider(final AbsoluteDate t0, final double omega) {
171             this.count = 0;
172             this.t0    = t0;
173             this.omega = omega;
174         }
175 
176         public Transform getTransform(final AbsoluteDate date) {
177             // the following transform corresponds to a frame moving along the circle r = 1
178             // with its x axis always pointing to the reference frame center
179             ++count;
180             final double dt = date.durationFrom(t0);
181             final double cos = FastMath.cos(omega * dt);
182             final double sin = FastMath.sin(omega * dt);
183             return new Transform(date,
184                                  new Transform(date,
185                                                new Vector3D(-cos, -sin, 0),
186                                                new Vector3D(omega * sin, -omega * cos, 0),
187                                                new Vector3D(omega * omega * cos, omega * omega * sin, 0)),
188                                  new Transform(date,
189                                                new Rotation(Vector3D.PLUS_K,
190                                                             FastMath.PI - omega * dt,
191                                                             RotationConvention.VECTOR_OPERATOR),
192                                                new Vector3D(omega, Vector3D.PLUS_K)));
193         }
194 
195         public <T extends CalculusFieldElement<T>> FieldTransform<T> getTransform(final FieldAbsoluteDate<T> date) {
196             throw new UnsupportedOperationException("never called in this test");
197         }
198 
199         public int getCount() {
200             return count;
201         }
202 
203         private Object readResolve() {
204             count = 0;
205             return this;
206         }
207     }
208 
209 }