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.estimation.measurements;
18
19 import java.util.IdentityHashMap;
20 import java.util.Map;
21
22 import org.orekit.propagation.SpacecraftState;
23 import org.orekit.time.AbsoluteDate;
24 import org.orekit.utils.TimeStampedPVCoordinates;
25
26 /** Class holding an estimated theoretical value associated to an {@link ObservedMeasurement observed measurement}.
27 * @param <T> the type of the measurement
28 * @author Luc Maisonobe
29 * @since 8.0
30 */
31 public class EstimatedMeasurementBase<T extends ObservedMeasurement<T>> implements ComparableMeasurement {
32
33 /** Associated observed measurement. */
34 private final T observedMeasurement;
35
36 /** Iteration number. */
37 private final int iteration;
38
39 /** Evaluations counter. */
40 private final int count;
41
42 /** States of the spacecrafts. */
43 private final SpacecraftState[] states;
44
45 /** Coordinates of the participants in signal travel order (can be empty if not computed for performance). */
46 private final TimeStampedPVCoordinates[] participants;
47
48 /** Original estimated value prior to any modification.
49 * @since 12.1
50 */
51 private double[] originalEstimatedValue;
52
53 /** Estimated value. */
54 private double[] estimatedValue;
55
56 /** Applied modifiers effects.
57 * @since 12.1
58 */
59 private final IdentityHashMap<EstimationModifier<T>, double[]> appliedEffects;
60
61 /** Measurement status. */
62 private Status status;
63
64 /** Simple constructor.
65 * @param observedMeasurement associated observed measurement
66 * @param iteration iteration number
67 * @param count evaluations counter
68 * @param states states of the spacecrafts
69 * @param participants coordinates of the participants in signal travel order
70 * in inertial frame of first state
71 */
72 public EstimatedMeasurementBase(final T observedMeasurement,
73 final int iteration, final int count,
74 final SpacecraftState[] states,
75 final TimeStampedPVCoordinates[] participants) {
76 this.observedMeasurement = observedMeasurement;
77 this.iteration = iteration;
78 this.count = count;
79 this.states = states.clone();
80 this.participants = participants.clone();
81 this.status = Status.PROCESSED;
82 this.appliedEffects = new IdentityHashMap<>();
83 }
84
85 /** Get the associated observed measurement.
86 * @return associated observed measurement
87 */
88 public T getObservedMeasurement() {
89 return observedMeasurement;
90 }
91
92 /** {@inheritDoc} */
93 @Override
94 public AbsoluteDate getDate() {
95 return observedMeasurement.getDate();
96 }
97
98 /** Get the iteration number.
99 * @return iteration number
100 */
101 public int getIteration() {
102 return iteration;
103 }
104
105 /** Get the evaluations counter.
106 * @return evaluations counter
107 */
108 public int getCount() {
109 return count;
110 }
111
112 /** Get the states of the spacecrafts.
113 * @return states of the spacecrafts
114 */
115 public SpacecraftState[] getStates() {
116 return states.clone();
117 }
118
119 /** Get the coordinates of the measurements participants in signal travel order.
120 * Can be empty if not computed beforehand for performance reasons.
121 * <p>
122 * First participant (at index 0) emits the signal (it is for example a ground
123 * station for two-way range measurement). Last participant receives the signal
124 * (it is also the ground station for two-way range measurement, but a few
125 * milliseconds later). Intermediate participants reflect the signal (it is the
126 * spacecraft for two-way range measurement).
127 * </p>
128 * @return coordinates of the measurements participants in signal travel order
129 * in inertial frame of first state
130 */
131 public TimeStampedPVCoordinates[] getParticipants() {
132 return participants.clone();
133 }
134
135 /** Get the time offset from first state date to measurement date.
136 * @return time offset from first state date to measurement date
137 */
138 public double getTimeOffset() {
139 return observedMeasurement.getDate().durationFrom(states[0].getDate());
140 }
141
142 /** {@inheritDoc} */
143 @Override
144 public double[] getObservedValue() {
145 return observedMeasurement.getObservedValue();
146 }
147
148 /** {@inheritDoc} */
149 @Override
150 public void setObservedValue(final double[] observed) {
151 observedMeasurement.setObservedValue(observed);
152 }
153
154 /** Get the original estimated value prior to any modification.
155 * @return original estimated value prior to any modification
156 * @since 12.1
157 */
158 public double[] getOriginalEstimatedValue() {
159 return originalEstimatedValue.clone();
160 }
161
162 /** Get the applied effects of modifiers.
163 * <p>
164 * The effects have already accounted for in {@link #getEstimatedValue()}
165 * </p>
166 * @return applied modifier effects
167 * @since 12.1
168 */
169 public Map<EstimationModifier<T>, double[]> getAppliedEffects() {
170 return appliedEffects;
171 }
172
173 /** Get the estimated value.
174 * @return estimated value
175 */
176 public double[] getEstimatedValue() {
177 return estimatedValue.clone();
178 }
179
180 /** Set the estimated value.
181 * @param estimatedValue estimated value
182 * @see #modifyEstimatedValue(EstimationModifier, double...)
183 */
184 public void setEstimatedValue(final double... estimatedValue) {
185 if (originalEstimatedValue == null) {
186 this.originalEstimatedValue = estimatedValue.clone();
187 }
188 this.estimatedValue = estimatedValue.clone();
189 }
190
191 /** Modify the estimated value.
192 * @param modifier modifier that generates this estimated value
193 * @param newEstimatedValue new estimated value
194 * @since 12.1
195 */
196 public void modifyEstimatedValue(final EstimationModifier<T> modifier, final double... newEstimatedValue) {
197
198 if (modifier == null) {
199 setEstimatedValue(newEstimatedValue);
200 } else {
201 final double[] effect = new double[newEstimatedValue.length];
202 for (int i = 0; i < effect.length; ++i) {
203 // compute effect
204 effect[i] = newEstimatedValue[i] - estimatedValue[i];
205 // update value
206 estimatedValue[i] = newEstimatedValue[i];
207 }
208
209 // store effect
210 appliedEffects.put(modifier, effect);
211 }
212
213 }
214
215 /** Get the status.
216 * <p>
217 * The status is set to {@link Status#PROCESSED PROCESSED} at construction, and
218 * can be reset to {@link Status#REJECTED REJECTED} later on, typically by
219 * {@link org.orekit.estimation.measurements.modifiers.OutlierFilter OutlierFilter}
220 * or {@link org.orekit.estimation.measurements.modifiers.DynamicOutlierFilter DynamicOutlierFilter}
221 * </p>
222 * @return status
223 */
224 public Status getStatus() {
225 return status;
226 }
227
228 /** Set the status.
229 * @param status status to set
230 */
231 public void setStatus(final Status status) {
232 this.status = status;
233 }
234
235 /** Enumerate for the status of the measurement. */
236 public enum Status {
237
238 /** Status for processed measurements. */
239 PROCESSED,
240
241 /** Status for rejected measurements. */
242 REJECTED
243
244 }
245
246 }