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.RotationConvention;
22  import org.hipparchus.geometry.euclidean.threed.RotationOrder;
23  import org.orekit.time.FieldAbsoluteDate;
24  import org.orekit.time.TimeScalarFunction;
25  import org.orekit.time.TimeScales;
26  import org.orekit.time.TimeVectorFunction;
27  import org.orekit.utils.IERSConventions;
28  
29  /** Provider for True of Date (ToD) frame.
30   * <p>This frame handles nutation effects according to selected IERS conventions.</p>
31   * <p>Transform is computed with reference to the {@link MODProvider Mean of Date} frame.</p>
32   * @author Pascal Parraud
33   */
34  class TODProvider implements FieldBasedTransformProvider, EOPBasedTransformProvider {
35  
36      /** Conventions. */
37      private final IERSConventions conventions;
38  
39      /** EOP history. */
40      private final EOPHistory eopHistory;
41  
42      /** Function computing the mean obliquity. */
43      private final transient TimeScalarFunction obliquityFunction;
44  
45      /** Function computing the nutation angles. */
46      private final transient TimeVectorFunction nutationFunction;
47  
48  
49      /**
50       * Simple constructor.
51       *  @param conventions IERS conventions to apply
52       * @param eopHistory  EOP history, or {@code null} if no correction should be
53       *                    applied.
54       * @param timeScales         TAI time scale.
55       */
56      TODProvider(final IERSConventions conventions,
57                  final EOPHistory eopHistory,
58                  final TimeScales timeScales) {
59          this.conventions       = conventions;
60          this.eopHistory        = eopHistory;
61          this.obliquityFunction = conventions.getMeanObliquityFunction(timeScales);
62          this.nutationFunction  =
63                  conventions.getNutationFunction(timeScales);
64      }
65  
66      /**
67       * Private constructor.
68       *
69       * @param conventions       IERS conventions to use.
70       * @param eopHistory        or {@code null} if no correction should be applied.
71       * @param obliquityFunction to use.
72       * @param nutationFunction  to use.
73       */
74      private TODProvider(final IERSConventions conventions,
75                          final EOPHistory eopHistory,
76                          final TimeScalarFunction obliquityFunction,
77                          final TimeVectorFunction nutationFunction) {
78          this.conventions = conventions;
79          this.eopHistory = eopHistory;
80          this.obliquityFunction = obliquityFunction;
81          this.nutationFunction = nutationFunction;
82      }
83  
84      /** {@inheritDoc} */
85      @Override
86      public EOPHistory getEOPHistory() {
87          return eopHistory;
88      }
89  
90      /** {@inheritDoc} */
91      @Override
92      public TODProvider getNonInterpolatingProvider() {
93          return new TODProvider(conventions, eopHistory.getEOPHistoryWithoutCachedTidalCorrection(),
94                  obliquityFunction, nutationFunction);
95      }
96  
97      /** Compute the complete nutation rotation.
98       * @param date current date
99       * @param <T> type of the field elements
100      * @return complete nutation rotation
101      */
102     public <T extends CalculusFieldElement<T>> FieldRotation<T> getRotation(final FieldAbsoluteDate<T> date) {
103 
104         // compute nutation angles
105         final T[] angles = nutationFunction.value(date);
106 
107         // compute the mean obliquity of the ecliptic
108         final T moe = obliquityFunction.value(date);
109 
110         T dpsi = angles[0];
111         T deps = angles[1];
112         if (eopHistory != null) {
113             // apply the corrections for the nutation parameters
114             final T[] correction = eopHistory.getEquinoxNutationCorrection(date);
115             dpsi = dpsi.add(correction[0]);
116             deps = deps.add(correction[1]);
117         }
118 
119         // compute the true obliquity of the ecliptic
120         final T toe = moe.add(deps);
121 
122         // complete nutation
123         return new FieldRotation<>(RotationOrder.XZX, RotationConvention.FRAME_TRANSFORM,
124                                    moe, dpsi.negate(), toe.negate());
125 
126     }
127 
128 }