1   /* Copyright 2002-2025 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 org.orekit.propagation.SpacecraftState;
20  import org.orekit.time.AbsoluteDate;
21  import org.orekit.utils.TimeStampedPVCoordinates;
22  
23  import java.util.IdentityHashMap;
24  import java.util.Map;
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. */
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      * <p>
121      * First participant (at index 0) emits the signal (it is for example a ground
122      * station for two-way range measurement). Last participant receives the signal
123      * (it is also the ground station for two-way range measurement, but a few
124      * milliseconds later). Intermediate participants relfect the signal (it is the
125      * spacecraft for two-way range measurement).
126      * </p>
127      * @return coordinates of the measurements participants in signal travel order
128      * in inertial frame of first state
129      */
130     public TimeStampedPVCoordinates[] getParticipants() {
131         return participants.clone();
132     }
133 
134     /** Get the time offset from first state date to measurement date.
135      * @return time offset from first state date to measurement date
136      */
137     public double getTimeOffset() {
138         return observedMeasurement.getDate().durationFrom(states[0].getDate());
139     }
140 
141     /** {@inheritDoc} */
142     @Override
143     public double[] getObservedValue() {
144         return observedMeasurement.getObservedValue();
145     }
146 
147     /** {@inheritDoc} */
148     @Override
149     public void setObservedValue(final double[] observed) {
150         observedMeasurement.setObservedValue(observed);
151     }
152 
153     /** Get the original estimated value prior to any modification.
154      * @return original estimated value prior to any modification
155      * @since 12.1
156      */
157     public double[] getOriginalEstimatedValue() {
158         return originalEstimatedValue.clone();
159     }
160 
161     /** Get the applied effects of modifiers.
162      * <p>
163      * The effects have already accounted for in {@link #getEstimatedValue()}
164      * </p>
165      * @return applied modifier effects
166      * @since 12.1
167      */
168     public Map<EstimationModifier<T>, double[]> getAppliedEffects() {
169         return appliedEffects;
170     }
171 
172     /** Get the estimated value.
173      * @return estimated value
174      */
175     public double[] getEstimatedValue() {
176         return estimatedValue.clone();
177     }
178 
179     /** Set the estimated value.
180      * @param estimatedValue estimated value
181      * @see #modifyEstimatedValue(EstimationModifier, double...)
182      */
183     public void setEstimatedValue(final double... estimatedValue) {
184         if (originalEstimatedValue == null) {
185             this.originalEstimatedValue = estimatedValue.clone();
186         }
187         this.estimatedValue = estimatedValue.clone();
188     }
189 
190     /** Modify the estimated value.
191      * @param modifier modifier that generates this estimated value
192      * @param newEstimatedValue new estimated value
193      * @since 12.1
194      */
195     public void modifyEstimatedValue(final EstimationModifier<T> modifier, final double... newEstimatedValue) {
196 
197         if (modifier == null) {
198             setEstimatedValue(newEstimatedValue);
199         } else {
200             final double[] effect = new double[newEstimatedValue.length];
201             for (int i = 0; i < effect.length; ++i) {
202                 // compute effect
203                 effect[i] = newEstimatedValue[i] - estimatedValue[i];
204                 // update value
205                 estimatedValue[i] = newEstimatedValue[i];
206             }
207 
208             // store effect
209             appliedEffects.put(modifier, effect);
210         }
211 
212     }
213 
214     /** Get the status.
215      * <p>
216      * The status is set to {@link Status#PROCESSED PROCESSED} at construction, and
217      * can be reset to {@link Status#REJECTED REJECTED} later on, typically by
218      * {@link org.orekit.estimation.measurements.modifiers.OutlierFilter OutlierFilter}
219      * or {@link org.orekit.estimation.measurements.modifiers.DynamicOutlierFilter DynamicOutlierFilter}
220      * </p>
221      * @return status
222      */
223     public Status getStatus() {
224         return status;
225     }
226 
227     /** Set the status.
228      * @param status status to set
229      */
230     public void setStatus(final Status status) {
231         this.status = status;
232     }
233 
234     /** Enumerate for the status of the measurement. */
235     public enum Status {
236 
237         /** Status for processed measurements. */
238         PROCESSED,
239 
240         /** Status for rejected measurements. */
241         REJECTED
242 
243     }
244 
245 }