1 /* Copyright 2002-2021 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 import java.util.stream.Stream;
22
23 import org.orekit.errors.OrekitIllegalArgumentException;
24 import org.orekit.errors.OrekitMessages;
25 import org.orekit.propagation.SpacecraftState;
26 import org.orekit.time.AbsoluteDate;
27 import org.orekit.utils.ParameterDriver;
28 import org.orekit.utils.TimeStampedPVCoordinates;
29
30 /** Class holding an estimated theoretical value associated to an {@link ObservedMeasurement observed measurement}.
31 * @param <T> the type of the measurement
32 * @author Luc Maisonobe
33 * @since 8.0
34 */
35 public class EstimatedMeasurement<T extends ObservedMeasurement<T>> implements ComparableMeasurement {
36
37 /** Associated observed measurement. */
38 private final T observedMeasurement;
39
40 /** Iteration number. */
41 private final int iteration;
42
43 /** Evaluations counter. */
44 private final int count;
45
46 /** States of the spacecrafts. */
47 private final SpacecraftState[] states;
48
49 /** Coordinates of the participants in signal travel order. */
50 private final TimeStampedPVCoordinates[] participants;
51
52 /** Estimated value. */
53 private double[] estimatedValue;
54
55 /** Measurement status. */
56 private Status status;
57
58 /** Partial derivatives with respect to states. */
59 private double[][][] stateDerivatives;
60
61 /** Partial derivatives with respect to parameters. */
62 private final Map<ParameterDriver, double[]> parametersDerivatives;
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
71 */
72 public EstimatedMeasurement(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.stateDerivatives = new double[states.length][][];
83 this.parametersDerivatives = new IdentityHashMap<ParameterDriver, double[]>();
84 }
85
86 /** Get the associated observed measurement.
87 * @return associated observed measurement
88 */
89 public T getObservedMeasurement() {
90 return observedMeasurement;
91 }
92
93 /** {@inheritDoc} */
94 @Override
95 public AbsoluteDate getDate() {
96 return observedMeasurement.getDate();
97 }
98
99 /** Get the iteration number.
100 * @return iteration number
101 */
102 public int getIteration() {
103 return iteration;
104 }
105
106 /** Get the evaluations counter.
107 * @return evaluations counter
108 */
109 public int getCount() {
110 return count;
111 }
112
113 /** Get the states of the spacecrafts.
114 * @return states of the spacecrafts
115 */
116 public SpacecraftState[] getStates() {
117 return states.clone();
118 }
119
120 /** Get the coordinates of the measurements participants in signal travel order.
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 relfect 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
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 /** Get the estimated value.
149 * @return estimated value
150 */
151 public double[] getEstimatedValue() {
152 return estimatedValue.clone();
153 }
154
155 /** Set the estimated value.
156 * @param estimatedValue estimated value
157 */
158 public void setEstimatedValue(final double... estimatedValue) {
159 this.estimatedValue = estimatedValue.clone();
160 }
161
162 /** Get the status.
163 * <p>
164 * The status is set to {@link Status#PROCESSED PROCESSED} at construction, and
165 * can be reset to {@link Status#REJECTED REJECTED} later on, typically by
166 * {@link org.orekit.estimation.measurements.modifiers.OutlierFilter OutlierFilter}
167 * or {@link org.orekit.estimation.measurements.modifiers.DynamicOutlierFilter DynamicOutlierFilter}
168 * </p>
169 * @return status
170 */
171 public Status getStatus() {
172 return status;
173 }
174
175 /** Set the status.
176 * @param status status to set
177 */
178 public void setStatus(final Status status) {
179 this.status = status;
180 }
181
182 /** Get state size.
183 * <p>
184 * Warning, the {@link #setStateDerivatives(int, double[][])}
185 * method must have been called before this method is called.
186 * </p>
187 * @return state size
188 * @since 10.1
189 */
190 public int getStateSize() {
191 return stateDerivatives[0][0].length;
192 }
193
194 /** Get the partial derivatives of the {@link #getEstimatedValue()
195 * simulated measurement} with respect to state Cartesian coordinates.
196 * @param index index of the state, according to the {@code states}
197 * passed at construction
198 * @return partial derivatives of the simulated value (array of size
199 * {@link ObservedMeasurement#getDimension() dimension} x 6)
200 */
201 public double[][] getStateDerivatives(final int index) {
202 final double[][] sd = new double[observedMeasurement.getDimension()][];
203 for (int i = 0; i < observedMeasurement.getDimension(); ++i) {
204 sd[i] = stateDerivatives[index][i].clone();
205 }
206 return sd;
207 }
208
209 /** Set the partial derivatives of the {@link #getEstimatedValue()
210 * simulated measurement} with respect to state Cartesian coordinates.
211 * @param index index of the state, according to the {@code states}
212 * passed at construction
213 * @param derivatives partial derivatives with respect to state
214 */
215 public void setStateDerivatives(final int index, final double[]... derivatives) {
216 this.stateDerivatives[index] = new double[observedMeasurement.getDimension()][];
217 for (int i = 0; i < observedMeasurement.getDimension(); ++i) {
218 this.stateDerivatives[index][i] = derivatives[i].clone();
219 }
220 }
221
222 /** Get all the drivers with set derivatives.
223 * @return all the drivers with set derivatives
224 * @since 9.0
225 */
226 public Stream<ParameterDriver> getDerivativesDrivers() {
227 return parametersDerivatives.entrySet().stream().map(entry -> entry.getKey());
228 }
229
230 /** Get the partial derivatives of the {@link #getEstimatedValue()
231 * simulated measurement} with respect to a parameter.
232 * @param driver driver for the parameter
233 * @return partial derivatives of the simulated value
234 * @exception OrekitIllegalArgumentException if parameter is unknown
235 */
236 public double[] getParameterDerivatives(final ParameterDriver driver)
237 throws OrekitIllegalArgumentException {
238 final double[] p = parametersDerivatives.get(driver);
239 if (p == null) {
240 final StringBuilder builder = new StringBuilder();
241 for (final Map.Entry<ParameterDriver, double[]> entry : parametersDerivatives.entrySet()) {
242 if (builder.length() > 0) {
243 builder.append(", ");
244 }
245 builder.append(entry.getKey().getName());
246 }
247 throw new OrekitIllegalArgumentException(OrekitMessages.UNSUPPORTED_PARAMETER_NAME,
248 driver.getName(),
249 builder.length() > 0 ? builder.toString() : "<none>");
250 }
251 return p;
252 }
253
254 /** Set the partial derivatives of the {@link #getEstimatedValue()
255 * simulated measurement} with respect to parameter.
256 * @param driver driver for the parameter
257 * @param parameterDerivatives partial derivatives with respect to parameter
258 */
259 public void setParameterDerivatives(final ParameterDriver driver, final double... parameterDerivatives) {
260 parametersDerivatives.put(driver, parameterDerivatives);
261 }
262
263 /** Enumerate for the status of the measurement. */
264 public enum Status {
265
266 /** Status for processed measurements. */
267 PROCESSED,
268
269 /** Status for rejected measurements. */
270 REJECTED;
271
272 }
273
274 }