diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt
index 092f1d00d36676fa2eb301c54164544f7c54442a..271dfba2f3f0d754cdfd873e6bfa38ed22234127 100644
--- a/python/CMakeLists.txt
+++ b/python/CMakeLists.txt
@@ -40,6 +40,7 @@ set(${PY_NAME}_TOOLS_PYTHON
   LoggerControl.py
   PyBulletSimulator.py
   qualisysClient.py
+  kinematics_utils.py
   )
 
 foreach(python ${${PY_NAME}_PYTHON})
diff --git a/python/quadruped_reactive_walking/Controller.py b/python/quadruped_reactive_walking/Controller.py
index 6f05de62f01fe3452ba583df33548a0d3751d6a1..55fb4731b90abe72b648e9ec443017f7cda76fcb 100644
--- a/python/quadruped_reactive_walking/Controller.py
+++ b/python/quadruped_reactive_walking/Controller.py
@@ -102,11 +102,11 @@ class Controller:
             self.mpc_result, self.mpc_cost = self.mpc.get_latest_result()
 
             #self.result.P = np.array(self.params.Kp_main.tolist() * 4)
-            self.result.P = np.array([5] * 3 + [1] * 3 + [5]*6)
+            self.result.P = np.array([5] * 3 + [3] * 3 + [5]*6)
             #self.result.D = np.array(self.params.Kd_main.tolist() * 4)
             self.result.D = np.array([0.3] * 3 + [0.5] * 3 + [0.3]*6)
-            #tauFF = self.mpc_result.u[0] + np.dot(self.mpc_result.K[0], self.mpc.ocp.state.diff(m["x_m"], self.mpc_result.x[0]))
-            #self.result.FF = self.params.Kff_main * np.array([0] * 3 + list(tauFF) + [0]*6) 
+            tauFF = self.mpc_result.u[0] + np.dot(self.mpc_result.K[0], self.mpc.ocp.state.diff(m["x_m"], self.mpc_result.x[0]))
+            self.result.FF = self.params.Kff_main * np.array([0] * 3 + list(tauFF) + [0]*6) 
 
             # Keep only the actuated joints and set the other to default values
             self.mpc_result.q = np.array([self.pd.q0] * (self.pd.T + 1))[:, 7: 19]
diff --git a/python/quadruped_reactive_walking/WB_MPC/ProblemData.py b/python/quadruped_reactive_walking/WB_MPC/ProblemData.py
index 30d62f4eacaf7ac913be6ec83d93fd9e991e71cf..dddcf933989fbc78d5fddd81ef68135064b49281 100644
--- a/python/quadruped_reactive_walking/WB_MPC/ProblemData.py
+++ b/python/quadruped_reactive_walking/WB_MPC/ProblemData.py
@@ -9,8 +9,8 @@ class problemDataAbstract:
         self.dt_bldc = 0.0005
         self.r1 = int(self.dt / self.dt_sim)
         self.r2 = int(self.dt_sim / self.dt_bldc)
-        self.init_steps = 20 # full stand phase
-        self.target_steps = 60 # manipulation steps
+        self.init_steps = 10 # full stand phase
+        self.target_steps = 50 # manipulation steps
         self.T = self.init_steps + self.target_steps -1
 
         self.robot = erd.load("solo12")
diff --git a/python/quadruped_reactive_walking/main_solo12_control.py b/python/quadruped_reactive_walking/main_solo12_control.py
index 5decbb164a2799ebe3f5195856de02c18febbece..9f664493a3d6d3ed8039725e5c386178604a78cc 100644
--- a/python/quadruped_reactive_walking/main_solo12_control.py
+++ b/python/quadruped_reactive_walking/main_solo12_control.py
@@ -142,7 +142,7 @@ def control_loop():
         qc = QualisysClient(ip="140.93.16.160", body_id=0)
 
     if params.LOGGING or params.PLOTTING:
-        loggerControl = LoggerControl(log_size=params.N_SIMULATION-1)
+        loggerControl = LoggerControl(pd, log_size=params.N_SIMULATION-1)
 
     if params.SIMULATION:
         device.Init(
@@ -234,9 +234,10 @@ def control_loop():
         device.Stop()
 
     print("End of script")
+    return loggerControl
 
 
 if __name__ == "__main__":
     #os.nice(-20)
-    control_loop()
+    log = control_loop()
     #quit()
diff --git a/python/quadruped_reactive_walking/tools/LoggerControl.py b/python/quadruped_reactive_walking/tools/LoggerControl.py
index 779f642c3ebf43c4faa779c36198ace529bb43bd..184a65672aa364b02ade356f9071c13b598586c3 100644
--- a/python/quadruped_reactive_walking/tools/LoggerControl.py
+++ b/python/quadruped_reactive_walking/tools/LoggerControl.py
@@ -1,10 +1,11 @@
 from datetime import datetime
 from time import time
 import numpy as np
+from .kinematics_utils import get_translation, get_translation_array
 
 
 class LoggerControl:
-    def __init__(self, log_size=60e3, loop_buffer=False, file=None):
+    def __init__(self, pd, log_size=60e3, loop_buffer=False, file=None):
         if file is not None:
             self.data = np.load(file, allow_pickle=True)
 
@@ -13,6 +14,7 @@ class LoggerControl:
         self.loop_buffer = loop_buffer
 
         size = self.log_size
+        self.pd = pd
 
         # IMU and actuators:
         self.q_mes = np.zeros([size, 12])
@@ -42,6 +44,7 @@ class LoggerControl:
         # Controller timings: MPC time, ...
 
         self.ocp_timings = np.zeros([size])
+        self.ocp_storage = {"xs": np.zeros([size, pd.T + 1, pd.nx])}
 
         # MPC
 
@@ -91,6 +94,7 @@ class LoggerControl:
 
         # Logging from model predictive control
         self.ocp_timings[self.i] = controller.mpc.ocp.results.solver_time
+        self.ocp_storage["xs"][self.i] = np.array(controller.mpc.ocp.results.x)
 
         # Logging from whole body control
         self.wbc_P[self.i] = controller.result.P
@@ -110,6 +114,14 @@ class LoggerControl:
         import matplotlib.pyplot as plt
         matplotlib.use("QtAgg")
         plt.style.use("seaborn")
+
+        horizon = self.ocp_storage["xs"].shape[0]
+        t15 = np.linspace(0, horizon*self.pd.dt, horizon+1)
+        t1 = np.linspace(0, (horizon)*self.pd.dt, (horizon)*self.pd.r1+1)
+        t_mpc = np.linspace(0, (horizon)*self.pd.dt, horizon+1)
+
+        all_ocp_feet_p_log = {idx: [get_translation_array(self.pd, x, idx)[0] for x in self.ocp_storage["xs"]] for idx in self.pd.allContactIds}
+        for foot in all_ocp_feet_p_log: all_ocp_feet_p_log[foot] = np.array(all_ocp_feet_p_log[foot])
         
         legend = ['Hip', 'Shoulder', 'Knee']
         plt.figure(figsize=(12, 6), dpi = 90)
@@ -155,6 +167,19 @@ class LoggerControl:
             plt.legend(legend)
         plt.draw()
 
+        legend = ['x', 'y', 'z']
+        plt.figure(figsize=(12, 18), dpi = 90)
+        for p in range(3):
+            plt.subplot(3,1, p+1)
+            plt.title('Free foot on ' + legend[p])
+            for i in range(horizon-1):
+                t = np.linspace(i*self.pd.dt, (self.pd.T+ i)*self.pd.dt, self.pd.T+1)
+                y = all_ocp_feet_p_log[self.pd.rfFootId][i+1][:,p]
+                for j in range(len(y) - 1):
+                    plt.plot(t[j:j+2], y[j:j+2], color='royalblue', linewidth = 3, marker='o' ,alpha=max([1 - j/len(y), 0]))
+            #plt.plot(t_mpc, feet_p_log_mpc[18][:, p], linewidth=0.8, color = 'tomato', marker='o')
+            #plt.plot(t1, feet_p_log_m[18][:, p], linewidth=2, color = 'lightgreen')
+        plt.draw()
 
         plt.show()
 
diff --git a/python/quadruped_reactive_walking/tools/kinematics_utils.py b/python/quadruped_reactive_walking/tools/kinematics_utils.py
new file mode 100644
index 0000000000000000000000000000000000000000..5dfcf9073bd9820ff5ba41c94d6ea54d66d460c4
--- /dev/null
+++ b/python/quadruped_reactive_walking/tools/kinematics_utils.py
@@ -0,0 +1,29 @@
+import pinocchio as pin
+import numpy as np
+from ..WB_MPC.ProblemData import ProblemData
+
+def get_translation(pd:ProblemData, x, idx, ref_frame=pin.WORLD):
+    q = x[: pd.nq]
+    v = x[pd.nq :]
+    pin.forwardKinematics(pd.model, pd.rdata, q, v)
+    pin.updateFramePlacements(pd.model, pd.rdata)
+    frame_p = pd.rdata.oMf[idx].translation
+    frame_v = pin.getFrameVelocity(pd.model, pd.rdata, idx, ref_frame).linear
+    return frame_p, frame_v
+
+def get_translation_array(pd:ProblemData, x, idx, ref_frame=pin.WORLD, x0=None):
+    frame_p = []
+    frame_v = []
+    if isinstance(x0, np.ndarray):
+        xiter = np.concatenate([x0.reshape(1,-1), x])
+    else:
+        xiter = x
+
+    for xs in xiter:
+        q = xs[: pd.nq]
+        v = xs[pd.nq :]
+        pin.forwardKinematics(pd.model, pd.rdata, q, v)
+        pin.updateFramePlacements(pd.model, pd.rdata)
+        frame_p += [pd.rdata.oMf[idx].translation.copy()]
+        frame_v += [pin.getFrameVelocity(pd.model, pd.rdata, idx, ref_frame).linear.copy()]
+    return np.array(frame_p), np.array(frame_v)