diff --git a/src/main/java/org/orekit/rugged/intersection/duvenhage/DuvenhageAlgorithm.java b/src/main/java/org/orekit/rugged/intersection/duvenhage/DuvenhageAlgorithm.java index 7009645126a6b34d2af91dfe78766d5a837d6f5f..ba6e1b8ef16e680ed1b4b262eb9626fbe92c2252 100644 --- a/src/main/java/org/orekit/rugged/intersection/duvenhage/DuvenhageAlgorithm.java +++ b/src/main/java/org/orekit/rugged/intersection/duvenhage/DuvenhageAlgorithm.java @@ -44,9 +44,12 @@ public class DuvenhageAlgorithm implements IntersectionAlgorithm { /** Step size when skipping from one tile to a neighbor one, in meters. */ private static final double STEP = 0.01; - /** Nb time cell intersection (with DEM) performed for null intersection: means that infinite loop. + /** Maximum number of attempts to refine intersection. + * <p> + * This parameter is intended to prevent infinite loops. + * </p> * @since 2.1 */ - private static final int NB_TIME_CELL_INTERSECTION = 100; + private static final int MAX_REFINING_ATTEMPTS = 100; /** Cache for DEM tiles. */ private final TilesCache<MinMaxTreeTile> cache; @@ -91,9 +94,31 @@ public class DuvenhageAlgorithm implements IntersectionAlgorithm { final Vector3D entryP = ellipsoid.pointAtAltitude(position, los, hMax + STEP); if (Vector3D.dotProduct(entryP.subtract(position), los) < 0) { // the entry point is behind spacecraft! - throw new RuggedException(RuggedMessages.DEM_ENTRY_POINT_IS_BEHIND_SPACECRAFT); + + // let's see if at least we are above DEM + try { + final NormalizedGeodeticPoint positionGP = + ellipsoid.transform(position, ellipsoid.getBodyFrame(), null, tile.getMinimumLongitude()); + final double elevationAtPosition = tile.interpolateElevation(positionGP.getLatitude(), positionGP.getLongitude()); + if (positionGP.getAltitude() >= elevationAtPosition) { + // we can use the current position as the entry point + current = positionGP; + } else { + current = null; + } + } catch (RuggedException re) { + if (re.getSpecifier() == RuggedMessages.OUT_OF_TILE_ANGLES) { + current = null; + } + } + + if (current == null) { + throw new RuggedException(RuggedMessages.DEM_ENTRY_POINT_IS_BEHIND_SPACECRAFT); + } + + } else { + current = ellipsoid.transform(entryP, ellipsoid.getBodyFrame(), null, tile.getMinimumLongitude()); } - current = ellipsoid.transform(entryP, ellipsoid.getBodyFrame(), null, tile.getMinimumLongitude()); if (tile.getLocation(current.getLatitude(), current.getLongitude()) != Tile.Location.HAS_INTERPOLATION_NEIGHBORS) { // the entry point is in another tile @@ -170,40 +195,35 @@ public class DuvenhageAlgorithm implements IntersectionAlgorithm { DumpManager.dumpAlgorithm(flatBody ? AlgorithmId.DUVENHAGE_FLAT_BODY : AlgorithmId.DUVENHAGE); - NormalizedGeodeticPoint currentGuess = closeGuess; - NormalizedGeodeticPoint foundIntersection = null; - if (flatBody) { // under the (bad) flat-body assumption, the reference point must remain // at DEM entry and exit, even if we already have a much better close guess :-( // this is in order to remain consistent with other systems - final Tile tile = cache.getTile(currentGuess.getLatitude(), currentGuess.getLongitude()); + final Tile tile = cache.getTile(closeGuess.getLatitude(), closeGuess.getLongitude()); final Vector3D exitP = ellipsoid.pointAtAltitude(position, los, tile.getMinElevation()); final Vector3D entryP = ellipsoid.pointAtAltitude(position, los, tile.getMaxElevation()); final NormalizedGeodeticPoint entry = ellipsoid.transform(entryP, ellipsoid.getBodyFrame(), null, tile.getMinimumLongitude()); - foundIntersection = tile.cellIntersection(entry, ellipsoid.convertLos(entryP, exitP), - tile.getFloorLatitudeIndex(currentGuess.getLatitude()), - tile.getFloorLongitudeIndex(currentGuess.getLongitude())); + return tile.cellIntersection(entry, ellipsoid.convertLos(entryP, exitP), + tile.getFloorLatitudeIndex(closeGuess.getLatitude()), + tile.getFloorLongitudeIndex(closeGuess.getLongitude())); - } else { // with a DEM - - // Keep the initial guess - final NormalizedGeodeticPoint currentGuess0 = closeGuess; + } else { + // regular curved ellipsoid model - // number of times cell intersection (with DEM) is performed for null intersection (used to avoid infinite loop) - int nbCall = 0; - // Shift for s to find the solution if foundIntersection is null - double deltaS = -1.; - // if the shifts in one way was not successful, try the other way - boolean secondChance = false; + NormalizedGeodeticPoint currentGuess = closeGuess; - while (foundIntersection == null && (nbCall < NB_TIME_CELL_INTERSECTION)) { + // normally, we should succeed at first attempt but in very rare cases + // we may loose the intersection (typically because some corrections introduced + // between the first intersection and the refining have slightly changed the + // relative geometry between Digital Elevation Model and Line Of Sight). + // In these rare cases, we have to recover a new intersection + for (int i = 0; i < MAX_REFINING_ATTEMPTS; ++i) { - final Vector3D delta = ellipsoid.transform(currentGuess).subtract(position); - final double s = Vector3D.dotProduct(delta, los) / los.getNormSq(); - final GeodeticPoint projected = ellipsoid.transform(new Vector3D(1, position, s, los), - ellipsoid.getBodyFrame(), null); + final Vector3D delta = ellipsoid.transform(currentGuess).subtract(position); + final double s = Vector3D.dotProduct(delta, los) / los.getNormSq(); + final Vector3D projectedP = new Vector3D(1, position, s, los); + final GeodeticPoint projected = ellipsoid.transform(projectedP, ellipsoid.getBodyFrame(), null); final NormalizedGeodeticPoint normalizedProjected = new NormalizedGeodeticPoint(projected.getLatitude(), projected.getLongitude(), @@ -211,38 +231,47 @@ public class DuvenhageAlgorithm implements IntersectionAlgorithm { currentGuess.getLongitude()); final Tile tile = cache.getTile(normalizedProjected.getLatitude(), normalizedProjected.getLongitude()); - foundIntersection = tile.cellIntersection(normalizedProjected, - ellipsoid.convertLos(normalizedProjected, los), - tile.getFloorLatitudeIndex(normalizedProjected.getLatitude()), - tile.getFloorLongitudeIndex(normalizedProjected.getLongitude())); - - // For extremely rare case : the cell intersection gave no results ... - // We use as a new guess a slightly modified projected geodetic point (which is on the LOS line) - if (foundIntersection == null) { - final double shiftedS = s + deltaS; - final GeodeticPoint currentGuessGP = ellipsoid.transform(new Vector3D(1, position, shiftedS, los), - ellipsoid.getBodyFrame(), null); + final Vector3D topoLOS = ellipsoid.convertLos(normalizedProjected, los); + final int iLat = tile.getFloorLatitudeIndex(normalizedProjected.getLatitude()); + final int iLon = tile.getFloorLongitudeIndex(normalizedProjected.getLongitude()); + final NormalizedGeodeticPoint foundIntersection = tile.cellIntersection(normalizedProjected, topoLOS, iLat, iLon); + + if (foundIntersection != null) { + // nominal case, we were able to refine the intersection + return foundIntersection; + } else { + // extremely rare case: we have lost the intersection + + // safety check, which should never be triggered... + if (currentGuess.getAltitude() < + tile.interpolateElevation(currentGuess.getLatitude(), currentGuess.getLongitude())) { + // this should never happen, we are below the DEM + throw RuggedException.createInternalError(null); + } + + // find a start point for new search, leaving the current cell behind + final double cellBoundaryLatitude = tile.getLatitudeAtIndex(topoLOS.getY() <= 0 ? iLat : iLat + 1); + final double cellBoundaryLongitude = tile.getLongitudeAtIndex(topoLOS.getX() <= 0 ? iLon : iLon + 1); + final Vector3D cellExit = new Vector3D(1, selectClosest(latitudeCrossing(ellipsoid, projectedP, los, cellBoundaryLatitude, projectedP), + longitudeCrossing(ellipsoid, projectedP, los, cellBoundaryLongitude, projectedP), + projectedP), + STEP, los); + + // We recompute fully a new guess, starting from the point after current cell + final GeodeticPoint currentGuessGP = intersection(ellipsoid, cellExit, los); currentGuess = new NormalizedGeodeticPoint(currentGuessGP.getLatitude(), currentGuessGP.getLongitude(), currentGuessGP.getAltitude(), projected.getLongitude()); - // to avoid infinite loop ... - nbCall++; - - // if impossible to find a solution with deltaS = -1 - // we start a new search with deltaS = +1 - if (nbCall == NB_TIME_CELL_INTERSECTION && !secondChance) { - currentGuess = currentGuess0; - deltaS = 1.; - nbCall = 0; - secondChance = true; // to avoid infinite loop if second chance does not work ! - } // end if nbCall == NB_TIME_CELL_INTERSECTION - } // end if foundIntersection = null - } // end while foundIntersection = null + } + + } + + // no intersection found + return null; } // end test on flatbody - return foundIntersection; } /** {@inheritDoc} */ @@ -487,24 +516,26 @@ public class DuvenhageAlgorithm implements IntersectionAlgorithm { if (gp != null) { // improve the point, by projecting it back on the 3D line, fixing the small body curvature at cell level - final Vector3D delta = ellipsoid.transform(gp).subtract(position); - final double s = Vector3D.dotProduct(delta, los) / los.getNormSq(); - final GeodeticPoint projected = ellipsoid.transform(new Vector3D(1, position, s, los), - ellipsoid.getBodyFrame(), null); - final NormalizedGeodeticPoint normalizedProjected = new NormalizedGeodeticPoint(projected.getLatitude(), - projected.getLongitude(), - projected.getAltitude(), - gp.getLongitude()); - final NormalizedGeodeticPoint gpImproved = tile.cellIntersection(normalizedProjected, - ellipsoid.convertLos(normalizedProjected, los), - i, j); - - if (gpImproved != null) { - final Vector3D point = ellipsoid.transform(gpImproved); - final double dot = Vector3D.dotProduct(point.subtract(position), los); - if (dot < intersectionDot) { - intersectionGP = gpImproved; - intersectionDot = dot; + final Vector3D delta = ellipsoid.transform(gp).subtract(position); + final double s = Vector3D.dotProduct(delta, los) / los.getNormSq(); + if (s > 0) { + final GeodeticPoint projected = ellipsoid.transform(new Vector3D(1, position, s, los), + ellipsoid.getBodyFrame(), null); + final NormalizedGeodeticPoint normalizedProjected = new NormalizedGeodeticPoint(projected.getLatitude(), + projected.getLongitude(), + projected.getAltitude(), + gp.getLongitude()); + final NormalizedGeodeticPoint gpImproved = tile.cellIntersection(normalizedProjected, + ellipsoid.convertLos(normalizedProjected, los), + i, j); + + if (gpImproved != null) { + final Vector3D point = ellipsoid.transform(gpImproved); + final double dot = Vector3D.dotProduct(point.subtract(position), los); + if (dot < intersectionDot) { + intersectionGP = gpImproved; + intersectionDot = dot; + } } } @@ -621,7 +652,7 @@ public class DuvenhageAlgorithm implements IntersectionAlgorithm { * @param latitude latitude with respect to ellipsoid * @param closeReference reference point used to select the closest solution * when there are two points at the desired latitude along the line - * @return point at altitude, or closeReference if no such point can be found + * @return point at latitude, or closeReference if no such point can be found */ private Vector3D latitudeCrossing(final ExtendedEllipsoid ellipsoid, final Vector3D position, final Vector3D los, @@ -639,8 +670,8 @@ public class DuvenhageAlgorithm implements IntersectionAlgorithm { * @param los pixel line-of-sight, not necessarily normalized (in body frame) * @param longitude longitude with respect to ellipsoid * @param closeReference reference point used to select the closest solution - * when there are two points at the desired latitude along the line - * @return point at altitude, or closeReference if no such point can be found + * when there are two points at the desired longitude along the line + * @return point at longitude, or closeReference if no such point can be found */ private Vector3D longitudeCrossing(final ExtendedEllipsoid ellipsoid, final Vector3D position, final Vector3D los, diff --git a/src/test/java/org/orekit/rugged/errors/DumpReplayerTest.java b/src/test/java/org/orekit/rugged/errors/DumpReplayerTest.java index 9b2bca87bbc5353708f772a1c8b8037711c706e5..85b06b8bf2c77661799affc9e4d8c3ef0397ae68 100644 --- a/src/test/java/org/orekit/rugged/errors/DumpReplayerTest.java +++ b/src/test/java/org/orekit/rugged/errors/DumpReplayerTest.java @@ -261,7 +261,7 @@ public class DumpReplayerTest { } } - + @Test public void testDirectLocIssue376_01() throws URISyntaxException, IOException { @@ -281,7 +281,7 @@ public class DumpReplayerTest { rugged.getEllipsoid().transform(replayedGP)); Assert.assertEquals(0.0, distance, 1.0e-8); } - + @Test public void testDirectLocIssue376_02() throws URISyntaxException, IOException { @@ -301,7 +301,7 @@ public class DumpReplayerTest { rugged.getEllipsoid().transform(replayedGP)); Assert.assertEquals(0.0, distance, 1.0e-8); } - + @Test public void testDirectLocIssue376_03() throws URISyntaxException, IOException { diff --git a/src/test/resources/replay/replay-direct-loc-Issue376-01.txt b/src/test/resources/replay/replay-direct-loc-Issue376-01.txt index 89e6aee2d61f3063490e19fa66279d0d42d311f6..8d3a0975b33115277140dea55a7c5e7a273c50a2 100644 --- a/src/test/resources/replay/replay-direct-loc-Issue376-01.txt +++ b/src/test/resources/replay/replay-direct-loc-Issue376-01.txt @@ -7,8 +7,8 @@ span: minDate 2018-11-17T09:28:09.75815400000000Z maxDate 2018-11-17T09:28:24.37 transform: index 3749 body r -1.582419730578572e-01 -8.877875020391763e-04 1.556906340657658e-04 -9.873999521756794e-01 Ω -1.314379576583188e-07 1.929883563714465e-09 -7.292103298515694e-05 ΩDot -1.238204383721699e-16 -4.429578390177184e-17 2.220234885205757e-19 spacecraft p -2.043780763621181e+06 2.649055676516346e+06 -6.230074460056063e+06 v 8.500193464365886e+03 -1.120156363674237e+04 -7.562611889558547e+03 a -7.774014494482032e+02 -2.165448216679694e+02 2.038618372832540e+02 r -4.471787778551135e-01 -2.556359378108412e-01 7.875656535717214e-01 3.382628404801900e-01 Ω 1.895876683374440e-03 6.208707436271533e-04 6.748857995964048e-04 ΩDot 2.850236048816703e-06 1.374797997377696e-04 -1.976120196823438e-05 algorithm: DUVENHAGE ellipsoid: ae 6.378137000000000e+06 f 3.352810664747481e-03 frame ITRF_CIO_CONV_2010_SIMPLE_EOP -DEM tile: t0 latMin 7.854054356026650e-01 latStep 1.454441043328608e-05 latRows 6000 lonMin 1.745401974046496e-01 lonStep 1.454441043328608e-05 lonCols 6000 -DEM cell: t0 latIndex 1051 lonIndex 4137 elevation 1.309400956268308e+01 +DEM tile: t0 latMin 7.854054356026650e-01 latStep 1.454441043328608e-05 latRows 1850 lonMin 1.745401974046496e-01 lonStep 1.454441043328608e-05 lonCols 2950 +DEM cell: t0 latIndex 1051 lonIndex 2937 elevation 1.309400956268308e+01 DEM cell: t0 latIndex 1809 lonIndex 653 elevation 3.915338283287048e+03 DEM cell: t0 latIndex 1743 lonIndex 2713 elevation 3.241641450760227e+03 DEM cell: t0 latIndex 1744 lonIndex 2713 elevation 3.183645801580853e+03 @@ -42,4 +42,8 @@ DEM cell: t0 latIndex 1750 lonIndex 2691 elevation 2.046708412363307e+03 DEM cell: t0 latIndex 1751 lonIndex 2691 elevation 1.988712685290527e+03 DEM cell: t0 latIndex 1752 lonIndex 2690 elevation 1.767717871236589e+03 DEM cell: t0 latIndex 1752 lonIndex 2691 elevation 1.932716958217748e+03 -direct location result: latitude 8.108743132084988e-01 longitude 2.136723329659456e-01 elevation 2.015454838793325e+03 +DEM cell: t0 latIndex 1751 lonIndex 2689 elevation 1.977714519950358e+03 +DEM cell: t0 latIndex 1752 lonIndex 2689 elevation 1.812718784255430e+03 +DEM cell: t0 latIndex 1753 lonIndex 2689 elevation 1.752723048560503e+03 +DEM cell: t0 latIndex 1753 lonIndex 2690 elevation 1.771722139852736e+03 +direct location result: latitude 8.108879611499973e-01 longitude 2.136511932240912e-01 elevation 1.806659334316842e+03 diff --git a/src/test/resources/replay/replay-direct-loc-Issue376-02.txt b/src/test/resources/replay/replay-direct-loc-Issue376-02.txt index 72733be73e6d9a14d90a3cfd1bc53cda01da0b4d..193745fddbfa4d98d78071fc45317320c9394464 100644 --- a/src/test/resources/replay/replay-direct-loc-Issue376-02.txt +++ b/src/test/resources/replay/replay-direct-loc-Issue376-02.txt @@ -7,8 +7,8 @@ span: minDate 2018-11-17T09:28:09.75815400000000Z maxDate 2018-11-17T09:28:24.37 transform: index 5248 body r -1.582959385747423e-01 -8.877789928041023e-04 1.557391550098440e-04 -9.873913020806478e-01 Ω -1.314379578439253e-07 1.929883497315641e-09 -7.292103298515672e-05 ΩDot -1.238198063406674e-16 -4.429504278953000e-17 2.220223692809437e-19 spacecraft p -2.031142024066962e+06 2.632378682422574e+06 -6.241283006704280e+06 v 8.397013991525502e+03 -1.122240538848754e+04 -7.476888804772309e+03 a -5.680029219465155e+02 -2.953217064872529e+02 9.484900057803327e+01 r -4.473594211185816e-01 -2.560156449934148e-01 7.879614096264105e-01 3.368120466886735e-01 Ω 1.874199110824172e-03 6.297218887138226e-04 6.941311311658171e-04 ΩDot 2.110863271348145e-05 1.094333236463635e-04 -6.188132051280828e-06 algorithm: DUVENHAGE ellipsoid: ae 6.378137000000000e+06 f 3.352810664747481e-03 frame ITRF_CIO_CONV_2010_SIMPLE_EOP -DEM tile: t0 latMin 7.854054356026650e-01 latStep 1.454441043328608e-05 latRows 6000 lonMin 1.745401974046496e-01 lonStep 1.454441043328608e-05 lonCols 6000 -DEM cell: t0 latIndex 1051 lonIndex 4137 elevation 1.309400956268308e+01 +DEM tile: t0 latMin 7.854054356026650e-01 latStep 1.454441043328608e-05 latRows 1850 lonMin 1.745401974046496e-01 lonStep 1.454441043328608e-05 lonCols 2950 +DEM cell: t0 latIndex 1051 lonIndex 2937 elevation 1.309400956268308e+01 DEM cell: t0 latIndex 1809 lonIndex 653 elevation 3.915338283287048e+03 DEM cell: t0 latIndex 1611 lonIndex 2905 elevation 2.683570229905023e+03 DEM cell: t0 latIndex 1612 lonIndex 2905 elevation 2.659575158110089e+03 @@ -45,4 +45,6 @@ DEM cell: t0 latIndex 1597 lonIndex 2866 elevation 2.091603812329271e+03 DEM cell: t0 latIndex 1598 lonIndex 2866 elevation 2.054608623253123e+03 DEM cell: t0 latIndex 1599 lonIndex 2865 elevation 1.847616058349609e+03 DEM cell: t0 latIndex 1599 lonIndex 2866 elevation 1.838613434176975e+03 -direct location result: latitude 8.086486919600299e-01 longitude 2.162109977595155e-01 elevation 2.040458228825512e+03 +DEM cell: t0 latIndex 1598 lonIndex 2864 elevation 1.985613877612813e+03 +DEM cell: t0 latIndex 1599 lonIndex 2864 elevation 1.872618682522244e+03 +direct location result: latitude 8.086569515781713e-01 longitude 2.161986944259714e-01 elevation 1.912154442728379e+03 diff --git a/src/test/resources/replay/replay-direct-loc-Issue376-03.txt b/src/test/resources/replay/replay-direct-loc-Issue376-03.txt index b6b1a0b797154d89eed8f235dad16741c1bb6ab7..7853cc5c920c3805fe49cc2e9f9efa6e979c0ad2 100644 --- a/src/test/resources/replay/replay-direct-loc-Issue376-03.txt +++ b/src/test/resources/replay/replay-direct-loc-Issue376-03.txt @@ -9,8 +9,8 @@ span: minDate 2018-11-17T09:28:09.75815400000000Z maxDate 2018-11-17T09:28:24.37 transform: index 9366 body r -1.584446506666181e-01 -8.881578177468675e-04 1.564888965877765e-04 -9.873674490087516e-01 Ω -1.314379583538120e-07 1.929883314912744e-09 -7.292103298515580e-05 ΩDot -1.238180701885198e-16 -4.429300681876970e-17 2.220189200053709e-19 spacecraft p -1.997175450486062e+06 2.586441579861389e+06 -6.271423934028421e+06 v 8.113280864301501e+03 -1.114024972785023e+04 -7.189075879755639e+03 a -1.053681313757033e+03 -1.503500666930414e+03 -2.459309668330822e+02 r -4.479168627946637e-01 -2.570042078686272e-01 7.890099484043995e-01 3.328402356700476e-01 Ω 1.817311260304385e-03 6.600167203271428e-04 7.119941113907730e-04 ΩDot 4.061126512029496e-05 1.694535855585867e-04 2.046888666103640e-04 algorithm: DUVENHAGE ellipsoid: ae 6.378137000000000e+06 f 3.352810664747481e-03 frame ITRF_CIO_CONV_2010_SIMPLE_EOP -DEM tile: t0 latMin 7.854054356026650e-01 latStep 1.454441043328608e-05 latRows 6000 lonMin 1.745401974046496e-01 lonStep 1.454441043328608e-05 lonCols 6000 -DEM cell: t0 latIndex 1051 lonIndex 4137 elevation 1.309400956268308e+01 +DEM tile: t0 latMin 7.854054356026650e-01 latStep 1.454441043328608e-05 latRows 1850 lonMin 1.745401974046496e-01 lonStep 1.454441043328608e-05 lonCols 2950 +DEM cell: t0 latIndex 1051 lonIndex 2937 elevation 1.309400956268308e+01 DEM cell: t0 latIndex 1809 lonIndex 653 elevation 3.915338283287048e+03 DEM cell: t0 latIndex 1248 lonIndex 2816 elevation 1.597661494047886e+03 DEM cell: t0 latIndex 1249 lonIndex 2816 elevation 1.603667936647203e+03 @@ -67,7 +67,9 @@ DEM cell: t0 latIndex 1242 lonIndex 2787 elevation 1.053714592147954e+03 DEM cell: t0 latIndex 1243 lonIndex 2787 elevation 1.076721007775370e+03 direct location result: latitude 8.034857669188987e-01 longitude 2.149854849334069e-01 elevation 6.876149051242718e+02 direct location: date 2018-11-17T09:28:19.12459483660332Z position 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 los 1.674948750587419e-03 -1.457123926920459e-02 9.998924309808744e-01 lightTime false aberration false refraction false -direct location result: latitude 8.034823539452234e-01 longitude 2.149911720557955e-01 elevation 7.409412497822065e+02 +DEM cell: t0 latIndex 1243 lonIndex 2779 elevation 6.157463116992526e+02 +DEM cell: t0 latIndex 1244 lonIndex 2779 elevation 5.807527198861440e+02 +direct location result: latitude 8.034854772265824e-01 longitude 2.149864448298378e-01 elevation 6.912515480966839e+02 direct location: date 2018-11-17T09:28:19.12459483660332Z position 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 los 1.674917457576505e-03 -1.457437451670205e-02 9.998923853390211e-01 lightTime false aberration false refraction false direct location result: latitude 8.034781401708480e-01 longitude 2.149980710325160e-01 elevation 8.070092894686161e+02 direct location: date 2018-11-17T09:28:19.12459483660332Z position 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00 los 1.674886170278741e-03 -1.457750977938711e-02 9.998923396871029e-01 lightTime false aberration false refraction false