diff --git a/matlab/LQT_nullspace.m b/matlab/LQT_nullspace.m
new file mode 100644
index 0000000000000000000000000000000000000000..7e6631f123349a80f3a5b766143426853914187e
--- /dev/null
+++ b/matlab/LQT_nullspace.m
@@ -0,0 +1,109 @@
+%%    Batch LQT with nullspace formulation
+%%
+%%    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/>.
+
+function LQT_nullspace
+
+%% Parameters
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+param.nbData = 50; %Number of datapoints
+param.nbRepros = 60; %Number of stochastic reproductions
+param.nbPoints = 1; %Number of keypoints
+param.nbVar = 2; %Dimension of state vector
+param.dt = 1E-1; %Time step duration
+param.rfactor = 1E-4; %param.dt^nbDeriv;	%Control cost in LQR
+
+
+R = speye((param.nbData-1)*param.nbVar) * param.rfactor;
+x0 = zeros(param.nbVar,1); %Initial point
+
+
+%% Dynamical System settings
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+Su = [zeros(param.nbVar, param.nbVar*(param.nbData-1)); kron(tril(ones(param.nbData-1)), eye(param.nbVar)*param.dt)];
+Sx = kron(ones(param.nbData,1), eye(param.nbVar));
+
+
+%% Task setting
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+tl = linspace(1,param.nbData,param.nbPoints+1);
+tl = round(tl(2:end)); %[param.nbData/2, param.nbData];
+%Mu = rand(param.nbVarPos,param.nbPoints) - 0.5; 
+Mu = [20; 10];
+
+Sigma = repmat(eye(param.nbVar)*1E-3, [1,1,param.nbPoints]);
+MuQ = zeros(param.nbVar*param.nbData,1); 
+Q = zeros(param.nbVar*param.nbData);
+for t=1:length(tl)
+    id(:,t) = [1:param.nbVar] + (tl(t)-1) * param.nbVar;
+    Q(id(:,t), id(:,t)) = inv(Sigma(:,:,t));
+    MuQ(id(:,t)) = Mu(:,t);
+end
+
+
+%% Batch LQR reproduction
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%Precomputation of basis functions to generate control commands u (here, with Bernstein basis functions)
+nbRBF = 10;
+H = buildPhiBernstein(param.nbData-1,nbRBF);
+
+%Reproduction with nullspace planning
+[V,D] = eig(Q);
+U = V * D.^.5;
+J = U' * Su; %Jacobian
+
+%Left pseudoinverse solution
+pinvJ = (J' * J + R) \ J'; %Left pseudoinverse
+N = speye((param.nbData-1)*param.nbVar) - pinvJ * J; %Nullspace projection matrix
+u1 = pinvJ * U' * (MuQ - Sx * x0); %Principal task (least squares solution)
+x = reshape(Sx*x0+Su*u1, param.nbVar, param.nbData); %Reshape data for plotting
+
+%General solutions
+for n=1:param.nbRepros
+    w = randn(param.nbVar,nbRBF) * 1E1; %Random weights	
+    u2 = w * H'; %Reconstruction of control signals by a weighted superposition of basis functions
+    u = u1 + N * u2(:);
+    r(n).x = reshape(Sx*x0+Su*u, param.nbVar, param.nbData); %Reshape data for plotting
+end
+
+
+%% Plot 2D
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+figure('position',[10 10 800 800],'color',[1 1 1],'name','x1-x2 plot'); hold on; axis off;
+for n=1:param.nbRepros
+    plot(r(n).x(1,:), r(n).x(2,:), '-','linewidth',1,'color',.9-[.7 .7 .7].*rand(1));
+end
+plot(x(1,:), x(2,:), '-','linewidth',2,'color',[.8 0 0]);
+plot(x(1,1), x(2,1), 'o','linewidth',2,'markersize',8,'color',[.8 0 0]);
+plot(MuQ(id(1,:)), MuQ(id(2,:)), '.','markersize',30,'color',[.8 0 0]);
+axis equal; 
+%print('-dpng','graphs/LQT_nullspace02.png');
+
+pause(10);
+close all;
+end
+
+%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
+end
+