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 org.hipparchus.geometry.euclidean.threed.Vector3D;
21  import org.hipparchus.util.FastMath;
22  import org.junit.Assert;
23  import org.junit.Before;
24  import org.junit.Test;
25  import org.orekit.Utils;
26  import org.orekit.time.AbsoluteDate;
27  import org.orekit.time.TimeScalesFactory;
28  import org.orekit.utils.Constants;
29  import org.orekit.utils.IERSConventions;
30  
31  public class HelmertTransformationTest {
32  
33      @Test
34      public void testHelmert20052008() {
35          // for this test, we arbitrarily assume FramesFactory provides an ITRF 2008
36          Frame itrf2008 = FramesFactory.getITRF(IERSConventions.IERS_2010, true);
37          HelmertTransformation.Predefined ht = HelmertTransformation.Predefined.ITRF_2008_TO_ITRF_2005;
38          Assert.assertEquals(ITRFVersion.ITRF_2008, ht.getOrigin());
39          Assert.assertEquals(ITRFVersion.ITRF_2005, ht.getDestination());
40          Assert.assertEquals(new AbsoluteDate(2000, 1, 1, 12, 0, 0, TimeScalesFactory.getTT()),
41                              ht.getTransformation().getEpoch());
42          Frame itrf2005 = ht.createTransformedITRF(itrf2008, "2005");
43          Vector3D pos2005 = new Vector3D(1234567.8, 2345678.9, 3456789.0);
44  
45          // check the Helmert transformation as per http://itrf.ign.fr/ITRF_solutions/2008/tp_08-05.php
46          AbsoluteDate date = new AbsoluteDate(2005, 1, 1, 12, 0, 0, TimeScalesFactory.getTT());
47          Vector3D pos2008 = itrf2005.getTransformTo(itrf2008, date).transformPosition(pos2005);
48          Vector3D generalOffset = pos2005.subtract(pos2008);
49          Vector3D linearOffset  = computeOffsetLinearly(-0.5, -0.9, -4.7, 0.000, 0.000, 0.000,
50                                                          0.3,  0.0,  0.0, 0.000, 0.000, 0.000,
51                                                         pos2005, 0.0);
52          Vector3D error         = generalOffset.subtract(linearOffset);
53          Assert.assertEquals(0.0, error.getNorm(), 2.0e-13 * pos2005.getNorm());
54  
55          date = date.shiftedBy(Constants.JULIAN_YEAR);
56          pos2008 = itrf2005.getTransformTo(itrf2008, date).transformPosition(pos2005);
57          generalOffset = pos2005.subtract(pos2008);
58          linearOffset  = computeOffsetLinearly(-0.5, -0.9, -4.7, 0.000, 0.000, 0.000,
59                                                 0.3,  0.0,  0.0, 0.000, 0.000, 0.000,
60                                                pos2005, 1.0);
61          error         = generalOffset.subtract(linearOffset);
62          Assert.assertEquals(0.0, error.getNorm(), 2.0e-13 * pos2005.getNorm());
63  
64      }
65  
66      @Test
67      public void testHelmert20002005() {
68          // for this test, we arbitrarily assume FramesFactory provides an ITRF 2008
69          Frame itrf2008 = FramesFactory.getITRF(IERSConventions.IERS_2010, true);
70          Frame itrf2000 =
71                  HelmertTransformation.Predefined.ITRF_2008_TO_ITRF_2000.createTransformedITRF(itrf2008, "2000");
72          Frame itrf2005 =
73                  HelmertTransformation.Predefined.ITRF_2008_TO_ITRF_2005.createTransformedITRF(itrf2008, "2005");
74          Vector3D pos2000 = new Vector3D(1234567.8, 2345678.9, 3456789.0);
75  
76          // check the Helmert transformation as per http://itrf.ign.fr/ITRF_solutions/2005/tp_05-00.php
77          AbsoluteDate date = AbsoluteDate.J2000_EPOCH;
78          Vector3D pos2005 = itrf2000.getTransformTo(itrf2005, date).transformPosition(pos2000);
79          Vector3D generalOffset = pos2000.subtract(pos2005);
80          Vector3D linearOffset  = computeOffsetLinearly( 0.1, -0.8, -5.8, 0.000, 0.000, 0.000,
81                                                         -0.2,  0.1, -1.8, 0.000, 0.000, 0.000,
82                                                         pos2000, 0.0);
83          Vector3D error         = generalOffset.subtract(linearOffset);
84          Assert.assertEquals(0.0, error.getNorm(), FastMath.ulp(pos2000.getNorm()));
85  
86          date = date.shiftedBy(Constants.JULIAN_YEAR);
87          pos2005 = itrf2000.getTransformTo(itrf2005, date).transformPosition(pos2000);
88          generalOffset = pos2000.subtract(pos2005);
89          linearOffset  = computeOffsetLinearly( 0.1, -0.8, -5.8, 0.000, 0.000, 0.000,
90                                                 -0.2,  0.1, -1.8, 0.000, 0.000, 0.000,
91                                                 pos2000, 1.0);
92          error         = generalOffset.subtract(linearOffset);
93          Assert.assertEquals(0.0, error.getNorm(), FastMath.ulp(pos2000.getNorm()));
94  
95      }
96  
97      @Test
98      public void testHelmert19972000() {
99          // for this test, we arbitrarily assume FramesFactory provides an ITRF 2008
100         Frame itrf2008 = FramesFactory.getITRF(IERSConventions.IERS_2010, true);
101         Frame itrf2000 =
102                 HelmertTransformation.Predefined.ITRF_2008_TO_ITRF_2000.createTransformedITRF(itrf2008, "2000");
103         Frame itrf97 =
104                 HelmertTransformation.Predefined.ITRF_2008_TO_ITRF_1997.createTransformedITRF(itrf2008, "97");
105         Vector3D pos97 = new Vector3D(1234567.8, 2345678.9, 3456789.0);
106 
107         // check the Helmert transformation as per ftp://itrf.ensg.ign.fr/pub/itrf/ITRF.TP
108         AbsoluteDate date = new AbsoluteDate(1997, 1, 1, 12, 0, 0, TimeScalesFactory.getTT());
109         Vector3D pos2000 = itrf97.getTransformTo(itrf2000, date).transformPosition(pos97);
110         Vector3D generalOffset = pos97.subtract(pos2000);
111         Vector3D linearOffset  = computeOffsetLinearly( 6.7,  6.1, -18.5, 0.000, 0.000, 0.000,
112                                                         0.0, -0.6,  -1.4, 0.000, 0.000, 0.002,
113                                                        pos2000, 0.0);
114         Vector3D error         = generalOffset.subtract(linearOffset);
115         Assert.assertEquals(0.0, error.getNorm(), 2.0e-11 * pos97.getNorm());
116 
117         date = date.shiftedBy(Constants.JULIAN_YEAR);
118         pos2000 = itrf97.getTransformTo(itrf2000, date).transformPosition(pos97);
119         generalOffset = pos97.subtract(pos2000);
120         linearOffset  = computeOffsetLinearly( 6.7,  6.1, -18.5, 0.000, 0.000, 0.000,
121                                                0.0, -0.6,  -1.4, 0.000, 0.000, 0.002,
122                                                pos2000, 1.0);
123         error         = generalOffset.subtract(linearOffset);
124         Assert.assertEquals(0.0, error.getNorm(), 6.0e-11 * pos97.getNorm());
125 
126     }
127 
128     @Test
129     public void testHelmert19932000() {
130         // for this test, we arbitrarily assume FramesFactory provides an ITRF 2008
131         Frame itrf2008 = FramesFactory.getITRF(IERSConventions.IERS_2010, true);
132         Frame itrf2000 =
133                 HelmertTransformation.Predefined.ITRF_2008_TO_ITRF_2000.createTransformedITRF(itrf2008, "2000");
134         Frame itrf93 =
135                 HelmertTransformation.Predefined.ITRF_2008_TO_ITRF_1993.createTransformedITRF(itrf2008, "93");
136         Vector3D pos93 = new Vector3D(1234567.8, 2345678.9, 3456789.0);
137 
138         // check the Helmert transformation as per ftp://itrf.ensg.ign.fr/pub/itrf/ITRF.TP
139         AbsoluteDate date = new AbsoluteDate(1988, 1, 1, 12, 0, 0, TimeScalesFactory.getTT());
140         Vector3D pos2000 = itrf93.getTransformTo(itrf2000, date).transformPosition(pos93);
141         Vector3D generalOffset = pos93.subtract(pos2000);
142         Vector3D linearOffset  = computeOffsetLinearly(12.7,  6.5, -20.9, -0.39,  0.80, -1.14,
143                                                        -2.9, -0.2,  -0.6, -0.11, -0.19,  0.07,
144                                                        pos2000, 0.0);
145         Vector3D error         = generalOffset.subtract(linearOffset);
146         Assert.assertEquals(0.0, error.getNorm(), FastMath.ulp(pos93.getNorm()));
147 
148         date = date.shiftedBy(Constants.JULIAN_YEAR);
149         pos2000 = itrf93.getTransformTo(itrf2000, date).transformPosition(pos93);
150         generalOffset = pos93.subtract(pos2000);
151         linearOffset  = computeOffsetLinearly(12.7,  6.5, -20.9, -0.39,  0.80, -1.14,
152                                               -2.9, -0.2,  -0.6, -0.11, -0.19,  0.07,
153                                               pos2000, 1.0);
154         error         = generalOffset.subtract(linearOffset);
155         Assert.assertEquals(0.0, error.getNorm(), FastMath.ulp(pos93.getNorm()));
156 
157     }
158 
159     @Test
160     public void test2014PivotVs2008Pivot() {
161 
162         // for this test, we arbitrarily assume FramesFactory provides an ITRF 2014
163         Frame itrf2014 = FramesFactory.getITRF(IERSConventions.IERS_2010, true);
164         Frame itrf2008 = HelmertTransformation.Predefined.ITRF_2014_TO_ITRF_2008.createTransformedITRF(itrf2014, "2008");
165 
166         for (final HelmertTransformation.Predefined p2008 : HelmertTransformation.Predefined.values()) {
167             if (p2008.toString().startsWith("ITRF_2008_TO")) {
168                 HelmertTransformation.Predefined p2014 =
169                                 HelmertTransformation.Predefined.valueOf(p2008.toString().replaceAll("2008", "2014"));
170                 Frame itrfXFrom2008 = p2008.createTransformedITRF(itrf2008, "x-from-2008");
171                 Frame itrfXFrom2014 = p2014.createTransformedITRF(itrf2014, "x-from-2014");
172                 for (int year = 2000; year < 2007; ++year) {
173                     AbsoluteDate date = new AbsoluteDate(year, 4, 17, 12, 0, 0, TimeScalesFactory.getTT());
174                     Transform t = itrfXFrom2014.getTransformTo(itrfXFrom2008, date);
175                     // the errors are not strictly zero (but they are very small) because
176                     // Helmert transformations are a translation plus a rotation. If we do
177                     // t1 -> r1 -> t2 -> r2, it is not the same as t1 -> t2 -> r1 -> r2
178                     // which would correspond to simply add the offsets, velocities, rotations and rate,
179                     // which is what is done in the reference documents. Anyway, the non-commutativity
180                     // errors are well below models accuracy
181                     Assert.assertEquals(0, t.getTranslation().getNorm(),  6.0e-6);
182                     Assert.assertEquals(0, t.getVelocity().getNorm(),     2.0e-22);
183                     Assert.assertEquals(0, t.getRotation().getAngle(),    2.0e-12);
184                     Assert.assertEquals(0, t.getRotationRate().getNorm(), 2.0e-32);
185                 }
186             }
187         }
188     }
189 
190     private Vector3D computeOffsetLinearly(final double t1,    final double t2,    final double t3,
191                                            final double r1,    final double r2,    final double r3,
192                                            final double t1Dot, final double t2Dot, final double t3Dot,
193                                            final double r1Dot, final double r2Dot, final double r3Dot,
194                                            final Vector3D p,   final double dt) {
195         double t1U = (t1 + dt * t1Dot) * 1.0e-3;
196         double t2U = (t2 + dt * t2Dot) * 1.0e-3;
197         double t3U = (t3 + dt * t3Dot) * 1.0e-3;
198         double r1U = FastMath.toRadians((r1 + dt * r1Dot) / 3.6e6);
199         double r2U = FastMath.toRadians((r2 + dt * r2Dot) / 3.6e6);
200         double r3U = FastMath.toRadians((r3 + dt * r3Dot) / 3.6e6);
201         return new Vector3D(t1U - r3U * p.getY() + r2U * p.getZ(),
202                             t2U + r3U * p.getX() - r1U * p.getZ(),
203                             t3U - r2U * p.getX() + r1U * p.getY());
204     }
205 
206     @Before
207     public void setUp() {
208         Utils.setDataRoot("compressed-data");
209     }
210 
211 }