From 1f170e5ff7534049738754a978213139151806ef Mon Sep 17 00:00:00 2001 From: Luc Maisonobe <luc@orekit.org> Date: Tue, 30 Sep 2014 17:35:55 +0200 Subject: [PATCH] Added a dedicated function for single pixel direct localization. --- .../java/org/orekit/rugged/api/Rugged.java | 74 +++++++++++++++++++ .../org/orekit/rugged/api/RuggedTest.java | 53 +++++++++++++ 2 files changed, 127 insertions(+) diff --git a/core/src/main/java/org/orekit/rugged/api/Rugged.java b/core/src/main/java/org/orekit/rugged/api/Rugged.java index f97e8345..94ba298f 100644 --- a/core/src/main/java/org/orekit/rugged/api/Rugged.java +++ b/core/src/main/java/org/orekit/rugged/api/Rugged.java @@ -798,6 +798,80 @@ public class Rugged { } } + /** Direct localization of a single line-of-sight. + * @param date date of the localization + * @param pixel position in spacecraft frame + * @param los normalized line-of-sight in spacecraft frame + * @return ground position of all pixels of the specified sensor line + * @exception RuggedException if line cannot be localized, or sensor is unknown + */ + public GeodeticPoint directLocalization(final AbsoluteDate date, final Vector3D position, final Vector3D los) + throws RuggedException { + try { + + // compute the approximate transform between spacecraft and observed body + final Transform scToInert = scToBody.getScToInertial(date); + final Transform inertToBody = scToBody.getInertialToBody(date); + final Transform approximate = new Transform(date, scToInert, inertToBody); + + final Vector3D spacecraftVelocity = + scToInert.transformPVCoordinates(PVCoordinates.ZERO).getVelocity(); + + // compute localization of specified pixel + final Vector3D pInert = scToInert.transformPosition(position); + + final Vector3D obsLInert = scToInert.transformVector(los); + final Vector3D lInert; + if (aberrationOfLightCorrection) { + // apply aberration of light correction + // as the spacecraft velocity is small with respect to speed of light, + // we use classical velocity addition and not relativistic velocity addition + // we look for a positive k such that: c * lInert + vsat = k * obsLInert + // with lInert normalized + final double a = obsLInert.getNormSq(); + final double b = -Vector3D.dotProduct(obsLInert, spacecraftVelocity); + final double c = spacecraftVelocity.getNormSq() - Constants.SPEED_OF_LIGHT * Constants.SPEED_OF_LIGHT; + final double s = FastMath.sqrt(b * b - a * c); + final double k = (b > 0) ? -c / (s + b) : (s - b) / a; + lInert = new Vector3D( k / Constants.SPEED_OF_LIGHT, obsLInert, + -1.0 / Constants.SPEED_OF_LIGHT, spacecraftVelocity); + } else { + // don't apply aberration of light correction + lInert = obsLInert; + } + + if (lightTimeCorrection) { + // compute DEM intersection with light time correction + final Vector3D sP = approximate.transformPosition(position); + final Vector3D sL = approximate.transformVector(los); + final Vector3D eP1 = ellipsoid.transform(ellipsoid.pointOnGround(sP, sL)); + final double deltaT1 = eP1.distance(sP) / Constants.SPEED_OF_LIGHT; + final Transform shifted1 = inertToBody.shiftedBy(-deltaT1); + final GeodeticPoint gp1 = algorithm.intersection(ellipsoid, + shifted1.transformPosition(pInert), + shifted1.transformVector(lInert)); + + final Vector3D eP2 = ellipsoid.transform(gp1); + final double deltaT2 = eP2.distance(sP) / Constants.SPEED_OF_LIGHT; + final Transform shifted2 = inertToBody.shiftedBy(-deltaT2); + return algorithm.refineIntersection(ellipsoid, + shifted2.transformPosition(pInert), + shifted2.transformVector(lInert), + gp1); + + } else { + // compute DEM intersection without light time correction + final Vector3D pBody = inertToBody.transformPosition(pInert); + final Vector3D lBody = inertToBody.transformVector(lInert); + return algorithm.refineIntersection(ellipsoid, pBody, lBody, + algorithm.intersection(ellipsoid, pBody, lBody)); + } + + } catch (OrekitException oe) { + throw new RuggedException(oe, oe.getSpecifier(), oe.getParts()); + } + } + /** Find the date at which sensor sees a ground point. * <p> * This method is a partial {@link #inverseLocalization(String, diff --git a/core/src/test/java/org/orekit/rugged/api/RuggedTest.java b/core/src/test/java/org/orekit/rugged/api/RuggedTest.java index 002a63c7..85d1d48e 100644 --- a/core/src/test/java/org/orekit/rugged/api/RuggedTest.java +++ b/core/src/test/java/org/orekit/rugged/api/RuggedTest.java @@ -554,6 +554,59 @@ public class RuggedTest { } + @Test + public void testLocalizationsinglePoint() + throws RuggedException, OrekitException, URISyntaxException { + + int dimension = 200; + + String path = getClass().getClassLoader().getResource("orekit-data").toURI().getPath(); + DataProvidersManager.getInstance().addProvider(new DirectoryCrawler(new File(path))); + final BodyShape earth = createEarth(); + final Orbit orbit = createOrbit(Constants.EIGEN5C_EARTH_MU); + + AbsoluteDate crossing = new AbsoluteDate("2012-01-01T12:30:00.000", TimeScalesFactory.getUTC()); + + // one line sensor + // position: 1.5m in front (+X) and 20 cm above (-Z) of the S/C center of mass + // los: swath in the (YZ) plane, looking at 50° roll, ±1° aperture + Vector3D position = new Vector3D(1.5, 0, -0.2); + List<Vector3D> los = createLOS(new Rotation(Vector3D.PLUS_I, FastMath.toRadians(50.0)).applyTo(Vector3D.PLUS_K), + Vector3D.PLUS_I, + FastMath.toRadians(1.0), dimension); + + // linear datation model: at reference time we get line 100, and the rate is one line every 1.5ms + LineDatation lineDatation = new LinearLineDatation(crossing, dimension / 2, 1.0 / 1.5e-3); + int firstLine = 0; + int lastLine = dimension; + LineSensor lineSensor = new LineSensor("line", lineDatation, position, los); + AbsoluteDate minDate = lineSensor.getDate(firstLine); + AbsoluteDate maxDate = lineSensor.getDate(lastLine); + + TileUpdater updater = + new RandomLandscapeUpdater(0.0, 9000.0, 0.5, 0xf0a401650191f9f6l, + FastMath.toRadians(1.0), 257); + + Rugged rugged = new Rugged(updater, 8, AlgorithmId.DUVENHAGE, + EllipsoidId.WGS84, InertialFrameId.EME2000, BodyRotatingFrameId.ITRF, + minDate, maxDate, 5.0, + orbitToPV(orbit, earth, minDate.shiftedBy(-1.0), maxDate.shiftedBy(+1.0), 0.25), 8, + CartesianDerivativesFilter.USE_PV, + orbitToQ(orbit, earth, minDate.shiftedBy(-1.0), maxDate.shiftedBy(+1.0), 0.25), 2, + AngularDerivativesFilter.USE_R, 0.001); + rugged.addLineSensor(lineSensor); + GeodeticPoint[] gpLine = rugged.directLocalization("line", 100); + + for (int i = 0; i < gpLine.length; ++i) { + GeodeticPoint gpPixel = + rugged.directLocalization(lineSensor.getDate(100), lineSensor.getPosition(), lineSensor.getLos(i)); + Assert.assertEquals(gpLine[i].getLatitude(), gpPixel.getLatitude(), 1.0e-10); + Assert.assertEquals(gpLine[i].getLongitude(), gpPixel.getLongitude(), 1.0e-10); + Assert.assertEquals(gpLine[i].getAltitude(), gpPixel.getAltitude(), 1.0e-10); + } + + } + @Test public void testBasicScan() throws RuggedException, OrekitException, URISyntaxException { -- GitLab