From 3a6a499f0cb929a603e510f325c316aa444d25fe Mon Sep 17 00:00:00 2001 From: Guylaine Prat <guylaine.prat@c-s.fr> Date: Thu, 18 Jan 2018 12:51:47 +0100 Subject: [PATCH] Change the parameters to adjust for optimization problem --- .../org/orekit/rugged/utils/RefiningTest.java | 241 +++++++++++++++--- 1 file changed, 204 insertions(+), 37 deletions(-) diff --git a/src/test/java/org/orekit/rugged/utils/RefiningTest.java b/src/test/java/org/orekit/rugged/utils/RefiningTest.java index d6f5e75c..bf0ff2da 100644 --- a/src/test/java/org/orekit/rugged/utils/RefiningTest.java +++ b/src/test/java/org/orekit/rugged/utils/RefiningTest.java @@ -4,17 +4,23 @@ import java.io.File; import java.lang.reflect.InvocationTargetException; import java.net.URISyntaxException; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import org.junit.After; +import org.junit.Assert; + import org.hipparchus.analysis.differentiation.DerivativeStructure; import org.hipparchus.geometry.euclidean.threed.Rotation; import org.hipparchus.geometry.euclidean.threed.RotationConvention; import org.hipparchus.geometry.euclidean.threed.RotationOrder; import org.hipparchus.geometry.euclidean.threed.Vector3D; import org.hipparchus.ode.nonstiff.DormandPrince853Integrator; +import org.hipparchus.random.GaussianRandomGenerator; +import org.hipparchus.random.UncorrelatedRandomVectorGenerator; +import org.hipparchus.random.Well19937a; import org.hipparchus.util.FastMath; -import org.junit.After; -import org.junit.Assert; + import org.orekit.attitudes.AttitudeProvider; import org.orekit.attitudes.LofOffset; import org.orekit.attitudes.NadirPointing; @@ -22,6 +28,7 @@ import org.orekit.attitudes.TabulatedLofOffset; import org.orekit.attitudes.YawCompensation; import org.orekit.bodies.BodyShape; import org.orekit.bodies.CelestialBodyFactory; +import org.orekit.bodies.GeodeticPoint; import org.orekit.data.DataProvidersManager; import org.orekit.data.DirectoryCrawler; import org.orekit.errors.OrekitException; @@ -39,6 +46,16 @@ import org.orekit.propagation.Propagator; import org.orekit.propagation.SpacecraftState; import org.orekit.propagation.analytical.KeplerianPropagator; import org.orekit.propagation.numerical.NumericalPropagator; +import org.orekit.time.AbsoluteDate; +import org.orekit.time.TimeScale; +import org.orekit.time.TimeScalesFactory; +import org.orekit.utils.AngularDerivativesFilter; +import org.orekit.utils.CartesianDerivativesFilter; +import org.orekit.utils.Constants; +import org.orekit.utils.ParameterDriver; +import org.orekit.utils.TimeStampedAngularCoordinates; +import org.orekit.utils.TimeStampedPVCoordinates; + import org.orekit.rugged.TestUtils; import org.orekit.rugged.adjustment.InterSensorsOptimizationProblemBuilder; import org.orekit.rugged.adjustment.measurements.Observables; @@ -58,17 +75,11 @@ import org.orekit.rugged.los.FixedRotation; import org.orekit.rugged.los.FixedZHomothety; import org.orekit.rugged.los.LOSBuilder; import org.orekit.rugged.los.TimeDependentLOS; -import org.orekit.time.AbsoluteDate; -import org.orekit.time.TimeScale; -import org.orekit.time.TimeScalesFactory; -import org.orekit.utils.AngularDerivativesFilter; -import org.orekit.utils.CartesianDerivativesFilter; -import org.orekit.utils.Constants; -import org.orekit.utils.ParameterDriver; -import org.orekit.utils.TimeStampedAngularCoordinates; -import org.orekit.utils.TimeStampedPVCoordinates; +/** Initialization for refining Junit tests. + * @author Guylaine Prat + */ public class RefiningTest { /** Pleiades viewing model A */ @@ -97,15 +108,32 @@ public class RefiningTest { static final String pitchSuffix = "_pitch"; static final String factorName = "factor"; + + /** + * Default values for disruption to apply to roll (deg), pitch (deg) and factor + */ + static final double defaultRollDisruptionA = 0.004; + static final double defaultPitchDisruptionA = 0.0008; + static final double defaultFactorDisruptionA = 1.000000001; + static final double defaultPitchDisruptionB = -0.0008; + + /** + * Initialize refining tests with default values for disruptions on sensors characteristics + * @throws RuggedException + */ + public void initRefiningTest() throws RuggedException { + + initRefiningTest(defaultRollDisruptionA, defaultPitchDisruptionA, defaultFactorDisruptionA, defaultPitchDisruptionB); + } - /** Initialize refining tests + /** Initialize refining tests with disruption on sensors characteristics * @param rollDisruptionA disruption to apply to roll angle for sensor A (deg) * @param pitchDisruptionA disruption to apply to pitch angle for sensor A (deg) * @param factorDisruptionA disruption to apply to homothety factor for sensor A * @param pitchDisruptionB disruption to apply to pitch angle for sensor B (deg) * @throws RuggedException */ - public void InitRefiningTest(double rollDisruptionA, double pitchDisruptionA, double factorDisruptionA, double pitchDisruptionB) throws RuggedException { + public void initRefiningTest(double rollDisruptionA, double pitchDisruptionA, double factorDisruptionA, double pitchDisruptionB) throws RuggedException { try { String path = getClass().getClassLoader().getResource("orekit-data").toURI().getPath(); @@ -137,8 +165,7 @@ public class RefiningTest { // ----Satellite position, velocity and attitude: create orbit model A BodyShape earthA = TestUtils.createEarth(); - NormalizedSphericalHarmonicsProvider gravityFieldA = TestUtils.createGravityField(); - Orbit orbitA = orbitmodelA.createOrbit(gravityFieldA.getMu(), refDateA); + Orbit orbitA = orbitmodelA.createOrbit(Constants.EIGEN5C_EARTH_MU, refDateA); // ----If no LOF Transform Attitude Provider is Nadir Pointing Yaw Compensation final double [] rollPoly = {0.0,0.0,0.0}; @@ -181,8 +208,7 @@ public class RefiningTest { // ----Satellite position, velocity and attitude: create orbit model B BodyShape earthB = TestUtils.createEarth(); - NormalizedSphericalHarmonicsProvider gravityFieldB = TestUtils.createGravityField(); - Orbit orbitB = orbitmodelB.createOrbit(gravityFieldB.getMu(), refDateB); + Orbit orbitB = orbitmodelB.createOrbit(Constants.EIGEN5C_EARTH_MU, refDateB); // ----Satellite attitude List<TimeStampedAngularCoordinates> satelliteQListB = orbitmodelB.orbitToQ(orbitB, earthB, minDateB.shiftedBy(-0.0), maxDateB.shiftedBy(+0.0), 0.25); @@ -208,30 +234,27 @@ public class RefiningTest { this.ruggedB = ruggedBuilderB.build(); - // Initialize disruptions: - // ----------------------- - // Introduce rotations around instrument axes (roll and pitch angles, scale factor) - final double rollValueA = FastMath.toRadians(rollDisruptionA); - final double pitchValueA = FastMath.toRadians(pitchDisruptionA); - final double pitchValueB = FastMath.toRadians(pitchDisruptionB); - final double factorValueA = factorDisruptionA; - + // Select parameters to adjust + // --------------------------- setSelectedRoll(ruggedA, sensorNameA); setSelectedPitch(ruggedA, sensorNameA); - setSelectedFactor(ruggedA, sensorNameA); - + setSelectedRoll(ruggedB, sensorNameB); setSelectedPitch(ruggedB, sensorNameB); -// setSelectedFactor(ruggedB, sensorNameB); - // Apply disruptions on physical model (acquisition A) - applyDisruptionsRoll(ruggedA, sensorNameA, rollValueA); - applyDisruptionsPitch(ruggedA, sensorNameA, pitchValueA); - applyDisruptionsFactor(ruggedA, sensorNameA, factorValueA); + // Initialize disruptions: + // ----------------------- + // introduce rotations around instrument axes (roll and pitch angles, scale factor) + + // apply disruptions on physical model (acquisition A) + applyDisruptionsRoll(ruggedA, sensorNameA, FastMath.toRadians(rollDisruptionA)); + applyDisruptionsPitch(ruggedA, sensorNameA, FastMath.toRadians(pitchDisruptionA)); + applyDisruptionsFactor(ruggedA, sensorNameA, factorDisruptionA); + + // apply disruptions on physical model (acquisition B) + applyDisruptionsPitch(ruggedB, sensorNameB, FastMath.toRadians(pitchDisruptionB)); - // Apply disruptions on physical model (acquisition B) - applyDisruptionsPitch(ruggedB, sensorNameB, pitchValueB); } catch (OrekitException oe) { Assert.fail(oe.getLocalizedMessage()); @@ -240,6 +263,15 @@ public class RefiningTest { } } + /** + * Get the list of Rugged instances + * @return rugged instances as list + */ + public List<Rugged> getRuggedList(){ + + List<Rugged> ruggedList = Arrays.asList(ruggedA, ruggedB); + return ruggedList; + } /** Apply disruptions on acquisition for roll angle * @param rugged Rugged instance @@ -295,7 +327,7 @@ public class RefiningTest { ParameterDriver rollDriver = rugged.getLineSensor(sensorName).getParametersDrivers(). - filter(driver -> driver.getName().equals(sensorName+rollSuffix)).findFirst().get(); + filter(driver -> driver.getName().equals(sensorName + rollSuffix)).findFirst().get(); rollDriver.setSelected(true); } @@ -399,6 +431,136 @@ public class RefiningTest { return distanceLOSwithDS; } + + /** Generate noisy measurements (sensor to sensor mapping) + * @param lineSampling line sampling + * @param pixelSampling pixel sampling + * @throws RuggedException + */ + public Observables generateNoisyPoints(final int lineSampling, final int pixelSampling) throws RuggedException { + + // Outliers control + final double outlierValue = 1.e+2; + + // Earth constraint weight + final double earthConstraintWeight = 0.1; + + // Number of measurements + int measurementCount = 0; + + // Generate measurements with constraints on Earth distance and outliers control + + // Generate reference mapping, with Earth distance constraints. + // Weighting will be applied as follow : + // (1-earthConstraintWeight) for losDistance weighting + // earthConstraintWeight for earthDistance weighting + SensorToSensorMapping interMapping = new SensorToSensorMapping(lineSensorA.getName(), ruggedA.getName(), + lineSensorB.getName(), ruggedB.getName(), + earthConstraintWeight); + + // Observables which contains sensor to sensor mapping + Observables observables = new Observables(2); + + + System.out.format("\n**** Generate noisy measurements (sensor to sensor mapping) **** %n"); + + // Generation noisy measurements + + // distribution: gaussian(0), vector dimension: 2 + final double meanA[] = { 5.0, 5.0 }; + final double stdA[] = { 0.1, 0.1 }; + final double meanB[] = { 0.0, 0.0 }; + final double stdB[] = { 0.1, 0.1 }; + + // Seed has been fixed for tests purpose + final GaussianRandomGenerator rngA = new GaussianRandomGenerator(new Well19937a(0xefac03d9be4d24b9l)); + final UncorrelatedRandomVectorGenerator rvgA = new UncorrelatedRandomVectorGenerator(meanA, stdA, rngA); + + // Seed has been fixed for tests purpose + final GaussianRandomGenerator rngB = new GaussianRandomGenerator(new Well19937a(0xdf1c03d9be0b34b9l)); + final UncorrelatedRandomVectorGenerator rvgB = new UncorrelatedRandomVectorGenerator(meanB, stdB, rngB); + + + // Search the sensor pixel seeing point + final int minLine = 0; + final int maxLine = pleiadesViewingModelB.getDimension() - 1; + + final String sensorNameB = lineSensorB.getName(); + + for (double line = 0; line < pleiadesViewingModelA.getDimension(); line += lineSampling) { + + final AbsoluteDate dateA = lineSensorA.getDate(line); + + for (double pixelA = 0; pixelA < lineSensorA.getNbPixels(); pixelA += pixelSampling) { + + final GeodeticPoint gpA = ruggedA.directLocation(dateA, lineSensorA.getPosition(), + lineSensorA.getLOS(dateA, pixelA)); + 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 = lineSensorB.getDate(sensorPixelB.getLineNumber()); + final double pixelB = sensorPixelB.getPixelNumber(); + + // Get spacecraft to body transform of Rugged instance A + final SpacecraftToObservedBody scToBodyA = ruggedA.getScToBody(); + + final GeodeticPoint gpB = ruggedB.directLocation(dateB, lineSensorB.getPosition(), + lineSensorB.getLOS(dateB, pixelB)); + final double geoDistance = computeDistanceInMeter(gpA, gpB); + + // Create the inter mapping if distance is below outlier value + if (geoDistance < outlierValue) { + + final double[] vecRandomA = rvgA.nextVector(); + final double[] vecRandomB = rvgB.nextVector(); + + final SensorPixel realPixelA = new SensorPixel(line + vecRandomA[0], pixelA + vecRandomA[1]); + final SensorPixel realPixelB = new SensorPixel(sensorPixelB.getLineNumber() + vecRandomB[0], + sensorPixelB.getPixelNumber() + vecRandomB[1]); + + final AbsoluteDate realDateA = lineSensorA.getDate(realPixelA.getLineNumber()); + final AbsoluteDate realDateB = lineSensorB.getDate(realPixelB.getLineNumber()); + + final double[] distanceLOSB = ruggedB.distanceBetweenLOS(lineSensorA, realDateA, realPixelA.getPixelNumber(), scToBodyA, + lineSensorB, realDateB, realPixelB.getPixelNumber()); + final Double losDistance = 0.0; + final Double earthDistance = distanceLOSB[1]; + + interMapping.addMapping(realPixelA, realPixelB, losDistance, earthDistance); + + // Increment the number of measurements + measurementCount++; + + } // end test if geoDistance < outlierValue + } // end test if sensorPixelB != null + + } // end loop on pixel of sensorA + } // end loop on line of sensorA + + observables.addInterMapping(interMapping); + + System.out.format("Number of tie points generated: %d %n", measurementCount); + + return observables; + } + + + /** Compute a geodetic distance in meters between two geodetic points. + * @param geoPoint1 first geodetic point (rad) + * @param geoPoint2 second geodetic point (rad) + * @return distance in meters + */ + private static double computeDistanceInMeter(final GeodeticPoint geoPoint1, final GeodeticPoint geoPoint2) { + + // get vectors on unit sphere from angular coordinates + final Vector3D p1 = new Vector3D(geoPoint1.getLatitude(), geoPoint1.getLongitude()); + final Vector3D p2 = new Vector3D(geoPoint2.getLatitude(), geoPoint2.getLongitude()); + return Constants.WGS84_EARTH_EQUATORIAL_RADIUS * Vector3D.angle(p1, p2); + } + @After public void tearDown() { @@ -406,6 +568,10 @@ public class RefiningTest { } + +/** + * Class to compute orbit for refining tests + */ class OrbitModel { /** Flag to change Attitude Law (by default Nadir Pointing Yaw Compensation). */ @@ -612,7 +778,7 @@ class OrbitModel { return list; } -} +} // end class OrbitModel /** @@ -747,4 +913,5 @@ class PleiadesViewingModel { lineSensor = new LineSensor(sensorName, lineDatation, msiOffset, lineOfSight); } -} + +} // end class PleiadesViewingModel -- GitLab