diff --git a/cpp/src/LQT.cpp b/cpp/src/LQT.cpp
index 52825301cf9551727dc88f756f76f375cf05fb17..fd261234779d879f25e4ac060ab7ad278b7771c0 100644
--- a/cpp/src/LQT.cpp
+++ b/cpp/src/LQT.cpp
@@ -1,11 +1,30 @@
-// LQT.cpp
-// Sylvain Calinon, 2021
+/*
+    LQT applied to a 2D manipulator system reaching a target.
+
+    Copyright (c) 2021 Idiap Research Institute, http://www.idiap.ch/
+    Written by Sylvain Calinon <https://calinon.ch>
+
+    This file is part of RCFS.
+
+    RCFS is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License version 3 as
+    published by the Free Software Foundation.
+
+    RCFS is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with RCFS. If not, see <http://www.gnu.org/licenses/>.
+*/
 
-#include <iostream>
 #include <Eigen/Dense>
-#include <eigen3/unsupported/Eigen/KroneckerProduct>
 #include <GL/glut.h>
+#include <eigen3/unsupported/Eigen/KroneckerProduct>
+#include <iostream>
 #include <math.h>
+#include <vector>
 
 using namespace Eigen;
 
@@ -23,7 +42,7 @@ struct Param {
     dt = 1e-2;
     linkLengths = VectorXd(4);
     linkLengths << 1.0, 1.0, 0.5, 0.5;
-    x_d << -2, 1, 4*M_PI/4.;
+    x_d << -2, 1, 4 * M_PI / 4.;
     Q_t = 0.0;
     Q_T = 100.0;
     R_t = 1e-2;
@@ -33,8 +52,7 @@ struct Param {
 
 // Kinematics functions
 // ===============================
-MatrixXd fkin(VectorXd q)
-{
+MatrixXd fkin(VectorXd q) {
   Param param;
   long int nbDoF = param.linkLengths.size();
   MatrixXd G = MatrixXd::Ones(nbDoF, nbDoF).triangularView<UnitLower>();
@@ -42,61 +60,70 @@ MatrixXd fkin(VectorXd q)
   x.row(0) = G * param.linkLengths.asDiagonal() * cos((G * q).array()).matrix();
   x.row(1) = G * param.linkLengths.asDiagonal() * sin((G * q).array()).matrix();
   x.row(2) = G * q;
-  
+
   return x;
 }
 
-MatrixXd jacobian(VectorXd q)
-{
+MatrixXd jacobian(VectorXd q) {
   Param param;
   long int nbDoF = param.linkLengths.size();
   MatrixXd G = MatrixXd::Ones(nbDoF, nbDoF).triangularView<UnitLower>();
   MatrixXd J = MatrixXd::Zero(3, nbDoF);
-  J.row(0) = - G.transpose() * param.linkLengths.asDiagonal() * sin((G * q).array()).matrix();
-  J.row(1) =   G.transpose() * param.linkLengths.asDiagonal() * cos((G * q).array()).matrix();
+  J.row(0) = -G.transpose() * param.linkLengths.asDiagonal() *
+             sin((G * q).array()).matrix();
+  J.row(1) = G.transpose() * param.linkLengths.asDiagonal() *
+             cos((G * q).array()).matrix();
   J.row(2) = VectorXd::Ones(nbDoF);
-  
+
   return J;
 }
 
 // Iterative Inverse Kinematics
 // ===============================
-std::vector<MatrixXd> IK(VectorXd& q)
-{
+std::vector<MatrixXd> IK(VectorXd &q) {
   Param param;
   std::vector<MatrixXd> x;
-  
-  for(unsigned int i = 0; i < param.nbSteps; i++) {
+
+  for (unsigned int i = 0; i < param.nbSteps; i++) {
     x.push_back(fkin(q));
     auto J = jacobian(q);
-    auto dx_d = - (x.back().col(param.linkLengths.size()-1) - param.x_d);
-  	VectorXd dq_d = J.completeOrthogonalDecomposition().solve(dx_d);
-  	q = q + param.dt * dq_d;
+    auto dx_d = -(x.back().col(param.linkLengths.size() - 1) - param.x_d);
+    VectorXd dq_d = J.completeOrthogonalDecomposition().solve(dx_d);
+    q = q + param.dt * dq_d;
   }
-  
+
   return x;
 }
 
 // Trajectory Optimization
 // ===============================
-std::vector<VectorXd> LQT(const VectorXd& q_init, const VectorXd& q_goal, const double T=1.0)
-{
+std::vector<VectorXd> LQT(const VectorXd &q_init, const VectorXd &q_goal,
+                          const double T = 1.0) {
   Param param;
   long int nbDoF = param.linkLengths.size();
   unsigned int nbSteps = (unsigned int)(T / param.dt);
-  MatrixXd Sq = kroneckerProduct(MatrixXd::Ones(nbSteps, 1), MatrixXd::Identity(nbDoF, nbDoF));
-  MatrixXd Su = MatrixXd::Zero(nbDoF*nbSteps, (nbSteps-1)*nbDoF);
-  Su.bottomRows((nbSteps-1)*nbDoF) = 
-    kroneckerProduct(MatrixXd::Ones(nbSteps-1, nbSteps-1), param.dt * MatrixXd::Identity(nbDoF, nbDoF)).eval().triangularView<Eigen::Lower>();
-  VectorXd q_d = VectorXd::Zero(nbDoF*nbSteps);
+  MatrixXd Sq = kroneckerProduct(MatrixXd::Ones(nbSteps, 1),
+                                 MatrixXd::Identity(nbDoF, nbDoF));
+  MatrixXd Su = MatrixXd::Zero(nbDoF * nbSteps, (nbSteps - 1) * nbDoF);
+  Su.bottomRows((nbSteps - 1) * nbDoF) =
+      kroneckerProduct(MatrixXd::Ones(nbSteps - 1, nbSteps - 1),
+                       param.dt * MatrixXd::Identity(nbDoF, nbDoF))
+          .eval()
+          .triangularView<Eigen::Lower>();
+  VectorXd q_d = VectorXd::Zero(nbDoF * nbSteps);
   q_d.tail(nbDoF) = q_goal;
-  MatrixXd Q = param.Q_t * MatrixXd::Identity(nbDoF*nbSteps, nbDoF*nbSteps);
-  Q.bottomRightCorner(nbDoF, nbDoF) = param.Q_T * MatrixXd::Identity(nbDoF, nbDoF);
-  MatrixXd R = param.R_t * MatrixXd::Identity(nbDoF*(nbSteps-1), nbDoF*(nbSteps-1));
-  VectorXd q_opt = Sq * q_init + Su * (Su.transpose() * Q * Su + R).ldlt().solve(Su.transpose() * Q * (q_d - Sq * q_init));
+  MatrixXd Q = param.Q_t * MatrixXd::Identity(nbDoF * nbSteps, nbDoF * nbSteps);
+  Q.bottomRightCorner(nbDoF, nbDoF) =
+      param.Q_T * MatrixXd::Identity(nbDoF, nbDoF);
+  MatrixXd R = param.R_t *
+               MatrixXd::Identity(nbDoF * (nbSteps - 1), nbDoF * (nbSteps - 1));
+  VectorXd q_opt =
+      Sq * q_init + Su * (Su.transpose() * Q * Su + R)
+                             .ldlt()
+                             .solve(Su.transpose() * Q * (q_d - Sq * q_init));
   std::vector<VectorXd> q(nbSteps);
-  for(unsigned int i = 0; i < nbSteps; i++) {
-    q[i] = q_opt.segment(i*nbDoF, nbDoF);
+  for (unsigned int i = 0; i < nbSteps; i++) {
+    q[i] = q_opt.segment(i * nbDoF, nbDoF);
   }
   return q;
 }
@@ -104,69 +131,70 @@ std::vector<VectorXd> LQT(const VectorXd& q_init, const VectorXd& q_goal, const
 // Plotting
 // ===============================
 
-void plot_robot(const MatrixXd& x, const double c=0.0)
-{
+void plot_robot(const MatrixXd &x, const double c = 0.0) {
   Param param;
   glColor3d(c, c, c);
   glLineWidth(8.0);
-	glBegin(GL_LINE_STRIP);
-	glVertex2d(0, 0);
-	for(unsigned int j = 0; j < param.linkLengths.size(); j++){
-		glVertex2d(x(0,j), x(1,j));
-	}
-	glEnd();
+  glBegin(GL_LINE_STRIP);
+  glVertex2d(0, 0);
+  for (unsigned int j = 0; j < param.linkLengths.size(); j++) {
+    glVertex2d(x(0, j), x(1, j));
+  }
+  glEnd();
 }
 
-void render(){
+void render() {
   Param param;
-  VectorXd q_init = VectorXd::Ones(param.linkLengths.size()) * M_PI / (double)param.linkLengths.size();
+  VectorXd q_init = VectorXd::Ones(param.linkLengths.size()) * M_PI /
+                    (double)param.linkLengths.size();
   VectorXd q_goal = q_init;
   auto x_IK = IK(q_goal);
-  
+
   auto q = LQT(q_init, q_goal, param.T);
-  
+
   std::vector<MatrixXd> x;
-  for(auto& q_ : q) {
+  for (auto &q_ : q) {
     x.push_back(fkin(q_));
   }
 
-	glLoadIdentity();
-	double d = (double)param.linkLengths.size() * .7;
-	glOrtho(-d, d, -.1, d-.1, -1.0, 1.0);
-	glClearColor(1.0, 1.0, 1.0, 1.0);
-	glClear(GL_COLOR_BUFFER_BIT);
+  glLoadIdentity();
+  double d = (double)param.linkLengths.size() * .7;
+  glOrtho(-d, d, -.1, d - .1, -1.0, 1.0);
+  glClearColor(1.0, 1.0, 1.0, 1.0);
+  glClear(GL_COLOR_BUFFER_BIT);
 
   // Plot start and end configuration
   plot_robot(x.front(), 0.8);
   plot_robot(x.back(), 0.4);
-	
-	// Plot end-effector trajectory
-	double c = 0.0;
+
+  // Plot end-effector trajectory
+  double c = 0.0;
   glColor3d(c, c, c);
   glLineWidth(4.0);
-	glBegin(GL_LINE_STRIP);
-	for(auto& x_ : x) {
-	  glVertex2d(x_(0,param.linkLengths.size()-1), x_(1,param.linkLengths.size()-1));
-	}
-	glEnd();
-	
-	// Plot target
-	glColor3d(1.0, 0, 0);
-	glPointSize(12.0);
-	glBegin(GL_POINTS);
-	glVertex2d(param.x_d(0), param.x_d(1));
-	glEnd();
-
-	//Render
-	glutSwapBuffers();
+  glBegin(GL_LINE_STRIP);
+  for (auto &x_ : x) {
+    glVertex2d(x_(0, param.linkLengths.size() - 1),
+               x_(1, param.linkLengths.size() - 1));
+  }
+  glEnd();
+
+  // Plot target
+  glColor3d(1.0, 0, 0);
+  glPointSize(12.0);
+  glBegin(GL_POINTS);
+  glVertex2d(param.x_d(0), param.x_d(1));
+  glEnd();
+
+  // Render
+  glutSwapBuffers();
 }
 
-int main(int argc, char** argv){
-	glutInit(&argc, argv);
-	glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
-	glutInitWindowPosition(20,20);
-	glutInitWindowSize(1200,600);
-	glutCreateWindow("IK");
-	glutDisplayFunc(render);
-	glutMainLoop();
+int main(int argc, char **argv) {
+  glutInit(&argc, argv);
+  glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
+  glutInitWindowPosition(20, 20);
+  glutInitWindowSize(1200, 600);
+  glutCreateWindow("IK");
+  glutDisplayFunc(render);
+  glutMainLoop();
 }
diff --git a/data/convert_mat_to_numpy.py b/data/convert_mat_to_numpy.py
deleted file mode 100644
index 3208403291a6467bfe9cc4888c5b81bd170626d9..0000000000000000000000000000000000000000
--- a/data/convert_mat_to_numpy.py
+++ /dev/null
@@ -1,28 +0,0 @@
-from pathlib import Path
-import numpy as np
-import matplotlib.pyplot as plt
-import scipy.io
-import os
-
-FILE_PATH = os.path.dirname(os.path.realpath(__file__))
-DATASET_LETTERS_FOLDER = "2Dletters/"
-
-dataset_folder = Path(FILE_PATH,DATASET_LETTERS_FOLDER)
-file_list = [str(p) for p in dataset_folder.rglob('*') if p.is_file() and p.match('*.mat')]
-
-for file_name in file_list:
-    junk_array = scipy.io.loadmat(file_name)["demos"].flatten()
-    
-    letter_demos = []
-    
-    for demo in junk_array:
-        pos = demo[0]['pos'].flatten()[0].T
-        vel = demo[0]['vel'].flatten()[0].T
-        acc = demo[0]['acc'].flatten()[0].T
-        
-        demo_concatenated = np.hstack(( pos , vel , acc ))
-        letter_demos += [demo_concatenated]
-        
-    letter_demos = np.asarray(letter_demos)
-    file_name_npy = Path( Path(file_name).parent , Path(file_name).stem + ".npy") 
-    np.save(file_name_npy,letter_demos)
\ No newline at end of file
diff --git a/matlab/iLQR_manipulator_CoM.m b/matlab/iLQR_manipulator_CoM.m
index 31fa7701e7883ff32e119fcf7605cebf24ca0b2e..ce657f36ed714d8394baef8ea4f89fcb2bc363c3 100644
--- a/matlab/iLQR_manipulator_CoM.m
+++ b/matlab/iLQR_manipulator_CoM.m
@@ -162,7 +162,7 @@ function [f, J] = f_reach_CoM(x, param)
 		         cos(L * x(:,t))' * L * diag(param.l' * L)] / param.nbVarX;
 				 
 		%Bounding boxes (optional)
-		for i=1:1
+		for i=1:1 %Only x direction
 			if abs(f(i,t)) < param.szCoM
 				f(i,t) = 0;
 				Jtmp(i,:) = 0;
diff --git a/python/IK.py b/python/IK.py
index b96f453f44af4566852f31290b77edd6364bcfd5..88224b69f13dee15f151056a7a5da2fae5243582 100644
--- a/python/IK.py
+++ b/python/IK.py
@@ -22,19 +22,48 @@
 import numpy as np
 import matplotlib.pyplot as fig
 
-T = 50 #Number of datapoints
-D = 3 #State space dimension (x1,x2,x3)
-l = np.array([2, 2, 1]); #Robot links lengths
+# Forward kinematics for all joints (in robot coordinate system)
+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
+
+# Jacobian with analytical computation (for single time step)
+def Jkin(x, param):
+	L = np.tril(np.ones([param.nbVarX, param.nbVarX]))
+	J = np.vstack([
+		-np.sin(L @ x).T @ np.diag(param.l) @ L,
+		 np.cos(L @ x).T @ np.diag(param.l) @ L
+	])
+	return 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
+param.nbVarX = 3 # State space dimension (x1,x2,x3)
+param.nbVarF = 2 # Objective function dimension (position of the end-effector
+param.l = [2,2,1] # Robot links lengths
+
 fh = np.array([-2, 1]) #Desired target for the end-effector
-x = np.ones(D) * np.pi / D #Initial robot pose
-L = np.tril(np.ones([D,D])) #Transformation matrix
+x = np.ones(param.nbVarX) * np.pi / param.nbVarX #Initial robot pose
+
+
+## Inverse kinematics (IK)
+# ===============================
 
 fig.scatter(fh[0], fh[1], color='r', marker='.', s=10**2) #Plot target
-for t in range(T):
-	f = np.array([L @ np.diag(l) @ np.cos(L @ x), L @ np.diag(l) @ np.sin(L @ x)]) #Forward kinematics (for all articulations, including end-effector)
-	J = np.array([-np.sin(L @ x).T @ np.diag(l) @ L, np.cos(L @ x).T @ np.diag(l) @ L]) #Jacobian (for end-effector)
-	x += np.linalg.pinv(J) @ (fh - f[:,-1]) * .1 #Update state 
-	f = np.concatenate((np.zeros([2,1]), f), axis=1) #Add robot base (for plotting)
+for t in range(param.nbData):
+	f = fkin0(x, param) #Forward kinematics (for all articulations, including end-effector)
+	J = Jkin(x, param) #Jacobian (for end-effector)
+	x += np.linalg.pinv(J) @ (fh - f[:,-1]) * 10 * param.dt #Update state 
 	fig.plot(f[0,:], f[1,:], color='k', linewidth=1) #Plot robot
 
 fig.axis('off')
diff --git a/python/IK_num.py b/python/IK_num.py
index 1563d58a6d223cce7c684570f17c10a1a493721a..b2b15015848b3952ef8ca29681877b6c85450ac9 100644
--- a/python/IK_num.py
+++ b/python/IK_num.py
@@ -2,7 +2,7 @@
 	Inverse kinematics with numerical computation for a planar manipulator
 
     Copyright (c) 2021 Idiap Research Institute, http://www.idiap.ch/
-    Written by Jérémy Maceiras <jeremy.maceiras@idiap.ch>,Sylvain Calinon <https://calinon.ch>
+    Written by Jérémy Maceiras <jeremy.maceiras@idiap.ch>, Sylvain Calinon <https://calinon.ch>
 
     This file is part of RCFS.
 
@@ -24,27 +24,26 @@ import matplotlib.pyplot as fig
 import copy
 
 # Forward kinematics (for end-effector)
-def fkin(x,l):
-    L = np.tril(np.ones([len(x),len(x)])) #Transformation matrix
+def fkin(x, l):
+    L = np.tril(np.ones([len(x),len(x)])) # Transformation matrix
     f = np.array([l.T  @ np.cos(L @ x),l.T @ np.sin(L@x)])
     return f
 
 # Forward kinematics (for all articulation)
-def fkin0(x,l):
-    L = np.tril(np.ones([len(x),len(x)])) #Transformation matrix
-    f = np.array([L @ np.diag(l) @ np.cos(L @ x), L @ np.diag(l) @ np.sin(L @ x)]) #Forward kinematics (for all articulations, including end-effector)
-    
+def fkin0(x, l):
+    L = np.tril(np.ones([len(x),len(x)])) # Transformation matrix
+    f = np.array([L @ np.diag(l) @ np.cos(L @ x), L @ np.diag(l) @ np.sin(L @ x)]) # Forward kinematics (for all articulations, including end-effector)
     return f
 
 # Jacobian with numerical computation
-def jkin(x,l):
+def Jkin(x, l):
     eps = 1e-6
     D = len(x)
 
     # Matrix computation
-    X = np.tile(x.reshape((-1,1)),[1,D])
-    F1 = fkin(X,l)
-    F2 = fkin(X+np.identity(D)*eps,l)
+    X = np.tile(x.reshape((-1,1)), [1,D])
+    F1 = fkin(X, l)
+    F2 = fkin(X+np.identity(D)*eps, l)
     J = (F2-F1) / eps
 
     # # For loop computation
@@ -67,8 +66,8 @@ x = np.ones(D) * np.pi / D #Initial robot pose
 fig.scatter(fh[0], fh[1], color='r', marker='.', s=10**2) #Plot target
 for t in range(T):
 	
-    J = jkin(x,l)
-    f = fkin0(x,l)
+    J = Jkin(x, l)
+    f = fkin0(x, l)
 
     x += np.linalg.pinv(J) @ (fh - f[:,-1]) * .1 #Update state 
     f = np.concatenate((np.zeros([2,1]), f), axis=1) #Add robot base (for plotting)
diff --git a/python/iLQR_manipulator.py b/python/iLQR_manipulator.py
index 2aa963d47157c32745eb03efae5692997e361aa9..1b10ac3f182a0b6685f55b29489a444a0b0f71ee 100644
--- a/python/iLQR_manipulator.py
+++ b/python/iLQR_manipulator.py
@@ -82,7 +82,7 @@ def f_reach(x, param):
 					f[i,t] -= np.sign(f[i,t]) * param.sz[i]
 		
 		J[t*param.nbVarF:(t+1)*param.nbVarF, t*param.nbVarX:(t+1)*param.nbVarX] = Jtmp
-	return f,J
+	return f, J
 
 ## Parameters
 # ===============================
@@ -98,8 +98,8 @@ param.nbVarF = 3 # Objective function dimension (f1,f2,f3, with f3 as orientatio
 param.l = [2,2,1] # Robot links lengths
 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.A = np.zeros([2,2,param.nbPoints]) # Object orientation matrices
+param.Mu = np.asarray([[2, 1, -np.pi/6], [3, 2, -np.pi/3]]).T # Viapoints 
+param.A = np.zeros([2, 2,param.nbPoints]) # Object orientation matrices
 param.useBoundingBox = True # Consider bounding boxes for reaching cost
 
 
@@ -143,7 +143,7 @@ x0 = np.array([3*np.pi/4, -np.pi/2, -np.pi/4]) # Initial state
 for i in range(param.nbIter):
 	x = Su0 @ u + Sx0 @ x0 # System evolution
 	x = x.reshape([param.nbVarX, param.nbData], order='F')
-	f,J = f_reach(x[:,tl], param) # Residuals and Jacobians
+	f, J = f_reach(x[:,tl], param) # Residuals and Jacobians
 	du = np.linalg.inv(Su.T @ J.T @ Q @ J @ Su + R) @ (-Su.T @ J.T @ Q @ f.flatten('F') - u * param.r) # Gauss-Newton update
 	# Estimate step size with backtracking line search method
 	alpha = 1
diff --git a/python/iLQR_manipulator_CP.py b/python/iLQR_manipulator_CP.py
index f92a7dd3c1ae47d1989b608ce8111d705e68d100..bbd43d3c9a630ae6e547fd1157d9feb86686af89 100644
--- a/python/iLQR_manipulator_CP.py
+++ b/python/iLQR_manipulator_CP.py
@@ -166,7 +166,7 @@ Q = np.identity( param.nbVarF  * param.nbPoints)
 # System parameters
 # ===============================
 
-# Time occurence of viapoints
+# Time occurrence 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* param.nbVarX)]) 
@@ -223,7 +223,7 @@ for i in range( param.nbIter ):
 	if np.linalg.norm( alpha * du ) < 1e-2:
 		break
 
-# Ploting
+# Plotting
 # ===============================
 
 plt.figure()
@@ -235,7 +235,7 @@ f = fkin(param,x)
 f00 = fkin0(param,x[0])
 f10 = fkin0(param,x[tl[0]])
 fT0 = fkin0(param,x[-1])
-u = u .reshape((-1,param.nbVarU))
+u = u.reshape((-1,param.nbVarU))
 
 plt.plot( f00[:,0] , f00[:,1],c='black',linewidth=5,alpha=.2)
 plt.plot( f10[:,0] , f10[:,1],c='black',linewidth=5,alpha=.4)
diff --git a/python/iLQR_manipulator_CoM.py b/python/iLQR_manipulator_CoM.py
index 6f74266847d4381d6aab25d8b64af172a8741664..4ab27da97e8c5b44ed8b50d8dfa74ae5a794709d 100644
--- a/python/iLQR_manipulator_CoM.py
+++ b/python/iLQR_manipulator_CoM.py
@@ -28,72 +28,66 @@ import matplotlib.patches as patches
 # Helper functions
 # ===============================
 
-# Forward kinematics (in robot coordinate system)
-def fkin(param,x):
-    x = x.T
-    A = np.tril(np.ones([param.nbVarX, param.nbVarX]))
-    f = np.vstack((param.l @ np.cos(A @ x),
-                   param.l @ np.sin(A @ x)))
-    return f
 
-# 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.l, 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
+# Forward kinematics for end-effector (in robot coordinate system)
+def fkin(x, param):
+	L = np.tril(np.ones([param.nbVarX, param.nbVarX]))
+	f = np.vstack([
+		param.l @ np.cos(L @ x),
+		param.l @ np.sin(L @ x)
+	]) 
+	return f
+
+# Forward kinematics for all joints (in robot coordinate system)
+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
 
 # Jacobian with analytical computation (for single time step)
-def jkin(param,x):
-    T = np.tril(np.ones((len(x), len(x))))
-    J = np.vstack((
-        -np.sin(T @ x).T @ np.diag(param.l) @ T,
-        np.cos(T @ x).T @ np.diag(param.l) @ T
-    ))
-    return J
-
-# Residual and Jacobian 
-def f_reach(param,x):
-    f = fkin(param,x).T - param.Mu
-    J = np.zeros((len(x) * param.nbVarF, len(x) * param.nbVarX))
-
-    for t in range(x.shape[0]):
-        Jtmp = jkin(param,x[t])
-        J[t * param.nbVarF:(t + 1) * param.nbVarF, t * param.nbVarX:(t + 1) * param.nbVarX] = Jtmp
-    return f.T, J
+def Jkin(x, param):
+	L = np.tril(np.ones([param.nbVarX, param.nbVarX]))
+	J = np.vstack([
+		-np.sin(L @ x).T @ np.diag(param.l) @ L,
+		 np.cos(L @ x).T @ np.diag(param.l) @ L
+	])
+	return J
+
+# Residual and Jacobian for a viapoints reaching task (in object coordinate system)
+def f_reach(x, param):
+	f = fkin(x, param) - param.Mu.reshape((-1,1))
+	J = np.zeros([param.nbPoints * param.nbVarF, param.nbPoints * param.nbVarX])
+	for t in range(param.nbPoints):
+		J[t*param.nbVarF:(t+1)*param.nbVarF, t*param.nbVarX:(t+1)*param.nbVarX] = Jkin(x[:,t], param)
+	return f, J
 
 # Forward kinematics for center of mass (in robot coordinate system, with mass located at the joints)
-def fkin_CoM(param,x):
-    x = x.T
-    A = np.tril(np.ones([param.nbVarX, param.nbVarX]))
-    f = np.vstack((param.l @ A @ np.cos(A @ x),
-                   param.l @ A @ np.sin(A @ x))) / param.nbVarX
+def fkin_CoM(x, param):
+    L = np.tril(np.ones([param.nbVarX, param.nbVarX]))
+    f = np.vstack((param.l @ L @ np.cos(L @ x),
+                   param.l @ L @ np.sin(L @ x))) / param.nbVarX
     return f
 
 # Residual and Jacobian for center of mass
-def f_reach_CoM(param,x):
-    f = fkin_CoM(param,x).T - param.MuCoM
-    J = np.zeros((len(x) * param.nbVarF, len(x) * param.nbVarX))
-    A = np.tril(np.ones([param.nbVarX, param.nbVarX]))
-    for t in range(x.shape[0]):
-        Jtmp = np.vstack((-np.sin(A @ x[t] ).T @ A @ np.diag(param.l @ A) ,
-                    np.cos(A @ x[t] ).T @ A @ np.diag(param.l @ A)))/param.nbVarX
+def f_reach_CoM(x, param):
+    f = fkin_CoM(x, param) - np.tile(param.MuCoM.reshape((-1,1)), [1,np.size(x,1)])
+    J = np.zeros((np.size(x,1) * param.nbVarF, np.size(x,1) * param.nbVarX))
+    L = np.tril(np.ones([param.nbVarX, param.nbVarX]))
+    for t in range(np.size(x,1)):
+        Jtmp = np.vstack((-np.sin(L @ x[:,t] ).T @ L @ np.diag(param.l @ L) ,
+                           np.cos(L @ x[:,t] ).T @ L @ np.diag(param.l @ L))) / param.nbVarX
         if param.useBoundingBox:
-            for i in range(1):
-                if abs(f[t, i]) < param.szCoM:
-                    f[t, i] = 0
+            for i in range(1): # Only x direction matters
+                if abs(f[i,t]) < param.szCoM:
+                    f[i,t] = 0
                     Jtmp[i] = 0
                 else:
-                    f[t, i] -= np.sign(f[t, i]) * param.szCoM
-        J[t * param.nbVarF:(t + 1) * param.nbVarF, t * param.nbVarX:(t + 1) * param.nbVarX] = Jtmp
-    f = f.flatten().T
+                    f[i,t] -= np.sign(f[i,t]) * param.szCoM
+        J[t*param.nbVarF:(t+1)*param.nbVarF, t*param.nbVarX:(t+1)*param.nbVarX] = Jtmp
     return f, J
 
 
@@ -113,6 +107,7 @@ param.r = 1e-5 # Control weight term
 param.Mu = np.asarray([3.5, 4]) # Target
 param.MuCoM = np.asarray([.4, 0]) # desired position of the center of mass
 
+
 # Main program
 # ===============================
 
@@ -129,10 +124,10 @@ Qc = np.kron(np.identity(param.nbData), np.diag([1E0, 0]))
 
 # System parameters
 # ===============================
-# Time occurence of viapoints
+# Time occurrence 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* param.nbVarX)])
+idx = np.array([i + np.arange(0,param.nbVarX,1) for i in (tl* param.nbVarX)])
 
 u = np.zeros(param.nbVarU * (param.nbData - 1))  # Initial control command
 a = .7
@@ -141,31 +136,32 @@ x0 = np.array([np.pi / 2 - a, 2 * a, - a, np.pi - np.pi / 4, 3 * np.pi / 4])  #
 # 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))])
+                 np.eye(param.nbVarX) * param.dt))])
 Sx0 = np.kron(np.ones(param.nbData), np.identity(param.nbVarX)).T
 Su = Su0[idx.flatten()]  # We remove the lines that are out of interest
 
+
 # Solving iLQR
 # ===============================
 for i in range(param.nbIter):
     x = Su0 @ u + Sx0 @ x0
-    x = x.reshape((param.nbData, param.nbVarX))
-
-    f, J = f_reach(param,x[tl])
-    fc, Jc = f_reach_CoM(param,x)
-    du = np.linalg.inv(Su.T @ J.T @ Q @ J @ Su + Su0.T @ Jc.T @ Qc @ Jc @ Su0 + R) @ (-Su.T @ J.T @ Q @ f.flatten() - Su0.T @ Jc.T @ Qc @ fc.flatten() - u * param.r)
+    x = x.reshape([param.nbVarX, param.nbData], order='F')
+    f, J = f_reach(x[:,tl], param)
+    fc, Jc = f_reach_CoM(x, param)
+    du = np.linalg.inv(Su.T @ J.T @ Q @ J @ Su + Su0.T @ Jc.T @ Qc @ Jc @ Su0 + R) @ \
+                      (-Su.T @ J.T @ Q @ f.flatten('F') - Su0.T @ Jc.T @ Qc @ fc.flatten('F') - u * param.r)
 
     # Perform line search
     alpha = 1
-    cost0 = f.flatten() @ Q @ f.flatten() + fc.flatten() @ Qc @ fc.flatten() + np.linalg.norm(u) * param.r
+    cost0 = f.flatten('F').T @ Q @ f.flatten('F') + fc.flatten('F').T @ Qc @ fc.flatten('F') + np.linalg.norm(u) * param.r
 
     while True:
         utmp = u + du * alpha
         xtmp = Su0 @ utmp + Sx0 @ x0
-        xtmp = xtmp.reshape((param.nbData, param.nbVarX))
-        ftmp, _ = f_reach(param,xtmp[tl])
-        fctmp, _ = f_reach_CoM(param,xtmp)
-        cost = ftmp.flatten() @ Q @ ftmp.flatten() + fctmp. T @ Qc @ fctmp + np.linalg.norm(utmp) * param.r
+        xtmp = xtmp.reshape([param.nbVarX, param.nbData], order='F')
+        ftmp, _ = f_reach(xtmp[:,tl], param)
+        fctmp, _ = f_reach_CoM(xtmp, param)
+        cost = ftmp.flatten('F').T @ Q @ ftmp.flatten('F') + fctmp.flatten('F').T @ Qc @ fctmp.flatten('F') + np.linalg.norm(utmp)**2 * param.r
 
         if cost < cost0 or alpha < 1e-3:
             u = utmp
@@ -174,7 +170,7 @@ for i in range(param.nbIter):
 
         alpha /= 2
 
-# Ploting
+# Plotting
 # ===============================
 plt.figure()
 plt.axis("off")
@@ -184,12 +180,12 @@ plt.gca().set_aspect('equal', adjustable='box')
 plt.plot([-1, 3], [0, 0], linestyle='-', c=[.2, .2, .2], linewidth=2)
 
 # Get points of interest
-f00 = fkin0(param,x[0])
-fT0 = fkin0(param,x[-1])
-fc = fkin_CoM(param,x)
+f00 = fkin0(x[:,0], param)
+fT0 = fkin0(x[:,-1], param)
+fc = fkin_CoM(x, param)
 
-plt.plot(f00[:, 0], f00[:, 1], c=[.8, .8, .8], linewidth=4, linestyle='-')
-plt.plot(fT0[:, 0], fT0[:, 1], c=[.4, .4, .4], linewidth=4, linestyle='-')
+plt.plot(f00[0,:], f00[1,:], c=[.8, .8, .8], linewidth=4, linestyle='-')
+plt.plot(fT0[0,:], fT0[1,:], c=[.4, .4, .4], linewidth=4, linestyle='-')
 
 #plot CoM
 plt.plot(fc[0, 0], fc[1, 0], c=[.5, .5, .5], marker="o", markeredgewidth=4, markersize=8, markerfacecolor='white')
diff --git a/python/iLQR_obstacle.py b/python/iLQR_obstacle.py
index 6de5c063bee4a32e215dc95e64bba4a1bf7906ed..10ba23c33ee40ea7207640d626470c82df19c6a4 100644
--- a/python/iLQR_obstacle.py
+++ b/python/iLQR_obstacle.py
@@ -28,7 +28,7 @@ import matplotlib.patches as patches
 def f_reach(x,param):
     f = x - param.Mu[:,:2]
     J = np.identity(x.shape[1]*x.shape[0])
-    return f,J
+    return f, J
 
 # Residual and Jacobian for an obstacle avoidance task
 def f_avoid(x,param):
@@ -56,7 +56,7 @@ def f_avoid(x,param):
     f = np.array(f)
     idx = np.array(idx)
     idt = np.array(idt)
-    return f,J.T,idx,idt
+    return f, J.T, idx, idt
 
 # General parameters
 # ===============================