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