diff --git a/include/qrw/FootTrajectoryGenerator.hpp b/include/qrw/FootTrajectoryGenerator.hpp
index 1b48ea9cd3f77d5ae27a6bf7f4527ff7b9c60ed3..70507a2535984c7729fa79d65c3302f5ed3f269d 100644
--- a/include/qrw/FootTrajectoryGenerator.hpp
+++ b/include/qrw/FootTrajectoryGenerator.hpp
@@ -72,6 +72,9 @@ class FootTrajectoryGenerator {
   MatrixN getFootPosition() { return position_; }          // Get the next foot position
   MatrixN getFootVelocity() { return velocity_; }          // Get the next foot velocity
   MatrixN getFootAcceleration() { return acceleration_; }  // Get the next foot acceleration
+  MatrixN getFootJerk() { return jerk_; }                  // Get the next foot jerk
+  Vector4 getT0s() { return t0s; }                         // Get the t0s for each foot
+  Vector4 getTswing() { return t_swing; }                  // Get the flying period for each foot
 
  private:
   Gait *gait_;        // Target lock before the touchdown
@@ -93,6 +96,7 @@ class FootTrajectoryGenerator {
   Matrix34 position_;      // Position computed in updateFootPosition
   Matrix34 velocity_;      // Velocity computed in updateFootPosition
   Matrix34 acceleration_;  // Acceleration computed in updateFootPosition
+  Matrix34 jerk_;          // Jerk computed in updateFootPosition
 
   Matrix34 position_base_;      // Position computed in updateFootPosition in base frame
   Matrix34 velocity_base_;      // Velocity computed in updateFootPosition in base frame
diff --git a/python/gepadd.cpp b/python/gepadd.cpp
index 48d25ae4006201bf6e61ba101872f870d3cd0f6e..d9fc8a7d13e741c1098e052de8c00193ca3e84d6 100644
--- a/python/gepadd.cpp
+++ b/python/gepadd.cpp
@@ -196,13 +196,18 @@ struct FootTrajectoryGeneratorPythonVisitor : public bp::def_visitor<FootTraject
             .def("getFootPosition", &FootTrajectoryGenerator::getFootPosition, "Get position_ matrix.\n")
             .def("getFootVelocity", &FootTrajectoryGenerator::getFootVelocity, "Get velocity_ matrix.\n")
             .def("getFootAcceleration", &FootTrajectoryGenerator::getFootAcceleration, "Get acceleration_ matrix.\n")
+            .def("getFootJerk", &FootTrajectoryGenerator::getFootJerk, "Get jerk_ matrix.\n")
 
             .def("initialize", &FootTrajectoryGenerator::initialize, bp::args("params", "gaitIn"),
                  "Initialize FootTrajectoryGenerator from Python.\n")
 
             // Compute target location of footsteps from Python
             .def("update", &FootTrajectoryGenerator::update, bp::args("k", "targetFootstep"),
-                 "Compute target location of footsteps from Python.\n");
+                 "Compute target location of footsteps from Python.\n")
+            
+            // Get flying period of the feet
+            .def("getT0s", &FootTrajectoryGenerator::getT0s, "Get the current timings of the flying feet.\n")
+            .def("getTswing", &FootTrajectoryGenerator::getTswing, "Get the flying period of the feet.\n");
 
     }
 
@@ -454,6 +459,7 @@ struct ParamsPythonVisitor : public bp::def_visitor<ParamsPythonVisitor<Params>>
             .def_readwrite("h_ref", &Params::h_ref)
             .def_readwrite("shoulders", &Params::shoulders)
             .def_readwrite("lock_time", &Params::lock_time)
+            .def_readwrite("vert_time", &Params::vert_time)
             .def_readwrite("footsteps_init", &Params::footsteps_init)
             .def_readwrite("footsteps_under_shoulders", &Params::footsteps_under_shoulders);
 
diff --git a/scripts/Controller.py b/scripts/Controller.py
index 334049024be0f18feb227e76c586074f8e2fbe3a..4de141bcd29c266fd1f8ae1dfff7bcfee76e3628 100644
--- a/scripts/Controller.py
+++ b/scripts/Controller.py
@@ -277,9 +277,14 @@ class Controller:
                 if self.type_MPC == 3:
                     # Compute the target foostep in local frame, to stop the optimisation around it when t_lock overpass
                     l_targetFootstep = oRh.transpose() @ (self.o_targetFootstep - oTh)
-                    self.mpc_wrapper.solve(self.k, xref, fsteps, cgait, l_targetFootstep, oRh, oTh)
-                else:
-                    self.mpc_wrapper.solve(self.k, xref, fsteps, cgait, np.zeros((3, 4)))
+                    self.mpc_wrapper.solve(self.k, xref, fsteps, cgait, l_targetFootstep, oRh, oTh,
+                                                self.footTrajectoryGenerator.getFootPosition(),
+                                                self.footTrajectoryGenerator.getFootVelocity(),
+                                                self.footTrajectoryGenerator.getFootAcceleration(),
+                                                self.footTrajectoryGenerator.getFootJerk(),
+                                                self.footTrajectoryGenerator.getTswing() - self.footTrajectoryGenerator.getT0s())
+                else :
+                    self.mpc_wrapper.solve(self.k, xref, fsteps, cgait, np.zeros((3,4)))
 
             except ValueError:
                 print("MPC Problem")
diff --git a/scripts/LoggerControl.py b/scripts/LoggerControl.py
index b390dd34e223540c146beac29aaa2391e188be5a..d702a334879303b4c74b5be9546c1affab7741d4 100644
--- a/scripts/LoggerControl.py
+++ b/scripts/LoggerControl.py
@@ -1,4 +1,5 @@
 '''This class will log 1d array in Nd matrix from device and qualisys object'''
+import pickle
 import numpy as np
 from datetime import datetime as datetime
 from time import time
@@ -73,9 +74,10 @@ class LoggerControl():
         self.planner_h_ref = np.zeros([logSize])  # reference height of the planner
 
         # Foot Trajectory Generator
-        self.planner_goals = np.zeros([logSize, 3, 4])  # 3D target feet positions
+        self.planner_goals = np.zeros([logSize, 3, 4])   # 3D target feet positions
         self.planner_vgoals = np.zeros([logSize, 3, 4])  # 3D target feet velocities
         self.planner_agoals = np.zeros([logSize, 3, 4])  # 3D target feet accelerations
+        self.planner_jgoals = np.zeros([logSize, 3, 4])  # 3D target feet accelerations
 
         # Model Predictive Control
         # output vector of the MPC (next state + reference contact force)
@@ -160,6 +162,7 @@ class LoggerControl():
         self.planner_goals[self.i] = footTrajectoryGenerator.getFootPosition()
         self.planner_vgoals[self.i] = footTrajectoryGenerator.getFootVelocity()
         self.planner_agoals[self.i] = footTrajectoryGenerator.getFootAcceleration()
+        self.planner_jgoals[self.i] = footTrajectoryGenerator.getFootJerk()
         self.planner_is_static[self.i] = gait.getIsStatic()
         self.planner_h_ref[self.i] = loop.h_ref
 
@@ -747,6 +750,7 @@ class LoggerControl():
                             planner_goals=self.planner_goals,
                             planner_vgoals=self.planner_vgoals,
                             planner_agoals=self.planner_agoals,
+                            planner_jgoals=self.planner_jgoals,
                             planner_is_static=self.planner_is_static,
                             planner_h_ref=self.planner_h_ref,
 
@@ -794,7 +798,7 @@ class LoggerControl():
             import glob
             fileName = np.sort(glob.glob('data_2021_*.npz'))[-1]  # Most recent file
 
-        data = np.load(fileName)
+        data = np.load(fileName, allow_pickle = True)
 
         # Load LoggerControl arrays
         self.joy_v_ref = data["joy_v_ref"]
@@ -842,6 +846,7 @@ class LoggerControl():
         self.planner_goals = data["planner_goals"]
         self.planner_vgoals = data["planner_vgoals"]
         self.planner_agoals = data["planner_agoals"]
+        self.planner_jgoals = data["planner_jgoals"]
         self.planner_is_static = data["planner_is_static"]
         self.planner_h_ref = data["planner_h_ref"]
 
@@ -1074,13 +1079,20 @@ class LoggerControl():
 if __name__ == "__main__":
 
     import LoggerSensors
+    import sys
+    import os
+    from sys import argv
+    sys.path.insert(0, os.getcwd()) # adds current directory to python path
+
+    # Data file name to load
+    file_name = "/home/thomas_cbrs/Desktop/edin/quadruped-reactive-walking/scripts/crocoddyl_eval/logs/explore_weight_acc/data_2021_09_16_15_10_3.npz"
 
     # Create loggers
     loggerSensors = LoggerSensors.LoggerSensors(logSize=20000-3)
     logger = LoggerControl(0.001, 30, logSize=20000-3)
 
     # Load data from .npz file
-    logger.loadAll(loggerSensors)
+    logger.loadAll(loggerSensors, fileName= file_name)
 
     # Call all ploting functions
     logger.plotAll(loggerSensors)
diff --git a/scripts/MPC_Wrapper.py b/scripts/MPC_Wrapper.py
index a82fde7422d6511d52447ed576cb4d7af2bd04e3..1dcc23a0020a6610a8f284b52ef8ada0ec1a65c8 100644
--- a/scripts/MPC_Wrapper.py
+++ b/scripts/MPC_Wrapper.py
@@ -1,5 +1,7 @@
 # coding: utf8
 
+from operator import pos
+from typing import FrozenSet
 import numpy as np
 import libquadruped_reactive_walking as MPC
 from multiprocessing import Process, Value, Array
@@ -8,6 +10,9 @@ import crocoddyl_class.MPC_crocoddyl_planner as MPC_crocoddyl_planner
 import pinocchio as pin
 from time import time
 from enum import Enum
+import libquadruped_reactive_walking as lqrw
+import ctypes
+from ctypes import Structure, c_double
 
 class MPC_type(Enum):
     OSQP = 0
@@ -16,6 +21,32 @@ class MPC_type(Enum):
     CROCODDYL_PLANNER = 3
     CROCODDYL_PLANNER_TIME = 4
 
+class DataInCtype(Structure):
+    ''' Ctype data structure for the shared memory between processes.
+    '''
+    params = lqrw.Params()                          # Object that holds all controller parameters
+    mpc_type = MPC_type(params.type_MPC)            # MPC type
+    n_steps = np.int(params.T_mpc/params.dt_mpc)    # Colomn size for xref (12 x n_steps)
+    N_gait = int(5 + params.T_mpc / params.dt_mpc)  # Row size for fsteps  (N_gait x 12), from utils_mpc.py
+
+    if mpc_type == MPC_type.CROCODDYL_PLANNER:
+        _fields_ = [('k',  ctypes.c_int64 ),
+                    ('xref',   ctypes.c_double * 12 * (n_steps+1) ),
+                    ('fsteps', ctypes.c_double * 12 * N_gait  ),
+                    ('l_fsteps_target', ctypes.c_double * 3 * 4 ),
+                    ('oRh', ctypes.c_double * 3 * 3 ),
+                    ('oTh', ctypes.c_double * 3 * 1 ),
+                    ('position', ctypes.c_double * 3 * 4 ),
+                    ('velocity', ctypes.c_double * 3 * 4 ),
+                    ('acceleration', ctypes.c_double * 3 * 4 ),
+                    ('jerk', ctypes.c_double * 3 * 4 ),
+                    ('dt_flying', ctypes.c_double * 4)]
+    else:
+        _fields_ = [('k',  ctypes.c_int64 ),
+                    ('xref',   ctypes.c_double * 12 * (n_steps+1) ),
+                    ('fsteps', ctypes.c_double * 12 * N_gait  )]
+
+
 class Dummy:
     """Dummy class to store variables"""
 
@@ -60,18 +91,17 @@ class MPC_Wrapper:
         self.T_gait = params.gait.shape[0] * params.dt_mpc
         self.gait_past = np.zeros(4)
         self.gait_next = np.zeros(4)
-        self.mass = params.mass
+        self.mass = params.mass        
 
         self.mpc_type = MPC_type(params.type_MPC)
         self.multiprocessing = params.enable_multiprocessing
         if self.multiprocessing:  # Setup variables in the shared memory
             self.newData = Value('b', False)
-            self.newResult = Value('b', False)            
-            if self.mpc_type == MPC_type.CROCODDYL_PLANNER:  # Need more space to store optimized footsteps and l_fsteps to stop the optimization around it (+ oTh and oRh)
-                self.dataIn = Array('d', [0.0] * (1 + (np.int(self.n_steps)+1) * 12 + 12*self.N_gait + 12 + 9 + 3) ) 
+            self.newResult = Value('b', False)
+            self.dataIn = Value(DataInCtype)            
+            if self.mpc_type == MPC_type.CROCODDYL_PLANNER:  
                 self.dataOut = Array('d', [0] * 32 * (np.int(self.n_steps)))
-            else:
-                self.dataIn = Array('d', [0.0] * (1 + (np.int(self.n_steps)+1) * 12 + 12*self.N_gait))
+            else:                
                 self.dataOut = Array('d', [0] * 24 * (np.int(self.n_steps)))
             self.fsteps_future = np.zeros((self.N_gait, 12))
             self.running = Value('b', True)
@@ -99,7 +129,8 @@ class MPC_Wrapper:
             self.last_available_result = np.zeros((24, (np.int(self.n_steps))))
         self.last_available_result[:24, 0] = np.hstack((x_init, np.array([0.0, 0.0, 8.0] * 4)))
 
-    def solve(self, k, xref, fsteps, gait, l_targetFootstep, oRh = np.eye(3), oTh = np.zeros((3,1)) ):
+    def solve(self, k, xref, fsteps, gait, l_fsteps_target, oRh = np.eye(3), oTh = np.zeros((3,1)), 
+                    position = np.zeros((3,4)), velocity = np.zeros((3,4)) , acceleration = np.zeros((3,4)), jerk = np.zeros((3,4)) , dt_flying = np.zeros(4)):
         """Call either the asynchronous MPC or the synchronous MPC depending on the value of multiprocessing during
         the creation of the wrapper
 
@@ -108,15 +139,15 @@ class MPC_Wrapper:
             xref (12xN): Desired state vector for the whole prediction horizon
             fsteps (12xN array): the [x, y, z]^T desired position of each foot for each time step of the horizon
             gait (4xN array): Contact state of feet (gait matrix)
-            l_targetFootstep (3x4 array) : 4*[x, y, z]^T target position in local frame, to stop the optimisation of the feet location around it
+            l_fsteps_target (3x4 array) : 4*[x, y, z]^T target position in local frame, to stop the optimisation of the feet location around it
         """
 
         self.t_mpc_solving_start = time()
 
         if self.multiprocessing:  # Run in parallel process
-            self.run_MPC_asynchronous(k, xref, fsteps, l_targetFootstep, oRh, oTh)
+            self.run_MPC_asynchronous(k, xref, fsteps, l_fsteps_target, oRh, oTh, position, velocity, acceleration, jerk, dt_flying)
         else:  # Run in the same process than main loop
-            self.run_MPC_synchronous(k, xref, fsteps, l_targetFootstep, oRh, oTh)
+            self.run_MPC_synchronous(k, xref, fsteps, l_fsteps_target, oRh, oTh, position, velocity, acceleration, jerk, dt_flying)
 
         if not np.allclose(gait[0, :], self.gait_past):  # If gait status has changed
             if np.allclose(gait[0, :], self.gait_next):  # If we're still doing what was planned the last time MPC was solved
@@ -157,14 +188,14 @@ class MPC_Wrapper:
             self.not_first_iter = True
             return self.last_available_result
 
-    def run_MPC_synchronous(self, k, xref, fsteps, l_targetFootstep, oRh, oTh):
+    def run_MPC_synchronous(self, k, xref, fsteps, l_fsteps_target, oRh, oTh, position, velocity, acceleration, jerk, dt_flying):
         """Run the MPC (synchronous version) to get the desired contact forces for the feet currently in stance phase
 
         Args:
             k (int): Number of inv dynamics iterations since the start of the simulation
             xref (12xN): Desired state vector for the whole prediction horizon
             fsteps (12xN array): the [x, y, z]^T desired position of each foot for each time step of the horizon
-            l_targetFootstep (3x4 array) : [x, y, z]^T target position in local frame, to stop the optimisation of the feet location around it
+            l_fsteps_target (3x4 array) : [x, y, z]^T target position in local frame, to stop the optimisation of the feet location around it
         """
 
         # Run the MPC to get the reference forces and the next predicted state
@@ -175,7 +206,7 @@ class MPC_Wrapper:
             self.mpc.run(np.int(k), xref.copy(), fsteps.copy())
         elif self.mpc_type == MPC_type.CROCODDYL_PLANNER: # Add goal position to stop the optimisation
             # Crocoddyl MPC
-            self.mpc.solve(k, xref.copy(), fsteps.copy(), l_targetFootstep)
+            self.mpc.solve(k, xref.copy(), fsteps.copy(), l_fsteps_target, position, velocity, acceleration, jerk, oRh, oTh,  dt_flying)
         else:
             # Crocoddyl MPC
             self.mpc.solve(k, xref.copy(), fsteps.copy())
@@ -186,7 +217,7 @@ class MPC_Wrapper:
         else:
             self.f_applied = self.mpc.get_latest_result()
 
-    def run_MPC_asynchronous(self, k, xref, fsteps, l_targetFootstep, oRh, oTh):
+    def run_MPC_asynchronous(self, k, xref, fsteps, l_fsteps_target, oRh, oTh, position, velocity, acceleration, jerk, dt_flying):
         """Run the MPC (asynchronous version) to get the desired contact forces for the feet currently in stance phase
 
         Args:
@@ -194,7 +225,7 @@ class MPC_Wrapper:
             xref (12xN): Desired state vector for the whole prediction horizon
             fsteps (12xN array): the [x, y, z]^T desired position of each foot for each time step of the horizon
             params (object): stores parameters
-            l_targetFootstep (3x4 array) : [x, y, z]^T target position in local frame, to stop the optimisation of the feet location around it
+            l_fsteps_target (3x4 array) : [x, y, z]^T target position in local frame, to stop the optimisation of the feet location around it
         """
 
         # If this is the first iteration, creation of the parallel process
@@ -204,7 +235,7 @@ class MPC_Wrapper:
             p.start()
 
         # Stacking data to send them to the parallel process
-        self.compress_dataIn(k, xref, fsteps, l_targetFootstep, oRh, oTh)
+        self.compress_dataIn(k, xref, fsteps, l_fsteps_target, oRh, oTh, position, velocity, acceleration, jerk, dt_flying)
         self.newData.value = True
 
         return 0
@@ -231,17 +262,9 @@ class MPC_Wrapper:
 
                 # Retrieve data thanks to the decompression function and reshape it
                 if self.mpc_type != MPC_type.CROCODDYL_PLANNER:
-                    kf, xref_1dim, fsteps_1dim = self.decompress_dataIn(dataIn)
+                    k, xref, fsteps = self.decompress_dataIn(dataIn)
                 else:
-                    kf, xref_1dim, fsteps_1dim, l_target_1dim, oRh, oTh = self.decompress_dataIn(dataIn)
-                    l_target = np.reshape(l_target_1dim, (3,4))
-                    oRh = np.reshape(oRh, (3,3))
-                    oTh = np.reshape(oTh, (3,1))
-
-                # Reshaping 1-dimensional data
-                k = int(kf[0])
-                xref = np.reshape(xref_1dim, (12, self.n_steps+1))
-                fsteps = np.reshape(fsteps_1dim, (self.N_gait, 12))
+                    k, xref, fsteps, l_fsteps_target, oRh, oTh, position, velocity, acceleration, jerk, dt_flying = self.decompress_dataIn(dataIn)
 
                 # Create the MPC object of the parallel process during the first iteration
                 if k == 0:
@@ -262,7 +285,9 @@ class MPC_Wrapper:
                     fsteps[np.isnan(fsteps)] = 0.0
                     loop_mpc.run(np.int(k), xref, fsteps)
                 elif self.mpc_type == MPC_type.CROCODDYL_PLANNER:
-                    loop_mpc.solve(k, xref.copy(), fsteps.copy(), l_target.copy())
+                    loop_mpc.solve(k, xref.copy(), fsteps.copy(), l_fsteps_target.copy(),  
+                                      position.copy(), velocity.copy(), acceleration.copy(), jerk.copy(),
+                                      oRh.copy(), oTh.copy(), dt_flying.copy())
                 else:
                     loop_mpc.solve(k, xref.copy(), fsteps.copy())
 
@@ -280,46 +305,69 @@ class MPC_Wrapper:
 
         return 0
 
-    def compress_dataIn(self, k, xref, fsteps, l_targetFootstep, oRh, oTh):
-        """Compress data in a single C-type array that belongs to the shared memory to send data from the main control
+    def compress_dataIn(self, k, xref, fsteps, l_fsteps_target, oRh, oTh, position, velocity, acceleration, jerk, dt_flying):
+        """Compress data in a C-type structure that belongs to the shared memory to send data from the main control
         loop to the asynchronous MPC
 
         Args:
             k (int): Number of inv dynamics iterations since the start of the simulation
             fstep_planner (object): FootstepPlanner object of the control loop
-            l_targetFootstep (3x4 array) : [x, y, z]^T target position in local frame, to stop the optimisation of the feet location around it
+            l_fsteps_target (3x4 array) : [x, y, z]^T target position in local frame, to stop the optimisation of the feet location around it
         """
 
         # Replace NaN values by 0.0 to be stored in C-type arrays
         fsteps[np.isnan(fsteps)] = 0.0
 
         # Compress data in the shared input array
-        if self.mpc_type == MPC_type.CROCODDYL_PLANNER:
-            self.dataIn[:] = np.concatenate([[(k/self.k_mpc)], xref.ravel(),
-                                            fsteps.ravel(), l_targetFootstep.ravel(), oRh.ravel(), oTh.ravel()], axis=0)
-        else:
-            self.dataIn[:] = np.concatenate([[(k/self.k_mpc)], xref.ravel(),
-                                            fsteps.ravel()], axis=0)
+        with self.dataIn.get_lock():
+            if self.mpc_type == MPC_type.CROCODDYL_PLANNER:
+                self.dataIn.k = k
+                np.frombuffer(self.dataIn.xref).reshape((12, self.n_steps+1))[:,:] = xref
+                np.frombuffer(self.dataIn.fsteps).reshape((self.N_gait, 12))[:,:] = fsteps
+                np.frombuffer(self.dataIn.l_fsteps_target).reshape((3, 4))[:,:] = l_fsteps_target
+                np.frombuffer(self.dataIn.oRh).reshape((3, 3))[:,:] = oRh
+                np.frombuffer(self.dataIn.oTh).reshape((3, 1))[:,:] = oTh
+                np.frombuffer(self.dataIn.position).reshape((3, 4))[:,:] = position
+                np.frombuffer(self.dataIn.velocity).reshape((3, 4))[:,:] = velocity
+                np.frombuffer(self.dataIn.acceleration).reshape((3, 4))[:,:] = acceleration
+                np.frombuffer(self.dataIn.jerk).reshape((3, 4))[:,:] = jerk
+                np.frombuffer(self.dataIn.dt_flying).reshape(4)[:] = dt_flying
 
-        return 0.0
+            else:
+                self.dataIn.k = k
+                np.frombuffer(self.dataIn.xref).reshape((12, self.n_steps+1))[:,:] = xref
+                np.frombuffer(self.dataIn.fsteps).reshape((self.N_gait, 12))[:,:] = fsteps
 
     def decompress_dataIn(self, dataIn):
-        """Decompress data from a single C-type array that belongs to the shared memory to retrieve data from the main control
+        """Decompress data from a C-type structure that belongs to the shared memory to retrieve data from the main control
         loop in the asynchronous MPC
 
         Args:
-            dataIn (Array): shared array that contains the data the asynchronous MPC will use as inputs
+            dataIn (Array): shared C-type structure that contains the data the asynchronous MPC will use as inputs
         """
 
-        # Sizes of the different variables that are stored in the C-type array
-        if self.mpc_type == MPC_type.CROCODDYL_PLANNER:
-            sizes = [0, 1, (np.int(self.n_steps)+1) * 12, 12*self.N_gait, 12, 9, 3]
-        else:
-            sizes = [0, 1, (np.int(self.n_steps)+1) * 12, 12*self.N_gait]
-        csizes = np.cumsum(sizes)
+        with dataIn.get_lock():
+            if self.mpc_type == MPC_type.CROCODDYL_PLANNER:
+                k = self.dataIn.k
+                xref = np.frombuffer(self.dataIn.xref).reshape((12, self.n_steps+1))
+                fsteps = np.frombuffer(self.dataIn.fsteps).reshape((self.N_gait, 12))
+                l_fsteps_target = np.frombuffer(self.dataIn.l_fsteps_target).reshape((3,4))
+                oRh = np.frombuffer(self.dataIn.oRh).reshape((3,3))
+                oTh = np.frombuffer(self.dataIn.oTh).reshape((3,1))
+                position = np.frombuffer(self.dataIn.position).reshape((3,4))
+                velocity = np.frombuffer(self.dataIn.velocity).reshape((3,4))
+                acceleration = np.frombuffer(self.dataIn.acceleration).reshape((3,4))
+                jerk = np.frombuffer(self.dataIn.jerk).reshape((3,4))
+                dt_flying = np.frombuffer(self.dataIn.dt_flying).reshape(4)               
+
+                return k, xref, fsteps, l_fsteps_target, oRh, oTh, position, velocity, acceleration, jerk, dt_flying
+
+            else:
+                k = self.dataIn.k
+                xref = np.frombuffer(self.dataIn.xref).reshape((12, self.n_steps+1))
+                fsteps = np.frombuffer(self.dataIn.fsteps).reshape((self.N_gait, 12))
 
-        # Return decompressed variables in a list
-        return [dataIn[csizes[i]:csizes[i+1]] for i in range(len(sizes)-1)]
+                return k, xref, fsteps
 
     def convert_dataOut(self):
         """Return the result of the asynchronous MPC (desired contact forces) that is stored in the shared memory
diff --git a/scripts/crocoddyl_class/MPC_crocoddyl_planner.py b/scripts/crocoddyl_class/MPC_crocoddyl_planner.py
index 0b9ac28938ab1e655ec516c173d01ed880ebc5d1..dee9bfbbfeb08b3f8070431ca909f29a3d7d9021 100644
--- a/scripts/crocoddyl_class/MPC_crocoddyl_planner.py
+++ b/scripts/crocoddyl_class/MPC_crocoddyl_planner.py
@@ -5,6 +5,10 @@ import numpy as np
 import quadruped_walkgen as quadruped_walkgen
 import pinocchio as pin
 
+
+
+
+
 class MPC_crocoddyl_planner():
     """Wrapper class for the MPC problem to call the ddp solver and
     retrieve the results.
@@ -13,29 +17,29 @@ class MPC_crocoddyl_planner():
         params (obj): Params object containing the simulation parameters
         mu (float): Friction coefficient
         inner (float): Inside or outside approximation of the friction cone (mu * 1/sqrt(2))
-        linearModel(bool) : Approximation in the cross product by using desired state
     """
 
-    def __init__(self, params,  mu=1, inner=True, warm_start=True, min_fz=0.0):
+    def __init__(self, params,  mu=1, inner=True):
 
-        self.dt = params.dt_mpc                   # Time step of the solver        
-        self.T_mpc = params.T_mpc                 # Period of the MPC    
+        self.dt = params.dt_mpc                   # Time step of the solver  
+        self.dt_wbc = params.dt_wbc               # Time step of the WBC      
+        self.T_mpc = params.T_mpc                 # Period of the MPC
+        self.T_gait = params.T_gait               # Period of the gait    
+        self.N_gait = params.N_gait               # Number of gait row
         self.n_nodes = int(self.T_mpc/self.dt)    # Number of nodes    
         self.mass = params.mass                   # Mass of the robot
         self.max_iteration = 10                   # Max iteration ddp solver
-        self.gI = np.array(params.I_mat.tolist()).reshape((3, 3)) # Inertia matrix in ody frame
+        self.gI = np.array(params.I_mat.tolist()).reshape((3, 3)) # Inertia matrix in body frame
 
         # Friction coefficient
         if inner:
             self.mu = (1/np.sqrt(2))*mu
         else:
-            self.mu = mu
-
-        # self.stateWeights = np.sqrt([2.0, 2.0, 20.0, 0.25, 0.25, 10.0, 0.2, 0.2, 0.2, 0.0, 0.0, 0.3]) 
+            self.mu = mu        
 
         # Weights Vector : States
+        # self.stateWeights = np.sqrt([2.0, 2.0, 20.0, 0.25, 0.25, 10.0, 0.2, 0.2, 0.2, 0.0, 0.0, 0.3]) 
         self.w_x = 0.3
-        # self.w_y = 0.3
         self.w_y = 0.3
         self.w_z = 20
         self.w_roll = 0.9
@@ -50,33 +54,51 @@ class MPC_crocoddyl_planner():
         self.stateWeights = np.array([self.w_x, self.w_y, self.w_z, self.w_roll, self.w_pitch, self.w_yaw,
                                       self.w_vx, self.w_vy, self.w_vz, self.w_vroll, self.w_vpitch, self.w_vyaw])
 
-        self.forceWeights = 1*np.array(4*[0.007, 0.007, 0.007])  # Weight Vector : Force Norm
-        self.frictionWeights = 1.                          # Weight Vector : Friction cone cost
-        self.heuristicWeights = 0.*np.array(4*[0.03, 0.04])      # Weights on the heuristic term
-        self.stepWeights = 0.*np.full(8, 0.005)                 # Weight on the step command (distance between steps)
-        self.stopWeights = 0.*np.ones(8)                       # Weights to stop the optimisation at the end of the flying phase
-        self.shoulderContactWeight = 0.5*np.full(4,1.)                    # Weight for shoulder-to-contact penalty
-        self.shoulder_hlim = 0.235
-        self.shoulderReferencePosition = False # Use the reference trajectory of the Com (True) or not (False) for shoulder/contact cost
+        self.forceWeights = 1*np.array(4*[0.007, 0.007, 0.007]) # Weight vector : Force Norm
+        self.frictionWeights = 1.                               # Weight vector : Friction cone penalisation
+        self.heuristicWeights = 0.*np.array(4*[0.03, 0.04])     # Weight vector : Heuristic term
+        self.stepWeights = 0.*np.full(8, 0.005)                 # Weight vector : Norm of step command (distance between steps)
+        self.stopWeights = 0.*np.ones(8)                        # Weight vector : Stop the optimisation at the end of the flying phase (position penalisation)
+        self.shoulderContactWeight = 1.5*np.full(4,1.)          # Weight vector : Shoulder-to-contact penalisation
+        self.shoulder_hlim = 0.235                              # Distance to activate the shoulder-to-contact penalisation
+        self.shoulderReferencePosition = False                  # Use the reference trajectory of the Com (True) or not (False) for shoulder-to-contact penalisation
 
         # TODO : create a proper warm-start with the previous optimisation
         self.warm_start = True
 
-        # Minimum normal force(N) and reference force vector bool
+        # Minimum/Maximal normal force(N) and relative_forces activation
         self.min_fz = 0.
         self.max_fz = 25.
-        self.relative_forces = True 
+        self.relative_forces = True # F_ref =  m*g/nb_contact
+
+        # Acceleration penalty
+        self.is_acc_activated = False
+        self.acc_limit = np.array([60.,60.])    # Acceleration to activate the penalisation
+        self.acc_weight = 0.0001
+        self.n_sampling = 8
+        self.flying_foot_old =  4*[False]
+        self.dx_new_phase = 0.
+        self.dy_new_phase = 0.
+
+        # Velocity penalty
+        self.is_vel_activated = True
+        self.vel_limit = np.array([4.,4.])  # Velocity to activate the penalisation
+        self.vel_weight = 1.
+
+        # Jerk penalty
+        self.is_jerk_activated = True
+        self.jerk_weight = 1e-7
+        self.jerk_alpha = 23    # Define the slope of the cost, not used
+        self.jerk_beta = 0.     # Define the slope of the cost, not used
 
         # Offset CoM
         self.offset_com = -0.03
+        self.vert_time = params.vert_time 
 
         # Gait matrix
         self.gait = np.zeros((params.N_gait, 4))
         self.gait_old = np.zeros(4)
 
-        # Position of the feet in local frame
-        self.fsteps = np.zeros((params.N_gait, 12))
-
         # List to generate the problem
         self.action_models = []
         self.x_init = []
@@ -105,24 +127,21 @@ class MPC_crocoddyl_planner():
         self.index_inital_stance_phase = []  # List of index to reset the stopWeights to 0 after optimisation
 
         # Initialize the lists of models
-        self.initialize_models(params)
+        self.initialize_models()
 
-    def initialize_models(self, params):
+    def initialize_models(self):
         ''' Reset the two lists of augmented and step-by-step models, to avoid recreating them at each loop.
         Not all models here will necessarily be used.  
-
-        Args : 
-            - params : object containing the parameters of the simulation
         '''
         self.models_augmented = []
         self.models_step = []
 
-        for _ in range(params.N_gait):
+        for _ in range(self.N_gait):
             model = quadruped_walkgen.ActionModelQuadrupedAugmented()
             self.update_model_augmented(model)
             self.models_augmented.append(model)
 
-        for _ in range(4 * int(params.T_mpc / params.T_gait)):
+        for _ in range(4 * int(self.T_mpc / self.T_gait)):
             model = quadruped_walkgen.ActionModelQuadrupedStep()
             self.update_model_step(model)
             self.models_step.append(model)
@@ -131,52 +150,60 @@ class MPC_crocoddyl_planner():
         self.terminal_model = quadruped_walkgen.ActionModelQuadrupedAugmented()
         self.update_model_augmented(self.terminal_model, terminal=True)
 
-    def solve(self, k, xref, footsteps, l_stop):
-        """ Solve the MPC problem
+    def solve(self, k, xref, footsteps, l_stop, position, velocity, acceleration, jerk, oRh, oTh, dt_flying):
+        """ Solve the MPC problem.
 
         Args:
-            k : Iteration
-            xref : the desired state vector
-            footsteps : current position of the feet (given by planner)
-            l_stop : current and target position of the feet (given by footstepTragectory generator)
+            k (int) : Iteration
+            xref (Array 12xN)       : Desired state vector
+            footsteps (Array 12xN)  : current position of the feet (given by planner)
+            l_stop (Array 3x4)      : Current target position of the feet
+            position (Array 3x4)    : Position of the flying feet
+            velocity (Array 3x4)    : Velocity of the flying feet
+            acceleration (Array 3x4): Acceleration position of the flying feet
+            jerk (Array 3x4)        : Jerk position of the flying feet
+            oRh (Array 3x3)         : Rotation matrix from base to ideal/world frame
+            oTh (Array 3x1)         : Translation vector from base to ideal/world frame
+            dt_flying (Array 4x)    : Remaining timing of flying feet
         """
         self.xref[:,:] = xref
         self.xref[2,:] += self.offset_com
 
-        self.updateProblem(k, self.xref, footsteps, l_stop)
+        self.updateProblem(k, self.xref, footsteps, l_stop, position, velocity, acceleration, jerk, oRh, oTh, dt_flying)
         self.ddp.solve(self.x_init, self.u_init, self.max_iteration)
-        
-        # np.set_printoptions(linewidth=300, precision=3)
-        # print(self.gait[:30,:])
-        # idx = 0
-        # for model in self.action_models:
-        #     if model.__class__.__name__ == "ActionModelQuadrupedStep" :
-        #         print(model.__class__.__name__)
-        #     else:
-        #         print(model.__class__.__name__ + "   :   " + str(model.shoulderContactWeight) + "     -    " + str(self.gait[idx,:]))
-        #         idx += 1        
-        # from IPython import embed
-        # embed()
-
-        # Reset to 0 the stopWeights for next optimisation
+
+        # Reset to 0 the stopWeights for next optimisation (already 0.)
         for index_stopped in self.index_stop_optimisation:
             self.models_augmented[index_stopped].stopWeights = np.zeros(8)
 
         for index_stance in self.index_inital_stance_phase:
             self.models_augmented[index_stance].shoulderContactWeight = self.shoulderContactWeight
 
-    def updateProblem(self, k, xref, footsteps, l_stop):
+    def updateProblem(self, k, xref, footsteps, l_stop, position, velocity, acceleration, jerk, oRh, oTh, dt_flying):
         """
-        Update the dynamic of the model list according to the predicted position of the feet,
-        and the desired state.
+        Update the models of the nodes according to parameters of the simulations. 
 
         Args:
+            k (int) : Iteration
+            xref (Array 12xN)       : Desired state vector
+            footsteps (Array 12xN)  : current position of the feet (given by planner)
+            l_stop (Array 3x4)      : Current target position of the feet
+            position (Array 3x4)    : Position of the flying feet
+            velocity (Array 3x4)    : Velocity of the flying feet
+            acceleration (Array 3x4): Acceleration position of the flying feet
+            jerk (Array 3x4)        : Jerk position of the flying feet
+            oRh (Array 3x3)         : Rotation matrix from base to ideal/world frame
+            oTh (Array 3x1)         : Translation vector from base to ideal/world frame
+            dt_flying (Array 4x)    : Remaining timing of flying feet
         """
+        # Update internal matrix
         self.compute_gait_matrix(footsteps)
 
+        # Set up intial feet position : shoulder for flying feet and current foot position for feet on the ground
         p0 = (1.0 - np.repeat(self.gait[0, :], 2)) * self.shoulders \
             + np.repeat(self.gait[0, :], 2) * footsteps[0, [0, 1, 3, 4, 6, 7, 9, 10]]
 
+        # Clear lists of models
         self.x_init.clear()
         self.u_init.clear()
         self.action_models.clear()
@@ -208,17 +235,76 @@ class MPC_crocoddyl_planner():
             self.index_inital_stance_phase.append(index_augmented)
 
         self.action_models.append(self.models_augmented[index_augmented])
-
         index_augmented += 1
+
         # Warm-start
         self.x_init.append(np.concatenate([xref[:, 0], p0]))
         self.u_init.append(np.repeat(self.gait[0, :], 3) * np.array(4*[0., 0., 2.5*9.81/np.sum(self.gait[0, :])]))
 
+        # Bool to activate the speed, acc or jerk on only current flying feet
+        is_first_step = True       
+
         while np.any(self.gait[j, :]):            
-            if np.any(self.gait[j, :] - self.gait[j-1, :]):
-                # Step model
+            if np.any(self.gait[j, :] - self.gait[j-1, :]):  # TODO Adapt this [1,1,1,1] --> [1,0,0,1] True here but not step model to add
+
+                flying_feet = np.where(self.gait[j-1, :] == 0)[0] # Current flying feet
+
+                # Get remaining dt incurrent flying phase
+                # TODO : dt_ is the same for all flying foot, could be different
+                dt_ = dt_flying[flying_feet[0]] 
+                
+                # part_curve explanation for foot trajectory :
+                #           ------- <- 2 (foot stopped, during params.vert_time)
+                #         /
+                #        /          <- 1 (foot moving)
+                #       /
+                # ------            <- 0 (foot stopped, during params.vert_time)
+                # TODO : get total flying period from gait and not T_gait/2 
+                part_curve = 0
+                dt_ -= self.dt_wbc   # dt_ has been computed on the previous loop, dt_wbc late 
+                if dt_ <= 0.001 or dt_ >= self.T_gait/2 - self.vert_time:    # Because of the delay, dt_ = 0 --> new flying phase
+                    dt_ = self.T_gait/2 - 2*self.vert_time
+                    part_curve = 0
+                elif dt_ >= self.vert_time :
+                    dt_ -= self.vert_time
+                    part_curve = 1
+                else:
+                    dt_ = 0.002     # Close to 0 to avoid high jerk and thus keep the optimised fstep from previous cycle
+                    part_curve = 2
+
+                if is_first_step :
+                    #  Acceleration cost                    
+                    # if self.flying_foot_old != self.flying_foot :
+                    #     self.dx_new_phase = abs(footsteps[j, 3*flying_feet[0] ] - position[0,flying_feet[0] ])
+                    #     self.dy_new_phase = abs(footsteps[j, 3*flying_feet[0]+1 ] - position[1,flying_feet[0] ])
+                    #     self.acc_limit = 2*5.625*np.array([ self.dx_new_phase / 0.24**2  , self.dy_new_phase / 0.24**2])
+                    self.models_step[index_step].is_acc_activated = self.is_acc_activated
+                    # self.models_step[index_step].acc_limit =  self.acc_limit
+
+                    # Velocity cost
+                    self.models_step[index_step].is_vel_activated = self.is_vel_activated
+
+                    if part_curve == 1 or part_curve == 2 :
+                        self.models_step[index_step].is_jerk_activated = self.is_jerk_activated
+                        # self.models_step[index_step].jerk_weight = self.exponential_cost(self.T_gait/2 - dt_)
+                        # self.models_step[index_step].jerk_weight = self.jerk_weight
+                    else :
+                        self.models_step[index_step].jerk_weight = 0.
+                    
+                    # Update is_first_step bool
+                    is_first_step = False
+
+                else:
+                    # Cost on the feet trajectory disabled
+                    # TODO : Only activate cost on the maximum speed (simplify the equations in step model, vmax = T/2)
+                    self.models_step[index_step].is_acc_activated = False
+                    self.models_step[index_step].is_vel_activated = False
+                    self.models_step[index_step].is_jerk_activated = False
+                    dt_ = 0.24
+
                 self.models_step[index_step].updateModel(np.reshape(footsteps[j, :], (3, 4), order='F'),
-                                                            xref[:, j], self.gait[j, :] - self.gait[j-1, :])
+                                                            xref[:, j], self.gait[j, :] - self.gait[j-1, :],
+                                                            position, velocity, acceleration, jerk, oRh, oTh, dt_)
                 self.action_models.append(self.models_step[index_step])
 
                 # Augmented model
@@ -366,6 +452,15 @@ class MPC_crocoddyl_planner():
         model.heuristicWeights = np.zeros(8)
         model.stateWeights = self.stateWeights
         model.stepWeights = self.stepWeights
+        model.acc_limit = self.acc_limit 
+        model.acc_weight = self.acc_weight
+        model.is_acc_activated = False
+        model.vel_limit = self.vel_limit 
+        model.vel_weight = self.vel_weight
+        model.is_vel_activated = False
+        model.is_jerk_activated =  False
+        model.jerk_weight = self.jerk_weight 
+        model.set_sample_feet_traj(self.n_sampling)
 
     def compute_gait_matrix(self, footsteps):
         """ 
@@ -383,6 +478,7 @@ class MPC_crocoddyl_planner():
             j += 1
 
         # Get the current flying feet and the number of nodes
+        self.flying_foot_old[:] = self.flying_foot[:]   # Update old matrix, usefull when new phase start
         for foot in range(4):
             row = 0
             if self.gait[0, foot] == 0:
@@ -403,5 +499,14 @@ class MPC_crocoddyl_planner():
                 self.stance_foot_nodes[foot] = int(row)
             else:
                 self.stance_foot[foot] = False
+
+    def exponential_cost(self, t):
+        """
+        Returns weight_jerk * exp(alpha(t-beta)) - 1 
+        Args:
+            t (float) : time in s 
+        """
+    
+        return self.jerk_weight * (np.exp(self.jerk_alpha*(t - self.jerk_beta)) - 1)
     
 
diff --git a/scripts/crocoddyl_eval/test_1/analyse_control_cycle.py b/scripts/crocoddyl_eval/test_1/analyse_control_cycle.py
index 1a5516583981677812909d69cb5e186e882437fd..ab222f1631b8a9370a3b8043057ef59932a46383 100644
--- a/scripts/crocoddyl_eval/test_1/analyse_control_cycle.py
+++ b/scripts/crocoddyl_eval/test_1/analyse_control_cycle.py
@@ -11,11 +11,12 @@ import libquadruped_reactive_walking as lqrw
 import crocoddyl_class.MPC_crocoddyl as MPC_crocoddyl
 import crocoddyl
 import utils_mpc
+np.set_printoptions(formatter={'float': lambda x: "{0:0.7f}".format(x)}, linewidth = 450)
 
 ##############
 #  Parameters
 ##############
-iteration_mpc = 2 # Control cycle
+iteration_mpc = 350  # Control cycle
 Relaunch_DDP = True # Compare a third MPC with != parameters
 linear_mpc = True
 params = lqrw.Params()  # Object that holds all controller parameters
@@ -29,7 +30,7 @@ solo = utils_mpc.init_robot(q_init, params)
 ######################
 # Recover Logged data 
 ######################
-file_name = "crocoddyl_eval/logs/chute_mpc_nl_noShoulder.npz"
+file_name = "/home/thomas_cbrs/Desktop/edin/quadruped-reactive-walking/scripts/crocoddyl_eval/logs/explore_weight_acc/data_cost.npz"
 logs = np.load(file_name)
 planner_gait = logs.get("planner_gait")
 planner_xref = logs.get("planner_xref")
@@ -42,14 +43,14 @@ k = int( iteration_mpc * (params.dt_mpc / params.dt_wbc) ) # simulation iteratio
 mpc_osqp = lqrw.MPC(params)
 mpc_osqp.run(0, planner_xref[0] , planner_fsteps[0]) # Initialization of the matrix
 # mpc_osqp.run(1, planner_xref[1] , planner_fsteps[1])
-# mpc_osqp.run(k, planner_xref[k] , planner_fsteps[k])
+mpc_osqp.run(k, planner_xref[k] , planner_fsteps[k])
 
 osqp_xs = mpc_osqp.get_latest_result()[:12,:] # States computed over the whole predicted horizon
 osqp_xs = np.vstack([planner_xref[k,:,0] , osqp_xs.transpose()]).transpose() # Add current state 
 osqp_us = mpc_osqp.get_latest_result()[12:,:] # Forces computed over the whole predicted horizon
 
 # DDP MPC 
-mpc_ddp = MPC_crocoddyl.MPC_crocoddyl(params, mu=0.9, inner=False, linearModel=False)
+mpc_ddp = MPC_crocoddyl.MPC_crocoddyl(params, mu=0.9, inner=False, linearModel=True)
 # Without warm-start :
 # mpc_ddp.warm_start = False
 # mpc_ddp.solve(k, planner_xref[k] , planner_fsteps[k] ) # Without warm-start
@@ -57,8 +58,14 @@ mpc_ddp = MPC_crocoddyl.MPC_crocoddyl(params, mu=0.9, inner=False, linearModel=F
 # Using warm-start logged :
 #( Exactly the function solve from MPC_crocoddyl)
 # But cannot be used because there areis no previous value inside ddp.xs and ddp.us
-mpc_ddp.updateProblem( planner_fsteps[k], planner_xref[k]) # Update dynamics
+planner_xref_offset =  planner_xref[k].copy()
+planner_xref_offset[2,:] += mpc_ddp.offset_com
+mpc_ddp.updateProblem( planner_fsteps[k], planner_xref_offset) # Update dynamics
 
+
+print("\n\n")
+print("model 0 :")
+print(mpc_ddp.problem.runningModels[0].B)
 x_init = []
 u_init = []
 mpc_ddp.ddp.solve(x_init,  u_init, mpc_ddp.max_iteration)
@@ -70,28 +77,30 @@ while planner_gait[k,i,:].any() :
     i +=1
 
 for j in range(mpc_x_f[0,:,:].shape[1] - 1 ) : 
-    u_init.append(mpc_x_f[k_previous,12:,j+1]) # Drag through an iteration (remove first)
+    u_init.append(mpc_x_f[k_previous,12:24,j+1]) # Drag through an iteration (remove first)
 u_init.append(np.repeat(planner_gait[k,i-1,:], 3)*np.array(4*[0.5, 0.5, 5.])) # Add last node with average values, depending on the gait
 
 for j in range(mpc_x_f[0,:,:].shape[1] - 1 ) : 
     x_init.append(mpc_x_f[k_previous,:12,j+1]) # Drag through an iteration (remove first)
 x_init.append(mpc_x_f[k_previous,:12,-1]) # repeat last term 
-x_init.insert(0, planner_xref[k,:, 0]) # With ddp, first value is the initial value 
+x_init.insert(0, planner_xref_offset[:, 0]) # With ddp, first value is the initial value 
 
 # Solve problem
 mpc_ddp.ddp.solve(x_init,  u_init, mpc_ddp.max_iteration)
 
 ddp_xs = mpc_ddp.get_latest_result()[:12,:] # States computed over the whole predicted horizon 
-ddp_xs = np.vstack([planner_xref[k,:,0] , ddp_xs.transpose()]).transpose() # Add current state 
+ddp_xs = np.vstack([planner_xref_offset[:,0] , ddp_xs.transpose()]).transpose() # Add current state 
 ddp_us = mpc_ddp.get_latest_result()[12:,:] # Forces computed over the whole predicted horizon
 
 ######################################
 # Relaunch DDP to adjust the gains 
 ######################################
 
-mpc_ddp_2 = MPC_crocoddyl.MPC_crocoddyl(params, mu=0.9, inner=False  , linearModel=False) # To modify the linear model if wanted, recreate a list with proper model
+mpc_ddp_2 = MPC_crocoddyl.MPC_crocoddyl(params, mu=0.9, inner=False  , linearModel=True) # To modify the linear model if wanted, recreate a list with proper model
 mpc_ddp_2.implicit_integration = False
-mpc_ddp_2.shoulderWeights = 0.
+mpc_ddp_2.offset_com = 0.0
+# mpc_ddp_2.stateWeights = np.sqrt([2.0, 2.0, 20.0, 0.25, 0.25, 1.0, 0.2, 0.2, 0.2, 0.0, 0.0, 0.3])
+# mpc_ddp_2.shoulderWeights = 1.
 # Weight Vector : State 
 # w_x = 0.2
 # w_y = 0.2
@@ -142,12 +151,15 @@ mpc_ddp_2.problem = crocoddyl.ShootingProblem(np.zeros(12),  mpc_ddp_2.ListActio
 mpc_ddp_2.ddp = crocoddyl.SolverDDP(mpc_ddp_2.problem)
 # Run ddp solver
 # Update the dynamic depending on the predicted feet position
+planner_xref_offset =  planner_xref[k]
+planner_xref_offset[2,:] += mpc_ddp_2.offset_com
+
 if Relaunch_DDP :
-    mpc_ddp_2.updateProblem( planner_fsteps[k], planner_xref[k])
+    mpc_ddp_2.updateProblem( planner_fsteps[k], planner_xref_offset)
     mpc_ddp_2.ddp.solve(x_init,  u_init, mpc_ddp_2.max_iteration, isFeasible = False)
     
     ddp_xs_relaunch = mpc_ddp_2.get_latest_result()[:12,:] # States computed over the whole predicted horizon 
-    ddp_xs_relaunch = np.vstack([planner_xref[k,:,0] , ddp_xs_relaunch.transpose()]).transpose() # Add current state 
+    ddp_xs_relaunch = np.vstack([planner_xref_offset[:,0] , ddp_xs_relaunch.transpose()]).transpose() # Add current state 
     ddp_us_relaunch = mpc_ddp_2.get_latest_result()[12:,:] # Forces computed over the whole predicted horizon
 
 #############
diff --git a/scripts/crocoddyl_eval/test_2/unittest_augmented.py b/scripts/crocoddyl_eval/test_2/unittest_augmented.py
index cf364c1e7d57c35bec623bcb422f04166104de84..1c9aa18c611bf5b158ffd4684f658a4d0f321e3f 100644
--- a/scripts/crocoddyl_eval/test_2/unittest_augmented.py
+++ b/scripts/crocoddyl_eval/test_2/unittest_augmented.py
@@ -16,6 +16,9 @@ model = quadruped_walkgen.ActionModelQuadrupedAugmented()
 model.stateWeights = 2*np.ones(12)
 model.heuristicWeights = 2*np.ones(8)
 model.stepWeights = np.ones(8)
+model.shoulderContactWeight = np.array([0.5,0.1,0.9,0.])
+model.shoulderReferencePosition = False
+model.max_fz = 0.5
 
 # Update the dynamic of the model 
 fstep = np.random.rand(12).reshape((3,4))
diff --git a/scripts/crocoddyl_eval/test_2/unittest_step.py b/scripts/crocoddyl_eval/test_2/unittest_step.py
index c31d6d2031eca2855bff357274910528d91055fc..453338a81cfa1b47ca28c3465c76a3b0a639ef15 100644
--- a/scripts/crocoddyl_eval/test_2/unittest_step.py
+++ b/scripts/crocoddyl_eval/test_2/unittest_step.py
@@ -17,11 +17,36 @@ model.stateWeights = 2*np.ones(12)
 model.heuristicWeights = 2*np.ones(8)
 model.stepWeights = np.ones(8)
 
+model.is_acc_activated = False
+model.acc_limit = np.array([0.09,0.])
+model.acc_weight = 1.88
+
+model.is_vel_activated = True
+model.vel_limit = np.array([0.,0.])
+model.vel_weight = 0.0015
+
+model.is_jerk_activated = True
+model.jerk_weight = 0.000001
+
+
 # Update the dynamic of the model 
 fstep = np.random.rand(12).reshape((3,4))
 xref = np.random.rand(12)
 gait = np.random.randint(2, size=4)
-model.updateModel(fstep, xref , gait)
+position = np.random.rand(12).reshape((3,4))
+velocity = np.random.rand(12).reshape((3,4))
+acceleration = np.random.rand(12).reshape((3,4))
+jerk = np.random.rand(12).reshape((3,4))
+oRh = np.zeros((3,3))
+oTh = np.zeros((3,1))
+oRh[0,0] = 0.88
+oRh[1,1] = 0.88
+oRh[0,1] = -0.2
+oRh[1,0] = 0.2
+oTh[0,0] = 0.1
+oTh[1,0] = 0.09
+Dt = 0.16
+model.updateModel(fstep, xref , gait, position, velocity, acceleration, jerk, oRh, oTh, Dt )
 
 ################################################
 ## CHECK DERIVATIVE WITH NUM_DIFF 
@@ -29,7 +54,7 @@ model.updateModel(fstep, xref , gait)
 
 a = 1
 b = -1 
-N_trial = 50
+N_trial = 1
 epsilon = 10e-6
 
 model_diff = crocoddyl.ActionModelNumDiff(model)
@@ -63,7 +88,12 @@ def run_calcDiff_numDiff(epsilon) :
     fstep = np.random.rand(12).reshape((3,4))
     xref = np.random.rand(12)
     gait = np.random.randint(2, size=4)
-    model.updateModel(fstep, xref , gait)
+    position = np.random.rand(12).reshape((3,4))
+    velocity = np.random.rand(12).reshape((3,4))
+    acceleration = np.random.rand(12).reshape((3,4))
+    jerk = np.random.rand(12).reshape((3,4))
+    Dt = 0.16
+    model.updateModel(fstep, xref , gait, position, velocity, acceleration, jerk, oRh, oTh, Dt )
     model_diff = crocoddyl.ActionModelNumDiff(model)     
    
     # Run calc & calcDiff function : numDiff     
@@ -78,6 +108,11 @@ def run_calcDiff_numDiff(epsilon) :
     Lx_err += np.sum( abs((data.Lx - data_diff.Lx )) )  
 
     Lu +=  np.sum( abs((data.Lu - data_diff.Lu )) >= epsilon  ) 
+    print("\n")
+    print("Lu :")
+    print(data.Lu)
+    print("Lu diff :")
+    print(data_diff.Lu )
     Lu_err += np.sum( abs((data.Lu - data_diff.Lu )) )  
 
     Lxu +=  np.sum( abs((data.Lxu - data_diff.Lxu )) >= epsilon  ) 
diff --git a/scripts/crocoddyl_eval/test_3/analyse_control_cycle.py b/scripts/crocoddyl_eval/test_3/analyse_control_cycle.py
index a3d7792485b16125552f69c21c5e556d36599736..c4977ec9c059a0a8dc24388674c7ac4bb7a77a0d 100644
--- a/scripts/crocoddyl_eval/test_3/analyse_control_cycle.py
+++ b/scripts/crocoddyl_eval/test_3/analyse_control_cycle.py
@@ -1,161 +1,692 @@
 # coding: utf8
 
 import sys
-import os 
+import os
 from sys import argv
+from matplotlib.cbook import ls_mapper
 sys.path.insert(0, os.getcwd()) # adds current directory to python path
 
 import numpy as np
 import matplotlib.pylab as plt
 import libquadruped_reactive_walking as lqrw
 import crocoddyl_class.MPC_crocoddyl_planner as MPC_crocoddyl_planner
-import time 
+import time
 import utils_mpc
-
-
-##############
+import pinocchio as pin
+from matplotlib.collections import LineCollection
+import matplotlib
+import LoggerSensors
+from LoggerControl import LoggerControl
+
+class Poly_5():
+    """
+    Class to evaluate 5th degree polynomial curve for the foot trajectory.
+    x(0) = x0 
+    x'(0) = v0
+    x''(0) = a0
+    x(Dt) = x1
+    Args :
+        - x0 (float) : initial position 
+        - v0 (float) : initial velocity 
+        - a0 (float) : initial acceleration 
+        - x1 (float) : final position 
+        - Dt (float) : Time of the trajectory
+    """
+
+    def __init__(self, x0, v0, a0, x1, Dt) -> None:
+        self.A0 = x0
+        self.A1 = v0 
+        self.A2 = a0/2
+        self.A3 = ( 20*(x1 - x0) - 12*Dt*v0 -3*a0*Dt**2) / (2*Dt**3)
+        self.A4 = - ( 30*(x1 - x0) - 16*Dt*v0 -3*a0*Dt**2) / (2*Dt**4)
+        self.A5 =  ( 12*(x1 - x0) - 6*Dt*v0 -a0*Dt**2) / (2*Dt**5)
+
+    def update_coeff(self, x0, v0, a0, x1, Dt ):
+        """
+        Re-compute the internal coefficients
+        Args :
+            - x0 (float) : initial position 
+            - v0 (float) : initial velocity 
+            - a0 (float) : initial acceleration 
+            - x1 (float) : final position 
+            - Dt (float) : Time of the trajectory
+        """
+        self.A0 = x0
+        self.A1 = v0 
+        self.A2 = a0/2
+        self.A3 = ( 20*(x1 - x0) - 12*Dt*v0 -3*a0*Dt**2) / (2*Dt**3)
+        self.A4 = - ( 30*(x1 - x0) - 16*Dt*v0 -3*a0*Dt**2) / (2*Dt**4)
+        self.A5 =  ( 12*(x1 - x0) - 6*Dt*v0 -a0*Dt**2) / (2*Dt**5)
+
+    def compute(self, t, index):
+        """
+        Evaluate the trajectory : x(index)(t) 
+        Args :
+            - t (float) : time 
+            - index (int) : Derivative order 
+        """
+        if index == 0:
+            return self.A0 + self.A1*t + self.A2*t**2 + self.A3*t**3 + self.A4*t**4 + self.A5*t**5
+
+        elif index == 1:
+            return self.A1 + 2*self.A2*t + 3*self.A3*t**2 + 4*self.A4*t**3 + 5*self.A5*t**4
+
+        elif index == 2:
+            return 2*self.A2 + 6*self.A3*t + 12*self.A4*t**2 + 20*self.A5*t**3 
+        
+        else:
+            return 6*self.A3 + 24*self.A4*t + 60*self.A5*t**2
+
+################
 #  Parameters
-##############
-iteration_mpc = 45 # Control cycle
-Relaunch_DDP = False # Compare a third MPC with != parameters
-linear_mpc = True
+################
+iteration_mpc = 180 # Control cycle
+iteration_init = iteration_mpc 
 params = lqrw.Params()  # Object that holds all controller parameters
+vert_time = params.vert_time
 
 # Default position after calibration
 q_init = np.array(params.q_init.tolist())
 
 # Update I_mat, etc...
-solo = utils_mpc.init_robot(q_init, params) 
+solo = utils_mpc.init_robot(q_init, params)
+
+#######################
+# Recover Logged data
+#######################
+file_name = "/home/thomas_cbrs/Desktop/edin/quadruped-reactive-walking/scripts/crocoddyl_eval/logs/explore_weight_acc/data_cost.npz"
 
-######################
-# Recover Logged data 
-######################
-file_name = "crocoddyl_eval/logs/data_2021_08_18_13_23.npz"
 logs = np.load(file_name)
 planner_gait = logs.get("planner_gait")
 planner_xref = logs.get("planner_xref")
 planner_fsteps = logs.get("planner_fsteps")
 planner_goals = logs.get("planner_goals")
+planner_vgoals = logs.get("planner_vgoals")
+planner_agoals = logs.get("planner_agoals")
+planner_jgoals = logs.get("planner_jgoals")
+loop_o_q = logs.get("loop_o_q")
 mpc_x_f = logs.get("mpc_x_f")
 
-k = int( iteration_mpc * (params.dt_mpc / params.dt_wbc) ) # simulation iteration corresponding
-k_previous = int( (iteration_mpc - 1) * (params.dt_mpc / params.dt_wbc) ) 
+# Create loggers and process mocap
+loggerSensors = LoggerSensors.LoggerSensors(logSize=20000-3)
+logger = LoggerControl(0.001, 30, logSize=20000-3)
+N_logger = logger.tstamps.shape[0]
+logger.processMocap(N_logger, loggerSensors)
+logger.loadAll(loggerSensors, fileName= file_name)
+
+mocap_RPY = logger.mocap_RPY
+mocap_pos = logger.mocap_pos
+
+k_0 = int( iteration_mpc * (params.dt_mpc / params.dt_wbc) ) # initial simulation iteration corresponding
+N_mpc = 12 # Number of mpc to launch
+
+
+t_init = k_0*params.dt_wbc
+t_end = k_0*params.dt_wbc + N_mpc*params.dt_mpc 
+T = np.linspace(t_init, t_end - params.dt_wbc , int( (t_end - t_init)/params.dt_wbc ) + 1)
+
+plt.figure()
+k_end = int(k_0 + N_mpc * params.dt_mpc / params.dt_wbc)
+
+gait = planner_gait[k_0,:,:]
+flying_feet = np.where(gait[0,:] == 0.)[0]
+foot = flying_feet[0]
+
+lgd = ["Position X", "Velocity X",  "Accleration X", "Jerk X", "Position Y", "Velocity Y", "Accleration Y",  "Jerk Y"]
+
+plt.subplot(2,4,1)
+plt.plot(T, planner_goals[k_0:k_end, 0,foot], linewidth=4, color="r" )
+plt.xlabel(lgd[0])
+plt.subplot(2,4,2)
+plt.plot(T, planner_vgoals[k_0:k_end, 0,foot], linewidth=4, color="r" )
+plt.xlabel(lgd[1])
+plt.subplot(2,4,3)
+plt.plot(T, planner_agoals[k_0:k_end, 0,foot], linewidth=4, color="r" )
+plt.xlabel(lgd[2])
+plt.subplot(2,4,4)
+plt.plot(T, planner_jgoals[k_0:k_end, 0,foot], linewidth=4, color="r" )
+plt.xlabel(lgd[3])
+
+plt.subplot(2,4,5)
+plt.plot(T, planner_goals[k_0:k_end, 1,foot], linewidth=4, color="r"  )
+plt.xlabel(lgd[4])
+plt.subplot(2,4,6)
+plt.plot(T, planner_vgoals[k_0:k_end, 1,foot], linewidth=4, color="r" )
+plt.xlabel(lgd[5])
+plt.subplot(2,4,7)
+plt.plot(T, planner_agoals[k_0:k_end, 1,foot], linewidth=4, color="r" )
+plt.xlabel(lgd[6])
+plt.subplot(2,4,8)
+plt.plot(T, planner_jgoals[k_0:k_end, 1,foot], linewidth=4, color="r" )
+plt.xlabel(lgd[7])
+
+
+cmap = plt.cm.get_cmap("hsv", N_mpc)
+
+for i in range(N_mpc):
+    
+    k = int( iteration_mpc * (params.dt_mpc / params.dt_wbc) ) - 1# simulation iteration corresponding
+    gait = planner_gait[k,:,:]
+    id = 0
+    while gait[id,foot] == 0 :
+        id += 1
+    o_fsteps = mpc_x_f[k,24 +  2*foot:24+2*foot+2, id+1] 
+    print(k)
+    x0 = planner_goals[k,0,foot]
+    y0 = planner_goals[k,1,foot]
+    xv0 = planner_vgoals[k,0,foot]
+    yv0 = planner_vgoals[k,1,foot]
+    xa0 = planner_agoals[k,0,foot]
+    ya0 = planner_agoals[k,1,foot]
+    dt_ = 0.24-params.dt_mpc*i
+
+    # part curve :
+    part_curve = 0
+    if dt_ >= 0.24 - vert_time : 
+        dt_ = 0.24 - 2*vert_time
+        part_curve = 0
+    elif dt_ >= vert_time :
+        dt_ -= vert_time
+        part_curve = 1
+    else :
+        part_curve = 2
+    poly_x = Poly_5(x0,xv0,xa0, o_fsteps[0],dt_)
+    poly_y = Poly_5(y0,yv0,ya0, o_fsteps[1],dt_)
+    
+    T =  np.linspace(0,dt_, 50)
+
+    
+    X = [poly_x.compute(t,0) for t in T]
+    VX = [poly_x.compute(t,1) for t in T]
+    AX = [poly_x.compute(t,2) for t in T]
+    JX = [poly_x.compute(t,3) for t in T]
+
+    Y = [poly_y.compute(t,0) for t in T]
+    VY = [poly_y.compute(t,1) for t in T]
+    AY = [poly_y.compute(t,2) for t in T]
+    JY = [poly_y.compute(t,3) for t in T]
+
+    
+    if part_curve == 0 :
+        t0 = t_init + vert_time
+        T += t0 
+    elif part_curve == 1 :
+        t0 = t_init + params.dt_mpc*i
+        T += t0 
+    else :
+        t0 = t_init + params.dt_mpc*i
+        T += t0
+
+
+    plt.subplot(2,4,1)
+    plt.plot(T,X, color = cmap(i) )
+    plt.plot(T[0], X[0],marker = "o", color = cmap(i) ) 
+
+    plt.subplot(2,4,2)
+    plt.plot(T,VX, color = cmap(i) )
+    plt.plot(T[0], VX[0],marker = "o", color = cmap(i) ) 
+    plt.subplot(2,4,3)
+    plt.plot(T,AX, color = cmap(i) )
+    plt.plot(T[0], AX[0],marker = "o", color = cmap(i) ) 
+    plt.subplot(2,4,4)
+    plt.plot(T,JX, color = cmap(i) )
+    plt.plot(T[0], JX[0],marker = "o", color = cmap(i) ) 
+
+    
+    plt.subplot(2,4,5)
+    plt.plot(T,Y, color = cmap(i) )
+    plt.plot(T[0], Y[0],marker = "o", color = cmap(i) )
+
+    plt.subplot(2,4,6)
+    plt.plot(T,VY, color = cmap(i) )
+    plt.plot(T[0], VY[0],marker = "o", color = cmap(i) )
+
+    plt.subplot(2,4,7)
+    plt.plot(T,AY, color = cmap(i) )
+    plt.plot(T[0], AY[0],marker = "o", color = cmap(i) )
+
+    plt.subplot(2,4,8)
+    plt.plot(T,JY, color = cmap(i) )
+    plt.plot(T[0], JY[0],marker = "o", color = cmap(i) )
+
+    iteration_mpc += 1
+
+
+
+fig_f, ax_f = plt.subplots(2,4)
+iteration_mpc = iteration_init
+t_init = k_0*params.dt_wbc
+t_end = k_0*params.dt_wbc + N_mpc*params.dt_mpc 
+
+for i in range(N_mpc):
+    
+    k = int( iteration_mpc * (params.dt_mpc / params.dt_wbc) ) - 1# simulation iteration corresponding
+    gait = planner_gait[k,:,:]
+    id = 0
+    while gait[id,foot] == 0 :
+        id += 1
+    o_fsteps = mpc_x_f[k,24 +  2*foot:24+2*foot+2, id+1] 
+    print(k)
+    x0 = planner_goals[k,0,foot]
+    y0 = planner_goals[k,1,foot]
+    xv0 = planner_vgoals[k,0,foot]
+    yv0 = planner_vgoals[k,1,foot]
+    xa0 = planner_agoals[k,0,foot]
+    ya0 = planner_agoals[k,1,foot]
+    dt_ = 0.24-params.dt_mpc*i
+
+    # part curve :
+    part_curve = 0
+    if dt_ >= 0.24 - vert_time : 
+        dt_ = 0.24 - 2*vert_time
+        part_curve = 0
+    elif dt_ >= vert_time :
+        dt_ -= vert_time
+        part_curve = 1
+    else :
+        part_curve = 2
+    poly_x = Poly_5(x0,xv0,xa0, o_fsteps[0],dt_)
+    poly_y = Poly_5(y0,yv0,ya0, o_fsteps[1],dt_)
+    
+    T =  np.linspace(0,dt_, 20)
+
+    
+    X = [poly_x.compute(t,0) for t in T]
+    VX = [poly_x.compute(t,1) for t in T]
+    AX = [poly_x.compute(t,2) for t in T]
+    JX = [poly_x.compute(t,3) for t in T]
+
+    Y = [poly_y.compute(t,0) for t in T]
+    VY = [poly_y.compute(t,1) for t in T]
+    AY = [poly_y.compute(t,2) for t in T]
+    JY = [poly_y.compute(t,3) for t in T]
+
+    
+    if part_curve == 0 :
+        t0 = t_init + vert_time
+        T += t0 
+    elif part_curve == 1 :
+        t0 = t_init + params.dt_mpc*i
+        T += t0 
+    else :
+        t0 = t_init + params.dt_mpc*i
+        T += t0
+
+    # Set up lists of (x,y) points for predicted state i
+    points_j = np.array([T, X]).transpose().reshape(-1,1,2)
+    # Set up lists of segments
+    segs_j = np.concatenate([points_j[:-1], points_j[1:]], axis=1)
+    # Make collections segments
+    cm = plt.get_cmap('Greys_r') 
+    lc_q = LineCollection(segs_j, cmap=cm, zorder=-1)
+    lc_q.set_array(T)
+    # Customize
+    lc_q.set_linestyle('-')
+
+
+    # Scatter to highlight points
+    colors = np.r_[np.linspace(0.1, 0.65, 19), 1] 
+    my_colors = cm(colors)
+
+
+    ax_f[0,0].add_collection(lc_q)
+    # Scatter to highlight points
+    ax_f[0,0].scatter(T, X, s=10, zorder=1, c=my_colors, cmap=matplotlib.cm.Greys)
+
+
+    #####
+
+    # Set up lists of (x,y) points for predicted state i
+    points_j = np.array([T, VX]).transpose().reshape(-1,1,2)
+    # Set up lists of segments
+    segs_j = np.concatenate([points_j[:-1], points_j[1:]], axis=1)
+    # Make collections segments
+    cm = plt.get_cmap('Greys_r') 
+    lc_q = LineCollection(segs_j, cmap=cm, zorder=-1)
+    lc_q.set_array(T)
+    # Customize
+    lc_q.set_linestyle('-')
+    ax_f[0,1].add_collection(lc_q)
+    # Scatter to highlight points
+    ax_f[0,1].scatter(T, VX, s=10, zorder=1, c=my_colors, cmap=matplotlib.cm.Greys)
+
+     #####
+
+    # Set up lists of (x,y) points for predicted state i
+    points_j = np.array([T, AX]).transpose().reshape(-1,1,2)
+    # Set up lists of segments
+    segs_j = np.concatenate([points_j[:-1], points_j[1:]], axis=1)
+    # Make collections segments
+    cm = plt.get_cmap('Greys_r') 
+    lc_q = LineCollection(segs_j, cmap=cm, zorder=-1)
+    lc_q.set_array(T)
+    # Customize
+    lc_q.set_linestyle('-')
+    ax_f[0,2].add_collection(lc_q)
+    # Scatter to highlight points
+    ax_f[0,2].scatter(T, AX, s=10, zorder=1, c=my_colors, cmap=matplotlib.cm.Greys)
+
+    #####
+
+    # Set up lists of (x,y) points for predicted state i
+    points_j = np.array([T, JX]).transpose().reshape(-1,1,2)
+    # Set up lists of segments
+    segs_j = np.concatenate([points_j[:-1], points_j[1:]], axis=1)
+    # Make collections segments
+    cm = plt.get_cmap('Greys_r') 
+    lc_q = LineCollection(segs_j, cmap=cm, zorder=-1)
+    lc_q.set_array(T)
+    # Customize
+    lc_q.set_linestyle('-')
+    ax_f[0,3].add_collection(lc_q)
+    # Scatter to highlight points
+    ax_f[0,3].scatter(T, JX, s=10, zorder=1, c=my_colors, cmap=matplotlib.cm.Greys)
+
+##################################################################################################
+
+     # Set up lists of (x,y) points for predicted state i
+    points_j = np.array([T, Y]).transpose().reshape(-1,1,2)
+    # Set up lists of segments
+    segs_j = np.concatenate([points_j[:-1], points_j[1:]], axis=1)
+    # Make collections segments
+    cm = plt.get_cmap('Greys_r') 
+    lc_q = LineCollection(segs_j, cmap=cm, zorder=-1)
+    lc_q.set_array(T)
+    # Customize
+    lc_q.set_linestyle('-')
+
+
+    # Scatter to highlight points
+    colors = np.r_[np.linspace(0.1, 0.65, 19), 1] 
+    my_colors = cm(colors)
+
+
+    ax_f[1,0].add_collection(lc_q)
+    # Scatter to highlight points
+    ax_f[1,0].scatter(T, Y, s=10, zorder=1, c=my_colors, cmap=matplotlib.cm.Greys)
+
+
+    #####
+
+    # Set up lists of (x,y) points for predicted state i
+    points_j = np.array([T, VY]).transpose().reshape(-1,1,2)
+    # Set up lists of segments
+    segs_j = np.concatenate([points_j[:-1], points_j[1:]], axis=1)
+    # Make collections segments
+    cm = plt.get_cmap('Greys_r') 
+    lc_q = LineCollection(segs_j, cmap=cm, zorder=-1)
+    lc_q.set_array(T)
+    # Customize
+    lc_q.set_linestyle('-')
+    ax_f[1,1].add_collection(lc_q)
+    # Scatter to highlight points
+    ax_f[1,1].scatter(T, VY, s=10, zorder=1, c=my_colors, cmap=matplotlib.cm.Greys)
+
+     #####
+
+    # Set up lists of (x,y) points for predicted state i
+    points_j = np.array([T, AY]).transpose().reshape(-1,1,2)
+    # Set up lists of segments
+    segs_j = np.concatenate([points_j[:-1], points_j[1:]], axis=1)
+    # Make collections segments
+    cm = plt.get_cmap('Greys_r') 
+    lc_q = LineCollection(segs_j, cmap=cm, zorder=-1)
+    lc_q.set_array(T)
+    # Customize
+    lc_q.set_linestyle('-')
+    ax_f[1,2].add_collection(lc_q)
+    # Scatter to highlight points
+    ax_f[1,2].scatter(T, AY, s=10, zorder=1, c=my_colors, cmap=matplotlib.cm.Greys)
+
+    #####
+
+    # Set up lists of (x,y) points for predicted state i
+    points_j = np.array([T, JY]).transpose().reshape(-1,1,2)
+    # Set up lists of segments
+    segs_j = np.concatenate([points_j[:-1], points_j[1:]], axis=1)
+    # Make collections segments
+    cm = plt.get_cmap('Greys_r') 
+    lc_q = LineCollection(segs_j, cmap=cm, zorder=-1)
+    lc_q.set_array(T)
+    # Customize
+    lc_q.set_linestyle('-')
+    ax_f[1,3].add_collection(lc_q)
+    # Scatter to highlight points
+    ax_f[1,3].scatter(T, JY, s=10, zorder=1, c=my_colors, cmap=matplotlib.cm.Greys)
+
+
+
+    # plt.subplot(2,4,1)
+    # plt.plot(T,X, color = cmap(i) )
+    # plt.plot(T[0], X[0],marker = "o", color = cmap(i) ) 
+
+    # plt.subplot(2,4,2)
+    # plt.plot(T,VX, color = cmap(i) )
+    # plt.plot(T[0], VX[0],marker = "o", color = cmap(i) ) 
+    # plt.subplot(2,4,3)
+    # plt.plot(T,AX, color = cmap(i) )
+    # plt.plot(T[0], AX[0],marker = "o", color = cmap(i) ) 
+    # plt.subplot(2,4,4)
+    # plt.plot(T,JX, color = cmap(i) )
+    # plt.plot(T[0], JX[0],marker = "o", color = cmap(i) ) 
+
+    
+    # plt.subplot(2,4,5)
+    # plt.plot(T,Y, color = cmap(i) )
+    # plt.plot(T[0], Y[0],marker = "o", color = cmap(i) )
+
+    # plt.subplot(2,4,6)
+    # plt.plot(T,VY, color = cmap(i) )
+    # plt.plot(T[0], VY[0],marker = "o", color = cmap(i) )
+
+    # plt.subplot(2,4,7)
+    # plt.plot(T,AY, color = cmap(i) )
+    # plt.plot(T[0], AY[0],marker = "o", color = cmap(i) )
 
-############
-# OSQP MPC
-###########
-mpc_osqp = lqrw.MPC(params)
-mpc_osqp.run(0, planner_xref[0] , planner_fsteps[0]) # Initialization of the matrix
-# mpc_osqp.run(1, planner_xref[1] , planner_fsteps[1])
-mpc_osqp.run(k, planner_xref[k] , planner_fsteps[k])
+    # plt.subplot(2,4,8)
+    # plt.plot(T,JY, color = cmap(i) )
+    # plt.plot(T[0], JY[0],marker = "o", color = cmap(i) )
 
-osqp_xs = mpc_osqp.get_latest_result()[:12,:] # States computed over the whole predicted horizon
-osqp_xs = np.vstack([planner_xref[k,:,0] , osqp_xs.transpose()]).transpose() # Add current state 
-osqp_us = mpc_osqp.get_latest_result()[12:,:] # Forces computed over the whole predicted horizon
+    iteration_mpc += 1
 
+t_init = k_0*params.dt_wbc
+t_end = k_0*params.dt_wbc + N_mpc*params.dt_mpc 
+T = np.linspace(t_init, t_end - params.dt_wbc , int( (t_end - t_init)/params.dt_wbc ) + 1)
 
-###########
-# DDP MPC 
-##########
-mpc_ddp = MPC_crocoddyl_planner.MPC_crocoddyl_planner(params, mu=0.9, inner=False)
 
-# Tune the weights 
-mpc_ddp.heuristicWeights = np.array(4*[0.3, 0.4])
-mpc_ddp.stepWeights = np.full(8, 0.5)
-mpc_ddp.stateWeights = np.sqrt([2.0, 2.0, 20.0, 0.25, 0.25, 10.0, 0.2, 0.2, 0.2, 0.0, 0.0, 0.3]) # fit osqp gains
-mpc_ddp.initialize_models(params) # re-initialize the model list with the new gains
+ax_f[0,0].plot(T, planner_goals[k_0:k_end, 0,foot], linewidth=2, color="b" )
+ax_f[0,0].set(xlabel=lgd[0])
+ax_f[0,1].plot(T, planner_vgoals[k_0:k_end, 0,foot], linewidth=2, color="b" )
+ax_f[0,1].set(xlabel=lgd[1])
+ax_f[0,2].plot(T, planner_agoals[k_0:k_end, 0,foot], linewidth=2, color="b" )
+ax_f[0,2].set(xlabel=lgd[2])
+ax_f[0,3].plot(T, planner_jgoals[k_0:k_end, 0,foot], linewidth=2, color="b" )
+ax_f[0,3].set(xlabel=lgd[3])
 
-mpc_ddp.gait = planner_gait[k_previous].copy() # gait_old will be initialised with that
 
-print(mpc_ddp.gait)
-mpc_ddp.updateProblem(k , planner_xref[k] , planner_fsteps[k], planner_goals[k])
+ax_f[1,0].plot(T, planner_goals[k_0:k_end, 1,foot], linewidth=2, color="b" )
+ax_f[1,0].set(xlabel=lgd[4])
+ax_f[1,1].plot(T, planner_vgoals[k_0:k_end, 1,foot], linewidth=2, color="b" )
+ax_f[1,1].set(xlabel=lgd[5])
+ax_f[1,2].plot(T, planner_agoals[k_0:k_end, 1,foot], linewidth=2, color="b" )
+ax_f[1,2].set(xlabel=lgd[6])
+ax_f[1,3].plot(T, planner_jgoals[k_0:k_end, 1,foot], linewidth=2, color="b" )
+ax_f[1,3].set(xlabel=lgd[7])
 
-mpc_ddp.ddp.solve(mpc_ddp.x_init,  mpc_ddp.u_init, mpc_ddp.max_iteration)
 
-oRh = np.eye(3)
-oTh = np.zeros((3,1))
 
-ddp_xs = mpc_ddp.get_latest_result(oRh, oTh)[:12,:] # States computed over the whole predicted horizon 
-ddp_xs = np.vstack([planner_xref[k,:,0] , ddp_xs.transpose()]).transpose() # Add current state 
-ddp_us = mpc_ddp.get_latest_result(oRh, oTh)[12:,:] # Forces computed over the whole predicted horizon
-ddp_fsteps = mpc_ddp.get_latest_result(oRh, oTh)[24:,:]
-ddp_fsteps = np.vstack([planner_fsteps[k,0,:][[0,1,3,4,6,7,9,10]] , ddp_fsteps.transpose()]).transpose() # Add current state 
 
 
-#############
-#  Plot     #
-#############
 
-# Predicted evolution of state variables
-l_t = np.linspace(0., params.T_gait, np.int(params.T_gait/params.dt_mpc)+1)
-l_str = ["X_osqp", "Y_osqp", "Z_osqp", "Roll_osqp", "Pitch_osqp", "Yaw_osqp", "Vx_osqp", "Vy_osqp", "Vz_osqp", "VRoll_osqp", "VPitch_osqp", "VYaw_osqp"]
-l_str2 = ["X_ddp", "Y_ddp", "Z_ddp", "Roll_ddp", "Pitch_ddp", "Yaw_ddp", "Vx_ddp", "Vy_ddp", "Vz_ddp", "VRoll_ddp", "VPitch_ddp", "VYaw_ddp"]
+
+
+
+
+iteration_mpc = iteration_init
+t_0 = k_0*params.dt_wbc 
+N = mpc_x_f.shape[2] 
+
+l_str = ["Position X", "Position Y", "Position Z",
+         "Position Roll", "Position Pitch", "Position Yaw",
+         "Linear velocity X", "Linear velocity Y", "Linear velocity Z",
+         "Angular velocity Roll", "Angular velocity Pitch", "Angular velocity Yaw"]
+
 
 index = [1, 5, 9, 2, 6, 10, 3, 7, 11, 4, 8, 12]
-plt.figure()
-for i in range(12):
-    plt.subplot(3, 4, index[i])
+
+# plt.figure()
+# for i in range(N_mpc):
+#     k = int( iteration_mpc * (params.dt_mpc / params.dt_wbc) ) - 1# simulation iteration corresponding
+#     xref = planner_xref[k].copy() # From logged value
+#     xs = mpc_x_f[k,:12,:]
+#     xs = np.vstack([xref[:,0] , xs.transpose()]).transpose()
+
+#     t_init = t_0 + i*params.dt_mpc
+#     t_end = t_init + N*params.dt_mpc
+#     T = np.linspace(t_init, t_end,N+1)
+
+#     for j in range(12):
+#         plt.subplot(3,4,index[j])
+#         plt.plot(T,xs[j,:])
     
-    pl1, = plt.plot(l_t, ddp_xs[i,:], linewidth=2, marker='x')
-    pl2, = plt.plot(l_t, osqp_xs[i,:], linewidth=2, marker='x')
+#     iteration_mpc +=1
+
+
+# for j in range(12):
+#     plt.subplot(3,4,index[j])
+#     plt.xlabel(l_str[j])
+
+iteration_mpc = iteration_init
+t_0 = k_0*params.dt_wbc 
+N = mpc_x_f.shape[2] 
+
+data_xs_mpc = np.zeros((12,25, N_mpc))
+iteration_mpc = iteration_init
+# Extract state prediction
+for i in range(N_mpc):
+    k = int( iteration_mpc * (params.dt_mpc / params.dt_wbc) ) - 1 # simulation iteration corresponding
+    xref = planner_xref[k].copy() # From logged value
+    xs = mpc_x_f[k,:12,:]
+    xs = np.vstack([xref[:,0] , xs.transpose()]).transpose()
+    data_xs_mpc[:,:,i] = xs
+    iteration_mpc +=1
+
 
-    if Relaunch_DDP : 
-        pl3, = plt.plot(l_t, ddp_xs_relaunch[i,:], linewidth=2, marker='x')
-        plt.legend([pl1,pl2,pl3] , [l_str2[i] , l_str[i], "ddp_redo" ])
     
-    else : 
-        plt.legend([pl1,pl2] , [l_str2[i] , l_str[i] ])      
 
-# Desired evolution of contact forces
-l_t = np.linspace(params.dt_mpc, params.T_gait, np.int(params.T_gait/params.dt_mpc))
-l_str = ["FL_X_osqp", "FL_Y_osqp", "FL_Z_osqp", "FR_X_osqp", "FR_Y_osqp", "FR_Z_osqp", "HL_X_osqp", "HL_Y_osqp", "HL_Z_osqp", "HR_X_osqp", "HR_Y_osqp", "HR_Z_osqp"]
-l_str2 = ["FL_X_ddp", "FL_Y_ddp", "FL_Z_ddp", "FR_X_ddp", "FR_Y_ddp", "FR_Z_ddp", "HL_X_ddp", "HL_Y_ddp", "HL_Z_ddp", "HR_X_ddp", "HR_Y_ddp", "HR_Z_ddp"]
+# index = [1, 5, 9, 2, 6, 10, 3, 7, 11, 4, 8, 12]
+
+fig_x, ax_x = plt.subplots(3,4)
+com_offset = 0.03
+# For each states
+for i in range(12):
+    # Extract state prediction
+    xs_i =  data_xs_mpc[i,:,:]
+    if i == 2 :
+        xs_i[1:,:] += com_offset
+    # For each planning step in the trajectory
+    for j in range(N_mpc):
+        # Receding horizon = [j,j+N_h]
+        t0_horizon = t_init + j*params.dt_mpc
+        t_end =  t0_horizon + N*params.dt_mpc
+        tspan_x_pred = np.linspace(t0_horizon, t_end,N+1)
+
+        # Set up lists of (x,y) points for predicted state i
+        points_j = np.array([tspan_x_pred, xs_i[:,j]]).transpose().reshape(-1,1,2)
+
+        # Set up lists of segments
+        segs_j = np.concatenate([points_j[:-1], points_j[1:]], axis=1)
+
+        # Make collections segments
+        cm = plt.get_cmap('Greys_r') 
+        lc_q = LineCollection(segs_j, cmap=cm, zorder=-1)
+
+        lc_q.set_array(tspan_x_pred)
+
+        # Customize
+        lc_q.set_linestyle('-')
+
+        # Scatter to highlight points
+        colors = np.r_[np.linspace(0.1, 1, N), 1] 
+        my_colors = cm(colors)
+
+        if i < 3:
+            # Plot collections
+            ax_x[i,0].add_collection(lc_q)
+            # Scatter to highlight points
+            ax_x[i,0].scatter(tspan_x_pred, xs_i[:,j], s=10, zorder=1, c=my_colors, cmap=matplotlib.cm.Greys)
+
+        elif i < 6:
+            # Plot collections
+            ax_x[i-3,1].add_collection(lc_q)
+            # Scatter to highlight points
+            ax_x[i-3,1].scatter(tspan_x_pred, xs_i[:,j], s=10, zorder=1, c=my_colors, cmap=matplotlib.cm.Greys)
+        
+        elif i < 9:
+            # Plot collections
+            ax_x[i-6,2].add_collection(lc_q)
+            # Scatter to highlight points
+            ax_x[i-6,2].scatter(tspan_x_pred, xs_i[:,j], s=10, zorder=1, c=my_colors, cmap=matplotlib.cm.Greys)
+        
+        else:
+            # Plot collections
+            ax_x[i-9,3].add_collection(lc_q)
+            # Scatter to highlight points
+            ax_x[i-9,3].scatter(tspan_x_pred, xs_i[:,j], s=10, zorder=1, c=my_colors, cmap=matplotlib.cm.Greys)
+
+        
+t_init = k_0*params.dt_wbc
+t_end = k_0*params.dt_wbc + N_mpc*params.dt_mpc 
+k_end = int(k_0 + N_mpc * params.dt_mpc / params.dt_wbc)
+T = np.linspace(t_init, t_end - params.dt_wbc , int( (t_end - t_init)/params.dt_wbc ) + 1)
+
+
+####
+# Measured & Reference position and orientation (ideal world frame)
+####
+
 index = [1, 5, 9, 2, 6, 10, 3, 7, 11, 4, 8, 12]
-plt.figure()
 for i in range(12):
-    plt.subplot(3, 4, index[i])
-    pl1, = plt.plot(l_t, ddp_us[i,:], linewidth=2, marker='x')
-    pl2, = plt.plot(l_t, osqp_us[i,:], linewidth=2, marker='x')
-   
-    if Relaunch_DDP : 
-        pl3, = plt.plot(l_t, ddp_us_relaunch[i,:], linewidth=2, marker='x')
-        plt.legend([pl1,pl2,pl3] , [l_str2[i] , l_str[i], "ddp_redo" ])
+    if i < 2 :
+        pass
+    elif i < 3:
+        ax_x[i,0].plot(T, planner_xref[k_0:k_end, i, 0], "b", linewidth=3)
+        ax_x[i,0].legend(["Robot state"], prop={'size': 8})
+        ax_x[i,0].set(xlabel=l_str[i])
+    elif i < 6:
+        ax_x[i-3,1].plot(T, planner_xref[k_0:k_end, i, 0], "b", linewidth=3)
+        ax_x[i-3,1].legend(["Robot state"], prop={'size': 8})
+        ax_x[i-3,1].set(xlabel=l_str[i])
+    elif i < 9:
+        ax_x[i-6,2].plot(T, planner_xref[k_0:k_end, i, 0], "b", linewidth=3)
+        ax_x[i-6,2].legend(["Robot state"], prop={'size': 8})
+        ax_x[i-6,2].set(xlabel=l_str[i])
+    else:
+        ax_x[i-9,3].plot(T, planner_xref[k_0:k_end, i, 0], "b", linewidth=3)
+        ax_x[i-9,3].legend(["Robot state"], prop={'size': 8})
+        ax_x[i-9,3].set(xlabel=l_str[i])
     
-    else : 
-        plt.legend([pl1,pl2] , [l_str2[i] , l_str[i] ])
 
-plt.figure()
-# CoM position predicted 
-l_t = np.linspace(0., params.T_gait, np.int(params.T_gait/params.dt_mpc)+1)
-for j in range(len(l_t)) : 
-    if j == 6 : # middle sizie of the cross, for the legend
-        pl1, = plt.plot(ddp_xs[0,j],  ddp_xs[1,j] ,color = "k" , marker='x', markersize= int(20/np.sqrt(j+3)) )
-        pl2, = plt.plot(planner_xref[k,0,j], planner_xref[k,1,j] ,color = "g" , marker='x', markersize= int(20/np.sqrt(j+3)) )
-    else : 
-        plt.plot(ddp_xs[0,j],  ddp_xs[1,j] ,color = "k" , marker='x', markersize= int(20/np.sqrt(j+3)) )
-        plt.plot(planner_xref[k,0,j], planner_xref[k,1,j] ,color = "g" , marker='x', markersize= int(20/np.sqrt(j+3)) )
-
-plt.legend([pl1,pl2] , ["CoM ddp" , "CoM ref" ])
-
-# First foot on the ground using previous gait matrix : iteration - 1
-for j in range(4) :       
-    if planner_gait[k_previous,0,j] == 1 : 
-        pl3, = plt.plot(planner_fsteps[k_previous,0 , 3*j] , planner_fsteps[k_previous,0 , 3*j] ,  'ro', markersize= 8   )
-        # plt.plot(mpc_planner.Xs[12+2*i , 0  ] , mpc_planner.Xs[12+2*i + 1 , 0  ] ,  'yo', markerSize= 8   )
-
-# Foostep computed by ddp and planner fsteps
-for j in range(len(l_t)) : 
-    for foot in range(4): 
-        if j == 6 : # middle sizie of the cross, for the legend
-            pl4, = plt.plot(ddp_fsteps[2*foot,j], ddp_fsteps[2*foot+ 1,j] ,color = "k" , marker='o', markersize= int(20/np.sqrt(j+3)),markerfacecolor='none' )
-            pl5, =  plt.plot(planner_fsteps[k,j , 3*foot] , planner_fsteps[k,j , 3*foot+1],color = "r" ,  marker='o', markersize= int(20/np.sqrt(j+3))  ,markerfacecolor='none' )
-        else : 
-            plt.plot(ddp_fsteps[2*foot,j], ddp_fsteps[2*foot+ 1,j] ,color = "k" , marker='o', markersize= int(20/np.sqrt(j+3)),markerfacecolor='none' )
-            plt.plot(planner_fsteps[k,j , 3*foot] , planner_fsteps[k,j , 3*foot+1],color = "r" ,  marker='o', markersize= int(20/np.sqrt(j+3))  ,markerfacecolor='none' )
-
-plt.legend([pl1,pl2,pl3] , ["CoM ddp" , "CoM ref" , "previous fstep"])
-plt.grid()
-plt.show(block=True)
 
+    
+    
+
+
+
+
+
+
+
+plt.show()
+
+
+
+
+# T = np.linspace()
+# for it in range(N_mpc):
+
+
+#     k_0 = int( iteration_mpc * (params.dt_mpc / params.dt_wbc) ) # simulation iteration corresponding
+#     gait = planner_gait[k_0]
 
 
diff --git a/scripts/crocoddyl_eval/test_6/compare_mpcs.py b/scripts/crocoddyl_eval/test_6/compare_mpcs.py
index a9a68a3156ded2ad8564f74535c1c582193ce983..01743216c262df9312a12e7529d6043810394f2e 100644
--- a/scripts/crocoddyl_eval/test_6/compare_mpcs.py
+++ b/scripts/crocoddyl_eval/test_6/compare_mpcs.py
@@ -88,7 +88,6 @@ for j in range(4):
         for t in range(N):
             if np.isnan(data_[t,i,j]):
                 data_[t,i,j] = data_[t-1,i,j]
-
 ##########
 # PLOTS 
 ##########
@@ -166,7 +165,7 @@ for i in range(6):
     
     for j in range(4):
         if MPCs[j]:
-            plt.plot(t_range, data_diff[:,index_error[i],j], color[j], linewidth=3)    
+            plt.plot(t_range, abs(data_diff[:,index_error[i],j]), color[j], linewidth=3)    
 
 # Add mean on graph
 # for i in range(6):
@@ -177,7 +176,7 @@ for i in range(6):
 
     plt.legend(legend, prop={'size': 8})
     plt.ylabel(lgd[i])
-plt.suptitle("Error wrt reference state")
+plt.suptitle("Absolute Error wrt reference state")
 
 plt.figure()
 for i in range(6):
@@ -212,7 +211,7 @@ bars = []
 bars_names = ["Lin", "NL", "Plan", "OSQP"]
 for j in range(4):
     if MPCs[j]:
-        bars.append(bars_names[j])
+        bars.append(MPCs_names[j])
 
 plt.figure()
 for i in range(6):
@@ -256,30 +255,30 @@ plt.suptitle("NORMALIZED RMSE -MEAN: sqrt(  (mes - ref - mean(mes-ref))  **2).me
 ####
 # FF torques & FB torques & Sent torques & Meas torques
 ####
-index12 = [1, 5, 9, 2, 6, 10, 3, 7, 11, 4, 8, 12]
-lgd1 = ["HAA", "HFE", "Knee"]
-lgd2 = ["FL", "FR", "HL", "HR"]
-plt.figure()
-my_axs = []
-for i in range(12):
-    if i == 0:
-        ax = plt.subplot(3, 4, index12[i])
-        my_axs.append(ax)
-    elif i in [1, 2]:
-        ax = plt.subplot(3, 4, index12[i], sharex=my_axs[0])
-        my_axs.append(ax)
-    else:
-        plt.subplot(3, 4, index12[i], sharex=my_axs[0], sharey=my_axs[int(i % 3)])
+# index12 = [1, 5, 9, 2, 6, 10, 3, 7, 11, 4, 8, 12]
+# lgd1 = ["HAA", "HFE", "Knee"]
+# lgd2 = ["FL", "FR", "HL", "HR"]
+# plt.figure()
+# my_axs = []
+# for i in range(12):
+#     if i == 0:
+#         ax = plt.subplot(3, 4, index12[i])
+#         my_axs.append(ax)
+#     elif i in [1, 2]:
+#         ax = plt.subplot(3, 4, index12[i], sharex=my_axs[0])
+#         my_axs.append(ax)
+#     else:
+#         plt.subplot(3, 4, index12[i], sharex=my_axs[0], sharey=my_axs[int(i % 3)])
 
-    for j in range(4):
-        if MPCs[j]:
-            plt.plot(t_range, tau_ff_[:,i,j], color[j], linewidth=3)
+#     for j in range(4):
+#         if MPCs[j]:
+#             plt.plot(t_range, tau_ff_[:,i,j], color[j], linewidth=3)
 
-    plt.xlabel("Time [s]")
-    plt.ylabel(lgd1[i % 3]+" "+lgd2[int(i/3)]+" [Nm]")
-    tmp = lgd1[i % 3]+" "+lgd2[int(i/3)]
-    plt.legend(legend, prop={'size': 8})
-    plt.ylim([-8.0, 8.0])
+#     plt.xlabel("Time [s]")
+#     plt.ylabel(lgd1[i % 3]+" "+lgd2[int(i/3)]+" [Nm]")
+#     tmp = lgd1[i % 3]+" "+lgd2[int(i/3)]
+#     plt.legend(legend, prop={'size': 8})
+#     plt.ylim([-8.0, 8.0])
 
 ####
 # Contact forces (MPC command) & WBC QP output
diff --git a/src/FootTrajectoryGenerator.cpp b/src/FootTrajectoryGenerator.cpp
index 299ca04a1af0ee6a6fbdf1d882a30187cd81143e..1ad0c5b5bc69582425244d0bd88d4084cf0b26c2 100644
--- a/src/FootTrajectoryGenerator.cpp
+++ b/src/FootTrajectoryGenerator.cpp
@@ -17,6 +17,7 @@ FootTrajectoryGenerator::FootTrajectoryGenerator()
       position_(Matrix34::Zero()),
       velocity_(Matrix34::Zero()),
       acceleration_(Matrix34::Zero()),
+      jerk_(Matrix34::Zero()),
       position_base_(Matrix34::Zero()),
       velocity_base_(Matrix34::Zero()),
       acceleration_base_(Matrix34::Zero()) {}
@@ -152,6 +153,8 @@ void FootTrajectoryGenerator::updateFootPosition(int const j, Vector3 const &tar
     velocity_(1, j) = 0.0;
     acceleration_(0, j) = 0.0;
     acceleration_(1, j) = 0.0;
+    jerk_(0, j) = 0.0;
+    jerk_(1, j) = 0.0;    
   } else {
     position_(0, j) = Ax(5, j) + Ax(4, j) * ev + Ax(3, j) * std::pow(ev, 2) + Ax(2, j) * std::pow(ev, 3) +
                       Ax(1, j) * std::pow(ev, 4) + Ax(0, j) * std::pow(ev, 5);
@@ -165,11 +168,15 @@ void FootTrajectoryGenerator::updateFootPosition(int const j, Vector3 const &tar
         2 * Ax(3, j) + 3 * 2 * Ax(2, j) * ev + 4 * 3 * Ax(1, j) * std::pow(ev, 2) + 5 * 4 * Ax(0, j) * std::pow(ev, 3);
     acceleration_(1, j) =
         2 * Ay(3, j) + 3 * 2 * Ay(2, j) * ev + 4 * 3 * Ay(1, j) * std::pow(ev, 2) + 5 * 4 * Ay(0, j) * std::pow(ev, 3);
+
+    jerk_(0, j) = 3 * 2 * Ax(2, j) + 4 * 3 * 2 * Ax(1, j) * ev + 5 * 4 * 3 * Ax(0, j) * std::pow(ev, 2);
+    jerk_(1, j) = 3 * 2 * Ay(2, j) + 4 * 3 * 2 * Ay(1, j) * ev + 5 * 4 * 3 * Ay(0, j) * std::pow(ev, 2);
   }
   velocity_(2, j) = 3 * Az(3, j) * std::pow(evz, 2) + 4 * Az(2, j) * std::pow(evz, 3) +
                     5 * Az(1, j) * std::pow(evz, 4) + 6 * Az(0, j) * std::pow(evz, 5);
   acceleration_(2, j) = 2 * 3 * Az(3, j) * evz + 3 * 4 * Az(2, j) * std::pow(evz, 2) +
                         4 * 5 * Az(1, j) * std::pow(evz, 3) + 5 * 6 * Az(0, j) * std::pow(evz, 4);
+  jerk_(2, j) = 2 * 3 * Az(3, j) + 3 * 4 * 2 * Az(2, j) * evz + 4 * 5 * 3 * Az(1, j) * std::pow(evz, 2) + 5 * 6 * 4 * Az(0, j) * std::pow(evz, 3);
   position_(2, j) = Az(3, j) * std::pow(evz, 3) + Az(2, j) * std::pow(evz, 4) + Az(1, j) * std::pow(evz, 5) +
                     Az(0, j) * std::pow(evz, 6);
 }