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 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.MathUtils;
26  import org.orekit.time.AbsoluteDate;
27  import org.orekit.time.DateComponents;
28  import org.orekit.time.FieldAbsoluteDate;
29  import org.orekit.time.TimeScales;
30  import org.orekit.utils.Constants;
31  
32  /** Veis 1950 Frame.
33   * <p>Its parent frame is the {@link GTODProvider} without EOP correction application.
34   * <p>This frame is mainly provided for consistency with legacy softwares.</p>
35   * @author Pascal Parraud
36   */
37  class VEISProvider implements TransformProvider {
38  
39      /** 1st coef for Veis sidereal time computation in radians (100.075542 deg). */
40      private static final double VST0 = 1.746647708617871;
41  
42      /** 2nd coef for Veis sidereal time computation in rad/s (0.985612288 deg/s). */
43      private static final double VST1 = 0.17202179573714597e-1;
44  
45      /** Veis sidereal time derivative in rad/s. */
46      private static final double VSTD = 7.292115146705209e-5;
47  
48      /** Set of time scales to use. */
49      private final TimeScales timeScales;
50  
51      /** Reference date. */
52      private final AbsoluteDate vstReference;
53  
54      /**
55       * Constructor for the singleton.
56       *
57       * @param timeScales to use when computing the transform.
58       */
59      VEISProvider(final TimeScales timeScales) {
60          this.timeScales = timeScales;
61          this.vstReference =
62                  new AbsoluteDate(DateComponents.FIFTIES_EPOCH, timeScales.getTAI());
63      }
64  
65      /** {@inheritDoc} */
66      @Override
67      public Transform getTransform(final AbsoluteDate date) {
68  
69          // offset from FIFTIES epoch (UT1 scale)
70          final double dtai = date.durationFrom(vstReference);
71          final double dutc = timeScales.getUTC().offsetFromTAI(date).toDouble();
72          final double dut1 = 0.0; // fixed at 0 since Veis parent is GTOD frame WITHOUT EOP corrections
73  
74          final double tut1 = dtai + dutc + dut1;
75          final double ttd  = tut1 / Constants.JULIAN_DAY;
76          final double rdtt = ttd - (int) ttd;
77  
78          // compute Veis sidereal time, in radians
79          final double vst = (VST0 + VST1 * ttd + MathUtils.TWO_PI * rdtt) % MathUtils.TWO_PI;
80  
81          // compute angular rotation of Earth, in rad/s
82          final Vector3D rotationRate = new Vector3D(-VSTD, Vector3D.PLUS_K);
83  
84          // set up the transform from parent GTOD
85          return new Transform(date,
86                               new Rotation(Vector3D.PLUS_K, vst, RotationConvention.VECTOR_OPERATOR),
87                               rotationRate);
88  
89      }
90  
91      /** {@inheritDoc} */
92      @Override
93      public <T extends CalculusFieldElement<T>> FieldTransform<T> getTransform(final FieldAbsoluteDate<T> date) {
94  
95          // offset from FIFTIES epoch (UT1 scale)
96          final T dtai = date.durationFrom(vstReference);
97          final double dutc = timeScales.getUTC().offsetFromTAI(date.toAbsoluteDate()).toDouble();
98          final double dut1 = 0.0; // fixed at 0 since Veis parent is GTOD frame WITHOUT EOP corrections
99  
100         final T tut1 = dtai.add(dutc + dut1);
101         final T ttd  = tut1.divide(Constants.JULIAN_DAY);
102         final T rdtt = ttd.subtract((int) ttd.getReal());
103 
104         // compute Veis sidereal time, in radians
105         final T vst = ttd.multiply(VST1).add(rdtt.multiply(MathUtils.TWO_PI)).add(VST0).remainder(MathUtils.TWO_PI);
106 
107         // compute angular rotation of Earth, in rad/s
108         final FieldVector3D<T> rotationRate = new FieldVector3D<>(date.getField().getZero().newInstance(-VSTD),
109                                                                   Vector3D.PLUS_K);
110 
111         // set up the transform from parent GTOD
112         return new FieldTransform<>(date,
113                                     new FieldRotation<>(FieldVector3D.getPlusK(date.getField()), vst,
114                                                         RotationConvention.VECTOR_OPERATOR),
115                                     rotationRate);
116 
117     }
118 
119 }