1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.time.clocks;
18
19 import java.util.Map;
20
21 import org.hipparchus.CalculusFieldElement;
22 import org.hipparchus.analysis.differentiation.Gradient;
23 import org.hipparchus.util.FastMath;
24 import org.orekit.errors.OrekitException;
25 import org.orekit.errors.OrekitMessages;
26 import org.orekit.time.AbsoluteDate;
27 import org.orekit.time.FieldAbsoluteDate;
28 import org.orekit.utils.ParameterDriver;
29
30
31
32
33
34
35
36 public class QuadraticClockModel implements ClockModel {
37
38
39
40
41
42
43
44 private static final double CLOCK_OFFSET_SCALE = FastMath.scalb(1.0, -10);
45
46
47 private final ParameterDriver a0;
48
49
50 private final ParameterDriver a1;
51
52
53 private final ParameterDriver a2;
54
55
56
57
58
59
60
61 public QuadraticClockModel(final AbsoluteDate referenceDate,
62 final double a0, final double a1, final double a2) {
63 this(new ParameterDriver("a0",
64 0.0, CLOCK_OFFSET_SCALE,
65 Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY),
66 new ParameterDriver("a1",
67 0.0, CLOCK_OFFSET_SCALE,
68 Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY),
69 new ParameterDriver("a2",
70 0.0, CLOCK_OFFSET_SCALE,
71 Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY));
72 this.a0.setValue(a0);
73 this.a0.setReferenceDate(referenceDate);
74 this.a1.setValue(a1);
75 this.a1.setReferenceDate(referenceDate);
76 this.a2.setValue(a2);
77 this.a2.setReferenceDate(referenceDate);
78 }
79
80
81
82
83
84
85 public QuadraticClockModel(final ParameterDriver a0, final ParameterDriver a1, final ParameterDriver a2) {
86 this.a0 = a0;
87 this.a1 = a1;
88 this.a2 = a2;
89 }
90
91
92 @Override
93 public AbsoluteDate getValidityStart() {
94 return AbsoluteDate.PAST_INFINITY;
95 }
96
97
98 @Override
99 public AbsoluteDate getValidityEnd() {
100 return AbsoluteDate.FUTURE_INFINITY;
101 }
102
103
104 @Override
105 public ClockOffset getOffset(final AbsoluteDate date) {
106 final double dt = date.durationFrom(getSafeReference(date));
107 final double c0 = a0.getValue(date);
108 final double c1 = a1.getValue(date);
109 final double c2 = a2.getValue(date);
110 return new ClockOffset(date,
111 (c2 * dt + c1) * dt + c0,
112 2 * c2 * dt + c1,
113 2 * c2);
114 }
115
116
117
118
119 public ParameterDriver getClockBiasDriver() {
120 return a0;
121 }
122
123
124
125
126 public ParameterDriver getClockDriftDriver() {
127 return a1;
128 }
129
130
131
132
133 public ParameterDriver getClockAccelerationDriver() {
134 return a2;
135 }
136
137
138 @Override
139 public <T extends CalculusFieldElement<T>> FieldClockOffset<T> getOffset(final FieldAbsoluteDate<T> date) {
140 final AbsoluteDate aDate = date.toAbsoluteDate();
141 final T dt = date.durationFrom(getSafeReference(aDate));
142 final double c0 = a0.getValue(aDate);
143 final double c1 = a1.getValue(aDate);
144 final double c2 = a2.getValue(aDate);
145 return new FieldClockOffset<>(date,
146 dt.multiply(dt.multiply(c2).add(c1)).add(c0),
147 dt.multiply(2 * c2).add(c1),
148 dt.newInstance(2 * c2));
149 }
150
151
152
153
154
155
156
157
158
159
160 private AbsoluteDate getSafeReference(final AbsoluteDate date) {
161 if (a0.getReferenceDate() == null) {
162 if (a1.getValue(date) == 0 && a2.getValue(date) == 0) {
163
164 return date;
165 } else {
166 throw new OrekitException(OrekitMessages.NO_REFERENCE_DATE_FOR_PARAMETER,
167 a0.getName());
168 }
169 } else {
170 return a0.getReferenceDate();
171 }
172 }
173
174
175
176
177
178
179
180
181 public QuadraticFieldClockModel<Gradient> toGradientModel(final int freeParameters,
182 final Map<String, Integer> indices,
183 final AbsoluteDate date) {
184 final Gradient g0 = a0.getValue(freeParameters, indices, date);
185 final Gradient g1 = a1.getValue(freeParameters, indices, date);
186 final Gradient g2 = a2.getValue(freeParameters, indices, date);
187 final FieldAbsoluteDate<Gradient> referenceDate =
188 new FieldAbsoluteDate<>(g0.getField(), getSafeReference(date));
189 return new QuadraticFieldClockModel<>(referenceDate, g0, g1, g2);
190 }
191
192 }