1   /* Copyright 2002-2022 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.modifiers;
18  
19  import java.util.List;
20  
21  import org.hipparchus.optim.nonlinear.vector.leastsquares.LevenbergMarquardtOptimizer;
22  import org.hipparchus.random.RandomGenerator;
23  import org.hipparchus.random.Well19937a;
24  import org.junit.Assert;
25  import org.junit.Test;
26  import org.orekit.errors.OrekitException;
27  import org.orekit.errors.OrekitMessages;
28  import org.orekit.estimation.Context;
29  import org.orekit.estimation.EstimationTestUtils;
30  import org.orekit.estimation.leastsquares.BatchLSEstimator;
31  import org.orekit.estimation.measurements.ObservedMeasurement;
32  import org.orekit.estimation.measurements.Range;
33  import org.orekit.estimation.measurements.RangeMeasurementCreator;
34  import org.orekit.frames.TopocentricFrame;
35  import org.orekit.orbits.OrbitType;
36  import org.orekit.orbits.PositionAngle;
37  import org.orekit.propagation.Propagator;
38  import org.orekit.propagation.conversion.NumericalPropagatorBuilder;
39  import org.orekit.utils.ParameterDriver;
40  
41  public class BiasTest {
42  
43      @SuppressWarnings("unchecked")
44      @Test
45      public void testEstimateBias() {
46  
47          Context context = EstimationTestUtils.eccentricContext("regular-data:potential:tides");
48  
49          final NumericalPropagatorBuilder propagatorBuilder =
50                          context.createBuilder(OrbitType.KEPLERIAN, PositionAngle.TRUE, true,
51                                                1.0e-6, 60.0, 0.001);
52  
53          // create perfect range measurements
54          final Propagator propagator = EstimationTestUtils.createPropagator(context.initialOrbit,
55                                                                             propagatorBuilder);
56          final List<ObservedMeasurement<?>> measurements =
57                          EstimationTestUtils.createMeasurements(propagator,
58                                                                 new RangeMeasurementCreator(context),
59                                                                 1.0, 3.0, 300.0);
60  
61          // create range biases: one bias for each station
62          final RandomGenerator random = new Well19937a(0x0c4b69da5d64b35al);
63          final Bias<?>[] stationsRangeBiases = new Bias<?>[context.stations.size()];
64          final double[] realStationsBiases  = new double[context.stations.size()];
65          for (int i = 0; i < context.stations.size(); ++i) {
66              final TopocentricFrame base = context.stations.get(i).getBaseFrame();
67              stationsRangeBiases[i] = new Bias<Range>(new String[] {
68                                                           base.getName() + " range bias"
69                                                       },
70                                                       new double[] {
71                                                           0.0
72                                                       },
73                                                       new double[] {
74                                                           1.0
75                                                       },
76                                                       new double[] {
77                                                           Double.NEGATIVE_INFINITY
78                                                       },
79                                                       new double[] {
80                                                           Double.POSITIVE_INFINITY
81                                                       });
82              realStationsBiases[i]  = 2 * random.nextDouble() - 1;
83          }
84  
85          // create orbit estimator
86          final BatchLSEstimator estimator = new BatchLSEstimator(new LevenbergMarquardtOptimizer(),
87                                                                  propagatorBuilder);
88  
89          // add the measurements, with both spacecraft and stations biases
90          for (final ObservedMeasurement<?> measurement : measurements) {
91              final Range range = (Range) measurement;
92              for (int i = 0; i < context.stations.size(); ++i) {
93                  if (range.getStation() == context.stations.get(i)) {
94                      double biasedRange = range.getObservedValue()[0] + realStationsBiases[i];
95                      final Range m = new Range(range.getStation(),
96                                                range.isTwoWay(),
97                                                range.getDate(),
98                                                biasedRange,
99                                                range.getTheoreticalStandardDeviation()[0],
100                                               range.getBaseWeight()[0],
101                                               range.getSatellites().get(0));
102                     m.addModifier((Bias<Range>) stationsRangeBiases[i]);
103                     estimator.addMeasurement(m);
104                 }
105             }
106         }
107 
108         estimator.setParametersConvergenceThreshold(1.0e-3);
109         estimator.setMaxIterations(10);
110         estimator.setMaxEvaluations(20);
111 
112         // we want to estimate the biases
113         for (Bias<?> bias : stationsRangeBiases) {
114             for (final ParameterDriver driver : bias.getParametersDrivers()) {
115                 driver.setSelected(true);
116             }
117         }
118 
119         EstimationTestUtils.checkFit(context, estimator, 2, 3,
120                                      0.0,  7.2e-7,
121                                      0.0,  2.1e-6,
122                                      0.0,  3.7e-7,
123                                      0.0,  1.7e-10);
124         for (int i = 0; i < stationsRangeBiases.length; ++i) {
125             Assert.assertEquals(realStationsBiases[i],
126                                 stationsRangeBiases[i].getParametersDrivers().get(0).getValue(),
127                                 3.3e-6);
128         }
129 
130     }
131 
132     @Test
133     public void testTooSmallScale() {
134         try {
135             new Bias<Range>(new String[] { "OK", "not-OK" },
136                             new double[] { 1000.0,    1000.0 },
137                             new double[] {    1.0,    0.0 },
138                             new double[] { -10000.0, -10000.0 },
139                             new double[] { +10000.0, +10000.0 });
140             Assert.fail("an exception should have been thrown");
141         } catch (OrekitException oe) {
142             Assert.assertEquals(OrekitMessages.TOO_SMALL_SCALE_FOR_PARAMETER, oe.getSpecifier());
143             Assert.assertEquals("not-OK", oe.getParts()[0]);
144         }
145     }
146 }
147 
148