1   package org.orekit.rugged.adjustment;
2   
3   import java.lang.reflect.Field;
4   import java.util.ArrayList;
5   import java.util.Collection;
6   import java.util.Collections;
7   import java.util.Iterator;
8   import java.util.List;
9   import java.util.Map.Entry;
10  import java.util.Set;
11  
12  import org.hipparchus.optim.nonlinear.vector.leastsquares.LeastSquaresOptimizer.Optimum;
13  import org.junit.jupiter.api.AfterEach;
14  import org.junit.jupiter.api.Assertions;
15  import org.junit.jupiter.api.BeforeEach;
16  import org.junit.jupiter.api.Test;
17  import org.orekit.bodies.GeodeticPoint;
18  import org.orekit.rugged.TestUtils;
19  import org.orekit.rugged.adjustment.measurements.Observables;
20  import org.orekit.rugged.adjustment.measurements.SensorToGroundMapping;
21  import org.orekit.rugged.adjustment.util.InitGroundRefiningTest;
22  import org.orekit.rugged.adjustment.util.RefiningParametersDriver;
23  import org.orekit.rugged.api.Rugged;
24  import org.orekit.rugged.errors.RuggedException;
25  import org.orekit.rugged.errors.RuggedMessages;
26  import org.orekit.rugged.linesensor.LineSensor;
27  import org.orekit.rugged.linesensor.SensorPixel;
28  
29  public class GroundOptimizationProblemBuilderTest {
30  
31      @BeforeEach
32      public void setUp() {
33  
34          try {
35              refiningTest = new InitGroundRefiningTest();
36              refiningTest.initGroundRefiningTest();
37              
38              rugged = refiningTest.getRugged();
39              // get the only line sensor 
40              LineSensor sensor = rugged.getLineSensors().iterator().next();
41              sensorName = sensor.getName();
42  
43              measurements = refiningTest.generateNoisyPoints(lineSampling, pixelSampling, false);
44              numberOfParameters = refiningTest.getParameterToAdjust();
45  
46          }  catch (RuggedException re) {
47              Assertions.fail(re.getLocalizedMessage());
48          }
49      }
50      
51      @Test
52      public void testEstimateFreeParameters() {
53          
54          AdjustmentContext adjustmentContext = new AdjustmentContext(Collections.singletonList(rugged), measurements);
55          final int maxIterations = 50;
56          final double convergenceThreshold = 1.e-11;
57          Optimum optimum = adjustmentContext.estimateFreeParameters(Collections.singletonList(rugged.getName()), maxIterations, convergenceThreshold);
58          
59          Assertions.assertTrue(optimum.getIterations() < maxIterations);
60  
61          // The default optimizer is a Gauss Newton.
62          // For Gauss Newton, the number of evaluations is equal to the number of iterations
63          Assertions.assertTrue(optimum.getEvaluations() == optimum.getIterations());
64  
65          final double expectedMaxValue = 39200.0;
66          Assertions.assertEquals(expectedMaxValue, optimum.getResiduals().getMaxValue(), 1.0e-6);
67  
68          final double expectedRMS = 5067.112098;
69          Assertions.assertEquals(expectedRMS, optimum.getRMS(), 1.0e-6);
70  
71          final double expectedCost = 286639.1460351976;
72          Assertions.assertEquals(expectedCost, optimum.getCost(), 1.0e-6);
73  
74          Assertions.assertTrue(numberOfParameters == optimum.getPoint().getDimension());
75  
76          final int sensorToGroundMappingSize = 1600;
77          Collection<SensorToGroundMapping> ssm = measurements.getGroundMappings();
78          Iterator<SensorToGroundMapping> it = ssm.iterator();
79          while (it.hasNext()) {
80              SensorToGroundMapping ssmit = it.next();
81              Assertions.assertTrue(sensorToGroundMappingSize == ssmit.getMapping().size());
82          }        
83          Assertions.assertTrue(sensorToGroundMappingSize*2 == optimum.getResiduals().getDimension());
84      }
85  
86      @Test
87      public void testNoParametersSelected() {
88          try {
89              RefiningParametersDriver.unselectRoll(rugged, sensorName);
90              RefiningParametersDriver.unselectPitch(rugged, sensorName);
91              
92              AdjustmentContext adjustmentContext = new AdjustmentContext(Collections.singletonList(rugged), measurements);
93              final int maxIterations = 50;
94              final double convergenceThreshold = 1.e-11;
95              
96              adjustmentContext.estimateFreeParameters(Collections.singletonList(rugged.getName()), maxIterations, convergenceThreshold);
97              Assertions.fail("An exception should have been thrown");
98  
99          } catch (RuggedException re) {
100             Assertions.assertEquals(RuggedMessages.NO_PARAMETERS_SELECTED,re.getSpecifier());
101         }
102     }
103     
104     @Test
105     public void testNoReferenceMapping() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
106 
107         try {
108             final int maxIterations = 50;
109             final double convergenceThreshold = 1.e-11;
110 
111             final List<LineSensor> selectedSensors = new ArrayList<LineSensor>();
112             selectedSensors.addAll(rugged.getLineSensors());
113             
114             final GroundOptimizationProblemBuilder groundOptimizationProblem = 
115                     new GroundOptimizationProblemBuilder(selectedSensors, measurements, rugged);
116 
117             Field sensorToGroundMapping = groundOptimizationProblem.getClass().getDeclaredField("sensorToGroundMappings");
118             sensorToGroundMapping.setAccessible(true);
119             sensorToGroundMapping.set(groundOptimizationProblem,new ArrayList<SensorToGroundMapping>());
120 
121             groundOptimizationProblem.build(maxIterations, convergenceThreshold);
122             Assertions.fail("An exception should have been thrown");
123 
124         } catch  (RuggedException re) {
125             Assertions.assertEquals(RuggedMessages.NO_REFERENCE_MAPPINGS,re.getSpecifier());
126         }
127     }
128     
129     @Test
130     public void testDefaultRuggedName(){
131         
132         // Get the measurements as computed in other tests
133         Collection<SensorToGroundMapping> sensorToGroundMapping = measurements.getGroundMappings();
134         int nbModels = measurements.getNbModels();
135 
136         // Recompute the measurements in another way ... but that must be the same after all
137         Observables measurementsNoName = refiningTest.generateNoisyPoints(lineSampling, pixelSampling, true);
138         Collection<SensorToGroundMapping> sensorToGroundMappingNoName = measurementsNoName.getGroundMappings();
139         int nbModelsWithWeight = measurementsNoName.getNbModels();
140         
141         // Compare the two collections of measurements
142         Assertions.assertEquals(nbModels, nbModelsWithWeight);
143 
144         Assertions.assertEquals(sensorToGroundMapping.size(), sensorToGroundMappingNoName.size());
145 
146         // There is only one item
147         SensorToGroundMapping arraySensorToGroundMapping          = (SensorToGroundMapping) sensorToGroundMapping.toArray()[0];
148         SensorToGroundMapping arraySensorToGroundMappingNoName = (SensorToGroundMapping) sensorToGroundMappingNoName.toArray()[0];
149 
150 
151         // Check if the two set are the same
152         Set<Entry<SensorPixel, GeodeticPoint>> mapping          = arraySensorToGroundMapping.getMapping();
153         Set<Entry<SensorPixel, GeodeticPoint>> mappingNoName = arraySensorToGroundMappingNoName.getMapping();
154 
155         Iterator<Entry<SensorPixel, GeodeticPoint>> itMapping = mapping.iterator();
156         while(itMapping.hasNext()) {
157             Entry<SensorPixel, GeodeticPoint> current = itMapping.next();
158             SensorPixel key = current.getKey();
159             GeodeticPoint value = current.getValue();
160 
161             // Will search in mappingNoName if we can find the (key,value) found in mapping 
162             Boolean found = false;
163             Iterator<Entry<SensorPixel, GeodeticPoint>> itMappingNoName = mappingNoName.iterator();
164             while(itMappingNoName.hasNext()) {
165                 Entry<SensorPixel, GeodeticPoint> currentNoName = itMappingNoName.next();
166                 SensorPixel keyNoName = currentNoName.getKey();
167                 GeodeticPoint valueNoName = currentNoName.getValue();
168 
169                 // Comparison of each SensorPixel (for the key part and the value part)
170                 if (TestUtils.sameSensorPixels(key, keyNoName, 1.e-3) &&
171                     TestUtils.sameGeodeticPoints(value, valueNoName, 1.e-3)) {
172                     // we found a match ...
173                     found = true;
174                 }
175             } // end iteration on mappingNoName
176 
177             if (!found) { // the current (key,value) of the mapping was not found in the mappingNoName
178                 Assertions.assertTrue(found);
179             }
180         } // end on iteration on mapping
181 
182         Assertions.assertEquals(arraySensorToGroundMapping.getRuggedName(),arraySensorToGroundMappingNoName.getRuggedName());
183         Assertions.assertEquals(arraySensorToGroundMapping.getSensorName(),arraySensorToGroundMappingNoName.getSensorName());;
184     }
185     
186     
187     @AfterEach
188     public void tearDown() {
189         measurements = null;
190     }
191 
192     private InitGroundRefiningTest refiningTest;
193     private Observables measurements;
194     private Rugged rugged;
195     private String sensorName;
196     private int numberOfParameters;
197     
198     private  final int lineSampling = 1000;
199     private final int pixelSampling = 1000;
200 }