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  
20  import org.hipparchus.CalculusFieldElement;
21  import org.hipparchus.geometry.euclidean.threed.FieldRotation;
22  import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
23  import org.hipparchus.geometry.euclidean.threed.Rotation;
24  import org.hipparchus.geometry.euclidean.threed.RotationConvention;
25  import org.hipparchus.geometry.euclidean.threed.Vector3D;
26  import org.hipparchus.util.MathUtils;
27  import org.orekit.time.AbsoluteDate;
28  import org.orekit.time.FieldAbsoluteDate;
29  import org.orekit.time.TimeScalarFunction;
30  import org.orekit.time.TimeScale;
31  import org.orekit.utils.Constants;
32  
33  /** Terrestrial Intermediate Reference Frame.
34   * <p> The pole motion is not considered : Pseudo Earth Fixed Frame. It handles
35   * the earth rotation angle, its parent frame is the {@link CIRFProvider}</p>
36   */
37  class TIRFProvider implements EOPBasedTransformProvider {
38  
39      /** Angular velocity of the Earth, in rad/s. */
40      private static final double AVE = 7.292115146706979e-5;
41  
42      /** EOP history. */
43      private final EOPHistory eopHistory;
44  
45      /** UT1 time scale. */
46      private final TimeScale ut1;
47  
48      /** ERA function. */
49      private final TimeScalarFunction era;
50  
51      /** Simple constructor.
52       * @param eopHistory EOP history
53       * @param ut1 the UT1 time scale.
54       */
55      protected TIRFProvider(final EOPHistory eopHistory, final TimeScale ut1) {
56  
57          this.ut1        = ut1;
58          this.eopHistory = eopHistory;
59          this.era        = eopHistory.getConventions().getEarthOrientationAngleFunction(
60                  ut1,
61                  eopHistory.getTimeScales().getTAI());
62  
63      }
64  
65      /** {@inheritDoc} */
66      @Override
67      public EOPHistory getEOPHistory() {
68          return eopHistory;
69      }
70  
71      /** {@inheritDoc} */
72      @Override
73      public TIRFProvider getNonInterpolatingProvider() {
74          return new TIRFProvider(eopHistory.getEOPHistoryWithoutCachedTidalCorrection(), ut1);
75      }
76  
77      /** {@inheritDoc} */
78      @Override
79      public Transform getTransform(final AbsoluteDate date) {
80          return new Transform(date, getRotation(date), getRotationRate(date));
81      }
82  
83      /** {@inheritDoc} */
84      @Override
85      public KinematicTransform getKinematicTransform(final AbsoluteDate date) {
86          return KinematicTransform.of(date, getRotation(date), getRotationRate(date));
87      }
88  
89      /** {@inheritDoc} */
90      @Override
91      public StaticTransform getStaticTransform(final AbsoluteDate date) {
92          return StaticTransform.of(date, getRotation(date));
93      }
94  
95      /** Form rotation to parent CIRF.
96       * @param date transform date
97       * @return rotation to parent at date
98       * @since 12.1
99       */
100     private Rotation getRotation(final AbsoluteDate date) {
101         // compute proper rotation
102         final double correctedERA = era.value(date);
103         // set up the transform from parent CIRF
104         return new Rotation(Vector3D.PLUS_K, correctedERA, RotationConvention.FRAME_TRANSFORM);
105     }
106 
107     /** Form rotation rate w.r.t. parent CIRF.
108      * @param date transform date
109      * @return rotation rate at date
110      * @since 12.1
111      */
112     private Vector3D getRotationRate(final AbsoluteDate date) {
113         // compute true angular rotation of Earth, in rad/s
114         final double lod = (eopHistory == null) ? 0.0 : eopHistory.getLOD(date);
115         final double omp = AVE * (1 - lod / Constants.JULIAN_DAY);
116         return new Vector3D(omp, Vector3D.PLUS_K);
117     }
118 
119     /** {@inheritDoc} */
120     @Override
121     public <T extends CalculusFieldElement<T>> FieldTransform<T> getTransform(final FieldAbsoluteDate<T> date) {
122         return new FieldTransform<>(date, getRotation(date), getRotationRate(date));
123     }
124 
125     /** {@inheritDoc} */
126     @Override
127     public <T extends CalculusFieldElement<T>> FieldKinematicTransform<T> getKinematicTransform(final FieldAbsoluteDate<T> date) {
128         return FieldKinematicTransform.of(date, getRotation(date), getRotationRate(date));
129     }
130 
131     /** {@inheritDoc} */
132     @Override
133     public <T extends CalculusFieldElement<T>> FieldStaticTransform<T> getStaticTransform(final FieldAbsoluteDate<T> date) {
134         return FieldStaticTransform.of(date, getRotation(date));
135     }
136 
137     /** Form rotation to parent CIRF.
138      * @param <T> type of the elements
139      * @param date transform date
140      * @return rotation to parent at date
141      * @since 12.1
142      */
143     private <T extends CalculusFieldElement<T>> FieldRotation<T> getRotation(final FieldAbsoluteDate<T> date) {
144         // compute proper rotation
145         final T correctedERA = era.value(date);
146 
147         // set up the transform from parent CIRF
148         return new FieldRotation<>(
149                 FieldVector3D.getPlusK(date.getField()),
150                 correctedERA,
151                 RotationConvention.FRAME_TRANSFORM);
152     }
153 
154     /** Form rotation rate w.r.t. parent CIRF.
155      * @param <T> type of the elements
156      * @param date transform date
157      * @return rotation rate at date
158      * @since 12.1
159      */
160     private <T extends CalculusFieldElement<T>> FieldVector3D<T> getRotationRate(final FieldAbsoluteDate<T> date) {
161         // compute true angular rotation of Earth, in rad/s
162         final T lod = (eopHistory == null) ? date.getField().getZero() : eopHistory.getLOD(date);
163         final T omp = lod.divide(Constants.JULIAN_DAY).subtract(1).multiply(-AVE);
164         return new FieldVector3D<>(omp, Vector3D.PLUS_K);
165     }
166 
167     /** Get the Earth Rotation Angle at the current date.
168      * @param  date the date
169      * @return Earth Rotation Angle at the current date in radians
170      */
171     public double getEarthRotationAngle(final AbsoluteDate date) {
172         return MathUtils.normalizeAngle(era.value(date), 0);
173     }
174 
175 }