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.leastsquares;
18  
19  import org.hipparchus.geometry.euclidean.threed.Vector3D;
20  import org.hipparchus.linear.ArrayRealVector;
21  import org.hipparchus.linear.RealMatrix;
22  import org.hipparchus.linear.RealVector;
23  import org.hipparchus.util.Incrementor;
24  import org.hipparchus.util.Pair;
25  import org.junit.jupiter.api.Assertions;
26  import org.junit.jupiter.api.Test;
27  import org.orekit.estimation.Context;
28  import org.orekit.estimation.EstimationTestUtils;
29  import org.orekit.estimation.measurements.EstimatedMeasurement;
30  import org.orekit.estimation.measurements.ObservedMeasurement;
31  import org.orekit.estimation.measurements.PVMeasurementCreator;
32  import org.orekit.orbits.Orbit;
33  import org.orekit.orbits.OrbitType;
34  import org.orekit.orbits.PositionAngleType;
35  import org.orekit.propagation.Propagator;
36  import org.orekit.propagation.conversion.NumericalPropagatorBuilder;
37  import org.orekit.time.AbsoluteDate;
38  import org.orekit.utils.ParameterDriver;
39  import org.orekit.utils.ParameterDriversList;
40  
41  import java.util.List;
42  import java.util.Map;
43  
44  public class BatchLSModelTest {
45  
46      @Test
47      public void testPerfectValue() {
48  
49          final Context context = EstimationTestUtils.eccentricContext("regular-data:potential:tides");
50  
51          final NumericalPropagatorBuilder propagatorBuilder =
52                          context.createBuilder(OrbitType.KEPLERIAN, PositionAngleType.TRUE, true,
53                                                1.0e-6, 60.0, 0.001);
54          final NumericalPropagatorBuilder[] builders = { propagatorBuilder };
55  
56          // create perfect PV measurements
57          final Propagator propagator = EstimationTestUtils.createPropagator(context.initialOrbit,
58                                                                             propagatorBuilder);
59          final List<ObservedMeasurement<?>> measurements =
60                          EstimationTestUtils.createMeasurements(propagator,
61                                                                 new PVMeasurementCreator(),
62                                                                 0.0, 1.0, 300.0);
63          final ParameterDriversList estimatedMeasurementsParameters = new ParameterDriversList();
64          for (ObservedMeasurement<?> measurement : measurements) {
65              for (final ParameterDriver driver : measurement.getParametersDrivers()) {
66                  if (driver.isSelected()) {
67                      estimatedMeasurementsParameters.add(driver);
68                  }
69              }
70          }
71  
72          // create model
73          final ModelObserver modelObserver = new ModelObserver() {
74              /** {@inheritDoc} */
75              @Override
76              public void modelCalled(final Orbit[] newOrbits,
77                                      final Map<ObservedMeasurement<?>, EstimatedMeasurement<?>> newEvaluations) {
78                  Assertions.assertEquals(1, newOrbits.length);
79                  Assertions.assertEquals(0, context.initialOrbit.getDate().durationFrom(newOrbits[0].getDate()),
80                          1.0e-15);
81                  Assertions.assertEquals(0, Vector3D.distance(context.initialOrbit.getPosition(),
82                                    newOrbits[0].getPosition()), 1.0e-15);
83                  Assertions.assertEquals(measurements.size(), newEvaluations.size());
84              }
85          };
86          final BatchLSModel model = new BatchLSModel(builders, measurements, estimatedMeasurementsParameters, modelObserver);
87          model.setIterationsCounter(new Incrementor(100));
88          model.setEvaluationsCounter(new Incrementor(100));
89  
90          // Test forward propagation flag to true
91          Assertions.assertEquals(true, model.isForwardPropagation());
92  
93          // evaluate model on perfect start point
94          final double[] normalizedProp = propagatorBuilder.getSelectedNormalizedParameters();
95          final double[] normalized = new double[normalizedProp.length + estimatedMeasurementsParameters.getNbParams()];
96          System.arraycopy(normalizedProp, 0, normalized, 0, normalizedProp.length);
97          int i = normalizedProp.length;
98          for (final ParameterDriver driver : estimatedMeasurementsParameters.getDrivers()) {
99              normalized[i++] = driver.getNormalizedValue(new AbsoluteDate());
100         }
101         Pair<RealVector, RealMatrix> value = model.value(new ArrayRealVector(normalized));
102         int index = 0;
103         for (ObservedMeasurement<?> measurement : measurements) {
104             for (int k = 0; k < measurement.getDimension(); ++k) {
105                 // the value is already a weighted residual
106                 Assertions.assertEquals(0.0, value.getFirst().getEntry(index++), 1.6e-7);
107             }
108         }
109         Assertions.assertEquals(index, value.getFirst().getDimension());
110 
111     }
112 
113     @Test
114     public void testBackwardPropagation() {
115 
116         final Context context = EstimationTestUtils.eccentricContext("regular-data:potential:tides");
117 
118         final NumericalPropagatorBuilder propagatorBuilder =
119                         context.createBuilder(OrbitType.KEPLERIAN, PositionAngleType.TRUE, true,
120                                               1.0e-6, 60.0, 0.001);
121         final NumericalPropagatorBuilder[] builders = { propagatorBuilder };
122 
123         // create perfect PV measurements
124         final Propagator propagator = EstimationTestUtils.createPropagator(context.initialOrbit,
125                                                                            propagatorBuilder);
126         final List<ObservedMeasurement<?>> measurements =
127                         EstimationTestUtils.createMeasurements(propagator,
128                                                                new PVMeasurementCreator(),
129                                                                0.0, -1.0, 300.0);
130         final ParameterDriversList estimatedMeasurementsParameters = new ParameterDriversList();
131         for (ObservedMeasurement<?> measurement : measurements) {
132             for (final ParameterDriver driver : measurement.getParametersDrivers()) {
133                 if (driver.isSelected()) {
134                     estimatedMeasurementsParameters.add(driver);
135                 }
136             }
137         }
138 
139         // create model
140         final ModelObserver modelObserver = new ModelObserver() {
141             /** {@inheritDoc} */
142             @Override
143             public void modelCalled(final Orbit[] newOrbits,
144                                     final Map<ObservedMeasurement<?>, EstimatedMeasurement<?>> newEvaluations) {
145                 // Do nothing here
146             }
147         };
148         final BatchLSModel model = new BatchLSModel(builders, measurements, estimatedMeasurementsParameters, modelObserver);
149         // Test forward propagation flag to false
150         Assertions.assertEquals(false, model.isForwardPropagation());
151     }
152 
153 }
154 
155 
156