diff --git a/src/constraint_imu.h b/src/constraint_imu.h
index 72deeb9a7af847f5ec43b39b99f1a6a1e76d4eab..c61d7d720eab1cf27e44d9d0639931e6dc3ce52c 100644
--- a/src/constraint_imu.h
+++ b/src/constraint_imu.h
@@ -270,7 +270,7 @@ inline bool ConstraintIMU::residual(const Eigen::MatrixBase<D1> &       _p1,
      *
      * NOTE: See optimization report at the end of this file for comparisons of both methods.
      */
-//#define METHOD_1 // if commented, then METHOD_2 will be applied
+#define METHOD_1 // if commented, then METHOD_2 will be applied
 
 
     //needed typedefs
diff --git a/src/test/gtest_IMU.cpp b/src/test/gtest_IMU.cpp
index d126a7a23f659587939472b5201f35f018375f96..9a932ac48572c4485d9fb885ba74b90f60468ab1 100644
--- a/src/test/gtest_IMU.cpp
+++ b/src/test/gtest_IMU.cpp
@@ -68,6 +68,13 @@ class Process_Constraint_IMU : public testing::Test
         VectorXs        D_optim_imu,     x1_optim_imu;      // corrected with imu_tools using optimized bias
         VectorXs                         x0_optim;          // optimized using constraint_imu
 
+        // Trajectory buffer of correction Jacobians
+        std::vector<MatrixXs> Buf_Jac_preint_prc;
+
+        // Trajectory matrices
+        MatrixXs Trj_D_exact, Trj_D_preint_imu, Trj_D_preint_prc, Trj_D_corrected_imu, Trj_D_corrected_prc;
+        MatrixXs Trj_x_exact, Trj_x_preint_imu, Trj_x_preint_prc, Trj_x_corrected_imu, Trj_x_corrected_prc;
+
         // Delta correction Jacobian and step
         Matrix<Scalar,9,6>  J_D_bias;                           // Jacobian of pre-integrated delta w
         Vector9s            step;
@@ -77,7 +84,6 @@ class Process_Constraint_IMU : public testing::Test
         bool                p1_fixed, q1_fixed, v1_fixed;
 
 
-
         virtual void SetUp( )
         {
             string wolf_root = _WOLF_ROOT_DIR;
@@ -120,7 +126,7 @@ class Process_Constraint_IMU : public testing::Test
          *   Delta: the preintegrated delta
          *   J_D_b_ptr: a pointer to the Jacobian of Delta wrt bias. Defaults to nullptr.
          */
-        static void integrateOneStep(const VectorXs& motion, const VectorXs& bias_real, const VectorXs& bias_preint, Scalar dt, Quaternions& q_real, VectorXs& Delta, Matrix<Scalar, 9, 6>* J_D_d_ptr = nullptr)
+        static void integrateOneStep(const VectorXs& motion, const VectorXs& bias_real, const VectorXs& bias_preint, Scalar dt, Quaternions& q_real, VectorXs& Delta, Matrix<Scalar, 9, 6>* J_D_b_ptr = nullptr)
         {
             VectorXs delta(10), data(6);
             VectorXs Delta_plus(10);
@@ -130,7 +136,7 @@ class Process_Constraint_IMU : public testing::Test
             data                = imu::motion2data(motion, q_real, bias_real);
             q_real              = q_real*exp_q(motion.tail(3)*dt);
             Vector6s body       = data - bias_preint;
-            if (J_D_d_ptr == nullptr)
+            if (J_D_b_ptr == nullptr)
             {
                 delta           = imu::body2delta(body, dt);
                 Delta_plus      = imu::compose(Delta, delta, dt);
@@ -139,10 +145,10 @@ class Process_Constraint_IMU : public testing::Test
             {
                 imu::body2delta(body, dt, delta, J_d_d);
                 imu::compose(Delta, delta, dt, Delta_plus, J_D_D, J_D_d);
-                J_D_b           = *J_D_d_ptr;
+                J_D_b           = *J_D_b_ptr;
                 J_d_b           = - J_d_d;
                 J_D_b           = J_D_D*J_D_b + J_D_d*J_d_b;
-                *J_D_d_ptr      = J_D_b;
+                *J_D_b_ptr      = J_D_b;
             }
             Delta               = Delta_plus;
         }
@@ -221,9 +227,40 @@ class Process_Constraint_IMU : public testing::Test
             return Delta;
         }
 
+        /* Integrate acc and angVel motion, obtain Delta_preintegrated
+         * Input:
+         *   q0: initial orientation
+         *   motion: Matrix with N columns [ax, ay, az, wx, wy, wz] with the true magnitudes in body frame
+         *   bias_real: the real bias of the IMU
+         *   bias_preint: the bias used for Delta pre-integration
+         * Output:
+         *   J_D_b: the Jacobian of the preintegrated delta wrt the bias
+         *   return: the preintegrated delta
+         */
+        static MotionBuffer integrateDeltaTrajectory(const Quaternions& q0, const MatrixXs& motion, const VectorXs& bias_real, const VectorXs& bias_preint, Scalar dt, Matrix<Scalar, 9, 6>& J_D_b)
+        {
+            MotionBuffer trajectory(6, 10, 9, 6);
+            VectorXs    Delta(10);
+            MatrixXs    M9(9,9), M6(6,6), J9(9,9), J96(9,6), V10(10,1), V6(6,1);
+            Quaternions q;
+
+            Delta   = imu::identity();
+            J_D_b   .setZero();
+            q       = q0;
+            TimeStamp t(0);
+            trajectory.get().emplace_back(t, Vector6s::Zero(), M6, VectorXs::Zero(10), M9, imu::identity(), M9, J9, J9, MatrixXs::Zero(9,6));
+            for (int n = 0; n < motion.cols(); n++)
+            {
+                t += dt;
+                integrateOneStep(motion.col(n), bias_real, bias_preint, dt, q, Delta, &J_D_b);
+                trajectory.get().emplace_back(t, motion.col(n), M6, V10, M9, Delta, M9, J9, J9, J_D_b);
+            }
+            return trajectory;
+        }
+
 
 
-        void integrateWithProcessor(int N, const TimeStamp& t0, const Quaternions q0, const MatrixXs& motion, const VectorXs& bias_real, const VectorXs& bias_preint, Scalar dt, VectorXs& D_preint, VectorXs& D_corrected)
+        MotionBuffer integrateWithProcessor(int N, const TimeStamp& t0, const Quaternions q0, const MatrixXs& motion, const VectorXs& bias_real, const VectorXs& bias_preint, Scalar dt, VectorXs& D_preint, VectorXs& D_corrected)
         {
             Vector6s      motion_now;
             data        = imu::motion2data(motion.col(0), q0, bias_real);
@@ -248,6 +285,7 @@ class Process_Constraint_IMU : public testing::Test
                 D_preint    = processor_imu->getLastPtr()->getDeltaPreint();
                 D_corrected = processor_imu->getLastPtr()->getDeltaCorrected(bias_real);
             }
+            return processor_imu->getBuffer();
         }
 
 
@@ -326,6 +364,94 @@ class Process_Constraint_IMU : public testing::Test
         }
 
 
+        // Integrate Trajectories all methods
+        virtual void integrateAllTrajectories()
+        {
+            Size cols = motion.cols() + 1;
+            Trj_D_exact.resize(10,cols); Trj_D_preint_imu.resize(10,cols); Trj_D_preint_prc.resize(10,cols); Trj_D_corrected_imu.resize(10,cols); Trj_D_corrected_prc.resize(10,cols);
+            Trj_x_exact.resize(10,cols); Trj_x_preint_imu.resize(10,cols); Trj_x_preint_prc.resize(10,cols); Trj_x_corrected_imu.resize(10,cols); Trj_x_corrected_prc.resize(10,cols);
+
+
+            // ===================================== INTEGRATE EXACTLY WITH IMU_TOOLS with no bias at all
+            MotionBuffer Buf_exact = integrateDeltaTrajectory(q0, motion, bias_null, bias_null, dt, J_D_bias);
+
+            // Build exact trajectories
+            int col = 0;
+            Scalar Dt = 0;
+            for (auto m : Buf_exact.get())
+            {
+                Trj_D_exact.col(col) = m.delta_integr_;
+                Trj_x_exact.col(col) = imu::composeOverState(x0, m.delta_integr_, Dt );
+                Dt += dt;
+                col ++;
+            }
+
+            // set
+            D_exact          = Trj_D_exact.col(cols-1);
+            x1_exact         = Trj_x_exact.col(cols-1);
+
+            // ===================================== INTEGRATE USING IMU_TOOLS
+            // pre-integrate
+            MotionBuffer Buf_preint_imu = integrateDeltaTrajectory(q0, motion, bias_real, bias_preint, dt, J_D_bias);
+
+            // Build trajectories preintegrated and corrected with imu_tools
+            col = 0;
+            Dt = 0;
+            for (auto m : Buf_preint_imu.get())
+            {
+                // preint
+                Trj_D_preint_imu.col(col) = m.delta_integr_;
+                Trj_x_preint_imu.col(col) = imu::composeOverState(x0, Trj_D_preint_imu.col(col).eval(), Dt );
+
+                // corrected
+                VectorXs step                = m.jacobian_calib_ * (bias_real - bias_preint);
+                Trj_D_corrected_imu.col(col) = imu::plus(m.delta_integr_, step) ;
+                Trj_x_corrected_imu.col(col) = imu::composeOverState(x0, Trj_D_corrected_imu.col(col).eval(), Dt );
+                Dt += dt;
+                col ++;
+            }
+
+            D_preint_imu     = Trj_D_preint_imu.col(cols-1);
+
+            // correct perturbated
+            step             = J_D_bias * (bias_real - bias_preint);
+            D_corrected_imu  = imu::plus(D_preint_imu, step);
+
+            // compose states
+            x1_preint_imu    = imu::composeOverState(x0, D_preint_imu    , DT );
+            x1_corrected_imu = imu::composeOverState(x0, D_corrected_imu , DT );
+
+            // ===================================== INTEGRATE USING PROCESSOR_IMU
+
+            MotionBuffer Buf_D_preint_prc = integrateWithProcessor(num_integrations, t0, q0, motion, bias_real, bias_preint, dt, D_preint, D_corrected);
+
+
+            // Build trajectories preintegrated and corrected with processorIMU
+            Dt = 0;
+            col = 0;
+            Buf_Jac_preint_prc.clear();
+            for (auto m : Buf_D_preint_prc.get())
+            {
+                // preint
+                Trj_D_preint_prc.col(col) = m.delta_integr_;
+                Trj_x_preint_prc.col(col) = imu::composeOverState(x0, Trj_D_preint_prc.col(col).eval(), Dt );
+
+                // corrected
+                VectorXs step                = m.jacobian_calib_ * (bias_real - bias_preint);
+                Trj_D_corrected_prc.col(col) = imu::plus(m.delta_integr_, step) ;
+                Trj_x_corrected_prc.col(col) = imu::composeOverState(x0, Trj_D_corrected_prc.col(col).eval(), Dt );
+
+                Buf_Jac_preint_prc.push_back(m.jacobian_calib_);
+                Dt += dt;
+                col ++;
+            }
+
+            // compose states
+            x1_preint        = imu::composeOverState(x0, D_preint        , DT );
+            x1_corrected     = imu::composeOverState(x0, D_corrected     , DT );
+        }
+
+
 
         // Set state_blocks status
         void setFixedBlocks()
@@ -535,6 +661,24 @@ class Process_Constraint_IMU_ODO : public Process_Constraint_IMU
             sensor_odo->process(capture_odo);
        }
 
+        virtual void integrateAllTrajectories() override
+        {
+            // ===================================== IMU
+            Process_Constraint_IMU::integrateAllTrajectories();
+
+            // ===================================== ODO
+            Vector6s    data;
+            Vector3s    p1  = x1_exact.head(3);
+            Quaternions q1   (x1_exact.data() + 3);
+            Vector3s    dp  =        q0.conjugate() * (p1 - p0);
+            Vector3s    dth = log_q( q0.conjugate() *  q1     );
+            data           << dp, dth;
+
+            CaptureOdom3DPtr capture_odo = make_shared<CaptureOdom3D>(t, sensor_odo, data, sensor_odo->getNoiseCov());
+
+            sensor_odo->process(capture_odo);
+       }
+
         virtual void buildProblem() override
         {
             // ===================================== IMU
@@ -1316,17 +1460,87 @@ TEST_F(Process_Constraint_IMU_ODO, MotionRandom_PqV_b__pqV_b) // F_ixed___e_stim
     // ===================================== RUN ALL
     string report = runAll(1);
 
-    // printAll(report);
+//    printAll(report);
 
     assertAll();
 
 }
 
+TEST_F(Process_Constraint_IMU_ODO, RecoverTrajectory_MotionRandom_PqV_b__pqV_b) // F_ixed___e_stimated
+{
+
+    // ================================================================================================================ //
+    // ==================================== INITIAL CONDITIONS -- USER OPTIONS ======================================== //
+    // ================================================================================================================ //
+    //
+    // ---------- time
+    t0                  = 0;
+    num_integrations    = 50;
+
+    // ---------- initial pose
+    p0                 << 0,0,0;
+    q0.coeffs()        << 0,0,0,1;
+    v0                 << 0,0,0;
+
+    // ---------- bias
+    bias_real          << .001, .002, .003,    -.001, -.002, -.003;
+    bias_preint         = -bias_real;
+
+    // ---------- motion params
+    a  = Matrix<Scalar, 3, 50>::Ones() + 0.1 * Matrix<Scalar, 3, 50>::Random();
+    w  = Matrix<Scalar, 3, 50>::Ones() + 0.1 * Matrix<Scalar, 3, 50>::Random();
+
+    // ---------- fix boundaries
+    p0_fixed       = true;
+    q0_fixed       = false;
+    v0_fixed       = true;
+    p1_fixed       = false;
+    q1_fixed       = false;
+    v1_fixed       = true;
+    //
+    // ===================================== INITIAL CONDITIONS -- USER INPUT ENDS HERE =============================== //
+    // ================================================================================================================ //
+
+
+    // ===================================== RUN ALL
+    configureAll();
+    integrateAllTrajectories();
+    buildProblem();
+    string report = solveProblem(1);
+
+    assertAll();
+
+    // Build optimal trajectory
+    MatrixXs Trj_x_optim(10,Trj_D_preint_prc.cols());
+    Scalar Dt = 0;
+    Size i = 0;
+    for (auto J_D_b : Buf_Jac_preint_prc)
+    {
+        VectorXs step       = J_D_b * (bias_0 - bias_preint);
+        VectorXs D_opt      = imu::plus(Trj_D_preint_prc.col(i).eval(), step);
+        Trj_x_optim.col(i)  = imu::composeOverState(x0_optim, D_opt, Dt);
+        Dt += dt;
+        i  ++;
+    }
+
+    // printAll(report);
+
+    WOLF_INFO("------------------------------------");
+    WOLF_INFO("Exact x0 \n", x0.transpose());
+    WOLF_INFO("Optim x0 \n", x0_optim.transpose());
+    WOLF_INFO("Optim x  \n", Trj_x_optim.transpose());
+    WOLF_INFO("Optim x1 \n", x1_optim.transpose());
+    WOLF_INFO("Exact x1 \n", x1_exact.transpose());
+    WOLF_INFO("------------------------------------");
+
+}
+
 int main(int argc, char **argv)
 {
     testing::InitGoogleTest(&argc, argv);
-//        ::testing::GTEST_FLAG(filter) = "Process_Constraint_IMU.*";
-//    ::testing::GTEST_FLAG(filter) = "Process_Constraint_IMU_ODO.*";
+    //    ::testing::GTEST_FLAG(filter) = "Process_Constraint_IMU.*";
+    //    ::testing::GTEST_FLAG(filter) = "Process_Constraint_IMU_ODO.*";
+    ::testing::GTEST_FLAG(filter) = "Process_Constraint_IMU_ODO.RecoverTrajectory_MotionRandom_PqV_b__pqV_b";
 
     return RUN_ALL_TESTS();
 }