From 049902bf550a1f66e798464a5acb928933fa9b94 Mon Sep 17 00:00:00 2001
From: Luc Maisonobe <luc@orekit.org>
Date: Wed, 24 Aug 2016 10:21:25 +0200
Subject: [PATCH] Added more error detection to parameters estimation.

---
 .../java/org/orekit/rugged/api/Rugged.java    | 18 +++--
 .../orekit/rugged/errors/RuggedMessages.java  |  2 +
 .../org/orekit/rugged/RuggedMessages_de.utf8  |  6 ++
 .../org/orekit/rugged/RuggedMessages_en.utf8  |  7 +-
 .../org/orekit/rugged/RuggedMessages_es.utf8  |  6 ++
 .../org/orekit/rugged/RuggedMessages_fr.utf8  |  7 +-
 .../org/orekit/rugged/RuggedMessages_gl.utf8  |  7 +-
 .../org/orekit/rugged/RuggedMessages_it.utf8  |  7 +-
 .../org/orekit/rugged/RuggedMessages_no.utf8  |  6 ++
 .../org/orekit/rugged/RuggedMessages_ro.utf8  |  6 ++
 .../org/orekit/rugged/api/RuggedTest.java     | 70 +++++++++++++++++--
 .../rugged/errors/RuggedMessagesTest.java     |  2 +-
 12 files changed, 127 insertions(+), 17 deletions(-)

diff --git a/src/main/java/org/orekit/rugged/api/Rugged.java b/src/main/java/org/orekit/rugged/api/Rugged.java
index 8b273060..3609513c 100644
--- a/src/main/java/org/orekit/rugged/api/Rugged.java
+++ b/src/main/java/org/orekit/rugged/api/Rugged.java
@@ -713,7 +713,7 @@ public class Rugged {
      * <p>
      * Before using this method, the {@link ParameterDriver viewing model
      * parameters} retrieved by calling the {@link
-     * LineSensor#getExtendedParametersDrivers() getExtendedParametersDrivers()}
+     * LineSensor#getParametersDrivers() getParametersDrivers()}
      * method on the desired sensors must be configured. The parameters that should
      * be estimated must have their {@link ParameterDriver#setSelected(boolean)
      * selection status} set to {@link true} whereas the parameters that should retain
@@ -730,11 +730,11 @@ public class Rugged {
      * </p>
      * <p>
      * The estimated parameters can be retrieved after the method completes by calling
-     * again the {@link LineSensor#getExtendedParametersDrivers() getExtendedParametersDrivers()}
+     * again the {@link LineSensor#getParametersDrivers() getParametersDrivers()}
      * method on the desired sensors and checking the updated values of the parameters.
      * In fact, as the values of the parameters are already updated by this method, if
-     * wants to use the updated values immediately to perform new direct/inverse
-     * locations they can do so without looking at the parameters: the viewing models
+     * users want to use the updated values immediately to perform new direct/inverse
+     * locations, they can do so without looking at the parameters: the viewing models
      * are already aware of the updated parameters.
      * </p>
      * @param references reference mappings between sensors pixels and ground point that
@@ -744,7 +744,8 @@ public class Rugged {
      * normalized parameters (dimensionless, related to parameters scales)
      * @return optimum of the least squares problem
      * @exception RuggedException if several parameters with the same name exist,
-     * or if parameters cannot be estimated (too few measurements, ill-conditioned problem ...)
+     * if no parameters have been selected for estimation, or if parameters cannot be
+     * estimated (too few measurements, ill-conditioned problem ...)
      */
     public Optimum estimateFreeParameters(final Collection<SensorToGroundMapping> references,
                                           final int maxEvaluations,
@@ -758,6 +759,9 @@ public class Rugged {
             }
             final DSGenerator generator = createGenerator(selectedSensors);
             final List<ParameterDriver> selected = generator.getSelected();
+            if (selected.isEmpty()) {
+                throw new RuggedException(RuggedMessages.NO_PARAMETERS_SELECTED);
+            }
 
             // get start point (as a normalized value)
             final double[] start = new double[selected.size()];
@@ -770,6 +774,9 @@ public class Rugged {
             for (final SensorToGroundMapping reference : references) {
                 n += reference.getMappings().size();
             }
+            if (n == 0) {
+                throw new RuggedException(RuggedMessages.NO_REFERENCE_MAPPINGS);
+            }
             final double[] target = new double[2 * n];
             double min = Double.POSITIVE_INFINITY;
             double max = Double.NEGATIVE_INFINITY;
@@ -905,6 +912,7 @@ public class Rugged {
                     throw new RuggedExceptionWrapper(new RuggedException(RuggedMessages.DUPLICATED_PARAMETER_NAME,
                                                                          driver.getName()));
                 }
+                names.add(driver.getName());
             });
         }
 
diff --git a/src/main/java/org/orekit/rugged/errors/RuggedMessages.java b/src/main/java/org/orekit/rugged/errors/RuggedMessages.java
index a0c453b1..0b021db9 100644
--- a/src/main/java/org/orekit/rugged/errors/RuggedMessages.java
+++ b/src/main/java/org/orekit/rugged/errors/RuggedMessages.java
@@ -75,6 +75,8 @@ public enum RuggedMessages implements Localizable {
     ABERRATION_OF_LIGHT_CORRECTION_REDEFINED("aberration of light correction redefined, line {0}, file {1}: {2}"),
     TILE_ALREADY_DEFINED("tile {0} already defined, line {1}, file {2}: {3}"),
     UNKNOWN_TILE("unknown tile {0}, line {1}, file {2}: {3}"),
+    NO_PARAMETERS_SELECTED("no parameters have been selected for estimation"),
+    NO_REFERENCE_MAPPINGS("no reference mappings for parameters estimation"),
     DUPLICATED_PARAMETER_NAME("a different parameter with name {0} already exists");
 
     // CHECKSTYLE: resume JavadocVariable check
diff --git a/src/main/resources/assets/org/orekit/rugged/RuggedMessages_de.utf8 b/src/main/resources/assets/org/orekit/rugged/RuggedMessages_de.utf8
index 9938abc6..3982b7c8 100644
--- a/src/main/resources/assets/org/orekit/rugged/RuggedMessages_de.utf8
+++ b/src/main/resources/assets/org/orekit/rugged/RuggedMessages_de.utf8
@@ -72,6 +72,12 @@ TILE_ALREADY_DEFINED = <MISSING TRANSLATION>
 
 # unknown tile {0}, line {1}, file {2}: {3}
 UNKNOWN_TILE = <MISSING TRANSLATION>
+ 
+# no parameters have been selected for estimation
+NO_PARAMETERS_SELECTED = <MISSING TRANSLATION>
+
+# no reference mappings for parameters estimation
+NO_REFERENCE_MAPPINGS = <MISSING TRANSLATION>
 
 # a different parameter with name {0} already exists
 DUPLICATED_PARAMETER_NAME = <MISSING TRANSLATION>
diff --git a/src/main/resources/assets/org/orekit/rugged/RuggedMessages_en.utf8 b/src/main/resources/assets/org/orekit/rugged/RuggedMessages_en.utf8
index b3604412..75e9cab1 100644
--- a/src/main/resources/assets/org/orekit/rugged/RuggedMessages_en.utf8
+++ b/src/main/resources/assets/org/orekit/rugged/RuggedMessages_en.utf8
@@ -73,6 +73,11 @@ TILE_ALREADY_DEFINED = tile {0} already defined, line {1}, file {2}: {3}
 # unknown tile {0}, line {1}, file {2}: {3}
 UNKNOWN_TILE = unknown tile {0}, line {1}, file {2}: {3}
 
+# no parameters have been selected for estimation
+NO_PARAMETERS_SELECTED = no parameters have been selected for estimation
+
+# no reference mappings for parameters estimation
+NO_REFERENCE_MAPPINGS = no reference mappings for parameters estimation
+
 # a different parameter with name {0} already exists
 DUPLICATED_PARAMETER_NAME = a different parameter with name {0} already exists
-
diff --git a/src/main/resources/assets/org/orekit/rugged/RuggedMessages_es.utf8 b/src/main/resources/assets/org/orekit/rugged/RuggedMessages_es.utf8
index 25642997..113d92b8 100644
--- a/src/main/resources/assets/org/orekit/rugged/RuggedMessages_es.utf8
+++ b/src/main/resources/assets/org/orekit/rugged/RuggedMessages_es.utf8
@@ -73,5 +73,11 @@ TILE_ALREADY_DEFINED = <MISSING TRANSLATION>
 # unknown tile {0}, line {1}, file {2}: {3}
 UNKNOWN_TILE = <MISSING TRANSLATION>
 
+# no parameters have been selected for estimation
+NO_PARAMETERS_SELECTED = <MISSING TRANSLATION>
+
+# no reference mappings for parameters estimation
+NO_REFERENCE_MAPPINGS = <MISSING TRANSLATION>
+
 # a different parameter with name {0} already exists
 DUPLICATED_PARAMETER_NAME = <MISSING TRANSLATION>
diff --git a/src/main/resources/assets/org/orekit/rugged/RuggedMessages_fr.utf8 b/src/main/resources/assets/org/orekit/rugged/RuggedMessages_fr.utf8
index 969170f1..9854f68f 100644
--- a/src/main/resources/assets/org/orekit/rugged/RuggedMessages_fr.utf8
+++ b/src/main/resources/assets/org/orekit/rugged/RuggedMessages_fr.utf8
@@ -73,6 +73,11 @@ TILE_ALREADY_DEFINED = tuile {0} déjà définie ligne {1} du fichier {2}: {3}
 # unknown tile {0}, line {1}, file {2}: {3}
 UNKNOWN_TILE = tuile {0} inconnue ligne {1} du fichier {2}: {3}
 
+# no parameters have been selected for estimation
+NO_PARAMETERS_SELECTED = aucun paramètre n''a été sélectionné pour être estimé
+
+# no reference mappings for parameters estimation
+NO_REFERENCE_MAPPINGS = aucune projection de référence pour l''estimation des paramètres
+
 # a different parameter with name {0} already exists
 DUPLICATED_PARAMETER_NAME = il existe déjà un autre paramètre nommé {0}
-
diff --git a/src/main/resources/assets/org/orekit/rugged/RuggedMessages_gl.utf8 b/src/main/resources/assets/org/orekit/rugged/RuggedMessages_gl.utf8
index 27bf9ece..434a10aa 100644
--- a/src/main/resources/assets/org/orekit/rugged/RuggedMessages_gl.utf8
+++ b/src/main/resources/assets/org/orekit/rugged/RuggedMessages_gl.utf8
@@ -73,6 +73,11 @@ TILE_ALREADY_DEFINED = <MISSING TRANSLATION>
 # unknown tile {0}, line {1}, file {2}: {3}
 UNKNOWN_TILE = <MISSING TRANSLATION>
 
+# no parameters have been selected for estimation
+NO_PARAMETERS_SELECTED = <MISSING TRANSLATION>
+
+# no reference mappings for parameters estimation
+NO_REFERENCE_MAPPINGS = <MISSING TRANSLATION>
+
 # a different parameter with name {0} already exists
 DUPLICATED_PARAMETER_NAME = <MISSING TRANSLATION>
-
diff --git a/src/main/resources/assets/org/orekit/rugged/RuggedMessages_it.utf8 b/src/main/resources/assets/org/orekit/rugged/RuggedMessages_it.utf8
index 569c8374..90dd36c0 100644
--- a/src/main/resources/assets/org/orekit/rugged/RuggedMessages_it.utf8
+++ b/src/main/resources/assets/org/orekit/rugged/RuggedMessages_it.utf8
@@ -73,6 +73,11 @@ TILE_ALREADY_DEFINED = <MISSING TRANSLATION>
 # unknown tile {0}, line {1}, file {2}: {3}
 UNKNOWN_TILE = <MISSING TRANSLATION>
 
+# no parameters have been selected for estimation
+NO_PARAMETERS_SELECTED = <MISSING TRANSLATION>
+
+# no reference mappings for parameters estimation
+NO_REFERENCE_MAPPINGS = <MISSING TRANSLATION>
+
 # a different parameter with name {0} already exists
 DUPLICATED_PARAMETER_NAME = <MISSING TRANSLATION>
-
diff --git a/src/main/resources/assets/org/orekit/rugged/RuggedMessages_no.utf8 b/src/main/resources/assets/org/orekit/rugged/RuggedMessages_no.utf8
index f94c208b..ccca6d63 100644
--- a/src/main/resources/assets/org/orekit/rugged/RuggedMessages_no.utf8
+++ b/src/main/resources/assets/org/orekit/rugged/RuggedMessages_no.utf8
@@ -73,5 +73,11 @@ TILE_ALREADY_DEFINED = <MISSING TRANSLATION>
 # unknown tile {0}, line {1}, file {2}: {3}
 UNKNOWN_TILE = <MISSING TRANSLATION>
 
+# no parameters have been selected for estimation
+NO_PARAMETERS_SELECTED = <MISSING TRANSLATION>
+
+# no reference mappings for parameters estimation
+NO_REFERENCE_MAPPINGS = <MISSING TRANSLATION>
+
 # a different parameter with name {0} already exists
 DUPLICATED_PARAMETER_NAME = <MISSING TRANSLATION>
diff --git a/src/main/resources/assets/org/orekit/rugged/RuggedMessages_ro.utf8 b/src/main/resources/assets/org/orekit/rugged/RuggedMessages_ro.utf8
index 72263acf..7aa5bbb8 100644
--- a/src/main/resources/assets/org/orekit/rugged/RuggedMessages_ro.utf8
+++ b/src/main/resources/assets/org/orekit/rugged/RuggedMessages_ro.utf8
@@ -73,5 +73,11 @@ TILE_ALREADY_DEFINED = <MISSING TRANSLATION>
 # unknown tile {0}, line {1}, file {2}: {3}
 UNKNOWN_TILE = <MISSING TRANSLATION>
 
+# no parameters have been selected for estimation
+NO_PARAMETERS_SELECTED = <MISSING TRANSLATION>
+
+# no reference mappings for parameters estimation
+NO_REFERENCE_MAPPINGS = <MISSING TRANSLATION>
+
 # a different parameter with name {0} already exists
 DUPLICATED_PARAMETER_NAME = <MISSING TRANSLATION>
diff --git a/src/test/java/org/orekit/rugged/api/RuggedTest.java b/src/test/java/org/orekit/rugged/api/RuggedTest.java
index f882dd9c..c91bd666 100644
--- a/src/test/java/org/orekit/rugged/api/RuggedTest.java
+++ b/src/test/java/org/orekit/rugged/api/RuggedTest.java
@@ -26,6 +26,7 @@ import java.net.URISyntaxException;
 import java.nio.MappedByteBuffer;
 import java.nio.channels.FileChannel;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 import java.util.Locale;
@@ -1229,6 +1230,62 @@ public class RuggedTest {
         }
     }
 
+    @Test
+    public void testNoParametersSelected()
+        throws OrekitException {
+        try {
+            Rugged perfect = createParameterEstimationContext(2000, false, false).build();
+            perfect.estimateFreeParameters(Collections.singletonList(new SensorToGroundMapping("line")),
+                                           100, 1.0e-3);
+            Assert.fail("an exception should have been thrown");
+        } catch (RuggedException re) {
+            Assert.assertEquals(RuggedMessages.NO_PARAMETERS_SELECTED, re.getSpecifier());
+        }
+    }
+
+    @Test
+    public void testDuplicatedParameter()
+        throws OrekitException {
+        try {
+            TimeDependentLOS los =
+                            TestUtils.createLOSPerfectLine(Vector3D.PLUS_K, Vector3D.PLUS_I, 0.1, 1000).
+                            addTransform(new FixedRotation("pitch", Vector3D.MINUS_J, 0.0)).build();
+            LineDatation lineDatation = new LinearLineDatation(AbsoluteDate.J2000_EPOCH, 50, 1.0 / 1.5e-3);
+            Rugged perfect = createParameterEstimationContext(2000, false, false).
+                             addLineSensor(new LineSensor("other", lineDatation, Vector3D.ZERO, los)).
+                             build();
+            // the duplicated parameter is "pitch", it will be detected even despite only "roll" is estimated
+            perfect.getLineSensor("line").
+                    getParametersDrivers().
+                    filter(driver -> driver.getName().equals("roll")).
+                    forEach(driver -> driver.setSelected(true));
+            perfect.estimateFreeParameters(Arrays.asList(new SensorToGroundMapping("line"),
+                                                         new SensorToGroundMapping("other")),
+                                           100, 1.0e-3);
+            Assert.fail("an exception should have been thrown");
+        } catch (RuggedException re) {
+            Assert.assertEquals(RuggedMessages.DUPLICATED_PARAMETER_NAME, re.getSpecifier());
+            Assert.assertEquals("pitch", re.getParts()[0]);
+        }
+    }
+
+    @Test
+    public void testNoReferenceMapping()
+        throws OrekitException {
+        try {
+            Rugged perfect = createParameterEstimationContext(2000, false, false).build();
+            perfect.getLineSensor("line").
+                    getParametersDrivers().
+                    filter(driver -> driver.getName().equals("roll") || driver.getName().equals("pitch")).
+                    forEach(driver -> driver.setSelected(true));
+            perfect.estimateFreeParameters(Collections.singletonList(new SensorToGroundMapping("line")),
+                                           100, 1.0e-3);
+            Assert.fail("an exception should have been thrown");
+        } catch (RuggedException re) {
+            Assert.assertEquals(RuggedMessages.NO_REFERENCE_MAPPINGS, re.getSpecifier());
+        }
+    }
+
     @Test
     public void testViewingModelParametersEstimationWithoutCorrections()
         throws OrekitException, RuggedException {
@@ -1277,7 +1334,7 @@ public class RuggedTest {
             // set up a perfect Rugged instance, with prescribed roll and pitch values
             Rugged perfect = createParameterEstimationContext(dimension,
                                                               lightTimeCorrection,
-                                                              aberrationOfLightCorrection);
+                                                              aberrationOfLightCorrection).build();
             perfect.
                 getLineSensor("line").
                 getParametersDrivers().
@@ -1306,7 +1363,7 @@ public class RuggedTest {
             // with 0.0 roll and pitch values and estimating rool and pitch
             Rugged normal = createParameterEstimationContext(dimension,
                                                              lightTimeCorrection,
-                                                             aberrationOfLightCorrection);
+                                                             aberrationOfLightCorrection).build();
             normal.
                 getLineSensor("line").
                 getParametersDrivers().
@@ -1344,9 +1401,9 @@ public class RuggedTest {
         }
     }
 
-    private Rugged createParameterEstimationContext(int dimension,
-                                                    boolean lightTimeCorrection,
-                                                    boolean aberrationOfLightCorrection)
+    private RuggedBuilder createParameterEstimationContext(int dimension,
+                                                           boolean lightTimeCorrection,
+                                                           boolean aberrationOfLightCorrection)
         throws OrekitException, RuggedException {
         
         try {
@@ -1396,8 +1453,7 @@ public class RuggedTest {
                                           2, AngularDerivativesFilter.USE_R).
                             setLightTimeCorrection(lightTimeCorrection).
                             setAberrationOfLightCorrection(aberrationOfLightCorrection).
-                            addLineSensor(lineSensor).
-                            build();
+                            addLineSensor(lineSensor);
 
         } catch (URISyntaxException e) {
             Assert.fail(e.getLocalizedMessage());
diff --git a/src/test/java/org/orekit/rugged/errors/RuggedMessagesTest.java b/src/test/java/org/orekit/rugged/errors/RuggedMessagesTest.java
index 62e411c5..0dd7a081 100644
--- a/src/test/java/org/orekit/rugged/errors/RuggedMessagesTest.java
+++ b/src/test/java/org/orekit/rugged/errors/RuggedMessagesTest.java
@@ -30,7 +30,7 @@ public class RuggedMessagesTest {
 
     @Test
     public void testMessageNumber() {
-        Assert.assertEquals(26, RuggedMessages.values().length);
+        Assert.assertEquals(28, RuggedMessages.values().length);
     }
 
     @Test
-- 
GitLab