1   /* Copyright 2022-2026 Thales Alenia Space
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.time.clocks;
18  
19  import java.util.Arrays;
20  import java.util.List;
21  
22  import org.hipparchus.CalculusFieldElement;
23  import org.orekit.errors.OrekitException;
24  import org.orekit.errors.OrekitMessages;
25  import org.orekit.time.FieldAbsoluteDate;
26  import org.orekit.time.FieldTimeStamped;
27  
28  /**
29   * Container for time stamped clock offset.
30   *
31   * @param <T> type of the field elements
32   * @author Luc Maisonobe
33   * @since 12.1
34   */
35  public class FieldClockOffset<T extends CalculusFieldElement<T>> implements FieldTimeStamped<T> {
36  
37      /** Date. */
38      private final FieldAbsoluteDate<T> date;
39  
40      /** Clock bias. */
41      private final T bias;
42  
43      /** Clock rate. */
44      private final T rate;
45  
46      /** Clock acceleration. */
47      private final T acceleration;
48  
49      /** Simple constructor.
50       *
51       * @param date         date
52       * @param bias         clock bias
53       * @param rate         clock rate (can be set to {@code null} if unknown)
54       * @param acceleration clock acceleration (can be set to {@code null} if
55       *                     unknown)
56       */
57      public FieldClockOffset(final FieldAbsoluteDate<T> date, final T bias,
58              final T rate, final T acceleration) {
59          this.date = date;
60          this.bias = bias;
61          this.rate = rate;
62          this.acceleration = acceleration;
63      }
64  
65      /** Simple constructor.
66       *
67       * @param date         date
68       * @param terms        array of clock terms (bias, rate, acceleration)
69       */
70      public FieldClockOffset(final FieldAbsoluteDate<T> date, final T[] terms) {
71          this(date, Arrays.asList(terms));
72      }
73  
74      /** Simple constructor.
75       *
76       * @param date         date
77       * @param terms        list of clock terms (bias, rate, acceleration)
78       */
79      public FieldClockOffset(final FieldAbsoluteDate<T> date, final List<T> terms) {
80          this.date = date;
81  
82          if (!terms.isEmpty()) {
83              this.bias = terms.getFirst();
84          } else {
85              this.bias = date.getField().getZero();
86          }
87          if (terms.size() >= 2) {
88              this.rate = terms.get(1);
89          } else {
90              this.rate = date.getField().getZero();
91          }
92          if (terms.size() == 3) {
93              this.acceleration = terms.get(2);
94          } else {
95              this.acceleration = date.getField().getZero();
96          }
97          if (terms.size() > 3) {
98              throw new OrekitException(OrekitMessages.CANNOT_PARSE_DATA);
99          }
100     }
101 
102     /**
103      * Add another offset to the instance.
104      * <p>
105      * The instance is not modified, a new instance is created
106      * </p>
107      *
108      * @param other offset to add (date part will be ignored)
109      * @return instance + other, at instance date
110      * @since 14.0
111      */
112     public FieldClockOffset<T> add(final FieldClockOffset<T> other) {
113         return new FieldClockOffset<>(date,
114                 bias.add(other.bias),
115                 rate.add(other.rate),
116                 acceleration.add(other.acceleration));
117     }
118 
119     /** Subtract another offset from the instance.
120      * <p>
121      * The instance is not modified, a new instance is created
122      * </p>
123      *
124      * @param other offset to subtract (date part will be ignored)
125      * @return instance - other, at instance date
126      * @since 14.0
127      */
128     public FieldClockOffset<T> subtract(final FieldClockOffset<T> other) {
129         return new FieldClockOffset<>(date,
130                 bias.subtract(other.bias),
131                 rate.subtract(other.rate),
132                 acceleration.subtract(other.acceleration));
133     }
134 
135     /** {@inheritDoc} */
136     @Override
137     public FieldAbsoluteDate<T> getDate() {
138         return date;
139     }
140 
141     /** Get bias.
142      * @return bias
143      */
144     public T getBias() {
145         return bias;
146     }
147 
148     /** Get rate.
149      * @return rate ({@code null} if unknown)
150      */
151     public T getRate() {
152         return rate;
153     }
154 
155     /** Get acceleration.
156      * @return acceleration ({@code null} if unknown)
157      */
158     public T getAcceleration() {
159         return acceleration;
160     }
161 
162     /** Negate instance.
163      * <p>
164      * The instance is not modified, a new instance is created
165      * </p>
166      *
167      * @return instance - other, at instance date
168      * @since 14.0
169      */
170     public FieldClockOffset<T> negate() {
171         return new FieldClockOffset<>(getDate(), bias.negate(), rate.negate(), acceleration.negate());
172     }
173 
174 }