diff --git a/core/src/main/java/org/orekit/rugged/api/FixedLOS.java b/core/src/main/java/org/orekit/rugged/api/FixedLOS.java
new file mode 100644
index 0000000000000000000000000000000000000000..5c24f8d0e43bb26a2b7eac70755b2d3f1516e91c
--- /dev/null
+++ b/core/src/main/java/org/orekit/rugged/api/FixedLOS.java
@@ -0,0 +1,43 @@
+/* Copyright 2013-2014 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.api;
+
+import org.apache.commons.math3.geometry.euclidean.threed.Vector3D;
+import org.orekit.time.AbsoluteDate;
+
+/** Line-of-sight which does not depends on time.
+ * @see LineSensor
+ * @author Luc Maisonobe
+ */
+public class FixedLOS implements TimeDependentLOS {
+
+    /** Fixed direction for los. */
+    final Vector3D los;
+
+    /** Simple constructor.
+     * @param los fixed direction for the line of sight
+     */
+    public FixedLOS(final Vector3D los) {
+        this.los = los;
+    }
+
+    /** {@inheritDoc}} */
+    public Vector3D getLOS(AbsoluteDate date) {
+        return los;
+    }
+
+}
diff --git a/core/src/main/java/org/orekit/rugged/api/LineSensor.java b/core/src/main/java/org/orekit/rugged/api/LineSensor.java
index f0bfd9a8cb919a6d7117a330ae4e90b95a658e99..6971fa4fe288568bd4b3c66d22d9045818218d04 100644
--- a/core/src/main/java/org/orekit/rugged/api/LineSensor.java
+++ b/core/src/main/java/org/orekit/rugged/api/LineSensor.java
@@ -39,7 +39,7 @@ public class LineSensor {
     private final Vector3D position;
 
     /** Pixels lines-of-sight. */
-    private final Vector3D[] x;
+    private final List<TimeDependentLOS> los;
 
     /** Simple constructor.
      * @param name name of the sensor
@@ -48,17 +48,12 @@ public class LineSensor {
      * @param datationModel datation model
      */
     public LineSensor(final String name, final LineDatation datationModel,
-                      final Vector3D position, final List<Vector3D> los) {
+                      final Vector3D position, final List<TimeDependentLOS> los) {
 
         this.name          = name;
         this.datationModel = datationModel;
         this.position      = position;
-
-        // normalize lines-of-sight
-        this.x = new Vector3D[los.size()];
-        for (int i = 0; i < los.size(); ++i) {
-            x[i] = los.get(i).normalize();
-        }
+        this.los           = los;
 
     }
 
@@ -73,15 +68,16 @@ public class LineSensor {
      * @return number of pixels
      */
     public int getNbPixels() {
-        return x.length;
+        return los.size();
     }
 
-    /** Get the pixel normalized line-of-sight.
+    /** Get the pixel normalized line-of-sight at some date.
+     * @param date current date
      * @param i pixel index (must be between 0 and {@link #getNbPixels()}
      * @return pixel normalized line-of-sight
      */
-    public Vector3D getLos(final int i) {
-        return x[i];
+    public Vector3D getLos(final AbsoluteDate date, final int i) {
+        return los.get(i).getLOS(date).normalize();
     }
 
     /** Get the date.
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 d37d8bd482e7db93b2b3a7f0e99eb9ba22caee3c..e7bdde20bdcadd6b5b5557348c23fdc88fb169fa 100644
--- a/core/src/main/java/org/orekit/rugged/api/Rugged.java
+++ b/core/src/main/java/org/orekit/rugged/api/Rugged.java
@@ -742,7 +742,7 @@ public class Rugged {
         final GeodeticPoint[] gp = new GeodeticPoint[sensor.getNbPixels()];
         for (int i = 0; i < sensor.getNbPixels(); ++i) {
 
-            final Vector3D obsLInert = scToInert.transformVector(sensor.getLos(i));
+            final Vector3D obsLInert = scToInert.transformVector(sensor.getLos(date, i));
             final Vector3D lInert;
             if (aberrationOfLightCorrection) {
                 // apply aberration of light correction
@@ -765,7 +765,7 @@ public class Rugged {
             if (lightTimeCorrection) {
                 // compute DEM intersection with light time correction
                 final Vector3D  sP       = approximate.transformPosition(sensor.getPosition());
-                final Vector3D  sL       = approximate.transformVector(sensor.getLos(i));
+                final Vector3D  sL       = approximate.transformVector(sensor.getLos(date, i));
                 final Vector3D  eP1      = ellipsoid.transform(ellipsoid.pointOnGround(sP, sL, 0.0));
                 final double    deltaT1  = eP1.distance(sP) / Constants.SPEED_OF_LIGHT;
                 final Transform shifted1 = inertToBody.shiftedBy(-deltaT1);
@@ -1005,7 +1005,7 @@ public class Rugged {
                 new SensorPixelCrossing(sensor, planeCrossing.getMeanPlaneNormal(),
                                         crossingResult.getTargetDirection().toVector3D(),
                                         MAX_EVAL, COARSE_INVERSE_LOCALIZATION_ACCURACY);
-        final double coarsePixel = pixelCrossing.locatePixel();
+        final double coarsePixel = pixelCrossing.locatePixel(crossingResult.getDate());
         if (Double.isNaN(coarsePixel)) {
             // target is out of search interval
             return null;
@@ -1014,10 +1014,9 @@ public class Rugged {
         // fix line by considering the closest pixel exact position and line-of-sight
         // (this pixel might point towards a direction slightly above or below the mean sensor plane)
         final int      lowIndex        = FastMath.max(0, FastMath.min(sensor.getNbPixels() - 2, (int) FastMath.floor(coarsePixel)));
-        final Vector3D lowLOS          = sensor.getLos(lowIndex);
-        final Vector3D highLOS         = sensor.getLos(lowIndex + 1);
+        final Vector3D lowLOS          = sensor.getLos(crossingResult.getDate(), lowIndex);
+        final Vector3D highLOS         = sensor.getLos(crossingResult.getDate(), lowIndex + 1);
         final Vector3D localZ          = Vector3D.crossProduct(lowLOS, highLOS);
-        final Vector3D localY          = Vector3D.crossProduct(localZ, lowLOS);
         final DerivativeStructure beta = FieldVector3D.angle(crossingResult.getTargetDirection(), localZ);
         final double   deltaL          = (0.5 * FastMath.PI - beta.getValue()) / beta.getPartialDerivative(1);
         final double   fixedLine       = crossingResult.getLine() + deltaL;
@@ -1025,11 +1024,17 @@ public class Rugged {
                                                       crossingResult.getTargetDirection().getY().taylor(deltaL),
                                                       crossingResult.getTargetDirection().getZ().taylor(deltaL)).normalize();
 
+        // fix neighbouring pixels
+        final AbsoluteDate fixedDate   = sensor.getDate(fixedLine);
+        final Vector3D fixedX          = sensor.getLos(fixedDate, lowIndex);
+        final Vector3D fixedZ          = Vector3D.crossProduct(fixedX, sensor.getLos(fixedDate, lowIndex + 1));
+        final Vector3D fixedY          = Vector3D.crossProduct(fixedZ, fixedX);
+
         // fix pixel
-        final double pixelWidth = FastMath.atan2(Vector3D.dotProduct(highLOS,        localY),
-                                                 Vector3D.dotProduct(highLOS,        lowLOS));
-        final double alpha      = FastMath.atan2(Vector3D.dotProduct(fixedDirection, localY),
-                                                 Vector3D.dotProduct(fixedDirection, lowLOS));
+        final double pixelWidth = FastMath.atan2(Vector3D.dotProduct(highLOS,        fixedY),
+                                                 Vector3D.dotProduct(highLOS,        fixedX));
+        final double alpha      = FastMath.atan2(Vector3D.dotProduct(fixedDirection, fixedY),
+                                                 Vector3D.dotProduct(fixedDirection, fixedX));
         final double fixedPixel = lowIndex + alpha / pixelWidth;
 
         return new SensorPixel(fixedLine, fixedPixel);
diff --git a/core/src/main/java/org/orekit/rugged/api/SensorMeanPlaneCrossing.java b/core/src/main/java/org/orekit/rugged/api/SensorMeanPlaneCrossing.java
index 21a92acddcfaa885911a78d6261a208cba6c812e..a23434968881cea9d535c2e3d7215dc2f074be5a 100644
--- a/core/src/main/java/org/orekit/rugged/api/SensorMeanPlaneCrossing.java
+++ b/core/src/main/java/org/orekit/rugged/api/SensorMeanPlaneCrossing.java
@@ -101,16 +101,17 @@ class SensorMeanPlaneCrossing {
         this.accuracy                    = accuracy;
         this.scToBody                    = scToBody;
 
-        this.midLine               = 0.5 * (minLine + maxLine);
-        final AbsoluteDate midDate = sensor.getDate(midLine);
-        this.midBodyToInert        = scToBody.getBodyToInertial(midDate);
-        this.midScToInert          = scToBody.getScToInertial(midDate);
+        this.midLine                     = 0.5 * (minLine + maxLine);
+        final AbsoluteDate midDate       = sensor.getDate(midLine);
+        this.midBodyToInert              = scToBody.getBodyToInertial(midDate);
+        this.midScToInert                = scToBody.getScToInertial(midDate);
 
-        this.meanPlaneNormal = computeMeanPlaneNormal();
+        this.meanPlaneNormal             = computeMeanPlaneNormal(midDate);
 
     }
 
     /** Compute the plane containing origin that best fits viewing directions point cloud.
+     * @param midDate middle date
      * <p>
      * The normal is oriented such traversing pixels in increasing indices
      * order corresponds is consistent with trigonometric order (i.e.
@@ -118,14 +119,14 @@ class SensorMeanPlaneCrossing {
      * </p>
      * @return normal of the mean plane
      */
-    private Vector3D computeMeanPlaneNormal() {
+    private Vector3D computeMeanPlaneNormal(final AbsoluteDate midDate) {
 
         // build a centered data matrix
         // (for each viewing direction, we add both the direction and its
         //  opposite, thus ensuring the plane will contain origin)
         final RealMatrix matrix = MatrixUtils.createRealMatrix(3, 2 * sensor.getNbPixels());
         for (int i = 0; i < sensor.getNbPixels(); ++i) {
-            final Vector3D l = sensor.getLos(i);
+            final Vector3D l = sensor.getLos(midDate, i);
             matrix.setEntry(0, 2 * i,      l.getX());
             matrix.setEntry(1, 2 * i,      l.getY());
             matrix.setEntry(2, 2 * i,      l.getZ());
@@ -143,8 +144,8 @@ class SensorMeanPlaneCrossing {
         final Vector3D singularVector = new Vector3D(svd.getU().getColumn(2)).normalize();
 
         // check rotation order
-        final Vector3D first = sensor.getLos(0);
-        final Vector3D last  = sensor.getLos(sensor.getNbPixels() - 1);
+        final Vector3D first = sensor.getLos(midDate, 0);
+        final Vector3D last  = sensor.getLos(midDate, sensor.getNbPixels() - 1);
         if (Vector3D.dotProduct(singularVector, Vector3D.crossProduct(first, last)) >= 0) {
             return singularVector;
         } else {
@@ -182,6 +183,9 @@ class SensorMeanPlaneCrossing {
     /** Container for mean plane crossing result. */
     public static class CrossingResult {
 
+        /** Crossing date. */
+        private final AbsoluteDate crossingDate;
+
         /** Crossing line. */
         private final double crossingLine;
 
@@ -189,15 +193,24 @@ class SensorMeanPlaneCrossing {
         private final FieldVector3D<DerivativeStructure> targetDirection;
 
         /** Simple constructor.
+         * @param crossingDate crossing date
          * @param crossingLine crossing line
          * @param targetDirection target direction in spacecraft frame
          */
-        private CrossingResult(final double crossingLine,
+        private CrossingResult(final AbsoluteDate crossingDate, final double crossingLine,
                                final FieldVector3D<DerivativeStructure> targetDirection) {
+            this.crossingDate    = crossingDate;
             this.crossingLine    = crossingLine;
             this.targetDirection = targetDirection;
         }
 
+        /** Get the crossing date.
+         * @return crossing date
+         */
+        public AbsoluteDate getDate() {
+            return crossingDate;
+        }
+
         /** Get the crossing line.
          * @return crossing line
          */
@@ -246,7 +259,7 @@ class SensorMeanPlaneCrossing {
             final double deltaL = (0.5 * FastMath.PI - beta.getValue()) / beta.getPartialDerivative(1);
             if (FastMath.abs(deltaL) <= accuracy) {
                 // return immediately, without doing any additional evaluation!
-                return new CrossingResult(crossingLine, targetDirection);
+                return new CrossingResult(sensor.getDate(crossingLine), crossingLine, targetDirection);
             }
             crossingLine += deltaL;
 
diff --git a/core/src/main/java/org/orekit/rugged/api/SensorPixelCrossing.java b/core/src/main/java/org/orekit/rugged/api/SensorPixelCrossing.java
index 6cd31e53edb56dc3e90b3bba6b0b7cda3eedd76e..157cbb1c1f67a786cd4443976c9198c5305a964f 100644
--- a/core/src/main/java/org/orekit/rugged/api/SensorPixelCrossing.java
+++ b/core/src/main/java/org/orekit/rugged/api/SensorPixelCrossing.java
@@ -24,6 +24,7 @@ import org.apache.commons.math3.exception.TooManyEvaluationsException;
 import org.apache.commons.math3.geometry.euclidean.threed.Vector3D;
 import org.apache.commons.math3.util.FastMath;
 import org.orekit.errors.OrekitExceptionWrapper;
+import org.orekit.time.AbsoluteDate;
 
 /** Class devoted to locate where ground point crosses a sensor line.
  * <p>
@@ -65,11 +66,12 @@ class SensorPixelCrossing {
     }
 
     /** Locate pixel along sensor line.
+     * @param date current date
      * @return pixel location ({@code Double.NaN} if the first and last
      * pixels of the line do not bracket a location)
      * @exception RuggedException if the maximum number of evaluations is exceeded
      */
-    public double locatePixel() throws RuggedException {
+    public double locatePixel(final AbsoluteDate date) throws RuggedException {
         try {
 
             // set up function evaluating to 0.0 where target matches pixel
@@ -77,7 +79,7 @@ class SensorPixelCrossing {
                 /** {@inheritDoc} */
                 @Override
                 public double value(final double x) throws OrekitExceptionWrapper {
-                    return Vector3D.angle(cross, getLOS(x)) - 0.5 * FastMath.PI;
+                    return Vector3D.angle(cross, getLOS(date, x)) - 0.5 * FastMath.PI;
                 }
             };
 
@@ -95,17 +97,19 @@ class SensorPixelCrossing {
     }
 
     /** Interpolate sensor pixels at some pixel index.
+     * @param date current date
      * @param x pixel index
      * @return interpolated direction for specified index
      */
-    private Vector3D getLOS(final double x) {
+    private Vector3D getLOS(final AbsoluteDate date, final double x) {
 
         // find surrounding pixels
         final int iInf = FastMath.max(0, FastMath.min(sensor.getNbPixels() - 2, (int) FastMath.floor(x)));
         final int iSup = iInf + 1;
 
         // interpolate
-        return new Vector3D(iSup - x, sensor.getLos(iInf), x - iInf, sensor.getLos(iSup)).normalize();
+        return new Vector3D(iSup - x, sensor.getLos(date, iInf),
+                            x - iInf, sensor.getLos(date, iSup)).normalize();
 
     }
 
diff --git a/core/src/main/java/org/orekit/rugged/api/TimeDependentLOS.java b/core/src/main/java/org/orekit/rugged/api/TimeDependentLOS.java
new file mode 100644
index 0000000000000000000000000000000000000000..d7f6014a141bba5a5d6c623e5275acaf2adb3e8a
--- /dev/null
+++ b/core/src/main/java/org/orekit/rugged/api/TimeDependentLOS.java
@@ -0,0 +1,34 @@
+/* Copyright 2013-2014 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.api;
+
+import org.apache.commons.math3.geometry.euclidean.threed.Vector3D;
+import org.orekit.time.AbsoluteDate;
+
+/** Interface representing a line-of-sight which depends on time.
+ * @see LineSensor
+ * @author Luc Maisonobe
+ */
+public interface TimeDependentLOS {
+
+    /** Get the line of sight for a given date.
+    * @param date date
+     * @return line of sight
+     */
+    Vector3D getLOS(AbsoluteDate date);
+
+}
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 fb2c2158fd271c3ba0e1e265fb276c01abae1ca1..b6a46d3a1287b66d6e29bbb81b4a5383312d7a92 100644
--- a/core/src/test/java/org/orekit/rugged/api/RuggedTest.java
+++ b/core/src/test/java/org/orekit/rugged/api/RuggedTest.java
@@ -303,8 +303,8 @@ public class RuggedTest {
         // position: 1.5m in front (+X) and 20 cm above (-Z) of the S/C center of mass
         // los: swath in the (YZ) plane, centered at +Z, ±10° aperture, 960 pixels
         Vector3D position = new Vector3D(1.5, 0, -0.2);
-        List<Vector3D> los = createLOSPerfectLine(Vector3D.PLUS_K, Vector3D.PLUS_I,
-                                       FastMath.toRadians(10.0), dimension);
+        List<TimeDependentLOS> los = createLOSPerfectLine(Vector3D.PLUS_K, Vector3D.PLUS_I,
+                                                          FastMath.toRadians(10.0), dimension);
 
         // linear datation model: at reference time we get line 1000, and the rate is one line every 1.5ms
         LineDatation lineDatation = new LinearLineDatation(crossing, dimension / 2, 1.0 / 1.5e-3);
@@ -384,8 +384,8 @@ public class RuggedTest {
         // position: 1.5m in front (+X) and 20 cm above (-Z) of the S/C center of mass
         // los: swath in the (YZ) plane, centered at +Z, ±10° aperture, 960 pixels
         Vector3D position = new Vector3D(1.5, 0, -0.2);
-        List<Vector3D> los = createLOSPerfectLine(Vector3D.PLUS_K, Vector3D.PLUS_I,
-                                       FastMath.toRadians(10.0), dimension);
+        List<TimeDependentLOS> los = createLOSPerfectLine(Vector3D.PLUS_K, Vector3D.PLUS_I,
+                                                          FastMath.toRadians(10.0), dimension);
 
         // linear datation model: at reference time we get line 200, and the rate is one line every 1.5ms
         LineDatation lineDatation = new LinearLineDatation(crossing, dimension / 2, 1.0 / 1.5e-3);
@@ -451,8 +451,8 @@ public class RuggedTest {
         // position: 1.5m in front (+X) and 20 cm above (-Z) of the S/C center of mass
         // los: swath in the (YZ) plane, centered at +Z, ±10° aperture, 960 pixels
         Vector3D position = new Vector3D(1.5, 0, -0.2);
-        List<Vector3D> los = createLOSPerfectLine(Vector3D.PLUS_K, Vector3D.PLUS_I,
-                                       FastMath.toRadians(10.0), dimension);
+        List<TimeDependentLOS> los = createLOSPerfectLine(Vector3D.PLUS_K, Vector3D.PLUS_I,
+                                                          FastMath.toRadians(10.0), dimension);
 
         // linear datation model: at reference time we get line 200, and the rate is one line every 1.5ms
         LineDatation lineDatation = new LinearLineDatation(crossing, dimension / 2, 1.0 / 1.5e-3);
@@ -506,9 +506,8 @@ public class RuggedTest {
         // 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 = createLOSPerfectLine(new Rotation(Vector3D.PLUS_I, FastMath.toRadians(50.0)).applyTo(Vector3D.PLUS_K),
-                                       Vector3D.PLUS_I,
-                                       FastMath.toRadians(1.0), dimension);
+        List<TimeDependentLOS> los = createLOSPerfectLine(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);
@@ -571,9 +570,8 @@ public class RuggedTest {
         // 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 = createLOSPerfectLine(new Rotation(Vector3D.PLUS_I, FastMath.toRadians(50.0)).applyTo(Vector3D.PLUS_K),
-                                       Vector3D.PLUS_I,
-                                       FastMath.toRadians(1.0), dimension);
+        List<TimeDependentLOS> los = createLOSPerfectLine(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);
@@ -599,7 +597,8 @@ public class RuggedTest {
 
         for (int i = 0; i < gpLine.length; ++i) {
             GeodeticPoint gpPixel =
-                    rugged.directLocalization(lineSensor.getDate(100), lineSensor.getPosition(), lineSensor.getLos(i));
+                    rugged.directLocalization(lineSensor.getDate(100), lineSensor.getPosition(),
+                                              lineSensor.getLos(lineSensor.getDate(100), 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);
@@ -624,9 +623,8 @@ public class RuggedTest {
         // 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 = createLOSPerfectLine(new Rotation(Vector3D.PLUS_I, FastMath.toRadians(50.0)).applyTo(Vector3D.PLUS_K),
-                                       Vector3D.PLUS_I,
-                                       FastMath.toRadians(1.0), dimension);
+        List<TimeDependentLOS> los = createLOSPerfectLine(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);
@@ -654,7 +652,8 @@ public class RuggedTest {
 
         for (int i = 0; i < gpLine.length; ++i) {
             GeodeticPoint gpPixel =
-                    rugged.directLocalization(lineSensor.getDate(100), lineSensor.getPosition(), lineSensor.getLos(i));
+                    rugged.directLocalization(lineSensor.getDate(100), lineSensor.getPosition(),
+                                              lineSensor.getLos(lineSensor.getDate(100), 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);
@@ -679,9 +678,8 @@ public class RuggedTest {
         // 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 = createLOSPerfectLine(new Rotation(Vector3D.PLUS_I, FastMath.toRadians(50.0)).applyTo(Vector3D.PLUS_K),
-                                       Vector3D.PLUS_I,
-                                       FastMath.toRadians(1.0), dimension);
+        List<TimeDependentLOS> los = createLOSPerfectLine(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);
@@ -741,9 +739,8 @@ public class RuggedTest {
         // 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 = createLOSPerfectLine(new Rotation(Vector3D.PLUS_I, FastMath.toRadians(50.0)).applyTo(Vector3D.PLUS_K),
-                                       Vector3D.PLUS_I,
-                                       FastMath.toRadians(1.0), dimension);
+        List<TimeDependentLOS> los = createLOSPerfectLine(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);
@@ -803,9 +800,8 @@ public class RuggedTest {
         // 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 = createLOSPerfectLine(new Rotation(Vector3D.PLUS_I, FastMath.toRadians(50.0)).applyTo(Vector3D.PLUS_K),
-                                       Vector3D.PLUS_I,
-                                       FastMath.toRadians(1.0), dimension);
+        List<TimeDependentLOS> los = createLOSPerfectLine(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);
@@ -850,9 +846,8 @@ public class RuggedTest {
         // 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 = createLOSPerfectLine(new Rotation(Vector3D.PLUS_I, FastMath.toRadians(50.0)).applyTo(Vector3D.PLUS_K),
-                                       Vector3D.PLUS_I,
-                                       FastMath.toRadians(1.0), dimension);
+        List<TimeDependentLOS> los = createLOSPerfectLine(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);
@@ -1001,10 +996,9 @@ public class RuggedTest {
             // 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 roughly at 50° roll (sensor-dependent), 2.6" per pixel
             Vector3D position = new Vector3D(1.5, 0, -0.2);
-            List<Vector3D> los = createLOSPerfectLine(new Rotation(Vector3D.PLUS_I,
-                                                        FastMath.toRadians(50.0 - 0.001 * i)).applyTo(Vector3D.PLUS_K),
-                                           Vector3D.PLUS_I,
-                                           FastMath.toRadians(dimension * 2.6 / 3600.0), dimension);
+            List<TimeDependentLOS> los = createLOSPerfectLine(new Rotation(Vector3D.PLUS_I,
+                                                                           FastMath.toRadians(50.0 - 0.001 * i)).applyTo(Vector3D.PLUS_K),
+                                                              Vector3D.PLUS_I, FastMath.toRadians(dimension * 2.6 / 3600.0), dimension);
 
             // linear datation model: at reference time we get roughly middle line, and the rate is one line every 1.5ms
             LineDatation lineDatation = new LinearLineDatation(crossing, i + dimension / 2, 1.0 / 1.5e-3);
@@ -1146,35 +1140,35 @@ public class RuggedTest {
                                    satellitePVList, 8, CartesianDerivativesFilter.USE_PV,
                                    satelliteQList, 8, AngularDerivativesFilter.USE_R, 0.001);
 
-        List<Vector3D> lineOfSight = new ArrayList<Vector3D>();
-        lineOfSight.add(new Vector3D(-0.011204, 0.181530, 1d).normalize());
-        lineOfSight.add(new Vector3D(-0.011204, 0.181518, 1d).normalize());
-        lineOfSight.add(new Vector3D(-0.011204, 0.181505, 1d).normalize());
-        lineOfSight.add(new Vector3D(-0.011204, 0.181492, 1d).normalize());
-        lineOfSight.add(new Vector3D(-0.011204, 0.181480, 1d).normalize());
-        lineOfSight.add(new Vector3D(-0.011204, 0.181467, 1d).normalize());
-        lineOfSight.add(new Vector3D(-0.011204, 0.181455, 1d).normalize());
-        lineOfSight.add(new Vector3D(-0.011204, 0.181442, 1d).normalize());
-        lineOfSight.add(new Vector3D(-0.011204, 0.181430, 1d).normalize());
-        lineOfSight.add(new Vector3D(-0.011204, 0.181417, 1d).normalize());
-        lineOfSight.add(new Vector3D(-0.011204, 0.181405, 1d).normalize());
-        lineOfSight.add(new Vector3D(-0.011204, 0.181392, 1d).normalize());
-
-        lineOfSight.add(new Vector3D(-0.011204, 0.149762, 1d).normalize());
-        lineOfSight.add(new Vector3D(-0.011204, 0.149749, 1d).normalize());
-        lineOfSight.add(new Vector3D(-0.011204, 0.149737, 1d).normalize());
-        lineOfSight.add(new Vector3D(-0.011204, 0.149724, 1d).normalize());
-        lineOfSight.add(new Vector3D(-0.011204, 0.149712, 1d).normalize());
-        lineOfSight.add(new Vector3D(-0.011204, 0.149699, 1d).normalize());
-        lineOfSight.add(new Vector3D(-0.011204, 0.149686, 1d).normalize());
-        lineOfSight.add(new Vector3D(-0.011204, 0.149674, 1d).normalize());
-        lineOfSight.add(new Vector3D(-0.011204, 0.149661, 1d).normalize());
-        lineOfSight.add(new Vector3D(-0.011204, 0.149649, 1d).normalize());
-        lineOfSight.add(new Vector3D(-0.011204, 0.149636, 1d).normalize());
-        lineOfSight.add(new Vector3D(-0.011204, 0.149624, 1d).normalize());
-        lineOfSight.add(new Vector3D(-0.011204, 0.149611, 1d).normalize());
-        lineOfSight.add(new Vector3D(-0.011204, 0.149599, 1d).normalize());
-        lineOfSight.add(new Vector3D(-0.011204, 0.149586, 1d).normalize());
+        List<TimeDependentLOS> lineOfSight = new ArrayList<TimeDependentLOS>();
+        lineOfSight.add(new FixedLOS(new Vector3D(-0.011204, 0.181530, 1d).normalize()));
+        lineOfSight.add(new FixedLOS(new Vector3D(-0.011204, 0.181518, 1d).normalize()));
+        lineOfSight.add(new FixedLOS(new Vector3D(-0.011204, 0.181505, 1d).normalize()));
+        lineOfSight.add(new FixedLOS(new Vector3D(-0.011204, 0.181492, 1d).normalize()));
+        lineOfSight.add(new FixedLOS(new Vector3D(-0.011204, 0.181480, 1d).normalize()));
+        lineOfSight.add(new FixedLOS(new Vector3D(-0.011204, 0.181467, 1d).normalize()));
+        lineOfSight.add(new FixedLOS(new Vector3D(-0.011204, 0.181455, 1d).normalize()));
+        lineOfSight.add(new FixedLOS(new Vector3D(-0.011204, 0.181442, 1d).normalize()));
+        lineOfSight.add(new FixedLOS(new Vector3D(-0.011204, 0.181430, 1d).normalize()));
+        lineOfSight.add(new FixedLOS(new Vector3D(-0.011204, 0.181417, 1d).normalize()));
+        lineOfSight.add(new FixedLOS(new Vector3D(-0.011204, 0.181405, 1d).normalize()));
+        lineOfSight.add(new FixedLOS(new Vector3D(-0.011204, 0.181392, 1d).normalize()));
+
+        lineOfSight.add(new FixedLOS(new Vector3D(-0.011204, 0.149762, 1d).normalize()));
+        lineOfSight.add(new FixedLOS(new Vector3D(-0.011204, 0.149749, 1d).normalize()));
+        lineOfSight.add(new FixedLOS(new Vector3D(-0.011204, 0.149737, 1d).normalize()));
+        lineOfSight.add(new FixedLOS(new Vector3D(-0.011204, 0.149724, 1d).normalize()));
+        lineOfSight.add(new FixedLOS(new Vector3D(-0.011204, 0.149712, 1d).normalize()));
+        lineOfSight.add(new FixedLOS(new Vector3D(-0.011204, 0.149699, 1d).normalize()));
+        lineOfSight.add(new FixedLOS(new Vector3D(-0.011204, 0.149686, 1d).normalize()));
+        lineOfSight.add(new FixedLOS(new Vector3D(-0.011204, 0.149674, 1d).normalize()));
+        lineOfSight.add(new FixedLOS(new Vector3D(-0.011204, 0.149661, 1d).normalize()));
+        lineOfSight.add(new FixedLOS(new Vector3D(-0.011204, 0.149649, 1d).normalize()));
+        lineOfSight.add(new FixedLOS(new Vector3D(-0.011204, 0.149636, 1d).normalize()));
+        lineOfSight.add(new FixedLOS(new Vector3D(-0.011204, 0.149624, 1d).normalize()));
+        lineOfSight.add(new FixedLOS(new Vector3D(-0.011204, 0.149611, 1d).normalize()));
+        lineOfSight.add(new FixedLOS(new Vector3D(-0.011204, 0.149599, 1d).normalize()));
+        lineOfSight.add(new FixedLOS(new Vector3D(-0.011204, 0.149586, 1d).normalize()));
 
         AbsoluteDate absDate = new AbsoluteDate("2009-12-11T16:58:51.593", gps);
         LinearLineDatation lineDatation = new LinearLineDatation(absDate, 1d, 638.5696040868454);
@@ -1298,10 +1292,10 @@ public class RuggedTest {
                 satellitePVList.get(0).getDate(), satellitePVList.get(satellitePVList.size() - 1).getDate(), 10.0, satellitePVList, 6,
                 CartesianDerivativesFilter.USE_P, satelliteQList, 8, AngularDerivativesFilter.USE_R, 0.1);
 
-        List<Vector3D> lineOfSight = new ArrayList<Vector3D>();
-        lineOfSight.add(new Vector3D(0.0046536264d, -0.1851800945d, 1d).normalize());
-        lineOfSight.add(new Vector3D(0.0000001251d, -0.0002815246d, 1d).normalize());
-        lineOfSight.add(new Vector3D(0.0046694108d, 0.1853863933d, 1d).normalize());
+        List<TimeDependentLOS> lineOfSight = new ArrayList<TimeDependentLOS>();
+        lineOfSight.add(new FixedLOS(new Vector3D(0.0046536264d, -0.1851800945d, 1d)));
+        lineOfSight.add(new FixedLOS(new Vector3D(0.0000001251d, -0.0002815246d, 1d)));
+        lineOfSight.add(new FixedLOS(new Vector3D(0.0046694108d, 0.1853863933d, 1d)));
 
         AbsoluteDate absDate = new AbsoluteDate("2013-07-07T17:16:36.857", gps);
         LinearLineDatation lineDatation = new LinearLineDatation(absDate, 0.03125d, 19.95565693384045);
@@ -1340,10 +1334,10 @@ public class RuggedTest {
         // 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 nadir, 2.6" per pixel, 3" sagitta
         Vector3D position = new Vector3D(1.5, 0, -0.2);
-        List<Vector3D> los = createLOSCurvedLine(Vector3D.PLUS_K, Vector3D.PLUS_I,
-                                                 FastMath.toRadians(dimension * 2.6 / 3600.0),
-                                                 FastMath.toRadians(3.0 / 3600.0),
-                                                 dimension);
+        List<TimeDependentLOS> los = createLOSCurvedLine(Vector3D.PLUS_K, Vector3D.PLUS_I,
+                                                         FastMath.toRadians(dimension * 2.6 / 3600.0),
+                                                         FastMath.toRadians(3.0 / 3600.0),
+                                                         dimension);
 
         // linear datation model: at reference time we get the middle line, and the rate is one line every 1.5ms
         LineDatation lineDatation = new LinearLineDatation(crossing, dimension / 2, 1.0 / 1.5e-3);
@@ -1414,9 +1408,9 @@ public class RuggedTest {
         // 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, 2.6" per pixel
         Vector3D position = new Vector3D(1.5, 0, -0.2);
-        List<Vector3D> los = createLOSPerfectLine(new Rotation(Vector3D.PLUS_I, FastMath.toRadians(50.0)).applyTo(Vector3D.PLUS_K),
-                                       Vector3D.PLUS_I,
-                                       FastMath.toRadians(dimension * 2.6 / 3600.0), dimension);
+        List<TimeDependentLOS> los = createLOSPerfectLine(new Rotation(Vector3D.PLUS_I, FastMath.toRadians(50.0)).applyTo(Vector3D.PLUS_K),
+                                                          Vector3D.PLUS_I,
+                                                          FastMath.toRadians(dimension * 2.6 / 3600.0), dimension);
 
         // linear datation model: at reference time we get the middle line, and the rate is one line every 1.5ms
         LineDatation lineDatation = new LinearLineDatation(crossing, dimension / 2, 1.0 / 1.5e-3);
@@ -1500,9 +1494,9 @@ public class RuggedTest {
         // 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, 2.6" per pixel
         Vector3D position = new Vector3D(1.5, 0, -0.2);
-        List<Vector3D> los = createLOSPerfectLine(new Rotation(Vector3D.PLUS_I, FastMath.toRadians(50.0)).applyTo(Vector3D.PLUS_K),
-                                       Vector3D.PLUS_I,
-                                       FastMath.toRadians(dimension * 2.6 / 3600.0), dimension);
+        List<TimeDependentLOS> los = createLOSPerfectLine(new Rotation(Vector3D.PLUS_I, FastMath.toRadians(50.0)).applyTo(Vector3D.PLUS_K),
+                                                          Vector3D.PLUS_I,
+                                                          FastMath.toRadians(dimension * 2.6 / 3600.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);
@@ -1624,24 +1618,24 @@ public class RuggedTest {
 
     }
 
-    private List<Vector3D> createLOSPerfectLine(Vector3D center, Vector3D normal, double halfAperture, int n) {
-        List<Vector3D> list = new ArrayList<Vector3D>(n);
+    private List<TimeDependentLOS> createLOSPerfectLine(Vector3D center, Vector3D normal, double halfAperture, int n) {
+        List<TimeDependentLOS> list = new ArrayList<TimeDependentLOS>(n);
         for (int i = 0; i < n; ++i) {
             double alpha = (halfAperture * (2 * i + 1 - n)) / (n - 1);
-            list.add(new Rotation(normal, alpha).applyTo(center));
+            list.add(new FixedLOS(new Rotation(normal, alpha).applyTo(center)));
         }
         return list;
     }
 
-    private List<Vector3D> createLOSCurvedLine(Vector3D center, Vector3D normal,
-                                               double halfAperture, double sagitta, int n) {
+    private List<TimeDependentLOS> createLOSCurvedLine(Vector3D center, Vector3D normal,
+                                                       double halfAperture, double sagitta, int n) {
         Vector3D u = Vector3D.crossProduct(center, normal);
-        List<Vector3D> list = new ArrayList<Vector3D>(n);
+        List<TimeDependentLOS> list = new ArrayList<TimeDependentLOS>(n);
         for (int i = 0; i < n; ++i) {
             double x = (2.0 * i + 1.0 - n) / (n - 1);
             double alpha = x * halfAperture;
             double beta  = x * x * sagitta;
-            list.add(new Rotation(normal, alpha).applyTo(new Rotation(u, beta).applyTo(center)));
+            list.add(new FixedLOS(new Rotation(normal, alpha).applyTo(new Rotation(u, beta).applyTo(center))));
         }
         return list;
     }
diff --git a/core/src/test/java/org/orekit/rugged/api/SensorMeanPlaneCrossingTest.java b/core/src/test/java/org/orekit/rugged/api/SensorMeanPlaneCrossingTest.java
index 4c799351ebfccda5e694cbe14ef5dc65afa33126..e8ddb1e47a11e4b591993b7fbc30596807995128 100644
--- a/core/src/test/java/org/orekit/rugged/api/SensorMeanPlaneCrossingTest.java
+++ b/core/src/test/java/org/orekit/rugged/api/SensorMeanPlaneCrossingTest.java
@@ -66,10 +66,10 @@ public class SensorMeanPlaneCrossingTest {
         final Vector3D       cross     = Vector3D.crossProduct(normal, fovCenter);
 
         // build lists of pixels regularly spread on a perfect plane
-        final List<Vector3D> los       = new ArrayList<Vector3D>();
+        final List<TimeDependentLOS> los       = new ArrayList<TimeDependentLOS>();
         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));
+            los.add(new FixedLOS(new Vector3D(FastMath.cos(alpha), fovCenter, FastMath.sin(alpha), cross)));
         }
 
         final LineSensor sensor = new LineSensor("perfect line",
@@ -96,7 +96,7 @@ public class SensorMeanPlaneCrossingTest {
         final Vector3D        cross     = Vector3D.crossProduct(normal, fovCenter);
 
         // build lists of pixels regularly spread on a perfect plane
-        final List<Vector3D> los       = new ArrayList<Vector3D>();
+        final List<TimeDependentLOS> los       = new ArrayList<TimeDependentLOS>();
         for (int i = -1000; i <= 1000; ++i) {
             final double alpha = i * 0.17 / 10 + 1.0e-5 * random.nextDouble();
             final double delta = 1.0e-5 * random.nextDouble();
@@ -104,7 +104,7 @@ public class SensorMeanPlaneCrossingTest {
             final double sA = FastMath.sin(alpha);
             final double cD = FastMath.cos(delta);
             final double sD = FastMath.sin(delta);
-            los.add(new Vector3D(cA * cD, fovCenter, sA * cD, cross, sD, normal));
+            los.add(new FixedLOS(new Vector3D(cA * cD, fovCenter, sA * cD, cross, sD, normal)));
         }
 
         final LineSensor sensor = new LineSensor("noisy line",
diff --git a/design/direct-localization-class-diagram.puml b/design/direct-localization-class-diagram.puml
index e4e73d4fb2e786a2907851f45fbf7f6f78daa04c..f49203d89438e3bc3e8dc3d79a94dd110c3f241d 100644
--- a/design/direct-localization-class-diagram.puml
+++ b/design/direct-localization-class-diagram.puml
@@ -61,7 +61,7 @@
       class LineSensor
       IntersectionAlgorithm "1" <--o Rugged : delegate DEM intersection
       ExtendedEllipsoid <-- Rugged : convert geodetic points
-      Rugged --> LineSensor : getLOS(pixel)
+      Rugged --> LineSensor : getLOS(date, pixel)
       Rugged --> LineSensor : getDate(line)
       SpacecraftToObservedBody <-- Rugged : convert positions/directions
     }
diff --git a/design/rugged-design.odt b/design/rugged-design.odt
index 296c73fdaf4e1e7af50aaae2bcbb85dcd59ba407..4be3e90bf3bcb9d3582705071aa026c82f87e9d0 100644
Binary files a/design/rugged-design.odt and b/design/rugged-design.odt differ