1 /* Copyright 2002-2026 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.utils.drivers;
18
19 import org.hipparchus.exception.LocalizedCoreFormats;
20 import org.hipparchus.util.FastMath;
21 import org.hipparchus.util.Precision;
22 import org.orekit.errors.OrekitException;
23 import org.orekit.errors.OrekitMessages;
24 import org.orekit.time.TimeInterval;
25
26 import java.util.ArrayList;
27 import java.util.Collections;
28 import java.util.Iterator;
29 import java.util.List;
30
31 /** Common features for both {@link ParameterDriver} and {@link FieldParameterDriver}.
32 * @param <P> type of the parameter driver
33 * @param <O> type of the parameter observer
34 * @see ParameterDriver
35 * @see FieldParameterDriver
36 * @author Luc Maisonobe
37 * @since 14.0
38 */
39 public abstract class BaseParameterDriver<P extends BaseParameterDriver<P, O>,
40 O extends BaseParameterObserver<P, O>> {
41
42 /** Name of the parameter. */
43 private String name;
44
45 /** Scaling factor. */
46 private double scale;
47
48 /** Minimum value. */
49 private double minValue;
50
51 /** Maximum value. */
52 private double maxValue;
53
54 /** Validity interval.
55 * @since 14.0
56 */
57 private TimeInterval validity;
58
59 /** Selection status.
60 * <p>
61 * Selection is used for estimated parameters in orbit determination,
62 * or to compute the Jacobian matrix in partial derivatives computation.
63 * </p>
64 */
65 private boolean selected;
66
67 /** Observers observing this driver. */
68 private final List<O> observers;
69
70 /**
71 * Simple constructor.
72 * <p>
73 * At construction, the parameter is configured as <em>not</em> selected, the reference date is set to {@code null},
74 * the value is set to the {@code referenceValue}.
75 * </p>
76 * @param name name of the parameter
77 * @param scale scaling factor to convert the parameters value to non-dimensional (typically set to the
78 * expected standard deviation of the parameter), it must be non-zero
79 * @param minValue minimum value allowed
80 * @param maxValue maximum value allowed
81 * @param validity validity interval
82 */
83 public BaseParameterDriver(final String name, final double scale,
84 final double minValue, final double maxValue,
85 final TimeInterval validity) {
86
87 if (FastMath.abs(scale) <= Precision.SAFE_MIN) {
88 throw new OrekitException(OrekitMessages.TOO_SMALL_SCALE_FOR_PARAMETER, name, scale);
89 }
90
91 this.name = name;
92 this.scale = scale;
93 this.minValue = minValue;
94 this.maxValue = maxValue;
95 this.validity = validity;
96 this.selected = false;
97 this.observers = new ArrayList<>();
98 }
99
100 /** Add an observer for this driver.
101 * @param observer observer to add
102 */
103 public void addObserver(final O observer) {
104 observers.add(observer);
105 }
106
107 /** Remove an observer.
108 * @param observer observer to remove
109 * @since 9.1
110 */
111 public void removeObserver(final O observer) {
112 for (final Iterator<O> iterator = observers.iterator(); iterator.hasNext();) {
113 if (iterator.next() == observer) {
114 iterator.remove();
115 return;
116 }
117 }
118 }
119
120 /** Replace an observer.
121 * @param oldObserver observer to replace
122 * @param newObserver new observer to use
123 * @since 10.1
124 */
125 public void replaceObserver(final O oldObserver, final O newObserver) {
126 for (int i = 0; i < observers.size(); ++i) {
127 if (observers.get(i) == oldObserver) {
128 observers.set(i, newObserver);
129 }
130 }
131 }
132
133 /** Get the observers for this driver.
134 * @return an unmodifiable view of the observers for this driver
135 * @since 9.1
136 */
137 public List<O> getObservers() {
138 return Collections.unmodifiableList(observers);
139 }
140
141 /** Get parameter driver general name.
142 * @return name
143 */
144 public String getName() {
145 return name;
146 }
147
148 /** Change the general name of this parameter driver.
149 * @param name new name
150 */
151 public void setName(final String name) {
152 final String previousName = this.name;
153 this.name = name;
154 @SuppressWarnings("unchecked")
155 final P self = (P) this;
156 for (final O observer : observers) {
157 observer.nameChanged(previousName, self);
158 }
159 }
160
161 /** Get minimum parameter value.
162 * @return minimum parameter value
163 */
164 public double getMinValue() {
165 return minValue;
166 }
167
168 /** Set minimum parameter value.
169 * @since 9.3
170 * @param minValue the minimum value to set.
171 */
172 public void setMinValue(final double minValue) {
173
174 // safety check
175 if (minValue > maxValue) {
176 throw new OrekitException(LocalizedCoreFormats.NUMBER_TOO_LARGE, minValue, maxValue);
177 }
178
179 final double previousMinValue = this.minValue;
180 this.minValue = minValue;
181 @SuppressWarnings("unchecked")
182 final P self = (P) this;
183 for (final O observer : observers) {
184 observer.minValueChanged(previousMinValue, self);
185 }
186
187 }
188
189 /** Get maximum parameter value.
190 * @return maximum parameter value
191 */
192 public double getMaxValue() {
193 return maxValue;
194 }
195
196 /** Set maximum parameter value.
197 * @param maxValue the maximum value to set.
198 */
199 public void setMaxValue(final double maxValue) {
200
201 // safety check
202 if (maxValue < minValue) {
203 throw new OrekitException(LocalizedCoreFormats.NUMBER_TOO_SMALL, maxValue, minValue);
204 }
205
206 final double previousMaxValue = this.maxValue;
207 this.maxValue = maxValue;
208 @SuppressWarnings("unchecked")
209 final P self = (P) this;
210 for (final O observer : observers) {
211 observer.maxValueChanged(previousMaxValue, self);
212 }
213
214 }
215
216 /** Get scale.
217 * @return scale
218 */
219 public double getScale() {
220 return scale;
221 }
222
223 /** Set scale.
224 * @since 9.3
225 * @param scale the scale to set.
226 */
227 public void setScale(final double scale) {
228 final double previousScale = this.scale;
229 this.scale = scale;
230 @SuppressWarnings("unchecked")
231 final P self = (P) this;
232 for (final O observer : observers) {
233 observer.scaleChanged(previousScale, self);
234 }
235 }
236
237 /** Get the validity interval.
238 * @return validity interval
239 * @since 14.0
240 */
241 public TimeInterval getValidity() {
242 return validity;
243 }
244
245 /** Set the validity interval.
246 * @param validity validity interval
247 * @since 14.0
248 */
249 public void setValidity(final TimeInterval validity) {
250 final TimeInterval previousValidity = getValidity();
251 this.validity = validity;
252 @SuppressWarnings("unchecked")
253 final P self = (P) this;
254 for (final O observer : observers) {
255 observer.validityChanged(previousValidity, self);
256 }
257 }
258
259 /** Configure a parameter selection status.
260 * <p>
261 * Selection is used for estimated parameters in orbit determination,
262 * or to compute the Jacobian matrix in partial derivatives computation.
263 * </p>
264 * @param selected if true the parameter is selected,
265 * otherwise it will be fixed
266 */
267 public void setSelected(final boolean selected) {
268 final boolean previousSelection = isSelected();
269 this.selected = selected;
270 @SuppressWarnings("unchecked")
271 final P self = (P) this;
272 for (final O observer : observers) {
273 observer.selectionChanged(previousSelection, self);
274 }
275 }
276
277 /** Check if parameter is selected.
278 * <p>
279 * Selection is used for estimated parameters in orbit determination,
280 * or to compute the Jacobian matrix in partial derivatives computation.
281 * </p>
282 * @return true if parameter is selected, false if it is not
283 */
284 public boolean isSelected() {
285 return selected;
286 }
287
288 }