diff --git a/pom.xml b/pom.xml
index 997060c7404fc83201ac2f10cbf81cc88e7c3d61..d5c44551a9ae3954c496e16311cb23570169fc9d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -461,7 +461,6 @@
         <artifactId>maven-javadoc-plugin</artifactId>
         <version>${rugged.maven-javadoc-plugin.version}</version>
         <configuration>
-          <overview>${basedir}/core/src/main/java/org/orekit/rugged/overview.html</overview>
           <links>
             <link>http://docs.oracle.com/javase/8/docs/api/</link>
             <link>https://hipparchus.org/apidocs/</link>
diff --git a/src/main/java/org/orekit/rugged/api/Rugged.java b/src/main/java/org/orekit/rugged/api/Rugged.java
index 2b0bef298a42497a73e03821485b75c5333b231a..7335cf55501f11eb49604c02846a0e4a224f299e 100644
--- a/src/main/java/org/orekit/rugged/api/Rugged.java
+++ b/src/main/java/org/orekit/rugged/api/Rugged.java
@@ -67,6 +67,7 @@ import org.orekit.utils.ParameterDriver;
 /** Main class of Rugged library API.
  * @see RuggedBuilder
  * @author Luc Maisonobe
+ * @author Guylaine Prat
  */
 public class Rugged {
 
@@ -425,8 +426,8 @@ public class Rugged {
      * are only an example and should be adjusted depending on mission needs.
      * </p>
      * @param sensorName name of the line  sensor
-     * @param latitude ground point latitude
-     * @param longitude ground point longitude
+     * @param latitude ground point latitude (rad)
+     * @param longitude ground point longitude (rad)
      * @param minLine minimum line number
      * @param maxLine maximum line number
      * @return date at which ground point is seen by line sensor
@@ -508,8 +509,8 @@ public class Rugged {
      * are only an example and should be adjusted depending on mission needs.
      * </p>
      * @param sensorName name of the line  sensor
-     * @param latitude ground point latitude
-     * @param longitude ground point longitude
+     * @param latitude ground point latitude (rad)
+     * @param longitude ground point longitude (rad)
      * @param minLine minimum line number
      * @param maxLine maximum line number
      * @return sensor pixel seeing ground point, or null if ground point cannot
diff --git a/src/main/java/org/orekit/rugged/api/RuggedBuilder.java b/src/main/java/org/orekit/rugged/api/RuggedBuilder.java
index 59d372e05043e485c62f5b1ad871add7beec4beb..1c8b32a94ec417fd04bdc5d02af7106e287cc9db 100644
--- a/src/main/java/org/orekit/rugged/api/RuggedBuilder.java
+++ b/src/main/java/org/orekit/rugged/api/RuggedBuilder.java
@@ -85,6 +85,7 @@ import org.orekit.utils.TimeStampedPVCoordinates;
  * @see <a href="https://en.wikipedia.org/wiki/Builder_pattern">Builder pattern (wikipedia)</a>
  * @see <a href="https://en.wikipedia.org/wiki/Fluent_interface">Fluent interface (wikipedia)</a>
  * @author Luc Maisonobe
+ * @author Guylaine Prat
  */
 public class RuggedBuilder {
 
@@ -97,7 +98,7 @@ public class RuggedBuilder {
     /** Updater used to load Digital Elevation Model tiles. */
     private TileUpdater tileUpdater;
 
-    /** Constant elevation over ellipsoid.
+    /** Constant elevation over ellipsoid (m).
      * used only with {@link AlgorithmId#CONSTANT_ELEVATION_OVER_ELLIPSOID. */
     private double constantElevation;
 
@@ -110,10 +111,10 @@ public class RuggedBuilder {
     /** End of search time span. */
     private AbsoluteDate maxDate;
 
-    /** Step to use for inertial frame to body frame transforms cache computations. */
+    /** Step to use for inertial frame to body frame transforms cache computations (s). */
     private double tStep;
 
-    /** OvershootTolerance tolerance in seconds allowed for {@code minDate} and {@code maxDate} overshooting. */
+    /** OvershootTolerance tolerance in seconds allowed for {@code minDate} and {@code maxDate} overshooting (s). */
     private double overshootTolerance;
 
     /** Inertial frame for position/velocity/attitude. */
@@ -140,7 +141,7 @@ public class RuggedBuilder {
     /** Propagator for position/velocity/attitude. */
     private Propagator pvaPropagator;
 
-    /** Step to use for inertial/Earth/spacraft transforms interpolations. */
+    /** Step to use for inertial/Earth/spacraft transforms interpolations (s). */
     private double iStep;
 
     /** Number of points to use for inertial/Earth/spacraft transforms interpolations. */
@@ -297,7 +298,7 @@ public class RuggedBuilder {
      * AlgorithmId#CONSTANT_ELEVATION_OVER_ELLIPSOID CONSTANT_ELEVATION_OVER_ELLIPSOID}.
      * If it is called for another algorithm, the elevation set here will be ignored.
      * </p>
-     * @param constantElevation constant elevation to use
+     * @param constantElevation constant elevation to use (m)
      * @return the builder instance
      * @see #setAlgorithm(AlgorithmId)
      * @see #getConstantElevation()
@@ -337,8 +338,8 @@ public class RuggedBuilder {
      * </p>
      * @param minDate start of search time span
      * @param maxDate end of search time span
-     * @param tStep step to use for inertial frame to body frame transforms cache computations
-     * @param overshootTolerance tolerance in seconds allowed for {@code minDate} and {@code maxDate} overshooting
+     * @param tStep step to use for inertial frame to body frame transforms cache computations (s)
+     * @param overshootTolerance tolerance in seconds allowed for {@code minDate} and {@code maxDate} overshooting (s)
      * @return the builder instance
      * @see #setTrajectoryAndTimeSpan(InputStream)
      * @see #getMinDate()
@@ -476,7 +477,7 @@ public class RuggedBuilder {
      * <em>must</em> be used together with the {@link #setTimeSpan(AbsoluteDate, AbsoluteDate, double, double)}
      * but should <em>not</em> be mixed with {@link #setTrajectoryAndTimeSpan(InputStream)}.
      * </p>
-     * @param interpolationStep step to use for inertial/Earth/spacraft transforms interpolations
+     * @param interpolationStep step to use for inertial/Earth/spacraft transforms interpolations (s)
      * @param interpolationNumber number of points to use for inertial/Earth/spacraft transforms interpolations
      * @param pvFilter filter for derivatives from the sample to use in position/velocity interpolation
      * @param aFilter filter for derivatives from the sample to use in attitude interpolation
diff --git a/src/main/java/org/orekit/rugged/raster/TileUpdater.java b/src/main/java/org/orekit/rugged/raster/TileUpdater.java
index 2943f16a73946dd80dc7dd007017cad859725bea..43bf954e35909d29565bac2d393171423c845ff0 100644
--- a/src/main/java/org/orekit/rugged/raster/TileUpdater.java
+++ b/src/main/java/org/orekit/rugged/raster/TileUpdater.java
@@ -24,7 +24,8 @@ import org.orekit.rugged.errors.RuggedException;
  * the image processing mission-specific layer, thus allowing
  * the Rugged library to access the Digital Elevation Model data.
  * </p>
- *  * @author Luc Maisonobe
+ * @author Luc Maisonobe
+ * @author Guylaine Prat
  */
 public interface TileUpdater {
 
@@ -76,8 +77,8 @@ public interface TileUpdater {
            latitudeStep, longitudeStep, latitudeRows, longitudeColumns)} call.
      *   </li>
      * </ul>
-     * @param latitude latitude that must be covered by the tile
-     * @param longitude longitude that must be covered by the tile
+     * @param latitude latitude that must be covered by the tile (rad)
+     * @param longitude longitude that must be covered by the tile (rad)
      * @param tile to update
      * @exception RuggedException if tile cannot be updated
      */
diff --git a/src/main/java/org/orekit/rugged/raster/UpdatableTile.java b/src/main/java/org/orekit/rugged/raster/UpdatableTile.java
index 0e38a7f71dca2df99656daf25f32ac65797e1dda..52c421f2b3c3675d0accedd058243fa189b92cf6 100644
--- a/src/main/java/org/orekit/rugged/raster/UpdatableTile.java
+++ b/src/main/java/org/orekit/rugged/raster/UpdatableTile.java
@@ -20,14 +20,15 @@ import org.orekit.rugged.errors.RuggedException;
 
 /** Interface representing one tile of a raster Digital Elevation Model.
  * @author Luc Maisonobe
+ * @author Guylaine Prat
  */
 public interface UpdatableTile {
 
     /** Set the tile global geometry.
-     * @param minLatitude minimum latitude
-     * @param minLongitude minimum longitude
-     * @param latitudeStep step in latitude (size of one raster element)
-     * @param longitudeStep step in longitude (size of one raster element)
+     * @param minLatitude minimum latitude (rad)
+     * @param minLongitude minimum longitude (rad)
+     * @param latitudeStep step in latitude (size of one raster element) (rad)
+     * @param longitudeStep step in longitude (size of one raster element) (rad)
      * @param latitudeRows number of latitude rows
      * @param longitudeColumns number of longitude columns
      * @exception RuggedException if tile is empty (zero rows or columns)
diff --git a/src/main/java/org/orekit/rugged/utils/ExtendedEllipsoid.java b/src/main/java/org/orekit/rugged/utils/ExtendedEllipsoid.java
index a90dd050a9b6fe0a418860e7ff779780444b1582..6ce1a013fcc08508e54f1267558dc1e59185d377 100644
--- a/src/main/java/org/orekit/rugged/utils/ExtendedEllipsoid.java
+++ b/src/main/java/org/orekit/rugged/utils/ExtendedEllipsoid.java
@@ -47,7 +47,7 @@ public class ExtendedEllipsoid extends OneAxisEllipsoid {
     private final double b2;
 
     /** Simple constructor.
-     * @param ae equatorial radius
+     * @param ae equatorial radius (m)
      * @param f the flattening (f = (a-b)/a)
      * @param bodyFrame body frame related to body shape
      * @see org.orekit.frames.FramesFactory#getITRF(org.orekit.utils.IERSConventions, boolean)
@@ -75,13 +75,13 @@ public class ExtendedEllipsoid extends OneAxisEllipsoid {
     }
 
     /** Get point at some latitude along a pixel line of sight.
-     * @param position cell position (in body frame)
+     * @param position cell position (in body frame) (m)
      * @param los pixel line-of-sight, not necessarily normalized (in body frame)
-     * @param latitude latitude with respect to ellipsoid
-     * @param closeReference reference point used to select the closest solution
+     * @param latitude latitude with respect to ellipsoid (rad)
+     * @param closeReference reference point used to select the closest solution 
      * when there are two points at the desired latitude along the line, it should
-     * be close to los surface intersection
-     * @return point at latitude
+     * be close to los surface intersection (m)
+     * @return point at latitude (m)
      * @exception RuggedException if no such point exists
      */
     public Vector3D pointAtLatitude(final Vector3D position, final Vector3D los,
@@ -161,10 +161,10 @@ public class ExtendedEllipsoid extends OneAxisEllipsoid {
     }
 
     /** Get point at some longitude along a pixel line of sight.
-     * @param position cell position (in body frame)
+     * @param position cell position (in body frame) (m)
      * @param los pixel line-of-sight, not necessarily normalized (in body frame)
-     * @param longitude longitude with respect to ellipsoid
-     * @return point at longitude
+     * @param longitude longitude with respect to ellipsoid (rad)
+     * @return point at longitude (m)
      * @exception RuggedException if no such point exists
      */
     public Vector3D pointAtLongitude(final Vector3D position, final Vector3D los, final double longitude)
@@ -186,10 +186,10 @@ public class ExtendedEllipsoid extends OneAxisEllipsoid {
     }
 
     /** Get point on ground along a pixel line of sight.
-     * @param position cell position (in body frame)
+     * @param position cell position (in body frame) (m)
      * @param los pixel line-of-sight, not necessarily normalized (in body frame)
      * @param centralLongitude reference longitude lc such that the point longitude will
-     * be normalized between lc-Ï€ and lc+Ï€
+     * be normalized between lc-Ï€ and lc+Ï€ (rad)
      * @return point on ground
      * @exception RuggedException if no such point exists (typically line-of-sight missing body)
      */
@@ -212,10 +212,10 @@ public class ExtendedEllipsoid extends OneAxisEllipsoid {
     }
 
     /** Get point at some altitude along a pixel line of sight.
-     * @param position cell position (in body frame)
+     * @param position cell position (in body frame) (m)
      * @param los pixel line-of-sight, not necessarily normalized (in body frame)
-     * @param altitude altitude with respect to ellipsoid
-     * @return point at altitude
+     * @param altitude altitude with respect to ellipsoid (m)
+     * @return point at altitude (m)
      * @exception RuggedException if no such point exists (typically too negative altitude)
      */
     public Vector3D pointAtAltitude(final Vector3D position, final Vector3D los, final double altitude)
@@ -321,11 +321,11 @@ public class ExtendedEllipsoid extends OneAxisEllipsoid {
     }
 
     /** Transform a cartesian point to a surface-relative point.
-     * @param point cartesian point
+     * @param point cartesian point (m)
      * @param frame frame in which cartesian point is expressed
      * @param date date of the computation (used for frames conversions)
      * @param centralLongitude reference longitude lc such that the point longitude will
-     * be normalized between lc-Ï€ and lc+Ï€
+     * be normalized between lc-Ï€ and lc+Ï€ (rad)
      * @return point at the same location but as a surface-relative point
      * @exception OrekitException if point cannot be converted to body frame
      */
diff --git a/src/main/java/org/orekit/rugged/utils/SpacecraftToObservedBody.java b/src/main/java/org/orekit/rugged/utils/SpacecraftToObservedBody.java
index 461613edbe7a280b030f1625fe1dcbe6f1a951ed..90e74131cb2ba80213f4f2d1e3a9260346d44096 100644
--- a/src/main/java/org/orekit/rugged/utils/SpacecraftToObservedBody.java
+++ b/src/main/java/org/orekit/rugged/utils/SpacecraftToObservedBody.java
@@ -37,6 +37,7 @@ import org.orekit.utils.TimeStampedPVCoordinates;
 
 /** Provider for observation transforms.
  * @author Luc Maisonobe
+ * @author Guylaine Prat
  */
 public class SpacecraftToObservedBody implements Serializable {
 
@@ -110,7 +111,7 @@ public class SpacecraftToObservedBody implements Serializable {
             if (minPVDate.durationFrom(minDate) > overshootTolerance) {
                 throw new RuggedException(RuggedMessages.OUT_OF_TIME_RANGE, minDate, minPVDate, maxPVDate);
             }
-            if (maxDate.durationFrom(maxDate) > overshootTolerance) {
+            if (maxDate.durationFrom(maxPVDate) > overshootTolerance) {
                 throw new RuggedException(RuggedMessages.OUT_OF_TIME_RANGE, maxDate, minPVDate, maxPVDate);
             }
 
diff --git a/src/site/markdown/tutorials/direct-location-with-DEM.md b/src/site/markdown/tutorials/direct-location-with-DEM.md
index 0ce8751e921bbd9f8c12a1f938625ca23d4b630f..0375fec32cbf77f3fef618205ba703b5dcefeb1a 100644
--- a/src/site/markdown/tutorials/direct-location-with-DEM.md
+++ b/src/site/markdown/tutorials/direct-location-with-DEM.md
@@ -39,7 +39,7 @@ The class `VolcanicConeElevationUpdater` implements the interface `TileUpdater`
 
 Here's the source code of the class `VolcanicConeElevationUpdater` :
 
-import org.hipparchus.util.FastMath;
+    import org.hipparchus.util.FastMath;
     import org.orekit.rugged.raster.TileUpdater;
     import org.orekit.rugged.raster.UpdatableTile;
     import org.orekit.bodies.GeodeticPoint;
@@ -88,7 +88,7 @@ import org.hipparchus.util.FastMath;
 
 ### Important notes on DEM tiles :
 
-* Ground point elevation are obtained by bilinear interpolation between 4 neighbouring cells. There is no specific algorithm for border management. As a consequence, a point falling on the border of the tile is considered outside. DEM tiles must be overlapping by at least one line/column in all directions, in a similar way as for the SRTM DEMs. 
+* Ground point elevation are obtained by bilinear interpolation between 4 neighbouring cells. There is no specific algorithm for border management. As a consequence, a point falling on the border of the tile is considered outside. **DEM tiles must be overlapping by at least one line/column in all directions**, in a similar way as for the SRTM DEMs. 
 
 * In Rugged terminology, the minimum latitude and longitude correspond to the centre of the farthest Southwest cell of the DEM. Be careful if using GDAL to pass the correct information as there is half a pixel shift with respect to the lower left corner coordinates in gdalinfo.
 
@@ -169,4 +169,4 @@ In a similar way as in the first tutorial [DirectLocation](./direct-location.htm
     }
 
 ## Source code
-The source code is available in DirectLocationWithDEM.java
+The source code is available in DirectLocationWithDEM.java (package fr.cs.examples under src/tutorials)
diff --git a/src/site/markdown/tutorials/direct-location.md b/src/site/markdown/tutorials/direct-location.md
index 0866e25b8294db303cfcc5511e4fb4a3ec80e186..076c1c87f5bc7c0d1cdc7d53bc93ad7c178ba5a8 100644
--- a/src/site/markdown/tutorials/direct-location.md
+++ b/src/site/markdown/tutorials/direct-location.md
@@ -55,7 +55,7 @@ The raw viewing direction of pixel i with respect to the instrument is defined b
 
     List<Vector3D> rawDirs = new ArrayList<Vector3D>();
     for (int i = 0; i < 2000; i++) {
-        //20° field of view, 2000 pixels
+        // 20° field of view, 2000 pixels
         rawDirs.add(new Vector3D(0d, i*FastMath.toRadians(20)/2000d, 1d));
     }
 
@@ -161,7 +161,7 @@ Each attitude sample (quaternion, time) is added to the list,
 
 where, for instance, gpsDateAsString is set to "2009-12-11T10:49:55.899994"
 
-### Position and velocities
+### Positions and velocities
 
 
 Similarly the positions and velocities will be set in a list of `TimeStampedPVCoordinates`. Before being
@@ -307,11 +307,17 @@ Finally everything is set to do some real work. Let's try to locate a point on E
 for upper left point (first line, first pixel): 
 
     import org.orekit.bodies.GeodeticPoint;
-    Vector3D position = lineSensor.getPosition(); // This returns a zero vector since we set the relative position of the sensor w.r.T the satellite to 0.
+    Vector3D position = lineSensor.getPosition(); // This returns a zero vector since we set the relative position of the sensor w.r.t. the satellite to 0.
     AbsoluteDate firstLineDate = lineSensor.getDate(0);
     Vector3D los = lineSensor.getLOS(firstLineDate, 0);
     GeodeticPoint upLeftPoint = rugged.directLocation(firstLineDate, position, los);
 
+The line number can have negative values; the associated date must belong to the time span given when building Rugged with setTimeSpan(acquisitionStartDate, acquisitionStopDate,...).
+Otherwise a RuggedException will be thrown.
+
+The pixel number must be given between 0 and the (Sensor pixel size – 1); in our example between 0 and 1999.
+Otherwise an ArrayIndexOutOfBoundsException will be thrown.
+
 ## Source code 
 
-The source code is available in DirectLocation.java
+The source code is available in DirectLocation.java (package fr.cs.examples under src/tutorials)
diff --git a/src/site/markdown/tutorials/inverse-location.md b/src/site/markdown/tutorials/inverse-location.md
index 42bb4a550efcb57fdbd21899c08c91d6a88c99f4..daa4ff0bd97fb71946ec42b4d1e43db7d4bd57ad 100644
--- a/src/site/markdown/tutorials/inverse-location.md
+++ b/src/site/markdown/tutorials/inverse-location.md
@@ -19,10 +19,10 @@ The aim of this tutorial is to compute the inverse location of a point on Earth
 We will also explain how to find the date at which sensor sees a ground point, which is a kind of inverse location only focusing on date.
 
 ## Inverse location of a point on Earth
-The initialisation of Rugged is similar as in the [Direct location](direct-location.html) tutorial up to the addition of the lines sensor.
+The initialization of Rugged is similar as in the [Direct location](direct-location.html) tutorial up to rugged initialization..
 
 ### Point defined by its latitude, longitude and altitude
-Once Rugged initialised, one can compute the line number and the pixel number of a point defined by its Geodetic coordinates:
+Once Rugged initialized, one can compute the line number and the pixel number of a point defined by its Geodetic coordinates:
 
     import org.orekit.bodies.GeodeticPoint;
     import org.orekit.rugged.linesensor.SensorPixel;
@@ -30,7 +30,7 @@ Once Rugged initialised, one can compute the line number and the pixel number of
     SensorPixel sensorPixel = rugged.inverseLocation(sensorName, gp, minLine, maxLine);
 where minLine (maxLine, respectively) is the minimum line number for the search interval (maximum line number, respectively). 
 
-The inverse location will give the sensor pixel number and the associated line number seeing the point. In case the point cannot be seen between the prescribed line numbers, the return result is null. No exception will be thrown in this particular case.
+The inverse location will give the sensor pixel number and the associated line number seeing the point on ground. *In case the point cannot be seen between the prescribed line numbers, the return result is null. No exception will be thrown in this particular case*.
    
 ### Point defined by its latitude and longitude (no altitude)
 Similarly, one can compute the line number and the pixel number of a point defined solely by its latitude en longitude. The altitude will be determined automatically with the DEM.
@@ -38,7 +38,7 @@ Similarly, one can compute the line number and the pixel number of a point defin
      SensorPixel sensorPixel = rugged.inverseLocation(sensorName, latitude, longitude, minLine, maxLine);
 
 ## Date location 
-Once Rugged initialised, one can compute the date at which sensor sees a point on Earth.
+Once Rugged initialized, one can compute the date at which sensor sees a point on Earth.
 
 ### Point defined by its latitude, longitude and altitude
 For a point defined by its Geodetic coordinates:
@@ -50,5 +50,27 @@ Similarly, for a point defined solely by its latitude en longitude (altitude det
 
      AbsoluteDate dateLine = rugged.dateLocation(sensorName, latitude, longitude, minLine, maxLine);
 
+## Determine the min/max lines interval
+Rugged provides a way to determine a **very** rough estimation of the line using only the position-velocities of the satellite. It assumes the position-velocities are regular enough and without holes.
+
+     OneAxisEllipsoid oneAxisEllipsoid = ruggedBuilder.getEllipsoid();
+     Frame pvFrame = ruggedBuilder.getInertialFrame();
+     RoughVisibilityEstimator roughVisibilityEstimator= new RoughVisibilityEstimator(oneAxisEllipsoid, pvFrame, satellitePVList);
+
+One can compute the approximated line with the rough visibility estimator:
+
+     AbsoluteDate roughLineDate = roughVisibilityEstimator.estimateVisibility(gp);
+     double roughLine = lineSensor.getLine(roughLineDate);
+
+The result will never be null, but may be really far from reality if ground point is away from trajectory.
+With this rough line, taken some margin around (for instance 100), one can initialize the min/max lines as search boundaries for inverse location, taken into account sensor min and max lines:
+
+     int minLineRough = (int) FastMath.max(FastMath.floor(roughLine - margin), sensorMinLine);
+     int maxLineRough = (int) FastMath.min(FastMath.floor(roughLine + margin), sensorMaxLine);
+
+then one can compute the inverse location:
+
+     SensorPixel sensorPixel = rugged.inverseLocation(sensorName, gp, minLineRough, maxLineRough);
+
 ## Source code
-The source code is available in InverseLocation.java 
+The source code is available in InverseLocation.java (package fr.cs.examples under src/tutorials)
diff --git a/src/test/java/org/orekit/rugged/raster/RandomLandscapeUpdater.java b/src/test/java/org/orekit/rugged/raster/RandomLandscapeUpdater.java
index 9d66ee7f436eed8ec3895c0452e0f1a27a9e161d..67fcfa8c58c4662f41c0b7344d5f71a027a71a98 100644
--- a/src/test/java/org/orekit/rugged/raster/RandomLandscapeUpdater.java
+++ b/src/test/java/org/orekit/rugged/raster/RandomLandscapeUpdater.java
@@ -35,10 +35,6 @@ public class RandomLandscapeUpdater implements TileUpdater {
         throws MathIllegalArgumentException {
 
         if (!ArithmeticUtils.isPowerOfTwo(n - 1)) {
-        	
-// TODO hipparchus migration : change to the appropriate message 
-//            throw new MathIllegalArgumentException(LocalizedFormats.SIMPLE_MESSAGE,
-//                                                   "tile size must be a power of two plus one");
             throw new MathIllegalArgumentException(LocalizedCoreFormats.SIMPLE_MESSAGE,
                                                    "tile size must be a power of two plus one");
         }
diff --git a/src/test/java/org/orekit/rugged/utils/SpacecraftToObservedBodyTest.java b/src/test/java/org/orekit/rugged/utils/SpacecraftToObservedBodyTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..23145b9a548b46092ea24473c048e5f1eb778192
--- /dev/null
+++ b/src/test/java/org/orekit/rugged/utils/SpacecraftToObservedBodyTest.java
@@ -0,0 +1,153 @@
+/* Copyright 2013-2016 CS Systèmes d'Information
+ * Licensed to CS Systèmes d'Information (CS) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * CS licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.orekit.rugged.utils;
+
+import java.io.File;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+import org.hipparchus.geometry.euclidean.threed.Vector3D;
+import org.hipparchus.util.FastMath;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+import org.orekit.bodies.BodyShape;
+import org.orekit.data.DataProvidersManager;
+import org.orekit.data.DirectoryCrawler;
+import org.orekit.errors.OrekitException;
+import org.orekit.frames.FramesFactory;
+import org.orekit.orbits.Orbit;
+import org.orekit.rugged.TestUtils;
+import org.orekit.rugged.errors.RuggedException;
+import org.orekit.rugged.errors.RuggedMessages;
+import org.orekit.rugged.linesensor.LineSensor;
+import org.orekit.rugged.linesensor.LinearLineDatation;
+import org.orekit.rugged.los.LOSBuilder;
+import org.orekit.time.AbsoluteDate;
+import org.orekit.utils.AngularDerivativesFilter;
+import org.orekit.utils.CartesianDerivativesFilter;
+import org.orekit.utils.Constants;
+import org.orekit.utils.TimeStampedAngularCoordinates;
+import org.orekit.utils.TimeStampedPVCoordinates;
+
+
+@RunWith(Parameterized.class)
+public class SpacecraftToObservedBodyTest {
+
+	@Parameters
+	public static Collection<Object[]> data() {
+		return Arrays.asList(new Object[][] {
+			// Run multiple times the tests, constructing this class with the following parameters
+			{ +10, +1., -1., +1}, { -1., -10., -1., +1}, { -1., +1., +15., +1}, { -1., +1., -1., -15.}
+		});
+	}
+	   
+	// configuration of the run : shift of date for PV and Q (min and max values)
+	private double shiftPVmin;
+	private double shiftPVmax;
+	private double shiftQmin;
+	private double shiftQmax;
+
+	
+    @Test
+    public void testIssue256() throws RuggedException, OrekitException {
+        
+        AbsoluteDate minSensorDate = sensor.getDate(0);
+        AbsoluteDate maxSensorDate = sensor.getDate(2000);
+        
+        AbsoluteDate minPVdate = minSensorDate.shiftedBy(this.shiftPVmin);
+        AbsoluteDate maxPVdate = maxSensorDate.shiftedBy(this.shiftPVmax);
+        List<TimeStampedPVCoordinates> pvList = TestUtils.orbitToPV(orbit, earth, minPVdate, maxPVdate, 0.25);
+        
+        AbsoluteDate minQdate = minSensorDate.shiftedBy(this.shiftQmin);
+        AbsoluteDate maxQdate = maxSensorDate.shiftedBy(this.shiftQmax);
+        List<TimeStampedAngularCoordinates> qList = TestUtils.orbitToQ(orbit, earth, minQdate, maxQdate, 0.25);
+        
+        try {
+        
+    	SpacecraftToObservedBody sToOb = new SpacecraftToObservedBody(FramesFactory.getEME2000(), earth.getBodyFrame(),
+                minSensorDate, maxSensorDate, 0.01,
+                5.0,
+                pvList,
+                8, CartesianDerivativesFilter.USE_PV,
+                qList,
+                2, AngularDerivativesFilter.USE_R);
+        Assert.fail("an exception should have been thrown");
+    	
+        } catch (RuggedException re){
+            Assert.assertEquals(RuggedMessages.OUT_OF_TIME_RANGE, re.getSpecifier());
+        }        	
+    }
+
+    
+	public SpacecraftToObservedBodyTest(double shiftPVmin, double shiftPVmax, double shiftQmin, double shiftQmax) {
+		super();
+		this.shiftPVmin = shiftPVmin;
+		this.shiftPVmax = shiftPVmax;
+		this.shiftQmin = shiftQmin;
+		this.shiftQmax = shiftQmax;
+	}
+	
+
+    @Before
+    public void setUp() {
+        try {
+
+            String path = getClass().getClassLoader().getResource("orekit-data").toURI().getPath();
+            DataProvidersManager.getInstance().addProvider(new DirectoryCrawler(new File(path)));
+
+            earth = TestUtils.createEarth();
+            orbit = TestUtils.createOrbit(Constants.EIGEN5C_EARTH_MU);
+            
+            // build lists of pixels regularly spread on a perfect plane
+            final Vector3D position  = new Vector3D(1.5, Vector3D.PLUS_I);
+            final Vector3D normal    = Vector3D.PLUS_I;
+            final Vector3D fovCenter = Vector3D.PLUS_K;
+            final Vector3D cross     = Vector3D.crossProduct(normal, fovCenter);
+            
+            final List<Vector3D> los = new ArrayList<Vector3D>();
+            for (int i = -1000; i <= 1000; ++i) {
+                final double alpha = i * 0.17 / 1000;
+                los.add(new Vector3D(FastMath.cos(alpha), fovCenter, FastMath.sin(alpha), cross));
+            }
+            sensor = new LineSensor("perfect line", new LinearLineDatation(AbsoluteDate.J2000_EPOCH, 0.0, 1.0 / 1.5e-3),
+                                    position, new LOSBuilder(los).build());
+            
+
+        } catch (OrekitException oe) {
+            Assert.fail(oe.getLocalizedMessage());
+        } catch (URISyntaxException use) {
+            Assert.fail(use.getLocalizedMessage());
+        }
+    }
+
+    @After
+    public void tearDown() {
+    }
+
+	private BodyShape  earth = null;
+	private Orbit      orbit = null;
+	private LineSensor sensor = null;
+	
+}
diff --git a/src/tutorials/java/fr/cs/examples/DirectLocation.java b/src/tutorials/java/fr/cs/examples/DirectLocation.java
index 23b08d063025723060f2b7671a6414c5fa740836..dbe241b33179fca9f510dead0855bf54a6350eb9 100644
--- a/src/tutorials/java/fr/cs/examples/DirectLocation.java
+++ b/src/tutorials/java/fr/cs/examples/DirectLocation.java
@@ -64,10 +64,14 @@ public class DirectLocation {
             File orekitData = new File(home, "orekit-data");
             DataProvidersManager.getInstance().addProvider(new DirectoryCrawler(orekitData));
 
+            // Sensor's definition 
+            // ===================
+            // Line of sight
+            // -------------            
             // The raw viewing direction of pixel i with respect to the instrument is defined by the vector:
             List<Vector3D> rawDirs = new ArrayList<Vector3D>();
             for (int i = 0; i < 2000; i++) {
-                //20° field of view, 2000 pixels
+                // 20° field of view, 2000 pixels
                 rawDirs.add(new Vector3D(0d, i*FastMath.toRadians(20)/2000d, 1d));
             }
 
@@ -78,14 +82,23 @@ public class DirectLocation {
 
             TimeDependentLOS lineOfSight = losBuilder.build();
 
+            // Datation model 
+            // --------------
             // We use Orekit for handling time and dates, and Rugged for defining the datation model:
             TimeScale gps = TimeScalesFactory.getGPS();
             AbsoluteDate absDate = new AbsoluteDate("2009-12-11T16:59:30.0", gps);
             LinearLineDatation lineDatation = new LinearLineDatation(absDate, 1d, 20); 
 
+            // Line sensor
+            // -----------
             // With the LOS and the datation now defined, we can initialize a line sensor object in Rugged:
             LineSensor lineSensor = new LineSensor("mySensor", lineDatation, Vector3D.ZERO, lineOfSight);
 
+            // Satellite position, velocity and attitude
+            // =========================================
+
+            // Reference frames
+            // ----------------
             // In our application, we simply need to know the name of the frames we are working with. Positions and
             // velocities are given in the ITRF terrestrial frame, while the quaternions are given in EME2000
             // inertial frame.  
@@ -93,8 +106,9 @@ public class DirectLocation {
             boolean simpleEOP = true; // we don't want to compute tiny tidal effects at millimeter level
             Frame itrf = FramesFactory.getITRF(IERSConventions.IERS_2010, simpleEOP);
 
+            // Satellite attitude
+            // ------------------
             ArrayList<TimeStampedAngularCoordinates> satelliteQList = new ArrayList<TimeStampedAngularCoordinates>();
-            ArrayList<TimeStampedPVCoordinates> satellitePVList = new ArrayList<TimeStampedPVCoordinates>();
 
             addSatelliteQ(gps, satelliteQList, "2009-12-11T16:58:42.592937", -0.340236d, 0.333952d, -0.844012d, -0.245684d);
             addSatelliteQ(gps, satelliteQList, "2009-12-11T16:59:06.592937", -0.354773d, 0.329336d, -0.837871d, -0.252281d);
@@ -107,6 +121,10 @@ public class DirectLocation {
             addSatelliteQ(gps, satelliteQList, "2009-12-11T17:01:54.592937", -0.452976d, 0.294556d, -0.787571d, -0.296279d);
             addSatelliteQ(gps, satelliteQList, "2009-12-11T17:02:18.592937", -0.466207d, 0.28935d, -0.779516d, -0.302131d);
 
+            // Positions and velocities
+            // ------------------------
+            ArrayList<TimeStampedPVCoordinates> satellitePVList = new ArrayList<TimeStampedPVCoordinates>();
+
             addSatellitePV(gps, eme2000, itrf, satellitePVList, "2009-12-11T16:58:42.592937", -726361.466d, -5411878.485d, 4637549.599d, -2463.635d, -4447.634d, -5576.736d);
             addSatellitePV(gps, eme2000, itrf, satellitePVList, "2009-12-11T16:59:04.192937", -779538.267d, -5506500.533d, 4515934.894d, -2459.848d, -4312.676d, -5683.906d);
             addSatellitePV(gps, eme2000, itrf, satellitePVList, "2009-12-11T16:59:25.792937", -832615.368d, -5598184.195d, 4392036.13d, -2454.395d, -4175.564d, -5788.201d);
@@ -119,6 +137,8 @@ public class DirectLocation {
             addSatellitePV(gps, eme2000, itrf, satellitePVList, "2009-12-11T17:01:56.992937", -1198331.706d, -6154056.146d, 3466192.446d, -2369.401d, -3161.764d, -6433.531d);
             addSatellitePV(gps, eme2000, itrf, satellitePVList, "2009-12-11T17:02:18.592937", -1249311.381d, -6220723.191d, 3326367.397d, -2350.574d, -3010.159d, -6513.056d);
 
+            // Rugged initialization
+            // ---------------------
             Rugged rugged = new RuggedBuilder().
                     setAlgorithm(AlgorithmId.IGNORE_DEM_USE_ELLIPSOID). 
                     setEllipsoid(EllipsoidId.WGS84, BodyRotatingFrameId.ITRF).
@@ -129,6 +149,8 @@ public class DirectLocation {
                                   addLineSensor(lineSensor).
                                   build();
 
+            // Direct location of a single sensor pixel (first line, first pixel)
+            // ------------------------------------------------------------------
             Vector3D position = lineSensor.getPosition(); // This returns a zero vector since we set the relative position of the sensor w.r.T the satellite to 0.
             AbsoluteDate firstLineDate = lineSensor.getDate(0);
             Vector3D los = lineSensor.getLOS(firstLineDate, 0);
@@ -154,8 +176,8 @@ public class DirectLocation {
                                   double px, double py, double pz, double vx, double vy, double vz)
         throws OrekitException {
         AbsoluteDate ephemerisDate = new AbsoluteDate(absDate, gps);
-        Vector3D position = new Vector3D(px, py, pz);
-        Vector3D velocity = new Vector3D(vx, vy, vz);
+        Vector3D position = new Vector3D(px, py, pz); // in ITRF, unit: m 
+        Vector3D velocity = new Vector3D(vx, vy, vz); // in ITRF, unit: m/s
         PVCoordinates pvITRF = new PVCoordinates(position, velocity);
         Transform transform = itrf.getTransformTo(eme2000, ephemerisDate);
         PVCoordinates pvEME2000 = transform.transformPVCoordinates(pvITRF); 
@@ -165,7 +187,7 @@ public class DirectLocation {
     private static void addSatelliteQ(TimeScale gps, ArrayList<TimeStampedAngularCoordinates> satelliteQList, String absDate,
                                       double q0, double q1, double q2, double q3) {
         AbsoluteDate attitudeDate = new AbsoluteDate(absDate, gps);
-        Rotation rotation = new Rotation(q0, q1, q2, q3, true);
+        Rotation rotation = new Rotation(q0, q1, q2, q3, true);  // q0 is the scalar term
         TimeStampedAngularCoordinates pair =
                 new TimeStampedAngularCoordinates(attitudeDate, rotation, Vector3D.ZERO, Vector3D.ZERO);
         satelliteQList.add(pair);
diff --git a/src/tutorials/java/fr/cs/examples/DirectLocationWithDEM.java b/src/tutorials/java/fr/cs/examples/DirectLocationWithDEM.java
index ebbddc7371eed50d273f6018c738de9ff7489146..8b3f187ffa77d09982fa04b66a9f1985a44c233e 100644
--- a/src/tutorials/java/fr/cs/examples/DirectLocationWithDEM.java
+++ b/src/tutorials/java/fr/cs/examples/DirectLocationWithDEM.java
@@ -67,10 +67,14 @@ public class DirectLocationWithDEM {
             File orekitData = new File(home, "orekit-data");
             DataProvidersManager.getInstance().addProvider(new DirectoryCrawler(orekitData));
 
+            // Sensor's definition 
+            // ===================
+            // Line of sight
+            // -------------            
             // The raw viewing direction of pixel i with respect to the instrument is defined by the vector:
             List<Vector3D> rawDirs = new ArrayList<Vector3D>();
             for (int i = 0; i < 2000; i++) {
-                //20° field of view, 2000 pixels
+                // 20° field of view, 2000 pixels
                 rawDirs.add(new Vector3D(0d, i*FastMath.toRadians(20)/2000d, 1d));
             }
 
@@ -81,14 +85,23 @@ public class DirectLocationWithDEM {
 
             TimeDependentLOS lineOfSight = losBuilder.build();
 
+            // Datation model 
+            // --------------
             // We use Orekit for handling time and dates, and Rugged for defining the datation model:
             TimeScale gps = TimeScalesFactory.getGPS();
             AbsoluteDate absDate = new AbsoluteDate("2009-12-11T16:59:30.0", gps);
             LinearLineDatation lineDatation = new LinearLineDatation(absDate, 1d, 20); 
 
-            // With the LOS and the datation now defined , we can initialize a line sensor object in Rugged:
+            // Line sensor
+            // -----------
+            // With the LOS and the datation now defined, we can initialize a line sensor object in Rugged:
             LineSensor lineSensor = new LineSensor("mySensor", lineDatation, Vector3D.ZERO, lineOfSight);
 
+            // Satellite position, velocity and attitude
+            // =========================================
+
+            // Reference frames
+            // ----------------
             // In our application, we simply need to know the name of the frames we are working with. Positions and
             // velocities are given in the ITRF terrestrial frame, while the quaternions are given in EME2000
             // inertial frame.  
@@ -96,8 +109,9 @@ public class DirectLocationWithDEM {
             boolean simpleEOP = true; // we don't want to compute tiny tidal effects at millimeter level
             Frame itrf = FramesFactory.getITRF(IERSConventions.IERS_2010, simpleEOP);
 
+            // Satellite attitude
+            // ------------------
             ArrayList<TimeStampedAngularCoordinates> satelliteQList = new ArrayList<TimeStampedAngularCoordinates>();
-            ArrayList<TimeStampedPVCoordinates> satellitePVList = new ArrayList<TimeStampedPVCoordinates>();
 
             addSatelliteQ(gps, satelliteQList, "2009-12-11T16:58:42.592937", -0.340236d, 0.333952d, -0.844012d, -0.245684d);
             addSatelliteQ(gps, satelliteQList, "2009-12-11T16:59:06.592937", -0.354773d, 0.329336d, -0.837871d, -0.252281d);
@@ -109,7 +123,11 @@ public class DirectLocationWithDEM {
             addSatelliteQ(gps, satelliteQList, "2009-12-11T17:01:30.592937", -0.439505d, 0.299722d, -0.795442d, -0.290301d);
             addSatelliteQ(gps, satelliteQList, "2009-12-11T17:01:54.592937", -0.452976d, 0.294556d, -0.787571d, -0.296279d);
             addSatelliteQ(gps, satelliteQList, "2009-12-11T17:02:18.592937", -0.466207d, 0.28935d, -0.779516d, -0.302131d);
- 
+
+            // Positions and velocities
+            // ------------------------
+            ArrayList<TimeStampedPVCoordinates> satellitePVList = new ArrayList<TimeStampedPVCoordinates>();
+
             addSatellitePV(gps, eme2000, itrf, satellitePVList, "2009-12-11T16:58:42.592937", -726361.466d, -5411878.485d, 4637549.599d, -2463.635d, -4447.634d, -5576.736d);
             addSatellitePV(gps, eme2000, itrf, satellitePVList, "2009-12-11T16:59:04.192937", -779538.267d, -5506500.533d, 4515934.894d, -2459.848d, -4312.676d, -5683.906d);
             addSatellitePV(gps, eme2000, itrf, satellitePVList, "2009-12-11T16:59:25.792937", -832615.368d, -5598184.195d, 4392036.13d, -2454.395d, -4175.564d, -5788.201d);
@@ -122,6 +140,8 @@ public class DirectLocationWithDEM {
             addSatellitePV(gps, eme2000, itrf, satellitePVList, "2009-12-11T17:01:56.992937", -1198331.706d, -6154056.146d, 3466192.446d, -2369.401d, -3161.764d, -6433.531d);
             addSatellitePV(gps, eme2000, itrf, satellitePVList, "2009-12-11T17:02:18.592937", -1249311.381d, -6220723.191d, 3326367.397d, -2350.574d, -3010.159d, -6513.056d);
 
+            // Rugged initialization
+            // ---------------------
             Rugged rugged = new RuggedBuilder().
                     setAlgorithm(AlgorithmId.DUVENHAGE).
                     setDigitalElevationModel(new VolcanicConeElevationUpdater(new GeodeticPoint(FastMath.toRadians(37.58),
@@ -139,6 +159,8 @@ public class DirectLocationWithDEM {
                                   addLineSensor(lineSensor).
                                   build();
 
+            // Direct location of a single sensor pixel (first line, first pixel)
+            // ------------------------------------------------------------------
             Vector3D position = lineSensor.getPosition(); // This returns a zero vector since we set the relative position of the sensor w.r.T the satellite to 0.
             AbsoluteDate firstLineDate = lineSensor.getDate(0);
             Vector3D los = lineSensor.getLOS(firstLineDate, 0);
@@ -164,8 +186,8 @@ public class DirectLocationWithDEM {
                                   double px, double py, double pz, double vx, double vy, double vz)
         throws OrekitException {
         AbsoluteDate ephemerisDate = new AbsoluteDate(absDate, gps);
-        Vector3D position = new Vector3D(px, py, pz);
-        Vector3D velocity = new Vector3D(vx, vy, vz);
+        Vector3D position = new Vector3D(px, py, pz); // in ITRF, unit: m 
+        Vector3D velocity = new Vector3D(vx, vy, vz); // in ITRF, unit: m/s
         PVCoordinates pvITRF = new PVCoordinates(position, velocity);
         Transform transform = itrf.getTransformTo(eme2000, ephemerisDate);        
         PVCoordinates pvEME2000 = transform.transformPVCoordinates(pvITRF); 
@@ -176,7 +198,7 @@ public class DirectLocationWithDEM {
     private static void addSatelliteQ(TimeScale gps, ArrayList<TimeStampedAngularCoordinates> satelliteQList, String absDate,
                                       double q0, double q1, double q2, double q3) {
         AbsoluteDate attitudeDate = new AbsoluteDate(absDate, gps);
-        Rotation rotation = new Rotation(q0, q1, q2, q3, true);
+        Rotation rotation = new Rotation(q0, q1, q2, q3, true);  // q0 is the scalar term
         TimeStampedAngularCoordinates pair =
                 new TimeStampedAngularCoordinates(attitudeDate, rotation, Vector3D.ZERO, Vector3D.ZERO);
         satelliteQList.add(pair);
diff --git a/src/tutorials/java/fr/cs/examples/InverseLocation.java b/src/tutorials/java/fr/cs/examples/InverseLocation.java
index e8c2df5a46d97f97d1b8d5b83633a5cf9e02822f..5520bff0e2e028a29586aa0ceb6d9682a5dd556d 100644
--- a/src/tutorials/java/fr/cs/examples/InverseLocation.java
+++ b/src/tutorials/java/fr/cs/examples/InverseLocation.java
@@ -25,6 +25,7 @@ import org.hipparchus.geometry.euclidean.threed.Rotation;
 import org.hipparchus.geometry.euclidean.threed.Vector3D;
 import org.hipparchus.util.FastMath;
 import org.orekit.bodies.GeodeticPoint;
+import org.orekit.bodies.OneAxisEllipsoid;
 import org.orekit.data.DataProvidersManager;
 import org.orekit.data.DirectoryCrawler;
 import org.orekit.errors.OrekitException;
@@ -44,6 +45,7 @@ import org.orekit.rugged.linesensor.SensorPixel;
 import org.orekit.rugged.los.FixedRotation;
 import org.orekit.rugged.los.LOSBuilder;
 import org.orekit.rugged.los.TimeDependentLOS;
+import org.orekit.rugged.utils.RoughVisibilityEstimator;
 import org.orekit.time.AbsoluteDate;
 import org.orekit.time.TimeScale;
 import org.orekit.time.TimeScalesFactory;
@@ -65,10 +67,14 @@ public class InverseLocation {
             File orekitData = new File(home, "orekit-data");
             DataProvidersManager.getInstance().addProvider(new DirectoryCrawler(orekitData));
 
+            // Sensor's definition 
+            // ===================
+            // Line of sight
+            // -------------            
             // The raw viewing direction of pixel i with respect to the instrument is defined by the vector:
             List<Vector3D> rawDirs = new ArrayList<Vector3D>();
             for (int i = 0; i < 2000; i++) {
-                //20° field of view, 2000 pixels
+                // 20° field of view, 2000 pixels
                 rawDirs.add(new Vector3D(0d, i*FastMath.toRadians(20)/2000d, 1d));
             }
 
@@ -79,17 +85,24 @@ public class InverseLocation {
 
             TimeDependentLOS lineOfSight = losBuilder.build();
 
+            // Datation model 
+            // --------------
             // We use Orekit for handling time and dates, and Rugged for defining the datation model:
             TimeScale gps = TimeScalesFactory.getGPS();
             AbsoluteDate absDate = new AbsoluteDate("2009-12-11T16:59:30.0", gps);
             LinearLineDatation lineDatation = new LinearLineDatation(absDate, 1d, 20); 
 
+            // Line sensor
+            // -----------
             // With the LOS and the datation now defined , we can initialize a line sensor object in Rugged:
             String sensorName = "mySensor";
             LineSensor lineSensor = new LineSensor(sensorName, lineDatation, Vector3D.ZERO, lineOfSight);
 
-            
-            
+            // Satellite position, velocity and attitude
+            // =========================================
+
+            // Reference frames
+            // ----------------
             // In our application, we simply need to know the name of the frames we are working with. Positions and
             // velocities are given in the ITRF terrestrial frame, while the quaternions are given in EME2000
             // inertial frame.  
@@ -97,8 +110,9 @@ public class InverseLocation {
             boolean simpleEOP = true; // we don't want to compute tiny tidal effects at millimeter level
             Frame itrf = FramesFactory.getITRF(IERSConventions.IERS_2010, simpleEOP);
 
+            // Satellite attitude
+            // ------------------
             ArrayList<TimeStampedAngularCoordinates> satelliteQList = new ArrayList<TimeStampedAngularCoordinates>();
-            ArrayList<TimeStampedPVCoordinates> satellitePVList = new ArrayList<TimeStampedPVCoordinates>();
 
             addSatelliteQ(gps, satelliteQList, "2009-12-11T16:58:42.592937", -0.340236d, 0.333952d, -0.844012d, -0.245684d);
             addSatelliteQ(gps, satelliteQList, "2009-12-11T16:59:06.592937", -0.354773d, 0.329336d, -0.837871d, -0.252281d);
@@ -111,6 +125,10 @@ public class InverseLocation {
             addSatelliteQ(gps, satelliteQList, "2009-12-11T17:01:54.592937", -0.452976d, 0.294556d, -0.787571d, -0.296279d);
             addSatelliteQ(gps, satelliteQList, "2009-12-11T17:02:18.592937", -0.466207d, 0.28935d, -0.779516d, -0.302131d);
 
+            // Positions and velocities
+            // ------------------------
+            ArrayList<TimeStampedPVCoordinates> satellitePVList = new ArrayList<TimeStampedPVCoordinates>();
+
             addSatellitePV(gps, eme2000, itrf, satellitePVList, "2009-12-11T16:58:42.592937", -726361.466d, -5411878.485d, 4637549.599d, -2463.635d, -4447.634d, -5576.736d);
             addSatellitePV(gps, eme2000, itrf, satellitePVList, "2009-12-11T16:59:04.192937", -779538.267d, -5506500.533d, 4515934.894d, -2459.848d, -4312.676d, -5683.906d);
             addSatellitePV(gps, eme2000, itrf, satellitePVList, "2009-12-11T16:59:25.792937", -832615.368d, -5598184.195d, 4392036.13d, -2454.395d, -4175.564d, -5788.201d);
@@ -123,37 +141,77 @@ public class InverseLocation {
             addSatellitePV(gps, eme2000, itrf, satellitePVList, "2009-12-11T17:01:56.992937", -1198331.706d, -6154056.146d, 3466192.446d, -2369.401d, -3161.764d, -6433.531d);
             addSatellitePV(gps, eme2000, itrf, satellitePVList, "2009-12-11T17:02:18.592937", -1249311.381d, -6220723.191d, 3326367.397d, -2350.574d, -3010.159d, -6513.056d);
 
-            Rugged rugged = new RuggedBuilder().
-                    setAlgorithm(AlgorithmId.IGNORE_DEM_USE_ELLIPSOID). 
-                    setEllipsoid(EllipsoidId.WGS84, BodyRotatingFrameId.ITRF).
-                    setTimeSpan(absDate, absDate.shiftedBy(60.0), 0.01, 5 / lineSensor.getRate(0)). 
-                    setTrajectory(InertialFrameId.EME2000,
+            // Rugged initialization
+            // ---------------------
+            RuggedBuilder ruggedBuilder = new RuggedBuilder();
+            
+            ruggedBuilder.setAlgorithm(AlgorithmId.IGNORE_DEM_USE_ELLIPSOID);
+            ruggedBuilder.setEllipsoid(EllipsoidId.WGS84, BodyRotatingFrameId.ITRF);
+            ruggedBuilder.setTimeSpan(absDate, absDate.shiftedBy(60.0), 0.01, 5 / lineSensor.getRate(0));
+            ruggedBuilder.setTrajectory(InertialFrameId.EME2000,
                                   satellitePVList, 4, CartesianDerivativesFilter.USE_P,
                                   satelliteQList,  4,  AngularDerivativesFilter.USE_R).
-                                  addLineSensor(lineSensor).
-                                  build();
+                                  addLineSensor(lineSensor);
+                    
+            Rugged rugged = ruggedBuilder.build();
 
+            // Inverse location of a Geodetic Point
+            // ------------------------------------
             // Point defined by its latitude, longitude and altitude
             double latitude = FastMath.toRadians(37.585);
             double longitude = FastMath.toRadians(-96.949);
             double altitude = 0.0d;
+            // For a GeodeticPoint : angles are given in radians and altitude in meters
             GeodeticPoint gp = new GeodeticPoint(latitude, longitude, altitude);
 
             // Search the sensor pixel seeing point
+            // ....................................
+            // interval of lines where to search the point
             int minLine = 0;
             int maxLine = 100;
             SensorPixel sensorPixel = rugged.inverseLocation(sensorName, gp, minLine, maxLine);
+            
             // we need to test if the sensor pixel is found in the prescribed lines otherwise the sensor pixel is null
+            // Be careful: no exception is thrown if the pixel is not found
             if (sensorPixel != null){
+            	// The pixel was found
                 System.out.format(Locale.US, "Sensor Pixel found : line = %5.3f, pixel = %5.3f %n", sensorPixel.getLineNumber(), sensorPixel.getPixelNumber());
             } else {
+            	// The pixel was not found: set to null 
                 System.out.println("Sensor Pixel is null: point cannot be seen between the prescribed line numbers\n");
             }
             
             // Find the date at which the sensor sees the ground point
+            // .......................................................
             AbsoluteDate dateLine = rugged.dateLocation(sensorName, gp, minLine, maxLine);
             System.out.println("Date at which the sensor sees the ground point : " + dateLine);
             
+            
+            // How to find min and max lines ? with the RoughVisibilityEstimator
+            // -------------------------------
+            // Create a RoughVisibilityEstimator for inverse location
+            OneAxisEllipsoid oneAxisEllipsoid = ruggedBuilder.getEllipsoid();
+            Frame pvFrame = ruggedBuilder.getInertialFrame();
+            
+            // Initialize the RoughVisibilityEstimator
+            RoughVisibilityEstimator roughVisibilityEstimator = new RoughVisibilityEstimator(oneAxisEllipsoid, pvFrame, satellitePVList); 
+            
+            // Compute the approximated line with a rough estimator    
+            AbsoluteDate roughLineDate = roughVisibilityEstimator.estimateVisibility(gp);
+            double roughLine = lineSensor.getLine(roughLineDate);
+            
+            // Compute the min / max lines interval using a margin around the roughLine
+            int sensorMinLine= 0;
+            int sensorMaxLine = 1000;
+            
+            int margin = 100;
+            int minLineRough = (int) FastMath.max(roughLine - margin, sensorMinLine);
+            int maxLineRough = (int) FastMath.min(roughLine + margin, sensorMaxLine);
+            SensorPixel sensorPixelRoughLine = rugged.inverseLocation(sensorName, gp, minLineRough, maxLineRough);
+
+            System.out.format(Locale.US, "Rough line found = %5.1f; InverseLocation gives (margin of %d around rough line): line = %5.3f, pixel = %5.3f %n", roughLine, margin, sensorPixelRoughLine.getLineNumber(), sensorPixel.getPixelNumber());
+
+            
         } catch (OrekitException oe) {
             System.err.println(oe.getLocalizedMessage());
             System.exit(1);
@@ -170,8 +228,8 @@ public class InverseLocation {
                                   double px, double py, double pz, double vx, double vy, double vz)
         throws OrekitException {
         AbsoluteDate ephemerisDate = new AbsoluteDate(absDate, gps);
-        Vector3D position = new Vector3D(px, py, pz);
-        Vector3D velocity = new Vector3D(vx, vy, vz);
+        Vector3D position = new Vector3D(px, py, pz); // in ITRF, unit: m 
+        Vector3D velocity = new Vector3D(vx, vy, vz); // in ITRF, unit: m/s
         PVCoordinates pvITRF = new PVCoordinates(position, velocity);
         Transform transform = itrf.getTransformTo(eme2000, ephemerisDate);
         PVCoordinates pvEME2000 = transform.transformPVCoordinates(pvITRF); 
@@ -181,7 +239,7 @@ public class InverseLocation {
     private static void addSatelliteQ(TimeScale gps, ArrayList<TimeStampedAngularCoordinates> satelliteQList, String absDate,
                                       double q0, double q1, double q2, double q3) {
         AbsoluteDate attitudeDate = new AbsoluteDate(absDate, gps);
-        Rotation rotation = new Rotation(q0, q1, q2, q3, true);
+        Rotation rotation = new Rotation(q0, q1, q2, q3, true);  // q0 is the scalar term
         TimeStampedAngularCoordinates pair =
                 new TimeStampedAngularCoordinates(attitudeDate, rotation, Vector3D.ZERO, Vector3D.ZERO);
         satelliteQList.add(pair);