diff --git a/src/main/java/org/orekit/estimation/sequential/EskfMeasurementHandler.java b/src/main/java/org/orekit/estimation/sequential/EskfMeasurementHandler.java
index f072250587f2de187bea19c406fe79438b18bbac..75f3a9d27e1d713b86acc99da11decfa5ad25202 100644
--- a/src/main/java/org/orekit/estimation/sequential/EskfMeasurementHandler.java
+++ b/src/main/java/org/orekit/estimation/sequential/EskfMeasurementHandler.java
@@ -21,12 +21,8 @@ import java.util.List;
 import org.hipparchus.exception.MathRuntimeException;
 import org.hipparchus.filtering.kalman.ProcessEstimate;
 import org.hipparchus.filtering.kalman.extended.ExtendedKalmanFilter;
-import org.hipparchus.linear.MatrixUtils;
-import org.hipparchus.linear.RealMatrix;
 import org.orekit.errors.OrekitException;
 import org.orekit.estimation.measurements.ObservedMeasurement;
-import org.orekit.estimation.measurements.PV;
-import org.orekit.estimation.measurements.Position;
 import org.orekit.propagation.SpacecraftState;
 import org.orekit.propagation.sampling.OrekitStepHandler;
 import org.orekit.propagation.sampling.OrekitStepInterpolator;
@@ -41,7 +37,7 @@ import org.orekit.time.AbsoluteDate;
  */
 public class EskfMeasurementHandler implements OrekitStepHandler {
 
-    /** Least squares model. */
+    /** ESKF model. */
     private final SemiAnalyticalKalmanModel model;
 
     /** Extended Kalman Filter. */
@@ -104,7 +100,7 @@ public class EskfMeasurementHandler implements OrekitStepHandler {
                 model.updateNominalSpacecraftState(interpolator.getInterpolatedState(observedMeasurements.get(index).getDate()));
 
                 // Process the current observation
-                final ProcessEstimate estimate = filter.estimationStep(decorate(observedMeasurements.get(index)));
+                final ProcessEstimate estimate = filter.estimationStep(KalmanEstimatorUtil.decorate(observedMeasurements.get(index), referenceDate));
 
                 // Finalize the estimation
                 model.finalizeEstimation(observedMeasurements.get(index), estimate);
@@ -128,39 +124,4 @@ public class EskfMeasurementHandler implements OrekitStepHandler {
 
     }
 
-    /** Decorate an observed measurement.
-     * <p>
-     * The "physical" measurement noise matrix is the covariance matrix of the measurement.
-     * Normalizing it consists in applying the following equation: Rn[i,j] =  R[i,j]/σ[i]/σ[j]
-     * Thus the normalized measurement noise matrix is the matrix of the correlation coefficients
-     * between the different components of the measurement.
-     * </p>
-     * @param observedMeasurement the measurement
-     * @return decorated measurement
-     */
-    private MeasurementDecorator decorate(final ObservedMeasurement<?> observedMeasurement) {
-
-        // Normalized measurement noise matrix contains 1 on its diagonal and correlation coefficients
-        // of the measurement on its non-diagonal elements.
-        // Indeed, the "physical" measurement noise matrix is the covariance matrix of the measurement
-        // Normalizing it leaves us with the matrix of the correlation coefficients
-        final RealMatrix covariance;
-        if (observedMeasurement instanceof PV) {
-            // For PV measurements we do have a covariance matrix and thus a correlation coefficients matrix
-            final PV pv = (PV) observedMeasurement;
-            covariance = MatrixUtils.createRealMatrix(pv.getCorrelationCoefficientsMatrix());
-        } else if (observedMeasurement instanceof Position) {
-            // For Position measurements we do have a covariance matrix and thus a correlation coefficients matrix
-            final Position position = (Position) observedMeasurement;
-            covariance = MatrixUtils.createRealMatrix(position.getCorrelationCoefficientsMatrix());
-        } else {
-            // For other measurements we do not have a covariance matrix.
-            // Thus the correlation coefficients matrix is an identity matrix.
-            covariance = MatrixUtils.createRealIdentityMatrix(observedMeasurement.getDimension());
-        }
-
-        return new MeasurementDecorator(observedMeasurement, covariance, referenceDate);
-
-    }
-
 }
diff --git a/src/main/java/org/orekit/estimation/sequential/KalmanEstimator.java b/src/main/java/org/orekit/estimation/sequential/KalmanEstimator.java
index 6faa7a4fb120d8ae41e9586f4fa84740cc95da92..6cb291a12cc87cad56c20a9da144f824a7d8b12d 100644
--- a/src/main/java/org/orekit/estimation/sequential/KalmanEstimator.java
+++ b/src/main/java/org/orekit/estimation/sequential/KalmanEstimator.java
@@ -22,13 +22,10 @@ import org.hipparchus.exception.MathRuntimeException;
 import org.hipparchus.filtering.kalman.ProcessEstimate;
 import org.hipparchus.filtering.kalman.extended.ExtendedKalmanFilter;
 import org.hipparchus.linear.MatrixDecomposer;
-import org.hipparchus.linear.MatrixUtils;
 import org.hipparchus.linear.RealMatrix;
 import org.hipparchus.linear.RealVector;
 import org.orekit.errors.OrekitException;
 import org.orekit.estimation.measurements.ObservedMeasurement;
-import org.orekit.estimation.measurements.PV;
-import org.orekit.estimation.measurements.Position;
 import org.orekit.propagation.Propagator;
 import org.orekit.propagation.conversion.OrbitDeterminationPropagatorBuilder;
 import org.orekit.propagation.conversion.PropagatorBuilder;
@@ -218,7 +215,7 @@ public class KalmanEstimator {
      */
     public Propagator[] estimationStep(final ObservedMeasurement<?> observedMeasurement) {
         try {
-            final ProcessEstimate estimate = filter.estimationStep(decorate(observedMeasurement));
+            final ProcessEstimate estimate = filter.estimationStep(KalmanEstimatorUtil.decorate(observedMeasurement, referenceDate));
             processModel.finalizeEstimation(observedMeasurement, estimate);
             if (observer != null) {
                 observer.evaluationPerformed(processModel);
@@ -241,39 +238,4 @@ public class KalmanEstimator {
         return propagators;
     }
 
-    /** Decorate an observed measurement.
-     * <p>
-     * The "physical" measurement noise matrix is the covariance matrix of the measurement.
-     * Normalizing it consists in applying the following equation: Rn[i,j] =  R[i,j]/σ[i]/σ[j]
-     * Thus the normalized measurement noise matrix is the matrix of the correlation coefficients
-     * between the different components of the measurement.
-     * </p>
-     * @param observedMeasurement the measurement
-     * @return decorated measurement
-     */
-    private MeasurementDecorator decorate(final ObservedMeasurement<?> observedMeasurement) {
-
-        // Normalized measurement noise matrix contains 1 on its diagonal and correlation coefficients
-        // of the measurement on its non-diagonal elements.
-        // Indeed, the "physical" measurement noise matrix is the covariance matrix of the measurement
-        // Normalizing it leaves us with the matrix of the correlation coefficients
-        final RealMatrix covariance;
-        if (observedMeasurement instanceof PV) {
-            // For PV measurements we do have a covariance matrix and thus a correlation coefficients matrix
-            final PV pv = (PV) observedMeasurement;
-            covariance = MatrixUtils.createRealMatrix(pv.getCorrelationCoefficientsMatrix());
-        } else if (observedMeasurement instanceof Position) {
-            // For Position measurements we do have a covariance matrix and thus a correlation coefficients matrix
-            final Position position = (Position) observedMeasurement;
-            covariance = MatrixUtils.createRealMatrix(position.getCorrelationCoefficientsMatrix());
-        } else {
-            // For other measurements we do not have a covariance matrix.
-            // Thus the correlation coefficients matrix is an identity matrix.
-            covariance = MatrixUtils.createRealIdentityMatrix(observedMeasurement.getDimension());
-        }
-
-        return new MeasurementDecorator(observedMeasurement, covariance, referenceDate);
-
-    }
-
 }
diff --git a/src/main/java/org/orekit/estimation/sequential/KalmanEstimatorUtil.java b/src/main/java/org/orekit/estimation/sequential/KalmanEstimatorUtil.java
index 93e89dfb70e1cfb2b51a205f28f0d06730e907c7..fddddbe19a950dac2c8a7732de0f688a2841d8bc 100644
--- a/src/main/java/org/orekit/estimation/sequential/KalmanEstimatorUtil.java
+++ b/src/main/java/org/orekit/estimation/sequential/KalmanEstimatorUtil.java
@@ -16,8 +16,14 @@
  */
 package org.orekit.estimation.sequential;
 
+import org.hipparchus.linear.MatrixUtils;
+import org.hipparchus.linear.RealMatrix;
 import org.orekit.errors.OrekitException;
 import org.orekit.errors.OrekitMessages;
+import org.orekit.estimation.measurements.ObservedMeasurement;
+import org.orekit.estimation.measurements.PV;
+import org.orekit.estimation.measurements.Position;
+import org.orekit.time.AbsoluteDate;
 import org.orekit.utils.ParameterDriver;
 import org.orekit.utils.ParameterDriversList;
 
@@ -34,6 +40,43 @@ public class KalmanEstimatorUtil {
     private KalmanEstimatorUtil() {
     }
 
+    /** Decorate an observed measurement.
+     * <p>
+     * The "physical" measurement noise matrix is the covariance matrix of the measurement.
+     * Normalizing it consists in applying the following equation: Rn[i,j] =  R[i,j]/σ[i]/σ[j]
+     * Thus the normalized measurement noise matrix is the matrix of the correlation coefficients
+     * between the different components of the measurement.
+     * </p>
+     * @param observedMeasurement the measurement
+     * @param referenceDate reference date
+     * @return decorated measurements
+     */
+    public static MeasurementDecorator decorate(final ObservedMeasurement<?> observedMeasurement,
+                                                final AbsoluteDate referenceDate) {
+
+        // Normalized measurement noise matrix contains 1 on its diagonal and correlation coefficients
+        // of the measurement on its non-diagonal elements.
+        // Indeed, the "physical" measurement noise matrix is the covariance matrix of the measurement
+        // Normalizing it leaves us with the matrix of the correlation coefficients
+        final RealMatrix covariance;
+        if (observedMeasurement instanceof PV) {
+            // For PV measurements we do have a covariance matrix and thus a correlation coefficients matrix
+            final PV pv = (PV) observedMeasurement;
+            covariance = MatrixUtils.createRealMatrix(pv.getCorrelationCoefficientsMatrix());
+        } else if (observedMeasurement instanceof Position) {
+            // For Position measurements we do have a covariance matrix and thus a correlation coefficients matrix
+            final Position position = (Position) observedMeasurement;
+            covariance = MatrixUtils.createRealMatrix(position.getCorrelationCoefficientsMatrix());
+        } else {
+            // For other measurements we do not have a covariance matrix.
+            // Thus the correlation coefficients matrix is an identity matrix.
+            covariance = MatrixUtils.createRealIdentityMatrix(observedMeasurement.getDimension());
+        }
+
+        return new MeasurementDecorator(observedMeasurement, covariance, referenceDate);
+
+    }
+
     /** Check dimension.
      * @param dimension dimension to check
      * @param orbitalParameters orbital parameters
diff --git a/src/main/java/org/orekit/estimation/sequential/SemiAnalyticalUnscentedKalmanEstimator.java b/src/main/java/org/orekit/estimation/sequential/SemiAnalyticalUnscentedKalmanEstimator.java
index c54a555c9c1abab0762d738b54308918b3631469..dda5fbb66eed6cb5a3bdb72344f7d24ff2a9d33a 100644
--- a/src/main/java/org/orekit/estimation/sequential/SemiAnalyticalUnscentedKalmanEstimator.java
+++ b/src/main/java/org/orekit/estimation/sequential/SemiAnalyticalUnscentedKalmanEstimator.java
@@ -27,8 +27,6 @@ import org.hipparchus.util.UnscentedTransformProvider;
 import org.orekit.errors.OrekitException;
 import org.orekit.estimation.measurements.ObservedMeasurement;
 import org.orekit.propagation.conversion.DSSTPropagatorBuilder;
-import org.orekit.propagation.conversion.OrbitDeterminationPropagatorBuilder;
-import org.orekit.propagation.numerical.NumericalPropagator;
 import org.orekit.propagation.semianalytical.dsst.DSSTPropagator;
 import org.orekit.time.AbsoluteDate;
 import org.orekit.utils.ParameterDriver;
@@ -38,22 +36,18 @@ import org.orekit.utils.ParameterDriversList.DelegatingDriver;
 /**
  * Implementation of an Unscented Semi-analytical Kalman filter (USKF) to perform orbit determination.
  * <p>
- * The filter uses a {@link OrbitDeterminationPropagatorBuilder} to initialize its reference trajectory {@link NumericalPropagator}
- * or {@link DSSTPropagator} .
+ * The filter uses a {@link DSSTPropagatorBuilder}.
  * </p>
  * <p>
  * The estimated parameters are driven by {@link ParameterDriver} objects. They are of 3 different types:<ol>
  *   <li><b>Orbital parameters</b>:The position and velocity of the spacecraft, or, more generally, its orbit.<br>
  *       These parameters are retrieved from the reference trajectory propagator builder when the filter is initialized.</li>
- *   <li><b>Propagation parameters</b>: Some parameters modelling physical processes (SRP or drag coefficients etc...).<br>
+ *   <li><b>Propagation parameters</b>: Some parameters modeling physical processes (SRP or drag coefficients etc...).<br>
  *       They are also retrieved from the propagator builder during the initialization phase.</li>
  *   <li><b>Measurements parameters</b>: Parameters related to measurements (station biases, positions etc...).<br>
  *       They are passed down to the filter in its constructor.</li>
  * </ol>
  * <p>
- * The total number of estimated parameters is m, the size of the state vector.
- * </p>
- * <p>
  * The Kalman filter implementation used is provided by the underlying mathematical library Hipparchus.
  * All the variables seen by Hipparchus (states, covariances...) are normalized
  * using a specific scale for each estimated parameters or standard deviation noise for each measurement components.
@@ -68,7 +62,7 @@ import org.orekit.utils.ParameterDriversList.DelegatingDriver;
 public class SemiAnalyticalUnscentedKalmanEstimator {
 
     /** Builders for orbit propagators. */
-    private OrbitDeterminationPropagatorBuilder propagatorBuilder;
+    private DSSTPropagatorBuilder propagatorBuilder;
 
     /** Unscented Kalman filter process model. */
     private final SemiAnalyticalUnscentedKalmanModel processModel;
@@ -87,22 +81,25 @@ public class SemiAnalyticalUnscentedKalmanEstimator {
      * @param measurementProcessNoiseMatrix provider for measurement process noise matrix
      * @param utProvider provider for the unscented transform
      */
-
     SemiAnalyticalUnscentedKalmanEstimator(final MatrixDecomposer decomposer,
-            final DSSTPropagatorBuilder propagatorBuilder,
-            final CovarianceMatrixProvider processNoiseMatricesProvider,
-            final ParameterDriversList estimatedMeasurementParameters,
-            final CovarianceMatrixProvider measurementProcessNoiseMatrix,
-            final UnscentedTransformProvider utProvider) {
+                                           final DSSTPropagatorBuilder propagatorBuilder,
+                                           final CovarianceMatrixProvider processNoiseMatricesProvider,
+                                           final ParameterDriversList estimatedMeasurementParameters,
+                                           final CovarianceMatrixProvider measurementProcessNoiseMatrix,
+                                           final UnscentedTransformProvider utProvider) {
 
         this.propagatorBuilder = propagatorBuilder;
         this.observer          = null;
-        this.processModel      = new SemiAnalyticalUnscentedKalmanModel(propagatorBuilder, processNoiseMatricesProvider,
-                                                          estimatedMeasurementParameters, measurementProcessNoiseMatrix);
-        this.filter = new UnscentedKalmanFilter<>(decomposer, processModel, processModel.getEstimate(), utProvider);
 
+        // Build the process model and measurement model
+        this.processModel = new SemiAnalyticalUnscentedKalmanModel(propagatorBuilder, processNoiseMatricesProvider,
+                                                                   estimatedMeasurementParameters, measurementProcessNoiseMatrix);
+
+        // Unscented Kalman Filter of Hipparchus
+        this.filter = new UnscentedKalmanFilter<>(decomposer, processModel, processModel.getEstimate(), utProvider);
 
     }
+
     /** Set the observer.
      * @param observer the observer
      */
@@ -178,6 +175,7 @@ public class SemiAnalyticalUnscentedKalmanEstimator {
     public ParameterDriversList getEstimatedMeasurementsParameters() {
         return processModel.getEstimatedMeasurementsParameters();
     }
+
     /** Process a single measurement.
      * <p>
      * Update the filter with the new measurement by calling the estimate method.
@@ -193,5 +191,6 @@ public class SemiAnalyticalUnscentedKalmanEstimator {
             throw new OrekitException(mrte);
         }
     }
+
 }
 
diff --git a/src/main/java/org/orekit/estimation/sequential/SemiAnalyticalUnscentedKalmanEstimatorBuilder.java b/src/main/java/org/orekit/estimation/sequential/SemiAnalyticalUnscentedKalmanEstimatorBuilder.java
index b645f725990c0cf7c629947fa76011e4384bf1f4..307fa92d75927adb8b3d66d918cb2a131e1b1f99 100644
--- a/src/main/java/org/orekit/estimation/sequential/SemiAnalyticalUnscentedKalmanEstimatorBuilder.java
+++ b/src/main/java/org/orekit/estimation/sequential/SemiAnalyticalUnscentedKalmanEstimatorBuilder.java
@@ -18,19 +18,16 @@ package org.orekit.estimation.sequential;
 
 import org.hipparchus.linear.MatrixDecomposer;
 import org.hipparchus.linear.QRDecomposer;
-import org.hipparchus.util.MerweUnscentedTransform;
 import org.hipparchus.util.UnscentedTransformProvider;
 import org.orekit.errors.OrekitException;
 import org.orekit.errors.OrekitMessages;
 import org.orekit.propagation.conversion.DSSTPropagatorBuilder;
-import org.orekit.utils.ParameterDriver;
 import org.orekit.utils.ParameterDriversList;
 
 /** Builder for an Unscented Semi-analytical Kalman filter estimator.
  * @author Gaëtan Pierre
  * @author Bryan Cazabonne
  */
-
 public class SemiAnalyticalUnscentedKalmanEstimatorBuilder {
 
     /** Decomposer to use for the correction phase. */
@@ -53,24 +50,26 @@ public class SemiAnalyticalUnscentedKalmanEstimatorBuilder {
 
     /** Default constructor.
      *  Set an Unscented Semi-analytical Kalman filter.
-     *  By default, a {@link MerweUnscentedTransform} provider is used. It considers that only the orbital parameters are estimated.
-     *  It is possible to override the default configuration by using {@link #unscentedTransformProvider(UnscentedTransformProvider)}.
      */
-
     public SemiAnalyticalUnscentedKalmanEstimatorBuilder() {
         this.decomposer                      = new QRDecomposer(1.0e-15);
         this.propagatorBuilder               = null;
         this.estimatedMeasurementsParameters = new ParameterDriversList();
         this.processNoiseMatrixProvider      = null;
         this.measurementProcessNoiseMatrix   = null;
-        this.utProvider                      = new MerweUnscentedTransform(6);
+        this.utProvider                      = null;
     }
 
     /** Construct a {@link SemiAnalyticalUnscentedKalmanEstimator} from the data in this builder.
      * <p>
-     * Before this method is called, {@link #addPropagationConfiguration(propagatorBuilder,
+     * Before this method is called, {@link #addPropagationConfiguration(DSSTPropagatorBuilder,
      * CovarianceMatrixProvider) addPropagationConfiguration()} must have been called
      * at least once, otherwise configuration is incomplete and an exception will be raised.
+     * <p>
+     * In addition, the {@link #unscentedTransformProvider(UnscentedTransformProvider)
+     * unscentedTransformProvider()} must be called to configure the unscented transform
+     * provider use during the estimation process, otherwise configuration is
+     * incomplete and an exception will be raised.
      * </p>
      * @return a new {@link SemiAnalyticalUnscentedKalmanEstimator}.
      */
@@ -78,30 +77,12 @@ public class SemiAnalyticalUnscentedKalmanEstimatorBuilder {
         if (propagatorBuilder == null) {
             throw new OrekitException(OrekitMessages.NO_PROPAGATOR_CONFIGURED);
         }
-     // Number of estimated parameters
-        int columns = 0;
-        for (final ParameterDriver driver : propagatorBuilder.getOrbitalParametersDrivers().getDrivers()) {
-            if (driver.isSelected()) {
-                columns++;
-            }
-        }
-        for (final ParameterDriver driver : propagatorBuilder.getPropagationParametersDrivers().getDrivers()) {
-            if (driver.isSelected()) {
-                columns++;
-            }
-        }
-
-        columns = columns + estimatedMeasurementsParameters.getNbParams();
-
-        // Check if the number of the selected parameters for the estimation (Orbital + Propagation + Measurement)
-        // is equal to the dimension of the state initialized in the unscented transform provider.
-        // If not, re-initialize the unscented transform with the appropriate dimension.
-        if (columns != (utProvider.getWc().getDimension() - 1) / 2) {
-            this.utProvider = new MerweUnscentedTransform(columns);
+        if (utProvider == null) {
+            throw new OrekitException(OrekitMessages.NO_UNSCENTED_TRANSFORM_CONFIGURED);
         }
-
         return new SemiAnalyticalUnscentedKalmanEstimator(decomposer, propagatorBuilder, processNoiseMatrixProvider,
-                                                 estimatedMeasurementsParameters, measurementProcessNoiseMatrix, utProvider);
+                                                          estimatedMeasurementsParameters, measurementProcessNoiseMatrix,
+                                                          utProvider);
     }
 
     /** Configure the matrix decomposer.
@@ -132,8 +113,8 @@ public class SemiAnalyticalUnscentedKalmanEstimatorBuilder {
      * @return this object.
      */
     public SemiAnalyticalUnscentedKalmanEstimatorBuilder addPropagationConfiguration(final DSSTPropagatorBuilder builder,
-                                                                            final CovarianceMatrixProvider provider) {
-        propagatorBuilder      = builder;
+                                                                                     final CovarianceMatrixProvider provider) {
+        propagatorBuilder          = builder;
         processNoiseMatrixProvider = provider;
         return this;
     }
@@ -147,10 +128,10 @@ public class SemiAnalyticalUnscentedKalmanEstimatorBuilder {
      * @return this object.
      */
     public SemiAnalyticalUnscentedKalmanEstimatorBuilder estimatedMeasurementsParameters(final ParameterDriversList estimatedMeasurementsParams,
-                                                                                final CovarianceMatrixProvider provider) {
+                                                                                         final CovarianceMatrixProvider provider) {
         estimatedMeasurementsParameters = estimatedMeasurementsParams;
         measurementProcessNoiseMatrix   = provider;
         return this;
     }
-}
 
+}
diff --git a/src/main/java/org/orekit/estimation/sequential/SemiAnalyticalUnscentedKalmanModel.java b/src/main/java/org/orekit/estimation/sequential/SemiAnalyticalUnscentedKalmanModel.java
index ab0a9fd971f0b85b021b573d96f525adc5d9cb55..f7ed2a966e6ffcbcb5857dffda16c0a3d632f385 100644
--- a/src/main/java/org/orekit/estimation/sequential/SemiAnalyticalUnscentedKalmanModel.java
+++ b/src/main/java/org/orekit/estimation/sequential/SemiAnalyticalUnscentedKalmanModel.java
@@ -22,7 +22,6 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
-import org.hipparchus.exception.MathRuntimeException;
 import org.hipparchus.filtering.kalman.ProcessEstimate;
 import org.hipparchus.filtering.kalman.unscented.UnscentedEvolution;
 import org.hipparchus.filtering.kalman.unscented.UnscentedKalmanFilter;
@@ -32,8 +31,6 @@ import org.hipparchus.linear.MatrixUtils;
 import org.hipparchus.linear.RealMatrix;
 import org.hipparchus.linear.RealVector;
 import org.hipparchus.util.FastMath;
-import org.orekit.errors.OrekitException;
-import org.orekit.errors.OrekitMessages;
 import org.orekit.estimation.measurements.EstimatedMeasurement;
 import org.orekit.estimation.measurements.EstimationModifier;
 import org.orekit.estimation.measurements.ObservedMeasurement;
@@ -42,8 +39,6 @@ import org.orekit.orbits.Orbit;
 import org.orekit.orbits.OrbitType;
 import org.orekit.orbits.PositionAngle;
 import org.orekit.propagation.PropagationType;
-import org.orekit.propagation.Propagator;
-import org.orekit.propagation.PropagatorsParallelizer;
 import org.orekit.propagation.SpacecraftState;
 import org.orekit.propagation.conversion.DSSTPropagatorBuilder;
 import org.orekit.propagation.semianalytical.dsst.DSSTPropagator;
@@ -56,20 +51,15 @@ import org.orekit.utils.ParameterDriver;
 import org.orekit.utils.ParameterDriversList;
 import org.orekit.utils.ParameterDriversList.DelegatingDriver;
 
-/** Class defining the process model dynamics to use with a {@link UnscentedKalmanEstimator}.
+/** Class defining the process model dynamics to use with a {@link SemiAnalyticalUnscentedKalmanEstimator}.
  * @author Gaëtan Pierre
+ * @author Bryan Cazabonne
  */
 public class SemiAnalyticalUnscentedKalmanModel implements KalmanEstimation, UnscentedProcess<MeasurementDecorator> {
 
     /** Initial builder for propagator. */
     private final DSSTPropagatorBuilder builder;
 
-    /** Builders for propagators. */
-    private List<DSSTPropagatorBuilder> propagatorBuilders;
-
-    /** Propagators. */
-    private List<Propagator> propagators;
-
     /** Estimated orbital parameters. */
     private final ParameterDriversList estimatedOrbitalParameters;
 
@@ -79,15 +69,6 @@ public class SemiAnalyticalUnscentedKalmanModel implements KalmanEstimation, Uns
     /** Estimated measurements parameters. */
     private final ParameterDriversList estimatedMeasurementsParameters;
 
-    /** Map for propagation parameters columns. */
-    private final Map<String, Integer> propagationParameterColumns;
-
-    /** Map for measurements parameters columns. */
-    private final Map<String, Integer> measurementParameterColumns;
-
-    /** Scaling factors. */
-    private final double[] scale;
-
     /** Provider for covariance matrice. */
     private final CovarianceMatrixProvider covarianceMatrixProvider;
 
@@ -97,6 +78,9 @@ public class SemiAnalyticalUnscentedKalmanModel implements KalmanEstimation, Uns
     /** Position angle type used during orbit determination. */
     private final PositionAngle angleType;
 
+    /** Orbit type used during orbit determination. */
+    private final OrbitType orbitType;
+
     /** Current corrected estimate. */
     private ProcessEstimate correctedEstimate;
 
@@ -106,23 +90,20 @@ public class SemiAnalyticalUnscentedKalmanModel implements KalmanEstimation, Uns
     /** Current number of measurement. */
     private int currentMeasurementNumber;
 
-    /** Reference date. */
-    private AbsoluteDate referenceDate;
-
     /** Current date. */
     private AbsoluteDate currentDate;
 
-    /** Predicted spacecraft states. */
-    private SpacecraftState predictedSpacecraftState;
+    /** Nominal mean spacecraft state. */
+    private SpacecraftState nominalMeanSpacecraftState;
 
-    /** Corrected spacecraft states. */
-    private SpacecraftState correctedSpacecraftState;
+    /** Previous nominal mean spacecraft state. */
+    private SpacecraftState previousNominalMeanSpacecraftState;
 
-    /** Nominal mean spacecraft states. */
-    private List<SpacecraftState> nominalMeanSpacecraftStates;
+    /** Predicted osculating spacecraft state. */
+    private SpacecraftState predictedSpacecraftState;
 
-    /** Previous nominal mean spacecraft states. */
-    private List<SpacecraftState> previousNominalMeanSpacecraftStates;
+    /** Corrected mean spacecraft state. */
+    private SpacecraftState correctedSpacecraftState;
 
     /** Predicted measurement. */
     private EstimatedMeasurement<?> predictedMeasurement;
@@ -130,6 +111,14 @@ public class SemiAnalyticalUnscentedKalmanModel implements KalmanEstimation, Uns
     /** Corrected measurement. */
     private EstimatedMeasurement<?> correctedMeasurement;
 
+    /** Predicted mean element filter correction. */
+    private RealVector predictedFilterCorrection;
+
+    /** Corrected mean element filter correction. */
+    private RealVector correctedFilterCorrection;
+
+    /** Propagators for the reference trajectories, up to current date. */
+    private DSSTPropagator dsstPropagator;
 
     /** Unscented Kalman process model constructor (package private).
      * @param propagatorBuilder propagators builders used to evaluate the orbits.
@@ -138,26 +127,24 @@ public class SemiAnalyticalUnscentedKalmanModel implements KalmanEstimation, Uns
      * @param measurementProcessNoiseMatrix provider for measurement process noise matrix
      */
     protected SemiAnalyticalUnscentedKalmanModel(final DSSTPropagatorBuilder propagatorBuilder,
-                                   final CovarianceMatrixProvider covarianceMatrixProvider,
-                                   final ParameterDriversList estimatedMeasurementParameters,
-                                   final CovarianceMatrixProvider measurementProcessNoiseMatrix) {
+                                                 final CovarianceMatrixProvider covarianceMatrixProvider,
+                                                 final ParameterDriversList estimatedMeasurementParameters,
+                                                 final CovarianceMatrixProvider measurementProcessNoiseMatrix) {
 
         this.builder                         = propagatorBuilder;
+        this.angleType                       = propagatorBuilder.getPositionAngle();
+        this.orbitType                       = propagatorBuilder.getOrbitType();
         this.estimatedMeasurementsParameters = estimatedMeasurementParameters;
-        this.measurementParameterColumns     = new HashMap<>(estimatedMeasurementsParameters.getDrivers().size());
         this.currentMeasurementNumber        = 0;
-        this.referenceDate                   = propagatorBuilder.getInitialOrbitDate();
-        this.currentDate                     = referenceDate;
+        this.currentDate                     = propagatorBuilder.getInitialOrbitDate();
         this.covarianceMatrixProvider        = covarianceMatrixProvider;
         this.measurementProcessNoiseMatrix   = measurementProcessNoiseMatrix;
-        this.propagators                     = new ArrayList<>();
-        this.propagatorBuilders              = new ArrayList<>();
-        this.angleType                       = builder.getPositionAngle();
+
         // Number of estimated parameters
         int columns = 0;
 
         // Set estimated orbital parameters
-        estimatedOrbitalParameters = new ParameterDriversList();
+        this.estimatedOrbitalParameters = new ParameterDriversList();
         for (final ParameterDriver driver : propagatorBuilder.getOrbitalParametersDrivers().getDrivers()) {
 
             // Verify if the driver reference date has been set
@@ -174,7 +161,7 @@ public class SemiAnalyticalUnscentedKalmanModel implements KalmanEstimation, Uns
         }
 
         // Set estimated propagation parameters
-        estimatedPropagationParameters = new ParameterDriversList();
+        this.estimatedPropagationParameters = new ParameterDriversList();
         final List<String> estimatedPropagationParametersNames = new ArrayList<>();
         for (final ParameterDriver driver : propagatorBuilder.getPropagationParametersDrivers().getDrivers()) {
 
@@ -197,7 +184,7 @@ public class SemiAnalyticalUnscentedKalmanModel implements KalmanEstimation, Uns
         estimatedPropagationParametersNames.sort(Comparator.naturalOrder());
 
         // Populate the map of propagation drivers' columns and update the total number of columns
-        propagationParameterColumns = new HashMap<>(estimatedPropagationParametersNames.size());
+        final Map<String, Integer> propagationParameterColumns = new HashMap<>(estimatedPropagationParametersNames.size());
         for (final String driverName : estimatedPropagationParametersNames) {
             propagationParameterColumns.put(driverName, columns);
             ++columns;
@@ -208,37 +195,9 @@ public class SemiAnalyticalUnscentedKalmanModel implements KalmanEstimation, Uns
             if (parameter.getReferenceDate() == null) {
                 parameter.setReferenceDate(currentDate);
             }
-            measurementParameterColumns.put(parameter.getName(), columns);
             ++columns;
         }
 
-        // Compute the scale factors
-        this.scale = new double[columns];
-        int index = 0;
-        for (final ParameterDriver driver : estimatedOrbitalParameters.getDrivers()) {
-            scale[index++] = driver.getScale();
-        }
-        for (final ParameterDriver driver : estimatedPropagationParameters.getDrivers()) {
-            scale[index++] = driver.getScale();
-        }
-        for (final ParameterDriver driver : estimatedMeasurementsParameters.getDrivers()) {
-            scale[index++] = driver.getScale();
-        }
-
-        // Initialize the estimated normalized state and fill its values
-        final RealVector correctedState = MatrixUtils.createRealVector(columns);
-
-        int p = 0;
-        for (final ParameterDriver driver : estimatedOrbitalParameters.getDrivers()) {
-            correctedState.setEntry(p++, driver.getValue());
-        }
-        for (final ParameterDriver driver : estimatedPropagationParameters.getDrivers()) {
-            correctedState.setEntry(p++, driver.getValue());
-        }
-        for (final ParameterDriver driver : estimatedMeasurementsParameters.getDrivers()) {
-            correctedState.setEntry(p++, driver.getValue());
-        }
-
         // Number of estimated measurement parameters
         final int nbMeas = estimatedMeasurementParameters.getNbParams();
 
@@ -246,29 +205,36 @@ public class SemiAnalyticalUnscentedKalmanModel implements KalmanEstimation, Uns
         final int nbDyn  = estimatedOrbitalParameters.getNbParams() +
                            estimatedPropagationParameters.getNbParams();
 
-        this.predictedSpacecraftState = propagatorBuilder.buildPropagator(propagatorBuilder.getSelectedNormalizedParameters()).getInitialState();
-        this.correctedSpacecraftState = predictedSpacecraftState;
+        // Build the reference propagator
+        this.dsstPropagator = getEstimatedPropagator();
+        final SpacecraftState meanState = dsstPropagator.initialIsOsculating() ?
+                         DSSTPropagator.computeMeanState(dsstPropagator.getInitialState(), dsstPropagator.getAttitudeProvider(), dsstPropagator.getAllForceModels()) :
+                         dsstPropagator.getInitialState();
+        this.nominalMeanSpacecraftState         = meanState;
+        this.predictedSpacecraftState           = meanState;
+        this.correctedSpacecraftState           = predictedSpacecraftState;
+        this.previousNominalMeanSpacecraftState = nominalMeanSpacecraftState;
+
+        // Initialize the estimated mean element filter correction
+        this.predictedFilterCorrection = MatrixUtils.createRealVector(columns);
+        this.correctedFilterCorrection = predictedFilterCorrection;
 
         // Covariance matrix
         final RealMatrix noiseK = MatrixUtils.createRealMatrix(nbDyn + nbMeas, nbDyn + nbMeas);
-        final RealMatrix noiseP = covarianceMatrixProvider.getInitialCovarianceMatrix(predictedSpacecraftState);
-
+        final RealMatrix noiseP = covarianceMatrixProvider.getInitialCovarianceMatrix(nominalMeanSpacecraftState);
         noiseK.setSubMatrix(noiseP.getData(), 0, 0);
-
         if (measurementProcessNoiseMatrix != null) {
-            final RealMatrix noiseM = measurementProcessNoiseMatrix.
-                                      getInitialCovarianceMatrix(correctedSpacecraftState);
+            final RealMatrix noiseM = measurementProcessNoiseMatrix.getInitialCovarianceMatrix(nominalMeanSpacecraftState);
             noiseK.setSubMatrix(noiseM.getData(), nbDyn, nbDyn);
         }
 
-        checkDimension(noiseK.getRowDimension(),
-                       propagatorBuilder.getOrbitalParametersDrivers(),
-                       propagatorBuilder.getPropagationParametersDrivers(),
-                       estimatedMeasurementsParameters);
-
+        KalmanEstimatorUtil.checkDimension(noiseK.getRowDimension(),
+                                           propagatorBuilder.getOrbitalParametersDrivers(),
+                                           propagatorBuilder.getPropagationParametersDrivers(),
+                                           estimatedMeasurementsParameters);
 
         // Initialize corrected estimate
-        this.correctedEstimate = new ProcessEstimate(0.0, correctedState, noiseK);
+        this.correctedEstimate = new ProcessEstimate(0.0, correctedFilterCorrection, noiseK);
 
     }
 
@@ -286,59 +252,63 @@ public class SemiAnalyticalUnscentedKalmanModel implements KalmanEstimation, Uns
         this.observer = observer;
     }
 
-    /** Process a single measurement.
-     * <p>
-     * Update the filter with the new measurements.
-     * </p>
+    /** Get the orbit type used during the estimation process.
+     * @return the orbit type
+     */
+    public OrbitType getOrbitType() {
+        return orbitType;
+    }
+
+    /** Get the position angle type used during the estimation process.
+     * @return the position angle type
+     */
+    public PositionAngle getAngleType() {
+        return angleType;
+    }
+
+    /** Get the current corrected estimate.
+     * @return current corrected estimate
+     */
+    public ProcessEstimate getEstimate() {
+        return correctedEstimate;
+    }
+
+    /** Process measurements.
      * @param observedMeasurements the list of measurements to process
-     * @param filter Extended Kalman Filter
+     * @param filter Unscented Kalman Filter
      * @return estimated propagator
      */
     public DSSTPropagator processMeasurements(final List<ObservedMeasurement<?>> observedMeasurements,
                                               final UnscentedKalmanFilter<MeasurementDecorator> filter) {
-        try {
-            // Compute sigma points
-            final ProcessEstimate estimate = filter.getCorrected();
-            final RealVector[] sigmaPoints = filter.getUnscentedTransformProvider().unscentedTransform(estimate.getState(), estimate.getCovariance());
-
-            for (int k = 0; k < sigmaPoints.length; ++k) {
-                // Current sigma point
-                final double[] currentPoint = sigmaPoints[k].copy().toArray();
-                // Create the corresponding orbit propagator
-                final DSSTPropagator currentPropagator = createPropagator(currentPoint);
-                // Add it to the list of propagators
-                propagators.add(currentPropagator);
-            }
-
-            // Create builders using the sigma points
-            propagatorBuilders = getEstimatedBuilders(sigmaPoints);
 
-            // Initialize spacecraft states
-            initializeMeanSpacecraftStates(sigmaPoints);
+        // Sort the measurement
+        observedMeasurements.sort(new ChronologicalComparator());
 
-            // Sort the measurement
-            observedMeasurements.sort(new ChronologicalComparator());
+        // Initialize step handler and set it to a parallelized propagator
+        final UskfMeasurementHandler  stepHandler = new UskfMeasurementHandler(this, filter, observedMeasurements, builder.getInitialOrbitDate());
+        dsstPropagator.getMultiplexer().add(stepHandler);
+        dsstPropagator.propagate(observedMeasurements.get(0).getDate(), observedMeasurements.get(observedMeasurements.size() - 1).getDate());
 
-            final UskfMeasurementHandler stepHandler = new UskfMeasurementHandler(this, filter, observedMeasurements, builder.getInitialOrbitDate(), propagators, propagatorBuilders, sigmaPoints);
-            final PropagatorsParallelizer parallelizer = new PropagatorsParallelizer(propagators, stepHandler);
+        // Return the last estimated propagator
+        return getEstimatedPropagator();
 
-            parallelizer.propagate(observedMeasurements.get(0).getDate(), observedMeasurements.get(observedMeasurements.size() - 1).getDate());
-
-            // Return the last estimated propagator
-            return createPropagator(correctedEstimate.getState().toArray());
+    }
 
-        } catch (MathRuntimeException mrte) {
-            throw new OrekitException(mrte);
-        }
+    /** Get the propagator estimated with the values set in the propagator builder.
+     * @return propagator based on the current values in the builder
+     */
+    public DSSTPropagator getEstimatedPropagator() {
+        // Return propagator built with current instantiation of the propagator builder
+        return builder.buildPropagator(builder.getSelectedNormalizedParameters());
     }
+
+    /** {@inheritDoc} */
     @Override
     public UnscentedEvolution getEvolution(final double previousTime, final RealVector[] sigmaPoints,
-           final MeasurementDecorator measurement) {
+                                           final MeasurementDecorator measurement) {
 
         // Set a reference date for all measurements parameters that lack one (including the not estimated ones)
         final ObservedMeasurement<?> observedMeasurement = measurement.getObservedMeasurement();
-        final RealVector[] predictedMeasurements = new RealVector[sigmaPoints.length];
-
         for (final ParameterDriver driver : observedMeasurement.getParametersDrivers()) {
             if (driver.getReferenceDate() == null) {
                 driver.setReferenceDate(builder.getInitialOrbitDate());
@@ -350,25 +320,23 @@ public class SemiAnalyticalUnscentedKalmanModel implements KalmanEstimation, Uns
 
         // Update the current date
         currentDate = measurement.getObservedMeasurement().getDate();
-        final RealVector[] nominalMeanElementsStates = computeMeanElementsStates();
-        // Calculate the predicted osculating elements
-        final RealVector[] osculating = computeOsculatingElementsStates();
 
-        for (int i = 0; i < osculating.length; i++) {
-            final Orbit osculatingOrbit = OrbitType.EQUINOCTIAL.mapArrayToOrbit(osculating[i].toArray(), null, builder.getPositionAngle(),
-                    currentDate, nominalMeanSpacecraftStates.get(i).getMu(),
-                    nominalMeanSpacecraftStates.get(i).getFrame());
+        // Estimate the measurement for each predicted state
+        final RealVector[] predictedMeasurements = new RealVector[sigmaPoints.length];
+        for (int k = 0; k < sigmaPoints.length; ++k) {
 
+            // Calculate the predicted osculating elements for the current mean state
+            final RealVector osculating = computeOsculatingElements(sigmaPoints[k], nominalMeanSpacecraftState);
+            final Orbit osculatingOrbit = orbitType.mapArrayToOrbit(osculating.toArray(), null, angleType,
+                                                                    currentDate, builder.getMu(), builder.getFrame());
+
+            // Then, estimate the measurement
             final EstimatedMeasurement<?> estimated = observedMeasurement.estimate(currentMeasurementNumber,
-                    currentMeasurementNumber,
-                    new SpacecraftState[] {
-                        new SpacecraftState(osculatingOrbit,
-                        nominalMeanSpacecraftStates.get(i).getAttitude(),
-                        nominalMeanSpacecraftStates.get(i).getMass(),
-                        nominalMeanSpacecraftStates.get(i).getAdditionalStatesValues(),
-                        nominalMeanSpacecraftStates.get(i).getAdditionalStatesDerivatives())
-                        });
-            predictedMeasurements[i] = new ArrayRealVector(estimated.getEstimatedValue());
+                                                                                   currentMeasurementNumber,
+                                                                                   new SpacecraftState[] {
+                                                                                       new SpacecraftState(osculatingOrbit)
+                                                                                   });
+            predictedMeasurements[k] = new ArrayRealVector(estimated.getEstimatedValue());
         }
 
         // Number of estimated measurement parameters
@@ -379,40 +347,40 @@ public class SemiAnalyticalUnscentedKalmanModel implements KalmanEstimation, Uns
 
         // Covariance matrix
         final RealMatrix noiseK = MatrixUtils.createRealMatrix(nbDyn + nbMeas, nbDyn + nbMeas);
-        final RealMatrix noiseP = covarianceMatrixProvider.getProcessNoiseMatrix(correctedSpacecraftState, predictedSpacecraftState);
+        final RealMatrix noiseP = covarianceMatrixProvider.getProcessNoiseMatrix(previousNominalMeanSpacecraftState, nominalMeanSpacecraftState);
         noiseK.setSubMatrix(noiseP.getData(), 0, 0);
         if (measurementProcessNoiseMatrix != null) {
-            final RealMatrix noiseM = measurementProcessNoiseMatrix.getProcessNoiseMatrix(correctedSpacecraftState, predictedSpacecraftState);
+            final RealMatrix noiseM = measurementProcessNoiseMatrix.getProcessNoiseMatrix(previousNominalMeanSpacecraftState, nominalMeanSpacecraftState);
             noiseK.setSubMatrix(noiseM.getData(), nbDyn, nbDyn);
         }
 
         // Verify dimension
-        checkDimension(noiseK.getRowDimension(),
-                       builder.getOrbitalParametersDrivers(),
-                       builder.getPropagationParametersDrivers(),
-                       estimatedMeasurementsParameters);
-
+        KalmanEstimatorUtil.checkDimension(noiseK.getRowDimension(),
+                                           builder.getOrbitalParametersDrivers(),
+                                           builder.getPropagationParametersDrivers(),
+                                           estimatedMeasurementsParameters);
 
+        // Return
+        return new UnscentedEvolution(measurement.getTime(), sigmaPoints, predictedMeasurements, noiseK);
 
-        return new UnscentedEvolution(measurement.getTime(), nominalMeanElementsStates, predictedMeasurements, noiseK);
     }
 
+    /** {@inheritDoc} */
     @Override
-    public RealVector getInnovation(final MeasurementDecorator measurement, final RealVector predictedMeas, final RealVector predictedState,
-            final RealMatrix innovationCovarianceMatrix) {
-
+    public RealVector getInnovation(final MeasurementDecorator measurement, final RealVector predictedMeas,
+                                    final RealVector predictedState, final RealMatrix innovationCovarianceMatrix) {
 
+        // Predicted filter correction
+        predictedFilterCorrection = predictedState;
 
-        // Calculate the corrected osculating elements
-        final double[] osculating = computeOsculatingElements(predictedState);
-        final Orbit osculatingOrbit = OrbitType.EQUINOCTIAL.mapArrayToOrbit(osculating, null, angleType,
-                                                                            currentDate, builder.getMu(),
-                                                                            builder.getFrame());
+        // Predicted measurement
+        final RealVector osculating = computeOsculatingElements(predictedFilterCorrection, nominalMeanSpacecraftState);
+        final Orbit osculatingOrbit = orbitType.mapArrayToOrbit(osculating.toArray(), null, angleType,
+                                                                currentDate, builder.getMu(), builder.getFrame());
         predictedSpacecraftState = new SpacecraftState(osculatingOrbit);
-        predictedMeasurement = measurement.getObservedMeasurement().estimate(currentMeasurementNumber, currentMeasurementNumber, new SpacecraftState[] {predictedSpacecraftState});
-//        predictedMeasurement.setEstimatedValue(predictedMeas.toArray()); // Regression on testRangeWithTesseral() and testRangeWithZonal() if uncommented
+        predictedMeasurement = measurement.getObservedMeasurement().estimate(currentMeasurementNumber, currentMeasurementNumber, getPredictedSpacecraftStates());
 
-        // set estimated value to the predicted value by the filter
+        // Apply the dynamic outlier filter, if it exists
         applyDynamicOutlierFilter(predictedMeasurement, innovationCovarianceMatrix);
         if (predictedMeasurement.getStatus() == EstimatedMeasurement.Status.REJECTED)  {
             // set innovation to null to notify filter measurement is rejected
@@ -428,6 +396,7 @@ public class SemiAnalyticalUnscentedKalmanModel implements KalmanEstimation, Uns
             }
             return MatrixUtils.createRealVector(residuals);
         }
+
     }
 
 
@@ -437,70 +406,32 @@ public class SemiAnalyticalUnscentedKalmanModel implements KalmanEstimation, Uns
      */
     public void finalizeEstimation(final ObservedMeasurement<?> observedMeasurement,
                                    final ProcessEstimate estimate) {
+        // Update the process estimate
         correctedEstimate = estimate;
-        previousNominalMeanSpacecraftStates = nominalMeanSpacecraftStates;
+        // Corrected filter correction
+        correctedFilterCorrection = estimate.getState();
 
-        final double[] osculating = computeOsculatingElements(estimate.getState());
-        final Orbit osculatingOrbit = OrbitType.EQUINOCTIAL.mapArrayToOrbit(osculating, null, angleType,
-                                                                            currentDate, builder.getMu(),
-                                                                            builder.getFrame());
-        correctedSpacecraftState = new SpacecraftState(osculatingOrbit);
+        // Update the previous nominal mean spacecraft state
+        previousNominalMeanSpacecraftState = nominalMeanSpacecraftState;
+
+        // Update the previous nominal mean spacecraft state
+        // Calculate the corrected osculating elements
+        final RealVector osculating = computeOsculatingElements(correctedFilterCorrection, nominalMeanSpacecraftState);
+        final Orbit osculatingOrbit = orbitType.mapArrayToOrbit(osculating.toArray(), null, builder.getPositionAngle(),
+                                                                currentDate, builder.getMu(), builder.getFrame());
 
         // Compute the corrected measurements
+        correctedSpacecraftState = new SpacecraftState(osculatingOrbit);
         correctedMeasurement = observedMeasurement.estimate(currentMeasurementNumber,
                                                             currentMeasurementNumber,
-                                                            new SpacecraftState[] {
-                                                                new SpacecraftState(osculatingOrbit,
-                                                                                    correctedSpacecraftState.getAttitude(),
-                                                                                    correctedSpacecraftState.getMass(),
-                                                                                    correctedSpacecraftState.getAdditionalStatesValues(),
-                                                                                    correctedSpacecraftState.getAdditionalStatesDerivatives())
-                                                            });
+                                                            getCorrectedSpacecraftStates());
 
-        // Update current date in the builder
-        builder.resetOrbit(correctedSpacecraftState.getOrbit());
     }
 
-
-    /** Get the current corrected estimate.
-     * @return current corrected estimate
-     */
-    public ProcessEstimate getEstimate() {
-        return correctedEstimate;
-    }
-
-
-    /** Get the builder estimated with the values of parameters.
-     * @param parameters array containing orbital parameters
-     * @return builder based on the values of parameters
-     */
-    public DSSTPropagatorBuilder getEstimatedBuilder(final double[] parameters) {
-        final DSSTPropagatorBuilder copy = builder.copy();
-        int j = 0;
-        for (DelegatingDriver orbitalDriver : copy.getOrbitalParametersDrivers().getDrivers()) {
-            if (orbitalDriver.isSelected()) {
-                orbitalDriver.setValue(parameters[j++]);
-            }
-        }
-        for (DelegatingDriver propagationDriver : copy.getPropagationParametersDrivers().getDrivers()) {
-            if (propagationDriver.isSelected()) {
-                propagationDriver.setValue(parameters[j++]);
-
-            }
-        }
-
-        return copy;
-    }
-
-
-    public List<DSSTPropagatorBuilder> getEstimatedBuilders(final RealVector[] sigmaPoints) {
-        /** Propagators */
-        final List<DSSTPropagatorBuilder> builders = new ArrayList<DSSTPropagatorBuilder>();
-        for (int i = 0; i < sigmaPoints.length; i++) {
-            final double[] currentPoint = sigmaPoints[i].copy().toArray();
-            builders.add(getEstimatedBuilder(currentPoint));
-        }
-        return builders;
+    /** Finalize estimation operations on the observation grid. */
+    public void finalizeOperationsObservationGrid() {
+        // Update parameters
+        updateParameters();
     }
 
     /** {@inheritDoc} */
@@ -539,7 +470,7 @@ public class SemiAnalyticalUnscentedKalmanModel implements KalmanEstimation, Uns
         // Method {@link ParameterDriver#getValue()} is used to get
         // the physical values of the state.
         // The scales'array is used to get the size of the state vector
-        final RealVector physicalEstimatedState = new ArrayRealVector(scale.length);
+        final RealVector physicalEstimatedState = new ArrayRealVector(getEstimate().getState().getDimension());
         int i = 0;
         for (final DelegatingDriver driver : getEstimatedOrbitalParameters().getDrivers()) {
             physicalEstimatedState.setEntry(i++, driver.getValue());
@@ -557,7 +488,6 @@ public class SemiAnalyticalUnscentedKalmanModel implements KalmanEstimation, Uns
     /** {@inheritDoc} */
     @Override
     public RealMatrix getPhysicalEstimatedCovarianceMatrix() {
-
         return correctedEstimate.getCovariance();
     }
 
@@ -584,16 +514,19 @@ public class SemiAnalyticalUnscentedKalmanModel implements KalmanEstimation, Uns
     public RealMatrix getPhysicalKalmanGain() {
         return correctedEstimate.getKalmanGain();
     }
+
     /** {@inheritDoc} */
     @Override
     public int getCurrentMeasurementNumber() {
         return currentMeasurementNumber;
     }
+
     /** {@inheritDoc} */
     @Override
     public AbsoluteDate getCurrentDate() {
         return currentDate;
     }
+
     /** {@inheritDoc} */
     @Override
     public EstimatedMeasurement<?> getPredictedMeasurement() {
@@ -606,198 +539,36 @@ public class SemiAnalyticalUnscentedKalmanModel implements KalmanEstimation, Uns
         return correctedMeasurement;
     }
 
+    /** Update the nominal spacecraft state.
+     * @param nominal nominal spacecraft state
+     */
+    public void updateNominalSpacecraftState(final SpacecraftState nominal) {
+        this.nominalMeanSpacecraftState = nominal;
+        // Update the builder with the nominal mean elements orbit
+        builder.resetOrbit(nominal.getOrbit(), PropagationType.MEAN);
+    }
+
     /** Update the DSST short periodic terms.
      * @param state current mean state
-     * @param dsstBuilder builder associated to the state
      */
-    public void updateShortPeriods(final SpacecraftState state, final DSSTPropagatorBuilder dsstBuilder) {
+    public void updateShortPeriods(final SpacecraftState state) {
         // Loop on DSST force models
-        for (final DSSTForceModel model : dsstBuilder.getAllForceModels()) {
+        for (final DSSTForceModel model : dsstPropagator.getAllForceModels()) {
             model.updateShortPeriodTerms(model.getParameters(), state);
         }
-
-    }
-    public void initializeMeanSpacecraftStates(final RealVector[] sigmaPoints) {
-        nominalMeanSpacecraftStates = new ArrayList<>();
-        previousNominalMeanSpacecraftStates = new ArrayList<>();
-        for (int i = 0; i < propagators.size(); i++) {
-            final Orbit orbit = OrbitType.EQUINOCTIAL.mapArrayToOrbit(sigmaPoints[i].toArray(), null, angleType,
-                    currentDate, builder.getMu(),
-                    builder.getFrame());
-            nominalMeanSpacecraftStates.add(new SpacecraftState(orbit));
-            previousNominalMeanSpacecraftStates.add(nominalMeanSpacecraftStates.get(i));
-        }
     }
+
     /** Initialize the short periodic terms for the Kalman Filter.
      * @param meanState mean state for auxiliary elements
-     * @param propagator propagator associated to the state
      */
-    public void initializeShortPeriodicTerms(final SpacecraftState meanState, final Propagator propagator) {
-
+    public void initializeShortPeriodicTerms(final SpacecraftState meanState) {
         final List<ShortPeriodTerms> shortPeriodTerms = new ArrayList<ShortPeriodTerms>();
-        for (final DSSTForceModel force :  ((DSSTPropagator) propagator).getAllForceModels()) {
+        for (final DSSTForceModel force :  builder.getAllForceModels()) {
             shortPeriodTerms.addAll(force.initializeShortPeriodTerms(new AuxiliaryElements(meanState.getOrbit(), 1), PropagationType.OSCULATING, force.getParameters()));
         }
-        ((DSSTPropagator) propagator).setShortPeriodTerms(shortPeriodTerms);
-    }
-    /**
-     * Create a propagator for the given sigma point.
-     * @param point input sigma point
-     * @return the corresponding orbit propagator
-     */
-    private DSSTPropagator createPropagator(final double[] point) {
-        // Create a new instance of the current propagator builder
-        final DSSTPropagatorBuilder copy = builder.copy();
-        // Convert the given sigma point to an orbit
-        final Orbit orbit = OrbitType.EQUINOCTIAL.mapArrayToOrbit(point, null, angleType, copy.getInitialOrbitDate(),
-                                                      copy.getMu(), copy.getFrame());
-        copy.resetOrbit(orbit);
-        // Create the propagator
-        final DSSTPropagator propagator = copy.buildPropagator(copy.getSelectedNormalizedParameters());
-        return propagator;
-    }
-
-    /** Check dimension.
-     * @param dimension dimension to check
-     * @param orbitalParameters orbital parameters
-     * @param propagationParameters propagation parameters
-     * @param measurementParameters measurements parameters
-     */
-    private void checkDimension(final int dimension,
-                                final ParameterDriversList orbitalParameters,
-                                final ParameterDriversList propagationParameters,
-                                final ParameterDriversList measurementParameters) {
-
-        // count parameters, taking care of counting all orbital parameters
-        // regardless of them being estimated or not
-        int requiredDimension = orbitalParameters.getNbParams();
-        for (final ParameterDriver driver : propagationParameters.getDrivers()) {
-            if (driver.isSelected()) {
-                ++requiredDimension;
-            }
-        }
-        for (final ParameterDriver driver : measurementParameters.getDrivers()) {
-            if (driver.isSelected()) {
-                ++requiredDimension;
-            }
-        }
-
-        if (dimension != requiredDimension) {
-            // there is a problem, set up an explicit error message
-            final StringBuilder sBuilder = new StringBuilder();
-            for (final ParameterDriver driver : orbitalParameters.getDrivers()) {
-                if (sBuilder.length() > 0) {
-                    sBuilder.append(", ");
-                }
-                sBuilder.append(driver.getName());
-            }
-            for (final ParameterDriver driver : propagationParameters.getDrivers()) {
-                if (driver.isSelected()) {
-                    sBuilder.append(driver.getName());
-                }
-            }
-            for (final ParameterDriver driver : measurementParameters.getDrivers()) {
-                if (driver.isSelected()) {
-                    sBuilder.append(driver.getName());
-                }
-            }
-            throw new OrekitException(OrekitMessages.DIMENSION_INCONSISTENT_WITH_PARAMETERS,
-                                      dimension, builder.toString());
-        }
-
-    }
-
-
-    /** Compute the predicted osculating elements.
-     * @return the predicted osculating element
-     */
-    private RealVector[] computeOsculatingElementsStates() {
-
-        // Number of estimated orbital parameters
-        final RealVector[] osculatingElementsStates = new RealVector[nominalMeanSpacecraftStates.size()];
-        final int nbOrb = getNumberSelectedOrbitalDrivers();
-        for (int i = 0; i < nominalMeanSpacecraftStates.size(); i++) {
-            final double[] shortPeriodTerms = ((DSSTPropagator) propagators.get(i)).getShortPeriodTermsValue(nominalMeanSpacecraftStates.get(i));
-            // Nominal mean elements
-            final double[] nominalMeanElements = new double[nbOrb];
-            OrbitType.EQUINOCTIAL.mapOrbitToArray(nominalMeanSpacecraftStates.get(i).getOrbit(), propagatorBuilders.get(i).getPositionAngle(), nominalMeanElements, null);
-         // Ref [1] Eq. 3.6
-            final double[] osculatingElements = new double[nbOrb];
-            for (int j = 0; j < nbOrb; j++) {
-                osculatingElements[j] = nominalMeanElements[j] +
-                                        shortPeriodTerms[j];
-            }
-            osculatingElementsStates[i] = new ArrayRealVector(osculatingElements);
-        }
-
-        return osculatingElementsStates;
-
-    }
-    /** Convert the nominal mean spacecraft state into array of RealVector.
-     * @return mean elements
-     */
-    private RealVector[] computeMeanElementsStates() {
-        // Number of estimated orbital parameters
-        final RealVector[] meanElementsStates = new RealVector[nominalMeanSpacecraftStates.size()];
-        final int nbOrb = getNumberSelectedOrbitalDrivers();
-        for (int i = 0; i < nominalMeanSpacecraftStates.size(); i++) {
-            // Nominal mean elements
-            final double[] nominalMeanElements = new double[nbOrb];
-            OrbitType.EQUINOCTIAL.mapOrbitToArray(nominalMeanSpacecraftStates.get(i).getOrbit(), propagatorBuilders.get(i).getPositionAngle(), nominalMeanElements, null);
-            meanElementsStates[i] = new ArrayRealVector(nominalMeanElements);
-
-        }
-        return meanElementsStates;
-
+        dsstPropagator.setShortPeriodTerms(shortPeriodTerms);
     }
 
-    /** Compute the predicted osculating elements.
-     * @param state state whose osculating elements are supposed to be computed
-     * @return the predicted osculating element
-     */
-    protected double[] computeOsculatingElements(final RealVector state) {
-
-        // Number of estimated orbital parameters
-        // update the predicted spacecraft state with predictedState
-        final Orbit orbit = builder.getOrbitType().mapArrayToOrbit(state.toArray(), null, angleType,
-                currentDate, builder.getMu(), builder.getFrame());
-        final SpacecraftState s = new SpacecraftState(orbit);
-        final int nbOrb = getNumberSelectedOrbitalDrivers();
-        final double[] shortPeriodTerms = ((DSSTPropagator) propagators.get(0)).getShortPeriodTermsValue(s);
-        // Nominal mean elements
-        final double[] nominalMeanElements = new double[nbOrb];
-        OrbitType.EQUINOCTIAL.mapOrbitToArray(s.getOrbit(), angleType, nominalMeanElements, null);
-        // Ref [1] Eq. 3.6
-        final double[] osculatingElements = new double[nbOrb];
-        for (int j = 0; j < nbOrb; j++) {
-            osculatingElements[j] = nominalMeanElements[j] +
-                                        shortPeriodTerms[j];
-        }
-        return osculatingElements;
-
-    }
-    /** Compute the predicted osculating elements.
-     * @param s Spacecraft state whose osculating elements are supposed to be computed
-     * @param index the index associated to the state
-     * @return the predicted osculating element
-     */
-    protected double[] computeOsculatingElements(final SpacecraftState s, final int index) {
-
-        // Number of estimated orbital parameters
-        final int nbOrb = getNumberSelectedOrbitalDrivers();
-        final double[] shortPeriodTerms = ((DSSTPropagator) propagators.get(index)).getShortPeriodTermsValue(s);
-        // Nominal mean elements
-        final double[] nominalMeanElements = new double[nbOrb];
-        OrbitType.EQUINOCTIAL.mapOrbitToArray(s.getOrbit(), angleType, nominalMeanElements, null);
-        // Ref [1] Eq. 3.6
-        final double[] osculatingElements = new double[nbOrb];
-        for (int j = 0; j < nbOrb; j++) {
-            osculatingElements[j] = nominalMeanElements[j] +
-                                        shortPeriodTerms[j];
-        }
-        return osculatingElements;
-
-    }
     /** Set and apply a dynamic outlier filter on a measurement.<p>
      * Loop on the modifiers to see if a dynamic outlier filter needs to be applied.<p>
      * Compute the sigma array using the matrix in input and set the filter.<p>
@@ -842,53 +613,78 @@ public class SemiAnalyticalUnscentedKalmanModel implements KalmanEstimation, Uns
         }
     }
 
+    /** Compute the predicted osculating elements.
+     * @param filterCorrection physical kalman filter correction
+     * @param meanState mean spacecraft state
+     * @return the predicted osculating element
+     */
+    private RealVector computeOsculatingElements(final RealVector filterCorrection, final SpacecraftState meanState) {
+
+        // Convert the input predicted mean state to a SpacecraftState
+        final RealVector stateVector = toRealVector(meanState);
+
+        // Short periodic terms
+        final RealVector shortPeriodTerms = new ArrayRealVector(dsstPropagator.getShortPeriodTermsValue(meanState));
+
+        // Return
+        return stateVector.add(filterCorrection).add(shortPeriodTerms);
+
+    }
+
+    /** Convert a SpacecraftState to a RealVector.
+     * @param state the input SpacecraftState
+     * @return the corresponding RealVector
+     */
+    private RealVector toRealVector(final SpacecraftState state) {
+
+        // Convert orbit to array
+        final double[] stateArray = new double[6];
+        orbitType.mapOrbitToArray(state.getOrbit(), angleType, stateArray, null);
+
+        // Return the SpacecraftState
+        return new ArrayRealVector(stateArray);
+
+    }
+
     /** Get the number of estimated orbital parameters.
      * @return the number of estimated orbital parameters
      */
-    private int getNumberSelectedOrbitalDrivers() {
+    public int getNumberSelectedOrbitalDrivers() {
         return estimatedOrbitalParameters.getNbParams();
     }
 
     /** Get the number of estimated propagation parameters.
      * @return the number of estimated propagation parameters
      */
-    private int getNumberSelectedPropagationDrivers() {
+    public int getNumberSelectedPropagationDrivers() {
         return estimatedPropagationParameters.getNbParams();
     }
 
     /** Get the number of estimated measurement parameters.
      * @return the number of estimated measurement parameters
      */
-    private int getNumberSelectedMeasurementDrivers() {
+    public int getNumberSelectedMeasurementDrivers() {
         return estimatedMeasurementsParameters.getNbParams();
     }
 
-    /**
-     * Update the nominal Spacecraft state using interpolated state.
-     * @param interpolatedState the interpolated state
-     * @param propagatorBuilder builder associated to the state
-     * @param index index of the sigma point associated to the state
+    /** Update the estimated parameters after the correction phase of the filter.
+     * The min/max allowed values are handled by the parameter themselves.
      */
-    public void updateNominalSpacecraftState(final SpacecraftState interpolatedState, final DSSTPropagatorBuilder propagatorBuilder, final int index) {
-        previousNominalMeanSpacecraftStates.set(index, nominalMeanSpacecraftStates.get(index));
-        nominalMeanSpacecraftStates.set(index, interpolatedState);
-        propagatorBuilder.resetOrbit(interpolatedState.getOrbit(), PropagationType.MEAN);
-    }
-
-    public void finalizeOperationsObservationGrid(final RealVector[] sigmaPoints) {
-        for (int i = 0; i < sigmaPoints.length; i++) {
-            int j = 0;
-            for (final DelegatingDriver driver : propagatorBuilders.get(i).getOrbitalParametersDrivers().getDrivers()) {
-                if (driver.isSelected()) {
-                    driver.setValue(sigmaPoints[i].getEntry(j++));
-                }
-            }
-            for (final DelegatingDriver driver : propagatorBuilders.get(i).getPropagationParametersDrivers().getDrivers()) {
-                if (driver.isSelected()) {
-                    driver.setValue(sigmaPoints[i].getEntry(j++));
-                }
-            }
+    private void updateParameters() {
+        final RealVector correctedState = correctedEstimate.getState();
+        int i = 0;
+        for (final DelegatingDriver driver : getEstimatedOrbitalParameters().getDrivers()) {
+            // let the parameter handle min/max clipping
+            driver.setValue(driver.getValue() + correctedState.getEntry(i++));
+        }
+        for (final DelegatingDriver driver : getEstimatedPropagationParameters().getDrivers()) {
+            // let the parameter handle min/max clipping
+            driver.setValue(driver.getValue() + correctedState.getEntry(i++));
+        }
+        for (final DelegatingDriver driver : getEstimatedMeasurementsParameters().getDrivers()) {
+            // let the parameter handle min/max clipping
+            driver.setValue(driver.getValue() + correctedState.getEntry(i++));
         }
-
     }
+
 }
diff --git a/src/main/java/org/orekit/estimation/sequential/UnscentedKalmanEstimator.java b/src/main/java/org/orekit/estimation/sequential/UnscentedKalmanEstimator.java
index 99f271facef8cc070c95f1bb44d439c468641dc8..e656dd0f2cf21155f68b2d9ef3884d136eaa5393 100644
--- a/src/main/java/org/orekit/estimation/sequential/UnscentedKalmanEstimator.java
+++ b/src/main/java/org/orekit/estimation/sequential/UnscentedKalmanEstimator.java
@@ -20,14 +20,11 @@ import org.hipparchus.exception.MathRuntimeException;
 import org.hipparchus.filtering.kalman.ProcessEstimate;
 import org.hipparchus.filtering.kalman.unscented.UnscentedKalmanFilter;
 import org.hipparchus.linear.MatrixDecomposer;
-import org.hipparchus.linear.MatrixUtils;
 import org.hipparchus.linear.RealMatrix;
 import org.hipparchus.linear.RealVector;
 import org.hipparchus.util.UnscentedTransformProvider;
 import org.orekit.errors.OrekitException;
 import org.orekit.estimation.measurements.ObservedMeasurement;
-import org.orekit.estimation.measurements.PV;
-import org.orekit.estimation.measurements.Position;
 import org.orekit.propagation.Propagator;
 import org.orekit.propagation.conversion.NumericalPropagatorBuilder;
 import org.orekit.time.AbsoluteDate;
@@ -191,7 +188,7 @@ public class UnscentedKalmanEstimator {
      */
     public Propagator estimationStep(final ObservedMeasurement<?> observedMeasurement) {
         try {
-            final ProcessEstimate estimate = filter.estimationStep(decorate(observedMeasurement));
+            final ProcessEstimate estimate = filter.estimationStep(KalmanEstimatorUtil.decorate(observedMeasurement, referenceDate));
             processModel.finalizeEstimation(observedMeasurement, estimate);
             if (observer != null) {
                 observer.evaluationPerformed(processModel);
@@ -214,39 +211,4 @@ public class UnscentedKalmanEstimator {
         return propagator;
     }
 
-    /** Decorate an observed measurement.
-     * <p>
-     * The "physical" measurement noise matrix is the covariance matrix of the measurement.
-     * Normalizing it consists in applying the following equation: Rn[i,j] =  R[i,j]/σ[i]/σ[j]
-     * Thus the normalized measurement noise matrix is the matrix of the correlation coefficients
-     * between the different components of the measurement.
-     * </p>
-     * @param observedMeasurement the measurement
-     * @return decorated measurement
-     */
-    private MeasurementDecorator decorate(final ObservedMeasurement<?> observedMeasurement) {
-
-        // Normalized measurement noise matrix contains 1 on its diagonal and correlation coefficients
-        // of the measurement on its non-diagonal elements.
-        // Indeed, the "physical" measurement noise matrix is the covariance matrix of the measurement
-        // Normalizing it leaves us with the matrix of the correlation coefficients
-        final RealMatrix covariance;
-        if (observedMeasurement instanceof PV) {
-            // For PV measurements we do have a covariance matrix and thus a correlation coefficients matrix
-            final PV pv = (PV) observedMeasurement;
-            covariance = MatrixUtils.createRealMatrix(pv.getCorrelationCoefficientsMatrix());
-        } else if (observedMeasurement instanceof Position) {
-            // For Position measurements we do have a covariance matrix and thus a correlation coefficients matrix
-            final Position position = (Position) observedMeasurement;
-            covariance = MatrixUtils.createRealMatrix(position.getCorrelationCoefficientsMatrix());
-        } else {
-            // For other measurements we do not have a covariance matrix.
-            // Thus the correlation coefficients matrix is an identity matrix.
-            covariance = MatrixUtils.createRealIdentityMatrix(observedMeasurement.getDimension());
-        }
-
-        return new MeasurementDecorator(observedMeasurement, covariance, referenceDate);
-
-    }
-
 }
diff --git a/src/main/java/org/orekit/estimation/sequential/UskfMeasurementHandler.java b/src/main/java/org/orekit/estimation/sequential/UskfMeasurementHandler.java
index ea55cbb8dee25139b53a28ec0957267273458a2c..94d6baa5d09081f93454fb6e8e14a64d7b9979b2 100644
--- a/src/main/java/org/orekit/estimation/sequential/UskfMeasurementHandler.java
+++ b/src/main/java/org/orekit/estimation/sequential/UskfMeasurementHandler.java
@@ -21,17 +21,10 @@ import java.util.List;
 import org.hipparchus.exception.MathRuntimeException;
 import org.hipparchus.filtering.kalman.ProcessEstimate;
 import org.hipparchus.filtering.kalman.unscented.UnscentedKalmanFilter;
-import org.hipparchus.linear.MatrixUtils;
-import org.hipparchus.linear.RealMatrix;
-import org.hipparchus.linear.RealVector;
 import org.orekit.errors.OrekitException;
 import org.orekit.estimation.measurements.ObservedMeasurement;
-import org.orekit.estimation.measurements.PV;
-import org.orekit.estimation.measurements.Position;
-import org.orekit.propagation.Propagator;
 import org.orekit.propagation.SpacecraftState;
-import org.orekit.propagation.conversion.DSSTPropagatorBuilder;
-import org.orekit.propagation.sampling.MultiSatStepHandler;
+import org.orekit.propagation.sampling.OrekitStepHandler;
 import org.orekit.propagation.sampling.OrekitStepInterpolator;
 import org.orekit.time.AbsoluteDate;
 
@@ -40,22 +33,7 @@ import org.orekit.time.AbsoluteDate;
  * @author Gaëtan Pierre
  * @author Bryan Cazabonne
  */
-public class UskfMeasurementHandler implements MultiSatStepHandler {
-
-    /** Least squares model. */
-    private final SemiAnalyticalUnscentedKalmanModel model;
-
-    /** DSST propagator builder. */
-    private final List<DSSTPropagatorBuilder> builders;
-
-    /** DSST propagator. */
-    private final List<Propagator> propagators;
-
-    /** Extended Kalman Filter. */
-    private final UnscentedKalmanFilter<MeasurementDecorator> filter;
-
-    /** Underlying measurements. */
-    private final List<ObservedMeasurement<?>> observedMeasurements;
+public class UskfMeasurementHandler implements OrekitStepHandler {
 
     /** Index of the next measurement component in the model. */
     private int index;
@@ -66,127 +44,82 @@ public class UskfMeasurementHandler implements MultiSatStepHandler {
     /** Observer to retrieve current estimation info. */
     private KalmanObserver observer;
 
-    /** Sigma points of the current step. */
-    private RealVector[] sigmaPoints;
+    /** Kalman model. */
+    private final SemiAnalyticalUnscentedKalmanModel model;
+
+    /** Unscented Kalman Filter. */
+    private final UnscentedKalmanFilter<MeasurementDecorator> filter;
+
+    /** Underlying measurements. */
+    private final List<ObservedMeasurement<?>> observedMeasurements;
 
     /** Simple constructor.
      * @param model semi-analytical kalman model
      * @param filter kalman filter instance
      * @param observedMeasurements list of observed measurements
      * @param referenceDate reference date
-     * @param propagators propagators
-     * @param builders builders
-     * @param sigmaPoints sigma points
      */
     public UskfMeasurementHandler(final SemiAnalyticalUnscentedKalmanModel model,
                                   final UnscentedKalmanFilter<MeasurementDecorator> filter,
                                   final List<ObservedMeasurement<?>> observedMeasurements,
-                                  final AbsoluteDate referenceDate,
-                                  final List<Propagator> propagators,
-                                  final List<DSSTPropagatorBuilder> builders,
-                                  final RealVector[] sigmaPoints) {
+                                  final AbsoluteDate referenceDate) {
         this.model                = model;
         this.filter               = filter;
         this.observer             = model.getObserver();
         this.observedMeasurements = observedMeasurements;
         this.referenceDate        = referenceDate;
-        this.propagators          = propagators;
-        this.builders             = builders;
-        this.sigmaPoints          = sigmaPoints;
     }
 
-
-    public void init(final List<SpacecraftState> initialStates, final AbsoluteDate t) {
+    /** {@inheritDoc} */
+    @Override
+    public void init(final SpacecraftState s0, final AbsoluteDate t) {
         this.index = 0;
         // Initialize short periodic terms.
-        for (int i = 0; i < initialStates.size(); i++) {
-            model.initializeShortPeriodicTerms(initialStates.get(i), propagators.get(i));
-            model.updateShortPeriods(initialStates.get(i), builders.get(i));
-        }
-
+        model.initializeShortPeriodicTerms(s0);
+        model.updateShortPeriods(s0);
     }
 
+    /** {@inheritDoc} */
     @Override
-    public void handleStep(final List<OrekitStepInterpolator> interpolators) {
-        // TODO Auto-generated method stub
-        final AbsoluteDate currentDate = interpolators.get(0).getCurrentState().getDate();
-
-        for (int i = 0; i < interpolators.size(); i++) {
-            // Update the short period terms with the current MEAN state
-            model.updateShortPeriods(interpolators.get(i).getCurrentState(), builders.get(i));
-            // Process the measurements between previous step and current step
-        }    
-            while (index < observedMeasurements.size() && (observedMeasurements.get(index).getDate().compareTo(currentDate) < 0 || index == observedMeasurements.size()-1)  ) {
-
-                try {
-
-                    for (int i = 0; i < interpolators.size(); i++) {
-                        // Update the nominal state with the interpolated parameters
-                        SpacecraftState s = interpolators.get(i).getInterpolatedState(observedMeasurements.get(index).getDate());
-                        model.updateNominalSpacecraftState(s, builders.get(i), i);
-                    }
-                    // Process the current observation
-                    ProcessEstimate estimate = filter.predictionAndCorrectionSteps(decorate(observedMeasurements.get(index)), sigmaPoints);
-                    // Finalize the estimation
-                    model.finalizeEstimation(observedMeasurements.get(index), estimate);
-                    // Call the observer if the user add one
-                    if (observer != null) {
-                        observer.evaluationPerformed(model);
-                    }
-
-                } catch (MathRuntimeException mrte) {
-                    throw new OrekitException(mrte);
-                }
-                // Increment the measurement index
-                index += 1;
-                
-            }
+    public void handleStep(final OrekitStepInterpolator interpolator) {
 
+        // Current date
+        final AbsoluteDate currentDate = interpolator.getCurrentState().getDate();
 
-        // Update the sigmaPoints
-        final ProcessEstimate estimate = filter.getCorrected();
-        sigmaPoints = filter.getUnscentedTransformProvider().unscentedTransform(estimate.getState(), estimate.getCovariance());
+        // Update the short period terms with the current MEAN state
+        model.updateShortPeriods(interpolator.getCurrentState());
 
+        // Process the measurements between previous step and current step
+        while (index < observedMeasurements.size() && observedMeasurements.get(index).getDate().compareTo(currentDate) < 0) {
 
-        // Reset the initial state of the propagators with sigma points
-        model.finalizeOperationsObservationGrid(sigmaPoints);
+            try {
 
-    }
+                // Update predicted spacecraft state
+                model.updateNominalSpacecraftState(interpolator.getInterpolatedState(observedMeasurements.get(index).getDate()));
+
+                // Process the current observation
+                final ProcessEstimate estimate = filter.estimationStep(KalmanEstimatorUtil.decorate(observedMeasurements.get(index), referenceDate));
+
+                // Finalize the estimation
+                model.finalizeEstimation(observedMeasurements.get(index), estimate);
+
+                // Call the observer if the user add one
+                if (observer != null) {
+                    observer.evaluationPerformed(model);
+                }
+
+            } catch (MathRuntimeException mrte) {
+                throw new OrekitException(mrte);
+            }
+
+            // Increment the measurement index
+            index += 1;
 
-    /** Decorate an observed measurement.
-     * <p>
-     * The "physical" measurement noise matrix is the covariance matrix of the measurement.
-     * Normalizing it consists in applying the following equation: Rn[i,j] =  R[i,j]/σ[i]/σ[j]
-     * Thus the normalized measurement noise matrix is the matrix of the correlation coefficients
-     * between the different components of the measurement.
-     * </p>
-     * @param observedMeasurement the measurement
-     * @return decorated measurement
-     */
-    private MeasurementDecorator decorate(final ObservedMeasurement<?> observedMeasurement) {
-
-        // Normalized measurement noise matrix contains 1 on its diagonal and correlation coefficients
-        // of the measurement on its non-diagonal elements.
-        // Indeed, the "physical" measurement noise matrix is the covariance matrix of the measurement
-        // Normalizing it leaves us with the matrix of the correlation coefficients
-        final RealMatrix covariance;
-        if (observedMeasurement instanceof PV) {
-            // For PV measurements we do have a covariance matrix and thus a correlation coefficients matrix
-            final PV pv = (PV) observedMeasurement;
-            covariance = MatrixUtils.createRealMatrix(pv.getCorrelationCoefficientsMatrix());
-        } else if (observedMeasurement instanceof Position) {
-            // For Position measurements we do have a covariance matrix and thus a correlation coefficients matrix
-            final Position position = (Position) observedMeasurement;
-            covariance = MatrixUtils.createRealMatrix(position.getCorrelationCoefficientsMatrix());
-        } else {
-            // For other measurements we do not have a covariance matrix.
-            // Thus the correlation coefficients matrix is an identity matrix.
-            covariance = MatrixUtils.createRealIdentityMatrix(observedMeasurement.getDimension());
         }
 
-        return new MeasurementDecorator(observedMeasurement, covariance, referenceDate);
+        // Reset the initial state of the propagator
+        model.finalizeOperationsObservationGrid();
 
     }
 
 }
-
diff --git a/src/test/java/org/orekit/estimation/sequential/KalmanEstimatorTest.java b/src/test/java/org/orekit/estimation/sequential/KalmanEstimatorTest.java
index 83fc140f8aaee99948381c02c0e1d90aede92aee..2aabb442c92b2f1c9d9f8fa176a6aa2294e7f91c 100644
--- a/src/test/java/org/orekit/estimation/sequential/KalmanEstimatorTest.java
+++ b/src/test/java/org/orekit/estimation/sequential/KalmanEstimatorTest.java
@@ -16,8 +16,6 @@
  */
 package org.orekit.estimation.sequential;
 
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.Comparator;
 import java.util.List;
@@ -933,39 +931,8 @@ public class KalmanEstimatorTest {
                                                new Vector3D(1.0, -1.0, 0.0),
                                                0.5, 1.0, new ObservableSatellite(0));
 
-        // Create propagator builder
-        final NumericalPropagatorBuilder propagatorBuilder =
-                        context.createBuilder(OrbitType.KEPLERIAN, PositionAngle.TRUE, true, 1.e-6, 60., 1.);
-
-        // Covariance matrix initialization
-        final RealMatrix initialP = MatrixUtils.createRealDiagonalMatrix(new double [] {
-            1e-2, 1e-2, 1e-2, 1e-5, 1e-5, 1e-5
-        });
-
-        // Process noise matrix
-        RealMatrix Q = MatrixUtils.createRealDiagonalMatrix(new double [] {
-            1.e-8, 1.e-8, 1.e-8, 1.e-8, 1.e-8, 1.e-8
-        });
-
-
-        // Build the Kalman filter
-        final KalmanEstimator kalman = new KalmanEstimatorBuilder().
-                        addPropagationConfiguration(propagatorBuilder, new ConstantProcessNoise(initialP, Q)).
-                        build();
-
         // Decorated measurement
-        MeasurementDecorator decorated = null;
-
-        // Call the private method "decorate" in KalmanEstimator class
-        try {
-            Method decorate = KalmanEstimator.class.getDeclaredMethod("decorate",
-                                                                      ObservedMeasurement.class);
-            decorate.setAccessible(true);
-            decorated = (MeasurementDecorator) decorate.invoke(kalman, position);
-        } catch (NoSuchMethodException | IllegalAccessException |
-                        IllegalArgumentException | InvocationTargetException e) {
-
-        }
+        MeasurementDecorator decorated = KalmanEstimatorUtil.decorate(position, context.initialOrbit.getDate());
 
         // Verify time
         Assert.assertEquals(0.0, decorated.getTime(), 1.0e-15);
diff --git a/src/test/java/org/orekit/estimation/sequential/SemiAnalyticalUnscentedKalmanEstimatorTest.java b/src/test/java/org/orekit/estimation/sequential/SemiAnalyticalUnscentedKalmanEstimatorTest.java
index 5e7a8afca54a1186e09c22be48f6d39fc23f69fb..2afc321d3a4bcc3a7717ffecfba0454bdead2514 100644
--- a/src/test/java/org/orekit/estimation/sequential/SemiAnalyticalUnscentedKalmanEstimatorTest.java
+++ b/src/test/java/org/orekit/estimation/sequential/SemiAnalyticalUnscentedKalmanEstimatorTest.java
@@ -1,8 +1,5 @@
 package org.orekit.estimation.sequential;
 
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.util.ArrayList;
 import java.util.List;
 
 import org.hipparchus.linear.MatrixUtils;
@@ -18,10 +15,8 @@ import org.orekit.estimation.DSSTContext;
 import org.orekit.estimation.DSSTEstimationTestUtils;
 import org.orekit.estimation.measurements.EstimatedMeasurement;
 import org.orekit.estimation.measurements.ObservedMeasurement;
-import org.orekit.estimation.measurements.PVMeasurementCreator;
 import org.orekit.estimation.measurements.Range;
 import org.orekit.estimation.measurements.RangeMeasurementCreator;
-import org.orekit.estimation.measurements.RangeRateMeasurementCreator;
 import org.orekit.forces.gravity.potential.GravityFieldFactory;
 import org.orekit.forces.gravity.potential.UnnormalizedSphericalHarmonicsProvider;
 import org.orekit.orbits.Orbit;
@@ -35,7 +30,6 @@ import org.orekit.propagation.semianalytical.dsst.forces.DSSTTesseral;
 import org.orekit.propagation.semianalytical.dsst.forces.DSSTZonal;
 import org.orekit.time.AbsoluteDate;
 import org.orekit.utils.Constants;
-import org.orekit.utils.ParameterDriver;
 
 public class SemiAnalyticalUnscentedKalmanEstimatorTest {
 
@@ -44,24 +38,10 @@ public class SemiAnalyticalUnscentedKalmanEstimatorTest {
 
         /** Residuals statistics. */
         private StreamingStatistics stats;
-        
-        private List<Double> residualsID;
-        private List<Double> residualsS;
-
-        private List<Double> timeID;
-        private List<Double> timeS;
-
-        private Boolean isFirstEvaluation;
-        private AbsoluteDate initialDate;
 
         /** Constructor. */
         public Observer() {
-            this.stats             = new StreamingStatistics();
-            this.residualsID       = new ArrayList<>();
-            this.residualsS        = new ArrayList<>();
-            this.timeID            = new ArrayList<>();
-            this.timeS             = new ArrayList<>();
-            this.isFirstEvaluation = true;
+            this.stats = new StreamingStatistics();
         }
 
         /** {@inheritDoc} */
@@ -70,10 +50,7 @@ public class SemiAnalyticalUnscentedKalmanEstimatorTest {
 
             // Estimated and observed measurements
             final EstimatedMeasurement<?> estimatedMeasurement = estimation.getPredictedMeasurement();
-            if (isFirstEvaluation) {
-                initialDate = estimatedMeasurement.getDate();
-                isFirstEvaluation = false;
-            }
+
             // Check
             if (estimatedMeasurement.getObservedMeasurement() instanceof Range) {
                 final double[] estimated = estimatedMeasurement.getEstimatedValue();
@@ -81,14 +58,6 @@ public class SemiAnalyticalUnscentedKalmanEstimatorTest {
                 // Calculate residual
                 final double res = observed[0] - estimated[0];
                 stats.addValue(res);
-                if (((Range)estimatedMeasurement.getObservedMeasurement()).getStation().getBaseFrame().getName().equals("Isla Desolación")) {
-                    residualsID.add(res);
-                    timeID.add(estimatedMeasurement.getDate().durationFrom(initialDate)/86400);
-                }
-                else {
-                    residualsS.add(res);
-                    timeS.add(estimatedMeasurement.getDate().durationFrom(initialDate)/86400);
-                }
             }
 
         }
@@ -99,33 +68,9 @@ public class SemiAnalyticalUnscentedKalmanEstimatorTest {
         public double getMeanResidual() {
             return stats.getMean();
         }
-        
-        public void printResults(String path, String path2) {
-            PrintWriter writerID = null;
-            PrintWriter writerS = null;
-            try {
-                String encoding = "UTF-8";
-                writerID = new PrintWriter(path, encoding); 
-                writerS = new PrintWriter(path2, encoding); 
-            }
-            catch (IOException e){
-                System.out.println("An error occurred.");
-                e.printStackTrace();
-              }
-            for (int i = 0; i < residualsID.size(); i++) {
-                writerID.print(timeID.get(i));
-                writerID.print(" ");
-                writerID.println(residualsID.get(i));
-            }
-            for (int i = 0; i < residualsS.size(); i++) {
-                writerS.print(timeS.get(i));
-                writerS.print(" ");
-                writerS.println(residualsS.get(i));
-            }
-            writerS.close();
-            writerID.close();
-        }
+
     }
+
     @Test
     public void testMissingPropagatorBuilder() {
         try {
@@ -137,209 +82,26 @@ public class SemiAnalyticalUnscentedKalmanEstimatorTest {
         }
     }
 
-    /**
-     * Perfect PV measurements with a perfect start.
-     */
-    @Test
-    public void testPV() {
-
-        // Create context
-        DSSTContext context = DSSTEstimationTestUtils.eccentricContext("regular-data:potential:tides");
-
-        // Create initial orbit and propagator builder
-        final PositionAngle positionAngle = PositionAngle.MEAN;
-        final boolean       perfectStart  = true;
-        final double        minStep       = 120.0;
-        final double        maxStep       = 1200.0;
-        final double        dP            = 1.;
-        final DSSTPropagatorBuilder propagatorBuilder =
-                        context.createBuilder(PropagationType.OSCULATING, PropagationType.MEAN, perfectStart,
-                                              minStep, maxStep, dP);
-        final DSSTPropagatorBuilder propagatorBuilderRef =
-                context.createBuilder(PropagationType.OSCULATING, PropagationType.MEAN, perfectStart,
-                                      minStep, maxStep, dP);
-        // Create perfect PV measurements
-        final Propagator propagator = DSSTEstimationTestUtils.createPropagator(context.initialOrbit,
-                                                                           propagatorBuilder);
-        final List<ObservedMeasurement<?>> measurements =
-                DSSTEstimationTestUtils.createMeasurements(propagator,
-                                                               new PVMeasurementCreator(),
-                                                               0.0, 6.0, 60.0);
-        // Reference propagator for estimation performances
-        final DSSTPropagator referencePropagator = propagatorBuilderRef.
-                        buildPropagator(propagatorBuilderRef.getSelectedNormalizedParameters());
-        
-        // Reference position/velocity at last measurement date
-        final Orbit refOrbit = referencePropagator.
-                        propagate(measurements.get(measurements.size()-1).getDate()).getOrbit();
-        
-        // Covariance matrix initialization
-        // final RealMatrix initialP = MatrixUtils.createRealDiagonalMatrix(new double[] {0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001}); 
-        final RealMatrix initialP = MatrixUtils.createRealMatrix(6, 6);
-        // Process noise matrix
-        RealMatrix Q = MatrixUtils.createRealMatrix(6, 6);
-  
-        
-        // Build the Kalman filter
-        final SemiAnalyticalUnscentedKalmanEstimator kalman = new SemiAnalyticalUnscentedKalmanEstimatorBuilder().
-                        addPropagationConfiguration(propagatorBuilder, new ConstantProcessNoise(initialP, Q)).
-                        build();
-        
-        // Filter the measurements and check the results
-        final double   expectedDeltaPos  = 0.;
-        final double   posEps            = 4e-9;
-        final double   expectedDeltaVel  = 0.;
-        final double   velEps            = 2.5e-12;
-
-        DSSTEstimationTestUtils.checkKalmanFit(context, kalman, measurements,
-                                           refOrbit, positionAngle,
-                                           expectedDeltaPos, posEps,
-                                           expectedDeltaVel, velEps);
-    }
-
-    
-    /**
-     * Perfect Range measurements with a perfect start.
-     */
     @Test
-    public void testCartesianRange() {
-
-        // Create context
-        DSSTContext context = DSSTEstimationTestUtils.eccentricContext("regular-data:potential:tides");
-
-        // Create initial orbit and propagator builder
-        final PositionAngle positionAngle = PositionAngle.MEAN;
-        final boolean       perfectStart  = true;
-        final double        minStep       = 1.e-6;
-        final double        maxStep       = 60.;
-        final double        dP            = 1.;
-        final DSSTPropagatorBuilder propagatorBuilder =
-                        context.createBuilder(PropagationType.OSCULATING, PropagationType.MEAN, perfectStart,
-                                              minStep, maxStep, dP);
-
-        // Create perfect PV measurements
-        final Propagator propagator = DSSTEstimationTestUtils.createPropagator(context.initialOrbit,
-                                                                           propagatorBuilder);
-        final List<ObservedMeasurement<?>> measurements =
-                DSSTEstimationTestUtils.createMeasurements(propagator,
-                                                               new RangeMeasurementCreator(context),
-                                                               0.0, 1.0, 300.0);
-        // Reference propagator for estimation performances
-        final DSSTPropagator referencePropagator = propagatorBuilder.
-                        buildPropagator(propagatorBuilder.getSelectedNormalizedParameters());
-        
-        // Reference position/velocity at last measurement date
-        final Orbit refOrbit = referencePropagator.
-                        propagate(measurements.get(measurements.size()-1).getDate()).getOrbit();
-        
-        // Covariance matrix initialization
-        final RealMatrix initialP = MatrixUtils.createRealMatrix(6, 6); 
-
-        // Process noise matrix
-        RealMatrix Q = MatrixUtils.createRealMatrix(6, 6);
-  
-
-        // Build the Kalman filter
-        final SemiAnalyticalUnscentedKalmanEstimator kalman = new SemiAnalyticalUnscentedKalmanEstimatorBuilder().
-                        addPropagationConfiguration(propagatorBuilder, new ConstantProcessNoise(initialP, Q)).
-                        build();
-        
-        // Filter the measurements and check the results
-        final double   expectedDeltaPos  = 0.;
-        final double   posEps            = 4e-3;
-        final double   expectedDeltaVel  = 0.;
-        final double   velEps            = 2.28e-5;
-
-        DSSTEstimationTestUtils.checkKalmanFit(context, kalman, measurements,
-                                           refOrbit, positionAngle,
-                                           expectedDeltaPos, posEps,
-                                           expectedDeltaVel, velEps);
+    public void testMissingUnscentedTransform() {
+        try {
+            DSSTContext context = DSSTEstimationTestUtils.eccentricContext("regular-data:potential:tides");
+            final boolean       perfectStart  = true;
+            final double        minStep       = 1.e-6;
+            final double        maxStep       = 60.;
+            final double        dP            = 1.;
+            final DSSTPropagatorBuilder propagatorBuilder =
+                            context.createBuilder(PropagationType.OSCULATING, PropagationType.MEAN, perfectStart,
+                                                  minStep, maxStep, dP);
+            new SemiAnalyticalUnscentedKalmanEstimatorBuilder().
+            addPropagationConfiguration(propagatorBuilder, new ConstantProcessNoise(MatrixUtils.createRealMatrix(6, 6))).
+            build();
+            Assert.fail("an exception should have been thrown");
+        } catch (OrekitException oe) {
+            Assert.assertEquals(OrekitMessages.NO_UNSCENTED_TRANSFORM_CONFIGURED, oe.getSpecifier());
+        }
     }
-    
-    /**
-     * Perfect range rate measurements with a perfect start
-     * Cartesian formalism
-     */
-    @Test
-    public void testCartesianRangeRate() {
-
-        // Create context
-        DSSTContext context = DSSTEstimationTestUtils.eccentricContext("regular-data:potential:tides");
-
-        // Create initial orbit and propagator builder
-        final OrbitType     orbitType     = OrbitType.EQUINOCTIAL;
-        final PositionAngle positionAngle = PositionAngle.MEAN;
-        final boolean       perfectStart  = true;
-        final double        minStep       = 1.e-6;
-        final double        maxStep       = 60.;
-        final double        dP            = 1.;
-        final DSSTPropagatorBuilder propagatorBuilder =
-                        context.createBuilder(PropagationType.OSCULATING, PropagationType.MEAN, perfectStart,
-                                              minStep, maxStep, dP);
-
-        // Create perfect range measurements
-        final Propagator propagator = DSSTEstimationTestUtils.createPropagator(context.initialOrbit,
-                                                                           propagatorBuilder);
-        final double satClkDrift = 3.2e-10;
-        final RangeRateMeasurementCreator creator = new RangeRateMeasurementCreator(context, false, satClkDrift);
-        final List<ObservedMeasurement<?>> measurements =
-                DSSTEstimationTestUtils.createMeasurements(propagator,
-                                                               creator,
-                                                               1.0, 3.0, 300.0);
-
-        // Reference propagator for estimation performances
-        final DSSTPropagator referencePropagator = propagatorBuilder.
-                        buildPropagator(propagatorBuilder.getSelectedNormalizedParameters());
-        
-        // Reference position/velocity at last measurement date
-        final Orbit refOrbit = referencePropagator.
-                        propagate(measurements.get(measurements.size()-1).getDate()).getOrbit();
-        
-        // Cartesian covariance matrix initialization
-        // 100m on position / 1e-2m/s on velocity 
-        final RealMatrix cartesianP = MatrixUtils.createRealDiagonalMatrix(new double [] {
-            1e-4, 1e-4, 1e-4, 1e-10, 1e-10, 1e-10
-        });
-        
-        // Jacobian of the orbital parameters w/r to Cartesian
-        final Orbit initialOrbit = orbitType.convertType(context.initialOrbit);
-        final double[][] dYdC = new double[6][6];
-        initialOrbit.getJacobianWrtCartesian(PositionAngle.TRUE, dYdC);
-        final RealMatrix Jac = MatrixUtils.createRealMatrix(dYdC);
-        
-        // Initial covariance matrix
-        final RealMatrix initialP = Jac.multiply(cartesianP.multiply(Jac.transpose()));
-
-        // Process noise matrix
-        final RealMatrix cartesianQ = MatrixUtils.createRealDiagonalMatrix(new double [] {
-            1.e-6, 1.e-6, 1.e-6, 1.e-12, 1.e-12, 1.e-12
-        });
-        final RealMatrix Q = Jac.multiply(cartesianQ.multiply(Jac.transpose()));
-        
-        // Build the Kalman filter
-        final SemiAnalyticalUnscentedKalmanEstimator kalman = new SemiAnalyticalUnscentedKalmanEstimatorBuilder().
-                        addPropagationConfiguration(propagatorBuilder, new ConstantProcessNoise(initialP, Q)).
-                        build();
-        
-        // Filter the measurements and check the results
-        final double   expectedDeltaPos  = 0.;
-        final double   posEps            = 4e-4;
-        final double   expectedDeltaVel  = 0.;
-        final double   velEps            = 2e-7;
 
-        DSSTEstimationTestUtils.checkKalmanFit(context, kalman, measurements,
-                                           refOrbit, positionAngle,
-                                           expectedDeltaPos, posEps,
-                                           expectedDeltaVel, velEps);
-    }
-    
-    /**
-     * Perfect range measurements.
-     * Only the Newtonian Attraction is used.
-     * Case 1 of : "Cazabonne B., Bayard J., Journot M., and Cefola P. J., A Semi-analytical Approach for Orbit
-     *              Determination based on Extended Kalman Filter, AAS Paper 21-614, AAS/AIAA Astrodynamics
-     *              Specialist Conference, Big Sky, August 2021."
-     */
     @Test
     public void testKeplerianRange() {
 
@@ -396,21 +158,22 @@ public class SemiAnalyticalUnscentedKalmanEstimatorTest {
         // Build the Kalman filter
         final SemiAnalyticalUnscentedKalmanEstimator kalman = new SemiAnalyticalUnscentedKalmanEstimatorBuilder().
                         addPropagationConfiguration(propagatorBuilder, new ConstantProcessNoise(initialP, Q)).
+                        unscentedTransformProvider(new MerweUnscentedTransform(6)).
                         build();
         final Observer observer = new Observer();
         kalman.setObserver(observer);
 
         // Filter the measurements and check the results
         final double   expectedDeltaPos  = 0.;
-        final double   posEps            = 6e-9;
+        final double   posEps            = 1.0e-15;
         final double   expectedDeltaVel  = 0.;
-        final double   velEps            = 2e-12;
+        final double   velEps            = 1.0e-15;
         DSSTEstimationTestUtils.checkKalmanFit(context, kalman, measurements,
                                            refOrbit, positionAngle,
                                            expectedDeltaPos, posEps,
                                            expectedDeltaVel, velEps);
 
-        Assert.assertEquals(0.0, observer.getMeanResidual(), 5.41e-8);
+        Assert.assertEquals(0.0, observer.getMeanResidual(), 4.98e-8);
         Assert.assertEquals(6, kalman.getOrbitalParametersDrivers(false).getNbParams());
         Assert.assertEquals(6, kalman.getOrbitalParametersDrivers(true).getNbParams());
         Assert.assertEquals(1, kalman.getPropagationParametersDrivers(false).getNbParams());
@@ -422,13 +185,6 @@ public class SemiAnalyticalUnscentedKalmanEstimatorTest {
 
     }
 
-    /**
-     * Perfect range measurements.
-     * J20 is added to the perturbation model compare to the previous test
-     * Case 2 of : "Cazabonne B., Bayard J., Journot M., and Cefola P. J., A Semi-analytical Approach for Orbit
-     *              Determination based on Extended Kalman Filter, AAS Paper 21-614, AAS/AIAA Astrodynamics
-     *              Specialist Conference, Big Sky, August 2021."
-     */
     @Test
     public void testRangeWithZonal() {
 
@@ -467,23 +223,19 @@ public class SemiAnalyticalUnscentedKalmanEstimatorTest {
         final Orbit refOrbit = referencePropagator.
                         propagate(measurements.get(measurements.size()-1).getDate()).getOrbit();
 
-        ParameterDriver aDriver = propagatorBuilder.getOrbitalParametersDrivers().getDrivers().get(0);
-        aDriver.setValue(aDriver.getValue() + 1.2);
-
-        // Cartesian covariance matrix initialization
-        // 100m on position / 1e-2m/s on velocity 
-        final RealMatrix cartesianP = MatrixUtils.createRealDiagonalMatrix(new double [] {
-            100., 100., 100., 1e-2, 1e-2, 1e-2
+        // Equinictial covariance matrix initialization
+        final RealMatrix equinoctialP = MatrixUtils.createRealDiagonalMatrix(new double [] {
+            0., 0., 0., 0., 0., 0.
         });
-        
+
         // Jacobian of the orbital parameters w/r to Cartesian
         final Orbit initialOrbit = orbitType.convertType(context.initialOrbit);
         final double[][] dYdC = new double[6][6];
-        initialOrbit.getJacobianWrtCartesian(PositionAngle.TRUE, dYdC);
+        initialOrbit.getJacobianWrtCartesian(PositionAngle.MEAN, dYdC);
         final RealMatrix Jac = MatrixUtils.createRealMatrix(dYdC);
-        
-        // Keplerian initial covariance matrix
-        final RealMatrix initialP = Jac.multiply(cartesianP.multiply(Jac.transpose()));
+
+        // Equinoctial initial covariance matrix
+        final RealMatrix initialP = Jac.multiply(equinoctialP.multiply(Jac.transpose()));
 
         // Process noise matrix is set to 0 here
         RealMatrix Q = MatrixUtils.createRealMatrix(6, 6);
@@ -491,21 +243,22 @@ public class SemiAnalyticalUnscentedKalmanEstimatorTest {
         // Build the Kalman filter
         final SemiAnalyticalUnscentedKalmanEstimator kalman = new SemiAnalyticalUnscentedKalmanEstimatorBuilder().
                         addPropagationConfiguration(propagatorBuilder, new ConstantProcessNoise(initialP, Q)).
+                        unscentedTransformProvider(new MerweUnscentedTransform(6)).
                         build();
         final Observer observer = new Observer();
         kalman.setObserver(observer);
 
         // Filter the measurements and check the results
         final double   expectedDeltaPos  = 0.;
-        final double   posEps            = 7.6e-1;
+        final double   posEps            = 1.1e-7;
         final double   expectedDeltaVel  = 0.;
-        final double   velEps            = 1.5e-4;
+        final double   velEps            = 3.9e-11;
         DSSTEstimationTestUtils.checkKalmanFit(context, kalman, measurements,
                                            refOrbit, positionAngle,
                                            expectedDeltaPos, posEps,
                                            expectedDeltaVel, velEps);
 
-        //Assert.assertEquals(0.0, observer.getMeanResidual(), 8.51e-3);
+        Assert.assertEquals(0.0, observer.getMeanResidual(), 2.59e-3);
         Assert.assertEquals(6, kalman.getOrbitalParametersDrivers(false).getNbParams());
         Assert.assertEquals(6, kalman.getOrbitalParametersDrivers(true).getNbParams());
         Assert.assertEquals(1, kalman.getPropagationParametersDrivers(false).getNbParams());
@@ -518,14 +271,6 @@ public class SemiAnalyticalUnscentedKalmanEstimatorTest {
 
     }
 
-    /**
-     * Perfect range measurements.
-     * J20 is added to the perturbation model
-     * In addition, J21 and J22 are also added
-     * Case 3 of : "Cazabonne B., Bayard J., Journot M., and Cefola P. J., A Semi-analytical Approach for Orbit
-     *              Determination based on Extended Kalman Filter, AAS Paper 21-614, AAS/AIAA Astrodynamics
-     *              Specialist Conference, Big Sky, August 2021."
-     */
     @Test
     public void testRangeWithTesseral() {
 
@@ -572,25 +317,19 @@ public class SemiAnalyticalUnscentedKalmanEstimatorTest {
         final Orbit refOrbit = referencePropagator.
                         propagate(measurements.get(measurements.size()-1).getDate()).getOrbit();
 
-        ParameterDriver aDriver = propagatorBuilder.getOrbitalParametersDrivers().getDrivers().get(0);
-        aDriver.setValue(aDriver.getValue() + 1.2);
-
-        // Cartesian covariance matrix initialization
-        // 100m on position / 1e-2m/s on velocity 
-        // Process noise matrix is set to 0 here
-//        final RealMatrix cartesianP = MatrixUtils.createRealMatrix(6, 6);
-        final RealMatrix cartesianP = MatrixUtils.createRealDiagonalMatrix(new double [] {
-            100., 100., 100., 1e-2, 1e-2, 1e-2
+        // Equinictial covariance matrix initialization
+        final RealMatrix equinoctialP = MatrixUtils.createRealDiagonalMatrix(new double [] {
+            0., 0., 0., 0., 0., 0.
         });
-        
+
         // Jacobian of the orbital parameters w/r to Cartesian
         final Orbit initialOrbit = orbitType.convertType(context.initialOrbit);
         final double[][] dYdC = new double[6][6];
-        initialOrbit.getJacobianWrtCartesian(PositionAngle.TRUE, dYdC);
+        initialOrbit.getJacobianWrtCartesian(PositionAngle.MEAN, dYdC);
         final RealMatrix Jac = MatrixUtils.createRealMatrix(dYdC);
-        
-        // Keplerian initial covariance matrix
-        final RealMatrix initialP = Jac.multiply(cartesianP.multiply(Jac.transpose()));
+
+        // Equinoctial initial covariance matrix
+        final RealMatrix initialP = Jac.multiply(equinoctialP.multiply(Jac.transpose()));
 
         // Process noise matrix is set to 0 here
         RealMatrix Q = MatrixUtils.createRealMatrix(6, 6);
@@ -598,22 +337,23 @@ public class SemiAnalyticalUnscentedKalmanEstimatorTest {
         final MerweUnscentedTransform utProvider = new MerweUnscentedTransform(6, 0.5, 2., 0.);
         // Build the Kalman filter
         final SemiAnalyticalUnscentedKalmanEstimator kalman = new SemiAnalyticalUnscentedKalmanEstimatorBuilder().
-                        addPropagationConfiguration(propagatorBuilder, new ConstantProcessNoise(initialP, Q)).unscentedTransformProvider(utProvider).
+                        addPropagationConfiguration(propagatorBuilder, new ConstantProcessNoise(initialP, Q)).
+                        unscentedTransformProvider(utProvider).
                         build();
         final Observer observer = new Observer();
         kalman.setObserver(observer);
 
         // Filter the measurements and check the results
         final double   expectedDeltaPos  = 0.;
-        final double   posEps            = 4.8e-1;
+        final double   posEps            = 4.2e-9;
         final double   expectedDeltaVel  = 0.;
-        final double   velEps            = 2.75e-4;
+        final double   velEps            = 1.7e-12;
         DSSTEstimationTestUtils.checkKalmanFit(context, kalman, measurements,
                                            refOrbit, positionAngle,
                                            expectedDeltaPos, posEps,
                                            expectedDeltaVel, velEps);
 
-        //Assert.assertEquals(0.0, observer.getMeanResidual(), 8.81e-3);
+        Assert.assertEquals(0.0, observer.getMeanResidual(), 2.55e-3);
         Assert.assertEquals(6, kalman.getOrbitalParametersDrivers(false).getNbParams());
         Assert.assertEquals(6, kalman.getOrbitalParametersDrivers(true).getNbParams());
         Assert.assertEquals(1, kalman.getPropagationParametersDrivers(false).getNbParams());