Commit 8c032d89 authored by Luc Maisonobe's avatar Luc Maisonobe

Allow either Levenberg-Marquardt or Gauss-Newton for OD.

parent 34b502c0
......@@ -36,8 +36,10 @@ import java.util.TreeSet;
import org.hipparchus.exception.LocalizedCoreFormats;
import org.hipparchus.geometry.euclidean.threed.Vector3D;
import org.hipparchus.optim.nonlinear.vector.leastsquares.GaussNewtonOptimizer;
import org.hipparchus.optim.nonlinear.vector.leastsquares.LeastSquaresOptimizer;
import org.hipparchus.optim.nonlinear.vector.leastsquares.LevenbergMarquardtOptimizer;
import org.hipparchus.optim.nonlinear.vector.leastsquares.GaussNewtonOptimizer.Decomposition;
import org.hipparchus.stat.descriptive.StreamingStatistics;
import org.hipparchus.util.FastMath;
import org.hipparchus.util.Precision;
......@@ -133,7 +135,7 @@ public class OrbitDeterminationTest {
final double velocityAccuracy = 1e-4;
//test on the convergence
final int numberOfIte = 3;
final int numberOfIte = 4;
final int numberOfEval = 4;
Assert.assertEquals(numberOfIte, odLageos2.getNumberOfIteration());
......@@ -1101,12 +1103,30 @@ public class OrbitDeterminationTest {
private BatchLSEstimator createEstimator(final KeyValueFileParser<ParameterKey> parser,
final NumericalPropagatorBuilder propagatorBuilder)
throws NoSuchElementException, OrekitException {
final double initialStepBoundFactor;
if (! parser.containsKey(ParameterKey.ESTIMATOR_LEVENBERG_MARQUARDT_INITIAL_STEP_BOUND_FACTOR)) {
initialStepBoundFactor = 100.0;
final boolean optimizerIsLevenbergMarquardt;
if (! parser.containsKey(ParameterKey.ESTIMATOR_OPTIMIZATION_ENGINE)) {
optimizerIsLevenbergMarquardt = true;
} else {
final String engine = parser.getString(ParameterKey.ESTIMATOR_OPTIMIZATION_ENGINE);
optimizerIsLevenbergMarquardt = engine.toLowerCase().contains("levenberg");
}
final LeastSquaresOptimizer optimizer;
if (optimizerIsLevenbergMarquardt) {
// we want to use a Levenberg-Marquardt optimization engine
final double initialStepBoundFactor;
if (! parser.containsKey(ParameterKey.ESTIMATOR_LEVENBERG_MARQUARDT_INITIAL_STEP_BOUND_FACTOR)) {
initialStepBoundFactor = 100.0;
} else {
initialStepBoundFactor = parser.getDouble(ParameterKey.ESTIMATOR_LEVENBERG_MARQUARDT_INITIAL_STEP_BOUND_FACTOR);
}
optimizer = new LevenbergMarquardtOptimizer().withInitialStepBoundFactor(initialStepBoundFactor);
} else {
initialStepBoundFactor = parser.getDouble(ParameterKey.ESTIMATOR_LEVENBERG_MARQUARDT_INITIAL_STEP_BOUND_FACTOR);
// we want to use a Gauss-Newton optimization engine
optimizer = new GaussNewtonOptimizer(Decomposition.QR);
}
final double convergenceThreshold;
if (! parser.containsKey(ParameterKey.ESTIMATOR_NORMALIZED_PARAMETERS_CONVERGENCE_THRESHOLD)) {
convergenceThreshold = 1.0e-3;
......@@ -1126,9 +1146,7 @@ public class OrbitDeterminationTest {
maxEvaluations = parser.getInt(ParameterKey.ESTIMATOR_MAX_EVALUATIONS);
}
final LeastSquaresOptimizer optimizer = new LevenbergMarquardtOptimizer().withInitialStepBoundFactor(initialStepBoundFactor);
final BatchLSEstimator estimator = new BatchLSEstimator(propagatorBuilder,
optimizer);
final BatchLSEstimator estimator = new BatchLSEstimator(propagatorBuilder, optimizer);
estimator.setParametersConvergenceThreshold(convergenceThreshold);
estimator.setMaxIterations(maxIterations);
estimator.setMaxEvaluations(maxEvaluations);
......@@ -1852,6 +1870,7 @@ public class OrbitDeterminationTest {
PV_OUTLIER_REJECTION_STARTING_ITERATION,
MEASUREMENTS_FILES,
OUTPUT_BASE_NAME,
ESTIMATOR_OPTIMIZATION_ENGINE,
ESTIMATOR_LEVENBERG_MARQUARDT_INITIAL_STEP_BOUND_FACTOR,
ESTIMATOR_ORBITAL_PARAMETERS_POSITION_SCALE,
ESTIMATOR_NORMALIZED_PARAMETERS_CONVERGENCE_THRESHOLD,
......
......@@ -252,6 +252,10 @@ PV.measurements.velocity.sigma = 0.01
# if not specified, the value set for propagator.position.error will be copied
estimator.orbital.parameters.position.scale = 10.0
# we can use either a Levenberg-Marquardt or a Gauss-Newton
# optimization engine. Default is Levenberg-Marquardt
estimator.optimization.engine = Gauss-Newton
# the default initial step bound factor is 100 for Levenberg-Marquardt
# this is too small for normalized parameters when initial guess is very
# far. An order of magnitude is 100 times the distance error of the initial guess
......
......@@ -318,6 +318,10 @@ estimator.orbital.parameters.position.scale = 10.0
# the initial step bound factor should be of the order of magnitude of 1.0e6
estimator.Levenberg.Marquardt.initial.step.bound.factor = 1.0e6
# we can use either a Levenberg-Marquardt or a Gauss-Newton
# optimization engine. Default is Levenberg-Marquardt
estimator.optimization.engine = Levenberg-Marquardt
# convergence is reached when max|p(k+1) - p(k)| < ε for each
# normalized estimated parameters p and iterations k and k+1
# so the ε threshold (which corresponds to the key
......
......@@ -39,9 +39,11 @@ import java.util.TreeSet;
import org.hipparchus.exception.LocalizedCoreFormats;
import org.hipparchus.geometry.euclidean.threed.Vector3D;
import org.hipparchus.optim.nonlinear.vector.leastsquares.GaussNewtonOptimizer;
import org.hipparchus.optim.nonlinear.vector.leastsquares.LeastSquaresOptimizer;
import org.hipparchus.optim.nonlinear.vector.leastsquares.LeastSquaresProblem;
import org.hipparchus.optim.nonlinear.vector.leastsquares.LevenbergMarquardtOptimizer;
import org.hipparchus.optim.nonlinear.vector.leastsquares.GaussNewtonOptimizer.Decomposition;
import org.hipparchus.stat.descriptive.StreamingStatistics;
import org.hipparchus.util.FastMath;
import org.hipparchus.util.Precision;
......@@ -1080,12 +1082,31 @@ public class OrbitDetermination {
private BatchLSEstimator createEstimator(final KeyValueFileParser<ParameterKey> parser,
final NumericalPropagatorBuilder propagatorBuilder)
throws NoSuchElementException, OrekitException {
final double initialStepBoundFactor;
if (! parser.containsKey(ParameterKey.ESTIMATOR_LEVENBERG_MARQUARDT_INITIAL_STEP_BOUND_FACTOR)) {
initialStepBoundFactor = 100.0;
final boolean optimizerIsLevenbergMarquardt;
if (! parser.containsKey(ParameterKey.ESTIMATOR_OPTIMIZATION_ENGINE)) {
optimizerIsLevenbergMarquardt = true;
} else {
final String engine = parser.getString(ParameterKey.ESTIMATOR_OPTIMIZATION_ENGINE);
optimizerIsLevenbergMarquardt = engine.toLowerCase().contains("levenberg");
}
final LeastSquaresOptimizer optimizer;
if (optimizerIsLevenbergMarquardt) {
// we want to use a Levenberg-Marquardt optimization engine
final double initialStepBoundFactor;
if (! parser.containsKey(ParameterKey.ESTIMATOR_LEVENBERG_MARQUARDT_INITIAL_STEP_BOUND_FACTOR)) {
initialStepBoundFactor = 100.0;
} else {
initialStepBoundFactor = parser.getDouble(ParameterKey.ESTIMATOR_LEVENBERG_MARQUARDT_INITIAL_STEP_BOUND_FACTOR);
}
optimizer = new LevenbergMarquardtOptimizer().withInitialStepBoundFactor(initialStepBoundFactor);
} else {
initialStepBoundFactor = parser.getDouble(ParameterKey.ESTIMATOR_LEVENBERG_MARQUARDT_INITIAL_STEP_BOUND_FACTOR);
// we want to use a Gauss-Newton optimization engine
optimizer = new GaussNewtonOptimizer(Decomposition.QR);
}
final double convergenceThreshold;
if (! parser.containsKey(ParameterKey.ESTIMATOR_NORMALIZED_PARAMETERS_CONVERGENCE_THRESHOLD)) {
convergenceThreshold = 1.0e-3;
......@@ -1105,10 +1126,7 @@ public class OrbitDetermination {
maxEvaluations = parser.getInt(ParameterKey.ESTIMATOR_MAX_EVALUATIONS);
}
final LeastSquaresOptimizer optimizer = new LevenbergMarquardtOptimizer().
withInitialStepBoundFactor(initialStepBoundFactor);
final BatchLSEstimator estimator = new BatchLSEstimator(propagatorBuilder,
optimizer);
final BatchLSEstimator estimator = new BatchLSEstimator(propagatorBuilder, optimizer);
estimator.setParametersConvergenceThreshold(convergenceThreshold);
estimator.setMaxIterations(maxIterations);
estimator.setMaxEvaluations(maxEvaluations);
......@@ -2069,6 +2087,7 @@ public class OrbitDetermination {
PV_OUTLIER_REJECTION_STARTING_ITERATION,
MEASUREMENTS_FILES,
OUTPUT_BASE_NAME,
ESTIMATOR_OPTIMIZATION_ENGINE,
ESTIMATOR_LEVENBERG_MARQUARDT_INITIAL_STEP_BOUND_FACTOR,
ESTIMATOR_ORBITAL_PARAMETERS_POSITION_SCALE,
ESTIMATOR_NORMALIZED_PARAMETERS_CONVERGENCE_THRESHOLD,
......
......@@ -310,6 +310,10 @@ PV.measurements.velocity.sigma = 0.01
# if not specified, the value set for propagator.position.error will be copied
estimator.orbital.parameters.position.scale = 10.0
# we can use either a Levenberg-Marquardt or a Gauss-Newton
# optimization engine. Default is Levenberg-Marquardt
estimator.optimization.engine = Levenberg-Marquardt
# the default initial step bound factor is 100 for Levenberg-Marquardt
# this is too small for normalized parameters when initial guess is very
# far. An order of magnitude is 100 times the distance error of the initial guess
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment