diff --git a/python/iLQR_manipulator.py b/python/iLQR_manipulator.py
index e216452cc017ec53960efc4fbadfc71322528c9c..2aa963d47157c32745eb03efae5692997e361aa9 100644
--- a/python/iLQR_manipulator.py
+++ b/python/iLQR_manipulator.py
@@ -85,6 +85,8 @@ def f_reach(x, param):
 	return f,J
 
 ## Parameters
+# ===============================
+
 param = lambda: None # Lazy way to define an empty class in python
 param.dt = 1e-2 # Time step length
 param.nbData = 50 # Number of datapoints
diff --git a/python/iLQR_manipulator_dynamics.py b/python/iLQR_manipulator_dynamics.py
index a0db108edde5fa223635a85301bb8d0afcc5f998..471e2f3e018106fa36eb8a4e4c4b3d620303e5d3 100644
--- a/python/iLQR_manipulator_dynamics.py
+++ b/python/iLQR_manipulator_dynamics.py
@@ -21,7 +21,6 @@
 '''
 
 import numpy as np
-import numpy.matlib
 import matplotlib.pyplot as plt
 import matplotlib.patches as patches
 
@@ -36,46 +35,43 @@ def logmap(f,f0):
     return error
 
 # Forward kinematics for E-E
-def fkin(param,x):
-    x = x.T
-    A = np.tril(np.ones([param.nbVarX,param.nbVarX]))
-    f = np.vstack((param.linkLengths @ np.cos(A @ x), 
-                   param.linkLengths @ np.sin(A @ x), 
-                   np.mod(np.sum(x,0)+np.pi, 2*np.pi) - np.pi)) #x1,x2,o (orientation as single Euler angle for planar robot)
-    return f.T
+def fkin(x,param):
+	L = np.tril(np.ones([param.nbVarX, param.nbVarX]))
+	f = np.vstack([
+		param.l @ np.cos(L @ x.T),
+		param.l @ np.sin(L @ x.T),
+		np.mod(np.sum(x.T,0)+np.pi, 2*np.pi) - np.pi
+	]) # f1,f2,f3, where f3 is the orientation (single Euler angle for planar robot)
+	return f.T
 
 # Forward Kinematics for all joints
-def fkin0(param,x):
-    T = np.tril(np.ones([param.nbVarX,param.nbVarX]))
-    T2 = np.tril(np.matlib.repmat(param.linkLengths,len(x),1))
-    f = np.vstack(( 
-        T2 @ np.cos(T@x),
-        T2 @ np.sin(T@x)
-    )).T
-    f = np.vstack(( 
-        np.zeros(2),
-        f
-    ))
-    return f
+def fkin0(x,param):
+	L = np.tril(np.ones([param.nbVarX, param.nbVarX]))
+	f = np.vstack([
+		L @ np.diag(param.l) @ np.cos(L @ x),
+		L @ np.diag(param.l) @ np.sin(L @ x)
+	])
+	f = np.hstack([np.zeros([2,1]), f])
+	return f.T
 
 # Jacobian with analytical computation (for single time step)
-def jkin(param,x):
-    T = np.tril( np.ones((len(x),len(x))) )
+def Jkin(x,param):
+    L = np.tril( np.ones((len(x),len(x))) )
     J = np.vstack((
-        -np.sin(T@x).T @ np.diag(param.linkLengths) @ T,
-        np.cos(T@x).T @ np.diag(param.linkLengths) @ T,
+        -np.sin(L@x).T @ np.diag(param.l) @ L,
+        np.cos(L@x).T @ np.diag(param.l) @ L,
         np.ones(len(x))
     ))
     return J
 
 # Residual and Jacobian
-def f_reach(param,x):
-    f = logmap(fkin(param,x),param.mu)
-    J = np.zeros(( len(x) * param.nbVarF , len(x) * param.nbVarX ))
+def f_reach(x,param):
+    f = logmap(fkin(x,param),param.Mu)
+    J = np.zeros(( param.nbPoints  * param.nbVarF , param.nbPoints  * param.nbVarX ))
 
-    for t in range(x.shape[0]):
+    for t in range(param.nbPoints ):
         f[t,:2] = param.A[t].T @ f[t,:2] # Object oriented fk
-        Jtmp = jkin(param,x[t])
+        Jtmp = Jkin(x[t],param)
         Jtmp[:2] = param.A[t].T @ Jtmp[:2] # Object centered jacobian
 
         if param.useBoundingBox:
@@ -91,74 +87,69 @@ def f_reach(param,x):
 # Forward dynamic to compute
 def forward_dynamics(x, u, param):
     
-    g = 9.81 #Gravity norm
-    kv = 1 #Joints Damping
-    l = np.reshape( param.linkLengths, [1,param.nbVarX] )
+    l = np.reshape( param.l, [1,param.nbVarX] )
     m = np.reshape( param.linkMasses, [1,param.nbVarX] )
-    dt = param.dt
     
-    nbDOFs = l.shape[1]
-    nbData = int(u.shape[0]/nbDOFs + 1)
-    Tm = np.multiply(np.triu(np.ones([nbDOFs,nbDOFs])), np.repeat(m, nbDOFs,0)) 
-    T = np.tril(np.ones([nbDOFs, nbDOFs]))
-    Su = np.zeros([2 * nbDOFs * nbData, nbDOFs * (nbData - 1)])
+    Tm = np.multiply(np.triu(np.ones([param.nbVarX,param.nbVarX])), np.repeat(m, param.nbVarX,0)) 
+    T = np.tril(np.ones([param.nbVarX, param.nbVarX]))
+    Su = np.zeros([2 * param.nbVarX * param.nbData , param.nbVarX * (param.nbData  - 1)])
     
     #Precomputation of mask (in tensor form)
-    S1= np.zeros([nbDOFs, nbDOFs, nbDOFs])
-    J_index = np.ones([1, nbDOFs])
-    for j in range(nbDOFs):
+    S1= np.zeros([param.nbVarX, param.nbVarX, param.nbVarX])
+    J_index = np.ones([1, param.nbVarX])
+    for j in range(param.nbVarX):
         J_index[0,:j] = np.zeros([j])
-        S1[:,:,j] = np.repeat(J_index @ np.eye(nbDOFs), nbDOFs, 0) - np.transpose(np.repeat(J_index @ np.eye(nbDOFs), nbDOFs, 0))
+        S1[:,:,j] = np.repeat(J_index @ np.eye(param.nbVarX), param.nbVarX, 0) - np.transpose(np.repeat(J_index @ np.eye(param.nbVarX), param.nbVarX, 0))
      
     #Initialization of dM and dC tensors and A21 matrix
-    dM = np.zeros([nbDOFs, nbDOFs, nbDOFs])
-    dC = np.zeros([nbDOFs, nbDOFs, nbDOFs])
-    A21 = np.zeros([nbDOFs, nbDOFs])
+    dM = np.zeros([param.nbVarX, param.nbVarX, param.nbVarX])
+    dC = np.zeros([param.nbVarX, param.nbVarX, param.nbVarX])
+    A21 = np.zeros([param.nbVarX, param.nbVarX])
     
     
-    for t in range(nbData-1):        
+    for t in range(param.nbData -1):        
         
         # Computation in matrix form of G,M, and C
-        G =-np.reshape(np.sum(Tm,1), [nbDOFs,1]) * l.T * np.cos(T @ np.reshape(x[t,0:nbDOFs], [nbDOFs,1])) * g
+        G =-np.reshape(np.sum(Tm,1), [param.nbVarX,1]) * l.T * np.cos(T @ np.reshape(x[t,0:param.nbVarX], [param.nbVarX,1])) * param.g
         G = T.T @ G
-        M = (l.T * l) * np.cos(np.reshape(T @ x[t,:nbDOFs], [nbDOFs,1]) - T @ x[t,:nbDOFs]) * (Tm ** .5 @ ((Tm ** .5).T))
+        M = (l.T * l) * np.cos(np.reshape(T @ x[t,:param.nbVarX], [param.nbVarX,1]) - T @ x[t,:param.nbVarX]) * (Tm ** .5 @ ((Tm ** .5).T))
         M = T.T @ M @ T 
-        C = -(l.T * l) * np.sin(np.reshape(T @ x[t,:nbDOFs], [nbDOFs,1]) - T @ x[t,:nbDOFs]) * (Tm ** .5 @ ((Tm ** .5).T))
+        C = -(l.T * l) * np.sin(np.reshape(T @ x[t,:param.nbVarX], [param.nbVarX,1]) - T @ x[t,:param.nbVarX]) * (Tm ** .5 @ ((Tm ** .5).T))
         
         
         # Computation in tensor form of derivatives dG,dM, and dC
-        dG = np.diagflat(np.reshape(np.sum(Tm,1), [nbDOFs,1]) * l.T * np.sin(T @ np.reshape(x[t,0:nbDOFs], [nbDOFs,1])) * g) @ T
-        dM_tmp = (l.T * l) * np.sin(np.reshape(T @ x[t,:nbDOFs], [nbDOFs,1]) - T @ x[t,:nbDOFs]) * (Tm ** .5 @ ((Tm ** .5).T)) 
+        dG = np.diagflat(np.reshape(np.sum(Tm,1), [param.nbVarX,1]) * l.T * np.sin(T @ np.reshape(x[t,0:param.nbVarX], [param.nbVarX,1])) * param.g) @ T
+        dM_tmp = (l.T * l) * np.sin(np.reshape(T @ x[t,:param.nbVarX], [param.nbVarX,1]) - T @ x[t,:param.nbVarX]) * (Tm ** .5 @ ((Tm ** .5).T)) 
         
         for j in range(dM.shape[2]):
             dM[:,:,j] = T.T @ (dM_tmp * S1[:,:,j]) @ T
         
-        dC_tmp = (l.T * l) * np.cos(np.reshape( T @ x[t,:nbDOFs], [nbDOFs,1]) - T @ x[t,:nbDOFs]) * (Tm ** .5 @ ((Tm ** .5).T)) 
+        dC_tmp = (l.T * l) * np.cos(np.reshape( T @ x[t,:param.nbVarX], [param.nbVarX,1]) - T @ x[t,:param.nbVarX]) * (Tm ** .5 @ ((Tm ** .5).T)) 
         for j in range(dC.shape[2]):
             dC[:,:,j] = dC_tmp * S1[:,:,j]   
             
         # update pose 
-        tau = np.reshape(u[(t) * nbDOFs:(t + 1) * nbDOFs], [nbDOFs, 1])
+        tau = np.reshape(u[(t) * param.nbVarX:(t + 1) * param.nbVarX], [param.nbVarX, 1])
         inv_M = np.linalg.inv(M)
-        ddq =inv_M @ (tau + G + T.T @ C @ (T @ np.reshape(x[t,nbDOFs:], [nbDOFs,1])) ** 2) - T @ np.reshape(x[t,nbDOFs:], [nbDOFs,1]) * kv
+        ddq =inv_M @ (tau + G + T.T @ C @ (T @ np.reshape(x[t,param.nbVarX:], [param.nbVarX,1])) ** 2) - T @ np.reshape(x[t,param.nbVarX:], [param.nbVarX,1]) * param.kv
         
         # compute local linear systems
-        x[t+1,:] = x[t,:] + np.hstack([x[t,nbDOFs:], np.reshape(ddq, [nbDOFs,])]) * dt
-        A11 = np.eye(nbDOFs)
-        A12 = A11 * dt
-        A22 = np.eye(nbDOFs) + (2 * inv_M @ T.T @ C @ np.diagflat(T @ x[t,nbDOFs:]) @ T - T * kv) * dt
-        for j in range(nbDOFs):
-            A21[:,j] = (-inv_M @ dM[:,:,j] @ inv_M @ (tau + G + T.T @ C @ (T @ np.reshape(x[t,nbDOFs:], [nbDOFs,1])) ** 2) 
-                        + np.reshape(inv_M @ T.T @ dG[:,j], [nbDOFs,1]) + inv_M @ T .T @ dC[:,:,j] @ (T @ np.reshape(x[t,nbDOFs:], [nbDOFs,1])) ** 2).flatten()
-        A = np.vstack((np.hstack((A11, A12)), np.hstack((A21 * dt, A22))))
-        B = np.vstack((np.zeros([nbDOFs, nbDOFs]), inv_M * dt))
+        x[t+1,:] = x[t,:] + np.hstack([x[t,param.nbVarX:], np.reshape(ddq, [param.nbVarX,])]) * param.dt
+        A11 = np.eye(param.nbVarX)
+        A12 = A11 * param.dt
+        A22 = np.eye(param.nbVarX) + (2 * inv_M @ T.T @ C @ np.diagflat(T @ x[t,param.nbVarX:]) @ T - T * param.kv) * param.dt
+        for j in range(param.nbVarX):
+            A21[:,j] = (-inv_M @ dM[:,:,j] @ inv_M @ (tau + G + T.T @ C @ (T @ np.reshape(x[t,param.nbVarX:], [param.nbVarX,1])) ** 2) 
+                        + np.reshape(inv_M @ T.T @ dG[:,j], [param.nbVarX,1]) + inv_M @ T .T @ dC[:,:,j] @ (T @ np.reshape(x[t,param.nbVarX:], [param.nbVarX,1])) ** 2).flatten()
+        A = np.vstack((np.hstack((A11, A12)), np.hstack((A21 * param.dt, A22))))
+        B = np.vstack((np.zeros([param.nbVarX, param.nbVarX]), inv_M * param.dt))
         
         # compute transformation matrix
-        Su[2 * nbDOFs * (t + 1):2 * nbDOFs * (t + 2),:] = A @ Su[2 * nbDOFs * t:2 * nbDOFs * (t + 1),:]
-        Su[2 * nbDOFs * (t + 1):2 * nbDOFs * (t + 2), nbDOFs * t:nbDOFs * (t + 1)] =B
+        Su[2 * param.nbVarX * (t + 1):2 * param.nbVarX * (t + 2),:] = A @ Su[2 * param.nbVarX * t:2 * param.nbVarX * (t + 1),:]
+        Su[2 * param.nbVarX * (t + 1):2 * param.nbVarX * (t + 2), param.nbVarX * t:param.nbVarX * (t + 1)] =B
     return x, Su
 
-# General param parameters
+# Parameters
 # ===============================
 
 param = lambda: None # Lazy way to define an empty class in python
@@ -169,66 +160,54 @@ param.nbPoints = 2 # Number of viapoints
 param.nbVarX = 3 # State space dimension (x1,x2,x3)
 param.nbVarU = 3 # Control space dimension (dx1,dx2,dx3)
 param.nbVarF = 3 # Objective function dimension (f1,f2,f3, with f3 as orientation)
-param.linkLengths = [2,2,1] # Robot links lengths
+param.l = [2,2,1] # Robot links lengths
 param.linkMasses = [1,1,1]
-param.sizeObj = [.2,.3] # Size of objects
+param.g = 9.81 # Gravity norm
+param.kv = 1 # Joint damping
+param.sz = [.2,.3] # Size of objects
 param.r = 1e-6 # Control weight term
-param.mu = np.asarray([[2,1,-np.pi/6], [3,2,-np.pi/3]]).T # Viapoints 
+param.Mu = np.asarray([[2,1,-np.pi/3], [3,2,-np.pi/3]]) # Viapoints 
 param.useBoundingBox = False
+param.A = np.zeros( (param.nbPoints,2,2) ) # Object orientation matrices
 
-# Task parameters
+# Main program
 # ===============================
 
-# Targets
-param.mu = np.asarray([
-    [2,1,-np.pi/3],                # x , y , orientation
-    [3,2,-np.pi/3]
-])
-
 # Transformation matrices
-param.A = np.zeros( (param.nbPoints,2,2) )
 for i in range(param.nbPoints):
-    orn_t = param.mu[i,-1]
+    orn_t = param.Mu[i,-1]
     param.A[i,:,:] = np.asarray([
         [np.cos(orn_t) , -np.sin(orn_t)],
         [np.sin(orn_t) , np.cos(orn_t)]
     ])
 
-# Regularization matrix
-R = np.identity( (param.nbData-1) * param.nbVarU ) * param.r
-
 # Precision matrix
 Q = np.identity( param.nbVarF  * param.nbPoints)*1e5
 
-# System parameters
-# ===============================
+# Regularization matrix
+R = np.identity( (param.nbData-1) * param.nbVarU ) * param.r
 
 # Time occurence of viapoints
 tl = np.linspace(0,param.nbData,param.nbPoints+1)
 tl = np.rint(tl[1:]).astype(np.int64)-1
 idx = np.array([ i + np.arange(0,param.nbVarX,1) for i in (tl* 2* param.nbVarX)]) 
 
+# iLQR
+# ===============================
+
 u = np.zeros( param.nbVarU * (param.nbData-1) ) # Initial control command
 x0 = np.array( [3 * np.pi/4 , -np.pi/2 , - np.pi/4] ) # Initial position (in joint space)
-v0 = np.array([0,0,0])#initial velocity (in joint space)
+v0 = np.array([0,0,0]) #initial velocity (in joint space)
 x = np.zeros([param.nbData, 2*param.nbVarX])
 x[0,:param.nbVarX] = x0
 x[0,param.nbVarX:] = v0
-# Transfer matrices (for linear system as single integrator)
-Su0 = np.vstack([np.zeros((param.nbVarX, param.nbVarX*(param.nbData-1))), 
-      np.tril(np.kron(np.ones((param.nbData-1, param.nbData-1)), np.eye(param.nbVarX)*param.dt))]) 
-Sx0 = np.kron( np.ones(param.nbData) , np.identity(param.nbVarX) ).T
- # We remove the lines that are out of interest
-
-# Solving iLQR
-# ===============================
 
 for i in range( param.nbIter ):
     # system evolution and Transfer matrix (computed from forward dynamics)
     x, Su0 = forward_dynamics(x, u, param)
     Su = Su0[idx.flatten()]
 
-    f, J = f_reach(param,x[tl,:param.nbVarX])
+    f, J = f_reach(x[tl,:param.nbVarX],param)
     du = np.linalg.inv(Su.T @ J.T @ Q @ J @ Su + R) @ (-Su.T @ J.T @ Q @ f.flatten() - u * param.r)
 
     # Perform line search
@@ -238,7 +217,7 @@ for i in range( param.nbIter ):
     while True:
         utmp = u + du * alpha
         xtmp, _ = forward_dynamics(x, utmp, param)
-        ftmp, _ = f_reach(param,xtmp[tl,:param.nbVarX])
+        ftmp, _ = f_reach(xtmp[tl,:param.nbVarX],param)
         cost = ftmp.flatten() @ Q @ ftmp.flatten() + np.linalg.norm(utmp) * param.r
         
         if cost < cost0 or alpha < 1e-3:
@@ -258,9 +237,9 @@ plt.axis("off")
 plt.gca().set_aspect('equal', adjustable='box')
 
 # Get points of interest
-f = fkin(param,x[:,:param.nbVarX])
-f00 = fkin0(param,x[0,:param.nbVarX])
-fT0 = fkin0(param,x[-1,:param.nbVarX])
+f = fkin(x[:,:param.nbVarX],param)
+f00 = fkin0(x[0,:param.nbVarX],param)
+fT0 = fkin0(x[-1,:param.nbVarX],param)
 
 plt.plot( f00[:,0] , f00[:,1],c='black',linewidth=5,alpha=.2)
 plt.plot( fT0[:,0] , fT0[:,1],c='black',linewidth=5,alpha=.6)
@@ -273,12 +252,12 @@ color_map = ["deepskyblue","darkorange"]
 for i in range(param.nbPoints):
     
     if param.useBoundingBox:
-        rect_origin = param.mu[i,:2] - param.A[i]@np.array(param.sizeObj)
-        rect_orn = param.mu[i,-1]
+        rect_origin = param.Mu[i,:2] - param.A[i]@np.array(param.sizeObj)
+        rect_orn = param.Mu[i,-1]
 
         rect = patches.Rectangle(rect_origin,param.sizeObj[0]*2,param.sizeObj[1]*2,np.degrees(rect_orn),color=color_map[i])
         ax.add_patch(rect)
     else:
-        plt.scatter(param.mu[i,0],param.mu[i,1],s=100,marker="X",c=color_map[i])
+        plt.scatter(param.Mu[i,0],param.Mu[i,1],s=100,marker="X",c=color_map[i])
 
 plt.show()