diff --git a/README.md b/README.md
index 07338434002826b14ea16165687ecbcf6be5b96f..b07602610e66de43de7d4b111843d4714cd32311 100644
--- a/README.md
+++ b/README.md
@@ -234,6 +234,7 @@ All the examples are located in the `demos` folder, and the functions are locate
 | [demo_search01.m](./demos/demo_search01.m) | [[2]](#ref-2) | EM-based stochastic optimization |
 | [demo_spring01.m](./demos/demo_spring01.m) | [[10]](#ref-10) | Influence of the damping ratio in mass-spring-damper systems |
 | [demo_stdPGMM01.m](./demos/demo_stdPGMM01.m) | [[1]](#ref-1) | Parametric Gaussian mixture model (PGMM) used as a task-parameterized model, with DS-GMR employed to retrieve continuous movements |
+| [demo_tensor_TTGO01.m](./demos/demo_tensor_TTGO01.m) | [[11]](#ref-11) | Global optimization with tensor trains (TTGO) |
 | [demo_TPHDDC01.m](./demos/demo_TPHDDC01.m) | [[1]](#ref-1) | Task-parameterized high dimensional data clustering (TP-HDDC) |
 | [demo_TPGMM01.m](./demos/demo_TPGMM01.m) | [[1]](#ref-1) | Task-parameterized Gaussian mixture model (TP-GMM) encoding |
 | [demo_TPGMM_bimanualReaching01.m](./demos/demo_TPGMM_bimanualReaching01.m) | [[1]](#ref-1) | Time-invariant task-parameterized GMM applied to a bimanual reaching task |
@@ -347,12 +348,21 @@ If you find PbDlib useful for your research, please cite the related publication
 </p>
 
 <p><a name="ref-11">
-[11] Lembono, T.S. and Calinon, S. (2021). <strong>Probabilistic Iterative LQR for Short Time Horizon MPC</strong>. arXiv:2012.06349.
+[11] Lembono, T.S. and Calinon, S. (2021). <strong>Probabilistic Iterative LQR for Short Time Horizon MPC</strong>. In Proc. IEEE/RSJ Intl Conf. on Intelligent Robots and Systems (IROS), pp. 556-562.
 </a><br>
-[[pdf]](https://arxiv.org/pdf/2012.06349.pdf)
+[[pdf]](https://calinon.ch/papers/Lembono-IROS2021.pdf)
+[[bib]](https://calinon.ch/papers/Lembono-IROS2021.bib)
 <br><strong>(Ref. for iLQR/DDP)</strong>
 </p>
 
+<p><a name="ref-12">
+[12] Shetty, S., Lembono, T., Löw, T. and Calinon, S. (2022). <strong>Tensor Train for Global Optimization Problems in Robotics</strong>. arXiv:2206.05077.
+</a><br>
+[[pdf]](https://calinon.ch/papers/Shetty-arXiv2022.pdf)
+[[bib]](https://calinon.ch/papers/Shetty-arXiv2022.bib)
+<br><strong>(Ref. for low-rank tensor train factorization)</strong>
+</p>
+
 ### Gallery
 
 |                         |                         |
@@ -368,9 +378,9 @@ If you find PbDlib useful for your research, please cite the related publication
 
 ### License
 
-The Matlab/GNU Octave version of PbDlib is maintained by Sylvain Calinon, Idiap Research Institute. 
+The Matlab/GNU Octave version of PbDlib is maintained by [Sylvain Calinon](https://calinon.ch), Idiap Research Institute. 
 
-Copyright (c) 2015-2021 Idiap Research Institute, https://idiap.ch/
+Copyright (c) 2015-2022 Idiap Research Institute, https://idiap.ch/
 
 PbDlib 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.
 
diff --git a/demos/demo_GPR_closedShape02.m b/demos/demo_GPR_closedShape02.m
index ec3f34f0ea3e307aed6636527a19375c5554360e..f060e5205c16fba32acf0b5a92946866b7b4383f 100644
--- a/demos/demo_GPR_closedShape02.m
+++ b/demos/demo_GPR_closedShape02.m
@@ -139,7 +139,7 @@ set(gca,'LooseInset',[0,0,0,0]);
 colormap(repmat(linspace(1,.4,64),3,1)');
 
 %Plot center of GP (acting as prior if points on the contours are missing)
-subplot(2,5,1); hold on; axis off; rotate3d on; title('Prior (circular contour)','fontsize',16);
+subplot(2,5,1); hold on; axis off; rotate3d on; title('Prior (circular shape)','fontsize',26);
 % for n=2:nbRepros/2
 % 	coltmp = [.5 .5 .5] + [.5 .5 .5].*rand(1);
 % 	mesh(Xm, Ym, reshape(r(n).Data(3,:), nbDataRepro^.5, nbDataRepro^.5), 'facealpha',.4,'edgealpha',.4,'facecolor',coltmp,'edgecolor',coltmp); %Prior samples
@@ -151,7 +151,7 @@ plot3(xc(1)+cos(tl)*rc, xc(2)+sin(tl)*rc, zeros(1,100), '-','linewidth',2,'color
 view(3); axis vis3d;
 
 %Plot posterior distribution (3D)
-subplot(2,5,6); hold on; axis off; rotate3d on; title('Posterior','fontsize',16);
+subplot(2,5,6); hold on; axis off; rotate3d on; title('Posterior','fontsize',26);
 % for n=nbRepros/2+1:nbRepros
 % 	coltmp = [.5 .5 .5] + [.5 .5 .5].*rand(1);
 % 	mesh(Xm, Ym, reshape(r(n).Data(3,:), nbDataRepro.^.5, nbDataRepro.^.5), 'facealpha',.4,'edgealpha',.4,'facecolor',coltmp,'edgecolor',coltmp); %posterior samples
@@ -159,24 +159,24 @@ subplot(2,5,6); hold on; axis off; rotate3d on; title('Posterior','fontsize',16)
 mesh(Xm, Ym, reshape(ry, nbDataRepro^.5, nbDataRepro^.5), 'facealpha',.8,'edgealpha',.8,'edgecolor',[.7 .7 .7]);
 mesh(Xm, Ym, zeros(nbDataRepro^.5, nbDataRepro^.5), 'facealpha',.3,'edgealpha',.6,'facecolor',[0 0 0],'edgecolor','none');
 contour(Xm, Ym, reshape(ry, nbDataRepro^.5, nbDataRepro^.5), [0,0], 'linewidth',2,'color',[0 0 0]); 
-plot3(x(1,y==1), x(2,y==1), y(y==1)+.04, '.','markersize',18,'color',[.8 0 0]); %Interior points
-plot3(x(1,y==0), x(2,y==0), y(y==0)+.04, '.','markersize',18,'color',[.8 .4 0]); %Border points
-plot3(x(1,y==-1), x(2,y==-1), y(y==-1)+.04, '.','markersize',18,'color',[0 .6 0]); %Exterior points
+%plot3(x(1,y==1), x(2,y==1), y(y==1)+.04, '.','markersize',38,'color',[.8 0 0]); %Interior points
+plot3(x(1,y==0), x(2,y==0), y(y==0)+.04, '.','markersize',38,'color',[.8 .4 0]); %Border points
+%plot3(x(1,y==-1), x(2,y==-1), y(y==-1)+.04, '.','markersize',38,'color',[0 .6 0]); %Exterior points
 view(3); axis vis3d;
 
 %Plot posterior distribution (2D)
-subplot(2,5,[2,3,7,8]); hold on; axis off; title('Distance to contour and gradient','fontsize',16);
+subplot(2,5,[2,3,7,8]); hold on; axis off; title('Distance to contour and gradient','fontsize',26);
 mshbrd = [-.5 -.5 .5 .5 -.5; -.5 .5 .5 -.5 -.5];
 plot(mshbrd(1,:), mshbrd(2,:), '-','linewidth',1,'color',[0 0 0]);
 surface(Xm, Ym, reshape(ry, nbDataRepro^.5, nbDataRepro^.5)-max(ry), 'FaceColor','interp','EdgeColor','interp');
-quiver(xs(1,:), xs(2,:), rdy(1,:), rdy(2,:),'color',[.2 .2 .2]);
+quiver(xs(1,1:4:end), xs(2,1:4:end), rdy(1,1:4:end), rdy(2,1:4:end),'color',[.2 .2 .2]);
 % quiver(xs(1,ry>0), xs(2,ry>0), rdy(1,ry>0), rdy(2,ry>0), 'color',[.8 .2 .2]);
 % quiver(xs(1,ry<0), xs(2,ry<0), rdy(1,ry<0), rdy(2,ry<0), 'color',[.2 .7 .2]);
-h(1) = plot(x(1,y==1), x(2,y==1), '.','markersize',28,'color',[.8 0 0]); %Interior points
-h(2) = plot(x(1,y==0), x(2,y==0), '.','markersize',28,'color',[.8 .4 0]); %Border points
-h(3) = plot(x(1,y==-1), x(2,y==-1), '.','markersize',28,'color',[0 .6 0]); %Exterior points
-h(4) = plot(xc(1)+cos(tl)*rc, xc(2)+sin(tl)*rc, '--','linewidth',2,'color',[0 0 0]);
-[~,h(5)] = contour(Xm, Ym, reshape(ry, nbDataRepro^.5, nbDataRepro^.5), [0,0], 'linewidth',2,'color',[0 0 0]);
+%h(1) = plot(x(1,y==1), x(2,y==1), '.','markersize',48,'color',[.8 0 0]); %Interior points
+h(1) = plot(x(1,y==0), x(2,y==0), '.','markersize',48,'color',[.8 .4 0]); %Border points
+%h(3) = plot(x(1,y==-1), x(2,y==-1), '.','markersize',48,'color',[0 .6 0]); %Exterior points
+h(2) = plot(xc(1)+cos(tl)*rc, xc(2)+sin(tl)*rc, '--','linewidth',2,'color',[0 0 0]);
+[~,h(3)] = contour(Xm, Ym, reshape(ry, nbDataRepro^.5, nbDataRepro^.5), [0,0], 'linewidth',4,'color',[0 0 0]);
 % contour(Xm, Ym, reshape(ry, nbDataRepro^.5, nbDataRepro^.5), [-.4,-.4], 'linewidth',2,'color',[.2 .2 .2]);
 % contour(Xm, Ym, reshape(ry, nbDataRepro^.5, nbDataRepro^.5), [-.8,-.8], 'linewidth',2,'color',[.4 .4 .4]);
 % contour(Xm, Ym, reshape(ry, nbDataRepro^.5, nbDataRepro^.5), [-1.2,-1.2], 'linewidth',2,'color',[.6 .6 .6]);
@@ -184,22 +184,23 @@ h(4) = plot(xc(1)+cos(tl)*rc, xc(2)+sin(tl)*rc, '--','linewidth',2,'color',[0 0
 % contour(Xm, Ym, reshape(ry(3,:)+2E0.*diag(S).^.5', nbDataRepro.^.5, nbDataRepro.^.5), [0,0], 'linewidth',1,'color',[.6 .6 .6]); 
 % contour(Xm, Ym, reshape(ry(3,:)-2E0.*diag(S).^.5', nbDataRepro.^.5, nbDataRepro.^.5), [0,0], 'linewidth',1,'color',[.6 .6 .6]); 
 axis tight; axis equal; axis([-.5 .5 -.5 .5]); axis ij;
-legend(h,{'Demonstrated interior points (y=1)','Demonstrated contour points (y=0)','Demonstrated exterior points (y=-1)','Prior for contour estimation','Estimated contour'},'fontsize',16,'location','southwest');
+%legend(h,{'Demonstrated interior points (y=1)','Demonstrated contour points (y=0)','Demonstrated exterior points (y=-1)','Prior for contour estimation','Estimated contour'},'fontsize',16,'location','southwest');
+legend(h,{'Provided contour points','Prior for contour estimation','Estimated contour'},'fontsize',26,'location','southwest');
 % legend('boxoff');
 
 %Plot uncertainty (2D)
-subplot(2,5,[4,5,9,10]); hold on; axis off; title('Uncertainty','fontsize',16);
+subplot(2,5,[4,5,9,10]); hold on; axis off; title('Uncertainty','fontsize',26);
 plot(mshbrd(1,:), mshbrd(2,:), '-','linewidth',1,'color',[0 0 0]);
 % surface(Xm, Ym, reshape(ry, nbDataRepro^.5, nbDataRepro^.5)-max(ry), 'FaceColor','interp','EdgeColor','interp');
 surface(Xm, Ym, reshape(diag(S), nbDataRepro^.5, nbDataRepro^.5)-max(S(:)), 'FaceColor','interp','EdgeColor','interp');
-plot(x(1,y==1), x(2,y==1), '.','markersize',28,'color',[.8 0 0]); %Interior points
-plot(x(1,y==0), x(2,y==0), '.','markersize',28,'color',[.8 .4 0]); %Border points
-plot(x(1,y==-1), x(2,y==-1), '.','markersize',28,'color',[0 .6 0]); %Exterior points
-contour(Xm, Ym, reshape(ry, nbDataRepro^.5, nbDataRepro^.5), [0,0], 'linewidth',2,'color',[0 0 0]);
+plot(x(1,y==1), x(2,y==1), '.','markersize',48,'color',[.8 0 0]); %Interior points
+plot(x(1,y==0), x(2,y==0), '.','markersize',48,'color',[.8 .4 0]); %Border points
+plot(x(1,y==-1), x(2,y==-1), '.','markersize',48,'color',[0 .6 0]); %Exterior points
+contour(Xm, Ym, reshape(ry, nbDataRepro^.5, nbDataRepro^.5), [0,0], 'linewidth',4,'color',[0 0 0]);
 plot(xc(1)+cos(tl)*rc, xc(2)+sin(tl)*rc, '--','linewidth',2,'color',[0 0 0]);
 axis tight; axis equal; axis([-.5 .5 -.5 .5]); axis ij;
 
-% print('-dpng','graphs/GPIS01.png');
+%print('-dpng','graphs/GPIS_new01.png');
 pause;
 close all;
 end
@@ -249,4 +250,4 @@ function [K, dK] = covFct(x1, x2, p, flag_noiseObs)
 	if flag_noiseObs==1
 		K = K + p(2) * eye(size(x1,2),size(x2,2)); %Consy==-1ration of noisy observation y
 	end
-end
\ No newline at end of file
+end
diff --git a/demos/demo_ID01.m b/demos/demo_ID01.m
index 05cd79651d1e770e751bf33901ff4b17f9363ea2..bb55539225e59852ee80bfb96cd9294dd2efdc89 100644
--- a/demos/demo_ID01.m
+++ b/demos/demo_ID01.m
@@ -110,7 +110,7 @@ for t=1:nbData
 
 % 	ddq = robot.accel(q', dq', u'); %Compute acceleration
 	ddq = accel(q, u, model);
-	pause
+
 % 	ddq = (u - uG) / M; %Compute acceleration
 	
 	dq = dq + ddq*dt;
@@ -154,4 +154,4 @@ function J = jacob0(q, model)
 		qtmp(n) = qtmp(n) + e;
 		J(:,n) = (fkine(qtmp, model) - fkine(q, model)) / e;
 	end
-end
\ No newline at end of file
+end
diff --git a/demos/demo_IK01.m b/demos/demo_IK01.m
index 1926d4a94c72e871c5c5320079dbbcf8269236d7..d9eaa231606f402c6e7d3cd275e89a3130847dc4 100644
--- a/demos/demo_IK01.m
+++ b/demos/demo_IK01.m
@@ -84,9 +84,9 @@ function [x, Tf] = fkine(q, model)
 		c = cos(q(n));
 		s = sin(q(n));
 		T(:,:,n) = [c, -s, 0, model.l * c; ...
-								s, c, 0, model.l * s; ...
-								0, 0, 1, 0; ...
-								0, 0, 0, 1]; %Homogeneous matrix 
+					s, c, 0, model.l * s; ...
+					0, 0, 1, 0; ...
+					0, 0, 0, 1]; %Homogeneous matrix 
 		Tf = Tf * T(:,:,n);
 	end
 	x = Tf(1:2,end);
@@ -102,4 +102,4 @@ function J = jacob0(q, model)
 		qtmp(n) = qtmp(n) + e;
 		J(:,n) = (fkine(qtmp, model) - fkine(q, model)) / e;
 	end
-end
\ No newline at end of file
+end
diff --git a/demos/demo_IK_expForm01.m b/demos/demo_IK_expForm01.m
index b5f53bff6aadd6247250a23b28678753a01622ef..93f6a3faccc5a8155166652f0a8472991dc6e5aa 100644
--- a/demos/demo_IK_expForm01.m
+++ b/demos/demo_IK_expForm01.m
@@ -40,7 +40,7 @@ end
 
 %% Plots
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-figure('position',[20,10,800,650],'color',[1 1 1]); hold on; axis off;
+h = figure('position',[20,10,800,650],'color',[1 1 1]); hold on; axis off;
 for t=floor(linspace(1,nbData,20))
 	colTmp = [.7,.7,.7] - [.7,.7,.7] * t/nbData;
 	plotArm(q(:,t), model.l, [0;0;-2+t/nbData], .2, colTmp);
@@ -52,8 +52,7 @@ plot(x(1,:), x(2,:), '.','markersize',20,'color',[0 .6 0]);
 axis equal; axis tight;
 
 %print('-dpng','graphs/demoIK_expForm01.png');
-pause;
-close all;
+waitfor(h);
 end
 
 function u = logmap(x, x0)
@@ -88,6 +87,6 @@ function J = jacob0(q, model)
 % 	J = [real(J); imag(J)]
 
 % 	J = model.l * 1i * exp(1i * tril(ones(model.nbDOFs)) * q)' * tril(ones(model.nbDOFs)); %Computation in matrix form
-	J = 1i * exp(1i * tril(ones(model.nbDOFs)) * q).' * tril(ones(model.nbDOFs)) * diag(model.l); %Computation in matrix form
+	J = 1i * exp(1i * tril(ones(model.nbDOFs)) * q).' * diag(model.l) * tril(ones(model.nbDOFs)); %Computation in matrix form
 	J = [real(J); imag(J); ones(1, model.nbDOFs)]; %x1,x2,o
-end
\ No newline at end of file
+end
diff --git a/demos/demo_IK_minimal01.m b/demos/demo_IK_minimal01.m
index 2e1ab9e56ee6f7914cb385bc4b44a2d41579b6be..016f7a6c38f0befa5681d20dfcdf6656f7de114e 100644
--- a/demos/demo_IK_minimal01.m
+++ b/demos/demo_IK_minimal01.m
@@ -10,49 +10,52 @@ addpath('./m_fcts/');
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 dt = 1E-2; %Time step
 nbData = 100; %Number of datapoints
-model.nbDOFs = 3; %Number of articulations
-model.l = [2, 2, 1]; %Length of each link
-q(:,1) = [pi-3*pi/4; pi/2; pi/4]; %Initial pose
-x(:,1) = fkine(q(:,1), model);
+model.nbVarX = 3; %Number of articulations
+model.l = [2; 2; 1]; %Length of each link
+x(:,1) = [3*pi/4; -pi/2; -pi/4]; %Initial pose
+%x(:,1) = ones(model.nbVarX,1) * pi / model.nbVarX; %Initial pose
 
 
 %% IK 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-xh = [2; 2]; 
+fh = [3; 1]; 
 for t=1:nbData-1
-	J = jacob(q(:,t), model); %Jacobian
-	dq = pinv(J) * 8E0 * (xh - x(:,t));
-	q(:,t+1) = q(:,t) + dq * dt;
-	x(:,t+1) = fkine(q(:,t+1), model); %FK for a planar robot
+	f(:,t) = fkin(x(:,t), model); %FK for a planar robot
+	J = Jkin(x(:,t), model); %Jacobian
+	dx = pinv(J) * (fh - f(:,t)) * 1E1;
+	x(:,t+1) = x(:,t) + dx * dt;	
 end
 
 
 %% Plots
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-figure('position',[20,10,800,650],'color',[1 1 1]); hold on; axis off;
+h = figure('position',[20,10,800,650],'color',[1 1 1]); hold on; axis off;
 for t=floor(linspace(1,nbData,2))
 	colTmp = [.7,.7,.7] - [.7,.7,.7] * t/nbData;
-	plotArm(q(:,t), model.l, [0;0;-2+t/nbData], .2, colTmp);
+	plotArm(x(:,t), model.l, [0;0;-2+t/nbData], .2, colTmp);
 end
-plot(xh(1), xh(2), '.','markersize',40,'color',[.8 0 0]);
-plot(x(1,:), x(2,:), '.','markersize',20,'color',[0 .6 0]);
+plot(fh(1), fh(2), '.','markersize',40,'color',[.8 0 0]);
+plot(f(1,:), f(2,:), '.','markersize',20,'color',[0 .6 0]);
 axis equal; axis tight;
 
 %print('-dpng','graphs/demoIK_minimal01.png');
-pause;
-close all;
+%pause;
+%close all;
+waitfor(h);
 end
 
 %%%%%%%%%%%%%%%%%%%%%%
 %Forward kinematics
-function x = fkine(q, model)
-	x = [model.l * cos(tril(ones(model.nbDOFs)) * q); ...
-		 model.l * sin(tril(ones(model.nbDOFs)) * q)];
+function f = fkin(x, model)
+	L = tril(ones(model.nbVarX));
+	f = [model.l' * cos(L * x); ...
+		 model.l' * sin(L * x)];
 end
 
 %%%%%%%%%%%%%%%%%%%%%%
 %Jacobian with analytical computation
-function J = jacob(q, model)
-	J = [-sin(tril(ones(model.nbDOFs)) * q)' * diag(model.l) * tril(ones(model.nbDOFs)); ...
-		  cos(tril(ones(model.nbDOFs)) * q)' * diag(model.l) * tril(ones(model.nbDOFs))];
-end
\ No newline at end of file
+function J = Jkin(x, model)
+	L = tril(ones(model.nbVarX));
+	J = [-sin(L * x)' * diag(model.l) * L; ...
+		  cos(L * x)' * diag(model.l) * L];
+end
diff --git a/demos/demo_OC_DDP_bicopter01.m b/demos/demo_OC_DDP_bicopter01.m
index 248815af9b92352e52547a24140221145f0b3889..aff5e1eecdcc5e5ed012e82c6d8a5f3350695384 100644
--- a/demos/demo_OC_DDP_bicopter01.m
+++ b/demos/demo_OC_DDP_bicopter01.m
@@ -99,19 +99,19 @@ figure('position',[10,10,800,800]); hold on; axis off; grid on; box on;
 for t=floor(linspace(1,model.nbData,20))
 	plot(r.x(1,t), r.x(2,t), '.','markersize',40,'color',[.6 .6 .6]);
 	msh = [r.x(1:2,t), r.x(1:2,t)] + [cos(r.x(3,t)); sin(r.x(3,t))] * [-.4, .4];
-	plot(msh(1,:), msh(2,:), '-','linewidth',5,'color',[.6 .6 .6]);
+	plot(msh(1,:), msh(2,:), '-','linewidth',5,'color',[.7 .7 .7]);
 end
-plot(r.x(1,:),r.x(2,:), '-','linewidth',2,'color',[.6 .6 .6]);
+plot(r.x(1,:),r.x(2,:), '-','linewidth',2,'color',[0 0 0]);
 msh = [r.x(1:2,1), r.x(1:2,1)] + [cos(r.x(3,1)); sin(r.x(3,1))] * [-.4, .4];
 plot(msh(1,:), msh(2,:), '-','linewidth',5,'color',[0 0 0]);
 h(1) = plot(r.x(1,1),r.x(2,1), '.','markersize',40,'color',[0 0 0]);
 msh = [model.Mu(1:2), model.Mu(1:2)] + [cos(model.Mu(3)); sin(model.Mu(3))] * [-.4, .4];
 plot(msh(1,:), msh(2,:), '-','linewidth',5,'color',[.8 0 0]);
 h(2) = plot(model.Mu(1), model.Mu(2), '.','markersize',40,'color',[.8 0 0]);
-legend(h,{'Initial pose','Target pose'},'location','northwest','fontsize',30);
+%legend(h,{'Initial pose','Target pose'},'location','northwest','fontsize',30);
 axis equal; axis([-.5 4.5 -.2 4.4]);
 xlabel('x_1'); ylabel('x_2');
-% print('-dpng','graphs/DDP_bicopter01.png');
+%print('-dpng','graphs/DDP_bicopter01.png');
 
 
 % %% Plot control space
@@ -223,4 +223,4 @@ function [A, B] = linSys(x, u, model)
 % 	f(6) =  l/I  * (u(1) - u(2));
 % 	jacobian(f, x)
 % 	jacobian(f, u)
-end
\ No newline at end of file
+end
diff --git a/demos/demo_OC_DDP_car01.m b/demos/demo_OC_DDP_car01.m
index a215a14268c2c23f1fd7e0304639455edc0a4b9e..97a74ef8369fe9bab12d73d305e448c0d9be8b4f 100644
--- a/demos/demo_OC_DDP_car01.m
+++ b/demos/demo_OC_DDP_car01.m
@@ -94,7 +94,7 @@ figure('position',[10,10,800,800]); hold on; axis off;
 for t=round(linspace(1, model.nbData, 20))
 	R = [cos(r.x(3,t)) -sin(r.x(3,t)); sin(r.x(3,t)) cos(r.x(3,t))];
 	msh = R * [-.6 -.6 .6 .6 -.6; -.4 .4 .4 -.4 -.4] + repmat(r.x(1:2,t),1,5);
-	plot(msh(1,:), msh(2,:), '-','linewidth',2,'color',[.6 .6 .6]);
+	plot(msh(1,:), msh(2,:), '-','linewidth',2,'color',[.7 .7 .7]);
 end
 plot(r.x(1,:),r.x(2,:), '-','linewidth',2,'color',[0 0 0]);
 %Initial pose
@@ -112,9 +112,9 @@ R = [cos(model.Mu(3)) -sin(model.Mu(3)); sin(model.Mu(3)) cos(model.Mu(3))];
 msh = R * [-.6 -.6 .6 .6 -.6; -.4 .4 .4 -.4 -.4] + repmat(model.Mu(1:2),1,5);
 plot(msh(1,:), msh(2,:), '-','linewidth',2,'color',[.8 0 0]);
 h(2) = plot(model.Mu(1), model.Mu(2), '.','markersize',20,'color',[.8 0 0]);
-legend(h,{'Initial pose','Target pose'},'location','northwest','fontsize',30);
+%legend(h,{'Initial pose','Target pose'},'location','northwest','fontsize',30);
 axis equal; axis([-1 5 -1 4]);
-% print('-dpng','graphs/DDP_car01.png');
+%print('-dpng','graphs/DDP_car01.png');
 
 
 % %% Plot control space
@@ -220,4 +220,4 @@ function [A, B] = linSys(x, u, model)
 % 	f(4) = u(2);
 % 	jacobian(f, x)
 % 	jacobian(f, u)
-end
\ No newline at end of file
+end
diff --git a/demos/demo_OC_DDP_manipulator01.m b/demos/demo_OC_DDP_manipulator01.m
index c2582e7845541873724f3c27d14f90e649ebfe82..c72f266cf57878833beb66b7d2ad680a4307b7c6 100644
--- a/demos/demo_OC_DDP_manipulator01.m
+++ b/demos/demo_OC_DDP_manipulator01.m
@@ -33,66 +33,79 @@ addpath('./m_fcts/');
 
 %% Parameters
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-model.dt = 1E-2; %Time step size
-model.nbData = 50; %Number of datapoints
-model.nbIter = 300; %Maximum number of iterations for iLQR
-model.nbPoints = 2; %Number of viapoints
-model.nbVarX = 3; %State space dimension (q1,q2,q3)
-model.nbVarU = 3; %Control space dimension (dq1,dq2,dq3)
-model.nbVarF = 3; %Task space dimension (x1,x2,o)
-model.l = [2, 2, 1]; %Robot links lengths
-model.sz = [.2, .3]; %Size of objects
-model.q = 1E0; %Tracking weighting term
-model.r = 1E-6; %Control weighting term
+param.dt = 1E-2; %Time step size
+param.nbData = 50; %Number of datapoints
+param.nbIter = 300; %Maximum number of iterations for iLQR
+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; %Task space dimension (f1,f2,f3, with f3 as orientation)
+param.l = [3; 2; 1]; %Robot links lengths
+param.fmax = [.2, .3, .01]; %Bounding boxes parameters
+param.q = 1E0; %Tracking weighting term
+param.r = 1E-5; %Control weighting term
 
-% model.Mu = [[2; 1; -pi/2], [3; 1; -pi/2]]; %Viapoints
-model.Mu = [[2; 1; -pi/6], [3; 2; -pi/3]]; %Viapoints 
-% model.Mu = [3; 0; -pi/2]; %Viapoints 
-for t=1:model.nbPoints
-	model.A(:,:,t) = [cos(model.Mu(3,t)), -sin(model.Mu(3,t)); sin(model.Mu(3,t)), cos(model.Mu(3,t))]; %Orientation
+% param.Mu = [[2; 1; -pi/2], [3; 1; -pi/2]]; %Viapoints
+param.Mu = [[2; 1; -pi/6], [3; 2; -pi/3]]; %Viapoints
+% param.Mu = [3; 0; -pi/2]; %Viapoints 
+for t=1:param.nbPoints
+	param.A(:,:,t) = [cos(param.Mu(3,t)), -sin(param.Mu(3,t)); sin(param.Mu(3,t)), cos(param.Mu(3,t))]; %Orientation
 end
 
-Q = speye(model.nbVarF * model.nbPoints) * model.q; %Precision matrix
-% Q = kron(eye(model.nbPoints), diag([1E0, 1E0, 0])); %Precision matrix (by removing orientation constraint)
-R = speye(model.nbVarU * (model.nbData-1)) * model.r; %Control weight matrix (at trajectory level)
+Q = speye(param.nbVarF * param.nbPoints) * param.q; %Precision matrix
+% Q = kron(eye(param.nbPoints), diag([1E0, 1E0, 0])); %Precision matrix (by removing orientation constraint)
+R = speye(param.nbVarU * (param.nbData-1)) * param.r; %Control weight matrix (at trajectory level)
 
 %Time occurrence of viapoints
-tl = linspace(1, model.nbData, model.nbPoints+1);
+tl = linspace(1, param.nbData, param.nbPoints+1);
 tl = round(tl(2:end));
-idx = (tl - 1) * model.nbVarX + [1:model.nbVarX]';
+idx = (tl - 1) * param.nbVarX + [1:param.nbVarX]';
 
 
 %% Iterative LQR (iLQR)
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-u = zeros(model.nbVarU*(model.nbData-1), 1); %Initial commands
+u = zeros(param.nbVarU*(param.nbData-1), 1); %Initial control commands
 x0 = [3*pi/4; -pi/2; -pi/4]; %Initial robot pose
 
 %Transfer matrices (for linear system as single integrator)
-% A = repmat(eye(model.nbVarX), [1 1 model.nbData-1]);
-% B = repmat(eye(model.nbVarX, model.nbVarU) * model.dt, [1 1 model.nbData-1]); 
+% A = repmat(eye(param.nbVarX), [1 1 param.nbData-1]);
+% B = repmat(eye(param.nbVarX, param.nbVarU) * param.dt, [1 1 param.nbData-1]); 
 % [Su0, Sx0] = transferMatrices(A, B); %Constant Su and Sx for the proposed system
-Su0 = [zeros(model.nbVarX, model.nbVarX*(model.nbData-1)); kron(tril(ones(model.nbData-1)), eye(model.nbVarX)*model.dt)];
-Sx0 = kron(ones(model.nbData,1), eye(model.nbVarX));
+Su0 = [zeros(param.nbVarX, param.nbVarX*(param.nbData-1)); kron(tril(ones(param.nbData-1)), eye(param.nbVarX)*param.dt)];
+Sx0 = kron(ones(param.nbData,1), eye(param.nbVarX));
 Su = Su0(idx,:);
 
-for n=1:model.nbIter	
-	x = reshape(Su0 * u + Sx0 * x0, model.nbVarX, model.nbData); %System evolution
-	[f, J] = f_reach(x(:,tl), model);
-	du = (Su' * J' * Q * J * Su + R) \ (-Su' * J' * Q * f(:) - u * model.r); %Gradient
+for n=1:param.nbIter	
+	x = reshape(Su0 * u + Sx0 * x0, param.nbVarX, param.nbData); %System evolution
+	[f, J] = f_reach(x(:,tl), param); %Residuals and Jacobian
+	du = (Su' * J' * Q * J * Su + R) \ (-Su' * J' * Q * f(:) - u * param.r); %Gauss-Newton update
 	
 	%Estimate step size with backtracking line search method
 	alpha = 1;
-	cost0 = f(:)' * Q * f(:) + norm(u)^2 * model.r; %u' * R * u
+	cost0 = f(:)' * Q * f(:) + norm(u)^2 * param.r; %u' * R * u
 	while 1
 		utmp = u + du * alpha;
-		xtmp = reshape(Su0 * utmp + Sx0 * x0, model.nbVarX, model.nbData);
-		ftmp = f_reach(xtmp(:,tl), model);
-		cost = ftmp(:)' * Q * ftmp(:) + norm(utmp)^2 * model.r; %utmp' * R * utmp
+		xtmp = reshape(Su0 * utmp + Sx0 * x0, param.nbVarX, param.nbData);
+		ftmp = f_reach(xtmp(:,tl), param);
+		cost = ftmp(:)' * Q * ftmp(:) + norm(utmp)^2 * param.r; %utmp' * R * utmp
 		if cost < cost0 || alpha < 1E-3
 			break;
 		end
 		alpha = alpha * 0.5;
 	end
+
+%	%Estimate step size with backtracking line search method
+%	cost0 = f(:)' * Q * f(:) + norm(u)^2 * param.r; %u' * R * u
+%	cost = 1E10;
+%	alpha = 2;
+%	while (cost > cost0 && alpha > 1E-3)
+%		alpha = alpha * 0.5;
+%		utmp = u + du * alpha;
+%		xtmp = reshape(Su0 * utmp + Sx0 * x0, param.nbVarX, param.nbData); %System evolution
+%		ftmp = f_reach(xtmp(:,tl), param); %Residuals
+%		cost = ftmp(:)' * Q * ftmp(:) + norm(utmp)^2 * param.r; %Cost
+%	end
+	
 	u = u + du * alpha;
 	
 	if norm(du * alpha) < 1E-2
@@ -101,99 +114,93 @@ for n=1:model.nbIter
 end
 disp(['iLQR converged in ' num2str(n) ' iterations.']);
 
-%Log data
-r.x = x;
-r.f = fkine0(x, model); 
-r.u = reshape(u, model.nbVarU, model.nbData-1);
-
 
 %% Plot state space
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-msh0 = diag(model.sz) * [-1 -1 1 1 -1; -1 1 1 -1 -1];
-for t=1:model.nbPoints
-	msh(:,:,t) = model.A(:,:,t) * msh0 + repmat(model.Mu(1:2,t), 1, size(msh0,2));
+msh0 = diag(param.fmax(1:2)) * [-1 -1 1 1 -1; -1 1 1 -1 -1];
+for t=1:param.nbPoints
+	msh(:,:,t) = param.A(:,:,t) * msh0 + repmat(param.Mu(1:2,t), 1, size(msh0,2));
 end
 
-figure('position',[10,10,800,800],'color',[1,1,1]); hold on; axis off;
-plotArm(r.x(:,1), model.l, [0; 0; -3], .2, [.8 .8 .8]);
-plotArm(r.x(:,tl(1)), model.l, [0; 0; -2], .2, [.6 .6 .6]);
-plotArm(r.x(:,tl(2)), model.l, [0; 0; -1], .2, [.4 .4 .4]);
-colMat = lines(model.nbPoints);
-for t=1:model.nbPoints
+h = figure('position',[10,10,1600,1200],'color',[1,1,1]); hold on; axis off;
+plotArm(x(:,1), param.l, [0; 0; -3], .2, [.8 .8 .8]);
+plotArm(x(:,tl(1)), param.l, [0; 0; -2], .2, [.6 .6 .6]);
+plotArm(x(:,tl(2)), param.l, [0; 0; -1], .2, [.4 .4 .4]);
+colMat = lines(param.nbPoints);
+for t=1:param.nbPoints
 	patch(msh(1,:,t), msh(2,:,t), min(colMat(t,:)*1.7,1),'linewidth',2,'edgecolor',colMat(t,:)); %,'facealpha',.2
-	plot2Dframe(model.A(:,:,t)*4E-1, model.Mu(1:2,t), repmat(colMat(t,:),3,1), 6);
+	plot2Dframe(param.A(:,:,t)*5E-1, param.Mu(1:2,t), repmat(colMat(t,:),3,1), 2);
 end
-plot(r.f(1,:), r.f(2,:), '-','linewidth',2,'color',[0 0 0]);
-plot(r.f(1,1), r.f(2,1), '.','markersize',40,'color',[0 0 0]);
-plot(r.f(1,tl), r.f(2,tl), '.','markersize',30,'color',[0 0 0]);
-axis equal; 
-% print('-dpng','graphs/DDP_manipulator01.png');
+%plot(param.Mu(1,:), param.Mu(2,:), '.','markersize',40,'color',[.8 0 0]);
+ftmp = fkin(x, param);
+plot(ftmp(1,:), ftmp(2,:), '-','linewidth',2,'color',[0 0 0]);
+plot(ftmp(1,1), ftmp(2,1), '.','markersize',40,'color',[0 0 0]);
+axis equal; %axis([-2.4 3.5 -0.6 3.8]);
+%print('-dpng','graphs/DDP_manipulator01.png');
 
 
-%% Timeline plot
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-figure('position',[820 10 800 800],'color',[1 1 1]); 
-%States plot
-for j=1:model.nbVarF
-	subplot(model.nbVarF+model.nbVarU, 1, j); hold on;
-	plot(tl, model.Mu(j,:), '.','markersize',35,'color',[.8 0 0]);
-	plot(r.f(j,:), '-','linewidth',2,'color',[0 0 0]);
-% 	set(gca,'xtick',[1,nbData],'xticklabel',{'0','T'},'ytick',[0:2],'fontsize',20);
-	ylabel(['$f_' num2str(j) '$'], 'interpreter','latex','fontsize',26);
-% 	axis([1, nbData, 0, 2.1]);
-end
-%Commands plot
-for j=1:model.nbVarU
-	subplot(model.nbVarF+model.nbVarU, 1, model.nbVarF+j); hold on;
-	plot(r.u(j,:), '-','linewidth',2,'color',[0 0 0]);
-% 	set(gca,'xtick',[1,nbData],'xticklabel',{'0','T'},'ytick',[0:2],'fontsize',20);
-	ylabel(['$u_' num2str(j) '$'], 'interpreter','latex','fontsize',26);
-% 	axis([1, nbData, 0, 2.1]);
-end
-xlabel('$t$','interpreter','latex','fontsize',26); 
+%%% Timeline plot
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%figure('position',[820 10 800 800],'color',[1 1 1]); 
+%%States plot
+%for j=1:param.nbVarF
+%	subplot(param.nbVarF+param.nbVarU, 1, j); hold on;
+%	plot(tl, param.Mu(j,:), '.','markersize',35,'color',[.8 0 0]);
+%	plot(r.f(j,:), '-','linewidth',2,'color',[0 0 0]);
+%% 	set(gca,'xtick',[1,nbData],'xticklabel',{'0','T'},'ytick',[0:2],'fontsize',20);
+%	ylabel(['$f_' num2str(j) '$'], 'interpreter','latex','fontsize',26);
+%% 	axis([1, nbData, 0, 2.1]);
+%end
+%%Commands plot
+%r.u = reshape(u, param.nbVarU, param.nbData-1);
+%for j=1:param.nbVarU
+%	subplot(param.nbVarF+param.nbVarU, 1, param.nbVarF+j); hold on;
+%	plot(r.u(j,:), '-','linewidth',2,'color',[0 0 0]);
+%% 	set(gca,'xtick',[1,nbData],'xticklabel',{'0','T'},'ytick',[0:2],'fontsize',20);
+%	ylabel(['$u_' num2str(j) '$'], 'interpreter','latex','fontsize',26);
+%% 	axis([1, nbData, 0, 2.1]);
+%end
+%xlabel('$t$','interpreter','latex','fontsize',26); 
 
 
-% %% Plot value function for reaching costs
-% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% A0 = model.A;
-% Mu0 = model.Mu;
-% 
-% nbRes = 20;
-% limAxes = [0 4 0 4];
-% [xx, yy] = ndgrid(linspace(limAxes(1),limAxes(2),nbRes), linspace(limAxes(3),limAxes(4),nbRes));
-% x = [xx(:)'; yy(:)'; zeros(1,nbRes^2)];
-% msh = [min(x(1,:)), min(x(1,:)), max(x(1,:)), max(x(1,:)), min(x(1,:)); ...
-% 			 min(x(2,:)), max(x(2,:)), max(x(2,:)), min(x(2,:)), min(x(2,:))];
-% %Reaching at T/2
-% model.Mu = [repmat(Mu0(1:2,1), [1 nbRes^2]); zeros(1,nbRes^2)];
-% model.A = repmat(A0(:,:,1), [1 1 nbRes^2]);
-% f = f_reach(x, model);
-% z = sum(f.^2, 1);
-% zz = reshape(z, nbRes, nbRes);
-% %Reaching at T
-% model.Mu = [repmat(Mu0(1:2,2), [1 nbRes^2]); zeros(1,nbRes^2)];
-% model.A = repmat(A0(:,:,2), [1 1 nbRes^2]);
-% f2 = f_reach(x, model);
-% z2 = sum(f2.^2, 1);
-% zz2 = reshape(z2, nbRes, nbRes);
-% 
-% figure('position',[820,10,860,400],'color',[1,1,1]); 
-% colormap(repmat(linspace(1,.4,64),3,1)');
-% %Reaching at T/2
-% subplot(1,2,1); hold on; axis off; title('Reaching cost (for t=T/2)');
-% surface(xx, yy, zz-max(zz(:)), 'EdgeColor','interp','FaceColor','interp'); 
-% plot(Mu0(1,1), Mu0(2,1),'.','markersize',30,'color',colMat(1,:));
-% plot(msh(1,:), msh(2,:),'-','linewidth',1,'color',[0 0 0]); %border
-% axis equal; axis(limAxes);
-% %Reaching at T
-% subplot(1,2,2); hold on; axis off; title('Reaching cost (for t=T)');
-% surface(xx, yy, zz2-max(zz2(:)), 'EdgeColor','interp','FaceColor','interp'); 
-% plot(Mu0(1,2), Mu0(2,2),'.','markersize',30,'color',colMat(2,:));
-% plot(msh(1,:), msh(2,:),'-','linewidth',1,'color',[0 0 0]); %border
-% axis equal; axis(limAxes);
+%%% Plot value function for reaching costs
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%nbRes = 100;
+%limAxes = [-2.4 3.5 -0.6 3.8];
+%[xx, yy] = ndgrid(linspace(limAxes(1),limAxes(2),nbRes), linspace(limAxes(3),limAxes(4),nbRes));
+%x = [xx(:)'; yy(:)'];
+%msh = [min(x(1,:)), min(x(1,:)), max(x(1,:)), max(x(1,:)), min(x(1,:)); ...
+%	   min(x(2,:)), max(x(2,:)), max(x(2,:)), min(x(2,:)), min(x(2,:))];
+%%Reaching at T/2
+%f = f_reach2(x, param.Mu(1:2,1), param.A(:,:,1), param.sz);
+%z = sum(f.^2, 1);
+%zz = reshape(z, nbRes, nbRes);
+%%Reaching at T
+%f2 = f_reach2(x, param.Mu(1:2,2), param.A(:,:,2), param.sz);
+%z2 = sum(f2.^2, 1);
+%zz2 = reshape(z2, nbRes, nbRes);
+
+%colMat = lines(param.nbPoints);
+%h = figure('position',[820,10,860,400],'color',[1,1,1]); 
+%colormap(repmat(linspace(1,.4,64),3,1)');
+%%Reaching at T/2
+%subplot(1,2,1); hold on; axis off; title('Reaching cost (for t=T/2)');
+%surface(xx, yy, zz-max(zz(:)), 'EdgeColor','interp','FaceColor','interp'); 
+%contour(xx, yy, zz, [0:.4:max(zz(:))].^2,'color',[.3,.3,.3]); 
+%plot(param.Mu(1,1), param.Mu(2,1),'.','markersize',30,'color',colMat(1,:));
+%plot(msh(1,:), msh(2,:),'-','linewidth',1,'color',[0 0 0]); %border
+%%plotArm(x(:,tl(1)), param.l, [0; 0; -2], .2, [.6 .6 .6]);
+%axis equal; axis(limAxes);
+%%Reaching at T
+%subplot(1,2,2); hold on; axis off; title('Reaching cost (for t=T)');
+%surface(xx, yy, zz2-max(zz2(:)), 'EdgeColor','interp','FaceColor','interp'); 
+%contour(xx, yy, zz2, [0:.4:max(zz2(:))].^2,'color',[.3,.3,.3]); 
+%plot(param.Mu(1,2), param.Mu(2,2),'.','markersize',30,'color',colMat(2,:));
+%plot(msh(1,:), msh(2,:),'-','linewidth',1,'color',[0 0 0]); %border
+%axis equal; axis(limAxes);
+%%print('-dpng','graphs/DDP_manipulator01b.png');
 
-pause;
-close all;
+waitfor(h);
 end 
 
 % %%%%%%%%%%%%%%%%%%%%%%
@@ -213,13 +220,6 @@ end
 % 	end
 % end
 
-% %%%%%%%%%%%%%%%%%%%%%%
-% %Logarithmic map for R^2 x S^1 manifold
-% function e = logmap(f, f0)
-% 	e(1:2,:) = f(1:2,:) - f0(1:2,:);
-% 	e(3,:) = imag(log(exp(f0(3,:)*1i)' .* exp(f(3,:)*1i).'));
-% end
-
 %%%%%%%%%%%%%%%%%%%%%%
 %Logarithmic map for R^2 x S^1 manifold
 function e = logmap(f, f0)
@@ -229,46 +229,79 @@ end
 
 %%%%%%%%%%%%%%%%%%%%%%
 %Forward kinematics (in robot coordinate system)
-function f = fkine0(x, model)
-	T = tril(ones(size(x,1)));
-	f = [model.l * cos(T * x); ...
-		 model.l * sin(T * x); ...
-		 mod(sum(x,1)+pi, 2*pi) - pi]; %x1,x2,o (orientation as single Euler angle for planar robot)
+function f = fkin(x, param)
+	L = tril(ones(size(x,1)));
+	f = [param.l' * cos(L * x); ...
+	     param.l' * sin(L * x); ...
+	     mod(sum(x,1)+pi, 2*pi) - pi]; %f1,f2,f3 (f3 represents orientation as single Euler angle for planar robot)
 end
 
 %%%%%%%%%%%%%%%%%%%%%%
-%Jacobian with analytical computation (for single time step)
-function J = jacob0(x, model)
-	T = tril(ones(size(x,1)));
-	J = [-sin(T * x)' * T * diag(model.l); ...
-		  cos(T * x)' * T * diag(model.l); ...
-		  ones(1, size(x,1))]; %x1,x2,o
+%Jacobian of forward kinematics function with analytical computation
+function J = Jkin(x, param)
+	L = tril(ones(size(x,1)));
+	J = [-sin(L * x)' * diag(param.l) * L; ...
+	      cos(L * x)' * diag(param.l) * L; ...
+	      ones(1, size(x,1))]; %f1,f2,f3 (f3 represents orientation as single Euler angle for planar robot)
+end
+
+%%%%%%%%%%%%%%%%%%%%%%
+%Jacobian of forward kinematics function with numerical computation
+function J = Jkin_num(x, param)
+	e = 1E-6;
+	
+%	%Slow for-loop computation
+%	J = zeros(param.nbVarF, param.nbVarX);
+%	for n=1:size(x,1)
+%		xtmp = x;
+%		xtmp(n) = xtmp(n) + e;
+%		J(:,n) = (fkine0(xtmp, param) - fkine0(x, param)) / e;
+%	end
+	
+	%Fast matrix computation
+	X = repmat(x, [1, param.nbVarX]);
+	F1 = fkin(X, param);
+	F2 = fkin(X + eye(param.nbVarX) * e, param);
+	J = (F2 - F1) / e;
 end
 
 %%%%%%%%%%%%%%%%%%%%%%
 %Cost and gradient for a viapoints reaching task (in object coordinate system)
-function [f, J] = f_reach(x, model)
-% 	f = fkine0(x, model) - model.Mu; %Error by ignoring manifold
-	f = logmap(model.Mu, fkine0(x, model)); %Error by considering manifold
+function [f, J] = f_reach(x, param)
+% 	f = fkin(x, param) - param.Mu; %Error by ignoring manifold
+	f = logmap(param.Mu, fkin(x, param)); %Error by considering manifold
 	
 	J = []; 
 	for t=1:size(x,2)
-% 		f(:,t) = logmap(fkine0(x(:,t), model), model.Mu(:,t));
-		f(1:2,t) = model.A(:,:,t)' * f(1:2,t); %Object-centered FK
+		f(1:2,t) = param.A(:,:,t)' * f(1:2,t); %Object-centered FK
+		
+		Jtmp = Jkin(x(:,t), param);
+		%Jtmp = Jkin_num(x(:,t), param);
 		
-		Jtmp = jacob0(x(:,t), model);
-		Jtmp(1:2,:) = model.A(:,:,t)' * Jtmp(1:2,:); %Object-centered Jacobian
+		Jtmp(1:2,:) = param.A(:,:,t)' * Jtmp(1:2,:); %Object-centered Jacobian
 		
 		%Bounding boxes (optional)
-		for i=1:2
-			if abs(f(i,t)) < model.sz(i)
+		for i=1:length(param.fmax)
+			if abs(f(i,t)) < param.fmax(i)
 				f(i,t) = 0;
 				Jtmp(i,:) = 0;
 			else
-				f(i,t) = f(i,t) - sign(f(i,t)) * model.sz(i);
+				f(i,t) = f(i,t) - sign(f(i,t)) * param.fmax(i);
 			end
 		end
 		
 		J = blkdiag(J, Jtmp);
 	end
-end
\ No newline at end of file
+end
+
+%%%%%%%%%%%%%%%%%%%%%%
+%Cost in task space for a viapoints reaching task (for visualization)
+function f = f_reach2(f, Mu, A, sz)
+	f = A' * (f - repmat(Mu,1,size(f,2))); %Object-centered error
+	%Bounding boxes (optional)
+	for i=1:2
+		id = abs(f(i,:)) < sz(i);
+		f(i,id) = 0;
+		f(i,~id) = f(i,~id) - sign(f(i,~id)) * sz(i);
+	end
+end
diff --git a/demos/demo_OC_LQT03.m b/demos/demo_OC_LQT03.m
index 6a9af095c637cb43cf8ac88fc9c9f7408bed91d5..196b53b98d812abc8cb1937e7a691f5e59ace7e6 100644
--- a/demos/demo_OC_LQT03.m
+++ b/demos/demo_OC_LQT03.m
@@ -40,12 +40,12 @@ nbRepros = 1; %Number of reproductions in new situations
 nbNewRepros = 0; %Number of stochastically generated reproductions
 nbData = 200; %Number of datapoints
 
-model.nbStates = 6; %Number of Gaussians in the GMM
+model.nbStates = 4; %Number of Gaussians in the GMM
 model.nbVarPos = 2; %Dimension of position data (here: x1,x2)
-model.nbDeriv = 1; %Number of static & dynamic features (nbDeriv=1 for just x)
+model.nbDeriv = 2; %Number of static & dynamic features (nbDeriv=1 for just x)
 model.nbVar = model.nbVarPos * model.nbDeriv; %Dimension of state vector
 model.dt = 1E-2; %Time step duration
-model.rfactor = 1E-3;	%Control cost in LQR
+model.rfactor = 1E-4;	%Control cost in LQR
 
 %Control cost matrix
 R = eye(model.nbVarPos) * model.rfactor;
@@ -237,6 +237,7 @@ for n=1:nbSamples
 end	
 for n=1:nbRepros
 	plot(r(n).Data(1,:), r(n).Data(2,:), '-','linewidth',2,'color',[.8 0 0]);
+	plot(r(n).Data(1,:), r(n).Data(2,:), '.','markersize',12,'color',[.8 0 0]);
 end
 for n=1:nbNewRepros
 	plot(rnew(n).Data(1,:), rnew(n).Data(2,:), '-','linewidth',1,'color',max(min([0 .7+randn(1)*1E-1 0],1),0));
@@ -353,4 +354,4 @@ xlabel('$t$','fontsize',14,'interpreter','latex');
 
 % print('-dpng','graphs/demo_batchLQR03.png');
 pause;
-close all;
\ No newline at end of file
+close all;
diff --git a/demos/demo_OC_LQT_Lagrangian01.m b/demos/demo_OC_LQT_Lagrangian01.m
index b9e4f38b90ef75c3e870b211239a6771f3c37f30..3c70be3ce01607638197108f4af507cfa02c7028 100644
--- a/demos/demo_OC_LQT_Lagrangian01.m
+++ b/demos/demo_OC_LQT_Lagrangian01.m
@@ -152,5 +152,5 @@ end
 axis equal; 
 % print('-dpng','graphs/demo_MPC_Lagrangian01.png');
 
-pause;
-close all;
\ No newline at end of file
+pause(10);
+close all;
diff --git a/demos/demo_OC_LQT_ballistic01.m b/demos/demo_OC_LQT_ballistic01.m
index c2f0af6a73fdbf37115ebe4451d4b3433ba2ee00..c1cba3904eff2475c64eacade0a46e7746213af1 100644
--- a/demos/demo_OC_LQT_ballistic01.m
+++ b/demos/demo_OC_LQT_ballistic01.m
@@ -109,7 +109,7 @@ legend('boxoff');
 % imagesc(Su);
 % axis tight; axis equal; axis ij;
 
-pause;
+pause(10);
 close all;
 end
 
@@ -131,4 +131,4 @@ function [Su, Sx] = transferMatrices(A, B)
 		Su(id2,:) = squeeze(A(:,:,t)) * Su(id1,:);	
 		Su(id2,id3) = B(:,:,t);	
 	end
-end
\ No newline at end of file
+end
diff --git a/demos/demo_OC_LQT_fullQ01.m b/demos/demo_OC_LQT_fullQ01.m
index e33c71963551a7d0e57027c2714c7d72d39a54a1..d41671cfad4362e2452e204b98f54d292a33b248 100644
--- a/demos/demo_OC_LQT_fullQ01.m
+++ b/demos/demo_OC_LQT_fullQ01.m
@@ -39,7 +39,7 @@ nbData = 200; %Number of datapoints
 % nbData = 40; %Number of datapoints
 nbPoints = 3; %Number of keypoints
 nbVarPos = 2; %Dimension of position data (here: x1,x2)
-nbDeriv = 1; %Number of static and dynamic features (nbDeriv=2 for [x,dx] and u=ddx)
+nbDeriv = 2; %Number of static and dynamic features (nbDeriv=2 for [x,dx] and u=ddx)
 nbVar = nbVarPos * nbDeriv; %Dimension of state vector
 dt = 1E-2; %Time step duration
 rfactor = 1E-8; %dt^nbDeriv;	%Control cost in LQR
@@ -109,23 +109,23 @@ end
 % 	Q(id2(:,2), id2(:,1)) = -eye(nbVarPos)*1E0;
 % end
 
-% %Constraining the velocity before and after the keypoints to be correlated, effectively creating a straight line (version 2)
-% toff = 12;
-% for k=1:nbPoints-1
-% 	for t=1:toff
-% 		id2(1:2,1) = id(:,k) - t * nbVar + nbVarPos;
-% 		id2(1:2,2) = id(:,k) + t * nbVar + nbVarPos;
-% 		Q(id2(:,1), id2(:,1)) = eye(nbVarPos)*1E0;
-% 		Q(id2(:,2), id2(:,2)) = eye(nbVarPos)*1E0;
-% 		Q(id2(:,1), id2(:,2)) = -eye(nbVarPos)*1E0;
-% 		Q(id2(:,2), id2(:,1)) = -eye(nbVarPos)*1E0;
-% 	end
-% end
+%Constraining the velocity before and after the keypoints to be correlated, effectively creating a straight line (version 2)
+toff = 12;
+for k=1:nbPoints-1
+	for t=1:toff
+		id2(1:2,1) = id(:,k) - t * nbVar + nbVarPos;
+		id2(1:2,2) = id(:,k) + t * nbVar + nbVarPos;
+		Q(id2(:,1), id2(:,1)) = eye(nbVarPos)*1E0;
+		Q(id2(:,2), id2(:,2)) = eye(nbVarPos)*1E0;
+		Q(id2(:,1), id2(:,2)) = -eye(nbVarPos)*1E0;
+		Q(id2(:,2), id2(:,1)) = -eye(nbVarPos)*1E0;
+	end
+end
 
 % %Constraining the velocity before and after the keypoints to form a desired angle (version 1)
 % a = pi/2; %desired angle
 % V = [cos(a) -sin(a); sin(a) cos(a)]; %rotation matrix
-% toff = 4;
+% toff = 12;
 % for k=1:nbPoints-1
 % 	id2(1:2,1) = id(:,k) - toff * nbVar + nbVarPos;
 % 	id2(1:2,2) = id(:,k) + toff * nbVar + nbVarPos;
@@ -151,7 +151,7 @@ end
 % end
 
 % %Constraining the velocities when reaching the keypoints to be correlated (version 1)
-% toff = 0;
+% toff = 12;
 % for k=1:nbPoints-1
 % 	id2(1:2,1) = id(:,k) - toff * nbVar + nbVarPos;
 % 	id2(1:2,2) = id(:,k+1) - toff * nbVar + nbVarPos;
@@ -162,7 +162,7 @@ end
 % end
 	
 % %Constraining the velocities when reaching the keypoints to be correlated (version 2)
-% toff = 8;
+% toff = 12;
 % for k=1:nbPoints-1
 % 	for t=1:toff
 % 		id2(1:2,1) = id(:,k) - t * nbVar + nbVarPos;
@@ -192,13 +192,13 @@ end
 % 	Q(id2(:,2), id2(:,1)) = -eye(nbVarPos)*1E0;
 % end
 
-%Constraining R (same control command applied during a time interval)
-toff = 12;
-for k=1:nbPoints-1
-	tt = tl(k) + [-toff,toff];
-	id2 = tt(1) * nbVarPos +1 : tt(2) * nbVarPos;
-	R(id2,id2) = -1E-1 * kron(ones(2*toff), eye(nbVarPos)) + 2 * 1E-1 * eye(length(id2));
-end
+%%Constraining R (same control command applied during a time interval)
+%toff = 12;
+%for k=1:nbPoints-1
+%	tt = tl(k) + [-toff,toff];
+%	id2 = tt(1) * nbVarPos +1 : tt(2) * nbVarPos;
+%	R(id2,id2) = -1E-1 * kron(ones(2*toff), eye(nbVarPos)) + 2 * 1E-1 * eye(length(id2));
+%end
 
 
 
@@ -211,7 +211,7 @@ rx = reshape(Sx*x0+Su*u, nbVar, nbData); %Reshape data for plotting
 
 %% Plot 2D
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-figure('position',[10 10 800 800],'color',[1 1 1],'name','x1-x2 plot'); hold on; axis off;
+h = figure('position',[10 10 800 800],'color',[1 1 1],'name','x1-x2 plot'); hold on; axis off;
 plot(rx(1,:), rx(2,:), '-','linewidth',2,'color',[0 0 0]);
 plot(rx(1,1), rx(2,1), '.','markersize',35,'color',[0 0 0]);
 for k=1:nbPoints-1
@@ -220,7 +220,7 @@ for k=1:nbPoints-1
 end
 plot(MuQ(id(1,:)), MuQ(id(2,:)), '.','markersize',35,'color',[.8 0 0]);
 axis equal; 
-% print('-dpng','graphs/MPC_fullQ01a.png');
+% print('-dpng','graphs/LQT_fullQ01a.png');
 
 %Plot 1D
 figure; hold on;
@@ -239,5 +239,4 @@ xlabel('t'); ylabel('u_1');
 % axis equal; axis ij;
 % print('-dpng','graphs/MPC_fullQ_Q01b.png');
 
-pause;
-close all;
\ No newline at end of file
+waitfor(h);
diff --git a/demos/demo_OC_LQT_fullQ02.m b/demos/demo_OC_LQT_fullQ02.m
index b19be31e5c82df5766d487ab0e8ce3270eb53d9f..49e9d091ce37b10224966d82239776c87311389d 100644
--- a/demos/demo_OC_LQT_fullQ02.m
+++ b/demos/demo_OC_LQT_fullQ02.m
@@ -43,7 +43,7 @@ nbVarPos = 2 * nbAgents; %Dimension of position data (here: x1,x2)
 nbDeriv = 2; %Number of static and dynamic features (nbDeriv=2 for [x,dx] and u=ddx)
 nbVar = nbVarPos * nbDeriv; %Dimension of state vector
 dt = 1E-2; %Time step duration
-rfactor = 1E-8; %dt^nbDeriv;	%Control cost in LQR
+rfactor = 1E-8; %dt^nbDeriv; %Control cost in LQR
 R = speye((nbData-1)*nbVarPos) * rfactor; %Control cost matrix
 Rx = speye(nbData*nbVar) * rfactor;
 
@@ -86,35 +86,20 @@ for t=1:length(tl)
 	MuQ(id(:,t)) = rand(nbVarPos,1) - 0.5;
 end
 
-% %Constraining the two agents to meet at the end of the motion
-% tlm = nbData;
-% MuQ(id(3:4,1)) = MuQ(id(1:2,1)); %Proposed meeting point for the two agents
-% Q(id(1:2,1), id(3:4,1)) = -eye(2)*1E0;
-% Q(id(3:4,1), id(1:2,1)) = -eye(2)*1E0;
-
 % %Constraining the two agents to meet in the middle of the motion
 % tlm = nbData/2;
 % idm = [1:nbVarPos] + (tlm-1) * nbVar;
-% % MuQ(idm(1:2)) = [1; 1]; %Proposed meeting point for the two agents (optional)
-% % MuQ(idm(3:4)) = MuQ(idm(1:2)); 
-% Q(idm(1:2), idm(1:2)) = eye(2)*1E0;
-% Q(idm(3:4), idm(3:4)) = eye(2)*1E0;
-% Q(idm(1:2), idm(3:4)) = -eye(2)*1E0;
-% Q(idm(3:4), idm(1:2)) = -eye(2)*1E0;
+% Q(idm,idm) = [eye(2), -eye(2); -eye(2), eye(2)];
 
-%Constraining the two agents to be at the same position at time t1 and t2
+%Constraining the two agents to be at a given position with an offset at time t1 and t2
 t1 = nbData/2;
 t2 = t1+50;
 idm(1:2) = [1:2] + (t1-1) * nbVar;
 idm(3:4) = [3:4] + (t2-1) * nbVar;
-Q(idm(1:2), idm(1:2)) = eye(2)*1E0;
-Q(idm(3:4), idm(3:4)) = eye(2)*1E0;
-Q(idm(1:2), idm(3:4)) = -eye(2)*1E0;
-Q(idm(3:4), idm(1:2)) = -eye(2)*1E0;
+Q(idm,idm) = [eye(2), -eye(2); -eye(2), eye(2)];
 MuQ(idm(1:2)) = [0; 0]; 
 MuQ(idm(3:4)) = MuQ(idm(1:2)) + [.05; 0]; %Meeting point with desired offset between the two agents 
 
-
 % %Constraining the two agents to meet at a given angle at the end of the motion
 % %Proposed meeting point for the two agents
 % tlm = nbData;
@@ -187,7 +172,7 @@ end
 
 %% Plot 2D
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-figure('position',[10 10 1200 600]); 
+h = figure('position',[10 10 2400 600]); 
 subplot(1,4,1); hold on; axis off;
 % set(0,'DefaultAxesLooseInset',[1,1,1,1]*1E2);
 % set(gca,'LooseInset',[1,1,1,1]*1E2);
@@ -248,5 +233,4 @@ end
 % plot([xlim(1,1),xlim(1,1:2),xlim(1,2:-1:1),xlim(1,1)], [xlim(2,1:2),xlim(2,2:-1:1),xlim(2,1),xlim(2,1)],'-','linewidth',2,'color',[0,0,0]);
 % axis equal; axis ij;
 
-pause;
-close all;
\ No newline at end of file
+waitfor(h);
diff --git a/demos/demo_OC_LQT_fullQ03.m b/demos/demo_OC_LQT_fullQ03.m
index 2c5f41425ec2f35bf54a00e4a16f9349cac6920d..fc8ba3f09d8d653b11d2b249d69ba77216a2561a 100644
--- a/demos/demo_OC_LQT_fullQ03.m
+++ b/demos/demo_OC_LQT_fullQ03.m
@@ -117,13 +117,13 @@ rx = reshape(Sx*x0+Su*u, nbVar, nbData); %Reshape data for plotting
 
 %% Plot 2D
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-figure('position',[10 10 800 800],'color',[1 1 1],'name','x1-x2 plot'); hold on; axis off;
+h = figure('position',[10 10 800 800],'color',[1 1 1],'name','x1-x2 plot'); hold on; axis off;
 
 %Agent 1
 % for t=1:nbData
 % 	plotGMM(rx(1:2,t), xSigma(nbVar*(t-1)+[1,2],nbVar*(t-1)+[1,2]).*1E-8, [.2 .2 .2], .03); %Plot uncertainty
 % end	
-h(1) = plot(rx(1,:), rx(2,:), '-','linewidth',2,'color',[0 0 0]);
+hf(1) = plot(rx(1,:), rx(2,:), '-','linewidth',2,'color',[0 0 0]);
 plot(rx(1,1), rx(2,1), '.','markersize',25,'color',[0 0 0]);
 plot2DArrow(rx(1:2,1), u(1:2).*1E-2, [.8 0 0]);
 % plot(rx(1,end-3), rx(2,end-2), '.','markersize',25,'color',[0 .6 0]); %meeting point
@@ -133,12 +133,12 @@ plot2DArrow(rx(1:2,1), u(1:2).*1E-2, [.8 0 0]);
 % for t=1:nbData
 % 	plotGMM(rx(3:4,t), xSigma(nbVar*(t-1)+[3,4],nbVar*(t-1)+[3,4]).*1E-8, [.2 .2 .2], .03); %Plot uncertainty
 % end	
-h(2) = plot(rx(3,:), rx(4,:), '-','linewidth',2,'color',[.6 .6 .6]);
+hf(2) = plot(rx(3,:), rx(4,:), '-','linewidth',2,'color',[.6 .6 .6]);
 plot(rx(3,1), rx(4,1), '.','markersize',25,'color',[.6 .6 .6]);
 plot2DArrow(rx(3:4,1), u(3:4).*1E-2, [.8 0 0]);
-h(3) = plot(rx(3,tEvent+1), rx(4,tEvent+1), '.','markersize',25,'color',[.4 .8 .4]); %meeting point
+hf(3) = plot(rx(3,tEvent+1), rx(4,tEvent+1), '.','markersize',25,'color',[.4 .8 .4]); %meeting point
 
-legend(h,{'Agent 1','Agent 2','End point'});
+legend(hf,{'Agent 1','Agent 2','End point'});
 % plot(MuQ(id(3)), MuQ(id(4)), '.','markersize',35,'color',[1 .6 .6]);
 axis equal;
 % print('-dpng','graphs/MPC_fullQ03a.png');
@@ -151,8 +151,7 @@ axis equal;
 % set(gca,'xtick',[1,size(Q,1)],'ytick',[1,size(Q,1)]);
 % axis square; axis([1 size(Q,1) 1 size(Q,1)]); shading flat;
 
-pause;
-close all;
+waitfor(h);
 end
 
 %%%%%%%%%%%%%%%%%%%%%%%%%
@@ -169,4 +168,4 @@ function [Su, Sx] = transferMatrices(A, B)
 		Su(id2,:) = squeeze(A(:,:,t)) * Su(id1,:);	
 		Su(id2,id3) = B(:,:,t);	
 	end
-end
\ No newline at end of file
+end
diff --git a/demos/demo_OC_LQT_fullQ04.m b/demos/demo_OC_LQT_fullQ04.m
index 9ab144e73ff0c3f56e764eb6c7c704596d5d5688..b993f543d7410f824060d679106d99ea051aa090 100644
--- a/demos/demo_OC_LQT_fullQ04.m
+++ b/demos/demo_OC_LQT_fullQ04.m
@@ -144,8 +144,8 @@ Q(id(3:4), id(1:2)) = -eye(2);
 %% Batch LQT reproduction
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 x0 = [x01; zeros(2,1); m(1)*g; ...
-			x02; zeros(2,1); m(2)*g; ...
-			x01; zeros(2,1); m(3)*g]; 
+      x02; zeros(2,1); m(2)*g; ...
+      x01; zeros(2,1); m(3)*g]; 
 u = (Su' * Q * Su + R) \ Su' * Q * (MuQ - Sx * x0); 
 rx = reshape(Sx*x0+Su*u, nbVar, nbData); %Reshape data for plotting
 
@@ -155,7 +155,7 @@ rx = reshape(Sx*x0+Su*u, nbVar, nbData); %Reshape data for plotting
 
 %% 2D plot 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-figure('position',[10 10 1200 800],'color',[1 1 1]); hold on; axis off;
+h = figure('position',[10 10 1200 800],'color',[1 1 1]); hold on; axis off;
 % %Uncertainty
 % for t=1:nbData
 % 	plotGMM(rx(1:2,t), xSigma(nbVar*(t-1)+[1,2],nbVar*(t-1)+[1,2])*3E-7, [0 0 0], .04); %Agent 1 (left hand)
@@ -168,31 +168,31 @@ figure('position',[10 10 1200 800],'color',[1 1 1]); hold on; axis off;
 % end
 
 %Agents
-h(1) = plot(rx(1,:), rx(2,:), '-','linewidth',4,'color',[0 0 0]); %Agent 1 (left hand)
-h(2) = plot(rx(7,:), rx(8,:), '-','linewidth',4,'color',[.6 .6 .6]); %Agent 2 (right hand)
-h(3) = plot(rx(13,:), rx(14,:), ':','linewidth',4,'color',[.8 .4 0]); %Agent 3 (ball)
+hf(1) = plot(rx(1,:), rx(2,:), '-','linewidth',4,'color',[0 0 0]); %Agent 1 (left hand)
+hf(2) = plot(rx(7,:), rx(8,:), '-','linewidth',4,'color',[.6 .6 .6]); %Agent 2 (right hand)
+hf(3) = plot(rx(13,:), rx(14,:), ':','linewidth',4,'color',[.8 .4 0]); %Agent 3 (ball)
 
 %Events
-h(4) = plot(rx(1,1), rx(2,1), '.','markersize',40,'color',[0 0 0]); %Initial position (left hand)
-h(5) = plot(rx(7,1), rx(8,1), '.','markersize',40,'color',[.6 .6 .6]); %Initial position (right hand)
-h(6) = plot(rx(1,tEvent(1)), rx(2,tEvent(1)), '.','markersize',40,'color',[0 .6 0]); %Release of ball
-h(7) = plot(rx(7,tEvent(2)), rx(8,tEvent(2)), '.','markersize',40,'color',[0 0 .8]); %Hitting of ball
-h(8) = plot(xTar(1), xTar(2), '.','markersize',40,'color',[.8 0 0]); %Ball target
+hf(4) = plot(rx(1,1), rx(2,1), '.','markersize',40,'color',[0 0 0]); %Initial position (left hand)
+hf(5) = plot(rx(7,1), rx(8,1), '.','markersize',40,'color',[.6 .6 .6]); %Initial position (right hand)
+hf(6) = plot(rx(1,tEvent(1)), rx(2,tEvent(1)), '.','markersize',40,'color',[0 .6 0]); %Release of ball
+hf(7) = plot(rx(7,tEvent(2)), rx(8,tEvent(2)), '.','markersize',40,'color',[0 0 .8]); %Hitting of ball
+hf(8) = plot(xTar(1), xTar(2), '.','markersize',40,'color',[.8 0 0]); %Ball target
 plot2DArrow(rx(1:2,tEvent(1)), diff(rx(1:2,tEvent(1):tEvent(1)+1),1,2)*12E0, [0 .6 0], 4, .01);
 plot2DArrow(rx(7:8,tEvent(2)), diff(rx(7:8,tEvent(2):tEvent(2)+1),1,2)*12E0, [0 0 .8], 4, .01);
 axis equal; axis([1, 2.2, -0.3, 0.2]); 
 
-% text(rx(1,1)+.01, rx(2,1)-.01,'$t=0$','interpreter','latex','fontsize',20);
-% text(rx(1,1)+.01, rx(2,1)-.03,'$t=\frac{3T}{4}$','interpreter','latex','fontsize',20);
-% text(rx(7,1)+.01, rx(8,1)+.02,'$t=0$','interpreter','latex','fontsize',20);
-% text(rx(7,1)+.01, rx(8,1),'$t=\frac{3T}{4}$','interpreter','latex','fontsize',20);
-% text(rx(1,tEvent(1))-.01, rx(2,tEvent(1))-.02,'$t=\frac{T}{4}$','interpreter','latex','fontsize',20);
-% text(rx(13,tEvent(2))+.01, rx(14,tEvent(2))+.01,'$t=\frac{T}{2}$','interpreter','latex','fontsize',20);
-% text(xTar(1)+.02, xTar(2),'$t=T$','interpreter','latex','fontsize',20);
-% legend(h, {'Left hand motion (Agent 1)','Right hand motion (Agent 2)','Ball motion (Agent 3)', ...
-% 	'Left hand initial point','Right hand initial point','Ball releasing point','Ball hitting point','Ball target'}, 'fontsize',20,'location','northwest'); 
-% legend('boxoff');
-% print('-dpng','graphs/MPC_tennisServe01.png');
+text(rx(1,1)+.01, rx(2,1)-.01,'$t=0$','interpreter','latex','fontsize',20);
+text(rx(1,1)+.01, rx(2,1)-.03,'$t=\frac{3T}{4}$','interpreter','latex','fontsize',20);
+text(rx(7,1)+.01, rx(8,1)+.02,'$t=0$','interpreter','latex','fontsize',20);
+text(rx(7,1)+.01, rx(8,1),'$t=\frac{3T}{4}$','interpreter','latex','fontsize',20);
+text(rx(1,tEvent(1))-.01, rx(2,tEvent(1))-.02,'$t=\frac{T}{4}$','interpreter','latex','fontsize',20);
+text(rx(13,tEvent(2))+.01, rx(14,tEvent(2))+.01,'$t=\frac{T}{2}$','interpreter','latex','fontsize',20);
+text(xTar(1)+.02, xTar(2),'$t=T$','interpreter','latex','fontsize',20);
+legend(hf, {'Left hand motion (Agent 1)','Right hand motion (Agent 2)','Ball motion (Agent 3)', ...
+'Left hand initial point','Right hand initial point','Ball releasing point','Ball hitting point','Ball target'}, 'fontsize',20,'location','northwest'); 
+legend('boxoff');
+%print('-dpng','graphs/iLQR_tennisServe01.png');
 
 
 % %% 2D animated plot 
@@ -326,8 +326,7 @@ axis equal; axis([1, 2.2, -0.3, 0.2]);
 % set(gca,'xtick',[1,size(Q,1)],'ytick',[1,size(Q,1)]);
 % axis square; axis([1 size(Q,1) 1 size(Q,1)]); shading flat;
 
-pause;
-close all;
+waitfor(h);
 end
 
 %%%%%%%%%%%%%%%%%%%%%%%%%
@@ -344,4 +343,4 @@ function [Su, Sx] = transferMatrices(A, B)
 		Su(id2,:) = squeeze(A(:,:,t)) * Su(id1,:);	
 		Su(id2,id3) = B(:,:,t);	
 	end
-end		
\ No newline at end of file
+end		
diff --git a/demos/demo_OC_LQT_recursive_augmSigma01.m b/demos/demo_OC_LQT_recursive_augmSigma01.m
index 93fed8540554036d1f596114c5a9a4cc0460554d..f84b78e6f1a2cb4084c586eb681cf45e9e253eda 100644
--- a/demos/demo_OC_LQT_recursive_augmSigma01.m
+++ b/demos/demo_OC_LQT_recursive_augmSigma01.m
@@ -43,7 +43,7 @@ model.nbStates = 5; %Number of Gaussians in the GMM
 model.nbVarPos = 2; %Dimension of position data (here: x1,x2)
 model.nbDeriv = 2; %Number of static and dynamic features (nbDeriv=2 for [x,dx] and u=ddx)
 model.nbVar = model.nbVarPos * model.nbDeriv; %Dimension of state vector
-model.dt = 0.01; %Time step duration
+model.dt = 1E-2; %Time step duration
 %model.rfactor = 0.1 * model.dt^model.nbDeriv;	%Control cost in LQR
 model.rfactor = 1E-6;	%Control cost in LQR
 
@@ -141,7 +141,7 @@ for t=nbData-1:-1:1
 	Q = inv(model.Sigma(:,:,qList(t)));
 	P(:,:,t) = Q - A' * (P(:,:,t+1) * B / (B' * P(:,:,t+1) * B + R) * B' * P(:,:,t+1) - P(:,:,t+1)) * A;
 end
-%Reproduction with only feedback (FB) on augmented state
+%Reproduction 
 for n=1:nbRepros
 	if n==1
 		x = [Data(:,1); 1];
@@ -151,8 +151,13 @@ for n=1:nbRepros
 	r(n).x0 = x;
 	for t=1:nbData
 		r(n).x(:,t) = x; %Log data
-		K = (B' * P(:,:,t) * B + R) \ B' * P(:,:,t) * A; %FB term
-		u = -K * x; %Acceleration command with FB on augmented state (resulting in FB and FF terms)
+		Ka = (B' * P(:,:,t) * B + R) \ B' * P(:,:,t) * A; %FB term
+		
+		u = -Ka * x; %Feedback control on augmented state (resulting in feedback and feedforward terms on state)
+%		K = Ka(:,1:model0.nbVar);
+%		uff = -Ka(:,end) - K * model0.Mu(:,qList(t));
+%		u = K * (model0.Mu(:,qList(t)) - x(1:end-1)) + uff; %Acceleration command with FB and FF terms computed explicitly from Ka
+		
 		x = A * x + B * u; %Update of state vector
 	end
 end
@@ -173,8 +178,8 @@ for n=1:nbRepros
 	for t=1:nbData
 		r2(n).x(:,t) = x; %Log data
 		K = (B0' * P(:,:,t) * B0 + R) \ B0' * P(:,:,t) * A0; %FB term
-		M = -(B0' * P(:,:,t) * B0 + R) \ B0' * (P(:,:,t) * (A0 * model0.Mu(:,qList(t)) - model0.Mu(:,qList(t))) + d(:,t)); %FF term
-		u = K * (model0.Mu(:,qList(t)) - x) + M; %Acceleration command with FB and FF terms
+		uff = -(B0' * P(:,:,t) * B0 + R) \ B0' * (P(:,:,t) * (A0 * model0.Mu(:,qList(t)) - model0.Mu(:,qList(t))) + d(:,t)); %FF term
+		u = K * (model0.Mu(:,qList(t)) - x) + uff; %Acceleration command with FB and FF terms
 		x = A0 * x + B0 * u; %Update of state vector
 	end
 end
@@ -183,7 +188,7 @@ end
 %% Plot
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %Plot position
-figure('position',[10 10 800 800],'color',[1 1 1]); axis off; hold on; 
+h = figure('position',[10 10 800 800],'color',[1 1 1]); axis off; hold on; 
 plotGMM(model0.Mu(1:2,:), model0.Sigma(1:2,1:2,:), [0.5 0.5 0.5], .3);
 for n=1:nbSamples
 	plot(Data(1,(n-1)*nbData+1:n*nbData), Data(2,(n-1)*nbData+1:n*nbData), '-','color',[.7 .7 .7]);
@@ -193,7 +198,7 @@ for n=1:nbRepros
 	h(2) = plot(r2(n).x(1,:), r2(n).x(2,:), '--','linewidth',2,'color',[0 .8 0]);
 end
 axis equal; 
-legend(h,'LQR with augmented state space',' LQT with FB and FF terms');
+legend(h,'LQR with augmented state space',' LQT with FB and FF terms','fontsize',26);
 
 % %Plot velocity
 % figure('position',[1020 10 1000 1000],'color',[1 1 1]); hold on; 
@@ -211,5 +216,6 @@ legend(h,'LQR with augmented state space',' LQT with FB and FF terms');
 % xlabel('dx_1'); ylabel('dx_2');
 
 % print('-dpng','graphs/demo_iterativeLQR_augmSigma01.png');
-pause;
-close all;
\ No newline at end of file
+%pause;
+%close all;
+waitfor(h);
diff --git a/demos/demo_Riemannian_S3_GMM01.m b/demos/demo_Riemannian_S3_GMM01.m
index c7d36f0763f9b0a7a4211136a2dee3be55a24a43..05bc9db925c3af0ba545887c15dda5752ffd81ea 100644
--- a/demos/demo_Riemannian_S3_GMM01.m
+++ b/demos/demo_Riemannian_S3_GMM01.m
@@ -154,14 +154,14 @@ function Log = logfct(x)
 % 	scale = acos(x(3,:)) ./ sqrt(1-x(3,:).^2);
 	scale = acoslog(x(1,:)) ./ sqrt(1-x(1,:).^2);
 	scale(isnan(scale)) = 1;
-	Log = [x(2,:) .* scale; x(3,:) .* scale; x(4,:) .* scale];
+	Log = [x(2,:) * scale; x(3,:) * scale; x(4,:) * scale];
 end
 
 function Q = QuatMatrix(q)
 	Q = [q(1) -q(2) -q(3) -q(4);
-			 q(2)  q(1) -q(4)  q(3);
-			 q(3)  q(4)  q(1) -q(2);
-			 q(4) -q(3)  q(2)  q(1)];
+	     q(2)  q(1) -q(4)  q(3);
+	     q(3)  q(4)  q(1) -q(2);
+	     q(4) -q(3)  q(2)  q(1)];
 end				 
 
 %Arcosine redefinition to make sure the distance between antipodal quaternions is zero (2.50 from Dubbelman's Thesis)
@@ -194,4 +194,4 @@ function Ac = transp(g,h)
 	uv = vm / mn;
 	Rpar = eye(4) - sin(mn)*(g*uv') - (1-cos(mn))*(uv*uv');	
 	Ac = E' * QuatMatrix(h)' * Rpar * QuatMatrix(g) * E; %Transportation operator from g to h 
-end
\ No newline at end of file
+end
diff --git a/demos/demo_Riemannian_S3_interp01.m b/demos/demo_Riemannian_S3_interp01.m
index 1420ff2872324fbe04ee608e291360275eb55f78..5bd78ab465991fa2a197efa15f2ac3f5e6bf8c5c 100644
--- a/demos/demo_Riemannian_S3_interp01.m
+++ b/demos/demo_Riemannian_S3_interp01.m
@@ -195,12 +195,12 @@ end
 
 function Q = QuatMatrix(q)
 	Q = [q(1) -q(2) -q(3) -q(4);
-			 q(2)  q(1) -q(4)  q(3);
-			 q(3)  q(4)  q(1) -q(2);
-			 q(4) -q(3)  q(2)  q(1)];
-end				 
+	     q(2)  q(1) -q(4)  q(3);
+	     q(3)  q(4)  q(1) -q(2);
+	     q(4) -q(3)  q(2)  q(1)];
+end					 
 
-% Arcosine re-defitinion to make sure the distance between antipodal quaternions is zero (2.50 from Dubbelman's Thesis)
+% Arcosine redefinition to make sure the distance between antipodal quaternions is zero (2.50 from Dubbelman's Thesis)
 function acosx = acoslog(x)
 	for n=1:size(x,2)
 		% sometimes abs(x) is not exactly 1.0
@@ -230,4 +230,4 @@ function Ac = transp(g,h)
 	uv = vm / mn;
 	Rpar = eye(4) - sin(mn)*(g*uv') - (1-cos(mn))*(uv*uv');	
 	Ac = E' * QuatMatrix(h)' * Rpar * QuatMatrix(g) * E; %Transportation operator from g to h 
-end
\ No newline at end of file
+end
diff --git a/demos/demo_Riemannian_Sd_interp01.m b/demos/demo_Riemannian_Sd_interp01.m
index 96d736eeef5867e60e7fd9067fb46cad8e5246ad..2c90453548ef70c869c44578608f60d5fa766dd3 100644
--- a/demos/demo_Riemannian_Sd_interp01.m
+++ b/demos/demo_Riemannian_Sd_interp01.m
@@ -167,12 +167,13 @@ function Ac = transp(x1, x2, t)
 end
 
 %As in https://ronnybergmann.net/mvirt/manifolds/Sn.html (gives the same result as transp(x1,x2,t)*v)
+%https://towardsdatascience.com/geodesic-regression-d0334de2d9d8
 function v = transp2(x, y, v)
 	d = acos(x'*y);
 	v = v - (logmap(y,x) + logmap(x,y)) .* (logmap(y,x)' * v) ./ d.^2;
 end
 
-% function x = geodesic(u, x0, t)
+function x = geodesic(u, x0, t)
 	normu = norm(u,'fro');
 	x = x0 * cos(normu*t) + u./normu * sin(normu*t);
-end
\ No newline at end of file
+end
diff --git a/demos/demo_TPGMM_teleoperation01.m b/demos/demo_TPGMM_teleoperation01.m
index 1b50462c09b967a4420a0e6388e2b78a3cd84019..8ac4170a3bf6c4189f0295cabae81ed3b0a73c35 100644
--- a/demos/demo_TPGMM_teleoperation01.m
+++ b/demos/demo_TPGMM_teleoperation01.m
@@ -1,6 +1,8 @@
 function demo_TPGMM_teleoperation01
 % Time-invariant task-parameterized GMM applied to a teleoperation task (position and orientation).
 %
+% Octave users should use: pkg load image, pkg load statistics
+%
 % If this code is useful for your research, please cite the related publication:
 % @article{Calinon16JIST,
 %   author="Calinon, S.",
@@ -49,7 +51,7 @@ model.rfactor = 5E-4;	%Control cost in LQR
 model.tfactor = 1E-2;	%Teleoperator cost
 R = eye(model.nbVarOut) * model.rfactor; %Control cost matrix
 
-imgVis = 1; %Visualization option
+imgVis = 0; %Visualization option
 if imgVis==1
 	global img alpha
 	[img, ~, alpha] = imread('data/drill06.png');
@@ -396,4 +398,4 @@ if strcmp(muoseside,'normal')==1
 end
 if strcmp(muoseside,'alt')==1
 	setappdata(gcf,'mb',1);
-end
\ No newline at end of file
+end
diff --git a/demos/demo_ergodicControl_1D01.m b/demos/demo_ergodicControl_1D01.m
index a2e1ca4f820c6b9e7a4a323bc1353ad65a91e153..a488020a3d1de39f805c0eca96548458262d684c 100644
--- a/demos/demo_ergodicControl_1D01.m
+++ b/demos/demo_ergodicControl_1D01.m
@@ -294,5 +294,5 @@ xlabel('$x$','interpreter','latex','fontsize',28);
 % % 	id = id + 1;
 % end
 
-pause;
-close all;
\ No newline at end of file
+pause(10);
+close all;
diff --git a/demos/demo_grabData01.m b/demos/demo_grabData01.m
index 5587bbf4d1d6131237ecd26e88e753083d2657e2..c9c97a913c006469d1920de7f33babb3761071e2 100644
--- a/demos/demo_grabData01.m
+++ b/demos/demo_grabData01.m
@@ -43,7 +43,7 @@ nbSamples = 5;
 
 %% Collect data
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-disp('Ude left mouse button to draw trajectories, use right mouse button to quit');
+disp('Use left mouse button to draw trajectories, use right mouse button to quit');
 Data = grabDataFromCursor(nbData);
 nbSamples = size(Data,2) / nbData;
 for n=1:nbSamples
@@ -68,4 +68,4 @@ axis equal; set(gca,'Xtick',[]); set(gca,'Ytick',[]);
 
 %print('-dpng','graphs/demo_grabData01.png');
 pause;
-close all;
\ No newline at end of file
+close all;
diff --git a/demos/demo_manipulabilityTracking_mainTask01.m b/demos/demo_manipulabilityTracking_mainTask01.m
index 2fbebb4b681a2706afcad4f67d2d61d6f9ae5503..3a8c2279103692dd2483fd5de580f2f745d129e2 100644
--- a/demos/demo_manipulabilityTracking_mainTask01.m
+++ b/demos/demo_manipulabilityTracking_mainTask01.m
@@ -1,6 +1,6 @@
 function demo_manipulabilityTracking_mainTask01
 % Matching of a desired manipulability ellipsoid as the main task (no desired position) 
-% using the formulation with the manipulability Jacobien (Mandel notation).
+% using the formulation with the manipulability Jacobian (Mandel notation).
 %
 % This demo requires the robotics toolbox RTB10 (http://petercorke.com/wordpress/toolboxes/robotics-toolbox).
 % First run 'startup_rvc' from the robotics toolbox.
@@ -57,10 +57,9 @@ J = robot.jacob0(q'); % Symbolic Jacobian
 % Define the desired manipulability
 q_Me_d = [pi/16 ; pi/4 ; pi/8 ; -pi/8]; % task 1
 % q_Me_d = [pi/2 ; -pi/6; -pi/2 ; -pi/2]; % task 2
-
 J_Me_d = robot.jacob0(q_Me_d); % Current Jacobian
 J_Me_d = J_Me_d(1:2,:);
-Me_d = (J_Me_d*J_Me_d');
+Me_d = J_Me_d * J_Me_d';
 
 
 %% Testing Manipulability Transfer
@@ -74,8 +73,7 @@ it = 1; % Iterations counter
 h1 = [];
 gmm_c = [];
 
-% Initial end-effector position (compatibility with 9.X and 10.X versions
-% of robotics toolbox)
+% Initial end-effector position (compatibility with 9.X and 10.X versions of robotics toolbox)
 Htmp = robot.fkine(q0); % Forward Kinematics
 if isobject(Htmp) % SE3 object verification
 	x0 = Htmp.t(1:2);
@@ -89,12 +87,12 @@ figure('position',[10 10 1000 450],'color',[1 1 1]);
 while( it < nbIter )
 	delete(h1);
 	
-	Jt = robot.jacob0(qt); % Current Jacobian
-    Jt_full = Jt;
-	Jt = Jt(1:2,:);
 	Htmp = robot.fkine(qt); % Forward Kinematics (needed for plots)
-	Me_ct = (Jt*Jt'); % Current manipulability
+	Jt_full = robot.jacob0(qt); % Current Jacobian
+    Jt = Jt_full(1:2,:);
+	Me_ct = Jt * Jt'; % Current manipulability
 	
+	% Log data
     Me_track(:,:,it) = Me_ct;
 	qt_track(:,it) = qt;
 	
@@ -109,24 +107,21 @@ while( it < nbIter )
 	Jm_t = compute_red_manipulability_Jacobian(Jt_full, 1:2);
 	
 	% Compute desired joint velocities
-	M_diff = logmap(Me_d,Me_ct);
-	dq_T1 = pinv(Jm_t)*Km*symmat2vec(M_diff);
+	M_diff = logmap(Me_d, Me_ct);
+	dq_T1 = pinv(Jm_t) * Km * symmat2vec(M_diff);
 	
 	% Plotting robot and manipulability ellipsoids
-	subplot(1,2,1); 
-	hold on;
+	subplot(1,2,1); hold on;
 	if(it == 1)
 		plotGMM(xt, 1E-2*Me_d, [0.2 0.8 0.2], .4); % Scaled matrix!
 	end
 	h1 = plotGMM(xt, 1E-2*Me_ct, [0.8 0.2 0.2], .4); % Scaled matrix!
 	colTmp = [1,1,1] - [.8,.8,.8] * (it+10)/nbIter;
 	plotArm(qt, ones(nbDOFs,1)*armLength, [0; 0; it*0.1], .2, colTmp);
-	axis square;
-	axis equal;
+	axis square; axis equal;
 	xlabel('x_1'); ylabel('x_2');
 	
-	subplot(1,2,2); 
-	hold on; axis equal;
+	subplot(1,2,2); hold on; axis equal;
 	delete(gmm_c);
 	gmm_c = plotGMM([0;0], 1E-2*Me_ct, [0.8 0.2 0.2], .1); % Scaled matrix!
 	if(it == 1)
@@ -135,7 +130,7 @@ while( it < nbIter )
 	drawnow;
 	
 	% Updating joint position
-	qt = qt + (dq_T1)*dt;
+	qt = qt + (dq_T1) * dt;
 	it = it + 1; % Iterations++
 end
 
@@ -201,23 +196,21 @@ xlabel('$t$','fontsize',22,'Interpreter','latex'); ylabel('$d$','fontsize',22,'I
 end
 
 %%%%%%%%%%%%%%%%%%
+% Compute the force manipulability Jacobian (symbolic) in the form of a matrix using Mandel notation
 function Jm_red = compute_red_manipulability_Jacobian(J, taskVar)
-	% Compute the force manipulability Jacobian (symbolic) in the form of a
-	% matrix using Mandel notation.
 	if nargin < 2
-			taskVar = 1:6;
+		taskVar = 1:6;
 	end
-
 	Jm = compute_manipulability_Jacobian(J);
 	Jm_red = [];
-	for i = 1:size(Jm,3)
+	for i=1:size(Jm,3)
 		Jm_red = [Jm_red, symmat2vec(Jm(taskVar,taskVar,i))];
 	end
 end
 
 %%%%%%%%%%%%%%%%%%
+% Compute the force manipulability Jacobian (symbolic)
 function Jm = compute_manipulability_Jacobian(J)
-	% Compute the force manipulability Jacobian (symbolic).
 	J_grad = compute_joint_derivative_Jacobian(J);
 	Jm = tmprod(J_grad,J,2) + tmprod(permute(J_grad,[2,1,3]),J,1);
 	% mat_mult = kdlJacToArma(J)*reshape( arma::mat(permDerivJ.memptr(), permDerivJ.n_elem, 1, false), columns, columns*rows);
@@ -225,57 +218,56 @@ function Jm = compute_manipulability_Jacobian(J)
 end
 
 %%%%%%%%%%%%%%%%%%
+% Compute the Jacobian derivative w.r.t joint angles (hybrid Jacobian representation). Ref: H. Bruyninck and J. de Schutter, 1996
 function J_grad = compute_joint_derivative_Jacobian(J)
-	% Compute the Jacobian derivative w.r.t joint angles (hybrid Jacobian
-	% representation). Ref: H. Bruyninck and J. de Schutter, 1996
 	nb_rows = size(J,1); % task space dim.
 	nb_cols = size(J,2); % joint space dim.
 	J_grad = zeros(nb_rows, nb_cols, nb_cols);
-	for i = 1:nb_cols
-		for j = 1:nb_cols
+	for i=1:nb_cols
+		for j=1:nb_cols
 			J_i = J(:,i);
 			J_j = J(:,j);
 			if j < i
-				J_grad(1:3,i,j) = cross(J_j(4:6,:),J_i(1:3,:));
-				J_grad(4:6,i,j) = cross(J_j(4:6,:),J_i(4:6,:));
+				J_grad(1:3,i,j) = cross(J_j(4:6,:), J_i(1:3,:));
+				J_grad(4:6,i,j) = cross(J_j(4:6,:), J_i(4:6,:));
 			elseif j > i
-				J_grad(1:3,i,j) = -cross(J_j(1:3,:),J_i(4:6,:));
+				J_grad(1:3,i,j) = -cross(J_j(1:3,:), J_i(4:6,:));
 			else
-				J_grad(1:3,i,j) = cross(J_i(4:6,:),J_i(1:3,:));
+				J_grad(1:3,i,j) = cross(J_i(4:6,:), J_i(1:3,:));
 			end
 		end
 	end
 end
 
 %%%%%%%%%%%%%%%%%%
-function U = logmap(X,S)
-	% Logarithm map (SPD manifold)
+% Logarithm map (SPD manifold)
+function U = logmap(X, S)	
 	N = size(X,3);
 	for n = 1:N
 	% 	U(:,:,n) = S^.5 * logm(S^-.5 * X(:,:,n) * S^-.5) * S^.5;
 	% 	tic
-	% 	U(:,:,n) = S * logm(S\X(:,:,n));
+	% 	U(:,:,n) = S * logm(S \ X(:,:,n));
 	% 	toc
 	% 	tic
-		[v,d] = eig(S\X(:,:,n));
-		U(:,:,n) = S * v*diag(log(diag(d)))*v^-1;
+		[V, D] = eig(S \ X(:,:,n));
+		U(:,:,n) = S * V * diag(log(diag(D))) / V;
 	% 	toc
 	end
 end
 
 %%%%%%%%%%%%%%%%%%
+% Vectorization of a symmetric matrix
 function v = symmat2vec(M)
-	% Vectorization of a symmetric matrix
 	N = size(M,1);
 	v = diag(M);
 	for n = 1:N-1
-		v = [v; sqrt(2).*diag(M,n)]; % Mandel notation
+		v = [v; sqrt(2) .* diag(M,n)]; % Mandel notation
 	end
 end
 
 %%%%%%%%%%%%%%%%%%
-function [S,iperm] = tmprod(T,U,mode)
-	% Mode-n tensor-matrix product
+% Mode-n tensor-matrix product
+function [S,iperm] = tmprod(T, U, mode)
 	size_tens = ones(1,mode);
 	size_tens(1:ndims(T)) = size(T);
 	N = length(size_tens);
@@ -291,7 +283,7 @@ function [S,iperm] = tmprod(T,U,mode)
 	size_tens = size_tens(perm);
 	S = T; 
 	if mode ~= 1
-			S = permute(S,perm); 
+		S = permute(S,perm); 
 	end
 
 	% n-mode product
@@ -301,4 +293,4 @@ function [S,iperm] = tmprod(T,U,mode)
 	% Inverse permutation
 	iperm(perm(1:N)) = 1:N;
 	S = permute(S,iperm); 
-end
\ No newline at end of file
+end
diff --git a/demos/demo_manipulabilityTracking_mainTask02.m b/demos/demo_manipulabilityTracking_mainTask02.m
index f8e5f4c3a9449ea053a4980be3812a94c49e3877..6c4479f8a620271273db45306f1230c0247e208c 100644
--- a/demos/demo_manipulabilityTracking_mainTask02.m
+++ b/demos/demo_manipulabilityTracking_mainTask02.m
@@ -1,6 +1,6 @@
 function demo_manipulabilityTracking_mainTask02
 % Matching of a desired manipulability ellipsoid as the main task (no desired position)
-% using the formulation with the manipulability Jacobien (Mandel notation).
+% using the formulation with the manipulability Jacobian (Mandel notation).
 % The matrix gain used for the manipulability tracking controller is now defined as the inverse of
 % a 2nd-order covariance matrix representing the variability information obtained from a learning algorithm.
 %
@@ -114,8 +114,7 @@ for n = 1:4
 	%% Final plots
 	%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 	% Robot and manipulability ellipsoids
-	figure('position',[10 10 900 900],'color',[1 1 1]);
-	hold on;
+	figure('position',[10 10 900 900],'color',[1 1 1]); hold on;
 	p = [];
 	for it = 1:2:nbIter-1
 		colTmp = [.95,.95,.95] - [.8,.8,.8] * (it)/nbIter;
@@ -132,8 +131,7 @@ for n = 1:4
 	plotGMM(xt(:,end), 1E-2*Me_d, [0.2 0.8 0.2], .4);
 	plotGMM(xt_track(:,1,n), 1E-2*Me_track(:,:,1,n), [0.2 0.2 0.8], .4);
 	plotGMM(xt(:,end), 1E-2*Me_ct, clrmap(n,:), .4);
-	axis equal
-	xlim([-3,9]); ylim([-4,8])
+	axis equal; xlim([-3,9]); ylim([-4,8]);
 	set(gca,'fontsize',22,'xtick',[],'ytick',[]);
 	xlabel('$x_1$','fontsize',38,'Interpreter','latex'); ylabel('$x_2$','fontsize',38,'Interpreter','latex');
 	title(names{n});
@@ -145,8 +143,7 @@ end
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 % Manipulability ellipsoids
 for n = 1:4
-	figure('position',[10 10 1200 300],'color',[1 1 1]);
-	hold on;
+	figure('position',[10 10 1200 300],'color',[1 1 1]); hold on;
 	for it = 1:10:nbIter-1
 		plotGMM([it*dt;0], 2E-4*Me_d, [0.2 0.8 0.2], .1);
 		plotGMM([it*dt;0], 2E-4*Me_track(:,:,it,n), clrmap(n,:), .3);
@@ -158,8 +155,7 @@ for n = 1:4
 	title(names{n});
 end
 
-figure('position',[10 10 900 900],'color',[1 1 1]);
-hold on;
+figure('position',[10 10 900 900],'color',[1 1 1]); hold on;
 for it = 1:2:nbIter-1
 	for n = 1:4
 		plotGMM(xt_track(:,it,n), 1E-2*Me_track(:,:,it,n), clrmap(n,:), .15);
@@ -169,7 +165,8 @@ plotGMM(xt_track(:,1,1), 1E-2*Me_track(:,:,1,1), [0.1 0.1 0.4], .6);
 axis equal;
 set(gca,'fontsize',18);
 xlabel('$x_1$','fontsize',30,'Interpreter','latex'); ylabel('$x_2$','fontsize',30,'Interpreter','latex');
-title('End-effector and manipulability ellipsoids trajectories')
+title('End-effector and manipulability ellipsoids trajectories');
+
 end
 
 %%%%%%%%%%%%%%%%%%
@@ -208,12 +205,12 @@ function J_grad = compute_joint_derivative_Jacobian(J)
 			J_i = J(:,i);
 			J_j = J(:,j);
 			if j < i
-				J_grad(1:3,i,j) = cross(J_j(4:6,:),J_i(1:3,:));
-				J_grad(4:6,i,j) = cross(J_j(4:6,:),J_i(4:6,:));
+				J_grad(1:3,i,j) = cross(J_j(4:6,:), J_i(1:3,:));
+				J_grad(4:6,i,j) = cross(J_j(4:6,:), J_i(4:6,:));
 			elseif j > i
-				J_grad(1:3,i,j) = -cross(J_j(1:3,:),J_i(4:6,:));
+				J_grad(1:3,i,j) = -cross(J_j(1:3,:), J_i(4:6,:));
 			else
-				J_grad(1:3,i,j) = cross(J_i(4:6,:),J_i(1:3,:));
+				J_grad(1:3,i,j) = cross(J_i(4:6,:), J_i(1:3,:));
 			end
 		end
 	end
@@ -226,11 +223,11 @@ function U = logmap(X,S)
 	for n = 1:N
 		% 	U(:,:,n) = S^.5 * logm(S^-.5 * X(:,:,n) * S^-.5) * S^.5;
 		% 	tic
-		% 	U(:,:,n) = S * logm(S\X(:,:,n));
+		% 	U(:,:,n) = S * logm(S \ X(:,:,n));
 		% 	toc
 		% 	tic
-		[v,d] = eig(S\X(:,:,n));
-		U(:,:,n) = S * v*diag(log(diag(d)))*v^-1;
+		[V,D] = eig(S \ X(:,:,n));
+		U(:,:,n) = S * V * diag(log(diag(d))) / V;
 		% 	toc
 	end
 end
@@ -241,7 +238,7 @@ function v = symmat2vec(M)
 	N = size(M,1);
 	v = diag(M);
 	for n = 1:N-1
-		v = [v; sqrt(2).*diag(M,n)]; % Mandel notation
+		v = [v; sqrt(2) .* diag(M,n)]; % Mandel notation
 	end
 end
 
@@ -273,4 +270,4 @@ function [S,iperm] = tmprod(T,U,mode)
 	% Inverse permutation
 	iperm(perm(1:N)) = 1:N;
 	S = permute(S,iperm);
-end
\ No newline at end of file
+end
diff --git a/demos/demo_proMP01.m b/demos/demo_proMP01.m
index 43592e3e9fa5d9b7a94243db8bf9780d8766395d..6b923891523fb56077bd5a47e0518b1513b44311 100644
--- a/demos/demo_proMP01.m
+++ b/demos/demo_proMP01.m
@@ -1,23 +1,9 @@
-function demo_proMP01
-% ProMP with several forms of basis functions, inspired by the original form with RBFs described in 
-% Paraschos, A., Daniel, C., Peters, J. and Neumann, G., "Probabilistic Movement Primitives", NIPS'2013
-%
-% If this code is useful for your research, please cite the related publication:
-% @incollection{Calinon19MM,
-% 	author="Calinon, S.",
-% 	title="Mixture Models for the Analysis, Edition, and Synthesis of Continuous Time Series",
-% 	booktitle="Mixture Models and Applications",
-% 	publisher="Springer",
-% 	editor="Bouguila, N. and Fan, W.", 
-% 	year="2019",
-% 	pages="39--57",
-% 	doi="10.1007/978-3-030-23876-6_3"
-% }
+% Movement primitives applied to 2D trajectory encoding and decoding
 %
-% Copyright (c) 2019 Idiap Research Institute, http://idiap.ch/
-% Written by Sylvain Calinon, http://calinon.ch/
+% Copyright (c) 2019 Idiap Research Institute, https://idiap.ch/
+% Written by Sylvain Calinon, https://calinon.ch/
 % 
-% This file is part of PbDlib, http://www.idiap.ch/software/pbdlib/
+% This file is part of PbDlib, https://www.idiap.ch/software/pbdlib/
 % 
 % PbDlib is free software: you can redistribute it and/or modify
 % it under the terms of the GNU General Public License version 3 as
@@ -29,142 +15,163 @@ function demo_proMP01
 % GNU General Public License for more details.
 % 
 % You should have received a copy of the GNU General Public License
-% along with PbDlib. If not, see <http://www.gnu.org/licenses/>.
-
-addpath('./m_fcts/');
+% along with PbDlib. If not, see <https://www.gnu.org/licenses/>.
 
+function demo_proMP01
 
 %% Parameters
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-nbStates = 8; %Number of basis functions
-nbVar = 2; %Dimension of position data (here: x1,x2)
-nbSamples = 5; %Number of demonstrations
-nbData = 200; %Number of datapoints in a trajectory
-nbRepros = 5; %Number of reproductions
+param.nbFct = 7; %Number of basis functions (odd number for Fourier basis functions)
+param.nbVar = 2; %Dimension of position data (here: x1,x2)
+param.nbData = 100; %Number of datapoints in a trajectory
+param.basisName = 'RBF'; %PIECEWISE, RBF, BERNSTEIN, FOURIER
 
 
 %% Load handwriting data
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 demos=[];
-load('data/2Dletters/C.mat');
-x=[];
-for n=1:nbSamples
-	s(n).x = spline(1:size(demos{n}.pos,2), demos{n}.pos, linspace(1,size(demos{n}.pos,2),nbData)); %Resampling
-	x = [x, s(n).x(:)]; %Reorganize as trajectory datapoints 
+load('./data/2Dletters/S.mat'); %Planar trajectories for writing alphabet letters
+x = spline(1:size(demos{1}.pos,2), demos{1}.pos, linspace(1,size(demos{1}.pos,2),param.nbData))(:); %Resampling
+
+if isequal(param.basisName,'FOURIER')
+	%Fourier basis functions require additional symmetrization (mirroring) if the signal is a discrete motion 
+	X = reshape(x, param.nbVar, param.nbData);
+	X = [X, fliplr(X)]; %Build real and even signal, characterized by f(-x) = f(x)
+	x = X(:); 
+	param.nbData = param.nbData * 2;
 end
-t = linspace(0,1,nbData); %Time range
 
 
-%% ProMP with radial basis functions 
+%% Movement primitives encoding and decoding 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%Compute basis functions Psi and activation weights w
-tMu = linspace(t(1), t(end), nbStates);
-m(1).phi = zeros(nbData,nbStates);
-for i=1:nbStates
-	m(1).phi(:,i) = gaussPDF(t, tMu(i), 1E-2);
-% 	m(1).phi(:,i) = mvnpdf(t', tMu(i), 1E-2); 
+if isequal(param.basisName,'PIECEWISE')
+    phi = buildPhiPiecewise(param.nbData, param.nbFct);
+elseif isequal(param.basisName,'RBF')
+    phi = buildPhiRBF(param.nbData, param.nbFct);
+elseif isequal(param.basisName,'BERNSTEIN')
+    phi = buildPhiBernstein(param.nbData, param.nbFct);
+elseif isequal(param.basisName,'FOURIER')
+    phi = buildPhiFourier(param.nbData, param.nbFct);
 end
-% m(1).phi = m(1).phi ./ repmat(sum(m(1).phi,2),1,nbStates); %Optional rescaling
-m(1).Psi = kron(m(1).phi, eye(nbVar)); %Eq.(27)
-m(1).w = (m(1).Psi' * m(1).Psi + eye(nbVar*nbStates).*1E-8) \ m(1).Psi' * x; %m(1).w = pinv(m(1).Psi) * x'; %Eq.(28)
-%Distribution in parameter space
-m(1).Mu_w = mean(m(1).w,2);
-m(1).Sigma_w = cov(m(1).w') + eye(nbVar*nbStates) * 1E0; 
-%Trajectory distribution
-m(1).Mu = m(1).Psi * m(1).Mu_w; %Eq.(29)
-m(1).Sigma = m(1).Psi * m(1).Sigma_w * m(1).Psi'; %Eq.(29)
-
-
-%% ProMP with Bernstein basis functions
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%Compute basis functions Psi and activation weights w
-m(2).phi = zeros(nbData,nbStates);
-for i=0:nbStates-1
-	m(2).phi(:,i+1) = factorial(nbStates-1) ./ (factorial(i) .* factorial(nbStates-1-i)) .* (1-t).^(nbStates-1-i) .* t.^i; %Bernstein basis functions
+
+Psi = kron(phi, eye(param.nbVar)); %Transform to multidimensional basis functions
+w = (Psi' * Psi + eye(param.nbVar*param.nbFct).*realmin) \ Psi' * x; %Estimation of superposition weights from data
+x_hat = Psi * w; %Reconstruction of data
+
+if isequal(param.basisName,'FOURIER')
+	%Fourier basis functions require de-symmetrization of the signal after processing (for visualization)
+	param.nbData = param.nbData/2;
+	x = x(1:param.nbData*param.nbVar);
+	x_hat = x_hat(1:param.nbData*param.nbVar);
+	phi = real(phi); %for plotting
+	%Psi = Psi(1:param.nbData*param.nbVar,:);
 end
-m(2).Psi = kron(m(2).phi, eye(nbVar)); %Eq.(27)
-m(2).w = (m(2).Psi' * m(2).Psi + eye(nbVar*nbStates).*1E-8) \ m(2).Psi' * x; %m(2).w = pinv(m(2).Psi) * x; %Eq.(28)
-%Distribution in parameter space
-m(2).Mu_w = mean(m(2).w,2);
-m(2).Sigma_w = cov(m(2).w') + eye(nbVar*nbStates) * 1E0; 
-%Trajectory distribution
-m(2).Mu = m(2).Psi * m(2).Mu_w; %Eq.(29)
-m(2).Sigma = m(2).Psi * m(2).Sigma_w * m(2).Psi'; %Eq.(29)
 
 
-%% ProMP with Fourier basis functions (here, only DCT)
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%Compute basis functions Psi and activation weights w
-m(3).phi = zeros(nbData,nbStates);
-for i=1:nbStates
-	xTmp = zeros(1,nbData);
-	xTmp(i) = 1;
-	m(3).phi(:,i) = idct(xTmp);
-end	
-m(3).Psi = kron(m(3).phi, eye(nbVar)); %Eq.(27)
-m(3).w = (m(3).Psi' * m(3).Psi + eye(nbVar*nbStates).*1E-8) \ m(3).Psi' * x; %m(3).w = pinv(m(3).Psi) * x; %Eq.(28)
-%Distribution in parameter space
-m(3).Mu_w = mean(m(3).w,2);
-m(3).Sigma_w = cov(m(3).w') + eye(nbVar*nbStates) * 1E0; 
-%Trajectory distribution
-m(3).Mu = m(3).Psi * m(3).Mu_w; %Eq.(29)
-m(3).Sigma = m(3).Psi * m(3).Sigma_w * m(3).Psi'; %Eq.(29)
-
-
-%% Conditioning with trajectory distribution (reconstruction from partial data)
+%% Plots
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-in0 = [1,nbData]; %Time steps input indices
-out0 = 2:nbData-1; %Time steps output indices
-in = [];
-for i=1:length(in0)
-	in = [in, (in0(i)-1)*nbVar+[1:nbVar]]; %Trajectory distribution input indices
+h = figure('position',[10 10 1800 500]); 
+clrmap = lines(param.nbFct);
+
+%Plot signals
+subplot(1,3,1); hold on; axis off; 
+l(1) = plot(x(1:2:end,:), x(2:2:end,:), 'linewidth',2,'color',[.2 .2 .2]);
+l(2) = plot(x_hat(1:2:end,:), x_hat(2:2:end,:), '-','linewidth',2,'color',[.9 .0 .0]);
+% legend(l,{'Demonstration','Reproduction'},'fontsize',20); % Throw an error with octave
+axis tight; axis equal; 
+
+%Plot basis functions (display only the real part for Fourier basis functions)
+subplot(1,3,2); hold on; 
+for i=1:param.nbFct
+	plot(phi(:,i), 'linewidth',2,'color',clrmap(i,:));
 end
-out = [];
-for i=1:length(out0)
-	out = [out, (out0(i)-1)*nbVar+[1:nbVar]]; %Trajectory distribution output indices
+if isequal(param.basisName,'FOURIER')
+	plot([param.nbData,param.nbData], [-1,1], 'k:','linewidth',4);
 end
-%Reproduction by Gaussian conditioning
-for k=1:3
-	for n=1:nbRepros
-		m(k).Mu2(in,n) = x(in,1) + repmat((rand(nbVar,1)-0.5)*2, length(in0), 1) ;
+axis tight;
+xlabel('t','fontsize',26); ylabel('\phi_k','fontsize',26);
+
+%Plot Psi*Psi' matrix (covariance matrix at trajectory level)
+subplot(1,3,3); hold on; axis off; title('\Psi\Psi^T','fontsize',26);
+msh = [0 1 1 0 0; 0 0 1 1 0];
+colormap(flipud(gray));
+imagesc(abs(Psi * Psi'));
+plot(msh(1,:)*size(Psi,1), msh(2,:)*size(Psi,1), 'k-');
+if isequal(param.basisName,'FOURIER')
+	plot(msh(1,:)*size(Psi,1)/2, msh(2,:)*size(Psi,1)/2, 'k:','linewidth',4);
+end
+axis tight; axis square; axis ij;
 
-% 		%Conditional distribution with trajectory distribution
-% 		m(k).Mu2(out,n) = m(k).Mu(out) + m(k).Sigma(out,in) / m(k).Sigma(in,in) * (m(k).Mu2(in,n) - m(k).Mu(in));
+waitfor(h);
+end
 
-		%Efficient computation of conditional distribution by exploiting ProMP structure
-		m(k).Mu2(out,n) = m(k).Psi(out,:) * ...
-			(m(k).Mu_w + m(k).Sigma_w * m(k).Psi(in,:)' / (m(k).Psi(in,:) * m(k).Sigma_w * m(k).Psi(in,:)') * (m(k).Mu2(in,n) - m(k).Psi(in,:) * m(k).Mu_w));
-	end
+
+%%Likelihood of datapoint(s) for a Gaussian parameterized with center and full covariance
+%function prob = gaussPDF(Data, Mu, Sigma)    
+%	[nbVar,nbData] = size(Data);
+%	Data = Data - repmat(Mu,1,nbData);
+%	prob = sum((Sigma\Data).*Data,1);
+%	prob = exp(-0.5*prob) / sqrt((2*pi)^nbVar * abs(det(Sigma)) + realmin);
+%end
+
+%Building piecewise constant basis functions
+function phi = buildPhiPiecewise(nbData, nbFct) 
+%	iList = round(linspace(0, nbData, nbFct+1));
+%	phi = zeros(nbData, nbFct);
+%	for i=1:nbFct
+%		phi(iList(i)+1:iList(i+1),i) = 1;
+%	end
+	phi = kron(eye(nbFct), ones(ceil(nbData/nbFct),1));
+	phi = phi(1:nbData,:);
 end
 
+%Building radial basis functions (RBFs)
+function phi = buildPhiRBF(nbData, nbFct) 
+	t = linspace(0, 1, nbData);
+	tMu = linspace(t(1), t(end), nbFct);
+
+%	%Version 1
+%	phi = zeros(nbData, nbFct);
+%	for i=1:nbFct
+%		phi(:,i) = gaussPDF(t, tMu(i), 1E-2);
+%		%phi(:,i) = mvnpdf(t', tMu(i), 1E-2); %Requires statistics package/toolbox
+%	end
+
+%	%Version 2
+%	%D = repmat(t', [1,nbFct]) - repmat(tMu, [nbData,1]);
+%	D = t' * ones(1,nbFct) - ones(nbData,1) * tMu;
+%	phi = exp(-1E2 * D.^2);
+
+	%Version 3
+	phi = exp(-1E1 * (t' - tMu).^2);
+	
+	%Optional rescaling
+	%phi = phi ./ repmat(sum(phi,2), 1, nbFct); 
+end
 
-%% Plot 
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-figure('position',[10 10 1800 1300]); 
-clrmap = lines(nbStates);
-methods = {'ProMP with Radial basis functions','ProMP with Bernstein basis functions','ProMP with Fourier basis functions'};
-for k=1:3
-	%Plot signal
-	subplot(3,3,k); hold on; axis off; title(methods{k},'fontsize',16);
-	plot(x(1:2:end,:), x(2:2:end,:), '.','markersize',10,'color',[.7 .7 .7]);
-	for n=1:nbRepros
-		plot(m(k).Mu2(1:2:end,n), m(k).Mu2(2:2:end,n), '-','lineWidth',2,'color',[1 .6 .6]);
+%Building Bernstein basis functions
+function phi = buildPhiBernstein(nbData, nbFct)
+	t = linspace(0, 1, nbData);
+	phi = zeros(nbData, nbFct);
+	for i=1:nbFct
+		phi(:,i) = factorial(nbFct-1) ./ (factorial(i-1) .* factorial(nbFct-i)) .* (1-t).^(nbFct-i) .* t.^(i-1);
 	end
-	plot(m(k).Mu(1:2:end), m(k).Mu(2:2:end), '-','lineWidth',2,'color',[0 0 0]);
-	axis tight; axis equal; 
-	%Plot activation functions
-	subplot(3,3,3+k); hold on; axis off; title('\phi_k','fontsize',16);
-	for i=1:nbStates
-		plot(1:nbData, m(k).phi(:,i),'linewidth',2,'color',clrmap(i,:));
-	end
-	axis([1, nbData, min(m(k).phi(:)), max(m(k).phi(:))]);
-	%Plot Psi*Psi' matrix
-	subplot(3,3,6+k); hold on; axis off; title('\Psi\Psi^T','fontsize',16);
-	colormap(flipud(gray));
-	imagesc(abs(m(k).Psi * m(k).Psi'));
-	axis tight; axis square; axis ij;
-end %k
-
-% print('-dpng','graphs/demo_proMP01.png');
-pause;
-close all;
\ No newline at end of file
+end
+
+%Building Fourier basis functions
+function phi = buildPhiFourier(nbData, nbFct)
+	t = linspace(0, 1, nbData);
+	
+%	%Computation for general signals (incl. complex numbers)
+%	d = ceil((nbFct-1)/2);
+%	k = -d:d;
+%	phi = exp(t' * k * 2 * pi * 1i); 
+%	%phi = cos(t' * k * 2 * pi); %Alternative computation for real signal
+		
+	%Alternative computation for real and even signal
+	k = 0:nbFct-1;
+	phi = cos(t' * k * 2 * pi);
+	%phi(:,2:end) = phi(:,2:end) * 2;
+	%invPhi = cos(k' * t * 2 * pi) / nbData;
+	%invPsi = kron(invPhi, eye(param.nbVar));
+end
diff --git a/demos/demo_proMP_Fourier01.m b/demos/demo_proMP_Fourier01.m
index 380966ba20d2ec3621ce57706a0396689f50fcf6..b9eb2be15c014d8440475a2b61328faecbce742f 100644
--- a/demos/demo_proMP_Fourier01.m
+++ b/demos/demo_proMP_Fourier01.m
@@ -53,7 +53,7 @@ end
 k = -5:5;
 nbFct = length(k);
 t = linspace(0,1,nbData);
-Psi = exp(t' * k * 2 * pi * 1i) / nbData;
+Psi = exp(t' * k * 2 * pi * 1i); % / nbData;
 % w = (Psi' * Psi + eye(nbStates).*1E-18) \ Psi' * x; 
 w = pinv(Psi) * x;
 
@@ -159,4 +159,4 @@ function Sigma = cov_angle(phi)
 	Mu = mean_angle(phi);
 	e = phi - repmat(Mu, size(phi,1), 1);
 	Sigma = cov(angle(exp(1i*e)));
-end
\ No newline at end of file
+end
diff --git a/demos/demo_proMP_Fourier_sampling02.m b/demos/demo_proMP_Fourier_sampling02.m
index f6981aa7cfe9618adb625131be15b740ec0a477c..3f4ef65decf63149de438a3b7773be953a6fae6d 100644
--- a/demos/demo_proMP_Fourier_sampling02.m
+++ b/demos/demo_proMP_Fourier_sampling02.m
@@ -49,7 +49,7 @@ end
 
 %Simulate phase variations
 for n=2:nbSamples
-	x(:,n) = circshift(x(:,1),(n-nbSamples/2-1)*4);
+	x(:,n) = circshift(x(:,1), (n-nbSamples/2-1)*4);
 end
 
 
@@ -178,4 +178,4 @@ function Sigma = cov_angle(phi)
 	Mu = mean_angle(phi);
 	e = phi - repmat(Mu, size(phi,1), 1);
 	Sigma = cov(angle(exp(1i*e)));
-end
\ No newline at end of file
+end