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 }