1 /* Copyright 2002-2021 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 org.hipparchus.CalculusFieldElement;
20 import org.hipparchus.geometry.euclidean.threed.FieldRotation;
21 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
22 import org.hipparchus.geometry.euclidean.threed.Rotation;
23 import org.hipparchus.geometry.euclidean.threed.RotationConvention;
24 import org.hipparchus.geometry.euclidean.threed.Vector3D;
25 import org.hipparchus.util.Precision;
26 import org.orekit.annotation.DefaultDataContext;
27 import org.orekit.data.DataContext;
28 import org.orekit.time.AbsoluteDate;
29 import org.orekit.time.DateTimeComponents;
30 import org.orekit.time.FieldAbsoluteDate;
31 import org.orekit.time.TimeScale;
32 import org.orekit.utils.Constants;
33 import org.orekit.utils.FieldPVCoordinates;
34 import org.orekit.utils.PVCoordinates;
35
36
37 /** Transformation class for geodetic systems.
38 *
39 * <p>The Helmert transformation is mainly used to convert between various
40 * realizations of geodetic frames, for example in the ITRF family.</p>
41 *
42 * <p>The original Helmert transformation is a 14 parameters transform that
43 * includes translation, velocity, rotation, rotation rate and scale factor.
44 * The scale factor is useful for coordinates near Earth surface, but it
45 * cannot be extended to outer space as it would correspond to a non-unitary
46 * transform. Therefore, the scale factor is <em>not</em> used here.
47 *
48 * <p>Instances of this class are guaranteed to be immutable.</p>
49 *
50 * @author Luc Maisonobe
51 * @since 5.1
52 */
53 public class HelmertTransformation implements TransformProvider {
54
55 /** serializable UID. */
56 private static final long serialVersionUID = -1900615992141291146L;
57
58 /** Enumerate for predefined Helmert transformations. */
59 public enum Predefined {
60
61 // see http://itrf.ign.fr/doc_ITRF/Transfo-ITRF2014_ITRFs.txt
62 // SOLUTION Tx Ty Tz D Rx Ry Rz EPOCH
63 // UNITS----------> mm mm mm ppb .001" .001" .001"
64 // . . . . . . .
65 // RATES Tx Ty Tz D Rx Ry Rz
66 // UNITS----------> mm/y mm/y mm/y ppb/y .001"/y .001"/y .001"/y
67 // -----------------------------------------------------------------------------------------
68 // ITRF2008 1.6 1.9 2.4 -0.02 0.00 0.00 0.00 2010.0
69 // rates 0.0 0.0 -0.1 0.03 0.00 0.00 0.00
70 // ITRF2005 2.6 1.0 -2.3 0.92 0.00 0.00 0.00 2010.0
71 // rates 0.3 0.0 -0.1 0.03 0.00 0.00 0.00
72 // ITRF2000 0.7 1.2 -26.1 2.12 0.00 0.00 0.00 2010.0
73 // rates 0.1 0.1 -1.9 0.11 0.00 0.00 0.00
74 // ITRF97 7.4 -0.5 -62.8 3.80 0.00 0.00 0.26 2010.0
75 // rates 0.1 -0.5 -3.3 0.12 0.00 0.00 0.02
76 // ITRF96 7.4 -0.5 -62.8 3.80 0.00 0.00 0.26 2010.0
77 // rates 0.1 -0.5 -3.3 0.12 0.00 0.00 0.02
78 // ITRF94 7.4 -0.5 -62.8 3.80 0.00 0.00 0.26 2010.0
79 // rates 0.1 -0.5 -3.3 0.12 0.00 0.00 0.02
80 // ITRF93 -50.4 3.3 -60.2 4.29 -2.81 -3.38 0.40 2010.0
81 // rates -2.8 -0.1 -2.5 0.12 -0.11 -0.19 0.07
82 // ITRF92 15.4 1.5 -70.8 3.09 0.00 0.00 0.26 2010.0
83 // rates 0.1 -0.5 -3.3 0.12 0.00 0.00 0.02
84 // ITRF91 27.4 15.5 -76.8 4.49 0.00 0.00 0.26 2010.0
85 // rates 0.1 -0.5 -3.3 0.12 0.00 0.00 0.02
86 // ITRF90 25.4 11.5 -92.8 4.79 0.00 0.00 0.26 2010.0
87 // rates 0.1 -0.5 -3.3 0.12 0.00 0.00 0.02
88 // ITRF89 30.4 35.5 -130.8 8.19 0.00 0.00 0.26 2010.0
89 // rates 0.1 -0.5 -3.3 0.12 0.00 0.00 0.02
90 // ITRF88 25.4 -0.5 -154.8 11.29 0.10 0.00 0.26 2010.0
91 // rates 0.1 -0.5 -3.3 0.12 0.00 0.00 0.02
92 // _________________________________________________________________________________________
93
94 /** Transformation from ITRF 2014 To ITRF 2008. */
95 ITRF_2014_TO_ITRF_2008(ITRFVersion.ITRF_2014, ITRFVersion.ITRF_2008, 2010,
96 1.6, 1.9, 2.4, 0.00, 0.00, 0.00,
97 0.0, 0.0, -0.1, 0.00, 0.00, 0.00),
98
99 /** Transformation from ITRF 2014 To ITRF 2005. */
100 ITRF_2014_TO_ITRF_2005(ITRFVersion.ITRF_2014, ITRFVersion.ITRF_2005, 2010,
101 2.6, 1.0, -2.3, 0.00, 0.00, 0.00,
102 0.3, 0.0, -0.1, 0.00, 0.00, 0.00),
103
104 /** Transformation from ITRF 2014 To ITRF 2000. */
105 ITRF_2014_TO_ITRF_2000(ITRFVersion.ITRF_2014, ITRFVersion.ITRF_2000, 2010,
106 0.7, 1.2, -26.1, 0.00, 0.00, 0.00,
107 0.1, 0.1, -1.9, 0.00, 0.00, 0.00),
108
109 /** Transformation from ITRF 2014 To ITRF 97. */
110 ITRF_2014_TO_ITRF_1997(ITRFVersion.ITRF_2014, ITRFVersion.ITRF_1997, 2010,
111 7.4, -0.5, -62.8, 0.00, 0.00, 0.26,
112 0.1, -0.5, -3.3, 0.00, 0.00, 0.02),
113
114 /** Transformation from ITRF 2014 To ITRF 96. */
115 ITRF_2014_TO_ITRF_1996(ITRFVersion.ITRF_2014, ITRFVersion.ITRF_1996, 2010,
116 7.4, -0.5, -62.8, 0.00, 0.00, 0.26,
117 0.1, -0.5, -3.3, 0.00, 0.00, 0.02),
118
119 /** Transformation from ITRF 2014 To ITRF 94. */
120 ITRF_2014_TO_ITRF_1994(ITRFVersion.ITRF_2014, ITRFVersion.ITRF_1994, 2010,
121 7.4, -0.5, -62.8, 0.00, 0.00, 0.26,
122 0.1, -0.5, -3.3, 0.00, 0.00, 0.02),
123
124 /** Transformation from ITRF 2014 To ITRF 93. */
125 ITRF_2014_TO_ITRF_1993(ITRFVersion.ITRF_2014, ITRFVersion.ITRF_1993, 2010,
126 -50.4, 3.3, -60.2, -2.81, -3.38, 0.40,
127 -2.8, -0.1, -2.5, -0.11, -0.19, 0.07),
128
129 /** Transformation from ITRF 2014 To ITRF 92. */
130 ITRF_2014_TO_ITRF_1992(ITRFVersion.ITRF_2014, ITRFVersion.ITRF_1992, 2010,
131 15.4, 1.5, -70.8, 0.00, 0.00, 0.26,
132 0.1, -0.5, -3.3, 0.00, 0.00, 0.02),
133
134 /** Transformation from ITRF 2014 To ITRF 91. */
135 ITRF_2014_TO_ITRF_1991(ITRFVersion.ITRF_2014, ITRFVersion.ITRF_1991, 2010,
136 27.4, 15.5, -76.8, 0.00, 0.00, 0.26,
137 0.1, -0.5, -3.3, 0.00, 0.00, 0.02),
138
139 /** Transformation from ITRF 2014 To ITRF 90. */
140 ITRF_2014_TO_ITRF_1990(ITRFVersion.ITRF_2014, ITRFVersion.ITRF_1990, 2010,
141 25.4, 11.5, -92.8, 0.00, 0.00, 0.26,
142 0.1, -0.5, -3.3, 0.00, 0.00, 0.02),
143
144 /** Transformation from ITRF 2014 To ITRF 89. */
145 ITRF_2014_TO_ITRF_1989(ITRFVersion.ITRF_2014, ITRFVersion.ITRF_1989, 2010,
146 30.4, 35.5, -130.8, 0.00, 0.00, 0.26,
147 0.1, -0.5, -3.3, 0.00, 0.00, 0.02),
148
149 /** Transformation from ITRF 2014 To ITRF 88. */
150 ITRF_2014_TO_ITRF_1988(ITRFVersion.ITRF_2014, ITRFVersion.ITRF_1988, 2010,
151 25.4, -0.5, -154.8, 0.10, 0.00, 0.26,
152 0.1, -0.5, -3.3, 0.00, 0.00, 0.02),
153
154 // see http://itrf.ensg.ign.fr/doc_ITRF/Transfo-ITRF2008_ITRFs.txt
155 // SOLUTION Tx Ty Tz D Rx Ry Rz EPOCH
156 // UNITS----------> mm mm mm ppb .001" .001" .001"
157 // . . . . . . .
158 // RATES Tx Ty Tz D Rx Ry Rz
159 // UNITS----------> mm/y mm/y mm/y ppb/y .001"/y .001"/y .001"/y
160 // -----------------------------------------------------------------------------------------
161 // ITRF2005 -2.0 -0.9 -4.7 0.94 0.00 0.00 0.00 2000.0
162 // rates 0.3 0.0 0.0 0.00 0.00 0.00 0.00
163 // ITRF2000 -1.9 -1.7 -10.5 1.34 0.00 0.00 0.00 2000.0
164 // rates 0.1 0.1 -1.8 0.08 0.00 0.00 0.00
165 // ITRF97 4.8 2.6 -33.2 2.92 0.00 0.00 0.06 2000.0
166 // rates 0.1 -0.5 -3.2 0.09 0.00 0.00 0.02
167 // ITRF96 4.8 2.6 -33.2 2.92 0.00 0.00 0.06 2000.0
168 // rates 0.1 -0.5 -3.2 0.09 0.00 0.00 0.02
169 // ITRF94 4.8 2.6 -33.2 2.92 0.00 0.00 0.06 2000.0
170 // rates 0.1 -0.5 -3.2 0.09 0.00 0.00 0.02
171 // ITRF93 -24.0 2.4 -38.6 3.41 -1.71 -1.48 -0.30 2000.0
172 // rates -2.8 -0.1 -2.4 0.09 -0.11 -0.19 0.07
173 // ITRF92 12.8 4.6 -41.2 2.21 0.00 0.00 0.06 2000.0
174 // rates 0.1 -0.5 -3.2 0.09 0.00 0.00 0.02
175 // ITRF91 24.8 18.6 -47.2 3.61 0.00 0.00 0.06 2000.0
176 // rates 0.1 -0.5 -3.2 0.09 0.00 0.00 0.02
177 // ITRF90 22.8 14.6 -63.2 3.91 0.00 0.00 0.06 2000.0
178 // rates 0.1 -0.5 -3.2 0.09 0.00 0.00 0.02
179 // ITRF89 27.8 38.6 -101.2 7.31 0.00 0.00 0.06 2000.0
180 // rates 0.1 -0.5 -3.2 0.09 0.00 0.00 0.02
181 // ITRF88 22.8 2.6 -125.2 10.41 0.10 0.00 0.06 2000.0
182 // rates 0.1 -0.5 -3.2 0.09 0.00 0.00 0.02
183 // _________________________________________________________________________________________
184
185 /** Transformation from ITRF 2008 To ITRF 2005. */
186 ITRF_2008_TO_ITRF_2005(ITRFVersion.ITRF_2008, ITRFVersion.ITRF_2005, 2000,
187 -2.0, -0.9, -4.7, 0.00, 0.00, 0.00,
188 0.3, 0.0, 0.0, 0.00, 0.00, 0.00),
189
190 /** Transformation from ITRF 2008 To ITRF 2000. */
191 ITRF_2008_TO_ITRF_2000(ITRFVersion.ITRF_2008, ITRFVersion.ITRF_2000, 2000,
192 -1.9, -1.7, -10.5, 0.00, 0.00, 0.00,
193 0.1, 0.1, -1.8, 0.00, 0.00, 0.00),
194
195 /** Transformation from ITRF 2008 To ITRF 97. */
196 ITRF_2008_TO_ITRF_1997(ITRFVersion.ITRF_2008, ITRFVersion.ITRF_1997, 2000,
197 4.8, 2.6, -33.2, 0.00, 0.00, 0.06,
198 0.1, -0.5, -3.2, 0.00, 0.00, 0.02),
199
200 /** Transformation from ITRF 2008 To ITRF 96. */
201 ITRF_2008_TO_ITRF_1996(ITRFVersion.ITRF_2008, ITRFVersion.ITRF_1996, 2000,
202 4.8, 2.6, -33.2, 0.00, 0.00, 0.06,
203 0.1, -0.5, -3.2, 0.00, 0.00, 0.02),
204
205 /** Transformation from ITRF 2008 To ITRF 94. */
206 ITRF_2008_TO_ITRF_1994(ITRFVersion.ITRF_2008, ITRFVersion.ITRF_1994, 2000,
207 4.8, 2.6, -33.2, 0.00, 0.00, 0.06,
208 0.1, -0.5, -3.2, 0.00, 0.00, 0.02),
209
210 /** Transformation from ITRF 2008 To ITRF 93. */
211 ITRF_2008_TO_ITRF_1993(ITRFVersion.ITRF_2008, ITRFVersion.ITRF_1993, 2000,
212 -24.0, 2.4, -38.6, -1.71, -1.48, -0.30,
213 -2.8, -0.1, -2.4, -0.11, -0.19, 0.07),
214
215 /** Transformation from ITRF 2008 To ITRF 92. */
216 ITRF_2008_TO_ITRF_1992(ITRFVersion.ITRF_2008, ITRFVersion.ITRF_1992, 2000,
217 12.8, 4.6, -41.2, 0.00, 0.00, 0.06,
218 0.1, -0.5, -3.2, 0.00, 0.00, 0.02),
219
220 /** Transformation from ITRF 2008 To ITRF 91. */
221 ITRF_2008_TO_ITRF_1991(ITRFVersion.ITRF_2008, ITRFVersion.ITRF_1991, 2000,
222 24.8, 18.6, -47.2, 0.00, 0.00, 0.06,
223 0.1, -0.5, -3.2, 0.00, 0.00, 0.02),
224
225 /** Transformation from ITRF 2008 To ITRF 90. */
226 ITRF_2008_TO_ITRF_1990(ITRFVersion.ITRF_2008, ITRFVersion.ITRF_1990, 2000,
227 22.8, 14.6, -63.2, 0.00, 0.00, 0.06,
228 0.1, -0.5, -3.2, 0.00, 0.00, 0.02),
229
230 /** Transformation from ITRF 2008 To ITRF 89. */
231 ITRF_2008_TO_ITRF_1989(ITRFVersion.ITRF_2008, ITRFVersion.ITRF_1989, 2000,
232 27.8, 38.6, -101.2, 0.00, 0.00, 0.06,
233 0.1, -0.5, -3.2, 0.00, 0.00, 0.02),
234
235 /** Transformation from ITRF 2008 To ITRF 88. */
236 ITRF_2008_TO_ITRF_1988(ITRFVersion.ITRF_2008, ITRFVersion.ITRF_1988, 2000,
237 22.8, 2.6, -125.2, 0.10, 0.00, 0.06,
238 0.1, -0.5, -3.2, 0.00, 0.00, 0.02);
239
240 /** Origin ITRF. */
241 private final ITRFVersion origin;
242
243 /** Destination ITRF. */
244 private final ITRFVersion destination;
245
246 /** Transformation. */
247 private final transient HelmertTransformationWithoutTimeScale transformation;
248
249 /** Simple constructor.
250 * @param origin origin ITRF
251 * @param destination destination ITRF
252 * @param refYear reference year for the epoch of the transform
253 * @param t1 translation parameter along X axis (BEWARE, this is in mm)
254 * @param t2 translation parameter along Y axis (BEWARE, this is in mm)
255 * @param t3 translation parameter along Z axis (BEWARE, this is in mm)
256 * @param r1 rotation parameter around X axis (BEWARE, this is in mas)
257 * @param r2 rotation parameter around Y axis (BEWARE, this is in mas)
258 * @param r3 rotation parameter around Z axis (BEWARE, this is in mas)
259 * @param t1Dot rate of translation parameter along X axis (BEWARE, this is in mm/y)
260 * @param t2Dot rate of translation parameter along Y axis (BEWARE, this is in mm/y)
261 * @param t3Dot rate of translation parameter along Z axis (BEWARE, this is in mm/y)
262 * @param r1Dot rate of rotation parameter around X axis (BEWARE, this is in mas/y)
263 * @param r2Dot rate of rotation parameter around Y axis (BEWARE, this is in mas/y)
264 * @param r3Dot rate of rotation parameter around Z axis (BEWARE, this is in mas/y)
265 */
266 Predefined(final ITRFVersion origin, final ITRFVersion destination, final int refYear,
267 final double t1, final double t2, final double t3,
268 final double r1, final double r2, final double r3,
269 final double t1Dot, final double t2Dot, final double t3Dot,
270 final double r1Dot, final double r2Dot, final double r3Dot) {
271 this.origin = origin;
272 this.destination = destination;
273 this.transformation =
274 new HelmertTransformationWithoutTimeScale(new DateTimeComponents(refYear, 1, 1, 12, 0, 0),
275 t1, t2, t3, r1, r2, r3, t1Dot, t2Dot, t3Dot, r1Dot, r2Dot, r3Dot);
276 }
277
278 /** Get the origin ITRF.
279 * @return origin ITRF
280 * @since 9.2
281 */
282 public ITRFVersion getOrigin() {
283 return origin;
284 }
285
286 /** Get the destination ITRF.
287 * @return destination ITRF
288 * @since 9.2
289 */
290 public ITRFVersion getDestination() {
291 return destination;
292 }
293
294 /** Get the underlying {@link HelmertTransformation}.
295 *
296 * <p>This method uses the {@link DataContext#getDefault() default data context}.
297 *
298 * @return underlying {@link HelmertTransformation}
299 * @since 9.2
300 * @see #getTransformation(TimeScale)
301 */
302 @DefaultDataContext
303 public HelmertTransformation getTransformation() {
304 return getTransformation(DataContext.getDefault().getTimeScales().getTT());
305 }
306
307 /** Get the underlying {@link HelmertTransformation}.
308 * @return underlying {@link HelmertTransformation}
309 * @param tt TT time scale.
310 * @since 10.1
311 */
312 public HelmertTransformation getTransformation(final TimeScale tt) {
313 return transformation.withTimeScale(tt);
314 }
315
316 /** Create an ITRF frame by transforming another ITRF frame.
317 *
318 * <p>This method uses the {@link DataContext#getDefault() default data context}.
319 *
320 * @param parent parent ITRF frame
321 * @param name name of the frame to create
322 * @return new ITRF frame
323 * @see #createTransformedITRF(Frame, String, TimeScale)
324 */
325 @DefaultDataContext
326 public Frame createTransformedITRF(final Frame parent, final String name) {
327 return createTransformedITRF(parent, name,
328 DataContext.getDefault().getTimeScales().getTT());
329 }
330
331 /** Create an ITRF frame by transforming another ITRF frame.
332 * @param parent parent ITRF frame
333 * @param name name of the frame to create
334 * @param tt TT time scale.
335 * @return new ITRF frame
336 * @since 10.1
337 */
338 public Frame createTransformedITRF(final Frame parent,
339 final String name,
340 final TimeScale tt) {
341 return new Frame(parent, getTransformation(tt), name);
342 }
343
344 }
345
346 /**
347 * A {@link HelmertTransformation} without reference to a {@link TimeScale}. This
348 * class is needed to maintain compatibility with Orekit 10.0 since {@link Predefined}
349 * is an enum and it had a reference to the TT time scale.
350 */
351 private static class HelmertTransformationWithoutTimeScale {
352
353 /** Cartesian part of the transform. */
354 private final PVCoordinates cartesian;
355
356 /** Global rotation vector (applying rotation is done by computing cross product). */
357 private final Vector3D rotationVector;
358
359 /** First time derivative of the rotation (norm representing angular rate). */
360 private final Vector3D rotationRate;
361
362 /** Reference epoch of the transform. */
363 private final DateTimeComponents epoch;
364
365 /** Build a transform from its primitive operations.
366 * @param epoch reference epoch of the transform
367 * @param t1 translation parameter along X axis (BEWARE, this is in mm)
368 * @param t2 translation parameter along Y axis (BEWARE, this is in mm)
369 * @param t3 translation parameter along Z axis (BEWARE, this is in mm)
370 * @param r1 rotation parameter around X axis (BEWARE, this is in mas)
371 * @param r2 rotation parameter around Y axis (BEWARE, this is in mas)
372 * @param r3 rotation parameter around Z axis (BEWARE, this is in mas)
373 * @param t1Dot rate of translation parameter along X axis (BEWARE, this is in mm/y)
374 * @param t2Dot rate of translation parameter along Y axis (BEWARE, this is in mm/y)
375 * @param t3Dot rate of translation parameter along Z axis (BEWARE, this is in mm/y)
376 * @param r1Dot rate of rotation parameter around X axis (BEWARE, this is in mas/y)
377 * @param r2Dot rate of rotation parameter around Y axis (BEWARE, this is in mas/y)
378 * @param r3Dot rate of rotation parameter around Z axis (BEWARE, this is in mas/y)
379 */
380 HelmertTransformationWithoutTimeScale(
381 final DateTimeComponents epoch,
382 final double t1, final double t2, final double t3,
383 final double r1, final double r2, final double r3,
384 final double t1Dot, final double t2Dot, final double t3Dot,
385 final double r1Dot, final double r2Dot, final double r3Dot) {
386
387 // conversion parameters to SI units
388 final double mmToM = 1.0e-3;
389 final double masToRad = 1.0e-3 * Constants.ARC_SECONDS_TO_RADIANS;
390
391 this.epoch = epoch;
392 this.cartesian = new PVCoordinates(new Vector3D(t1 * mmToM,
393 t2 * mmToM,
394 t3 * mmToM),
395 new Vector3D(t1Dot * mmToM / Constants.JULIAN_YEAR,
396 t2Dot * mmToM / Constants.JULIAN_YEAR,
397 t3Dot * mmToM / Constants.JULIAN_YEAR));
398 this.rotationVector = new Vector3D(r1 * masToRad,
399 r2 * masToRad,
400 r3 * masToRad);
401 this.rotationRate = new Vector3D(r1Dot * masToRad / Constants.JULIAN_YEAR,
402 r2Dot * masToRad / Constants.JULIAN_YEAR,
403 r3Dot * masToRad / Constants.JULIAN_YEAR);
404
405 }
406
407 /**
408 * Get the Helmert transformation with reference to the given time scale.
409 *
410 * @param tt TT time scale.
411 * @return Helmert transformation.
412 */
413 public HelmertTransformation withTimeScale(final TimeScale tt) {
414 return new HelmertTransformation(cartesian, rotationVector, rotationRate,
415 new AbsoluteDate(epoch, tt));
416 }
417
418 }
419
420 /** Cartesian part of the transform. */
421 private final PVCoordinates cartesian;
422
423 /** Global rotation vector (applying rotation is done by computing cross product). */
424 private final Vector3D rotationVector;
425
426 /** First time derivative of the rotation (norm representing angular rate). */
427 private final Vector3D rotationRate;
428
429 /** Reference epoch of the transform. */
430 private final AbsoluteDate epoch;
431
432 /** Build a transform from its primitive operations.
433 * @param epoch reference epoch of the transform
434 * @param t1 translation parameter along X axis (BEWARE, this is in mm)
435 * @param t2 translation parameter along Y axis (BEWARE, this is in mm)
436 * @param t3 translation parameter along Z axis (BEWARE, this is in mm)
437 * @param r1 rotation parameter around X axis (BEWARE, this is in mas)
438 * @param r2 rotation parameter around Y axis (BEWARE, this is in mas)
439 * @param r3 rotation parameter around Z axis (BEWARE, this is in mas)
440 * @param t1Dot rate of translation parameter along X axis (BEWARE, this is in mm/y)
441 * @param t2Dot rate of translation parameter along Y axis (BEWARE, this is in mm/y)
442 * @param t3Dot rate of translation parameter along Z axis (BEWARE, this is in mm/y)
443 * @param r1Dot rate of rotation parameter around X axis (BEWARE, this is in mas/y)
444 * @param r2Dot rate of rotation parameter around Y axis (BEWARE, this is in mas/y)
445 * @param r3Dot rate of rotation parameter around Z axis (BEWARE, this is in mas/y)
446 */
447 public HelmertTransformation(final AbsoluteDate epoch,
448 final double t1, final double t2, final double t3,
449 final double r1, final double r2, final double r3,
450 final double t1Dot, final double t2Dot, final double t3Dot,
451 final double r1Dot, final double r2Dot, final double r3Dot) {
452
453 // conversion parameters to SI units
454 final double mmToM = 1.0e-3;
455 final double masToRad = 1.0e-3 * Constants.ARC_SECONDS_TO_RADIANS;
456
457 this.epoch = epoch;
458 this.cartesian = new PVCoordinates(new Vector3D(t1 * mmToM,
459 t2 * mmToM,
460 t3 * mmToM),
461 new Vector3D(t1Dot * mmToM / Constants.JULIAN_YEAR,
462 t2Dot * mmToM / Constants.JULIAN_YEAR,
463 t3Dot * mmToM / Constants.JULIAN_YEAR));
464 this.rotationVector = new Vector3D(r1 * masToRad,
465 r2 * masToRad,
466 r3 * masToRad);
467 this.rotationRate = new Vector3D(r1Dot * masToRad / Constants.JULIAN_YEAR,
468 r2Dot * masToRad / Constants.JULIAN_YEAR,
469 r3Dot * masToRad / Constants.JULIAN_YEAR);
470
471 }
472
473 /**
474 * Private constructor.
475 *
476 * @param cartesian part of the transform.
477 * @param rotationVector global rotation vector.
478 * @param rotationRate time derivative of rotation.
479 * @param epoch of transform.
480 */
481 private HelmertTransformation(final PVCoordinates cartesian,
482 final Vector3D rotationVector,
483 final Vector3D rotationRate,
484 final AbsoluteDate epoch) {
485 this.cartesian = cartesian;
486 this.rotationVector = rotationVector;
487 this.rotationRate = rotationRate;
488 this.epoch = epoch;
489 }
490
491 /** Get the reference epoch of the transform.
492 * @return reference epoch of the transform
493 */
494 public AbsoluteDate getEpoch() {
495 return epoch;
496 }
497
498 /** {@inheritDoc} */
499 @Override
500 public Transform getTransform(final AbsoluteDate date) {
501
502 // compute parameters evolution since reference epoch
503 final double dt = date.durationFrom(epoch);
504 final Vector3D dR = new Vector3D(1, rotationVector, dt, rotationRate);
505
506 // build translation part
507 final Transform translationTransform = new Transform(date, cartesian.shiftedBy(dt));
508
509 // build rotation part
510 final double angle = dR.getNorm();
511 final Transform rotationTransform =
512 new Transform(date,
513 (angle < Precision.SAFE_MIN) ?
514 Rotation.IDENTITY :
515 new Rotation(dR, angle, RotationConvention.VECTOR_OPERATOR),
516 rotationRate);
517
518 // combine both parts
519 return new Transform(date, translationTransform, rotationTransform);
520
521 }
522
523 /** {@inheritDoc} */
524 @Override
525 public <T extends CalculusFieldElement<T>> FieldTransform<T> getTransform(final FieldAbsoluteDate<T> date) {
526
527 // compute parameters evolution since reference epoch
528 final T dt = date.durationFrom(epoch);
529 final FieldVector3D<T> dR = new FieldVector3D<>(date.getField().getOne(), rotationVector,
530 dt, rotationRate);
531
532 // build translation part
533 final FieldTransform<T> translationTransform =
534 new FieldTransform<>(date,
535 new FieldPVCoordinates<>(date.getField(), cartesian).shiftedBy(dt));
536
537 // build rotation part
538 final T angle = dR.getNorm();
539 final FieldTransform<T> rotationTransform =
540 new FieldTransform<>(date,
541 (angle.getReal() < Precision.SAFE_MIN) ?
542 FieldRotation.getIdentity(date.getField()) :
543 new FieldRotation<>(dR, angle, RotationConvention.VECTOR_OPERATOR),
544 new FieldVector3D<>(date.getField(), rotationRate));
545
546 // combine both parts
547 return new FieldTransform<>(date, translationTransform, rotationTransform);
548
549 }
550
551 }