From f938334f638808560c2fb10274ccc366a75ef39a Mon Sep 17 00:00:00 2001 From: Jonathan Guinet <jonathan.guinet@c-s.fr> Date: Fri, 17 Feb 2017 13:10:07 -0500 Subject: [PATCH] add adjustment package --- .../rugged/adjustment/AdjustmentContext.java | 172 +++++++------ .../GroundOptimizationProblemBuilder.java | 197 +++++++++++++++ .../adjustment/LeastSquareAdjuster.java | 58 ++++- .../OptimizationProblemBuilder.java | 226 +++++++++++++++--- 4 files changed, 546 insertions(+), 107 deletions(-) create mode 100644 src/main/java/org/orekit/rugged/adjustment/GroundOptimizationProblemBuilder.java diff --git a/src/main/java/org/orekit/rugged/adjustment/AdjustmentContext.java b/src/main/java/org/orekit/rugged/adjustment/AdjustmentContext.java index 6e0fbe43..74b6d088 100644 --- a/src/main/java/org/orekit/rugged/adjustment/AdjustmentContext.java +++ b/src/main/java/org/orekit/rugged/adjustment/AdjustmentContext.java @@ -16,29 +16,23 @@ */ package org.orekit.rugged.adjustment; -import org.orekit.rugged.refining.measures.Observables; -import org.orekit.rugged.api.Rugged; -import org.orekit.rugged.errors.RuggedException; - -import org.hipparchus.optim.ConvergenceChecker; -import org.hipparchus.optim.nonlinear.vector.leastsquares.GaussNewtonOptimizer; -import org.hipparchus.optim.nonlinear.vector.leastsquares.LevenbergMarquardtOptimizer; -import org.hipparchus.optim.nonlinear.vector.leastsquares.LeastSquaresBuilder; -import org.hipparchus.optim.nonlinear.vector.leastsquares.LeastSquaresProblem; -import org.hipparchus.optim.nonlinear.vector.leastsquares.LeastSquaresOptimizer; -import org.hipparchus.optim.nonlinear.vector.leastsquares.LeastSquaresOptimizer.Optimum; -import org.hipparchus.optim.nonlinear.vector.leastsquares.MultivariateJacobianFunction; -import org.hipparchus.optim.nonlinear.vector.leastsquares.ParameterValidator; -import org.orekit.rugged.adjustment.OptimizerId; - -import org.hipparchus.linear.DiagonalMatrix; -import org.hipparchus.optim.ConvergenceChecker; - +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import org.hipparchus.optim.nonlinear.vector.leastsquares.LeastSquaresOptimizer.Optimum; +import org.orekit.errors.OrekitException; +import org.orekit.errors.OrekitExceptionWrapper; +import org.orekit.rugged.api.Rugged; +import org.orekit.rugged.errors.RuggedException; +import org.orekit.rugged.errors.RuggedExceptionWrapper; +import org.orekit.rugged.errors.RuggedMessages; +import org.orekit.rugged.linesensor.LineSensor; +import org.orekit.rugged.refining.measures.Observables; +import org.orekit.utils.ParameterDriver; + /** * Create adjustment context for viewing model refining refining * @@ -53,6 +47,10 @@ public class AdjustmentContext { /** set of measures. */ private final Observables measures; + /** least square optimizer choice.*/ + private OptimizerId optimizerID; + + /** Build a new instance. * @param viewingModel viewingModel * @param measures control and tie points @@ -64,62 +62,102 @@ public class AdjustmentContext { this.viewingModel.put("Rugged", r); } this.measures = measures; + this.optimizerID = OptimizerId.GAUSS_NEWTON_QR; } - - public Optimum estimateFreeParameters(String RuggedName) { - Optimum optimum; - return optimum; - } - - public Optimum estimateFreeParameters2Viewing(String RuggedNameA, String RuggedNameB) { - Optimum optimum; - return optimum; - } - - /** Create the LeastSquareProblem. - * @param maxEvaluations maximum iterations and evaluations in optimization problem - * @param weight Measures weight matrix - * @param start - * @param target - * @param validator - * @param checker - * @param model - * @return the least square problem + + /** setter for optimizer algorithm. + * @param optimizerId the algorithm */ - public LeastSquaresProblem LeastSquaresProblemBuilder(final int maxEvaluations, final double[] weight, - final double[] start, final double[] target, - final ParameterValidator validator, - final ConvergenceChecker<LeastSquaresProblem.Evaluation> checker, - final MultivariateJacobianFunction model) { - final LeastSquaresProblem problem = new LeastSquaresBuilder() - .lazyEvaluation(false).maxIterations(maxEvaluations) - .maxEvaluations(maxEvaluations).weight(new DiagonalMatrix(weight)).start(start) - .target(target).parameterValidator(validator).checker(checker) - .model(model).build(); - return problem; + public void setOptimizer(final OptimizerId optimizerId) + { + this.optimizerID = optimizerId; } - /** Create the optimizer. - * @param optimizerID reference optimizer identifier - * @return optimizer + /** + * Estimate the free parameters in viewing model to match specified sensor + * to ground mappings. + * <p> + * This method is typically used for calibration of on-board sensor + * parameters, like rotation angles polynomial coefficients. + * </p> + * <p> + * Before using this method, the {@link ParameterDriver viewing model + * parameters} retrieved by calling the + * {@link 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 their current value must have their + * {@link ParameterDriver#setSelected(boolean) selection status} set to + * {@link false}. If needed, the {@link ParameterDriver#setValue(double) + * value} of the estimated/selected parameters can also be changed before + * calling the method, as this value will serve as the initial value in the + * estimation process. + * </p> + * <p> + * The method solves a least-squares problem to minimize the residuals + * between test locations and the reference mappings by adjusting the + * selected viewing models parameters. + * </p> + * <p> + * The estimated parameters can be retrieved after the method completes by + * calling 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 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 should ultimately be reached by adjusting selected + * viewing models parameters + * @param maxEvaluations maximum number of evaluations + * @param parametersConvergenceThreshold convergence threshold on normalized + * parameters (dimensionless, related to parameters scales) + * @return optimum of the least squares problem + * @exception RuggedException if several parameters with the same name + * exist, if no parameters have been selected for estimation, or + * if parameters cannot be estimated (too few measurements, + * ill-conditioned problem ...) */ - private LeastSquaresOptimizer selectOptimizer(final OptimizerId optimizerID) { - // set up the optimizer - switch (optimizerID) { - case LEVENBERG_MARQUADT: - return new LevenbergMarquardtOptimizer(); - case GAUSS_NEWTON_LU : - return new GaussNewtonOptimizer() - .withDecomposition(GaussNewtonOptimizer.Decomposition.LU); - case GAUSS_NEWTON_QR : - return new GaussNewtonOptimizer() - .withDecomposition(GaussNewtonOptimizer.Decomposition.QR); - default : - // this should never happen - throw RuggedException.createInternalError(null); - } + public Optimum estimateFreeParameters(final String RuggedName, final int maxEvaluations, final double parametersConvergenceThreshold) + throws RuggedException { + try { + + final Rugged rugged = this.viewingModel.get(RuggedName); + if (rugged == null) { + throw new RuggedException(RuggedMessages.INVALID_RUGGED_NAME); + } + + + final String sensorName = measures.getGroundMapping().getSensorName(); + + final List<LineSensor> selectedSensors = new ArrayList<>(); + //TODO loop over all sensors + //for (final SensorToGroundMapping reference : references) { + selectedSensors.add(rugged.getLineSensor(sensorName)); + //} + /** builder */ + final GroundOptimizationProblemBuilder optimizationProblem = new GroundOptimizationProblemBuilder(selectedSensors, measures, rugged); + + + final LeastSquareAdjuster adjuster = new LeastSquareAdjuster(this.optimizerID); + + return adjuster.optimize(optimizationProblem.build(maxEvaluations, parametersConvergenceThreshold)); + + + } catch (RuggedExceptionWrapper rew) { + throw rew.getException(); + } catch (OrekitExceptionWrapper oew) { + final OrekitException oe = oew.getException(); + throw new RuggedException(oe, oe.getSpecifier(), oe.getParts()); + } } + /*public Optimum estimateFreeParameters(final String RuggedNameA, final String RuggedNameB, final int maxEvaluations, final float parametersConvergenceThreshold)*/ + } diff --git a/src/main/java/org/orekit/rugged/adjustment/GroundOptimizationProblemBuilder.java b/src/main/java/org/orekit/rugged/adjustment/GroundOptimizationProblemBuilder.java new file mode 100644 index 00000000..54371084 --- /dev/null +++ b/src/main/java/org/orekit/rugged/adjustment/GroundOptimizationProblemBuilder.java @@ -0,0 +1,197 @@ +package org.orekit.rugged.adjustment; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.hipparchus.analysis.differentiation.DerivativeStructure; +import org.hipparchus.linear.Array2DRowRealMatrix; +import org.hipparchus.linear.ArrayRealVector; +import org.hipparchus.linear.RealMatrix; +import org.hipparchus.linear.RealVector; +import org.hipparchus.optim.ConvergenceChecker; +import org.hipparchus.optim.nonlinear.vector.leastsquares.LeastSquaresBuilder; +import org.hipparchus.optim.nonlinear.vector.leastsquares.LeastSquaresProblem; +import org.hipparchus.optim.nonlinear.vector.leastsquares.MultivariateJacobianFunction; +import org.hipparchus.optim.nonlinear.vector.leastsquares.ParameterValidator; +import org.hipparchus.util.FastMath; +import org.hipparchus.util.Pair; +import org.orekit.bodies.GeodeticPoint; +import org.orekit.errors.OrekitException; +import org.orekit.errors.OrekitExceptionWrapper; +import org.orekit.rugged.api.Rugged; +import org.orekit.rugged.errors.RuggedException; +import org.orekit.rugged.errors.RuggedExceptionWrapper; +import org.orekit.rugged.errors.RuggedMessages; +import org.orekit.rugged.linesensor.LineSensor; +import org.orekit.rugged.linesensor.SensorPixel; +import org.orekit.rugged.refining.measures.Observables; +import org.orekit.rugged.refining.measures.SensorToGroundMapping; +import org.orekit.utils.ParameterDriver; + + + +public class GroundOptimizationProblemBuilder +extends OptimizationProblemBuilder { + + /** rugged instance to refine.*/ + private final Rugged rugged; + + /** sensorToGround mapping to generate target tab for optimization.*/ + private final SensorToGroundMapping sensorToGroundMapping; + + /** minimum line for inverse location estimation.*/ + private int minLine; + + /** maximum line for inverse location estimation.*/ + private int maxLine; + + private HashMap<String, double[] > targetAndWeight; + + /** + * @param sensors list of sensors to refine + * @param measures set of observables + * @param rugged name of rugged to refine + * @throws RuggedException an exception is generated if no parameters has been selected for refining + */ + public GroundOptimizationProblemBuilder(final List<LineSensor> sensors, + final Observables measures, final Rugged rugged) + throws RuggedException { + super(sensors, measures); + this.rugged = rugged; + this.sensorToGroundMapping = this.measures.getGroundMapping(); + } + + + @Override + protected void createTargetAndWeight() + throws RuggedException { + try { + final int n = this.sensorToGroundMapping.getMapping().size(); + if (n == 0) { + throw new RuggedException(RuggedMessages.NO_REFERENCE_MAPPINGS); + } + final double[] target = new double[2 * n]; + final double[] weight = new double[2 * n]; + + double min = Double.POSITIVE_INFINITY; + double max = Double.NEGATIVE_INFINITY; + int k = 0; + + for (final Map.Entry<SensorPixel, GeodeticPoint> mapping : this.sensorToGroundMapping.getMapping()) { + final SensorPixel sp = mapping.getKey(); + weight[k] = 1.0; + target[k++] = sp.getLineNumber(); + weight[k] = 1.0; + target[k++] = sp.getPixelNumber(); + min = FastMath.min(min, sp.getLineNumber()); + max = FastMath.max(max, sp.getLineNumber()); + } + + this.minLine = (int) FastMath + .floor(min - ESTIMATION_LINE_RANGE_MARGIN); + this.maxLine = (int) FastMath + .ceil(max - ESTIMATION_LINE_RANGE_MARGIN); + this.targetAndWeight = new HashMap<String, double[]>(); + this.targetAndWeight.put("Target", target); + this.targetAndWeight.put("Weight", weight); + + } catch (RuggedExceptionWrapper rew) { + throw rew.getException(); + } + } + + @Override + protected MultivariateJacobianFunction createFunction() + { + // model function + final MultivariateJacobianFunction model = point -> { + try { + + // set the current parameters values + int i = 0; + for (final ParameterDriver driver : this.drivers.getDrivers()) { + driver.setNormalizedValue(point.getEntry(i++)); + } + + final double[] target = this.targetAndWeight.get("Target"); + + // compute inverse loc and its partial derivatives + final RealVector value = new ArrayRealVector(target.length); + final RealMatrix jacobian = new Array2DRowRealMatrix(target.length, this.nbParams); + int l = 0; + for (final Map.Entry<SensorPixel, GeodeticPoint> mapping : this.sensorToGroundMapping.getMapping()) { + final GeodeticPoint gp = mapping.getValue(); + final DerivativeStructure[] ilResult = this.rugged.inverseLocationDerivatives(this.sensorToGroundMapping.getSensorName(), gp, minLine, maxLine, generator); + + if (ilResult == null) { + value.setEntry(l, minLine - 100.0); // arbitrary + // line far + // away + value.setEntry(l + 1, -100.0); // arbitrary + // pixel far away + } else { + // extract the value + value.setEntry(l, ilResult[0].getValue()); + value.setEntry(l + 1, ilResult[1].getValue()); + + // extract the Jacobian + final int[] orders = new int[this.nbParams]; + int m = 0; + for (final ParameterDriver driver : this.drivers.getDrivers()) { + final double scale = driver.getScale(); + orders[m] = 1; + jacobian.setEntry(l, m, + ilResult[0] + .getPartialDerivative(orders) * + scale); + jacobian.setEntry(l + 1, m, + ilResult[1] + .getPartialDerivative(orders) * + scale); + orders[m] = 0; + m++; + } + } + + l += 2; + + } + + + // inverse loc result with Jacobian for all reference points + return new Pair<RealVector, RealMatrix>(value, jacobian); + + } catch (RuggedException re) { + throw new RuggedExceptionWrapper(re); + } catch (OrekitException oe) { + throw new OrekitExceptionWrapper(oe); + } + }; + return model; + } + + + /** leastsquare problem builder. + * @param maxEvaluations maxIterations and evaluations + * @param convergenceThreshold parameter convergence treshold + * @throws RuggedException if sensor is not found + * @return + */ + @Override + public final LeastSquaresProblem build(final int maxEvaluations, final double convergenceThreshold) throws RuggedException { + + this.createTargetAndWeight(); + final double[] target = this.targetAndWeight.get("Target"); + final double[] start = this.createStartTab(); + final ParameterValidator validator = this.createParameterValidator(); + final ConvergenceChecker<LeastSquaresProblem.Evaluation> checker = this.createChecker(convergenceThreshold); + final MultivariateJacobianFunction model = this.createFunction(); + return new LeastSquaresBuilder() + .lazyEvaluation(false).maxIterations(maxEvaluations) + .maxEvaluations(maxEvaluations).weight(null).start(start) + .target(target).parameterValidator(validator).checker(checker) + .model(model).build(); + } + +} diff --git a/src/main/java/org/orekit/rugged/adjustment/LeastSquareAdjuster.java b/src/main/java/org/orekit/rugged/adjustment/LeastSquareAdjuster.java index 8a344468..10b31a04 100644 --- a/src/main/java/org/orekit/rugged/adjustment/LeastSquareAdjuster.java +++ b/src/main/java/org/orekit/rugged/adjustment/LeastSquareAdjuster.java @@ -17,8 +17,64 @@ package org.orekit.rugged.adjustment; - +import org.hipparchus.optim.nonlinear.vector.leastsquares.GaussNewtonOptimizer; +import org.hipparchus.optim.nonlinear.vector.leastsquares.LeastSquaresOptimizer; +import org.hipparchus.optim.nonlinear.vector.leastsquares.LeastSquaresOptimizer.Optimum; +import org.hipparchus.optim.nonlinear.vector.leastsquares.LeastSquaresProblem; +import org.hipparchus.optim.nonlinear.vector.leastsquares.LevenbergMarquardtOptimizer; +import org.orekit.rugged.errors.RuggedException; public class LeastSquareAdjuster { + /** least square optimzaer.*/ + private final LeastSquaresOptimizer adjuster; + + /** least square optimizer choice.*/ + private final OptimizerId optimizerID; + + /** constructor. + * @param optimizerID optimizer choice + */ + LeastSquareAdjuster(final OptimizerId optimizerID) + { + this.optimizerID = optimizerID; + this.adjuster = this.selectOptimizer(); + } + + /** default constructor assuming Gauss Newton QR algorithm.*/ + LeastSquareAdjuster() + { + this.optimizerID = OptimizerId.GAUSS_NEWTON_QR; + this.adjuster = this.selectOptimizer(); + } + + /** solve the least square problem. + * @param problem the least square problem + * @return the solution + */ + public Optimum optimize(final LeastSquaresProblem problem) { + return this.adjuster.optimize(problem); + } + + /** Create the optimizer. + * @return optimizer + */ + private LeastSquaresOptimizer selectOptimizer() { + // set up the optimizer + switch (this.optimizerID) { + case LEVENBERG_MARQUADT: + return new LevenbergMarquardtOptimizer(); + case GAUSS_NEWTON_LU : + return new GaussNewtonOptimizer() + .withDecomposition(GaussNewtonOptimizer.Decomposition.LU); + case GAUSS_NEWTON_QR : + return new GaussNewtonOptimizer() + .withDecomposition(GaussNewtonOptimizer.Decomposition.QR); + default : + // this should never happen + throw RuggedException.createInternalError(null); + } + + } + } diff --git a/src/main/java/org/orekit/rugged/adjustment/OptimizationProblemBuilder.java b/src/main/java/org/orekit/rugged/adjustment/OptimizationProblemBuilder.java index 7dc0b50c..a1cfa78d 100644 --- a/src/main/java/org/orekit/rugged/adjustment/OptimizationProblemBuilder.java +++ b/src/main/java/org/orekit/rugged/adjustment/OptimizationProblemBuilder.java @@ -1,58 +1,138 @@ /** - * + * */ package org.orekit.rugged.adjustment; - -import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; import java.util.Set; -import org.orekit.rugged.refining.measures.SensorToGroundMapping; -import org.orekit.rugged.refining.measures.SensorToSensorMapping; - -import org.hipparchus.optim.nonlinear.vector.leastsquares.LeastSquaresProblem; -import java.lang.Object; -import org.orekit.utils.ParameterDriver; -import org.orekit.utils.ParameterDriversList; +import org.hipparchus.analysis.differentiation.DerivativeStructure; import org.hipparchus.optim.ConvergenceChecker; +import org.hipparchus.optim.nonlinear.vector.leastsquares.LeastSquaresProblem; +import org.hipparchus.optim.nonlinear.vector.leastsquares.MultivariateJacobianFunction; import org.hipparchus.optim.nonlinear.vector.leastsquares.ParameterValidator; - import org.orekit.errors.OrekitException; import org.orekit.errors.OrekitExceptionWrapper; +import org.orekit.rugged.errors.RuggedException; +import org.orekit.rugged.errors.RuggedExceptionWrapper; +import org.orekit.rugged.errors.RuggedMessages; +import org.orekit.rugged.linesensor.LineSensor; +import org.orekit.rugged.refining.measures.Observables; +import org.orekit.rugged.utils.DSGenerator; +import org.orekit.utils.ParameterDriver; +import org.orekit.utils.ParameterDriversList; -/** Builder for optimization problem +/** + * Builder for optimization problem * <p> -* </p> + * </p> + * * @author Jonathan Guinet */ -public class OptimizationProblemBuilder { - - final ParameterDriversList drivers; +abstract class OptimizationProblemBuilder { + + /** + * Margin used in parameters estimation for the inverse location lines + * range. + */ + protected static final int ESTIMATION_LINE_RANGE_MARGIN = 100; + + /** + * + */ + final DSGenerator generator; + + /** + * + */ + protected final ParameterDriversList drivers; + + /** number of params to refine. */ + protected final int nbParams; - public OptimizationProblemBuilder(final ParameterDriversList drivers) { - this.drivers = drivers; - + + /** measures .*/ + protected Observables measures; + + + /** OptimizationProblemBuilder constructor + * @param sensors + * @param measures + * @throws RuggedException + */ + OptimizationProblemBuilder(final List<LineSensor> sensors, + Observables measures) + throws RuggedException { + try { + this.generator = this.createGenerator(sensors); + this.drivers = this.generator.getSelected(); + this.nbParams = this.drivers.getNbParams(); + if (this.nbParams == 0) { + throw new RuggedException(RuggedMessages.NO_PARAMETERS_SELECTED); + } + } catch (RuggedExceptionWrapper rew) { + throw rew.getException(); + } + + this.measures = measures; + } + + /** nbParams getter. + * @return returns the number of variable parameters + */ + public final int getNbParams() + { + return this.getNbParams(); + } + + /** + * parameters drivers list getter. + * + * @return selected parameters driver list + */ + public final ParameterDriversList getSelectedParametersDriver() { + return this.drivers; } - /** Create the convergence check + + + /** leastsquare problem builder. + * @param maxEvaluations maxIterations and evaluations + * @param convergenceThreshold parameter convergence threshold + * @throws RuggedException if sensor is not found + * @return the problem + */ + + public abstract LeastSquaresProblem build(final int maxEvaluations, final float convergenceThreshold) throws RuggedException; + + + /** + * Create the convergence check. * <p> - * check Linf distance of parameters variation between previous and current iteration + * check Linf distance of parameters variation between previous and current + * iteration * </p> + * * @param parametersConvergenceThreshold convergence threshold * @return the checker */ final ConvergenceChecker<LeastSquaresProblem.Evaluation> - createChecker(final float parametersConvergenceThreshold) { + createChecker(final float parametersConvergenceThreshold) { final ConvergenceChecker<LeastSquaresProblem.Evaluation> checker = (iteration, - previous, - current) -> current - .getPoint() - .getLInfDistance(previous - .getPoint()) <= parametersConvergenceThreshold; - return checker; + previous, + current) -> current + .getPoint() + .getLInfDistance(previous + .getPoint()) <= parametersConvergenceThreshold; + return checker; } - /** create start point for optimization algorithm. + /** + * create start point for optimization algorithm. + * * @return start parameters values */ final double[] createStartTab() { @@ -66,16 +146,16 @@ public class OptimizationProblemBuilder { } - final Set<double[]> createTargetAndWeight(SensorToSensorMapping references) { - return Set<>; - } - - final Set<double[]> createTargetAndWeight(SensorToGroundMapping references) { - return Set<>; - } - - - /** create parameter validator. + protected abstract void createTargetAndWeight() throws RuggedException; + + + protected abstract MultivariateJacobianFunction createFunction(); + + + + /** + * create parameter validator. + * * @return parameter validator */ final ParameterValidator createParameterValidator() { @@ -95,4 +175,72 @@ public class OptimizationProblemBuilder { }; return validator; } + + /** + * Create the generator for {@link DerivativeStructure} instances. + * + * @param selectedSensors sensors referencing the parameters drivers + * @return a new generator + */ + private DSGenerator + createGenerator(final List<LineSensor> selectedSensors) { + + final Set<String> names = new HashSet<>(); + for (final LineSensor sensor : selectedSensors) { + sensor.getParametersDrivers().forEach(driver -> { + if (names.contains(driver.getName()) == false) { + names.add(driver.getName()); + } + }); + } + + // set up generator list and map + final ParameterDriversList selected = new ParameterDriversList(); + final Map<String, Integer> map = new HashMap<>(); + for (final LineSensor sensor : selectedSensors) { + sensor.getParametersDrivers().filter(driver -> driver.isSelected()) + .forEach(driver -> { + if (map.get(driver.getName()) == null) { + map.put(driver.getName(), map.size()); + } + + try { + selected.add(driver); + } catch (OrekitException e) { + e.printStackTrace(); + } + + }); + } + + return new DSGenerator() { + + /** {@inheritDoc} */ + @Override + public ParameterDriversList getSelected() { + return selected; + } + + /** {@inheritDoc} */ + @Override + public DerivativeStructure constant(final double value) { + return new DerivativeStructure(map.size(), 1, value); + } + + /** {@inheritDoc} */ + @Override + public DerivativeStructure variable(final ParameterDriver driver) { + final Integer index = map.get(driver.getName()); + if (index == null) { + return constant(driver.getValue()); + } else { + return new DerivativeStructure(map.size(), 1, + index.intValue(), + driver.getValue()); + } + } + + }; + } + } -- GitLab