diff --git a/src/main/java/org/orekit/rugged/adjustment/AdjustmentContext.java b/src/main/java/org/orekit/rugged/adjustment/AdjustmentContext.java index 10deaa25f966206a2b363982d448e1419057d3b4..3ab99a86d555f60c9b03b6a182903556a26d399f 100644 --- a/src/main/java/org/orekit/rugged/adjustment/AdjustmentContext.java +++ b/src/main/java/org/orekit/rugged/adjustment/AdjustmentContext.java @@ -18,11 +18,13 @@ package org.orekit.rugged.adjustment; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import org.hipparchus.optim.nonlinear.vector.leastsquares.LeastSquaresOptimizer.Optimum; +import org.hipparchus.optim.nonlinear.vector.leastsquares.LeastSquaresProblem; import org.orekit.errors.OrekitException; import org.orekit.errors.OrekitExceptionWrapper; import org.orekit.rugged.api.Rugged; @@ -55,7 +57,7 @@ public class AdjustmentContext { * @param viewingModel viewingModel * @param measures control and tie points */ - public AdjustmentContext(final List<Rugged> viewingModel, final Observables measures) { + public AdjustmentContext(final Collection<Rugged> viewingModel, final Observables measures) { this.viewingModel = new HashMap<String, Rugged>(); for (final Rugged r : viewingModel) { this.viewingModel.put(r.getName(), r); @@ -110,9 +112,6 @@ public class AdjustmentContext { * 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) @@ -122,24 +121,40 @@ public class AdjustmentContext { * if parameters cannot be estimated (too few measurements, * ill-conditioned problem ...) */ - public Optimum estimateFreeParameters(final String ruggedName, final int maxEvaluations, final double parametersConvergenceThreshold) + public Optimum estimateFreeParameters(final Collection<String> ruggedNameList, 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 List<LineSensor> selectedSensors = new ArrayList<LineSensor>(rugged.getLineSensors()); + List<Rugged> ruggedList = new ArrayList<Rugged>(); + List<LineSensor> selectedSensors = new ArrayList<LineSensor>(); + for (String ruggedName : ruggedNameList){ + final Rugged rugged = this.viewingModel.get(ruggedName); + if (rugged == null) { + throw new RuggedException(RuggedMessages.INVALID_RUGGED_NAME); + } - /** builder */ - final GroundOptimizationProblemBuilder optimizationProblem = new GroundOptimizationProblemBuilder(selectedSensors, measures, rugged); + ruggedList.add(rugged); + selectedSensors.addAll(rugged.getLineSensors()); + } final LeastSquareAdjuster adjuster = new LeastSquareAdjuster(this.optimizerID); + LeastSquaresProblem theProblem = null; + /** builder */ + switch (ruggedList.size()) { + case 1: + final Rugged rugged = ruggedList.get(0); + final GroundOptimizationProblemBuilder groundOptimizationProblem = new GroundOptimizationProblemBuilder(selectedSensors, measures, rugged); + theProblem = groundOptimizationProblem.build(maxEvaluations, parametersConvergenceThreshold); + break; + case 2: + final InterSensorsOptimizationProblemBuilder interSensorsOptimizationProblem = new InterSensorsOptimizationProblemBuilder(selectedSensors, measures, ruggedList); + theProblem = interSensorsOptimizationProblem.build(maxEvaluations, parametersConvergenceThreshold); + break; + default : + throw new RuggedException(RuggedMessages.UNSUPPORTED_REFINING_CONTEXT,ruggedList.size()); + } - return adjuster.optimize(optimizationProblem.build(maxEvaluations, parametersConvergenceThreshold)); - + return adjuster.optimize(theProblem); } catch (RuggedExceptionWrapper rew) { throw rew.getException(); @@ -149,6 +164,4 @@ public class AdjustmentContext { } } - /*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 index a116bd55fde70383b28d536726c423a955eaca69..4b5d763c44a14fff978553ee920b759656b0c4cc 100644 --- a/src/main/java/org/orekit/rugged/adjustment/GroundOptimizationProblemBuilder.java +++ b/src/main/java/org/orekit/rugged/adjustment/GroundOptimizationProblemBuilder.java @@ -47,6 +47,7 @@ extends OptimizationProblemBuilder { /** maximum line for inverse location estimation.*/ private int maxLine; + /** target and weight (the solution of the optimization problem) */ private HashMap<String, double[] > targetAndWeight; /** @@ -60,14 +61,25 @@ extends OptimizationProblemBuilder { throws RuggedException { super(sensors, measures); this.rugged = rugged; + this.initMapping(); + } + + /* (non-Javadoc) + * @see org.orekit.rugged.adjustment.OptimizationProblemBuilder#initMapping() + */ + @Override + protected void initMapping() + { + final String ruggedName = rugged.getName(); this.sensorToGroundMappings = new ArrayList<SensorToGroundMapping>(); - for (Map.Entry<String, SensorToGroundMapping> entry : this.measures.getGroundMappings()) { - this.sensorToGroundMappings.add(entry.getValue()); + for (final LineSensor lineSensor : sensors) + { + final SensorToGroundMapping mapping = this.measures.getGroundMapping(ruggedName, lineSensor.getName()); + if(mapping != null) + this.sensorToGroundMappings.add(mapping); } - } - @Override protected void createTargetAndWeight() throws RuggedException { diff --git a/src/main/java/org/orekit/rugged/adjustment/InterSensorsOptimizationProblemBuilder.java b/src/main/java/org/orekit/rugged/adjustment/InterSensorsOptimizationProblemBuilder.java new file mode 100644 index 0000000000000000000000000000000000000000..bff043b05a3cf53441585020a4ff578e9e37891a --- /dev/null +++ b/src/main/java/org/orekit/rugged/adjustment/InterSensorsOptimizationProblemBuilder.java @@ -0,0 +1,273 @@ +package org.orekit.rugged.adjustment; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +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.Pair; +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.SensorToSensorMapping; +import org.orekit.rugged.utils.SpacecraftToObservedBody; +import org.orekit.time.AbsoluteDate; +import org.orekit.utils.ParameterDriver; + + + +public class InterSensorsOptimizationProblemBuilder +extends OptimizationProblemBuilder { + + /** list of rugged instance to refine.*/ + private Map<String, Rugged> ruggedMap; + + /** sensorToGround mapping to generate target tab for optimization.*/ + private List<SensorToSensorMapping> sensorToSensorMappings; + + + 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 InterSensorsOptimizationProblemBuilder(final List<LineSensor> sensors, + final Observables measures, final Collection<Rugged> ruggedList) + throws RuggedException { + super(sensors, measures); + + this.ruggedMap = new LinkedHashMap<String, Rugged>(); + + for(final Rugged rugged : ruggedList) + { + this.ruggedMap.put(rugged.getName(),rugged); + } + this.initMapping(); + } + + /* (non-Javadoc) + * @see org.orekit.rugged.adjustment.OptimizationProblemBuilder#initMapping() + */ + @Override + protected void initMapping() + { + this.sensorToSensorMappings = new ArrayList<SensorToSensorMapping>(); + for (final String ruggedNameA : this.ruggedMap.keySet()){ + for (final String ruggedNameB : this.ruggedMap.keySet()){ + for (final LineSensor sensorA : this.sensors){ + for (final LineSensor sensorB : this.sensors){ + final String sensorNameA = sensorA.getName(); + final String sensorNameB = sensorB.getName(); + final SensorToSensorMapping mapping = this.measures.getInterMapping(ruggedNameA, sensorNameA, ruggedNameB, sensorNameB); + if (mapping != null) + { + + this.sensorToSensorMappings.add(mapping); + } + } + } + + } + + } + + } + + @Override + protected void createTargetAndWeight() + throws RuggedException { + try { + int n = 0; + for (final SensorToSensorMapping reference : this.sensorToSensorMappings) { + n += reference.getMapping().size(); + } + + if (n == 0) { + throw new RuggedException(RuggedMessages.NO_REFERENCE_MAPPINGS); + } + + n = 2*n ; + + final double[] target = new double[n]; + final double[] weight = new double[n]; + + int k = 0; + + for (final SensorToSensorMapping reference : this.sensorToSensorMappings) { + + // Get Earth constraint weight + final double earthConstraintWeight = reference.getEarthConstraintWeight(); + int i=0; + for (Iterator<Map.Entry<SensorPixel, SensorPixel>> gtIt = reference.getMapping().iterator();gtIt.hasNext();i++){ + if(i==reference.getMapping().size()) break; + + // Get LOS distance + Double losDistance = reference.getLosDistance(i); + + weight[k] = 1.0 - earthConstraintWeight; + target[k++] = losDistance.doubleValue(); + + // Get Earth distance (constraint) + Double earthDistance = reference.getEarthDistance(i); + weight[k] = earthConstraintWeight; + target[k++] = earthDistance.doubleValue(); + } + } + + 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 distance 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 SensorToSensorMapping reference : this.sensorToSensorMappings) { + + + final String ruggedNameA = reference.getRuggedNameA(); + final String ruggedNameB = reference.getRuggedNameB(); + final Rugged ruggedA = this.ruggedMap.get(ruggedNameA); + + if (ruggedA == null) { + throw new RuggedException(RuggedMessages.INVALID_RUGGED_NAME); + } + final Rugged ruggedB = this.ruggedMap.get(ruggedNameB); + if (ruggedB == null) { + throw new RuggedException(RuggedMessages.INVALID_RUGGED_NAME); + } + + + for (final Map.Entry<SensorPixel, SensorPixel> mapping : reference.getMapping()) { + + final SensorPixel spA = mapping.getKey(); + final SensorPixel spB = mapping.getValue(); + + LineSensor lineSensorB = ruggedB.getLineSensor(reference.getSensorNameB()); + LineSensor lineSensorA = ruggedA.getLineSensor(reference.getSensorNameA()); + + final AbsoluteDate dateA = lineSensorA.getDate(spA.getLineNumber()); + final AbsoluteDate dateB = lineSensorB.getDate(spB.getLineNumber()); + + final double pixelA = spA.getPixelNumber(); + final double pixelB = spB.getPixelNumber(); + + final SpacecraftToObservedBody scToBodyA = ruggedA.getScToBody(); + + final DerivativeStructure[] ilResult = ruggedB.distanceBetweenLOSDerivatives(lineSensorA, + dateA, + pixelA, + scToBodyA, + lineSensorB, + dateB, + pixelB, + generator); + + if (ilResult == null) { + // TODO + } 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; // pass to the next evaluation + } + } + + // distance 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 threshold + * @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/OptimizationProblemBuilder.java b/src/main/java/org/orekit/rugged/adjustment/OptimizationProblemBuilder.java index bab37effaf84ce5c5d123e43d747d0d11ccc2ae7..7669c75d6e08965ff1fa2baf4d0311dc746df349 100644 --- a/src/main/java/org/orekit/rugged/adjustment/OptimizationProblemBuilder.java +++ b/src/main/java/org/orekit/rugged/adjustment/OptimizationProblemBuilder.java @@ -57,6 +57,7 @@ abstract class OptimizationProblemBuilder { /** measures .*/ protected Observables measures; + protected final List<LineSensor> sensors; /** OptimizationProblemBuilder constructor * @param sensors @@ -78,6 +79,7 @@ abstract class OptimizationProblemBuilder { } this.measures = measures; + this.sensors = sensors; } /** nbParams getter. @@ -151,7 +153,8 @@ abstract class OptimizationProblemBuilder { protected abstract MultivariateJacobianFunction createFunction(); - + /** parse the observables to select mapping .*/ + protected abstract void initMapping(); /** * create parameter validator. diff --git a/src/main/java/org/orekit/rugged/api/Rugged.java b/src/main/java/org/orekit/rugged/api/Rugged.java index df4fa50609b609e693b46ea937eaa96f44b075aa..019451c7cf80e38c1d55f7a2c4ee6a76e5bb545d 100644 --- a/src/main/java/org/orekit/rugged/api/Rugged.java +++ b/src/main/java/org/orekit/rugged/api/Rugged.java @@ -849,7 +849,7 @@ public class Rugged { * @see #distanceBetweenLOS(String, AbsoluteDate, int, String, AbsoluteDate, * int) */ - private DerivativeStructure[] + public DerivativeStructure[] distanceBetweenLOSDerivatives(final LineSensor sensorA, final AbsoluteDate dateA, final double pixelA, diff --git a/src/main/java/org/orekit/rugged/errors/RuggedMessages.java b/src/main/java/org/orekit/rugged/errors/RuggedMessages.java index e4687f4f3bf678febaab670069148e14aa1628ae..10bf1b9aad57f17e8874c83df6ef4449e8e53030 100644 --- a/src/main/java/org/orekit/rugged/errors/RuggedMessages.java +++ b/src/main/java/org/orekit/rugged/errors/RuggedMessages.java @@ -80,7 +80,8 @@ public enum RuggedMessages implements Localizable { 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"), - INVALID_RUGGED_NAME("invalid rugged name."); + INVALID_RUGGED_NAME("invalid rugged name."), + UNSUPPORTED_REFINING_CONTEXT("refining using {0} rugged instance is not handled."); // CHECKSTYLE: resume JavadocVariable check diff --git a/src/main/java/org/orekit/rugged/refining/generators/GroundMeasureGenerator.java b/src/main/java/org/orekit/rugged/refining/generators/GroundMeasureGenerator.java index a673df2dc1a4d9ffa72aca8c329836d7a802f017..deef2691be994de1bdfcb33c48664a5fa33ae58e 100644 --- a/src/main/java/org/orekit/rugged/refining/generators/GroundMeasureGenerator.java +++ b/src/main/java/org/orekit/rugged/refining/generators/GroundMeasureGenerator.java @@ -16,23 +16,22 @@ */ package org.orekit.rugged.refining.generators; +import org.hipparchus.geometry.euclidean.threed.Vector3D; +import org.hipparchus.random.GaussianRandomGenerator; +import org.hipparchus.random.UncorrelatedRandomVectorGenerator; +import org.hipparchus.random.Well19937a; +import org.hipparchus.util.FastMath; import org.orekit.bodies.GeodeticPoint; import org.orekit.rugged.api.Rugged; import org.orekit.rugged.errors.RuggedException; import org.orekit.rugged.linesensor.LineSensor; import org.orekit.rugged.linesensor.SensorPixel; import org.orekit.rugged.refining.measures.Noise; +import org.orekit.rugged.refining.measures.Observables; import org.orekit.rugged.refining.measures.SensorToGroundMapping; import org.orekit.rugged.refining.metrics.DistanceTools; - import org.orekit.time.AbsoluteDate; -import org.hipparchus.geometry.euclidean.threed.Vector3D; -import org.hipparchus.random.UncorrelatedRandomVectorGenerator; -import org.hipparchus.random.GaussianRandomGenerator; -import org.hipparchus.random.Well19937a; -import org.hipparchus.util.FastMath; - /** Ground measures generator (sensor to ground mapping). @@ -45,14 +44,17 @@ public class GroundMeasureGenerator implements Measurable { /** mapping */ private SensorToGroundMapping groundMapping; + /** observables which contains ground mapping.*/ + private Observables observables; + private Rugged rugged; - + private LineSensor sensor; private int measureCount; - + private int dimension; - + /** Simple constructor. * <p> * @@ -60,112 +62,129 @@ public class GroundMeasureGenerator implements Measurable { */ public GroundMeasureGenerator(final Rugged rugged, final String sensorName, final int dimension) throws RuggedException { - - // generate reference mapping - groundMapping = new SensorToGroundMapping(sensorName); - this.rugged = rugged; - sensor = rugged.getLineSensor(groundMapping.getSensorName()); - measureCount = 0; - this.dimension = dimension; - + + // generate reference mapping + groundMapping = new SensorToGroundMapping(rugged.getName(), sensorName); + + //create observables for one model + this.observables = new Observables(1); + + this.rugged = rugged; + sensor = rugged.getLineSensor(groundMapping.getSensorName()); + measureCount = 0; + this.dimension = dimension; + } public SensorToGroundMapping getGroundMapping() { - return groundMapping; + return groundMapping; } + + /** getter for observables. + * @return the observables + */ + public Observables getObservables() { + return observables; + } + + @Override public int getMeasureCount() { - return measureCount; - } + return measureCount; + } + @Override public void createMeasure(final int lineSampling,final int pixelSampling) throws RuggedException { for (double line = 0; line < dimension; line += lineSampling) { - final AbsoluteDate date = sensor.getDate(line); - for (int pixel = 0; pixel < sensor.getNbPixels(); pixel += pixelSampling) { + final AbsoluteDate date = sensor.getDate(line); + for (int pixel = 0; pixel < sensor.getNbPixels(); pixel += pixelSampling) { - final GeodeticPoint gp2 = rugged.directLocation(date, sensor.getPosition(), - sensor.getLOS(date, pixel)); + final GeodeticPoint gp2 = rugged.directLocation(date, sensor.getPosition(), + sensor.getLOS(date, pixel)); - groundMapping.addMapping(new SensorPixel(line, pixel), gp2); - measureCount++; - } + groundMapping.addMapping(new SensorPixel(line, pixel), gp2); + measureCount++; + } } + this.observables.addGroundMapping(groundMapping); } + @Override public void createNoisyMeasure(final int lineSampling,final int pixelSampling, final Noise noise) throws RuggedException { /* Estimate latitude and longitude errors estimation */ - final Vector3D latLongError = estimateLatLongError(); - - /* Get noise features */ - final double[] mean = noise.getMean(); /* [latitude, longitude, altitude] mean */ - final double[] std = noise.getStandardDeviation(); /* [latitude, longitude, altitude] standard deviation */ - - final double latErrorMean = mean[0] * latLongError.getX(); // in line: -0.000002 deg - final double lonErrorMean = mean[1] * latLongError.getY(); // in line: 0.000012 deg - final double latErrorStd = std[0] * latLongError.getX(); // in line: -0.000002 deg - final double lonErrorStd = std[1] * latLongError.getY(); // in line: 0.000012 deg - - // Gaussian random generator - // Build a null mean random uncorrelated vector generator with standard deviation corresponding to the estimated error on ground - final double meanGenerator[] = {latErrorMean, lonErrorMean, mean[2]}; - final double stdGenerator[] = {latErrorStd, lonErrorStd, std[2]}; - System.out.format("Corresponding error estimation on ground {Latitude, Longitude, Altitude}:%n"); + final Vector3D latLongError = estimateLatLongError(); + + /* Get noise features */ + final double[] mean = noise.getMean(); /* [latitude, longitude, altitude] mean */ + final double[] std = noise.getStandardDeviation(); /* [latitude, longitude, altitude] standard deviation */ + + final double latErrorMean = mean[0] * latLongError.getX(); // in line: -0.000002 deg + final double lonErrorMean = mean[1] * latLongError.getY(); // in line: 0.000012 deg + final double latErrorStd = std[0] * latLongError.getX(); // in line: -0.000002 deg + final double lonErrorStd = std[1] * latLongError.getY(); // in line: 0.000012 deg + + // Gaussian random generator + // Build a null mean random uncorrelated vector generator with standard deviation corresponding to the estimated error on ground + final double meanGenerator[] = {latErrorMean, lonErrorMean, mean[2]}; + final double stdGenerator[] = {latErrorStd, lonErrorStd, std[2]}; + System.out.format("Corresponding error estimation on ground {Latitude, Longitude, Altitude}:%n"); System.out.format("\tMean: {%1.10f rad, %1.10f rad, %1.10f m} %n", meanGenerator[0], meanGenerator[1], meanGenerator[2]); System.out.format("\tStd : {%1.10f rad, %1.10f rad, %1.10f m} %n", stdGenerator[0], stdGenerator[1], stdGenerator[2]); - final GaussianRandomGenerator rng = new GaussianRandomGenerator(new Well19937a(0xefac03d9be4d24b9l)); - final UncorrelatedRandomVectorGenerator rvg = new UncorrelatedRandomVectorGenerator(meanGenerator, stdGenerator, rng); - - System.out.format("Add a gaussian noise to measures without biais (null mean) and standard deviation%n corresponding to the estimated error on ground.%n"); - for (double line = 0; line < dimension; line += lineSampling) { - - final AbsoluteDate date = sensor.getDate(line); - for (int pixel = 0; pixel < sensor.getNbPixels(); pixel += pixelSampling) { - - // Components of generated vector follow (independent) Gaussian distribution - final Vector3D vecRandom = new Vector3D(rvg.nextVector()); - - final GeodeticPoint gp2 = rugged.directLocation(date, sensor.getPosition(), - sensor.getLOS(date, pixel)); - - - final GeodeticPoint gpNoisy = new GeodeticPoint(gp2.getLatitude()+vecRandom.getX(), - gp2.getLongitude()+vecRandom.getY(), - gp2.getAltitude()+vecRandom.getZ()); - - //if(line == 0) { - // System.out.format("Init gp: (%f,%d): %s %n",line,pixel,gp2.toString()); - // System.out.format("Random: (%f,%d): %s %n",line,pixel,vecRandom.toString()); - // System.out.format("Final gp: (%f,%d): %s %n",line,pixel,gpNoisy.toString()); - //} - - groundMapping.addMapping(new SensorPixel(line, pixel), gpNoisy); - measureCount++; - } + final GaussianRandomGenerator rng = new GaussianRandomGenerator(new Well19937a(0xefac03d9be4d24b9l)); + final UncorrelatedRandomVectorGenerator rvg = new UncorrelatedRandomVectorGenerator(meanGenerator, stdGenerator, rng); + + System.out.format("Add a gaussian noise to measures without biais (null mean) and standard deviation%n corresponding to the estimated error on ground.%n"); + for (double line = 0; line < dimension; line += lineSampling) { + + final AbsoluteDate date = sensor.getDate(line); + for (int pixel = 0; pixel < sensor.getNbPixels(); pixel += pixelSampling) { + + // Components of generated vector follow (independent) Gaussian distribution + final Vector3D vecRandom = new Vector3D(rvg.nextVector()); + + final GeodeticPoint gp2 = rugged.directLocation(date, sensor.getPosition(), + sensor.getLOS(date, pixel)); + + + final GeodeticPoint gpNoisy = new GeodeticPoint(gp2.getLatitude()+vecRandom.getX(), + gp2.getLongitude()+vecRandom.getY(), + gp2.getAltitude()+vecRandom.getZ()); + + //if(line == 0) { + // System.out.format("Init gp: (%f,%d): %s %n",line,pixel,gp2.toString()); + // System.out.format("Random: (%f,%d): %s %n",line,pixel,vecRandom.toString()); + // System.out.format("Final gp: (%f,%d): %s %n",line,pixel,gpNoisy.toString()); + //} + + groundMapping.addMapping(new SensorPixel(line, pixel), gpNoisy); + measureCount++; + } } + this.observables.addGroundMapping(groundMapping); } private Vector3D estimateLatLongError() throws RuggedException { - - System.out.format("Uncertainty in pixel (in line) for a real geometric refining: 1 pixel (assumption)%n"); - final int pix =sensor.getNbPixels()/2; - final int line= (int) FastMath.floor(pix); // assumption : same number of line and pixels; - System.out.format("Pixel size estimated at position pix: %d line: %d %n", pix, line); - final AbsoluteDate date = sensor.getDate(line); - final GeodeticPoint gp_pix0 = rugged.directLocation(date, sensor.getPosition(), sensor.getLOS(date, pix)); - final AbsoluteDate date1 = sensor.getDate(line+1); - final GeodeticPoint gp_pix1 = rugged.directLocation(date1, sensor.getPosition(), sensor.getLOS(date1, pix+1)); - final double latErr = FastMath.abs(gp_pix0.getLatitude() - gp_pix1.getLatitude()); - final double lonErr = FastMath.abs(gp_pix0.getLongitude() - gp_pix1.getLongitude()); - //double dist = FastMath.sqrt(lonErr*lonErr + latErr*latErr)/FastMath.sqrt(2); - final double distanceX = DistanceTools.computeDistanceInMeter(gp_pix0.getLongitude(), gp_pix0.getLatitude(),gp_pix1.getLongitude(), gp_pix0.getLatitude()); - final double distanceY = DistanceTools.computeDistanceInMeter(gp_pix0.getLongitude(), gp_pix0.getLatitude(),gp_pix0.getLongitude(), gp_pix1.getLatitude()); - - System.out.format("Estimated distance: X %3.3f Y %3.3f %n",distanceX, distanceY); - - //System.out.format(" lat : %1.10f %1.10f %n", latErr, lonErr); - return new Vector3D(latErr, lonErr, 0.0); + + System.out.format("Uncertainty in pixel (in line) for a real geometric refining: 1 pixel (assumption)%n"); + final int pix =sensor.getNbPixels()/2; + final int line= (int) FastMath.floor(pix); // assumption : same number of line and pixels; + System.out.format("Pixel size estimated at position pix: %d line: %d %n", pix, line); + final AbsoluteDate date = sensor.getDate(line); + final GeodeticPoint gp_pix0 = rugged.directLocation(date, sensor.getPosition(), sensor.getLOS(date, pix)); + final AbsoluteDate date1 = sensor.getDate(line+1); + final GeodeticPoint gp_pix1 = rugged.directLocation(date1, sensor.getPosition(), sensor.getLOS(date1, pix+1)); + final double latErr = FastMath.abs(gp_pix0.getLatitude() - gp_pix1.getLatitude()); + final double lonErr = FastMath.abs(gp_pix0.getLongitude() - gp_pix1.getLongitude()); + //double dist = FastMath.sqrt(lonErr*lonErr + latErr*latErr)/FastMath.sqrt(2); + final double distanceX = DistanceTools.computeDistanceInMeter(gp_pix0.getLongitude(), gp_pix0.getLatitude(),gp_pix1.getLongitude(), gp_pix0.getLatitude()); + final double distanceY = DistanceTools.computeDistanceInMeter(gp_pix0.getLongitude(), gp_pix0.getLatitude(),gp_pix0.getLongitude(), gp_pix1.getLatitude()); + + System.out.format("Estimated distance: X %3.3f Y %3.3f %n",distanceX, distanceY); + + //System.out.format(" lat : %1.10f %1.10f %n", latErr, lonErr); + return new Vector3D(latErr, lonErr, 0.0); } } diff --git a/src/main/java/org/orekit/rugged/refining/generators/InterMeasureGenerator.java b/src/main/java/org/orekit/rugged/refining/generators/InterMeasureGenerator.java index f366c5eb88e61d8d1085307666079dc5e14fb2cd..f6ee7b8c88c3a26dca17843498607615bd99b984 100644 --- a/src/main/java/org/orekit/rugged/refining/generators/InterMeasureGenerator.java +++ b/src/main/java/org/orekit/rugged/refining/generators/InterMeasureGenerator.java @@ -13,6 +13,9 @@ */ package org.orekit.rugged.refining.generators; +import org.hipparchus.random.GaussianRandomGenerator; +import org.hipparchus.random.UncorrelatedRandomVectorGenerator; +import org.hipparchus.random.Well19937a; import org.orekit.bodies.GeodeticPoint; import org.orekit.rugged.api.Rugged; import org.orekit.rugged.errors.RuggedException; @@ -21,16 +24,12 @@ import org.orekit.rugged.errors.RuggedMessages; import org.orekit.rugged.linesensor.LineSensor; import org.orekit.rugged.linesensor.SensorPixel; import org.orekit.rugged.refining.measures.Noise; +import org.orekit.rugged.refining.measures.Observables; import org.orekit.rugged.refining.measures.SensorToSensorMapping; import org.orekit.rugged.refining.metrics.DistanceTools; import org.orekit.rugged.utils.SpacecraftToObservedBody; - import org.orekit.time.AbsoluteDate; -import org.hipparchus.random.UncorrelatedRandomVectorGenerator; -import org.hipparchus.random.GaussianRandomGenerator; -import org.hipparchus.random.Well19937a; - /** * Inter-measures generator (sensor to sensor mapping). * @author Jonathan Guinet @@ -41,6 +40,9 @@ public class InterMeasureGenerator implements Measurable { /** mapping. */ private SensorToSensorMapping interMapping; + /** observables which contains sensor to sensor mapping.*/ + private Observables observables; + private Rugged ruggedA; private Rugged ruggedB; @@ -54,15 +56,15 @@ public class InterMeasureGenerator implements Measurable { private String sensorNameA; private String sensorNameB; - + private int dimensionA; - + private int dimensionB; - + private double outlier=0.0; - - /** Default constructor: measures generation without outlier points control + + /** Default constructor: measures generation without outlier points control * and without Earth distance constraint. * @param viewingModelA * @param ruggedA @@ -70,9 +72,9 @@ public class InterMeasureGenerator implements Measurable { * @param ruggedB * @throws RuggedException */ - public InterMeasureGenerator(Rugged ruggedA, String sensorNameA, int dimensionA, + public InterMeasureGenerator(Rugged ruggedA, String sensorNameA, int dimensionA, Rugged ruggedB, String sensorNameB, int dimensionB) - throws RuggedException { + throws RuggedException { // Initialize parameters this.initParams(ruggedA, sensorNameA, dimensionA, ruggedB, sensorNameB, dimensionB); @@ -80,11 +82,13 @@ public class InterMeasureGenerator implements Measurable { // generate reference mapping, without Earth distance constraint interMapping = new SensorToSensorMapping(sensorNameA, sensorNameB); + //create observables for two models + this.observables = new Observables(2); } - - + + /** Constructor for measures generation taking into account outlier points control, - * without Earth distance constraint. + * without Earth distance constraint. * @param viewingModelA viewing model A * @param ruggedA Rugged instance corresponding to the viewing model A * @param viewingModelB viewing model B @@ -92,143 +96,154 @@ public class InterMeasureGenerator implements Measurable { * @param outlier limit value of outlier points * @throws RuggedException */ - public InterMeasureGenerator(Rugged ruggedA, String sensorNameA, int dimensionA, + public InterMeasureGenerator(Rugged ruggedA, String sensorNameA, int dimensionA, Rugged ruggedB, String sensorNameB, int dimensionB, double outlier) - throws RuggedException { + throws RuggedException { this(ruggedA, sensorNameA, dimensionA, ruggedB, sensorNameB, dimensionB); this.outlier = outlier; } - + /** Constructor for measures generation taking into account outlier points control, - * and Earth distance constraint. + * and Earth distance constraint. * @param viewingModelA viewing model A * @param ruggedA Rugged instance corresponding to the viewing model A * @param viewingModelB viewing model B * @param ruggedB Rugged instance corresponding to the viewing model B * @param outlier limit value of outlier points - * @param earthConstraintWeight weight given to the Earth distance constraint + * @param earthConstraintWeight weight given to the Earth distance constraint * with respect to the LOS distance (between 0 and 1). * @throws RuggedException * @see Rugged#estimateFreeParams2Models */ - public InterMeasureGenerator(Rugged ruggedA, String sensorNameA, int dimensionA, - Rugged ruggedB, String sensorNameB, int dimensionB, + public InterMeasureGenerator(Rugged ruggedA, String sensorNameA, int dimensionA, + Rugged ruggedB, String sensorNameB, int dimensionB, double outlier, final double earthConstraintWeight) - throws RuggedException { + throws RuggedException { - // Initialize parameters + // Initialize parameters this.initParams(ruggedA, sensorNameA, dimensionA, ruggedB, sensorNameB, dimensionB); // generate reference mapping, with Earth distance constraints // Weighting will be applied as follow : // (1-earthConstraintWeight) for losDistance weighting // earthConstraintWeight for earthDistance weighting - interMapping = new SensorToSensorMapping(sensorNameA, sensorNameB, earthConstraintWeight); + interMapping = new SensorToSensorMapping(sensorNameA, ruggedA.getName(), sensorNameB, ruggedB.getName(), earthConstraintWeight); // outlier points control this.outlier = outlier; + this.observables = new Observables(2); + } public SensorToSensorMapping getInterMapping() { return interMapping; } + + /** getter for observables. + * @return the observables + */ + public Observables getObservables() { + return observables; + } + + @Override public int getMeasureCount() { return measureCount; } + @Override public void createMeasure(final int lineSampling, final int pixelSampling) throws RuggedException { - // Get outlier - double outlier = this.outlier; - + // Search the sensor pixel seeing point final int minLine = 0; final int maxLine = dimensionB - 1; - + for (double line = 0; line < dimensionA; line += lineSampling) { - AbsoluteDate dateA = sensorA.getDate(line); - + final AbsoluteDate dateA = sensorA.getDate(line); + for (double pixelA = 0; pixelA < sensorA.getNbPixels(); pixelA += pixelSampling) { - GeodeticPoint gpA = ruggedA.directLocation(dateA, sensorA.getPosition(), - sensorA.getLOS(dateA, pixelA)); + final GeodeticPoint gpA = ruggedA.directLocation(dateA, sensorA.getPosition(), + sensorA.getLOS(dateA, pixelA)); - SensorPixel sensorPixelB = ruggedB.inverseLocation(sensorNameB, gpA, minLine, maxLine); + final SensorPixel sensorPixelB = ruggedB.inverseLocation(sensorNameB, gpA, minLine, maxLine); // we need to test if the sensor pixel is found in the // prescribed lines otherwise the sensor pixel is null if (sensorPixelB != null) { final AbsoluteDate dateB = sensorB.getDate(sensorPixelB.getLineNumber()); - double pixelB = sensorPixelB.getPixelNumber(); + final double pixelB = sensorPixelB.getPixelNumber(); final SpacecraftToObservedBody scToBodyA = ruggedA.getScToBody(); - - GeodeticPoint gpB = ruggedB.directLocation(dateB, sensorB.getPosition(), - sensorB.getLOS(dateB, pixelB)); - - double GEOdistance = DistanceTools.computeDistanceInMeter(gpA.getLongitude(), gpA.getLatitude(), - gpB.getLongitude(), gpB.getLatitude()); - if(GEOdistance < outlier) + final GeodeticPoint gpB = ruggedB.directLocation(dateB, sensorB.getPosition(), + sensorB.getLOS(dateB, pixelB)); + + final double GEOdistance = DistanceTools.computeDistanceInMeter(gpA.getLongitude(), gpA.getLatitude(), + gpB.getLongitude(), gpB.getLatitude()); + + if (GEOdistance < this.outlier) { - /*System.out.format("A line %2.3f pixel %2.3f %n", line, pixelA);*/ - - SensorPixel RealPixelA = new SensorPixel(line, pixelA); - - SensorPixel RealPixelB = new SensorPixel(sensorPixelB.getLineNumber(), - sensorPixelB.getPixelNumber()); - - AbsoluteDate RealDateA = sensorA.getDate(RealPixelA.getLineNumber()); - AbsoluteDate RealDateB = sensorB.getDate(RealPixelB.getLineNumber()); - double[] distanceLOSB = ruggedB.distanceBetweenLOS(sensorA, RealDateA, RealPixelA.getPixelNumber(), scToBodyA, - sensorB, RealDateB, RealPixelB.getPixelNumber()); - - final double losDistance = distanceLOSB[1]; - final double earthDistance = 0.0; - - interMapping.addMapping(RealPixelA, RealPixelB, losDistance, earthDistance); - measureCount++; + /*System.out.format("A line %2.3f pixel %2.3f %n", line, pixelA);*/ + + final SensorPixel RealPixelA = new SensorPixel(line, pixelA); + + final SensorPixel RealPixelB = new SensorPixel(sensorPixelB.getLineNumber(), + sensorPixelB.getPixelNumber()); + + final AbsoluteDate RealDateA = sensorA.getDate(RealPixelA.getLineNumber()); + final AbsoluteDate RealDateB = sensorB.getDate(RealPixelB.getLineNumber()); + final double[] distanceLOSB = ruggedB.distanceBetweenLOS(sensorA, RealDateA, RealPixelA.getPixelNumber(), scToBodyA, + sensorB, RealDateB, RealPixelB.getPixelNumber()); + + + final double losDistance = 0.0; + final double earthDistance = distanceLOSB[1]; + + interMapping.addMapping(RealPixelA, RealPixelB, losDistance, earthDistance); + measureCount++; } else { /*System.out.format("A line %2.3f pixel %2.3f %n rejected ", line, pixelA);*/ } - } + } } } + this.observables.addInterMapping(interMapping); } - /** - * tie point creation from directLocation with RuggedA and inverse location + /** tie point creation from directLocation with RuggedA and inverse location. * with RuggedB * @param lineSampling sampling along lines * @param pixelSampling sampling along columns * @param noise error tabulation * @throws RuggedException */ + @Override public void createNoisyMeasure(final int lineSampling, final int pixelSampling, final Noise noise) - throws RuggedException { - + throws RuggedException { + // Get outlier double outlier = this.outlier; - + /* Get noise features (errors) */ final double[] mean = noise.getMean(); /* [pixelA, pixelB] mean */ final double[] std = noise.getStandardDeviation(); /* [pixelA, pixelB] standard deviation */ - - + // Search the sensor pixel seeing point final int minLine = 0; final int maxLine = dimensionB - 1; - + double meanA[] = {mean[0],mean[0]}; double stdA[] = {std[0],std[0]}; double meanB[] = {mean[1],mean[1]}; - double stdB[] = {std[1],std[1]}; + double stdB[] = {std[1],std[1]}; GaussianRandomGenerator rngA = new GaussianRandomGenerator(new Well19937a(0xefac03d9be4d24b9l)); UncorrelatedRandomVectorGenerator rvgA = new UncorrelatedRandomVectorGenerator(meanA, stdA, rngA); @@ -240,20 +255,20 @@ public class InterMeasureGenerator implements Measurable { AbsoluteDate dateA = sensorA.getDate(line); for (double pixelA = 0; pixelA < sensorA - .getNbPixels(); pixelA += pixelSampling) { + .getNbPixels(); pixelA += pixelSampling) { GeodeticPoint gpA = ruggedA - .directLocation(dateA, sensorA.getPosition(), - sensorA.getLOS(dateA, pixelA)); + .directLocation(dateA, sensorA.getPosition(), + sensorA.getLOS(dateA, pixelA)); SensorPixel sensorPixelB = ruggedB - .inverseLocation(sensorNameB, gpA, minLine, maxLine); + .inverseLocation(sensorNameB, gpA, minLine, maxLine); // we need to test if the sensor pixel is found in the // prescribed lines otherwise the sensor pixel is null if (sensorPixelB != null) { //System.out.format(" %n"); final AbsoluteDate dateB = sensorB - .getDate(sensorPixelB.getLineNumber()); + .getDate(sensorPixelB.getLineNumber()); double pixelB = sensorPixelB.getPixelNumber(); final SpacecraftToObservedBody scToBodyA = ruggedA .getScToBody(); @@ -271,17 +286,17 @@ public class InterMeasureGenerator implements Measurable { double distanceLOSA = ruggedA .distanceBetweenLOS(sensorB, dateB, pixelB, scToBodyB, sensorA, dateA, pixelA);*/ - + //System.out.format("distance LOS %1.8e %1.8e %n",distanceLOSB,distanceLOSA); - - - + + + GeodeticPoint gpB = ruggedB .directLocation(dateB, sensorB.getPosition(), sensorB.getLOS(dateB, pixelB)); - + double GEOdistance = DistanceTools.computeDistanceInMeter(gpA.getLongitude(), gpA.getLatitude(), - gpB.getLongitude(), gpB.getLatitude()); + gpB.getLongitude(), gpB.getLatitude()); if(GEOdistance < outlier) { @@ -295,9 +310,9 @@ public class InterMeasureGenerator implements Measurable { vecRandomA[0], pixelA + vecRandomA[1]); SensorPixel RealPixelB = new SensorPixel(sensorPixelB - .getLineNumber() + vecRandomB[0], sensorPixelB - .getPixelNumber() + vecRandomB[1]); - /*System.out.format("pix A %f %f Real %f %f %n", line, + .getLineNumber() + vecRandomB[0], sensorPixelB + .getPixelNumber() + vecRandomB[1]); + /*System.out.format("pix A %f %f Real %f %f %n", line, pixelA, RealPixelA.getLineNumber(), RealPixelA.getPixelNumber()); System.out.format("pix B %f %f Real %f %f %n", @@ -309,10 +324,10 @@ public class InterMeasureGenerator implements Measurable { AbsoluteDate RealDateB = sensorB.getDate(RealPixelB.getLineNumber()); double[] distanceLOSB = ruggedB .distanceBetweenLOS(sensorA, RealDateA, RealPixelA.getPixelNumber(), scToBodyA, - sensorB, RealDateB, RealPixelB.getPixelNumber()); + sensorB, RealDateB, RealPixelB.getPixelNumber()); final Double losDistance = 0.0; final Double earthDistance = distanceLOSB[1]; - + interMapping.addMapping(RealPixelA, RealPixelB, losDistance, earthDistance); measureCount++; } @@ -321,13 +336,14 @@ public class InterMeasureGenerator implements Measurable { /*System.out.format("A line %2.3f pixel %2.3f %n rejected ", line, pixelA);*/ } - } + } } } + this.observables.addInterMapping(interMapping); } - - /** Default constructor: measures generation without outlier points control + + /** Default constructor: measures generation without outlier points control * and Earth distances constraint. * @param viewingModelA * @param ruggedA @@ -337,14 +353,14 @@ public class InterMeasureGenerator implements Measurable { */ private void initParams(Rugged ruggedA, String sensorNameA, int dimensionA, Rugged ruggedB, String sensorNameB, int dimensionB) throws RuggedException { - + // generate reference mapping this.sensorNameA = sensorNameA; this.sensorNameB = sensorNameB; // check that sensors's name is different if (sensorNameA.contains(sensorNameB)) { throw new RuggedExceptionWrapper(new RuggedException(RuggedMessages.DUPLICATED_PARAMETER_NAME, - sensorNameA)); + sensorNameA)); } this.ruggedA = ruggedA; @@ -352,10 +368,10 @@ public class InterMeasureGenerator implements Measurable { sensorA = ruggedA.getLineSensor(sensorNameA); sensorB = ruggedB.getLineSensor(sensorNameB); - + this.dimensionA = dimensionA; this.dimensionB = dimensionB; - + measureCount = 0; } diff --git a/src/main/java/org/orekit/rugged/refining/measures/Observables.java b/src/main/java/org/orekit/rugged/refining/measures/Observables.java index 79bf1312e21ed5543394d0c92b35ac4c461a7b58..4e2318b405ab7592f3ccec40689193e3053546ea 100644 --- a/src/main/java/org/orekit/rugged/refining/measures/Observables.java +++ b/src/main/java/org/orekit/rugged/refining/measures/Observables.java @@ -16,15 +16,9 @@ */ package org.orekit.rugged.refining.measures; -import java.util.ArrayList; -import java.util.Collections; +import java.util.Collection; import java.util.LinkedHashMap; -import java.util.List; import java.util.Map; -import java.util.Set; - -import org.orekit.rugged.errors.RuggedException; -import org.orekit.rugged.errors.RuggedMessages; /** Class for measures generation. * @author Lucie Labat-Allee @@ -38,7 +32,7 @@ public class Observables { private final Map<String, SensorToGroundMapping> groundMappings; /** Sensor to sensor mappings structure (liaison points). */ - private final List<SensorToSensorMapping> interMappings; + private final Map<String, SensorToSensorMapping> interMappings; /** Number of viewing models to map */ private final int nbModels; @@ -50,7 +44,7 @@ public class Observables { */ public Observables(final int nbModels) { this.groundMappings = new LinkedHashMap<String, SensorToGroundMapping>(); - this.interMappings = new ArrayList<SensorToSensorMapping>(); + this.interMappings = new LinkedHashMap<String, SensorToSensorMapping>(); this.nbModels = nbModels; } @@ -58,22 +52,23 @@ public class Observables { * @param SensorToSensorMapping sensor to sensor mapping */ public void addInterMapping(final SensorToSensorMapping interMapping) { - interMappings.add(interMapping); + final String key = this.createKey(interMapping); + interMappings.put(this.createKey(interMapping),interMapping); } /** Add a ground mapping between * @param SensorToGroundMapping sensor to ground mapping */ public void addGroundMapping(final SensorToGroundMapping groundMapping) { - groundMappings.put(groundMapping.getSensorName(), groundMapping); + groundMappings.put(this.createKey(groundMapping), groundMapping); } /** Get all the ground mapping entries. * @return an unmodifiable view of all mapping entries */ - public Set<Map.Entry<String, SensorToGroundMapping>> getGroundMappings() { - return Collections.unmodifiableSet(groundMappings.entrySet()); + public Collection<SensorToGroundMapping> getGroundMappings() { + return groundMappings.values(); } @@ -81,26 +76,38 @@ public class Observables { * Get a ground Mapping for a sensor. * * @param sensorName sensor name - * @return selected ground mapping - * @exception RuggedException if sensor is not known + * @return selected ground mapping or null of sensorName is not found */ - public SensorToGroundMapping getGroundMapping(final String sensorName) - throws RuggedException { - final SensorToGroundMapping mapping = this.groundMappings.get(sensorName); - if (mapping == null) { - throw new RuggedException(RuggedMessages.UNKNOWN_SENSOR, - sensorName); - } + public SensorToGroundMapping getGroundMapping(final String ruggedName, final String sensorName) { + final SensorToGroundMapping mapping = this.groundMappings.get(ruggedName + "_" + sensorName); return mapping; } /** * @return the interMappings */ - public List<SensorToSensorMapping> getInterMappings() { - return interMappings; + public Collection<SensorToSensorMapping> getInterMappings() { + return interMappings.values(); } + /** + * Get a sensor Mapping for a sensor. + * + * @param ruggedNameA rugged name A + * @param sensorNameA sensor name A + * @param ruggedNameB rugged name B + * @param sensorNameB sensor name B + * @return selected ground mapping or null of sensorName is not found + */ + public SensorToSensorMapping getInterMapping(final String ruggedNameA, final String sensorNameA, final String ruggedNameB, final String sensorNameB) { + + final String keyA = ruggedNameA + "_" + sensorNameA; + final String keyB = ruggedNameB + "_" + sensorNameB; + final SensorToSensorMapping mapping = this.interMappings.get(keyA + "__" + keyB); + return mapping; + } + + /** * @return the nbModels */ @@ -108,4 +115,27 @@ public class Observables { return nbModels; } + + /** create key for GroudMapping map. + * @param groundMapping the groundMapping + * @return the key + */ + private String createKey(final SensorToGroundMapping groundMapping) + { + final String key = groundMapping.getRuggedName() + "_" + groundMapping.getSensorName(); + return key; + } + + /** create key for SensorToSensorMapping map. + * @param groundMapping the groundMapping + * @return the key + */ + private String createKey(final SensorToSensorMapping sensorMapping) + { + final String keyA = sensorMapping.getRuggedNameA() + "_" + sensorMapping.getSensorNameA(); + final String keyB = sensorMapping.getRuggedNameB() + "_" + sensorMapping.getSensorNameB(); + return keyA + "__" + keyB; + } + + } diff --git a/src/main/java/org/orekit/rugged/refining/measures/SensorMapping.java b/src/main/java/org/orekit/rugged/refining/measures/SensorMapping.java index 0784bc5dea03ed002b3cf76460d24dd08a4af288..b6d1d00789066396c6996f93f2dfdc0ae26c31f8 100644 --- a/src/main/java/org/orekit/rugged/refining/measures/SensorMapping.java +++ b/src/main/java/org/orekit/rugged/refining/measures/SensorMapping.java @@ -20,6 +20,7 @@ import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; + import org.orekit.rugged.linesensor.SensorPixel; /** Container for mapping sensor pixels with sensor pixels or ground points. @@ -31,6 +32,10 @@ public class SensorMapping<T> { /** Name of the sensor to which mapping applies. */ private final String sensorName; + /** Name of the rugged to which mapping applies. */ + private final String ruggedName; + + /** Mapping from sensor to other (sensor or ground). */ private final Map<SensorPixel, T> mapping; @@ -39,10 +44,20 @@ public class SensorMapping<T> { * @param sensorName name of the sensor to which mapping applies */ public SensorMapping(final String sensorName) { + this(sensorName, "Rugged"); + } + + /** Build a new instance. + * @param sensorName name of the sensor to which mapping applies + * @param ruggedName name of the rugged to which mapping applies + */ + public SensorMapping(final String sensorName, final String ruggedName) { this.sensorName = sensorName; - this.mapping = new LinkedHashMap<SensorPixel,T>(); + this.ruggedName = ruggedName; + this.mapping = new LinkedHashMap<SensorPixel, T>(); } + /** Get the name of the sensor to which mapping applies. * @return name of the sensor to which mapping applies */ @@ -50,6 +65,14 @@ public class SensorMapping<T> { return sensorName; } + /** Get the name of the rugged to which mapping applies. + * @return name of the rugged to which mapping applies + */ + public String getRuggedName() { + return ruggedName; + } + + /** Add a mapping between a sensor pixel and another point (sensor pixel or ground point). * @param pixel sensor pixel * @param point sensor pixel / ground point corresponding to the sensor pixel diff --git a/src/main/java/org/orekit/rugged/refining/measures/SensorToGroundMapping.java b/src/main/java/org/orekit/rugged/refining/measures/SensorToGroundMapping.java index 2fe172ed66f8222974939afd41cc5346c2b7c9fc..f9410bc84309878376a39bd8aa2003604e07bc3b 100644 --- a/src/main/java/org/orekit/rugged/refining/measures/SensorToGroundMapping.java +++ b/src/main/java/org/orekit/rugged/refining/measures/SensorToGroundMapping.java @@ -38,11 +38,20 @@ public class SensorToGroundMapping { private final SensorMapping<GeodeticPoint> groundMapping; /** Build a new instance. + * @param ruggedName name of the rugged to which mapping applies * @param sensorName name of the sensor to which mapping applies */ - public SensorToGroundMapping(final String sensorName) { + public SensorToGroundMapping(final String ruggedName, final String sensorName) { this.sensorName = sensorName; - this.groundMapping = new SensorMapping<GeodeticPoint>(sensorName); + this.groundMapping = new SensorMapping<GeodeticPoint>(sensorName, ruggedName); + } + + + /** Build a new instance. + * @param sensorName name of the sensor to which mapping applies + */ + public SensorToGroundMapping(final String sensorName) { + this(sensorName, "Rugged"); } /** Get the name of the sensor to which mapping applies. @@ -52,6 +61,13 @@ public class SensorToGroundMapping { return sensorName; } + /** Get the name of the rugged to which mapping applies. + * @return name of the rugged to which mapping applies + */ + public String getRuggedName() { + return this.groundMapping.getRuggedName(); + } + /** Add a mapping between one sensor pixel and one ground point. * @param pixel sensor pixel * @param groundPoint ground point corresponding to the sensor pixel @@ -67,4 +83,7 @@ public class SensorToGroundMapping { return Collections.unmodifiableSet(groundMapping.getMapping()); } + + //public Boolean Match(final String SensorName,final String ) + } diff --git a/src/main/java/org/orekit/rugged/refining/measures/SensorToSensorMapping.java b/src/main/java/org/orekit/rugged/refining/measures/SensorToSensorMapping.java index 37b47a518e6918f47fa3c47c6cfc2df610e3c4ff..22d01216d17a6c817f0b6e8ce88bcfada09a9672 100644 --- a/src/main/java/org/orekit/rugged/refining/measures/SensorToSensorMapping.java +++ b/src/main/java/org/orekit/rugged/refining/measures/SensorToSensorMapping.java @@ -21,12 +21,13 @@ import java.util.List; import java.util.Map; import java.util.Set; +import org.orekit.rugged.api.Rugged; import org.orekit.rugged.linesensor.SensorPixel; -/** Container for mapping sensors pixels of two viewing models. +/** Container for mapping sensors pixels of two viewing models. * Store the distance between both lines of sight computed with @link {@link Rugged#distanceBetweenLOS( * String, org.orekit.time.AbsoluteDate, int, String, org.orekit.time.AbsoluteDate, int)} - * Constraints in relation to Earth distance can be added. + * Constraints in relation to Earth distance can be added. * @author Lucie LabatAllee * @see SensorMapping * @since 2.0 @@ -36,48 +37,68 @@ public class SensorToSensorMapping { /** Name of the sensor B to which mapping applies. */ private final String sensorNameB; + /** Name of the rugged B to which mapping applies. */ + private final String ruggedNameB; + /** Mapping from sensor A to sensor B. */ private final SensorMapping<SensorPixel> interMapping; /** Distance between two LOS */ private final List<Double> losDistances; - + /** Earth distance associated with pixel A */ private final List<Double> earthDistances; - + /** Earth constraint weight */ private double earthConstraintWeight; - - + + /** Build a new instance without Earth constraints * @param sensorNameA name of the sensor A to which mapping applies * @param sensorNameB name of the sensor B to which mapping applies */ public SensorToSensorMapping(final String sensorNameA, final String sensorNameB) { - this.interMapping = new SensorMapping<SensorPixel>(sensorNameA); + this(sensorNameA, "Rugged", sensorNameB, "Rugged", 0.0); + } + + /** Build a new instance without Earth constraints + * @param sensorNameA name of the sensor A to which mapping applies + * @param sensorNameB name of the sensor B to which mapping applies + */ + public SensorToSensorMapping(final String sensorNameA, final String ruggedNameA , final String sensorNameB, final String ruggedNameB, final double constraintWeight) { + this.interMapping = new SensorMapping<SensorPixel>(sensorNameA, ruggedNameA); this.sensorNameB = sensorNameB; + this.ruggedNameB = ruggedNameB; this.losDistances = new ArrayList<Double>(); this.earthDistances = new ArrayList<Double>(); - this.earthConstraintWeight = 0.0; - + this.earthConstraintWeight = constraintWeight; + } - - /** Build a new instance with Earth constraints: we want to minimize the distance between pixelA and Earth + /** Build a new instance without Earth constraints * @param sensorNameA name of the sensor A to which mapping applies * @param sensorNameB name of the sensor B to which mapping applies - * @param constraintWeight weight given to the Earth distance constraint + */ + public SensorToSensorMapping(final String sensorNameA, final String ruggedNameA , final String sensorNameB, final String ruggedNameB) { + this(sensorNameA, ruggedNameA, sensorNameB, ruggedNameB, 0.0); + } + + + + /** Build a new instance with Earth constraints: we want to minimize the distance between pixelA and Earth + * @param sensorNameA name of the sensor A to which mapping applies + * @param sensorNameB name of the sensor B to which mapping applies + * @param constraintWeight weight given to the Earth distance constraint * with respect to the LOS distance (between 0 and 1). Weighting will be applied as follow : * (1-earthConstraintWeight) for losDistance weighting * earthConstraintWeight for earthDistance weighting */ - public SensorToSensorMapping(final String sensorNameA, final String sensorNameB, + public SensorToSensorMapping(final String sensorNameA, final String sensorNameB, final double constraintWeight) { - this(sensorNameA, sensorNameB); - this.earthConstraintWeight = constraintWeight; + this(sensorNameA, "Rugged", sensorNameB, "Rugged", constraintWeight); } - + /** Get the name of the sensor B to which mapping applies. * @return name of the sensor B to which mapping applies */ @@ -91,22 +112,40 @@ public class SensorToSensorMapping { public String getSensorNameA() { return interMapping.getSensorName(); } - + + + /** Get the name of the rugged B to which mapping applies. + * @return name of the rugged B to which mapping applies + */ + public String getRuggedNameB() { + return ruggedNameB; + } + + /** Get the name of the rugged A to which mapping applies. + * @return name of the rugged A to which mapping applies + */ + public String getRuggedNameA() { + return interMapping.getRuggedName(); + } + + + + /** Get all the inter-mapping entries. * @return an unmodifiable view of all mapping entries */ public Set<Map.Entry<SensorPixel, SensorPixel>> getMapping() { return interMapping.getMapping(); } - + /** Get distances between lines of sight (from both view) * @return the losDistances */ public List<Double> getLosDistances() { return losDistances; - } - + } + /** Get distances between Earth and pixel A (mapping with constraints) * @return the earthDistances @@ -115,7 +154,7 @@ public class SensorToSensorMapping { return earthDistances; } - + /** Get the weight given to the Earth distance constraint with respect to the LOS distance * @return the earthConstraintWeight */ @@ -123,7 +162,7 @@ public class SensorToSensorMapping { return earthConstraintWeight; } - + /** Get distance between Earth and pixel A, corresponding to the inter mapping index * @param idx inter mapping index * @return the earthDistances @@ -131,8 +170,8 @@ public class SensorToSensorMapping { public Double getEarthDistance(final int idx) { return getEarthDistances().get(idx); } - - + + /** Get distance between LOS, corresponding to the inter mapping index * @param idx inter mapping index * @return the losDistance @@ -140,7 +179,7 @@ public class SensorToSensorMapping { public Double getLosDistance(final int idx) { return getLosDistances().get(idx); } - + /** Add a mapping between two sensor pixels (A and B) and corresponding distance between the LOS * @param pixelA sensor pixel A @@ -153,19 +192,19 @@ public class SensorToSensorMapping { } /** Add a mapping between two sensor pixels (A and B) and corresponding distance between the LOS - * and the earth distance constraint associated with pixel A + * and the earth distance constraint associated with pixel A * @param pixelA sensor pixel A * @param pixelB sensor pixel B corresponding to the sensor pixel A * @param losDistance distance between both line of sight * @param earthDistance distance between Earth and pixel A */ - public void addMapping(final SensorPixel pixelA, final SensorPixel pixelB, + public void addMapping(final SensorPixel pixelA, final SensorPixel pixelB, final Double losDistance, final Double earthDistance) { interMapping.addMapping(pixelA, pixelB); losDistances.add(losDistance); earthDistances.add(earthDistance); } - + /** Set the Earth constraint weight * @param earthConstraintWeight the Earth constraint weight to set */ diff --git a/src/tutorials/java/AffinagePleiades/GroundRefining.java b/src/tutorials/java/AffinagePleiades/GroundRefining.java index 20c561587281501bf08e71cbb01def9420a1dacd..f52dffb04491ab012317f1d9ed46023636837d99 100644 --- a/src/tutorials/java/AffinagePleiades/GroundRefining.java +++ b/src/tutorials/java/AffinagePleiades/GroundRefining.java @@ -238,7 +238,7 @@ public class GroundRefining extends Refining { int maxIterations = 100; double convergenceThreshold = 1e-14; - refining.optimization(maxIterations, convergenceThreshold, measures.getGroundMapping(), refining.getRugged()); + refining.optimization(maxIterations, convergenceThreshold, measures.getObservables(), refining.getRugged()); // Check estimated values diff --git a/src/tutorials/java/AffinagePleiades/InterRefining.java b/src/tutorials/java/AffinagePleiades/InterRefining.java index 100f03640fa23154966eed4179a9dd6ce15bc5c3..2412255c840e11b5888b9befa21571eacdc5340e 100644 --- a/src/tutorials/java/AffinagePleiades/InterRefining.java +++ b/src/tutorials/java/AffinagePleiades/InterRefining.java @@ -17,19 +17,20 @@ package AffinagePleiades; -import org.hipparchus.util.FastMath; -import org.hipparchus.geometry.euclidean.threed.Vector3D; import java.io.File; -import java.util.Locale; +import java.util.Arrays; +import java.util.Collection; import java.util.List; +import java.util.Locale; +import org.hipparchus.geometry.euclidean.threed.Vector3D; +import org.hipparchus.util.FastMath; import org.orekit.bodies.BodyShape; import org.orekit.bodies.GeodeticPoint; import org.orekit.data.DataProvidersManager; import org.orekit.data.DirectoryCrawler; import org.orekit.errors.OrekitException; import org.orekit.forces.gravity.potential.NormalizedSphericalHarmonicsProvider; - import org.orekit.orbits.Orbit; import org.orekit.rugged.api.AlgorithmId; import org.orekit.rugged.api.BodyRotatingFrameId; @@ -37,7 +38,6 @@ import org.orekit.rugged.api.EllipsoidId; import org.orekit.rugged.api.InertialFrameId; import org.orekit.rugged.api.Rugged; import org.orekit.rugged.api.RuggedBuilder; - import org.orekit.rugged.errors.RuggedException; import org.orekit.rugged.linesensor.LineSensor; import org.orekit.rugged.refining.generators.GroundMeasureGenerator; @@ -58,7 +58,7 @@ import org.orekit.utils.TimeStampedPVCoordinates; /** * Class for testing refining (liaison points study) - * with or without noisy measurements + * with or without noisy measurements * @author Jonathan Guinet * @author Lucie Labat-Allee * @see SensorToGroundMapping @@ -68,54 +68,54 @@ public class InterRefining extends Refining { /** Pleiades viewing model A */ PleiadesViewingModel pleiadesViewingModelA; - + /** Pleiades viewing model B */ PleiadesViewingModel pleiadesViewingModelB; /** Orbit model corresponding to viewing model A */ OrbitModel orbitmodelA; - + /** Orbit model corresponding to viewing model B */ OrbitModel orbitmodelB; - + /** Sensor name A corresponding to viewing model A */ String sensorNameA; - + /** Sensor name A corresponding to viewing model B */ String sensorNameB; - + /** RuggedA 's instance */ Rugged ruggedA; - + /** RuggedB 's instance */ Rugged ruggedB; /** Inter-measurements (between both viewing models) */ InterMeasureGenerator measures; - - + + /** * Constructor */ public InterRefining() throws RuggedException, OrekitException { - + sensorNameA = "SensorA"; final double incidenceAngleA = -5.0; final String dateA = "2016-01-01T11:59:50.0"; - + pleiadesViewingModelA = new PleiadesViewingModel(sensorNameA, incidenceAngleA, dateA); - + sensorNameB = "SensorB"; final double incidenceAngleB = 0.0; final String dateB = "2016-01-01T12:02:50.0"; pleiadesViewingModelB = new PleiadesViewingModel(sensorNameB, incidenceAngleB, dateB); - + orbitmodelA = new OrbitModel(); orbitmodelB = new OrbitModel(); } - - + + /** Main functions * @param args */ @@ -129,71 +129,71 @@ public class InterRefining extends Refining { File orekitData = new File(home, "COTS/orekit-data"); DataProvidersManager.getInstance().addProvider(new DirectoryCrawler(orekitData)); - + // Initialize refining context // --------------------------- InterRefining refining = new InterRefining(); - + // Sensors's definition: create 2 Pleiades viewing models // ------------------------------------------------------ System.out.format("**** Build Pleiades viewing model A and its orbit definition **** %n"); - + // 1/- Create First Pleiades Viewing Model PleiadesViewingModel pleiadesViewingModelA = refining.getPleiadesViewingModelA(); final AbsoluteDate minDateA = pleiadesViewingModelA.getMinDate(); final AbsoluteDate maxDateA = pleiadesViewingModelA.getMaxDate(); final AbsoluteDate refDateA = pleiadesViewingModelA.getDatationReference(); - LineSensor lineSensorA = pleiadesViewingModelA.getLineSensor(); - System.out.format(Locale.US, "Viewing model A - date min: %s max: %s ref: %s %n", minDateA, maxDateA, refDateA); + LineSensor lineSensorA = pleiadesViewingModelA.getLineSensor(); + System.out.format(Locale.US, "Viewing model A - date min: %s max: %s ref: %s %n", minDateA, maxDateA, refDateA); // ----Satellite position, velocity and attitude: create orbit model A OrbitModel orbitmodelA = refining.getOrbitmodelA(); BodyShape earthA = orbitmodelA.createEarth(); NormalizedSphericalHarmonicsProvider gravityFieldA = orbitmodelA.createGravityField(); Orbit orbitA = orbitmodelA.createOrbit(gravityFieldA.getMu(), refDateA); - + // ----If no LOF Transform Attitude Provider is Nadir Pointing Yaw Compensation final double [] rollPoly = {0.0,0.0,0.0}; double[] pitchPoly = {0.025,0.0}; double[] yawPoly = {0.0,0.0,0.0}; orbitmodelA.setLOFTransform(rollPoly, pitchPoly, yawPoly, minDateA); - + // ----Satellite attitude List<TimeStampedAngularCoordinates> satelliteQListA = orbitmodelA.orbitToQ(orbitA, earthA, minDateA.shiftedBy(-0.0), maxDateA.shiftedBy(+0.0), 0.25); int nbQPoints = 2; - + // ----Position and velocities PVCoordinates PVA = orbitA.getPVCoordinates(earthA.getBodyFrame()); List<TimeStampedPVCoordinates> satellitePVListA = orbitmodelA.orbitToPV(orbitA, earthA, minDateA.shiftedBy(-0.0), maxDateA.shiftedBy(+0.0), 0.25); int nbPVPoints = 8; - + // ----Convert frame and coordinates type in one call GeodeticPoint gpA = earthA.transform(PVA.getPosition(), earthA.getBodyFrame(), orbitA.getDate()); - + System.out.format(Locale.US, "(A) Geodetic Point at date %s : φ = %8.10f °, λ = %8.10f %n", orbitA.getDate().toString(), FastMath.toDegrees(gpA.getLatitude()), - FastMath.toDegrees(gpA.getLongitude())); - - + FastMath.toDegrees(gpA.getLongitude())); + + // Rugged A initialization // --------------------- System.out.format("**** Rugged A initialization **** %n"); RuggedBuilder ruggedBuilderA = new RuggedBuilder(); - + ruggedBuilderA.addLineSensor(lineSensorA); ruggedBuilderA.setAlgorithm(AlgorithmId.IGNORE_DEM_USE_ELLIPSOID); ruggedBuilderA.setEllipsoid(EllipsoidId.WGS84, BodyRotatingFrameId.ITRF); ruggedBuilderA.setTimeSpan(minDateA,maxDateA, 0.001, 5.0). - setTrajectory(InertialFrameId.EME2000, satellitePVListA, nbPVPoints, CartesianDerivativesFilter.USE_PV, - satelliteQListA, nbQPoints, AngularDerivativesFilter.USE_R) - .setLightTimeCorrection(false) - .setAberrationOfLightCorrection(false); - + setTrajectory(InertialFrameId.EME2000, satellitePVListA, nbPVPoints, CartesianDerivativesFilter.USE_PV, + satelliteQListA, nbQPoints, AngularDerivativesFilter.USE_R) + .setLightTimeCorrection(false) + .setAberrationOfLightCorrection(false); + ruggedBuilderA.setName("RuggedA"); refining.setRuggedA(ruggedBuilderA.build()); - + System.out.format("\n**** Build Pleiades viewing model B and its orbit definition **** %n"); // 2/- Create Second Pleiades Viewing Model PleiadesViewingModel pleiadesViewingModelB = refining.getPleiadesViewingModelB(); @@ -201,7 +201,7 @@ public class InterRefining extends Refining { final AbsoluteDate maxDateB = pleiadesViewingModelB.getMaxDate(); final AbsoluteDate refDateB = pleiadesViewingModelB.getDatationReference(); LineSensor lineSensorB = pleiadesViewingModelB.getLineSensor(); - System.out.format(Locale.US, "Viewing model B - date min: %s max: %s ref: %s %n", minDateB, maxDateB, refDateB); + System.out.format(Locale.US, "Viewing model B - date min: %s max: %s ref: %s %n", minDateB, maxDateB, refDateB); // ----Satellite position, velocity and attitude: create orbit model B OrbitModel orbitmodelB = new OrbitModel(); @@ -209,49 +209,49 @@ public class InterRefining extends Refining { NormalizedSphericalHarmonicsProvider gravityFieldB = orbitmodelB.createGravityField(); Orbit orbitB = orbitmodelB.createOrbit(gravityFieldB.getMu(), refDateB); //orbitmodelB.setLOFTransform(rollPoly, pitchPoly, yawPoly, minDateB); - + // ----Satellite attitude List<TimeStampedAngularCoordinates> satelliteQListB = orbitmodelB.orbitToQ(orbitB, earthB, minDateB.shiftedBy(-0.0), maxDateB.shiftedBy(+0.0), 0.25); - + // ----Position and velocities PVCoordinates PVB = orbitB.getPVCoordinates(earthB.getBodyFrame()); List<TimeStampedPVCoordinates> satellitePVListB = orbitmodelB.orbitToPV(orbitB, earthB, minDateB.shiftedBy(-0.0), maxDateB.shiftedBy(+0.0), 0.25); GeodeticPoint gpB = earthB.transform(PVB.getPosition(), earthB.getBodyFrame(), orbitB.getDate()); - + System.out.format(Locale.US, "(B) Geodetic Point at date %s : φ = %8.10f °, λ = %8.10f %n",orbitA.getDate().toString(), FastMath.toDegrees(gpB.getLatitude()), - FastMath.toDegrees(gpB.getLongitude())); - + FastMath.toDegrees(gpB.getLongitude())); + // Rugged B initialization // --------------------- System.out.format("**** Rugged B initialization **** %n"); RuggedBuilder ruggedBuilderB = new RuggedBuilder(); - + ruggedBuilderB.addLineSensor(lineSensorB); ruggedBuilderB.setAlgorithm(AlgorithmId.IGNORE_DEM_USE_ELLIPSOID); ruggedBuilderB.setEllipsoid(EllipsoidId.WGS84, BodyRotatingFrameId.ITRF); ruggedBuilderB.setTimeSpan(minDateB,maxDateB, 0.001, 5.0). - setTrajectory(InertialFrameId.EME2000, satellitePVListB, nbPVPoints, CartesianDerivativesFilter.USE_PV, - satelliteQListB, nbQPoints, AngularDerivativesFilter.USE_R) - .setLightTimeCorrection(false) - .setAberrationOfLightCorrection(false); - + setTrajectory(InertialFrameId.EME2000, satellitePVListB, nbPVPoints, CartesianDerivativesFilter.USE_PV, + satelliteQListB, nbQPoints, AngularDerivativesFilter.USE_R) + .setLightTimeCorrection(false) + .setAberrationOfLightCorrection(false); + ruggedBuilderB.setName("RuggedB"); refining.setRuggedB(ruggedBuilderB.build()); - - - + + + // Compute distance between LOS // ----------------------------- double distance = refining.computeDistance(lineSensorA, lineSensorB); System.out.format("distance %f meters %n",distance); - - - // Initialize disruptions: + + + // Initialize disruptions: // ----------------------- - + // Introduce rotations around instrument axes (roll and pitch translations, scale factor) - System.out.format("\n**** Add disruptions on both acquisitions (A,B): roll and pitch rotations, scale factor **** %n"); + System.out.format("\n**** Add disruptions on both acquisitions (A,B): roll and pitch rotations, scale factor **** %n"); double rollValueA = FastMath.toRadians(0.004); double pitchValueA = FastMath.toRadians(0.0008); double rollValueB = FastMath.toRadians(-0.004); @@ -259,23 +259,23 @@ public class InterRefining extends Refining { double factorValue = 1.0; System.out.format("Acquisition A roll: %3.5f \tpitch: %3.5f \tfactor: %3.5f \n",rollValueA,pitchValueA,factorValue); System.out.format("Acquisition B roll: %3.5f \tpitch: %3.5f \tfactor: %3.5f \n",rollValueB,pitchValueB,factorValue); - + // Apply disruptions on physical model (acquisition A) refining.applyDisruptions(refining.getRuggedA(),refining.getSensorNameA(), rollValueA, pitchValueA, factorValue); - + // Apply disruptions on physical model (acquisition B) refining.applyDisruptions(refining.getRuggedB(),refining.getSensorNameB(), rollValueB, pitchValueB, factorValue); - - - + + + // Generate measures (observations) from physical model disrupted // -------------------------------------------------------------- - + int lineSampling = 1000; - int pixelSampling = 1000; - + int pixelSampling = 1000; + // Noise definition final Noise noise = new Noise(0,2); /* distribution: gaussian(0), vector dimension:3 */ final double[] mean = {5.0,0.0}; /* {pixelA mean, pixelB mean} */ @@ -286,54 +286,54 @@ public class InterRefining extends Refining { System.out.format("\tSensor A mean: %f std %f %n",mean[0],standardDeviation[0]); System.out.format("\tSensor B mean: %f std %f %n",mean[1],standardDeviation[1]); - InterMeasureGenerator measures = refining.generateNoisyPoints(lineSampling, pixelSampling, + InterMeasureGenerator measures = refining.generateNoisyPoints(lineSampling, pixelSampling, refining.getRuggedA(), refining.getSensorNameA(), refining.getPleiadesViewingModelA().getDimension(), refining.getRuggedB(), refining.getSensorNameB(), refining.getPleiadesViewingModelB().getDimension(), noise); - -// // To test with measures without noise -// InterMeasureGenerator measures = refining.generatePoints(lineSampling, pixelSampling, -// refining.getRuggedA(), refining.getSensorNameA(), -// refining.getPleiadesViewingModelA().getDimension(), -// refining.getRuggedB(), refining.getSensorNameB(), -// refining.getPleiadesViewingModelB().getDimension()); - + + // // To test with measures without noise + // InterMeasureGenerator measures = refining.generatePoints(lineSampling, pixelSampling, + // refining.getRuggedA(), refining.getSensorNameA(), + // refining.getPleiadesViewingModelA().getDimension(), + // refining.getRuggedB(), refining.getSensorNameB(), + // refining.getPleiadesViewingModelB().getDimension()); + refining.setMeasures(measures); - - + + // Compute ground truth residues // ----------------------------- System.out.format("\n**** Ground truth residuals **** %n"); refining.computeMetrics(measures.getInterMapping(), refining.getRuggedA(), refining.getRuggedB(), false); - + // Initialize physical models without disruptions // ----------------------------------------------- System.out.format("\n**** Initialize physical models (A,B) without disruptions: reset Roll/Pitch/Factor **** %n"); refining.resetModel(refining.getRuggedA(), refining.getSensorNameA(), false); refining.resetModel(refining.getRuggedB(), refining.getSensorNameB(), false); - - + + // Compute initial residues // ------------------------ System.out.format("\n**** Initial Residuals **** %n"); refining.computeMetrics(measures.getInterMapping(), refining.getRuggedA(), refining.getRuggedB(), false); - - + + // Start optimization // ------------------ System.out.format("\n**** Start optimization **** %n"); - + int maxIterations = 100; double convergenceThreshold = 1e-10; - - refining.optimization(maxIterations, convergenceThreshold, - measures.getInterMapping(), - refining.getRuggedA(), refining.getRuggedB()); - - + + refining.optimization(maxIterations, convergenceThreshold, + measures.getObservables(), + refining.getRuggeds()); + + // Check estimated values // ---------------------- System.out.format("\n**** Check parameters ajustement **** %n"); @@ -344,15 +344,15 @@ public class InterRefining extends Refining { refining.paramsEstimation(refining.getRuggedB(), refining.getSensorNameB(), rollValueB, pitchValueB, factorValue); //refining.paramsEstimation(rollValueA, pitchValueA, factorValue, rollValueB, pitchValueB); - - + + // Compute statistics // ------------------ System.out.format("\n**** Compute Statistics **** %n"); refining.computeMetrics(measures.getInterMapping(), refining.getRuggedA(), refining.getRuggedB(), false); - - - + + + } catch (OrekitException oe) { System.err.println(oe.getLocalizedMessage()); System.exit(1); @@ -364,7 +364,7 @@ public class InterRefining extends Refining { } - + /** * @return the pleiadesViewingModelA */ @@ -373,17 +373,17 @@ public class InterRefining extends Refining { } - + /** * @param pleiadesViewingModelA the pleiadesViewingModelA to set */ public void - setPleiadesViewingModelA(PleiadesViewingModel pleiadesViewingModelA) { + setPleiadesViewingModelA(PleiadesViewingModel pleiadesViewingModelA) { this.pleiadesViewingModelA = pleiadesViewingModelA; } - + /** * @return the pleiadesViewingModelB */ @@ -392,17 +392,17 @@ public class InterRefining extends Refining { } - + /** * @param pleiadesViewingModelB the pleiadesViewingModelB to set */ public void - setPleiadesViewingModelB(PleiadesViewingModel pleiadesViewingModelB) { + setPleiadesViewingModelB(PleiadesViewingModel pleiadesViewingModelB) { this.pleiadesViewingModelB = pleiadesViewingModelB; } - + /** * @return the orbitmodelA */ @@ -411,7 +411,7 @@ public class InterRefining extends Refining { } - + /** * @param orbitmodelA the orbitmodelA to set */ @@ -420,7 +420,7 @@ public class InterRefining extends Refining { } - + /** * @return the orbitmodelB */ @@ -429,7 +429,7 @@ public class InterRefining extends Refining { } - + /** * @param orbitmodelB the orbitmodelB to set */ @@ -438,8 +438,8 @@ public class InterRefining extends Refining { } - - + + /** * @return the sensorNameA */ @@ -448,7 +448,7 @@ public class InterRefining extends Refining { } - + /** * @return the sensorNameB */ @@ -465,7 +465,7 @@ public class InterRefining extends Refining { } - + /** * @param ruggedA the ruggedA to set */ @@ -481,8 +481,16 @@ public class InterRefining extends Refining { return ruggedB; } + /** + * @return the ruggedList + */ + public Collection<Rugged> getRuggeds() { + List<Rugged> ruggedList = Arrays.asList(this.ruggedA, this.ruggedB); + return ruggedList; + } + + - /** * @param ruggedB the ruggedB to set */ @@ -505,47 +513,47 @@ public class InterRefining extends Refining { * @return GSD */ private double computeDistance(final LineSensor lineSensorA, final LineSensor lineSensorB) throws RuggedException { - + Vector3D positionA = lineSensorA.getPosition(); // This returns a zero vector since we set the relative position of the sensor w.r.T the satellite to 0. - + AbsoluteDate lineDateA = lineSensorA.getDate(pleiadesViewingModelA.dimension/2); Vector3D losA = lineSensorA.getLOS(lineDateA,pleiadesViewingModelA.dimension/2); GeodeticPoint centerPointA = ruggedA.directLocation(lineDateA, positionA, losA); System.out.format(Locale.US, "\ncenter geodetic position A : φ = %8.10f °, λ = %8.10f °, h = %8.3f m%n", FastMath.toDegrees(centerPointA.getLatitude()), - FastMath.toDegrees(centerPointA.getLongitude()),centerPointA.getAltitude()); - - + FastMath.toDegrees(centerPointA.getLongitude()),centerPointA.getAltitude()); + + Vector3D positionB = lineSensorB.getPosition(); // This returns a zero vector since we set the relative position of the sensor w.r.T the satellite to 0. - + AbsoluteDate lineDateB = lineSensorB.getDate(pleiadesViewingModelB.dimension/2); Vector3D losB = lineSensorB.getLOS(lineDateB,pleiadesViewingModelB.dimension/2); GeodeticPoint centerPointB = ruggedB.directLocation(lineDateB, positionB, losB); System.out.format(Locale.US, "center geodetic position B : φ = %8.10f °, λ = %8.10f °, h = %8.3f m%n", FastMath.toDegrees(centerPointB.getLatitude()), - FastMath.toDegrees(centerPointB.getLongitude()),centerPointB.getAltitude()); - + FastMath.toDegrees(centerPointB.getLongitude()),centerPointB.getAltitude()); + lineDateB = lineSensorB.getDate(0); losB = lineSensorB.getLOS(lineDateB,0); GeodeticPoint firstPointB = ruggedB.directLocation(lineDateB, positionB, losB); System.out.format(Locale.US, "first geodetic position B : φ = %8.10f °, λ = %8.10f °, h = %8.3f m%n", FastMath.toDegrees(firstPointB.getLatitude()), - FastMath.toDegrees(firstPointB.getLongitude()),firstPointB.getAltitude()); - + FastMath.toDegrees(firstPointB.getLongitude()),firstPointB.getAltitude()); + lineDateB = lineSensorB.getDate(pleiadesViewingModelB.dimension-1); losB = lineSensorB.getLOS(lineDateB,pleiadesViewingModelB.dimension-1); GeodeticPoint lastPointB = ruggedB.directLocation(lineDateB, positionB, losB); System.out.format(Locale.US, "last geodetic position B : φ = %8.10f °, λ = %8.10f °, h = %8.3f m%n", FastMath.toDegrees(lastPointB.getLatitude()), - FastMath.toDegrees(lastPointB.getLongitude()),lastPointB.getAltitude()); - + FastMath.toDegrees(lastPointB.getLongitude()),lastPointB.getAltitude()); + double distance = DistanceTools.computeDistanceInMeter(centerPointA.getLongitude(), centerPointA.getLatitude(), - centerPointB.getLongitude(), centerPointB.getLatitude()); - + centerPointB.getLongitude(), centerPointB.getLatitude()); + return distance; } - + diff --git a/src/tutorials/java/AffinagePleiades/Refining.java b/src/tutorials/java/AffinagePleiades/Refining.java index 7f93ae890b5f9d95fdec2d6e128862b6efa8d74a..e7ede5128a03ae99e32a63f03af05725c1145896 100644 --- a/src/tutorials/java/AffinagePleiades/Refining.java +++ b/src/tutorials/java/AffinagePleiades/Refining.java @@ -17,6 +17,7 @@ package AffinagePleiades; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.List; @@ -26,6 +27,7 @@ import org.orekit.errors.OrekitExceptionWrapper; import org.orekit.rugged.adjustment.AdjustmentContext; import org.orekit.rugged.api.Rugged; import org.orekit.rugged.errors.RuggedException; +import org.orekit.rugged.errors.RuggedMessages; import org.orekit.rugged.refining.generators.GroundMeasureGenerator; import org.orekit.rugged.refining.generators.InterMeasureGenerator; import org.orekit.rugged.refining.measures.Noise; @@ -316,24 +318,19 @@ public class Refining { * @throws RuggedException */ public void optimization(int maxIterations, double convergenceThreshold, - SensorToGroundMapping measures, + Observables measures, Rugged rugged) throws OrekitException, RuggedException { - System.out.format("Iterations max: %d\tconvergence threshold: %3.6e \n",maxIterations, convergenceThreshold); - List<Rugged> viewingModel = new ArrayList<Rugged>(); - viewingModel.add(rugged); + System.out.format("Iterations max: %d\tconvergence threshold: %3.6e \n", maxIterations, convergenceThreshold); - Observables observables = new Observables(1); - observables.addGroundMapping(measures); - - AdjustmentContext adjustmentContext = new AdjustmentContext(viewingModel, observables); - Optimum optimum = adjustmentContext.estimateFreeParameters("Rugged_refining",maxIterations,convergenceThreshold); + AdjustmentContext adjustmentContext = new AdjustmentContext(Collections.singletonList(rugged), measures); + Optimum optimum = adjustmentContext.estimateFreeParameters(Collections.singletonList(rugged.getName()), maxIterations, convergenceThreshold); // Print statistics - System.out.format("Max value: %3.6e %n",optimum.getResiduals().getMaxValue()); - System.out.format("Optimization performed in %d iterations \n",optimum.getEvaluations()); - System.out.format("RMSE: %f \n",optimum.getRMS()); + System.out.format("Max value: %3.6e %n", optimum.getResiduals().getMaxValue()); + System.out.format("Optimization performed in %d iterations \n", optimum.getEvaluations()); + System.out.format("RMSE: %f \n", optimum.getRMS()); } @@ -347,22 +344,30 @@ public class Refining { * @throws RuggedException */ public void optimization(int maxIterations, double convergenceThreshold, - SensorToSensorMapping interMapping, - Rugged ruggedA, Rugged ruggedB) throws OrekitException, RuggedException { + Observables measures, + Collection<Rugged> ruggeds) throws OrekitException, RuggedException { + + + System.out.format("Iterations max: %d\tconvergence threshold: %3.6e \n", maxIterations, convergenceThreshold); + if(ruggeds.size()!= 2 ) + { + throw new RuggedException(RuggedMessages.UNSUPPORTED_REFINING_CONTEXT,ruggeds.size()); + } + AdjustmentContext adjustmentContext = new AdjustmentContext(ruggeds, measures); - System.out.format("Iterations max: %d\tconvergence threshold: %3.6e \n",maxIterations, convergenceThreshold); + List<String> ruggedNameList = new ArrayList<String>(); + for(Rugged rugged : ruggeds) { + ruggedNameList.add(rugged.getName()); + } - // Note: estimateFreeParams2Models() is supposed to be applying on ruggedB, not on ruggedA (to be compliant with notations) - // Adapt parameters - Optimum optimum = ruggedB.estimateFreeParams2Models(Collections.singletonList(interMapping), - maxIterations,convergenceThreshold, ruggedA); + Optimum optimum = adjustmentContext.estimateFreeParameters(ruggedNameList, maxIterations, convergenceThreshold); // Print statistics - System.out.format("Max value: %3.6e %n",optimum.getResiduals().getMaxValue()); - System.out.format("Optimization performed in %d iterations \n",optimum.getEvaluations()); - System.out.format("RMSE: %f \n",optimum.getRMS()); + System.out.format("Max value: %3.6e %n", optimum.getResiduals().getMaxValue()); + System.out.format("Optimization performed in %d iterations \n", optimum.getEvaluations()); + System.out.format("RMSE: %f \n", optimum.getRMS()); }