1   /* Copyright 2002-2025 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  import java.util.Optional;
20  import java.util.stream.Stream;
21  
22  import org.hipparchus.CalculusFieldElement;
23  import org.hipparchus.Field;
24  import org.hipparchus.geometry.euclidean.threed.FieldRotation;
25  import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
26  import org.hipparchus.geometry.euclidean.threed.Rotation;
27  import org.hipparchus.geometry.euclidean.threed.RotationConvention;
28  import org.hipparchus.geometry.euclidean.threed.Vector3D;
29  import org.hipparchus.util.Precision;
30  import org.orekit.annotation.DefaultDataContext;
31  import org.orekit.data.DataContext;
32  import org.orekit.time.AbsoluteDate;
33  import org.orekit.time.DateTimeComponents;
34  import org.orekit.time.FieldAbsoluteDate;
35  import org.orekit.time.TimeScale;
36  import org.orekit.utils.Constants;
37  import org.orekit.utils.FieldPVCoordinates;
38  import org.orekit.utils.PVCoordinates;
39  
40  
41  /** Transformation class for geodetic systems.
42   *
43   * <p>The Helmert transformation is mainly used to convert between various
44   * realizations of geodetic frames, for example in the ITRF family.</p>
45   *
46   * <p>The original Helmert transformation is a 14 parameters transform that
47   * includes translation, velocity, rotation, rotation rate and scale factor.
48   * The scale factor is useful for coordinates near Earth surface, but it
49   * cannot be extended to outer space as it would correspond to a non-unitary
50   * transform. Therefore, the scale factor is <em>not</em> used here.
51   *
52   * <p>Instances of this class are guaranteed to be immutable.</p>
53   *
54   * @author Luc Maisonobe
55   * @since 5.1
56   */
57  public class HelmertTransformation implements TransformProvider {
58  
59      /** Enumerate for predefined Helmert transformations. */
60      public enum Predefined {
61  
62          // see https://itrf.ign.fr/docs/solutions/itrf2020/Transfo-ITRF2020_TRFs.txt
63          // SOLUTION         Tx       Ty       Tz        D        Rx        Ry        Rz      EPOCH
64          // UNITS----------> mm       mm       mm       ppb       .001"     .001"     .001"
65          //                  .        .        .         .        .         .         .
66          //        RATES     Tx       Ty       Tz        D        Rx        Ry        Rz
67          // UNITS----------> mm/y     mm/y     mm/y     ppb/y    .001"/y   .001"/y   .001"/y
68          // -----------------------------------------------------------------------------------------
69          //   ITRF2014       -1.4     -0.9      1.4     -0.42      0.00      0.00      0.00    2015.0
70          //        rates      0.0     -0.1      0.2      0.00      0.00      0.00      0.00
71          //   ITRF2008        0.2      1.0      3.3     -0.29      0.00      0.00      0.00    2015.0
72          //        rates      0.0     -0.1      0.1      0.03      0.00      0.00      0.00
73          //   ITRF2005        2.7      0.1     -1.4      0.65      0.00      0.00      0.00    2015.0
74          //        rates      0.3     -0.1      0.1      0.03      0.00      0.00      0.00
75          //   ITRF2000       -0.2      0.8    -34.2      2.25      0.00      0.00      0.00    2015.0
76          //        rates      0.1      0.0     -1.7      0.11      0.00      0.00      0.00
77          //   ITRF97          6.5     -3.9    -77.9      3.98      0.00      0.00      0.36    2015.0
78          //        rates      0.1     -0.6     -3.1      0.12      0.00      0.00      0.02
79          //   ITRF96          6.5     -3.9    -77.9      3.98      0.00      0.00      0.36    2015.0
80          //        rates      0.1     -0.6     -3.1      0.12      0.00      0.00      0.02
81          //   ITRF94          6.5     -3.9    -77.9      3.98      0.00      0.00      0.36    2015.0
82          //        rates      0.1     -0.6     -3.1      0.12      0.00      0.00      0.02
83          //   ITRF93        -65.8      1.9    -71.3      4.47     -3.36     -4.33      0.75    2015.0
84          //        rates     -2.8     -0.2     -2.3      0.12     -0.11     -0.19      0.07
85          //   ITRF92         14.5     -1.9    -85.9      3.27      0.00      0.00      0.36    2015.0
86          //        rates      0.1     -0.6     -3.1      0.12      0.00      0.00      0.02
87          //   ITRF91         26.5     12.1    -91.9      4.67      0.00      0.00      0.36    2015.0
88          //        rates      0.1     -0.6     -3.1      0.12      0.00      0.00      0.02
89          //   ITRF90         24.5      8.1   -107.9      4.97      0.00      0.00      0.36    2015.0
90          //        rates      0.1     -0.6     -3.1      0.12      0.00      0.00      0.02
91          //   ITRF89         29.5     32.1   -145.9      8.37      0.00      0.00      0.36    2015.0
92          //        rates      0.1     -0.6     -3.1      0.12      0.00      0.00      0.02
93          //   ITRF88         24.5     -3.9   -169.9     11.47      0.10      0.00      0.36    2015.0
94          //        rates      0.1     -0.6     -3.1      0.12      0.00      0.00      0.02
95          // _________________________________________________________________________________________
96  
97          /** Transformation from ITRF 2020 To ITRF 2014. */
98          ITRF_2020_TO_ITRF_2014(ITRFVersion.ITRF_2020, ITRFVersion.ITRF_2014, 2015,
99                                 -1.4, -0.9,   1.4,  0.00,  0.00,  0.00,
100                                 0.0, -0.1,   0.2,  0.00,  0.00,  0.00),
101 
102         /** Transformation from ITRF 2020 To ITRF 2008. */
103         ITRF_2020_TO_ITRF_2008(ITRFVersion.ITRF_2020, ITRFVersion.ITRF_2008, 2015,
104                                0.2,  1.0,   3.3,  0.00,  0.00,  0.00,
105                                0.0, -0.1,   0.1,  0.00,  0.00,  0.00),
106 
107         /** Transformation from ITRF 2020 To ITRF 2005. */
108         ITRF_2020_TO_ITRF_2005(ITRFVersion.ITRF_2020, ITRFVersion.ITRF_2005, 2015,
109                                2.7,  0.1,  -1.4,  0.00,  0.00,  0.00,
110                                0.3, -0.1,   0.1,  0.00,  0.00,  0.00),
111 
112         /** Transformation from ITRF 2020 To ITRF 2000. */
113         ITRF_2020_TO_ITRF_2000(ITRFVersion.ITRF_2020, ITRFVersion.ITRF_2000, 2015,
114                                -0.2,  0.8, -34.2,  0.00,  0.00,  0.00,
115                                 0.1,  0.0,  -1.7,  0.00,  0.00,  0.00),
116 
117         /** Transformation from ITRF 2020 To ITRF 97. */
118         ITRF_2020_TO_ITRF_1997(ITRFVersion.ITRF_2020, ITRFVersion.ITRF_1997, 2015,
119                                6.5, -3.9, -77.9,  0.00,  0.00,  0.36,
120                                0.1, -0.6,  -3.1,  0.00,  0.00,  0.02),
121 
122         /** Transformation from ITRF 2020 To ITRF 96. */
123         ITRF_2020_TO_ITRF_1996(ITRFVersion.ITRF_2020, ITRFVersion.ITRF_1996, 2015,
124                                6.5, -3.9, -77.9,  0.00,  0.00,  0.36,
125                                0.1, -0.6,  -3.1,  0.00,  0.00,  0.02),
126 
127         /** Transformation from ITRF 2020 To ITRF 94. */
128         ITRF_2020_TO_ITRF_1994(ITRFVersion.ITRF_2020, ITRFVersion.ITRF_1994, 2015,
129                                6.5, -3.9, -77.9,  0.00,  0.00,  0.36,
130                                0.1, -0.6,  -3.1,  0.00,  0.00,  0.02),
131 
132         /** Transformation from ITRF 2020 To ITRF 93. */
133         ITRF_2020_TO_ITRF_1993(ITRFVersion.ITRF_2020, ITRFVersion.ITRF_1993, 2015,
134                                -65.8,  1.9, -71.3, -3.36, -4.33,  0.75,
135                                 -2.8, -0.2,  -2.3, -0.11, -0.19,  0.07),
136 
137         /** Transformation from ITRF 2020 To ITRF 92. */
138         ITRF_2020_TO_ITRF_1992(ITRFVersion.ITRF_2020, ITRFVersion.ITRF_1992, 2015,
139                                14.5, -1.9, -85.9,  0.00,  0.00,  0.36,
140                                 0.1, -0.6,  -3.1,  0.00,  0.00,  0.02),
141 
142         /** Transformation from ITRF 2020 To ITRF 91. */
143         ITRF_2020_TO_ITRF_1991(ITRFVersion.ITRF_2020, ITRFVersion.ITRF_1991, 2015,
144                                26.5, 12.1, -91.9,  0.00,  0.00,  0.36,
145                                 0.1, -0.6,  -3.1,  0.00,  0.00,  0.02),
146 
147         /** Transformation from ITRF 2020 To ITRF 90. */
148         ITRF_2020_TO_ITRF_1990(ITRFVersion.ITRF_2020, ITRFVersion.ITRF_1990, 2015,
149                                24.5,  8.1, -107.9,  0.00,  0.00,  0.36,
150                                 0.1, -0.6,   -3.1,  0.00,  0.00,  0.02),
151 
152         /** Transformation from ITRF 2020 To ITRF 89. */
153         ITRF_2020_TO_ITRF_1989(ITRFVersion.ITRF_2020, ITRFVersion.ITRF_1989, 2015,
154                                29.5, 32.1, -145.9,  0.00,  0.00,  0.36,
155                                 0.1, -0.6,   -3.1,  0.00,  0.00,  0.02),
156 
157         /** Transformation from ITRF 2020 To ITRF 88. */
158         ITRF_2020_TO_ITRF_1988(ITRFVersion.ITRF_2020, ITRFVersion.ITRF_1988, 2015,
159                                24.5, -3.9, -169.9,  0.10,  0.00,  0.36,
160                                 0.1, -0.6,   -3.1,  0.00,  0.00,  0.02),
161 
162         // see http://itrf.ign.fr/doc_ITRF/Transfo-ITRF2014_ITRFs.txt
163         // SOLUTION         Tx       Ty       Tz        D        Rx        Ry        Rz      EPOCH
164         // UNITS----------> mm       mm       mm       ppb       .001"     .001"     .001"
165         //                  .        .        .         .        .         .         .
166         //        RATES     Tx       Ty       Tz        D        Rx        Ry        Rz
167         // UNITS----------> mm/y     mm/y     mm/y     ppb/y    .001"/y   .001"/y   .001"/y
168         // -----------------------------------------------------------------------------------------
169         //   ITRF2008        1.6      1.9      2.4     -0.02      0.00      0.00      0.00    2010.0
170         //        rates      0.0      0.0     -0.1      0.03      0.00      0.00      0.00
171         //   ITRF2005        2.6      1.0     -2.3      0.92      0.00      0.00      0.00    2010.0
172         //        rates      0.3      0.0     -0.1      0.03      0.00      0.00      0.00
173         //   ITRF2000        0.7      1.2    -26.1      2.12      0.00      0.00      0.00    2010.0
174         //        rates      0.1      0.1     -1.9      0.11      0.00      0.00      0.00
175         //   ITRF97          7.4     -0.5    -62.8      3.80      0.00      0.00      0.26    2010.0
176         //        rates      0.1     -0.5     -3.3      0.12      0.00      0.00      0.02
177         //   ITRF96          7.4     -0.5    -62.8      3.80      0.00      0.00      0.26    2010.0
178         //        rates      0.1     -0.5     -3.3      0.12      0.00      0.00      0.02
179         //   ITRF94          7.4     -0.5    -62.8      3.80      0.00      0.00      0.26    2010.0
180         //        rates      0.1     -0.5     -3.3      0.12      0.00      0.00      0.02
181         //   ITRF93        -50.4      3.3    -60.2      4.29     -2.81     -3.38      0.40    2010.0
182         //        rates     -2.8     -0.1     -2.5      0.12     -0.11     -0.19      0.07
183         //   ITRF92         15.4      1.5    -70.8      3.09      0.00      0.00      0.26    2010.0
184         //        rates      0.1     -0.5     -3.3      0.12      0.00      0.00      0.02
185         //   ITRF91         27.4     15.5    -76.8      4.49      0.00      0.00      0.26    2010.0
186         //        rates      0.1     -0.5     -3.3      0.12      0.00      0.00      0.02
187         //   ITRF90         25.4     11.5    -92.8      4.79      0.00      0.00      0.26    2010.0
188         //        rates      0.1     -0.5     -3.3      0.12      0.00      0.00      0.02
189         //   ITRF89         30.4     35.5   -130.8      8.19      0.00      0.00      0.26    2010.0
190         //        rates      0.1     -0.5     -3.3      0.12      0.00      0.00      0.02
191         //   ITRF88         25.4     -0.5   -154.8     11.29      0.10      0.00      0.26    2010.0
192         //        rates      0.1     -0.5     -3.3      0.12      0.00      0.00      0.02
193         // _________________________________________________________________________________________
194 
195         /** Transformation from ITRF 2014 To ITRF 2008. */
196         ITRF_2014_TO_ITRF_2008(ITRFVersion.ITRF_2014, ITRFVersion.ITRF_2008, 2010,
197                                 1.6, 1.9,     2.4, 0.00, 0.00, 0.00,
198                                 0.0, 0.0,    -0.1, 0.00, 0.00, 0.00),
199 
200         /** Transformation from ITRF 2014 To ITRF 2005. */
201         ITRF_2014_TO_ITRF_2005(ITRFVersion.ITRF_2014, ITRFVersion.ITRF_2005, 2010,
202                                 2.6, 1.0,    -2.3, 0.00, 0.00, 0.00,
203                                 0.3, 0.0,    -0.1, 0.00, 0.00, 0.00),
204 
205         /** Transformation from ITRF 2014 To ITRF 2000. */
206         ITRF_2014_TO_ITRF_2000(ITRFVersion.ITRF_2014, ITRFVersion.ITRF_2000, 2010,
207                                0.7, 1.2,   -26.1, 0.00, 0.00, 0.00,
208                                0.1, 0.1,    -1.9, 0.00, 0.00, 0.00),
209 
210         /** Transformation from ITRF 2014 To ITRF 97. */
211         ITRF_2014_TO_ITRF_1997(ITRFVersion.ITRF_2014, ITRFVersion.ITRF_1997, 2010,
212                                7.4, -0.5,  -62.8, 0.00, 0.00, 0.26,
213                                0.1, -0.5,   -3.3, 0.00, 0.00, 0.02),
214 
215         /** Transformation from ITRF 2014 To ITRF 96. */
216         ITRF_2014_TO_ITRF_1996(ITRFVersion.ITRF_2014, ITRFVersion.ITRF_1996, 2010,
217                                7.4, -0.5,  -62.8, 0.00, 0.00, 0.26,
218                                0.1, -0.5,  -3.3, 0.00, 0.00, 0.02),
219 
220         /** Transformation from ITRF 2014 To ITRF 94. */
221         ITRF_2014_TO_ITRF_1994(ITRFVersion.ITRF_2014, ITRFVersion.ITRF_1994, 2010,
222                                7.4, -0.5,  -62.8, 0.00, 0.00, 0.26,
223                                0.1, -0.5,   -3.3, 0.00, 0.00, 0.02),
224 
225         /** Transformation from ITRF 2014 To ITRF 93. */
226         ITRF_2014_TO_ITRF_1993(ITRFVersion.ITRF_2014, ITRFVersion.ITRF_1993, 2010,
227                                -50.4,  3.3,  -60.2, -2.81, -3.38, 0.40,
228                                -2.8, -0.1,   -2.5, -0.11, -0.19, 0.07),
229 
230         /** Transformation from ITRF 2014 To ITRF 92. */
231         ITRF_2014_TO_ITRF_1992(ITRFVersion.ITRF_2014, ITRFVersion.ITRF_1992, 2010,
232                                15.4,  1.5,  -70.8, 0.00, 0.00, 0.26,
233                                0.1, -0.5,   -3.3, 0.00, 0.00, 0.02),
234 
235         /** Transformation from ITRF 2014 To ITRF 91. */
236         ITRF_2014_TO_ITRF_1991(ITRFVersion.ITRF_2014, ITRFVersion.ITRF_1991, 2010,
237                                27.4, 15.5,  -76.8, 0.00, 0.00, 0.26,
238                                0.1, -0.5,   -3.3, 0.00, 0.00, 0.02),
239 
240         /** Transformation from ITRF 2014 To ITRF 90. */
241         ITRF_2014_TO_ITRF_1990(ITRFVersion.ITRF_2014, ITRFVersion.ITRF_1990, 2010,
242                                25.4, 11.5,  -92.8, 0.00, 0.00, 0.26,
243                                0.1, -0.5,   -3.3, 0.00, 0.00, 0.02),
244 
245         /** Transformation from ITRF 2014 To ITRF 89. */
246         ITRF_2014_TO_ITRF_1989(ITRFVersion.ITRF_2014, ITRFVersion.ITRF_1989, 2010,
247                                30.4, 35.5, -130.8, 0.00, 0.00, 0.26,
248                                0.1, -0.5,   -3.3, 0.00, 0.00, 0.02),
249 
250         /** Transformation from ITRF 2014 To ITRF 88. */
251         ITRF_2014_TO_ITRF_1988(ITRFVersion.ITRF_2014, ITRFVersion.ITRF_1988, 2010,
252                                25.4, -0.5, -154.8, 0.10, 0.00, 0.26,
253                                0.1, -0.5,   -3.3, 0.00, 0.00, 0.02),
254 
255         // see http://itrf.ensg.ign.fr/doc_ITRF/Transfo-ITRF2008_ITRFs.txt
256         // SOLUTION         Tx       Ty       Tz        D        Rx        Ry        Rz      EPOCH
257         // UNITS----------> mm       mm       mm       ppb       .001"     .001"     .001"
258         //                         .        .        .         .        .         .         .
259         //        RATES     Tx       Ty       Tz        D        Rx        Ry        Rz
260         // UNITS----------> mm/y     mm/y     mm/y     ppb/y    .001"/y   .001"/y   .001"/y
261         // -----------------------------------------------------------------------------------------
262         //   ITRF2005       -2.0     -0.9     -4.7      0.94      0.00      0.00      0.00    2000.0
263         //        rates      0.3      0.0      0.0      0.00      0.00      0.00      0.00
264         //   ITRF2000       -1.9     -1.7    -10.5      1.34      0.00      0.00      0.00    2000.0
265         //        rates      0.1      0.1     -1.8      0.08      0.00      0.00      0.00
266         //   ITRF97          4.8      2.6    -33.2      2.92      0.00      0.00      0.06    2000.0
267         //        rates      0.1     -0.5     -3.2      0.09      0.00      0.00      0.02
268         //   ITRF96          4.8      2.6    -33.2      2.92      0.00      0.00      0.06    2000.0
269         //        rates      0.1     -0.5     -3.2      0.09      0.00      0.00      0.02
270         //   ITRF94          4.8      2.6    -33.2      2.92      0.00      0.00      0.06    2000.0
271         //        rates      0.1     -0.5     -3.2      0.09      0.00      0.00      0.02
272         //   ITRF93        -24.0      2.4    -38.6      3.41     -1.71     -1.48     -0.30    2000.0
273         //        rates     -2.8     -0.1     -2.4      0.09     -0.11     -0.19      0.07
274         //   ITRF92         12.8      4.6    -41.2      2.21      0.00      0.00      0.06    2000.0
275         //        rates      0.1     -0.5     -3.2      0.09      0.00      0.00      0.02
276         //   ITRF91         24.8     18.6    -47.2      3.61      0.00      0.00      0.06    2000.0
277         //        rates      0.1     -0.5     -3.2      0.09      0.00      0.00      0.02
278         //   ITRF90         22.8     14.6    -63.2      3.91      0.00      0.00      0.06    2000.0
279         //        rates      0.1     -0.5     -3.2      0.09      0.00      0.00      0.02
280         //   ITRF89         27.8     38.6   -101.2      7.31      0.00      0.00      0.06    2000.0
281         //        rates      0.1     -0.5     -3.2      0.09      0.00      0.00      0.02
282         //   ITRF88         22.8      2.6   -125.2     10.41      0.10      0.00      0.06    2000.0
283         //        rates      0.1     -0.5     -3.2      0.09      0.00      0.00      0.02
284         // _________________________________________________________________________________________
285 
286         /** Transformation from ITRF 2008 To ITRF 2005. */
287         ITRF_2008_TO_ITRF_2005(ITRFVersion.ITRF_2008, ITRFVersion.ITRF_2005, 2000,
288                                -2.0, -0.9,   -4.7,  0.00,  0.00,  0.00,
289                                 0.3,  0.0,    0.0,  0.00,  0.00,  0.00),
290 
291         /** Transformation from ITRF 2008 To ITRF 2000. */
292         ITRF_2008_TO_ITRF_2000(ITRFVersion.ITRF_2008, ITRFVersion.ITRF_2000, 2000,
293                                -1.9, -1.7,  -10.5,  0.00,  0.00,  0.00,
294                                 0.1,  0.1,   -1.8,  0.00,  0.00,  0.00),
295 
296         /** Transformation from ITRF 2008 To ITRF 97. */
297         ITRF_2008_TO_ITRF_1997(ITRFVersion.ITRF_2008, ITRFVersion.ITRF_1997, 2000,
298                                4.8,  2.6,  -33.2,  0.00,  0.00,  0.06,
299                                0.1, -0.5,   -3.2,  0.00,  0.00,  0.02),
300 
301         /** Transformation from ITRF 2008 To ITRF 96. */
302         ITRF_2008_TO_ITRF_1996(ITRFVersion.ITRF_2008, ITRFVersion.ITRF_1996, 2000,
303                                4.8,  2.6,  -33.2,  0.00,  0.00,  0.06,
304                                0.1, -0.5,   -3.2,  0.00,  0.00,  0.02),
305 
306         /** Transformation from ITRF 2008 To ITRF 94. */
307         ITRF_2008_TO_ITRF_1994(ITRFVersion.ITRF_2008, ITRFVersion.ITRF_1994, 2000,
308                                4.8,  2.6,  -33.2,  0.00,  0.00,  0.06,
309                                0.1, -0.5,   -3.2,  0.00,  0.00,  0.02),
310 
311         /** Transformation from ITRF 2008 To ITRF 93. */
312         ITRF_2008_TO_ITRF_1993(ITRFVersion.ITRF_2008, ITRFVersion.ITRF_1993, 2000,
313                                -24.0,  2.4,  -38.6, -1.71, -1.48, -0.30,
314                                -2.8, -0.1,   -2.4, -0.11, -0.19,  0.07),
315 
316         /** Transformation from ITRF 2008 To ITRF 92. */
317         ITRF_2008_TO_ITRF_1992(ITRFVersion.ITRF_2008, ITRFVersion.ITRF_1992, 2000,
318                                12.8,  4.6,  -41.2,  0.00,  0.00,  0.06,
319                                0.1, -0.5,   -3.2,  0.00,  0.00,  0.02),
320 
321         /** Transformation from ITRF 2008 To ITRF 91. */
322         ITRF_2008_TO_ITRF_1991(ITRFVersion.ITRF_2008, ITRFVersion.ITRF_1991, 2000,
323                                24.8, 18.6,  -47.2,  0.00,  0.00,  0.06,
324                                0.1, -0.5,   -3.2,  0.00,  0.00,  0.02),
325 
326         /** Transformation from ITRF 2008 To ITRF 90. */
327         ITRF_2008_TO_ITRF_1990(ITRFVersion.ITRF_2008, ITRFVersion.ITRF_1990, 2000,
328                                22.8, 14.6,  -63.2,  0.00,  0.00,  0.06,
329                                0.1, -0.5,   -3.2,  0.00,  0.00,  0.02),
330 
331         /** Transformation from ITRF 2008 To ITRF 89. */
332         ITRF_2008_TO_ITRF_1989(ITRFVersion.ITRF_2008, ITRFVersion.ITRF_1989, 2000,
333                                27.8, 38.6, -101.2,  0.00,  0.00,  0.06,
334                                0.1, -0.5,   -3.2,  0.00,  0.00,  0.02),
335 
336         /** Transformation from ITRF 2008 To ITRF 88. */
337         ITRF_2008_TO_ITRF_1988(ITRFVersion.ITRF_2008, ITRFVersion.ITRF_1988, 2000,
338                                22.8,  2.6, -125.2,  0.10,  0.00,  0.06,
339                                0.1, -0.5,   -3.2,  0.00,  0.00,  0.02);
340 
341         /** Origin ITRF. */
342         private final ITRFVersion origin;
343 
344         /** Destination ITRF. */
345         private final ITRFVersion destination;
346 
347         /** Transformation. */
348         private final transient HelmertTransformationWithoutTimeScale transformation;
349 
350         /** Simple constructor.
351          * @param origin origin ITRF
352          * @param destination destination ITRF
353          * @param refYear reference year for the epoch of the transform
354          * @param t1 translation parameter along X axis (BEWARE, this is in mm)
355          * @param t2 translation parameter along Y axis (BEWARE, this is in mm)
356          * @param t3 translation parameter along Z axis (BEWARE, this is in mm)
357          * @param r1 rotation parameter around X axis (BEWARE, this is in mas)
358          * @param r2 rotation parameter around Y axis (BEWARE, this is in mas)
359          * @param r3 rotation parameter around Z axis (BEWARE, this is in mas)
360          * @param t1Dot rate of translation parameter along X axis (BEWARE, this is in mm/y)
361          * @param t2Dot rate of translation parameter along Y axis (BEWARE, this is in mm/y)
362          * @param t3Dot rate of translation parameter along Z axis (BEWARE, this is in mm/y)
363          * @param r1Dot rate of rotation parameter around X axis (BEWARE, this is in mas/y)
364          * @param r2Dot rate of rotation parameter around Y axis (BEWARE, this is in mas/y)
365          * @param r3Dot rate of rotation parameter around Z axis (BEWARE, this is in mas/y)
366          */
367         Predefined(final ITRFVersion origin, final ITRFVersion destination, final int refYear,
368                    final double t1, final double t2, final double t3,
369                    final double r1, final double r2, final double r3,
370                    final double t1Dot, final double t2Dot, final double t3Dot,
371                    final double r1Dot, final double r2Dot, final double r3Dot) {
372             this.origin         = origin;
373             this.destination    = destination;
374             this.transformation =
375                     new HelmertTransformationWithoutTimeScale(new DateTimeComponents(refYear, 1, 1, 12, 0, 0),
376                                               t1, t2, t3, r1, r2, r3, t1Dot, t2Dot, t3Dot, r1Dot, r2Dot, r3Dot);
377         }
378 
379         /** Get the origin ITRF.
380          * @return origin ITRF
381          * @since 9.2
382          */
383         public ITRFVersion getOrigin() {
384             return origin;
385         }
386 
387         /** Get the destination ITRF.
388          * @return destination ITRF
389          * @since 9.2
390          */
391         public ITRFVersion getDestination() {
392             return destination;
393         }
394 
395         /** Get the underlying {@link HelmertTransformation}.
396          *
397          * <p>This method uses the {@link DataContext#getDefault() default data context}.
398          *
399          * @return underlying {@link HelmertTransformation}
400          * @since 9.2
401          * @see #getTransformation(TimeScale)
402          */
403         @DefaultDataContext
404         public HelmertTransformation getTransformation() {
405             return getTransformation(DataContext.getDefault().getTimeScales().getTT());
406         }
407 
408         /** Get the underlying {@link HelmertTransformation}.
409          * @return underlying {@link HelmertTransformation}
410          * @param tt TT time scale.
411          * @since 10.1
412          */
413         public HelmertTransformation getTransformation(final TimeScale tt) {
414             return transformation.withTimeScale(tt);
415         }
416 
417         /** Create an ITRF frame by transforming another ITRF frame.
418          *
419          * <p>This method uses the {@link DataContext#getDefault() default data context}.
420          *
421          * @param parent parent ITRF frame
422          * @param name name of the frame to create
423          * @return new ITRF frame
424          * @see #createTransformedITRF(Frame, String, TimeScale)
425          */
426         @DefaultDataContext
427         public Frame createTransformedITRF(final Frame parent, final String name) {
428             return createTransformedITRF(parent, name,
429                     DataContext.getDefault().getTimeScales().getTT());
430         }
431 
432         /** Create an ITRF frame by transforming another ITRF frame.
433          * @param parent parent ITRF frame
434          * @param name name of the frame to create
435          * @param tt TT time scale.
436          * @return new ITRF frame
437          * @since 10.1
438          */
439         public Frame createTransformedITRF(final Frame parent,
440                                            final String name,
441                                            final TimeScale tt) {
442             return new Frame(parent, getTransformation(tt), name);
443         }
444 
445         /** Select a predefined transform between two years.
446          * @param origin origin year
447          * @param destination destination year
448          * @return predefined transform from origin to destination, or null if no such predefined transform exist
449          * @since 11.2
450          */
451         public static Predefined selectPredefined(final int origin, final int destination) {
452             final Optional<HelmertTransformation.Predefined> optional =
453                             Stream.
454                             of(HelmertTransformation.Predefined.values()).
455                             filter(p -> p.getOrigin().getYear() == origin && p.getDestination().getYear() == destination).
456                             findFirst();
457             return optional.isPresent() ? optional.get() : null;
458         }
459 
460     }
461 
462     /**
463      * A {@link HelmertTransformation} without reference to a {@link TimeScale}. This
464      * class is needed to maintain compatibility with Orekit 10.0 since {@link Predefined}
465      * is an enum and it had a reference to the TT time scale.
466      */
467     private static class HelmertTransformationWithoutTimeScale {
468 
469         /** Cartesian part of the transform. */
470         private final PVCoordinates cartesian;
471 
472         /** Global rotation vector (applying rotation is done by computing cross product). */
473         private final Vector3D rotationVector;
474 
475         /** First time derivative of the rotation (norm representing angular rate). */
476         private final Vector3D rotationRate;
477 
478         /** Reference epoch of the transform. */
479         private final DateTimeComponents epoch;
480 
481         /** Build a transform from its primitive operations.
482          * @param epoch reference epoch of the transform
483          * @param t1 translation parameter along X axis (BEWARE, this is in mm)
484          * @param t2 translation parameter along Y axis (BEWARE, this is in mm)
485          * @param t3 translation parameter along Z axis (BEWARE, this is in mm)
486          * @param r1 rotation parameter around X axis (BEWARE, this is in mas)
487          * @param r2 rotation parameter around Y axis (BEWARE, this is in mas)
488          * @param r3 rotation parameter around Z axis (BEWARE, this is in mas)
489          * @param t1Dot rate of translation parameter along X axis (BEWARE, this is in mm/y)
490          * @param t2Dot rate of translation parameter along Y axis (BEWARE, this is in mm/y)
491          * @param t3Dot rate of translation parameter along Z axis (BEWARE, this is in mm/y)
492          * @param r1Dot rate of rotation parameter around X axis (BEWARE, this is in mas/y)
493          * @param r2Dot rate of rotation parameter around Y axis (BEWARE, this is in mas/y)
494          * @param r3Dot rate of rotation parameter around Z axis (BEWARE, this is in mas/y)
495          */
496         HelmertTransformationWithoutTimeScale(
497                 final DateTimeComponents epoch,
498                 final double t1, final double t2, final double t3,
499                 final double r1, final double r2, final double r3,
500                 final double t1Dot, final double t2Dot, final double t3Dot,
501                 final double r1Dot, final double r2Dot, final double r3Dot) {
502 
503             // conversion parameters to SI units
504             final double mmToM    = 1.0e-3;
505             final double masToRad = 1.0e-3 * Constants.ARC_SECONDS_TO_RADIANS;
506 
507             this.epoch          = epoch;
508             this.cartesian = new PVCoordinates(new Vector3D(t1 * mmToM,
509                     t2 * mmToM,
510                     t3 * mmToM),
511                     new Vector3D(t1Dot * mmToM / Constants.JULIAN_YEAR,
512                             t2Dot * mmToM / Constants.JULIAN_YEAR,
513                             t3Dot * mmToM / Constants.JULIAN_YEAR));
514             this.rotationVector = new Vector3D(r1 * masToRad,
515                     r2 * masToRad,
516                     r3 * masToRad);
517             this.rotationRate   = new Vector3D(r1Dot * masToRad / Constants.JULIAN_YEAR,
518                     r2Dot * masToRad / Constants.JULIAN_YEAR,
519                     r3Dot * masToRad / Constants.JULIAN_YEAR);
520 
521         }
522 
523         /**
524          * Get the Helmert transformation with reference to the given time scale.
525          *
526          * @param tt TT time scale.
527          * @return Helmert transformation.
528          */
529         public HelmertTransformation withTimeScale(final TimeScale tt) {
530             return new HelmertTransformation(cartesian, rotationVector, rotationRate,
531                     new AbsoluteDate(epoch, tt));
532         }
533 
534     }
535 
536     /** Cartesian part of the transform. */
537     private final PVCoordinates cartesian;
538 
539     /** Global rotation vector (applying rotation is done by computing cross product). */
540     private final Vector3D rotationVector;
541 
542     /** First time derivative of the rotation (norm representing angular rate). */
543     private final Vector3D rotationRate;
544 
545     /** Reference epoch of the transform. */
546     private final AbsoluteDate epoch;
547 
548     /** Build a transform from its primitive operations.
549      * @param epoch reference epoch of the transform
550      * @param t1 translation parameter along X axis (BEWARE, this is in mm)
551      * @param t2 translation parameter along Y axis (BEWARE, this is in mm)
552      * @param t3 translation parameter along Z axis (BEWARE, this is in mm)
553      * @param r1 rotation parameter around X axis (BEWARE, this is in mas)
554      * @param r2 rotation parameter around Y axis (BEWARE, this is in mas)
555      * @param r3 rotation parameter around Z axis (BEWARE, this is in mas)
556      * @param t1Dot rate of translation parameter along X axis (BEWARE, this is in mm/y)
557      * @param t2Dot rate of translation parameter along Y axis (BEWARE, this is in mm/y)
558      * @param t3Dot rate of translation parameter along Z axis (BEWARE, this is in mm/y)
559      * @param r1Dot rate of rotation parameter around X axis (BEWARE, this is in mas/y)
560      * @param r2Dot rate of rotation parameter around Y axis (BEWARE, this is in mas/y)
561      * @param r3Dot rate of rotation parameter around Z axis (BEWARE, this is in mas/y)
562      */
563     public HelmertTransformation(final AbsoluteDate epoch,
564                                  final double t1, final double t2, final double t3,
565                                  final double r1, final double r2, final double r3,
566                                  final double t1Dot, final double t2Dot, final double t3Dot,
567                                  final double r1Dot, final double r2Dot, final double r3Dot) {
568 
569         // conversion parameters to SI units
570         final double mmToM    = 1.0e-3;
571         final double masToRad = 1.0e-3 * Constants.ARC_SECONDS_TO_RADIANS;
572 
573         this.epoch          = epoch;
574         this.cartesian = new PVCoordinates(new Vector3D(t1 * mmToM,
575                                                         t2 * mmToM,
576                                                         t3 * mmToM),
577                                            new Vector3D(t1Dot * mmToM / Constants.JULIAN_YEAR,
578                                                         t2Dot * mmToM / Constants.JULIAN_YEAR,
579                                                         t3Dot * mmToM / Constants.JULIAN_YEAR));
580         this.rotationVector = new Vector3D(r1 * masToRad,
581                                            r2 * masToRad,
582                                            r3 * masToRad);
583         this.rotationRate   = new Vector3D(r1Dot * masToRad / Constants.JULIAN_YEAR,
584                                            r2Dot * masToRad / Constants.JULIAN_YEAR,
585                                            r3Dot * masToRad / Constants.JULIAN_YEAR);
586 
587     }
588 
589     /**
590      * Private constructor.
591      *
592      * @param cartesian      part of the transform.
593      * @param rotationVector global rotation vector.
594      * @param rotationRate   time derivative of rotation.
595      * @param epoch          of transform.
596      */
597     private HelmertTransformation(final PVCoordinates cartesian,
598                                   final Vector3D rotationVector,
599                                   final Vector3D rotationRate,
600                                   final AbsoluteDate epoch) {
601         this.cartesian = cartesian;
602         this.rotationVector = rotationVector;
603         this.rotationRate = rotationRate;
604         this.epoch = epoch;
605     }
606 
607     /** Get the reference epoch of the transform.
608      * @return reference epoch of the transform
609      */
610     public AbsoluteDate getEpoch() {
611         return epoch;
612     }
613 
614     /** {@inheritDoc} */
615     @Override
616     public Transform getTransform(final AbsoluteDate date) {
617 
618         // compute parameters evolution since reference epoch
619         final double dt = date.durationFrom(epoch);
620         final Vector3D dR = new Vector3D(1, rotationVector, dt, rotationRate);
621 
622         // build translation part
623         final Transform translationTransform = new Transform(date, cartesian.shiftedBy(dt));
624 
625         // build rotation part
626         final double angle = dR.getNorm();
627         final Transform rotationTransform =
628                 new Transform(date,
629                               (angle < Precision.SAFE_MIN) ?
630                               Rotation.IDENTITY :
631                               new Rotation(dR, angle, RotationConvention.VECTOR_OPERATOR),
632                               rotationRate);
633 
634         // combine both parts
635         return new Transform(date, translationTransform, rotationTransform);
636 
637     }
638 
639     /** {@inheritDoc} */
640     @Override
641     public StaticTransform getStaticTransform(final AbsoluteDate date) {
642 
643         // compute parameters evolution since reference epoch
644         final double dt = date.durationFrom(epoch);
645         final Vector3D dR = new Vector3D(1, rotationVector, dt, rotationRate);
646 
647         // build translation part
648         final Vector3D translation = cartesian.shiftedBy(dt).getPosition();
649 
650         // build rotation part
651         final double angle = dR.getNorm();
652         final Rotation rotation = (angle < Precision.SAFE_MIN) ?
653                 Rotation.IDENTITY :
654                 new Rotation(dR, angle, RotationConvention.VECTOR_OPERATOR);
655 
656         // combine both parts
657         return StaticTransform.of(date, translation, rotation);
658 
659     }
660 
661     /** {@inheritDoc} */
662     @Override
663     public <T extends CalculusFieldElement<T>> FieldTransform<T> getTransform(final FieldAbsoluteDate<T> date) {
664 
665         // compute parameters evolution since reference epoch
666         final T dt = date.durationFrom(epoch);
667         final FieldVector3D<T> dR = new FieldVector3D<>(date.getField().getOne(), rotationVector,
668                                                         dt, rotationRate);
669 
670         // build translation part
671         final FieldTransform<T> translationTransform =
672                         new FieldTransform<>(date,
673                                              new FieldPVCoordinates<>(date.getField(), cartesian).shiftedBy(dt));
674 
675         // build rotation part
676         final T angle = dR.getNorm();
677         final FieldTransform<T> rotationTransform =
678                 new FieldTransform<>(date,
679                                     (angle.getReal() < Precision.SAFE_MIN) ?
680                                      FieldRotation.getIdentity(date.getField()) :
681                                     new FieldRotation<>(dR, angle, RotationConvention.VECTOR_OPERATOR),
682                                     new FieldVector3D<>(date.getField(), rotationRate));
683 
684         // combine both parts
685         return new FieldTransform<>(date, translationTransform, rotationTransform);
686 
687     }
688 
689     /** {@inheritDoc} */
690     @Override
691     public <T extends CalculusFieldElement<T>> FieldStaticTransform<T> getStaticTransform(final FieldAbsoluteDate<T> date) {
692 
693         // field
694         final Field<T> field = date.getField();
695 
696         // compute parameters evolution since reference epoch
697         final T dt = date.durationFrom(epoch);
698         final FieldVector3D<T> dR = new FieldVector3D<>(field.getOne(), rotationVector, dt, rotationRate);
699 
700         // build translation part
701         final FieldVector3D<T> translation = new FieldPVCoordinates<>(date.getField(), cartesian).shiftedBy(dt).getPosition();
702 
703         // build rotation part
704         final T angle = dR.getNorm();
705         final FieldRotation<T> rotation = (angle.getReal() < Precision.SAFE_MIN) ?
706                 FieldRotation.getIdentity(field) :
707                 new FieldRotation<>(dR, angle, RotationConvention.VECTOR_OPERATOR);
708 
709         // combine both parts
710         return FieldStaticTransform.of(date, translation, rotation);
711 
712     }
713 
714 }