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