diff --git a/demos/demo_Bezier01.m b/demos/demo_Bezier01.m index 15d803a7c68d9f2a897ca5d254e34452963b34bf..14a98078bd098178626e081aa8ad685eeca1da81 100644 --- a/demos/demo_Bezier01.m +++ b/demos/demo_Bezier01.m @@ -50,19 +50,20 @@ x = p * B; %Reconstruction of signal %% Plot %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -figure('position',[10,10,800,1200]); +figure('position',[10,10,800,800]); subplot(2,1,1); hold on; axis off; -plot(p(1,:), p(2,:), 'r.','markersize',20); +plot(p(1,:), p(2,:), '.','markersize',30,'color',[.6 .6 .6]); if nbDeg==3 - plot(p(1,[1:2]), p(2,[1:2]), 'r-','linewidth',2); - plot(p(1,[3:4]), p(2,[3:4]), 'r-','linewidth',2); + plot(p(1,[1:2]), p(2,[1:2]), '-','linewidth',2,'color',[.6 .6 .6]); + plot(p(1,[3:4]), p(2,[3:4]), '-','linewidth',2,'color',[.6 .6 .6]); end -plot(x(1,:), x(2,:), 'k-','linewidth',3); +plot(x(1,:), x(2,:), '-','linewidth',3,'color',[0 0 0]); subplot(2,1,2); hold on; for i=0:nbDeg plot(t, B(i+1,:),'linewidth',3); end -xlabel('t','fontsize',16); ylabel('b_i','fontsize',16); +set(gca,'xtick',[0,1],'ytick',[0,1],'fontsize',16); +xlabel('t','fontsize',18); ylabel('b_i','fontsize',18); pause; -close all; +close all; \ No newline at end of file diff --git a/demos/demo_Bezier02.m b/demos/demo_Bezier02.m index 3cd7d1473428fb116e8115d5b353d52deed846b2..cf550c0f4c37fdb6caba18f112e904cefe85e10f 100644 --- a/demos/demo_Bezier02.m +++ b/demos/demo_Bezier02.m @@ -56,30 +56,32 @@ x2 = phi * w; %Reconstruction %Alternative computation through vectorization (useful for extending the approach to proMP representations including trajectory covariance) Psi = kron(phi, eye(nbVar)); -w = pinv(Psi) * x(:); %Control points -x2Vec = Psi * w; %Reconstruction +w2 = pinv(Psi) * x(:); %Control points +x2Vec = Psi * w2; %Reconstruction %% Plot %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% figure('position',[10,10,800,1200]); subplot(2,1,1); hold on; axis off; -plot(x(:,1), x(:,2), '-','linewidth',2,'color',[.7 .7 .7]); +% plot(w(:,1), w(:,2), '.','markersize',30,'color',[.6 .6 .6]); +plot(x(1,:), x(2,:), '-','linewidth',6,'color',[.7 .7 .7]); plot(x2(:,1), x2(:,2), 'k-','linewidth',2); plot(x2Vec(1:2:end), x2Vec(2:2:end), 'r--','linewidth',2); % plot(w(1,:), w(2,:), 'r.','markersize',20); subplot(2,1,2); hold on; for i=0:nbDeg - plot(t,phi(:,i+1)); + plot(t, phi(:,i+1), '-','linewidth',3); end -xlabel('t'); ylabel('b_i'); +xlabel('t','fontsize',18); ylabel('b_i','fontsize',18); +set(gca,'xtick',[0,1],'ytick',[0,1],'fontsize',16); -%Plot covariance -figure('position',[1640 10 800 800]); hold on; -colormap(flipud(gray)); -pcolor(abs(Psi*Psi')); -set(gca,'xtick',[1,nbData*nbVar],'ytick',[1,nbData*nbVar]); -axis square; axis([1 nbData*nbVar 1 nbData*nbVar]); shading flat; +% %Plot covariance +% figure('position',[1640 10 800 800]); hold on; +% colormap(flipud(gray)); +% pcolor(abs(Psi*Psi')); +% set(gca,'xtick',[1,nbData*nbVar],'ytick',[1,nbData*nbVar]); +% axis square; axis([1 nbData*nbVar 1 nbData*nbVar]); shading flat; pause; -close all; +close all; \ No newline at end of file diff --git a/demos/demo_Bezier_illustr01.m b/demos/demo_Bezier_illustr01.m index f742934eedd5fa326e84b292655f317277043de3..783f8c0f6aa2e42199a4dc793ca0243846338e4d 100644 --- a/demos/demo_Bezier_illustr01.m +++ b/demos/demo_Bezier_illustr01.m @@ -78,4 +78,4 @@ end %nb % print('-dpng','graphs/demo_Bezier_illustr01.png'); pause; -close all; +close all; \ No newline at end of file diff --git a/demos/demo_Bezier_illustr02.m b/demos/demo_Bezier_illustr02.m index f140a92a50682e191a004e0fb9445dfcabd8e1ee..9d6b23e9357a2f342fa929d9376092cb52da7de2 100644 --- a/demos/demo_Bezier_illustr02.m +++ b/demos/demo_Bezier_illustr02.m @@ -163,4 +163,4 @@ axis equal; % % print('-dpng','graphs/demo_Bezier_highOrder02.png'); pause; -close all; +close all; \ No newline at end of file diff --git a/demos/demo_GPR_closedShape02.m b/demos/demo_GPR_closedShape02.m index ac6642463ae0390305070d9d7f738914cfd2ef58..ec3f34f0ea3e307aed6636527a19375c5554360e 100644 --- a/demos/demo_GPR_closedShape02.m +++ b/demos/demo_GPR_closedShape02.m @@ -19,10 +19,10 @@ function demo_GPR_closedShape02 % year = "2007" % } % -% Copyright (c) 2019 Idiap Research Institute, http://idiap.ch/ +% Copyright (c) 2019 y==1ap Research Institute, http://y==1ap.ch/ % Written by Sylvain Calinon, http://calinon.ch/ % -% This file is part of PbDlib, http://www.idiap.ch/software/pbdlib/ +% This file is part of PbDlib, http://www.y==1ap.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 @@ -39,15 +39,11 @@ function demo_GPR_closedShape02 % addpath('./m_fcts/'); - %% Parameters %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% nbDataRepro = 50^2; %Number of datapoints in a reproduction -nbVarX = 2; %Dimension of x -% nbVarY = 1; %Dimension of y -% nbRepros = 6; %Number of randomly sampled reproductions -% SigmaY = eye(nbVarY); -p(1)=1E0; p(2)=1E-5; %Thin-plate covariance function parameters +% nbVarX = 2; %Dimension of x +p = [1E0, 1E-5]; %Thin-plate covariance function parameters %% Generate data @@ -60,71 +56,90 @@ p(1)=1E0; p(2)=1E-5; %Thin-plate covariance function parameters % y = [zeros(1,nbData-5), 1, -1, -1, -1, -1]; %0, 1 and -1 represent border, interior, and exterior points %mean(x,2)+[-1;0], mean(x,2)+[1;0], mean(x,2)+[0;-1], mean(x,2)+[0;1] -x0 = [3 3 2 2 0 -1 -1 -3 -3; - 2 1 0 -1 -2 -2 -1 2 1]; -x = [x0, mean(x0,2), [-3;3], [-2;-3], [4;-2], [-3;3], [4;2], [2;-2] [4;4]] * 1E-1; -y = [zeros(1,size(x0,2)), 1, -1, -1, -1, -1, -1, -1, -1]; %0, 1 and -1 represent border, interior, and exterior points -Data = [x; y]; +% x0 = [3 3 2 2 0 -1 -1 -3 -3; +% 2 1 0 -1 -2 -2 -1 2 1]; +% x = [x0, mean(x0,2), [-3;3], [-2;-3], [4;-2], [-3;3], [4;2], [2;-2] [4;4]] * 1E-1; +% y = [zeros(1,size(x0,2)), 1, -1, -1, -1, -1, -1, -1, -1]; %0, 1 and -1 represent border, interior, and exterior points + +% x = [-.3, -.1, .1; 0, 0, 0]; +% y = [-1, 0, 1]; %-1, 0 and 1 represent exterior, border and interior points + +% x = rand(2,15) - .5; +% y = randi(3,1,15) - 2; %-1, 0 and 1 represent exterior, border and interior points + +% x = [-0.3, -0.1, 0.1, 0.0, 0.4, 0.4, 0.3, 0.0, -0.3, 0.0, 0.2, 0.0, 0.4; ... +% 0.0, 0.0, 0.0, 0.4, -0.4, 0.4, 0.1, 0.2, 0.3, -0.4, -0.2, -0.3, -0.2]; +% y = [-1, 0, 1, -1, -1, -1, 0, 0, -1, -1, 0, 0, 0]; + +% x = [-0.3, -0.2, 0.1, -0.2, 0.2, 0.3, 0.4; ... +% 0.0, 0.0, 0.0, 0.4, -0.2, 0.2, -0.4]; +% y = [-1, 0, 1, -1, 0 0, -1]; + +x = [-0.4500 -0.0006 0.0829 -0.3480 -0.1983; ... + -0.4500 -0.2000 -0.3920 -0.3451 -0.0423]; +y = [-1 1 0 0 0]; %% Reproduction with GPR %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%Mean computation [Xm, Ym] = meshgrid(linspace(-.5,.5,nbDataRepro^.5), linspace(-.5,.5,nbDataRepro^.5)); xs = [Xm(:)'; Ym(:)']; p(1) = max(max(pdist2(xs', xs'))); %Refine thin-plate covariance function parameter -rc = 4E-1; -S = eye(nbVarX) * rc.^-2; -MuS = .5 * rc * diag(1 - xs' * S * xs)'; -Mu = .5 * rc * diag(1 - x' * S * x)'; +%Circle as geometric prior +rc = 4E-1; %Radius of circle +xc = [.05; .05]; %Location of circle +S = eye(2) * rc^-2; +MuS = .5 * rc * diag(1 - (xs-repmat(xc,1,nbDataRepro))' * S * (xs-repmat(xc,1,nbDataRepro)))'; +Mu = .5 * rc * diag(1 - (x-repmat(xc,1,size(x,2)))' * S * (x-repmat(xc,1,size(x,2))))'; K = covFct(x, x, p, 1); %Inclusion of noise on the inputs for the computation of K [Ks, dKs] = covFct(xs, x, p); -% r(1).Data = [xs; (Ks / K * y')']; %GPR with Mu=0 -r(1).Data = [xs; MuS + (Ks / K * (y - Mu)')']; -r(1).dData = [xs; (dKs(:,:,1) / K * (y - Mu)')'; (dKs(:,:,2) / K * (y - Mu)')']; %Gradients -a = min(r(1).Data(3,:),0); %Amplitude -for t=1:size(r(1).dData,2) - r(1).dData(3:4,t) = - exp(a(t)) * r(1).dData(3:4,t) / norm(r(1).dData(3:4,t)); %Vector moving away from contour, with stronger influence when close to the border -end +% ry = (Ks / K * y')'; %GPR with Mu=0 +ry = MuS + (Ks / K * (y - Mu)')'; +rdy = [(dKs(:,:,1) / K * (y - Mu)')'; (dKs(:,:,2) / K * (y - Mu)')']; %Gradients + +%Redefine gradient +% a = min(ry,0); %Amplitude +% for t=1:size(rdy,2) +% rdy(:,t) = - exp(a(t)) * rdy(:,t) / norm(rdy(:,t)); %Vector moving away from contour, with stronger influence when close to the border +% end -% %Uncertainty evaluation -% Kss = covFct(xs, xs, p); -% S = Kss - Ks / K * Ks'; -% r(1).SigmaOut = zeros(nbVarY, nbVarY, nbData); +%Uncertainty evaluation +Kss = covFct(xs, xs, p); +S = Kss - Ks / K * Ks'; +% nbVarY = 1; %Dimension of y +% SigmaY = eye(nbVarY); +% SigmaOut = zeros(nbVarY, nbVarY, nbDataRepro); % for t=1:nbDataRepro -% r(1).SigmaOut(:,:,t) = SigmaY * S(t,t); +% SigmaOut(:,:,t) = SigmaY * S(t,t); % end % %Generate stochastic samples from the prior +% nbRepros = 6; %Number of randomly sampled reproductions % [V,D] = eig(Kss); % for n=2:nbRepros/2 % yp = real(V*D^.5) * randn(nbDataRepro, nbVarY) * SigmaY .* 2E-1; -% r(n).Data = [xs; yp']; +% r(n).y = yp'; % end % % %Generate stochastic samples from the posterior % [V,D] = eig(S); % for n=nbRepros/2+1:nbRepros -% ys = real(V*D^.5) * randn(nbDataRepro, nbVarY) * SigmaY .* 0.5 + r(1).Data(nbVarX+1:end,:)'; -% r(n).Data = [xs; ys']; +% ys = real(V*D^.5) * randn(nbDataRepro, nbVarY) * SigmaY .* 0.5 + ry(nbVarX+1:end,:)'; +% r(n).y = ys'; % end -% %% Spatial plots -% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -idi = (Data(3,:)==1); -idb = (Data(3,:)==0); -ide = (Data(3,:)==-1); - -figure('position',[10 10 2300 1300],'color',[1,1,1]); hold on; axis off; %'PaperPosition',[0 0 14 5] +%% Spatial plots +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +figure('position',[10 10 1200 800],'color',[1,1,1]); hold on; axis off; %'PaperPosition',[0 0 14 5] set(0,'DefaultAxesLooseInset',[0,0,0,0]); set(gca,'LooseInset',[0,0,0,0]); -colormap(repmat(linspace(1,0,64),3,1)'); +colormap(repmat(linspace(1,.4,64),3,1)'); %Plot center of GP (acting as prior if points on the contours are missing) -subplot(2,3,1); hold on; axis off; rotate3d on; title('Prior (circular contour)','fontsize',20); +subplot(2,5,1); hold on; axis off; rotate3d on; title('Prior (circular contour)','fontsize',16); % 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 @@ -132,87 +147,106 @@ subplot(2,3,1); hold on; axis off; rotate3d on; title('Prior (circular contour)' mesh(Xm, Ym, reshape(MuS, 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'); tl = linspace(0,2*pi,100); -plot(cos(tl)*rc, sin(tl)*rc, 'k-','linewidth',2); +plot3(xc(1)+cos(tl)*rc, xc(2)+sin(tl)*rc, zeros(1,100), '-','linewidth',2,'color',[0 0 0]); view(3); axis vis3d; %Plot posterior distribution (3D) -subplot(2,3,4); hold on; axis off; rotate3d on; title('Posterior (3d plot)','fontsize',20); +subplot(2,5,6); hold on; axis off; rotate3d on; title('Posterior','fontsize',16); % 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 % end -mesh(Xm, Ym, reshape(r(1).Data(3,:), nbDataRepro^.5, nbDataRepro^.5), 'facealpha',.8,'edgealpha',.8,'edgecolor',[.7 .7 .7]); +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(r(1).Data(3,:), nbDataRepro^.5, nbDataRepro^.5), [0,0], 'linewidth',2,'color',[0 0 0]); -plot3(Data(1,idi), Data(2,idi), Data(3,idi)+.04, '.','markersize',18,'color',[.8 0 0]); %Interior points -plot3(Data(1,idb), Data(2,idb), Data(3,idb)+.04, '.','markersize',18,'color',[.8 .4 0]); %Border points -plot3(Data(1,ide), Data(2,ide), Data(3,ide)+.04, '.','markersize',18,'color',[0 .6 0]); %Exterior points +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 view(3); axis vis3d; %Plot posterior distribution (2D) -subplot(2,3,[2,3,5,6]); hold on; axis off; title('Posterior (2d plot)','fontsize',20); -surface(Xm, Ym, reshape(r(1).Data(3,:), nbDataRepro^.5, nbDataRepro^.5)-2, 'FaceColor','interp','EdgeColor','interp'); -quiver(r(1).dData(1,:), r(1).dData(2,:), r(1).dData(3,:), r(1).dData(4,:),'color',[0 0 .8]); -h(1) = plot(Data(1,idi), Data(2,idi), '.','markersize',28,'color',[.8 0 0]); %Interior points -h(2) = plot(Data(1,idb), Data(2,idb), '.','markersize',28,'color',[.8 .4 0]); %Border points -h(3) = plot(Data(1,ide), Data(2,ide), '.','markersize',28,'color',[0 .6 0]); %Exterior points -contour(Xm, Ym, reshape(r(1).Data(3,:), nbDataRepro.^.5, nbDataRepro.^.5), [0,0], 'linewidth',2,'color',[0 0 0]); -[c, h(4)] = contour(Xm, Ym, reshape(r(1).Data(3,:), nbDataRepro.^.5, nbDataRepro.^.5), [0,0], 'linewidth',2,'color',[0 0 0]); -% h(4) = plot3(c(1,2:end), c(2,2:end), ones(1,size(c,2)-1), '-','linewidth',2,'color',[0 0 0]); -% contour(Xm, Ym, reshape(r(1).Data(3,:)+2E0.*diag(S).^.5', nbDataRepro.^.5, nbDataRepro.^.5), [0,0], 'linewidth',1,'color',[.6 .6 .6]); -% contour(Xm, Ym, reshape(r(1).Data(3,:)-2E0.*diag(S).^.5', nbDataRepro.^.5, nbDataRepro.^.5), [0,0], 'linewidth',1,'color',[.6 .6 .6]); +subplot(2,5,[2,3,7,8]); hold on; axis off; title('Distance to contour and gradient','fontsize',16); +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,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]); +% 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]); +% patch(c(1,2:end), c(2,2:end), ones(1,size(c,2)-1), [.8 0 0], 'edgecolor','none','facealpha', .1); +% 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)','Estimated contour'},'fontsize',20); +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('boxoff'); -% print('-dpng','graphs/GPR_GPIS01.png'); +%Plot uncertainty (2D) +subplot(2,5,[4,5,9,10]); hold on; axis off; title('Uncertainty','fontsize',16); +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(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'); pause; close all; end +%%%%%%%%%%%%%%%%%%%%%%%%% function d = substr(x1, x2) d = x1 - x2; end +%%%%%%%%%%%%%%%%%%%%%%%%% function [K, dK] = covFct(x1, x2, p, flag_noiseObs) if nargin<4 flag_noiseObs = 0; end - %Thin plate covariance function (for 3D implicit shape) - K = 12^-1 * (2 * pdist2(x1',x2').^3 - 3 * p(1) * pdist2(x1',x2').^2 + p(1)^3); - dK(:,:,1) = 12^-1 * (6 * pdist2(x1',x2') .* substr(x1(1,:)',x2(1,:)) - 6 * p(1) * substr(x1(1,:)',x2(1,:))); %Derivatives along x1 - dK(:,:,2) = 12^-1 * (6 * pdist2(x1',x2') .* substr(x1(2,:)',x2(2,:)) - 6 * p(1) * substr(x1(2,:)',x2(2,:))); %Derivatives along x2 -% for i=1:size(x1,2) -% for j=1:size(x2,2) -% e = x1(:,i) - x2(:,j); -% % K(i,j) = 12^-1 * (2 * pdist2(x1(:,i)',x2(:,j)')^3 - 3 * p(1) * pdist2(x1(:,i)',x2(:,j)')^2 + p(1)^3); -% % K(i,j) = 12^-1 * (2 * norm(e)^3 - 3 * p(1) * e'*e + p(1)^3); -% K(i,j) = 12^-1 * (2 * (e'*e)^1.5 - 3 * p(1) * e'*e + p(1)^3); %Kernel (slow one by one computation) -% dK(i,j,:) = 12^-1 * (6 * (e'*e)^.5 * e - 6 * p(1) * e); %Derivatives (slow one by one computation) -% end -% end +% %Thin plate covariance function (for 3D implicit shape) +% K = 12^-1 * (2 * pdist2(x1',x2').^3 - 3 * p(1) * pdist2(x1',x2').^2 + p(1)^3); %Kernel +% dK(:,:,1) = 12^-1 * (6 * pdist2(x1',x2') .* substr(x1(1,:)',x2(1,:)) - 6 * p(1) * substr(x1(1,:)',x2(1,:))); %Derivatives along x1 +% dK(:,:,2) = 12^-1 * (6 * pdist2(x1',x2') .* substr(x1(2,:)',x2(2,:)) - 6 * p(1) * substr(x1(2,:)',x2(2,:))); %Derivatives along x2 +% % for i=1:size(x1,2) +% % for j=1:size(x2,2) +% % e = x1(:,i) - x2(:,j); +% % % K(i,j) = 12^-1 * (2 * pdist2(x1(:,i)',x2(:,j)')^3 - 3 * p(1) * pdist2(x1(:,i)',x2(:,j)')^2 + p(1)^3); +% % % K(i,j) = 12^-1 * (2 * norm(e)^3 - 3 * p(1) * e'*e + p(1)^3); +% % K(i,j) = 12^-1 * (2 * (e'*e)^1.5 - 3 * p(1) * e'*e + p(1)^3); %Kernel (slow one by one computation) +% % dK(i,j,:) = 12^-1 * (6 * (e'*e)^.5 * e - 6 * p(1) * e); %Derivatives (slow one by one computation) +% % end +% % end % %Thin plate covariance function (for 2D implicit shape -> does not seem to work) % K = 2 * pdist2(x1',x2').^2 .* log(pdist2(x1',x2')) - (1 + 2*log(p(1))) .* pdist2(x1',x2').^2 + p(1)^2; -% %RBF covariance function -% K = 1E-1 * exp(-1E-1^-1 * pdist2(x1',x2').^2); -% % size(x1) -% % size(x2) -% % dK(:,:,1) = 1E-1 * exp(-1E-1^-1 * pdist2(x1',x2').^2) .* repmat(x1(1,:)-x2(1,:), size(x1,2), 1); %Derivative -% % dK(:,:,2) = 1E-1 * exp(-1E-1^-1 * pdist2(x1',x2').^2) .* repmat(x1(2,:)-x2(2,:), size(x1,2), 1); %Derivative + %RBF covariance function + p = [5E-2^-1, 1E-4, 1E-2]; + K = p(3) * exp(-p(1) * pdist2(x1', x2').^2); %Kernel + dK(:,:,1) = -p(1) * p(3) * exp(-p(1) * pdist2(x1', x2').^2) .* substr(x1(1,:)',x2(1,:)); %Derivatives along x1 + dK(:,:,2) = -p(1) * p(3) * exp(-p(1) * pdist2(x1', x2').^2) .* substr(x1(2,:)',x2(2,:)); %Derivatives along x2 % for i=1:size(x1,2) % for j=1:size(x2,2) -% dK(i,j,:) = 1E-1 * exp(-1E-1^-1 * pdist2(x1(:,i)',x2(:,j)').^2) * (x1(:,i) - x2(:,j)); -% % e = x1(:,i) - x2(:,j); -% % dK(i,j,:) = 1E-1 * exp(-1E-1^-1 * e'*e) * e; +% K(i,j) = p(3) * exp(-p(1) * pdist2(x1(:,i)', x2(:,j)').^2); %Kernel (slow one by one computation) +% dK(i,j,:) = -p(1) * p(3) * exp(-p(1) * pdist2(x1(:,i)', x2(:,j)').^2) * (x1(:,i) - x2(:,j)); %Derivatives (slow one by one computation) % end % end if flag_noiseObs==1 - K = K + p(2) * eye(size(x1,2),size(x2,2)); %Consideration of noisy observation y + 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 diff --git a/demos/demo_ID01.m b/demos/demo_ID01.m index 9f9fc4cd0743d8041adec76a711fa391be4953d0..05cd79651d1e770e751bf33901ff4b17f9363ea2 100644 --- a/demos/demo_ID01.m +++ b/demos/demo_ID01.m @@ -32,29 +32,31 @@ kV = (2*kP)^.5; %Damping in task space % kV = 10; %Damping in task space kPq = 10; %Stiffness in joint space kVq = 1; %Damping in joint space -dt = 0.01; %Time step -nbData = 30; - +dt = 1E-2; %Time step +nbData = 100; %% Create robot %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -nbDOFs = 5; %Number of articulations -armLength = 0.3; %Length of each link +nbDOFs = 2; %Number of articulations + +model.l = 0.3; %Length of each link +model.m = 1.7; %Mass +model.g = 9.81; %Acceleration due to gravity + for k=1:nbDOFs - lnk(k).L = Link([0 0 armLength 0], 'standard'); %Links with dh = [THETA D A ALPHA SIGMA OFFSET] - lnk(k).L.m = 1; %Mass - lnk(k).L.r = [-armLength/2 0 0]; %Center of mass - %lnk(k).L.I = zeros(3); %Inertia - lnk(k).L.I = eye(3)*1E-2; %Inertia + lnk(k).L = Link([0 0 model.l 0], 'standard'); %Links with dh = [THETA D A ALPHA SIGMA OFFSET] + lnk(k).L.m = model.m; %Mass + lnk(k).L.r = [-model.l/2 0 0]; %Link COG (center of rod) + lnk(k).L.I = [0; 0; model.m * model.l^2 / 12]; %Inertia at link COG (rod of length L and mass m, https://en.wikipedia.org/wiki/List_of_moments_of_inertia) lnk(k).L.Jm = 0; %1E6; lnk(k).L.G = 0; lnk(k).L.B = 0; - %lnk(k).L.G = 1E-5; strTmp(k) = lnk(k).L; lnk(k).rob = SerialLink(strTmp); - lnk(k).rob.gravity = [0 9.81 0]; %for 2D robot + lnk(k).rob.gravity = [0 model.g 0]; %for 2D robot end robot = lnk(end).rob; + %Initial pose q0(:,1) = ones(nbDOFs,1)*pi/4; Htmp = robot.fkine(q0); @@ -72,33 +74,49 @@ dx = zeros(2,1); dq = zeros(nbDOFs,1); for t=1:nbData r.q(:,t) = q; %Log data + Htmp = robot.fkine(q); x = Htmp.t(1:2); J = robot.jacob0(q,'trans'); J = J(1:2,:); - tauG = robot.gravload(q')'; %Compute gravity compensation term + + uG = robot.gravload(q')'; %Compute torque due to gravity +% uG = cos(q) * model.l * model.m * model.g / 2; %Compute torque due to gravity + %Dynamically consistent nullspace (Jinv=pinv(J) would not work) - JI = robot.inertia(q'); %Joint inertia - CI = J/JI*J' + eye(2)*1E-12; %Cartesian inertia - W = inv(JI); + M = robot.inertia(q') %Joint inertia +% M = model.m * model.l^2 / 3; %Inertia at link frame origin (rod of length L and mass m, https://en.wikipedia.org/wiki/List_of_moments_of_inertia) + + Mx = inv(J / M * J' + eye(2)*1E-12); %Cartesian inertia + W = inv(M); %W = eye(nbDOFs); - Jinv = W * J' / (J*W*J'); %Generalized inverse (weighted pseudoinverse) + Jinv = W * J' / (J*W*J' + eye(2)*1E-12); %Generalized inverse (weighted pseudoinverse) N = eye(nbDOFs) - J'*Jinv'; %Nullspace projection matrix (dynamically consistent) %N = (eye(nbDOFs) - Jinv*J)'; %Same as the line above but with Roy Featherston's paper notation %N = eye(nbDOFs) - pinv(J)*J; %Nullspace projection matrix (for standard least squares solution) %N = eye(nbDOFs) - J'*pinv(J)'; %Same as the line above (because of symmetry) %Computed torque control command -% tau = J'/ CI * (ddxh + kP*(xh-x) + kV*(dxh-dx)) + N * JI*(kPq*(qh-q)-kVq*dq) + tauG; -% tau = J'/ CI * (kP*(xh-x)-kV*dx) + N * (kPq*(qh-q)-kVq*dq) + tauG; -% tau = J' * (kP*(xh-x)-kV*dx) + N * (kPq*(qh-q)-kVq*dq) + tauG; - tau = N * (kPq*(qh-q)-kVq*dq) + tauG; +% u = J'* Mx * (ddxh + kP*(xh - x) + kV*(dxh - dx)) + N * M *(kPq * (qh - q) - kVq * dq) + uG; +% u = J'* Mx * (kP * (xh - x) - kV * dx) + N * (kPq * (qh - q) - kVq * dq) + uG; +% u = J' * (kP * (xh - x) - kV * dx) + N * (kPq * (qh - q) - kVq * dq) + uG; +% u = N * (kPq * (qh - q) - kVq * dq) + uG; +% u = uG; + u = rand(nbDOFs,1) * 1E-1 + uG; + +% robot.inertia(q') +% uG = robot.gravload(q')' + +% ddq = robot.accel(q', dq', u'); %Compute acceleration + ddq = accel(q, u, model); + pause +% ddq = (u - uG) / M; %Compute acceleration - ddq = robot.accel(q', dq', tau'); dq = dq + ddq*dt; - dx = J*dq; q = q + dq*dt; + + dx = J * dq; end @@ -106,11 +124,34 @@ end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% figure('position',[20,10,1800,1200],'color',[1 1 1]); hold on; axis off; for t=round(linspace(1,nbData,10)) - plotArm(r.q(:,t), ones(nbDOFs,1)*armLength, [0;0;t*0.1], .02, [.7 .7 .7]); + plotArm(r.q(:,t), ones(nbDOFs,1)*model.l, [0;0;t*0.1], .02, [.7 .7 .7]-.7*t/nbData); end plot(xh(1),xh(2),'r+'); -axis([-.2 1 -.2 1]); axis equal; set(gca,'xtick',[],'ytick',[]); +axis equal; %axis([-.2 1 -.2 1]); %print('-dpng','demoID01.png'); pause; -close all; \ No newline at end of file +close all; +end + +%%%%%%%%%%%%%%%%%%%%%% +%Rollout +function ddq = accel(q, u, model) + for n=1:size(q,1) + M = model.m * model.l^2 / 3 %Inertia at link frame origin (rod of length L and mass m, https://en.wikipedia.org/wiki/List_of_moments_of_inertia) + uG = cos(q(n)) * model.l * model.m * model.g / 2; %Compute torque due to gravity + ddq(n) = (u(n) - uG) / M; + end +end + +%%%%%%%%%%%%%%%%%%%%%% +%Jacobian with numerical computation +function J = jacob0(q, model) + e = 1E-6; + J = zeros(2,size(q,1)); + for n=1:size(q,1) + qtmp = q; + qtmp(n) = qtmp(n) + e; + J(:,n) = (fkine(qtmp, model) - fkine(q, model)) / e; + end +end \ No newline at end of file diff --git a/demos/demo_IK01.m b/demos/demo_IK01.m index e93d44c6d2d470882fd65974daa7a3166fb1fb7c..03a4d2aa379dd50381c8a68907473d56d644c9ec 100644 --- a/demos/demo_IK01.m +++ b/demos/demo_IK01.m @@ -1,111 +1,104 @@ -function demo_IK01 -% Inverse kinematics with nullspace. -% -% This demo requires the robotics toolbox RTB10 (http://petercorke.com/wordpress/toolboxes/robotics-toolbox). -% First run 'startup_rvc' from the robotics toolbox. -% -% Copyright (c) 2019 Idiap Research Institute, http://idiap.ch/ -% Written by Sylvain Calinon, http://calinon.ch/ -% -% This file is part of PbDlib, http://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 -% published by the Free Software Foundation. -% -% PbDlib 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 PbDlib. If not, see <http://www.gnu.org/licenses/>. - -addpath('./m_fcts/'); -disp('This demo requires the robotics toolbox RTB10 (http://petercorke.com/wordpress/toolboxes/robotics-toolbox).'); - - -%% Parameters -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -dt = 0.01; %Time step -nbData = 100; - - -%% Robot parameters -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -nbDOFs = 3; %Number of articulations -armLength = 0.6; %Length of each link -L1 = Link('d', 0, 'a', armLength, 'alpha', 0); -robot = SerialLink(repmat(L1,nbDOFs,1)); -%Initial pose -q(:,1) = [pi/2 pi/2 pi/3]; %ones(1,nbDOFs) .* pi/3; - - -%% IK with nullspace -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -dxh = [0; 0]; -%dxh = 0; - -%dqh = ones(nbDOFs,1)*1; -%dqh = [-1; zeros(nbDOFs-1,1)]; - -for t=1:nbData - r.q(:,t) = q; %Log data - -% Htmp = robot.fkine(q); -% r.x(:,t) = Htmp.t(1:2); - - J = robot.jacob0(q,'trans'); - J = J(1:2,:); - %J = J(2,:); - -% pinvJ = pinv(J); -% pinvJ = J' / ( J * J'); -% pinvJ = (J' * J) \ J'; - [U,S,V] = svd(J); - S(S>0) = S(S>0).^-1; - pinvJ = V*S'*U'; - - %Kx = J*Kq*J'; % Stiffness at the end-effector - %robot.maniplty(q) %Manipulability index - -% %Nullspace projection matrix -% N = eye(nbDOFs) - pinvJ*J; -% %N = eye(nbDOFs) - J'*pinv(J)' - - -% %Alternative way of computing the nullspace projection matrix, see e.g. wiki page on svd -% %(https://en.wikipedia.org/wiki/Singular-value_decomposition) or -% %http://math.stackexchange.com/questions/421813/projection-matrix-onto-null-space -% %[U,S,V] = svd(J); - sp = (sum(S,1)<1E-1); %Span of zero rows - N = V(:,sp) * V(:,sp)'; - -% [U,S,V] = svd(pinvJ); -% sp = (sum(S,2)<1E-1); %Span of zero rows -% N = U(:,sp) * U(:,sp)'; %N = U * [0 0 0; 0 0 0; 0 0 1] * U' -% % d = zeros(nbDOFs,1); -% % d(sp) = 1; -% % N = U * diag(d) * U'; - -% dqh = [5*(pi/4-q(1)); zeros(nbDOFs-1,1)]; - dqh = ones(nbDOFs,1); - - dq = pinvJ * dxh + N * dqh; - q = q + dq * dt; -end - -%% Plots -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -figure('position',[20,10,1000,650],'color',[1 1 1]); hold on; axis off; -%plotopt = robot.plot({'noraise', 'nobase', 'noshadow', 'nowrist', 'nojaxes'}); -for t=round(linspace(1,nbData,10)) - colTmp = [1,1,1] - [.7,.7,.7] * t/nbData; - plotArm(r.q(:,t), ones(nbDOFs,1)*armLength, [0;0;t*0.1], .02, colTmp); - %robot.plot(r.q(:,t)', plotopt); -end -axis equal; axis tight; - -%print('-dpng','graphs/demoIK01.png'); -pause; -close all; \ No newline at end of file +function demo_IK01 +% Basic forward and inverse kinematics for a planar robot, with numerical Jacobian computation. +% +% If this code is useful for your research, please cite the related publication: +% @article{Silverio19TRO, +% author="Silv\'erio, J. and Calinon, S. and Rozo, L. and Caldwell, D. G.", +% title="Learning Task Priorities from Demonstrations", +% journal="{IEEE} Trans. on Robotics", +% year="2019", +% volume="35", +% number="1", +% pages="78--94", +% doi="10.1109/TRO.2018.2878355" +% } +% +% Copyright (c) 2020 Idiap Research Institute, http://idiap.ch/ +% Written by Sylvain Calinon, http://calinon.ch/ +% +% This file is part of PbDlib, http://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 +% published by the Free Software Foundation. +% +% PbDlib 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 PbDlib. If not, see <http://www.gnu.org/licenses/>. + +addpath('./m_fcts/'); + + +%% Parameters +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +dt = 1E-2; %Time step +nbData = 100; + + +%% Robot parameters +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +model.nbDOFs = 2; %Number of articulations +model.l = 0.6; %Length of each link +q(:,1) = [pi/2; pi/2; pi/3]; %Initial pose +% q = rand(model.nbDOFs,1); + + +%% IK +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +dxh = [.1; 0]; +for t=1:nbData-1 + J = jacob0(q(:,t), model); %Jacobian + dq = pinv(J) * dxh; + q(:,t+1) = q(:,t) + dq * dt; + x(:,t+1) = fkine(q(:,t+1), model); %FK for a planar robot +end + + +%% Plots +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +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), ones(model.nbDOFs,1)*model.l, [0;0;-2+t/nbData], .03, colTmp); + plot(x(1,t), x(2,t), '.','markersize',50,'color',[.8 0 0]); +end +plot(x(1,:), x(2,:), '.','markersize',20,'color',[0 0 0]); +axis equal; axis tight; + +%print('-dpng','graphs/demoIK01.png'); +pause; +close all; +end + +%%%%%%%%%%%%%%%%%%%%%% +%Forward kinematics +function [x, Tf] = fkine(q, model) + Tf = eye(4); + T = repmat(Tf, [1,1,size(q,1)]); + for n=1:size(q,1) + 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 + Tf = Tf * T(:,:,n); + end + x = Tf(1:2,end); +end + +%%%%%%%%%%%%%%%%%%%%%% +%Jacobian with numerical computation +function J = jacob0(q, model) + e = 1E-6; + J = zeros(2,size(q,1)); + for n=1:size(q,1) + qtmp = q; + qtmp(n) = qtmp(n) + e; + J(:,n) = (fkine(qtmp, model) - fkine(q, model)) / e; + end +end \ No newline at end of file diff --git a/demos/demo_IK02.m b/demos/demo_IK02.m index 50ebc1ab410e284bd54fd525459ea140f231a450..d1198fac12c7d14129ae34d77b9c384cc7039128 100644 --- a/demos/demo_IK02.m +++ b/demos/demo_IK02.m @@ -1,8 +1,5 @@ function demo_IK02 -% Inverse kinematics with two arms and nullspace. -% -% This demo requires the robotics toolbox RTB10 (http://petercorke.com/wordpress/toolboxes/robotics-toolbox). -% First run 'startup_rvc' from the robotics toolbox. +% Inverse kinematics with nullspace projection operator. % % If this code is useful for your research, please cite the related publication: % @article{Silverio19TRO, @@ -15,8 +12,11 @@ function demo_IK02 % pages="78--94", % doi="10.1109/TRO.2018.2878355" % } -% -% Copyright (c) 2019 Idiap Research Institute, http://idiap.ch/ +% +% The commented parts of this demo require the robotics toolbox RTB10 (http://petercorke.com/wordpress/toolboxes/robotics-toolbox). +% First run 'startup_rvc' from the robotics toolbox if you uncomment these parts. +% +% Copyright (c) 2020 Idiap Research Institute, http://idiap.ch/ % Written by Sylvain Calinon, http://calinon.ch/ % % This file is part of PbDlib, http://www.idiap.ch/software/pbdlib/ @@ -34,92 +34,119 @@ function demo_IK02 % along with PbDlib. If not, see <http://www.gnu.org/licenses/>. addpath('./m_fcts/'); -disp('This demo requires the robotics toolbox RTB10 (http://petercorke.com/wordpress/toolboxes/robotics-toolbox).'); %% Parameters %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% dt = 0.01; %Time step -nbData = 500; %Numer of points in a trajectory +nbData = 100; -%% Create robot +%% Robot parameters %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%Robot parameters -nbDOFs = 5; %Number of articulations -armLength = 0.6; %Length of each link -L1 = Link('d', 0, 'a', armLength, 'alpha', 0); -arm = SerialLink(repmat(L1,3,1)); +nbDOFs = 3; %Number of articulations +model.l = 0.6; %Length of each link +% L1 = Link('d', 0, 'a', model.l, 'alpha', 0); +% robot = SerialLink(repmat(L1,nbDOFs,1)); -%Initial pose -q0(:,1) = [pi/2 pi/2 pi/3 -pi/2 -pi/3]; -q = q0; +q(:,1) = [pi/2 pi/2 pi/3]; %Initial pose %% IK with nullspace %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -r=[]; -for t=1:nbData - r.q(:,t)=q; %Log data - - Htmp = arm.fkine(q([1,4:5])); - r.rx(:,t) = Htmp.t(1:2); - Htmp = arm.fkine(q(1:3)); - r.lx(:,t) = Htmp.t(1:2); +dxh = [0; 0]; +%dxh = 0; - if t==1 - rxh = [linspace(r.rx(1,1),r.rx(1,1)+.3,nbData); linspace(r.rx(2,1),r.rx(2,1)+1.2,nbData)]; - lxh = [linspace(r.lx(1,1),r.lx(1,1)-.3,nbData); linspace(r.lx(2,1),r.lx(2,1)+1.2,nbData)]; - end +%dqh = ones(nbDOFs,1)*1; +%dqh = [-1; zeros(nbDOFs-1,1)]; - rJ = arm.jacob0(q([1,4:5]),'trans'); - rJ = rJ(1:2,:); +for t=1:nbData + r.q(:,t) = q; %Log data +% Htmp = robot.fkine(q); +% r.x(:,t) = Htmp.t(1:2); + r.x(:,t) = fkine(q, model); %Log data - lJ = arm.jacob0(q(1:3),'trans'); - lJ = lJ(1:2,:); - - J = lJ; - J(3:4,[1,4:5]) = rJ; +% J = robot.jacob0(q,'trans'); +% J = J(1:2,:); + J = jacob0(q, model); + +% pinvJ = pinv(J); +% pinvJ = J' / ( J * J'); +% pinvJ = (J' * J) \ J'; + [U,S,V] = svd(J); + S(S>0) = S(S>0).^-1; + pinvJ = V*S'*U'; - Ja = J(1:2,:); - Jb = J(3:4,:); + %Kx = J*Kq*J'; % Stiffness at the end-effector + %robot.maniplty(q) %Manipulability index -% Na = eye(nbDOFs) - pinv(Ja) * Ja; %Nullspace projection matrix - Nb = eye(nbDOFs) - pinv(Jb) * Jb; %Nullspace projection matrix +% %Nullspace projection matrix +% N = eye(nbDOFs) - pinvJ*J; +% %N = eye(nbDOFs) - J'*pinv(J)' + + +% %Alternative way of computing the nullspace projection matrix, see e.g. wiki page on svd +% %(https://en.wikipedia.org/wiki/Singular-value_decomposition) or +% %http://math.stackexchange.com/questions/421813/projection-matrix-onto-null-space +% %[U,S,V] = svd(J); + sp = (sum(S,1)<1E-1); %Span of zero rows + N = V(:,sp) * V(:,sp)'; - ldx = 100 * (lxh(:,t) - r.lx(:,t)); - rdx = 100 * (rxh(:,t) - r.rx(:,t)); +% [U,S,V] = svd(pinvJ); +% sp = (sum(S,2)<1E-1); %Span of zero rows +% N = U(:,sp) * U(:,sp)'; %N = U * [0 0 0; 0 0 0; 0 0 1] * U' +% % d = zeros(nbDOFs,1); +% % d(sp) = 1; +% % N = U * diag(d) * U'; - %Prioritized bimanual tracking task - Ja_mod = Ja * Nb; - pinvJa_mod = Ja_mod' / (Ja_mod * Ja_mod' + eye(2) .* 1E-1); - dqb = pinv(Jb) * rdx; - dq = dqb + Nb * pinvJa_mod * (ldx - Ja * dqb); -% dq = dqb + Nb * pinv(Ja) * ldx; %Approximation +% dqh = [5*(pi/4-q(1)); zeros(nbDOFs-1,1)]; + dqh = ones(nbDOFs,1); - q = q + dq*dt; + dq = pinvJ * dxh + N * dqh; + q = q + dq * dt; end - %% Plots %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -figure('position',[10,10,2300,1200],'color',[1 1 1]); hold on; axis off; -listT = round(linspace(1,nbData,10)); -i=0; -for t=listT - i=i+1; - colTmp = [.9,.9,.9] - [.7,.7,.7] * i/length(listT); - plotArm(r.q(1:3,t), ones(3,1)*armLength, [0;0;i], .03, colTmp); %left arm - plotArm(r.q([1,4:5],t), ones(3,1)*armLength, [0;0;i+0.1], .03, colTmp); %right arm +figure('position',[20,10,1000,650],'color',[1 1 1]); hold on; axis off; +%plotopt = robot.plot({'noraise', 'nobase', 'noshadow', 'nowrist', 'nojaxes'}); +for t=round(linspace(1,nbData,10)) + %robot.plot(r.q(:,t)', plotopt); + colTmp = [1,1,1] - [.7,.7,.7] * t/nbData; + plotArm(r.q(:,t), ones(nbDOFs,1)*model.l, [0;0;t*0.1], .02, colTmp); end -plot3(rxh(1,:), rxh(2,:), ones(1,nbData)*20, '-','linewidth',2,'color',[.8 0 0]); -plot3(lxh(1,:), lxh(2,:), ones(1,nbData)*20, '-','linewidth',2,'color',[.8 0 0]); -plot3(rxh(1,listT), rxh(2,listT), ones(1,10)*20, '.','markersize',25,'color',[.8 0 0]); -plot3(lxh(1,listT), lxh(2,listT), ones(1,10)*20, '.','markersize',25,'color',[.8 0 0]); - -%axis([-.2 1 -.2 1]); axis equal; axis tight; -% print('-dpng','graphs/demoIK02.png'); +%print('-dpng','graphs/demoIK02.png'); pause; -close all; \ No newline at end of file +close all; +end + +%%%%%%%%%%%%%%%%%%%%%% +%Forward kinematics +function [x, Tf] = fkine(q, model) + Tf = eye(4); + T = repmat(Tf, [1,1,size(q,1)]); + for n=1:size(q,1) + 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 + Tf = Tf * T(:,:,n); + end + x = Tf(1:2,end); +end + +%%%%%%%%%%%%%%%%%%%%%% +%Jacobian with numerical computation +function J = jacob0(q, model) + e = 1E-6; + J = zeros(2,size(q,1)); + for n=1:size(q,1) + qtmp = q; + qtmp(n) = qtmp(n) + e; + J(:,n) = (fkine(qtmp, model) - fkine(q, model)) / e; + end +end \ No newline at end of file diff --git a/demos/demo_IK_nullspaceAsProduct01.m b/demos/demo_IK_nullspaceAsProduct01.m index 5737f985436fdb6da54d9079365067e060d12c2a..5c9d461fed329cf8b2520997fa0eb7bf4267595d 100644 --- a/demos/demo_IK_nullspaceAsProduct01.m +++ b/demos/demo_IK_nullspaceAsProduct01.m @@ -1,5 +1,6 @@ function demo_IK_nullspaceAsProduct01 % 3-level nullspace control formulated as product of Gaussians (PoG). +% (see also demo_IK_weighted01.m) % % This demo requires the robotics toolbox RTB10 (http://petercorke.com/wordpress/toolboxes/robotics-toolbox). % First run 'startup_rvc' from the robotics toolbox. diff --git a/demos/demo_IK_quat01.m b/demos/demo_IK_quat01.m index cb911e77fb4296757fc210fa12a6aa03b1b78f34..2de809f311467f8574a1775c192827a2258e8494 100644 --- a/demos/demo_IK_quat01.m +++ b/demos/demo_IK_quat01.m @@ -1,11 +1,12 @@ function demo_IK_quat01 % Inverse kinematics for orientation data represented as unit quaternions. +% (see also demo_IK_orient01.m) % -% This demo requires the robotics toolbox RTB10 (http://petercorke.com/wordpress/toolboxes/robotics-toolbox). -% First run 'startup_rvc' from the robotics toolbox. +% Copyright (c) 2020 Idiap Research Institute, http://idiap.ch/ +% Written by Sylvain Calinon, http://calinon.ch/ % -% Copyright (c) 2019 Idiap Research Institute, http://idiap.ch/ -% Written by João Silvério and Sylvain Calinon +% The commented parts of this demo require the robotics toolbox RTB10 (http://petercorke.com/wordpress/toolboxes/robotics-toolbox). +% First run 'startup_rvc' from the robotics toolbox if you uncomment these parts. % % This file is part of PbDlib, http://www.idiap.ch/software/pbdlib/ % @@ -22,34 +23,28 @@ function demo_IK_quat01 % along with PbDlib. If not, see <http://www.gnu.org/licenses/>. addpath('./m_fcts/'); -disp('This demo requires the robotics toolbox RTB10 (http://petercorke.com/wordpress/toolboxes/robotics-toolbox).'); %% Parameters %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% dt = 0.01; %Time step -nbData = 100; +nbData = 100; %Number of points in a trajectory +Kp = 1E-1; %Tracking gain +nbDOFs = 5; %Number of articulations +model.l = 0.2; %Length of links -%% Create robot -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%Robot parameters (based on mdl_twolink.m model) -nbDOFs = 5; %Nb of degrees of freedom -armLength = 0.2; -L1 = Link('d', 0, 'a', armLength, 'alpha', 0); -robot = SerialLink(repmat(L1,nbDOFs,1)); -%Initial pose -% q0(:,1) = [pi/2 pi/2 pi/3]; -q0(:,1) = [pi/5 pi/5 pi/5 pi/8 pi/8]; +q0 = rand(nbDOFs,1) * pi/2; %Initial pose +% q0 = [pi/5; pi/5; pi/5; pi/8; pi/8]; %Initial pose -%Set desired pose (pointing vertically) -% Htmp = robot.fkine([pi/2 pi/2 pi/2]); -Htmp = robot.fkine([pi/5 pi/5 pi/5 pi/5 pi/5]); +% L1 = Link('d', 0, 'a', model.l, 'alpha', 0); +% robot = SerialLink(repmat(L1,nbDOFs,1)); +% %Set desired pose (pointing vertically) +% Htmp = robot.fkine(ones(1,nbDOFs)*pi/5); +% Qh = UnitQuaternion(Htmp) % Q denotes quaternion, q denotes joint position +% % Qh = Quaternion(-pi/4, [0 0 1]); % -> Quaternion(angle,vector) -Qh = UnitQuaternion(Htmp); % Q denotes quaternion, q denotes joint position -% Qh = Quaternion(-pi/4, [0 0 1]); % -> Quaternion(angle,vector) -% Qh = Quaternion(-3*pi/4, [0 0 1]); -% Qh = Quaternion(-rand*pi/4, [0 0 1]); +[~, Qh] = fkine(ones(nbDOFs,1)*pi/5, model); %% IK @@ -57,26 +52,102 @@ Qh = UnitQuaternion(Htmp); % Q denotes quaternion, q denotes joint position q = q0; for t=1:nbData r.q(:,t) = q; %Log data - Htmp = robot.fkine(q); - Q = UnitQuaternion(Htmp); - J = robot.jacob0(q,'rot'); - dx = angDiffFromQuat(Qh,Q) / dt; - dq = pinv(J) * dx; + +% Htmp = robot.fkine(q); +% Q = UnitQuaternion(Htmp); +% J = robot.jacob0(q,'rot'); +% dx = angDiffFromQuat(Qh, Q) / dt +% +% u = logmap(Qh.double', Q.double'); +% dx = 4 * omegaConversionMatrix(Q.double') * u / dt + + [~, Q] = fkine(q, model); + %Keep quaternion with closest difference + if(Qh'*Q<0) + Q = -Q; + end + + dx = 4 * omegaConversionMatrix(Q) * logmap(Qh, Q) / dt; + + J = [zeros(2,nbDOFs); ones(1, nbDOFs)]; %Jacobian for orientation data (corresponds to a constant matrix for planar robots) +% [~, J] = jacob0(q, model); + + dq = pinv(J) * Kp * dx; q = q + dq * dt; end %% Plots %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -figure('position',[20,10,1000,650]); hold on; +figure('position',[20,10,1000,650]); hold on; axis off; %plotopt = robot.plot({'noraise', 'nobase', 'noshadow', 'nowrist', 'nojaxes'}); -for t=round(linspace(1,nbData,10)) - colTmp = [1,1,1] - [.7,.7,.7] * t/nbData; - plotArm(r.q(:,t), ones(nbDOFs,1)*armLength, [0;0;t*0.1], .02, colTmp); +for t=round(linspace(1,nbData,2)) + colTmp = [.8,.8,.8] - [.7,.7,.7] * t/nbData; + plotArm(r.q(:,t), ones(nbDOFs,1)*model.l, [0;0;t*0.1], .02, colTmp); %robot.plot(r.q(:,t)', plotopt); end -axis([-.2 1 -0.4 1]); axis equal; set(gca,'xtick',[],'ytick',[]); +axis([-.2 1 -0.4 1]); axis equal; %print('-dpng','graphs/demoIK_quat02.png'); pause; -close all; \ No newline at end of file +close all; +end + +function x = expmap(u, x0) + theta = sqrt(sum(u.^2,1)); %norm(u,'fro') + x = real(repmat(x0,[1,size(u,2)]) .* repmat(cos(theta),[size(u,1),1]) + u .* repmat(sin(theta)./theta,[size(u,1),1])); + x(:,theta<1e-16) = repmat(x0,[1,sum(theta<1e-16)]); +end + +function u = logmap(x, x0) + theta = acos(x0'*x); %acos(trace(x0'*x)) + u = (x - repmat(x0,[1,size(x,2)]) .* repmat(cos(theta),[size(x,1),1])) .* repmat(theta./sin(theta),[size(x,1),1]); + u(:,theta<1e-16) = 0; +end + +function G = omegaConversionMatrix(q) +%See Basile Graf (2017) "Quaternions And Dynamics" for definition of E and G + G = [-q(2) q(1) -q(4) q(3); ... + -q(3) q(4) q(1) -q(2); ... + -q(4) -q(3) q(2) q(1)]; %E +% G = [-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 + +%%%%%%%%%%%%%%%%%%%%%% +%Forward kinematics +function [xp, xo, Tf] = fkine(q, model) + Tf = eye(4); + T = repmat(Tf, [1,1,size(q,1)]); + for n=1:size(q,1) + 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 + Tf = Tf * T(:,:,n); + end + xp = Tf(1:2,end); %Position + xo = atan2(Tf(2,1), Tf(1,1)); %Orientation (as single Euler angle for planar robot) + xo = [cos(xo/2); [0;0;1] * sin(xo/2)]; %Orientation (as unit quaternion) +% xo = rotm2quat(Tf(1:3,1:3)); %Orientation (as unit quaternion) +end + +%%%%%%%%%%%%%%%%%%%%%% +%Jacobian with numerical computation +function [Jp, Jo] = jacob0(q, model) + e = 1E-4; + Jp = zeros(2, size(q,1)); %Jacobian for position data + Jo = [zeros(2, size(q,1)); ones(1, size(q,1))]; %Jacobian for orientation data (corresponds to a vector with 1 elements for planar robots) + for n=1:size(q,1) + qtmp = q; + qtmp(n) = qtmp(n) + e; + Jp(:,n) = (fkine(qtmp, model) - fkine(q, model)) / e; +% [xp2, xo2] = fkine(qtmp, model); +% [xp1, xo1] = fkine(q, model); +% Jp(:,n) = (xp2 - xp1) / e; +% Jo(:,n) = (xo2 - xo1) / e; + end +end \ No newline at end of file diff --git a/demos/demo_IK_quat02.m b/demos/demo_IK_quat02.m index 92b08725b0f96d68e99eb56992966a2348be7572..92054799421db5e944e4295e0790e386c42f2830 100644 --- a/demos/demo_IK_quat02.m +++ b/demos/demo_IK_quat02.m @@ -28,9 +28,9 @@ disp('This demo requires the robotics toolbox RTB10 (http://petercorke.com/wordp %% Parameters %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -dt = 0.01; %Time step +dt = 1E-2; %Time step nbData = 100; %Number of datapoints -Kp = 2; %Tracking gain +Kp = 2E-1; %Tracking gain %% Create robot @@ -38,12 +38,16 @@ Kp = 2; %Tracking gain %Robot parameters (built from function that contains WAM D-H parameters) %[robot,L] = initWAMstructure('WAM'); [robot, link] = initiCubstructure('iCub'); -nbDOFs = robot.n; +nbDOFs = robot.n; %Number of articulations %Initial pose -q0(:,1) = zeros(1,nbDOFs); +q0 = zeros(nbDOFs,1); + %Set desired orientation -Qh = UnitQuaternion([0 0 1 0]); % Aligned with the basis frame +% Qh = UnitQuaternion([0 0 1 0]); % Aligned with the basis frame +qh = ones(nbDOFs,1) * 2E-1; +Htmp = robot.fkine(qh); +Qh = UnitQuaternion(Htmp); %% IK @@ -53,37 +57,57 @@ for t=1:nbData r.q(:,t) = q; %Log data Htmp = robot.fkine(q); Q = UnitQuaternion(Htmp); - Jw = robot.jacob0(q,'rot'); - - %The new Jacobian is built from the geometric Jacobian to allow the - %tracking of quaternion velocities in Cartesian space - J = 0.5 * QuatToMatrix(Q) * [zeros(1,nbDOFs);Jw]; - - %Compute the quaternion derivative - %-> The quaternion derivative at time t is given by: - %dq(t) = (1/2) * q(t) * w(t), where w(t) is the angular velocity + %Keep quaternion with closest difference + if(Qh.inner(Q)<0) + Q = Quaternion(-Q.double); + end - w = Kp*2*quaternionLog(Qh*Q.inv); % first compute angular velocity - dQh = 0.5*Q*UnitQuaternion([0 w]); % quaternion derivative + Jw = robot.jacob0(q,'rot'); - r.Q(t,:) = Q.double; %Log the quaternion at each instant +% %The new Jacobian is built from the geometric Jacobian to allow the tracking of quaternion velocities in Cartesian space +% J = 0.5 * QuatToMatrix(Q) * [zeros(1,nbDOFs); Jw]; +% +% %Compute the quaternion derivative +% %-> The quaternion derivative at time t is given by: +% %dq(t) = (1/2) * q(t) * w(t), where w(t) is the angular velocity +% +% w = Kp * 2 * quaternionLog(Qh * Q.inv); % first compute angular velocity +% dQh = 0.5 * Q * UnitQuaternion([0 w]); % quaternion derivative +% +% r.Q(t,:) = Q.double; %Log the quaternion at each instant +% +% dq = pinv(J) * dQh.double'; % now with a quaternion derivative reference +% %N = eye(nbDOFs) - pinv(J)*J; %Nullspace +% %dq = pinv(J) * dQh.double' + N * [1; 0; 0; 0; 0]; +% %dq = N * [-1; -1; 0; 0; 1]; - dq = pinv(J) * dQh.double'; % now with a quaternion derivative reference - %N = eye(nbDOFs) - pinv(J)*J; %Nullspace - %dq = pinv(J) * dQh.double' + N * [1; 0; 0; 0; 0]; - %dq = N * [-1; -1; 0; 0; 1]; + + %The two functions below return the same dx + dx = 4 * omegaConversionMatrix(Q.double') * logmap(Qh.double', Q.double') / dt; +% dx = angDiffFromQuat(Qh.double', Q.double') / dt; + dq = pinv(Jw) * dx * Kp; q = q + dq * dt; end +Qh.double' +Q.double' %% Plots % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% figure('position',[20,10,1000,650]); hold on; rotate3d on; +plot3Dframe(eye(3)*5E-2, zeros(3,1)); % %Plot animation of the movement (with robotics toolbox functionalities) % plotopt = robot.plot({'noraise', 'nobase', 'noshadow', 'nowrist', 'nojaxes'}); % robot.plot(r.q'); %'floorlevel',-0.5 +for i=1:nbDOFs + T = link(i).fkine(qh(1:i)); + posTmp(:,i+1) = T.t(1:3,end); +end +plot3(posTmp(1,:),posTmp(2,:),posTmp(3,:), '-','linewidth',2,'color',[.8 0 0]); +plot3(posTmp(1,:),posTmp(2,:),posTmp(3,:), '.','markersize',18,'color',[.8 0 0]); + %Plot animation of the movement (with standard plot functions) posTmp(:,1) = zeros(3,1); @@ -97,7 +121,6 @@ for t=round(linspace(1,nbData,10)) plot3(posTmp(1,:),posTmp(2,:),posTmp(3,:), '.','markersize',18,'color',colTmp); % plot3Dframe(T.t(1:3,1:3)*1E-1, T.t(1:3,end), min(eye(3)+colTmp(1,1),1)); end -plot3Dframe(eye(3)*2E-1, zeros(3,1)); set(gca,'xtick',[],'ytick',[],'ztick',[]); xlabel('x_1'); ylabel('x_2'); zlabel('x_3'); view(3); axis equal; axis vis3d; @@ -110,4 +133,27 @@ view(3); axis equal; axis vis3d; % xlabel('t'); pause; -close all; \ No newline at end of file +close all; +end + +function x = expmap(u, x0) + theta = sqrt(sum(u.^2,1)); %norm(u,'fro') + x = real(repmat(x0,[1,size(u,2)]) .* repmat(cos(theta), [size(u,1),1]) + u .* repmat(sin(theta)./theta, [size(u,1),1])); + x(:,theta<1e-16) = repmat(x0, [1,sum(theta<1e-16)]); +end + +function u = logmap(x, x0) + theta = acos(x0'*x); %acos(trace(x0'*x)) + u = (x - repmat(x0, [1,size(x,2)]) .* repmat(cos(theta), [size(x,1),1])) .* repmat(theta./sin(theta), [size(x,1),1]); + u(:,theta<1e-16) = 0; +end + +function G = omegaConversionMatrix(q) +%See Basile Graf (2017) "Quaternions And Dynamics" for definition of E and G + G = [-q(2) q(1) -q(4) q(3); ... + -q(3) q(4) q(1) -q(2); ... + -q(4) -q(3) q(2) q(1)]; %E +% G = [-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 \ No newline at end of file diff --git a/demos/demo_IK_weighted01.m b/demos/demo_IK_weighted01.m index 119574c89b7347a1b6e544c62176cf28dc053dcd..f53c447c7531b7d95b92c87e4c1859d64a5f9760 100644 --- a/demos/demo_IK_weighted01.m +++ b/demos/demo_IK_weighted01.m @@ -1,5 +1,6 @@ function demo_IK_weighted01 % Inverse kinematics with nullspace control, by considering weights in both joint space and in task space. +% (see also demo_IK_nullspaceAsProduct01.m) % % This demo requires the robotics toolbox RTB10 (http://petercorke.com/wordpress/toolboxes/robotics-toolbox). % First run 'startup_rvc' from the robotics toolbox. @@ -48,10 +49,12 @@ Wq = diag([1E-44, ones(1,nbDOFs-1)]); %Weight in configuration space (-> we don' %% Create robot %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -armLength = 0.3; -L1 = Link('d', 0, 'a', armLength, 'alpha', 0); +model.l = 0.3; + +L1 = Link('d', 0, 'a', model.l, 'alpha', 0); robot = SerialLink(repmat(L1,nbDOFs,1)); robot2 = SerialLink(repmat(L1,3,1)); + q0(:,1) = [pi/4; zeros(nbDOFs-1,1)]; %Initial pose @@ -66,14 +69,19 @@ xh = [-0.2; 0.8]; xh2 = [0; 0.4]; for t=1:nbData r(1).q(:,t) = q; %Log data - J = robot.jacob0(q,'trans'); - J = J(1:2,:); - J2 = [J(1:2,1:3), zeros(2,nbDOFs-3)]; + Htmp = robot.fkine(q); x = Htmp.t(1:2); Htmp2 = robot2.fkine(q(1:3)); x2 = Htmp2.t(1:2); + J = robot.jacob0(q,'trans'); + J = J(1:2,:); + +% x = fkine(q, model); +% x2 = fkine(q(1:3), model); +% J = jacob0(q, model); + J2 = [J(1:2,1:3), zeros(2, nbDOFs-3)]; Jw = Vx * J * Vq; pinvJw = pinv(Jw); N = eye(nbDOFs) - pinvJw * Jw; @@ -98,22 +106,22 @@ end %% Plots %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -figure('position',[20,10,1000,650],'color',[1 1 1]); hold on; axis off; +figure('position',[20,10,2000,1300],'color',[1 1 1]); hold on; axis off; h(1) = plot3(xh(1), xh(2), 11, '.','markersize',25,'color',[.4 1 .4]); h(2) = plot3(xh2(1), xh2(2), 11, '.','markersize',25,'color',[.4 .4 1]); -htmp = plotArm(q0, ones(nbDOFs,1)*armLength, [0;0;1], .02, [.8,.8,.8]); +htmp = plotArm(q0, ones(nbDOFs,1)*model.l, [0;0;1], .02, [.8,.8,.8]); h(3) = htmp(1); ii = 2; for t=nbData:nbData %round(linspace(1,nbData,2)) colTmp = [1,1,1] - [.7,.7,.7] * t/nbData; - htmp = plotArm(r(1).q(:,t), ones(nbDOFs,1)*armLength, [0;0;ii], .02, colTmp); + htmp = plotArm(r(1).q(:,t), ones(nbDOFs,1)*model.l, [0;0;ii], .02, colTmp); ii = ii + 1; end h(4) = htmp(1); h(5) = plot3([xh(1),xh(1)], [xh(2)-.3,xh(2)+.3], [10,10], '-','linewidth',2,'color',[.8 0 0]); -plotArm(q0(1), armLength, [0;0;10], .02, [.8,0,0]); +plotArm(q0(1), model.l, [0;0;10], .02, [.8,0,0]); axis equal; axis tight; -legend(h,{'Primary task','Secondary task','Initial pose','Weighted IK','Weights'},'location','southeast','fontsize',18); +legend(h,{'Primary task (tracking with endeffector point)','Secondary task (tracking with other point on the kinematic chain)','Initial pose','Weighted IK solution','Weights (in joint space and task space)'},'location','southoutside','fontsize',12); % figure; hold on; % plot(r(2).q(1,:),'k-'); @@ -122,4 +130,34 @@ legend(h,{'Primary task','Secondary task','Initial pose','Weighted IK','Weights' % print('-dpng','graphs/demoIK_weighted01.png'); pause; -close all; \ No newline at end of file +close all; +end + +%%%%%%%%%%%%%%%%%%%%%% +%Forward kinematics +function [x, Tf] = fkine(q, model) + Tf = eye(4); + T = repmat(Tf, [1,1,size(q,1)]); + for n=1:size(q,1) + 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 + Tf = Tf * T(:,:,n); + end + x = Tf(1:2,end); +end + +%%%%%%%%%%%%%%%%%%%%%% +%Jacobian with numerical computation +function J = jacob0(q, model) + e = 1E-3; + J = zeros(2,size(q,1)); + for n=1:size(q,1) + qtmp = q; + qtmp(n) = qtmp(n) + e; + J(:,n) = (fkine(qtmp, model) - fkine(q, model)) / e; + end +end \ No newline at end of file diff --git a/demos/demo_MPC01.m b/demos/demo_MPC01.m index f9eb7de2a5a20b013da0ed10f42be4521867269c..a6bac4861b914c654c953fbbafe2465cbd7354e8 100644 --- a/demos/demo_MPC01.m +++ b/demos/demo_MPC01.m @@ -74,7 +74,7 @@ end %% Task setting %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -tl = linspace(1,nbData,nbPoints+1); +tl = linspace(1, nbData, nbPoints+1); tl = round(tl(2:end)); MuQ = zeros(nbVar*nbData,1); Q = zeros(nbVar*nbData); @@ -97,7 +97,7 @@ xSigma = Su * uSigma * Su'; %% Plot 2D %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -figure('position',[10 10 1000 1000]); hold on; axis off; +figure('position',[10 10 800 800]); hold on; axis off; for t=1:nbData plotGMM(rx(1:2,t), xSigma(nbVar*(t-1)+[1,2],nbVar*(t-1)+[1,2]).*1E-6, [.2 .2 .2], .1); end diff --git a/demos/demo_MPC02.m b/demos/demo_MPC02.m index 2f8957728b2d555ef51b55877f45727bd4d5c79d..36135c3a0a909dc19ed98e68b6f8f8dc31619b72 100644 --- a/demos/demo_MPC02.m +++ b/demos/demo_MPC02.m @@ -356,7 +356,7 @@ axis equal; %% Timeline plot %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% labList = {'$x_1$','$x_2$','$\dot{x}_1$','$\dot{x}_2$','$\ddot{x}_1$','$\ddot{x}_2$'}; -figure('position',[620 10 1000 1290],'color',[1 1 1]); +figure('position',[620 10 1000 850],'color',[1 1 1]); for j=1:model.nbVar subplot(model.nbVar+model.nbVarPos+1,1,j); hold on; limAxes = [1, nbData, min(r(1).x(j,:))-8E0, max(r(1).x(j,:))+8E0]; diff --git a/demos/demo_MPC03.m b/demos/demo_MPC03.m index d03c75c2d2418d92eb54fb61ce8d3bfd08cc2bd7..0c7fb581194044b1aeef132e961fec844e47024b 100644 --- a/demos/demo_MPC03.m +++ b/demos/demo_MPC03.m @@ -40,11 +40,11 @@ nbRepros = 1; %Number of reproductions in new situations nbNewRepros = 0; %Number of stochastically generated reproductions nbData = 200; %Number of datapoints -model.nbStates = 8; %Number of Gaussians in the GMM +model.nbStates = 6; %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.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 = 1E-3; %Control cost in LQR %Control cost matrix @@ -100,7 +100,8 @@ end %% Load handwriting data %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -load('data/2Dletters/E.mat'); +demos = []; +load('data/2Dletters/S.mat'); Data=[]; for n=1:nbSamples s(n).Data = spline(1:size(demos{n}.pos,2), demos{n}.pos, linspace(1,size(demos{n}.pos,2),nbData)); %Resampling @@ -229,7 +230,7 @@ end %% Plot 2D %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -figure('position',[10 10 1200 1200],'color',[1 1 1]); hold on; axis off; +figure('position',[10 10 800 800],'color',[1 1 1]); hold on; axis off; plotGMM(model.Mu(1:2,:), model.Sigma(1:2,1:2,:), [.8 .8 .8]); for n=1:nbSamples plot(Data(1,(n-1)*nbData+1:n*nbData), Data(2,(n-1)*nbData+1:n*nbData), '-','lineWidth',1,'color',[.7 .7 .7]); @@ -296,7 +297,7 @@ for n=1:nbNewRepros end %Plot labList = {'$x_1$','$x_2$','$\dot{x}_1$','$\dot{x}_2$'}; -figure('position',[1210 10 1000 1200],'color',[1 1 1]); +figure('position',[810 10 800 800],'color',[1 1 1]); for j=1:4 subplot(5,1,j); hold on; if j<=model.nbVarPos diff --git a/demos/demo_MPC_fullQ02.m b/demos/demo_MPC_fullQ02.m index ab40a2ad710bcc788e7169566a8ecaefcdbe3e58..7e4f57773f0048db6d562b780d85df2f5dcea567 100644 --- a/demos/demo_MPC_fullQ02.m +++ b/demos/demo_MPC_fullQ02.m @@ -107,12 +107,12 @@ t1 = nbData/2; t2 = t1+50; idm(1:2) = [1:2] + (t1-1) * nbVar; idm(3:4) = [3:4] + (t2-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; +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 @@ -163,11 +163,11 @@ xSigma = Su * uSigma * Su'; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %Generate structured stochastic u through Bezier curves nbRBF = 18; -H = zeros(nbRBF,nbData-1); -tl = linspace(0,1,nbData-1); +H = zeros(nbRBF, nbData-1); +tl = linspace(0, 1, nbData-1); nbDeg = nbRBF - 1; for i=0:nbDeg - H(i+1,:) = factorial(nbDeg) ./ (factorial(i) .* factorial(nbDeg-i)) .* (1-tl).^(nbDeg-i) .* tl.^i; %Bernstein basis functions + H(i+1,:) = factorial(nbDeg) / (factorial(i) * factorial(nbDeg-i)) * (1-tl).^(nbDeg-i) .* tl.^i; %Bernstein basis functions end %Nullspace planning @@ -175,6 +175,8 @@ end U = V * D.^.5; N = eye((nbData-1)*nbVarPos) - Su' * U / (U' * (Su * Su') * U + Rx) * U' * Su; %Nullspace projection matrix up = Su' * U / (U' * (Su * Su') * U + Rx) * U' * (MuQ - Sx * x0); %Principal task +% up = (Su' * Q * Su + R) \ (Su' * Q * (MuQ - Sx * x0)); + for n=1:nbRepros w = randn(nbVarPos,nbRBF) .* 1E0; %Random weights un = w * H; %Reconstruction of signals by weighted superposition of basis functions @@ -197,6 +199,7 @@ plot(rx(1,:), rx(2,:), '-','linewidth',2,'color',[0 0 0]); plot(rx(1,1), rx(2,1), 'o','linewidth',2,'markersize',8,'color',[0 0 0]); % plot(rx(1,tlm), rx(2,tlm), '.','markersize',35,'color',[0 .6 0]); %meeting point plot(rx(1,t1), rx(2,t1), '.','markersize',35,'color',[0 .6 0]); %meeting point +plot(rx(1,t1), rx(2,t1), '.','markersize',35,'color',[0 .6 0]); %meeting point plot(MuQ(id(1,:)), MuQ(id(2,:)), '.','markersize',35,'color',[0 0 0]); %Agent 2 % for t=1:nbData @@ -222,6 +225,7 @@ for n=1:nbRepros plot(r(n).x(1,:), r(n).x(2,:), '-','linewidth',2,'color',[0 0 0]); plot(r(n).x(1,1), r(n).x(2,1), 'o','linewidth',2,'markersize',8,'color',[0 0 0]); % plot(r(n).x(1,tlm), r(n).x(2,tlm), '.','markersize',35,'color',[0 .6 0]); %meeting point + plot(r(n).x(1,t1), r(n).x(2,t1), '.','markersize',35,'color',[0 .6 0]); %meeting point plot(MuQ(id(1,:)), MuQ(id(2,:)), '.','markersize',35,'color',[0 0 0]); %Agent 2 plot(r(n).x(3,:), r(n).x(4,:), '-','linewidth',2,'color',[.8 0 0]); diff --git a/demos/demo_MPC_iterativeLQR01.m b/demos/demo_MPC_iterativeLQR01.m index f762004ea43d33c3b082ec71a4ca087fd68244f4..1bdddf87b42f44b72cc11b672ad5e82e0916d26e 100644 --- a/demos/demo_MPC_iterativeLQR01.m +++ b/demos/demo_MPC_iterativeLQR01.m @@ -1,5 +1,5 @@ function demo_MPC_iterativeLQR01 -% Iterative computation of linear quadratic tracking (with feedback and feedforward terms). +% Recursive computation of linear quadratic tracking (with feedback and feedforward terms). % % If this code is useful for your research, please cite the related publication: % @incollection{Calinon19chapter, diff --git a/demos/demo_MPC_iterativeLQR02.m b/demos/demo_MPC_iterativeLQR02.m index 222fde594dc815ca0cfb10ee71cfc38d46b3c5ad..ac4505e1211da57e23d89c220a5a82b43ebbed09 100644 --- a/demos/demo_MPC_iterativeLQR02.m +++ b/demos/demo_MPC_iterativeLQR02.m @@ -1,5 +1,5 @@ function demo_MPC_iterativeLQR02 -% Iterative computation of linear quadratic tracking (with feedback and feedforward terms), +% Recursive computation of linear quadratic tracking (with feedback and feedforward terms), % by relying on a GMM encoding of position and velocity data, including comparison with batch LQT. % % If this code is useful for your research, please cite the related publication: diff --git a/demos/demo_MPC_iterativeLQR03.m b/demos/demo_MPC_iterativeLQR03.m index 7cfd74619e26fc4826046e7a9a2bd1a3c4584252..f8fc44416de4d9723b9f8263696572f02f179f5e 100644 --- a/demos/demo_MPC_iterativeLQR03.m +++ b/demos/demo_MPC_iterativeLQR03.m @@ -1,5 +1,5 @@ function demo_MPC_iterativeLQR03 -% Iterative computation of linear quadratic tracking (with feedback and feedforward terms), +% Recursive computation of linear quadratic tracking (with feedback and feedforward terms), % by relying on a GMM encoding of only position data. % % If this code is useful for your research, please cite the related publication: diff --git a/demos/demo_MPC_iterativeLQR04.m b/demos/demo_MPC_iterativeLQR04.m index 8cbcfbe621ec71cf4e18ec77d983aa2a75315d6f..6f90751747d8093d6a2c7ec7e1e244593e7eb1ea 100644 --- a/demos/demo_MPC_iterativeLQR04.m +++ b/demos/demo_MPC_iterativeLQR04.m @@ -1,5 +1,5 @@ function demo_MPC_iterativeLQR04 -% Control of a spring attached to a point with iterative linear quadratic tracking (with feedback and feedforward terms). +% Control of a spring attached to a point with linear quadratic tracking (with feedback and feedforward terms using the recursive formulation). % % If this code is useful for your research, please cite the related publication: % @incollection{Calinon19chapter, diff --git a/demos/demo_MPC_iterativeLQR_augmSigma01.m b/demos/demo_MPC_iterativeLQR_augmSigma01.m index f5b305ee43a39b417a1c7f927f072280c9869f94..a17f034107cf19210f8874ad375a8e73a82996fb 100644 --- a/demos/demo_MPC_iterativeLQR_augmSigma01.m +++ b/demos/demo_MPC_iterativeLQR_augmSigma01.m @@ -1,5 +1,5 @@ function demo_MPC_iterativeLQR_augmSigma01 -% Iterative LQR with augmented covariance to transform the tracking problem to a regulation problem. +% Recursive LQR with augmented covariance to transform the tracking problem to a regulation problem. % % If this code is useful for your research, please cite the related publication: % @incollection{Calinon19chapter, @@ -85,6 +85,7 @@ B = [B0; zeros(1,model.nbVarPos)]; %Augmented B %% Load handwriting data %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +demos=[]; load('data/2Dletters/S.mat'); Data=[]; for n=1:nbSamples @@ -129,7 +130,7 @@ for i=1:model.nbStates end -%% Iterative LQR with augmented state space +%% LQR with recursive computation and augmented state space %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %Set list of states according to first demonstration (alternatively, an HSMM can be used) [~,qList] = max(H(:,1:nbData),[],1); %works also for nbStates=1 @@ -140,24 +141,23 @@ 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) terms on augmented state +%Reproduction with only feedback (FB) on augmented state for n=1:nbRepros if n==1 - X = [Data(:,1); 1]; + x = [Data(:,1); 1]; else - X = [Data(:,1); 1] + [randn(model.nbVarPos,1)*2E0; zeros(model.nbVar-model.nbVarPos,1)]; + x = [Data(:,1); 1] + [randn(model.nbVarPos,1)*2E0; zeros(model.nbVar-model.nbVarPos,1)]; end - r(n).X0 = X; + r(n).x0 = x; for t=1:nbData - r(n).Data(:,t) = X; %Log data + 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 terms on augmented state (resulting in FB and FF terms) - X = A * X + B * u; %Update of state vector + u = -K * x; %Acceleration command with FB on augmented state (resulting in FB and FF terms) + x = A * x + B * u; %Update of state vector end end - -%% Iterative linear quadratic tracking (for comparison) +%% Linear quadratic tracking with recursive computation (for comparison) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% P = zeros(model0.nbVar,model0.nbVar,nbData); P(:,:,end) = inv(model0.Sigma(:,:,qList(nbData))); @@ -169,13 +169,13 @@ for t=nbData-1:-1:1 end %Reproduction with feedback (FB) and feedforward (FF) terms for n=1:nbRepros - X = r(n).X0(1:end-1); + x = r(n).x0(1:end-1); for t=1:nbData - r2(n).Data(:,t) = X; %Log data + 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 - X = A0 * X + B0 * u; %Update of state vector + u = K * (model0.Mu(:,qList(t)) - x) + M; %Acceleration command with FB and FF terms + x = A0 * x + B0 * u; %Update of state vector end end @@ -183,14 +183,14 @@ end %% Plot %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %Plot position -figure('position',[10 10 1000 1000],'color',[1 1 1]); axis off; hold on; +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]); end for n=1:nbRepros - h(1) = plot(r(n).Data(1,:), r(n).Data(2,:), '-','linewidth',2,'color',[.8 0 0]); - h(2) = plot(r2(n).Data(1,:), r2(n).Data(2,:), '--','linewidth',2,'color',[0 .8 0]); + h(1) = plot(r(n).x(1,:), r(n).x(2,:), '-','linewidth',2,'color',[.8 0 0]); + 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'); @@ -202,14 +202,14 @@ legend(h,'LQR with augmented state space',' LQT with FB and FF terms'); % plot(Data(3,(n-1)*nbData+1:n*nbData), Data(4,(n-1)*nbData+1:n*nbData), '-','color',[.7 .7 .7]); % end % for n=1:nbRepros -% plot(r(n).Data(3,:), r(n).Data(4,:), '-','linewidth',2,'color',[.8 0 0]); -% plot(r(n).Data(3,1), r(n).Data(4,1), '.','markersize',18,'color',[.6 0 0]); -% plot(r2(n).Data(3,:), r2(n).Data(4,:), '--','linewidth',2,'color',[0 .8 0]); +% plot(r(n).x(3,:), r(n).x(4,:), '-','linewidth',2,'color',[.8 0 0]); +% plot(r(n).x(3,1), r(n).x(4,1), '.','markersize',18,'color',[.6 0 0]); +% plot(r2(n).x(3,:), r2(n).x(4,:), '--','linewidth',2,'color',[0 .8 0]); % end % plot(0,0,'k+'); % axis equal; % xlabel('dx_1'); ylabel('dx_2'); -%print('-dpng','graphs/demo_iterativeLQR_augmSigma01.png'); +% print('-dpng','graphs/demo_iterativeLQR_augmSigma01.png'); pause; close all; \ No newline at end of file diff --git a/demos/demo_MPC_iterativeLQR_augmSigma_online01.m b/demos/demo_MPC_iterativeLQR_augmSigma_online01.m index 031596f9dbff8a322285f4f04b84caae1372d9e7..ffdb1e2489ba1f44609486cff42ae736418df72c 100644 --- a/demos/demo_MPC_iterativeLQR_augmSigma_online01.m +++ b/demos/demo_MPC_iterativeLQR_augmSigma_online01.m @@ -1,5 +1,5 @@ function demo_MPC_iterativeLQR_augmSigma_online01 -% Iterative LQR with augmented covariance to transform the tracking problem to a regulation problem, recomputed in an online manner. +% Recursive LQR with augmented covariance to transform the tracking problem to a regulation problem, recomputed in an online manner. % % If this code is useful for your research, please cite the related publication: % @incollection{Calinon19chapter, diff --git a/demos/demo_MPC_robot01.m b/demos/demo_MPC_robot01.m index adf4402b578c446cbda5eda857dc56f10b301da9..ba1b8c9a8403d84b6fb039699736eb12b7f7a325 100644 --- a/demos/demo_MPC_robot01.m +++ b/demos/demo_MPC_robot01.m @@ -1,9 +1,6 @@ function demo_MPC_robot01 % Robot manipulator tracking task with MPC, by relinearization of the system plant at each time step. % -% This demo requires the robotics toolbox RTB10 (http://petercorke.com/wordpress/toolboxes/robotics-toolbox). -% First run 'startup_rvc' from the robotics toolbox. -% % If this code is useful for your research, please cite the related publication: % @incollection{Calinon19chapter, % author="Calinon, S. and Lee, D.", @@ -16,6 +13,9 @@ function demo_MPC_robot01 % doi="10.1007/978-94-007-6046-2_68" % } % +% The commented parts of this demo require the robotics toolbox RTB10 (http://petercorke.com/wordpress/toolboxes/robotics-toolbox). +% First run 'startup_rvc' from the robotics toolbox if you uncomment these parts. +% % Copyright (c) 2019 Idiap Research Institute, http://idiap.ch/ % Written by Sylvain Calinon, http://calinon.ch/ % @@ -34,7 +34,6 @@ function demo_MPC_robot01 % along with PbDlib. If not, see <http://www.gnu.org/licenses/>. addpath('./m_fcts/'); -disp('This demo requires the robotics toolbox RTB10 (http://petercorke.com/wordpress/toolboxes/robotics-toolbox).'); %% Parameters @@ -56,49 +55,52 @@ model.rfactor = 1E-2; %Control cost in LQR R = eye(model.nbVarU) * model.rfactor; R = kron(eye(nbD-1),R); +%Robot description +model.l = 0.6; -%% Robot description -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -armLength = 0.6; -L1 = Link('d', 0, 'a', armLength, 'alpha', 0); -robot = SerialLink(repmat(L1,nbDOFs,1)); +% L1 = Link('d', 0, 'a', model.l, 'alpha', 0); +% robot = SerialLink(repmat(L1,nbDOFs,1)); %% Task description %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -model.Mu = ones(model.nbVarPos,1) .* .7; -model.Sigma = eye(model.nbVarPos) .* 1E-3; +model.Mu = ones(model.nbVarPos,1) * .7; +model.Sigma = eye(model.nbVarPos) * 1E-3; MuQ = kron(ones(nbD,1), model.Mu); Q = kron(eye(nbD), inv(model.Sigma)); %% Online batch LQR with relinearization of the system plant %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -q = ones(nbDOFs,1) .* 0.1; -Htmp = robot.fkine(q); -x = Htmp.t(1:model.nbVarPos); +q = ones(nbDOFs,1) * 0.1; +% Htmp = robot.fkine(q); +% x = Htmp.t(1:model.nbVarPos); +x = fkine(q, model); + for t=1:nbData - [Su, Sx] = computeTransferMatrices(q, model, robot, nbD); %Linearization of system plant +% [Su, Sx] = computeTransferMatrices(q, model, robot, nbD); %Linearization of system plant + [Su, Sx] = computeTransferMatrices(q, model, nbD); %Linearization of system plant u = (Su' * Q * Su + R) \ Su' * Q * (MuQ - Sx * x); %Control trajectory %Log data r(1).q(:,t) = q; r(1).x(:,t) = x; r(1).u(:,t) = u(1:model.nbVarU); %Update state - q = q + u(1:model.nbVarU) .* model.dt; - Htmp = robot.fkine(q); %Forward kinematics - x = Htmp.t(1:model.nbVarPos); + q = q + u(1:model.nbVarU) * model.dt; +% Htmp = robot.fkine(q); %Forward kinematics +% x = Htmp.t(1:model.nbVarPos); + x = fkine(q, model); end %% Plot 2D %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -figure('position',[10 10 700 700],'color',[1 1 1],'name','x1-x2 plot'); hold on; axis off; +figure('position',[10 10 800 800],'color',[1 1 1],'name','x1-x2 plot'); hold on; axis off; for t=round(linspace(1,nbData,2)) colTmp = [.9,.9,.9] - [.7,.7,.7] * t/nbData; - plotArm(r(1).q(:,t), ones(nbDOFs,1)*armLength, [0;0;-10+t*0.1], .06, colTmp); + plotArm(r(1).q(:,t), ones(nbDOFs,1)*model.l, [0;0;-10+t*0.1], .06, colTmp); end -% plotArm(model.Mu, ones(nbDOFs,1)*armLength, [0;0;10], .02, [.8 0 0]); +% plotArm(model.Mu, ones(nbDOFs,1)*model.l, [0;0;10], .02, [.8 0 0]); plotGMM(model.Mu, model.Sigma, [.8 0 0], .5); plot(model.Mu(1,:), model.Mu(2,:), '.','markersize',20,'color',[.8 0 0]); @@ -112,7 +114,7 @@ axis equal; %% Timeline plot %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% labList = {'$x_1$','$x_2$','$\dot{x}_1$','$\dot{x}_2$'}; -figure('position',[720 10 1000 1300],'color',[1 1 1]); +figure('position',[830 10 800 800],'color',[1 1 1]); for j=1:model.nbVarX subplot(model.nbVarX+model.nbVarU,1,j); hold on; plot([1,nbData],[model.Mu(j) model.Mu(j)],':','color',[.5 .5 .5]); @@ -156,10 +158,41 @@ function [Su, Sx] = transferMatrices(A, B, nbD) end %%%%%%%%%%%%%%%%%%%%%% -function [Su, Sx, A, B] = computeTransferMatrices(q, model, robot, nbD) - J = robot.jacob0(q,'trans'); +% function [Su, Sx, A, B] = computeTransferMatrices(q, model, robot, nbD) +function [Su, Sx, A, B] = computeTransferMatrices(q, model, nbD) +% J = robot.jacob0(q,'trans'); + J = jacob0(q, model); %Discrete linear system x(t+1) = x(t) + J * dq A = eye(model.nbVarX); - B = J(1:model.nbVarPos,:) .* model.dt; + B = J * model.dt; [Su, Sx] = transferMatrices(A, B, nbD); +end + +%%%%%%%%%%%%%%%%%%%%%% +%Forward kinematics +function [x, Tf] = fkine(q, model) + Tf = eye(4); + T = repmat(Tf, [1,1,size(q,1)]); + for n=1:size(q,1) + 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 + Tf = Tf * T(:,:,n); + end + x = Tf(1:2,end); +end + +%%%%%%%%%%%%%%%%%%%%%% +%Jacobian with numerical computation +function J = jacob0(q, model) + e = 1E-4; + J = zeros(2,size(q,1)); + for n=1:size(q,1) + qtmp = q; + qtmp(n) = qtmp(n) + e; + J(:,n) = (fkine(qtmp, model) - fkine(q, model)) / e; + end end \ No newline at end of file diff --git a/demos/demo_Riemannian_S2_batchLQR01.m b/demos/demo_Riemannian_S2_batchLQR01.m index 3316c2545752a10c0828db4f7cb2a3ef12b5da6f..95c327f960f3e87f7810b520a09672927d625768 100644 --- a/demos/demo_Riemannian_S2_batchLQR01.m +++ b/demos/demo_Riemannian_S2_batchLQR01.m @@ -1,6 +1,7 @@ function demo_Riemannian_S2_batchLQR01 % LQT on a sphere (version with viapoints) by relying on Riemannian manifold (recomputed in an online manner), % by using position and velocity data (-> acceleration commands) +% (see also demo_Riemannian_Sd_MPC01.m) % % If this code is useful for your research, please cite the related publication: % @article{Calinon20RAM, @@ -235,8 +236,10 @@ for i=1:model.nbStates end %S2 manifold plot -figure('position',[10,10,2500,700]); +figure('position',[10,10,1600,500]); subplot(2,3,[1,4]); hold on; axis off; grid off; rotate3d on; +set(0,'DefaultAxesLooseInset',[0,0,0,0]); +set(gca,'LooseInset',[0,0,0,0]); colormap([.8 .8 .8]); [X,Y,Z] = sphere(20); mesh(X,Y,Z); @@ -250,7 +253,7 @@ for n=1:nbRepros plot3(r(n).x(1,:), r(n).x(2,:), r(n).x(3,:), '-','linewidth',2,'color',[.6 .6 .6]); plot3(r(n).x(1,1), r(n).x(2,1), r(n).x(3,1), '.','markersize',24,'color',[.6 .6 .6]); end -view(-20,15); axis equal; axis([-1 1 -1 1 -1 1].*1.8); axis vis3d; +view(-20,15); axis equal; axis([-1 1 -1 1 -1 1].*1.4); axis vis3d; %Tangent plane plot subplot(2,3,[2,5]); hold on; axis off; @@ -282,13 +285,14 @@ end %% Anim plots %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -for tt=1:nbData %58:58 +for tt=floor(linspace(1,nbData,nbData)) %58:58 e0 = r(n).x(:,tt); xTmp = expmap(r(1).s(tt).u(1:model.nbVarPos,:), e0); %Tangent plane on S2 anim subplot(2,3,[1,4]); hold on; - msh = repmat(e0,1,5) + rotM(e0)' * [1 1 -1 -1 1; 1 -1 -1 1 1; 0 0 0 0 0] * 1E0; - h = patch(msh(1,:),msh(2,:),msh(3,:), [.8 .8 .8],'edgecolor',[.6 .6 .6],'facealpha',.3,'edgealpha',.3); + msh = repmat(e0,1,5) + rotM(e0)' * [1 1 -1 -1 1; 1 -1 -1 1 1; 0 0 0 0 0] * 5E-1; +% h = patch(msh(1,:),msh(2,:),msh(3,:), [.8 .8 .8],'edgecolor',[.6 .6 .6]),'facealpha',.3,'edgealpha',.3); + h = plot3(msh(1,:),msh(2,:),msh(3,:), '-','color',[.6 .6 .6]); h = [h, plot3(e0(1), e0(2), e0(3), '.','markersize',20,'color',[0 0 0])]; %Referential on S2 anim msh = repmat(e0,1,2) + rotM(e0)' * [1 -1; 0 0; 0 0] * 2E-1; @@ -315,8 +319,8 @@ for tt=1:nbData %58:58 end drawnow; -% pause; -% print('-dpng','-r600','graphs/S2_batchLQR01.png'); +% print('-dpng',['graphs/anim/S2_batchLQR_anim' num2str(tt,'%.3d') '.png']); + delete(h); end diff --git a/demos/demo_Riemannian_S2_batchLQR02.m b/demos/demo_Riemannian_S2_batchLQR02.m index a703b460ff23de58c33b8eb354013fb91552270a..eb1d1c1b0be36e92efd993856f6506a2ad8df149 100644 --- a/demos/demo_Riemannian_S2_batchLQR02.m +++ b/demos/demo_Riemannian_S2_batchLQR02.m @@ -220,7 +220,7 @@ for i=1:model.nbStates end %Plots -figure('position',[10,10,1650,1250]); hold on; axis off; grid off; rotate3d on; +figure('position',[10,10,800,800]); hold on; axis off; grid off; rotate3d on; colormap([.8 .8 .8]); [X,Y,Z] = sphere(20); mesh(X,Y,Z); diff --git a/demos/demo_Riemannian_S2_batchLQR03.m b/demos/demo_Riemannian_S2_batchLQR03.m index 9730422296fb20f611fd85194665df73b26b37f1..b5a80812ceef3f3a2216e6d2b3546ae5ccd182bd 100644 --- a/demos/demo_Riemannian_S2_batchLQR03.m +++ b/demos/demo_Riemannian_S2_batchLQR03.m @@ -123,9 +123,8 @@ for nb=1:nbIterEM model.Priors(i) = sum(GAMMA(i,:)) / (nbData*nbSamples); %Update MuMan for n=1:nbIter - xTar = model.MuMan(1:3,i); %Position target - uTmp = logmap(x0(1:3,:), xTar); - model.MuMan(:,i) = expmap(uTmp*H(i,:)', xTar); + uTmp = logmap(x0(1:3,:), model.MuMan(1:3,i)); + model.MuMan(:,i) = expmap(uTmp*H(i,:)', model.MuMan(1:3,i)); end %Update Sigma model.Sigma(:,:,i) = uTmp * diag(H(i,:)) * uTmp' + eye(size(uTmp,1)) * model.params_diagRegFact; @@ -186,7 +185,7 @@ for i=1:model.nbStates end %Manifold plot -figure('position',[10,10,1200,1200]); hold on; axis off; grid off; rotate3d on; +figure('position',[10,10,800,800]); hold on; axis off; grid off; rotate3d on; colormap([.8 .8 .8]); [X,Y,Z] = sphere(20); mesh(X,Y,Z); %,'facealpha',.5 @@ -217,7 +216,7 @@ patch(msh(1,:),msh(2,:),msh(3,:), [.8 .8 .8],'edgecolor',[.6 .6 .6],'facealpha', %% Tangent space plots %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -figure('position',[1220,10,650,650]); hold on; axis off; box on; +figure('position',[820,10,650,650]); hold on; axis off; box on; plot(0,0,'+','markersize',40,'linewidth',2,'color',[.7 .7 .7]); plot(0,0,'.','markersize',20,'color',[0 0 0]); % % plot(u0(1,:), u0(2,:), '.','markersize',12,'color',[.5 .5 .5]); diff --git a/demos/demo_Riemannian_S2_infHorLQR01.m b/demos/demo_Riemannian_S2_infHorLQR01.m index c1d6f023b295c99caed3a2356834b621fcd1c9b0..e77a9a26d9d63ed276c1bc0a118a8fcf811ee98e 100644 --- a/demos/demo_Riemannian_S2_infHorLQR01.m +++ b/demos/demo_Riemannian_S2_infHorLQR01.m @@ -36,96 +36,96 @@ nbData = 100; %Number of datapoints nbDrawingSeg = 50; %Number of segments used to draw ellipsoids nbRepros = 20; %Number of reproductions -model.nbVarPos = 2; %Dimension of position data (here: x1,x2) -model.nbDeriv = 2; %Number of static & dynamic features (D=2 for [x,dx]) -model.nbVar = model.nbVarPos * model.nbDeriv; %Dimension of state vector in the tangent space -model.nbVarMan = model.nbVarPos+1; %Dimension of the manifold -model.dt = 1E-3; %Time step duration -model.rfactor = 1E-6; %Control cost in LQR +nbVarPos = 2; %Dimension of position data (here: x1,x2) +nbDeriv = 2; %Number of static & dynamic features (D=2 for [x,dx]) +nbVar = nbVarPos * nbDeriv; %Dimension of state vector in the tangent space +nbVarMan = nbVarPos+1; %Dimension of the manifold +dt = 1E-3; %Time step duration +rfactor = 1E-6; %Control cost in LQR %Control cost matrix -R = eye(model.nbVarPos) * model.rfactor; +R = eye(nbVarPos) * rfactor; %Target and desired covariance xTar = [-1; .2; .6]; xTar = xTar / norm(xTar); -[Ar,~] = qr(randn(model.nbVarPos)); +[Ar,~] = qr(randn(nbVarPos)); uCov = Ar*diag([.1,1.4])*Ar' * 1E-1; %uCov = diag([.1,.1]) * 1E-1; -%Eigendecomposition -[V,D] = eig(uCov); -U0 = V * D.^.5; +% %Eigendecomposition +% [V,D] = eig(uCov); +% U0 = V * D.^.5; %% Discrete dynamical System settings (in tangent space) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -A1d = zeros(model.nbDeriv); -for i=0:model.nbDeriv-1 - A1d = A1d + diag(ones(model.nbDeriv-i,1),i) * model.dt^i * 1/factorial(i); %Discrete 1D +A1d = zeros(nbDeriv); +for i=0:nbDeriv-1 + A1d = A1d + diag(ones(nbDeriv-i,1),i) * dt^i * 1/factorial(i); %Discrete 1D end -B1d = zeros(model.nbDeriv,1); -for i=1:model.nbDeriv - B1d(model.nbDeriv-i+1) = model.dt^i * 1/factorial(i); %Discrete 1D +B1d = zeros(nbDeriv,1); +for i=1:nbDeriv + B1d(nbDeriv-i+1) = dt^i * 1/factorial(i); %Discrete 1D end -A = kron(A1d, eye(model.nbVarPos)); %Discrete nD -B = kron(B1d, eye(model.nbVarPos)); %Discrete nD +A = kron(A1d, eye(nbVarPos)); %Discrete nD +B = kron(B1d, eye(nbVarPos)); %Discrete nD %Generate initial conditions for n=1:nbRepros - x0(:,n) = [-1; -1; 0] + randn(model.nbVarMan,1)*9E-1; + x0(:,n) = [-1; -1; 0] + randn(nbVarMan,1)*9E-1; x0(:,n) = x0(:,n) / norm(x0(:,n)); end %% Discrete LQR with infinite horizon (computation centered on xTar) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -duTar = zeros(model.nbVarPos*(model.nbDeriv-1),1); -Q = blkdiag(inv(uCov), zeros(model.nbVarPos*(model.nbDeriv-1))); %Precision matrix +duTar = zeros(nbVarPos*(nbDeriv-1),1); +Q = blkdiag(inv(uCov), zeros(nbVarPos*(nbDeriv-1))); %Precision matrix P = solveAlgebraicRiccati_eig_discrete(A, B*(R\B'), (Q+Q')/2); L = (B'*P*B + R) \ B'*P*A; %Feedback gain (discrete version) for n=1:nbRepros x = x0(:,n); - U = [logmap(x,xTar); zeros(model.nbVarPos*(model.nbDeriv-1),1)]; + U = [logmap(x,xTar); zeros(nbVarPos*(nbDeriv-1),1)]; for t=1:nbData r(n).x(:,t) = x; %Log data - %U = [-logmap(x,xTar); U(model.nbVarPos+1:end)]; - ddu = L * [-logmap(x,xTar); duTar-U(model.nbVarPos+1:end)]; %Compute acceleration (with only feedback terms) + %U = [-logmap(x,xTar); U(nbVarPos+1:end)]; + ddu = L * [-logmap(x,xTar); duTar-U(nbVarPos+1:end)]; %Compute acceleration (with only feedback terms) U = A*U + B*ddu; %Update U - x = expmap(U(1:model.nbVarPos), xTar); + x = expmap(U(1:nbVarPos), xTar); end end %% Discrete LQR with infinite horizon (computation centered on x, for comparison) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -duTar = zeros(model.nbVarPos*(model.nbDeriv-1),1); +duTar = zeros(nbVarPos*(nbDeriv-1),1); for n=1:nbRepros x = x0(:,n); x_old = x; - U = zeros(model.nbVar,1); + U = zeros(nbVar,1); for t=1:nbData r2(n).x(:,t) = x; %Log data - U(1:model.nbVarPos) = zeros(model.nbVarPos,1); %Set tangent space at x + U(1:nbVarPos) = zeros(nbVarPos,1); %Set tangent space at x %Transportation of velocity vector from x_old to x Ac = transp(x_old, x); - U(model.nbVarPos+1:end) = Ac * U(model.nbVarPos+1:end); %Transport of velocity + U(nbVarPos+1:end) = Ac * U(nbVarPos+1:end); %Transport of velocity %Transportation of uCov from xTar to x Ac = transp(xTar, x); uCovTmp = Ac * uCov * Ac'; - Q = blkdiag(inv(uCovTmp), zeros(model.nbVarPos*(model.nbDeriv-1))); %Precision matrix + Q = blkdiag(inv(uCovTmp), zeros(nbVarPos*(nbDeriv-1))); %Precision matrix P = solveAlgebraicRiccati_eig_discrete(A, B*(R\B'), (Q+Q')/2); L = (B'*P*B + R) \ B'*P*A; %Feedback gain (discrete version) - ddu = L * [logmap(xTar,x); duTar-U(model.nbVarPos+1:end)]; %Compute acceleration - %ddu = L * [logmap(x,xTar); duTar-U(model.nbVarPos+1:end)]; %Compute acceleration + ddu = L * [logmap(xTar,x); duTar-U(nbVarPos+1:end)]; %Compute acceleration + %ddu = L * [logmap(x,xTar); duTar-U(nbVarPos+1:end)]; %Compute acceleration U = A*U + B*ddu; %Update U x_old = x; - x = expmap(U(1:model.nbVarPos), x); + x = expmap(U(1:nbVarPos), x); end end diff --git a/demos/demo_Riemannian_S3_GMM01.m b/demos/demo_Riemannian_S3_GMM01.m index 933cac0b8721844c7286db2e5155dc5c23b02434..62b11a9c3a329c7d35cbd17bb41efdab6056863a 100644 --- a/demos/demo_Riemannian_S3_GMM01.m +++ b/demos/demo_Riemannian_S3_GMM01.m @@ -137,20 +137,20 @@ function u = logmap(x, mu) else Q = QuatMatrix(mu); end - u = logfct(Q'*x); + u = logfct(Q' * x); end function Exp = expfct(u) normv = sqrt(u(1,:).^2+u(2,:).^2+u(3,:).^2); - Exp = real([cos(normv) ; u(1,:).*sin(normv)./normv ; u(2,:).*sin(normv)./normv ; u(3,:).*sin(normv)./normv]); - Exp(:,normv < 1e-16) = repmat([1;0;0;0],1,sum(normv < 1e-16)); + Exp = real([cos(normv) ; u(1,:) .* sin(normv) ./ normv ; u(2,:) .* sin(normv) ./ normv ; u(3,:) .* sin(normv) ./ normv]); + Exp(:,normv < 1e-16) = repmat([1;0;0;0], 1, sum(normv < 1e-16)); end 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) @@ -160,7 +160,7 @@ function Q = QuatMatrix(q) 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 diff --git a/demos/demo_Riemannian_Sd_MPC01.m b/demos/demo_Riemannian_Sd_MPC01.m index b5f38b84af8f7054eef043bf455d843de78f7b4c..a685dbe3199df55b347cb7b2bb4348ca03fd9d76 100644 --- a/demos/demo_Riemannian_Sd_MPC01.m +++ b/demos/demo_Riemannian_Sd_MPC01.m @@ -49,7 +49,7 @@ model.nbDeriv = 2; %Number of static & dynamic features (D=2 for [x,dx]) model.nbVar = model.nbVarPos * model.nbDeriv; %Dimension of state vector in the tangent space model.dt = 1E-2; %Time step duration model.params_diagRegFact = 1E-4; %Regularization of covariance -model.rfactor = 1E-10; %Control cost in LQR +model.rfactor = 1E-8; %Control cost in LQR e0 = [0; -1; 0]; %Origin on manifold %Control cost matrix @@ -256,7 +256,9 @@ for i=1:model.nbStates end %S2 manifold plot -figure('position',[10,10,2500,700]); +figure('position',[10,10,1600,500]); +set(0,'DefaultAxesLooseInset',[0,0,0,0]); +set(gca,'LooseInset',[0,0,0,0]); subplot(2,3,[1,4]); hold on; axis off; grid off; rotate3d on; colormap([.8 .8 .8]); [X,Y,Z] = sphere(20); @@ -271,7 +273,7 @@ for n=1:nbRepros plot3(r(n).x(1,:), r(n).x(2,:), r(n).x(3,:), '-','linewidth',2,'color',[.6 .6 .6]); plot3(r(n).x(1,1), r(n).x(2,1), r(n).x(3,1), '.','markersize',24,'color',[.6 .6 .6]); end -view(-20,15); axis equal; axis([-1 1 -1 1 -1 1].*1.8); axis vis3d; +view(-20,15); axis equal; axis([-1 1 -1 1 -1 1].*1.4); axis vis3d; %Tangent plane plot subplot(2,3,[2,5]); hold on; axis off; @@ -308,8 +310,9 @@ for tt=1:nbData %58:58 xTmp = expmap(r(1).s(tt).u(1:model.nbVarPos,:), e0); %Tangent plane on S2 anim subplot(2,3,[1,4]); hold on; - msh = repmat(e0,1,5) + rotM(e0)' * [1 1 -1 -1 1; 1 -1 -1 1 1; 0 0 0 0 0] * 1E0; - h = patch(msh(1,:),msh(2,:),msh(3,:), [.8 .8 .8],'edgecolor',[.6 .6 .6],'facealpha',.3,'edgealpha',.3); + msh = repmat(e0,1,5) + rotM(e0)' * [1 1 -1 -1 1; 1 -1 -1 1 1; 0 0 0 0 0] * 5E-1; + h = patch(msh(1,:), msh(2,:), msh(3,:), [.8 .8 .8],'edgecolor',[.6 .6 .6],'facealpha',.3,'edgealpha',.3); +% h = plot3(msh(1,:), msh(2,:), msh(3,:), '-','color',[.6 .6 .6]); h = [h, plot3(e0(1), e0(2), e0(3), '.','markersize',20,'color',[0 0 0])]; %Referential on S2 anim msh = repmat(e0,1,2) + rotM(e0)' * [1 -1; 0 0; 0 0] * 2E-1; @@ -336,7 +339,7 @@ for tt=1:nbData %58:58 end drawnow; -% pause; +% print('-dpng',['graphs/anim/S2_MPC_anim' num2str(tt,'%.3d') '.png']); % print('-dpng','graphs/demo_Riemannian_Sd_MPC01.png'); delete(h); end @@ -348,21 +351,21 @@ end %% Functions %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function x = expmap(u,x0) +function x = expmap(u, x0) theta = sqrt(sum(u.^2,1)); %norm(u,'fro') x = real(repmat(x0,[1,size(u,2)]) .* repmat(cos(theta),[size(u,1),1]) + u .* repmat(sin(theta)./theta,[size(u,1),1])); x(:,theta<1e-16) = repmat(x0,[1,sum(theta<1e-16)]); end -function u = logmap(x,x0) +function u = logmap(x, x0) theta = acos(x0'*x); %acos(trace(x0'*x)) u = (x - repmat(x0,[1,size(x,2)]) .* repmat(cos(theta),[size(x,1),1])) .* repmat(theta./sin(theta),[size(x,1),1]); u(:,theta<1e-16) = 0; end -function Ac = transp(x1,x2,t) +function Ac = transp(x1, x2, t) if nargin==2 - t=1; + t = 1; end u = logmap(x2,x1); e = norm(u,'fro'); diff --git a/demos/demo_Riemannian_Sd_MPC_infHor01.m b/demos/demo_Riemannian_Sd_MPC_infHor01.m index 7a1f39c2008d138020b8c16df07c553831a1500c..aabd354626805163972af141f895c8bbcde01aad 100644 --- a/demos/demo_Riemannian_Sd_MPC_infHor01.m +++ b/demos/demo_Riemannian_Sd_MPC_infHor01.m @@ -81,13 +81,13 @@ L = (B'*P*B + R) \ B'*P*A; %Feedback gain (discrete version) for n=1:nbRepros x = [-1; -1; 1; 0] + randn(model.nbVarPos,1)*9E-1; x = x / norm(x); - U = [-logmap(x,xTar); zeros(model.nbVarPos*(model.nbDeriv-1),1)]; + u = [-logmap(x,xTar); zeros(model.nbVarPos*(model.nbDeriv-1),1)]; for t=1:nbData r(n).x(:,t) = x; %Log data %U = [-logmap(x,xTar); U(model.nbVarPos+1:end)]; - ddu = L * [logmap(x,xTar); dxTar-U(model.nbVarPos+1:end)]; %Compute acceleration (with only feedback terms) - U = A*U + B*ddu; %Update U - x = expmap(-U(1:model.nbVarPos), xTar); + ddu = L * [logmap(x,xTar); dxTar - u(model.nbVarPos+1:end)]; %Compute acceleration (with only feedback terms) + u = A * u + B * ddu; %Update U + x = expmap(-u(1:model.nbVarPos), xTar); end end @@ -140,31 +140,30 @@ for k=1:4 axis([1 nbData -1 1]); end -%3D plot -figure('PaperPosition',[0 0 6 8],'position',[670,10,650,650]); hold on; axis off; rotate3d on; -colormap([.9 .9 .9]); -[X,Y,Z] = sphere(20); -mesh(X,Y,Z,'facealpha',.3,'edgealpha',.3); -plot3Dframe(quat2rotm(xTar'), zeros(3,1), eye(3)*.3); -view(3); axis equal; axis tight; axis vis3d; -h=[]; -for n=1:min(nbRepros,1) - for t=1:nbData - delete(h); - h = plot3Dframe(quat2rotm(r(n).x(:,t)'), zeros(3,1)); - drawnow; - if t==1 - %pause; - end - end -end +% %3D plot +% figure('PaperPosition',[0 0 6 8],'position',[670,10,650,650]); hold on; axis off; rotate3d on; +% colormap([.9 .9 .9]); +% [X,Y,Z] = sphere(20); +% mesh(X,Y,Z,'facealpha',.3,'edgealpha',.3); +% plot3Dframe(quat2rotm(xTar'), zeros(3,1), eye(3)*.3); +% h=[]; +% for n=1:min(nbRepros,1) +% for t=floor(linspace(1,nbData,10)) +% % delete(h); +% h = plot3Dframe(quat2rotm(r(n).x(:,t)'), zeros(3,1)); +% % drawnow; +% if t==1 +% %pause; +% end +% end +% end +% view(3); axis equal; axis tight; axis vis3d; %print('-dpng','graphs/demo_Riemannian_Sd_MPC_infHor01.png'); pause; close all; end - %% Functions %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function x = expmap(u,x0) @@ -179,11 +178,11 @@ function u = logmap(x,x0) u(:,theta<1e-16) = 0; end -function Ac = transp(x1,x2,t) - if nargin==2 - t=1; - end - xdir = logmap(x2,x1); - nrxdir = xdir./norm(xdir,'fro'); - Ac = -x1 * sin(norm(xdir,'fro')*t)*nrxdir' + nrxdir*cos(norm(xdir,'fro')*t)*nrxdir' + eye(size(xdir,1))-nrxdir*nrxdir'; -end \ No newline at end of file +% function Ac = transp(x1,x2,t) +% if nargin==2 +% t=1; +% end +% xdir = logmap(x2,x1); +% nrxdir = xdir./norm(xdir,'fro'); +% Ac = -x1 * sin(norm(xdir,'fro')*t)*nrxdir' + nrxdir*cos(norm(xdir,'fro')*t)*nrxdir' + eye(size(xdir,1))-nrxdir*nrxdir'; +% end \ No newline at end of file diff --git a/demos/demo_Riemannian_Sd_interp01.m b/demos/demo_Riemannian_Sd_interp01.m index 3048a65617d98e1ac4949d5966ac814b69af93d4..75b4220032dd7d23644564b8ab9f905d785af4cc 100644 --- a/demos/demo_Riemannian_Sd_interp01.m +++ b/demos/demo_Riemannian_Sd_interp01.m @@ -114,7 +114,7 @@ end %% Functions %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function x = expmap(u,x0) +function x = expmap(u, x0) th = sqrt(sum(u.^2,1)); %norm(u,'fro') x = repmat(x0,[1,size(u,2)]) .* repmat(cos(th),[size(u,1),1]) + u .* repmat(sin(th)./th,[size(u,1),1]); x(:,th<1e-16) = repmat(x0,[1,sum(th<1e-16)]); @@ -123,7 +123,7 @@ function x = expmap(u,x0) % end end -function u = logmap(x,x0) +function u = logmap(x, x0) % %Version 0 % p = (x-x0) - trace(x0'*(x-x0)) * x0; % if norm(p,'fro')<1e-16 diff --git a/demos/demo_TPGMM_teleoperation01.m b/demos/demo_TPGMM_teleoperation01.m index 2ca89993bfa68dab87cdc67e0dbb42bb044fb79e..1b50462c09b967a4420a0e6388e2b78a3cd84019 100644 --- a/demos/demo_TPGMM_teleoperation01.m +++ b/demos/demo_TPGMM_teleoperation01.m @@ -327,12 +327,13 @@ while (ishandle(H)) % hp = [hp plotEE(xh, [0 .7 0], 0)]; % hp = [hp plotEE(xh2, [.8 0 0], 0)]; drawnow; -% print('-dpng',['graphs/anim/teleop_drill' num2str(id,'%.3d') '.png']); - id = id+1; - if mod(id,10)==0 - print('-dpng',['graphs/anim/teleop_drill' num2str(idf,'%.3d') '.png']); - idf = idf+1; - end + +% % print('-dpng',['graphs/anim/teleop_drill' num2str(id,'%.3d') '.png']); +% id = id+1; +% if mod(id,10)==0 +% print('-dpng',['graphs/anim/teleop_drill' num2str(idf,'%.3d') '.png']); +% idf = idf+1; +% end end diff --git a/demos/demo_gradientDescent01.m b/demos/demo_gradientDescent01.m index d971c136de051b428a2037048b9c351934d1c254..47c1defe7c3f738c8a5be56c09c3a51cdbd71e63 100644 --- a/demos/demo_gradientDescent01.m +++ b/demos/demo_gradientDescent01.m @@ -1,5 +1,5 @@ function demo_gradientDescent01 -% Optimization with gradient descent for 1D input (Newton's method) +% Optimization with gradient descent for 1D input (Newton's method for roots finding) % % Copyright (c) 2019 Idiap Research Institute, http://idiap.ch/ % Written by Sylvain Calinon, http://calinon.ch/ @@ -23,7 +23,7 @@ addpath('./m_fcts/'); %% Parameters %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -nbIter = 10; %Number of iterations +nbIter = 20; %Number of iterations %% Create manifold @@ -35,13 +35,14 @@ ym = fct(xm); %% Gradient descent %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -s(1).x0 = .45; -[s(1).xg, s(1).yg, s(1).J, s(1).H] = findMin(s(1).x0, nbIter); +% x0 = -.25; +x0 = 0.45; +[xg, yg, J, H] = findMin(x0, nbIter); %% Plots %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -figure('position',[10,10,800,1000],'color',[1 1 1]); hold on; axis off; +figure('position',[10,10,800,800],'color',[1 1 1]); hold on; axis off; plot(xm, ym, '-','linewidth',2,'color',[.6 .6 .6]); plot(xm, zeros(1,nbp), '-','linewidth',2,'color',[.6 .6 .6]); plot(xm, -ones(1,nbp)*.1, '-','linewidth',2,'color',[.6 .6 .6]); @@ -49,30 +50,30 @@ axis equal; axis([min(xm), max(xm), -.12, max(ym)]); % print('-dpng',['graphs/demo_1DgradientDescent' num2str(0,'%.2d') '.png']); % pause(.2); for t=1:nbIter-1 - plot(s(1).xg(1,t), s(1).yg(1,t), '.','markersize',30,'color',[.6 .6 .6]); - plot(s(1).xg(1,t), -.1, '.','markersize',30,'color',[.6 .6 .6]); + plot(xg(1,t), yg(1,t), '.','markersize',30,'color',[.6 .6 .6]); + plot(xg(1,t), -.1, '.','markersize',30,'color',[.6 .6 .6]); %Plot tangent plane - dx = s(1).xg(1,t+1) - s(1).xg(1,t); + dx = xg(1,t+1) - xg(1,t); if dx<0 xtmp = [dx, 4E-2]; else xtmp = [-4E-2, dx]; end - msh = [xtmp; s(1).J(1,t)'*xtmp] + repmat([s(1).xg(:,t); s(1).yg(:,t)], 1, 2); - h(1) = plot([s(1).xg(1,t), s(1).xg(1,t)], [-.1, s(1).yg(1,t)], '-','linewidth',1,'color',[.8 .8 .8]); + msh = [xtmp; J(1,t)'*xtmp] + repmat([xg(:,t); yg(:,t)], 1, 2); + h(1) = plot([xg(1,t), xg(1,t)], [-.1, yg(1,t)], '-','linewidth',1,'color',[.8 .8 .8]); h(2) = plot(msh(1,:),msh(2,:), '-','linewidth',2,'color',[0 0 .8]); - h(3) = plot2DArrow([s(1).xg(1,t); -.1], [dx; 0], [0 0 .8], 3, 1E-2); - h(4) = plot(s(1).xg(1,t), s(1).yg(1,t), '.','markersize',30,'color',[0 0 0]); - h(5) = plot(s(1).xg(1,t), -.1, '.','markersize',30,'color',[0 0 0]); + h(3) = plot2DArrow([xg(1,t); -.1], [dx; 0], [0 0 .8], 3, 1E-2); + h(4) = plot(xg(1,t), yg(1,t), '.','markersize',30,'color',[0 0 0]); + h(5) = plot(xg(1,t), -.1, '.','markersize',30,'color',[0 0 0]); % print('-dpng',['graphs/demo_1DgradientDescent' num2str(t,'%.2d') '.png']); % pause(.2); % delete(h); end -% plot(s(1).xg, s(1).yg, '.','markersize',20,'color',[0 0 0]); -% plot(s(1).xg, zeros(1,nbIter), '.','markersize',20,'color',[0 0 0]); -plot(s(1).xg(1,end), s(1).yg(1,end), '.','markersize',40,'color',[.8 0 0]); -plot(s(1).xg(1,end), -.1, '.','markersize',40,'color',[.8 0 0]); -% print('-dpng',['graphs/demo_1DgradientDescent' num2str(nbIter+1,'%.2d') '.png']); +% plot(xg, yg, '.','markersize',20,'color',[0 0 0]); +% plot(xg, zeros(1,nbIter), '.','markersize',20,'color',[0 0 0]); +plot(xg(1,end), yg(1,end), '.','markersize',40,'color',[.8 0 0]); +plot(xg(1,end), -.1, '.','markersize',40,'color',[.8 0 0]); +% print('-dpng','graphs/NewtonMethod_rootsFinding_final01.png'); % %Plot Jacobian and Hessian % Jm = grad(xm); @@ -80,15 +81,15 @@ plot(s(1).xg(1,end), -.1, '.','markersize',40,'color',[.8 0 0]); % plot(xm, Jm, '-','linewidth',2,'color',[.6 .6 .6]); % plot(xm, zeros(1,nbp),'-','linewidth',2,'color',[.6 .6 .6]); % for t=1:nbIter-1 -% plot(s(1).xg(1,t), s(1).J(1,t), '.','markersize',20,'color',[.3 .3 .3]); +% plot(xg(1,t), J(1,t), '.','markersize',20,'color',[.3 .3 .3]); % %Plot tangent plane % xtmp = [-1, 1] * 4E-2; -% msh = [xtmp; s(1).H(1,t)'*xtmp] + repmat([s(1).xg(:,t); s(1).J(1,t)], 1, 2); +% msh = [xtmp; H(1,t)'*xtmp] + repmat([xg(:,t); J(1,t)], 1, 2); % h(1) = plot(msh(1,:),msh(2,:), '-','linewidth',3,'color',[.3 .3 1]); % pause % delete(h); % end -% plot(s(1).xg(1,end), s(1).J(1,end), '.','markersize',30,'color',[.8 0 0]); +% plot(xg(1,end), J(1,end), '.','markersize',30,'color',[.8 0 0]); % %axis equal; pause; @@ -109,6 +110,7 @@ end function H = hess(x) %H = diff(g,x) + %H = hessian(f,x) H = 10.*exp(-x.^2) - 20.*x.^2.*exp(-x.^2) - 20.*sin(10.*x); end @@ -128,7 +130,7 @@ function [xg,yg,J,H] = findMin(x,nbIter) % %Second order gradient method (Newton's method for optimization used to find minimum of a function (with null Jacobian), https://en.wikipedia.org/wiki/Newton%27s_method_in_optimization) % H(:,t) = hess(x); -% x = x - 8E-1 * (H(:,t) \ J(:,t)); %Use of a 8E-1 factor to obtain more stable results +% x = x - 8E-1 * (H(:,t) \ J(:,t)); %Use of a step size (optional) %Newton's method for finding the zeros of a function (https://en.wikipedia.org/wiki/Newton%27s_method) x = x - J(:,t) \ fct(x); diff --git a/demos/demo_gradientDescent02.m b/demos/demo_gradientDescent02.m index fe05ec5cde9e2b3e990605a04173089ab4ce4a25..e95ebc56ac5615d880deebefeafbd203e1a43254 100644 --- a/demos/demo_gradientDescent02.m +++ b/demos/demo_gradientDescent02.m @@ -1,5 +1,5 @@ function demo_gradientDescent02 -% Optimization with gradient descent for 2D input (Newton's method) +% Optimization with gradient descent for 2D input (Newton's method for roots finding) % % Copyright (c) 2019 Idiap Research Institute, http://idiap.ch/ % Written by Sylvain Calinon, http://calinon.ch/ @@ -36,13 +36,13 @@ ym = fct(xm); %% Gradient descent %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -s(1).x0 = [.47; .4]; %(rand(nbVarIn,1)-0.5) .* .8; -[s(1).xg, s(1).yg, s(1).J] = findMin(s(1).x0,nbIter); +x0 = [.47; .4]; %(rand(nbVarIn,1)-0.5) .* .8; +[xg, yg, J] = findMin(x0,nbIter); %% Plots %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -figure('position',[10,10,1100,1000],'color',[1 1 1]); hold on; axis off; rotate3d on; +figure('position',[10,10,800,800],'color',[1 1 1]); hold on; axis off; rotate3d on; colormap([.7 .7 .7]); mesh(reshape(xm(1,:),nbp,nbp), reshape(xm(2,:),nbp,nbp), reshape(ym(1,:),nbp,nbp),'facealpha',.8,'edgealpha',.8); msh = [1 1 -1 -1 1; 1 -1 -1 1 1; -.4*ones(1,5)] .* .5; @@ -52,24 +52,23 @@ view(53,33); axis equal; axis vis3d; axis([-.55,.55,-.55,.55,-.22,.7]); % print('-dpng',['graphs/demo_2DgradientDescent' num2str(0,'%.2d') '.png']); % pause(.4); for t=1:nbIter-1 - plot3(s(1).xg(1,t), s(1).xg(2,t), s(1).yg(1,t), '.','markersize',20,'color',[.6 .6 .6]); - plot3(s(1).xg(1,t), s(1).xg(2,t), -.2, '.','markersize',20,'color',[.6 .6 .6]); + plot3(xg(1,t), xg(2,t), yg(1,t), '.','markersize',20,'color',[.6 .6 .6]); + plot3(xg(1,t), xg(2,t), -.2, '.','markersize',20,'color',[.6 .6 .6]); %Plot tangent plane xtmp = [1 1 -1 -1 1; 1 -1 -1 1 1] * 1E-1; - msh = [xtmp; s(1).J(:,t)'*xtmp] + repmat([s(1).xg(:,t); s(1).yg(1,t)], 1, 5); + msh = [xtmp; J(:,t)'*xtmp] + repmat([xg(:,t); yg(1,t)], 1, 5); h = patch(msh(1,:),msh(2,:),msh(3,:), [.3 .3 1],'edgecolor',[.6 .6 .6],'facealpha',.3,'edgealpha',.3); - h = [h, mArrow3([s(1).xg(:,t); -.2], [s(1).xg(:,t+1); -.2],'tipWidth',8E-3,'stemWidth',2E-3,'color',[.3 .3 1])]; %*norm(s(1).J(:,t)) - h = [h, plot3(s(1).xg(1,t), s(1).xg(2,t), s(1).yg(1,t), '.','markersize',20,'color',[0 0 0])]; - h = [h, plot3(s(1).xg(1,t), s(1).xg(2,t), -.2, '.','markersize',20,'color',[0 0 0])]; + h = [h, mArrow3([xg(:,t); -.2], [xg(:,t+1); -.2],'tipWidth',8E-3,'stemWidth',2E-3,'color',[.3 .3 1])]; %*norm(J(:,t)) + h = [h, plot3(xg(1,t), xg(2,t), yg(1,t), '.','markersize',20,'color',[0 0 0])]; + h = [h, plot3(xg(1,t), xg(2,t), -.2, '.','markersize',20,'color',[0 0 0])]; % pause(.4); % print('-dpng',['graphs/demo_2DgradientDescent' num2str(t,'%.2d') '.png']); % delete(h); end -% plot3(s(1).xg(1,:), s(1).xg(2,:), s(1).yg(1,:), '.','markersize',20,'color',[0 0 0]); -% plot3(s(1).xg(1,:), s(1).xg(2,:), zeros(1,nbIter), '.','markersize',20,'color',[0 0 0]); -plot3(s(1).xg(1,end), s(1).xg(2,end), s(1).yg(1,end), '.','markersize',40,'color',[.8 0 0]); -plot3(s(1).xg(1,end), s(1).xg(2,end), -.2, '.','markersize',40,'color',[.8 0 0]); - +% plot3(xg(1,:), xg(2,:), yg(1,:), '.','markersize',20,'color',[0 0 0]); +% plot3(xg(1,:), xg(2,:), zeros(1,nbIter), '.','markersize',20,'color',[0 0 0]); +plot3(xg(1,end), xg(2,end), yg(1,end), '.','markersize',40,'color',[.8 0 0]); +plot3(xg(1,end), xg(2,end), -.2, '.','markersize',40,'color',[.8 0 0]); % print('-dpng',['graphs/demo_2DgradientDescent' num2str(nbIter,'%.2d') '.png']); pause; diff --git a/demos/demo_gradientDescent03.m b/demos/demo_gradientDescent03.m index 8c0fe64ad4935a7328550821f7b1185e69d368d4..024877681452a88defab0c6c6e049f0d1a2b5940 100644 --- a/demos/demo_gradientDescent03.m +++ b/demos/demo_gradientDescent03.m @@ -1,5 +1,5 @@ function demo_gradientDescent03 -% Optimization with gradient descent for 1D input and 2D output (Gauss-Newton algorithm) +% Optimization with gradient descent for 1D input and 2D output (Newton's method for roots finding) % % Copyright (c) 2019 Idiap Research Institute, http://idiap.ch/ % Written by Sylvain Calinon, http://calinon.ch/ @@ -35,13 +35,13 @@ ym = fct(xm); %% Gradient descent %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -s(1).x0 = .45; -[s(1).xg, s(1).yg, s(1).J] = findMin(s(1).x0, nbIter); +x0 = .45; +[xg, yg, J] = findMin(x0, nbIter); %% Plots %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -figure('position',[10,10,800,1300],'color',[1 1 1]); hold on; axis off; +figure('position',[10,10,800,800],'color',[1 1 1]); hold on; axis off; ofs = 1; for k=1:2 plot(xm, ym(k,:)+(k-1)*ofs, '-','linewidth',2,'color',[.6 .6 .6]); @@ -56,24 +56,24 @@ axis([min(xm), max(xm), -.12, max(ym(k,:))+ofs]); for t=1:nbIter-1 h=[]; for k=1:2 - plot(s(1).xg(1,t), s(1).yg(k,t)+(k-1)*ofs, '.','markersize',30,'color',[.6 .6 .6]); + plot(xg(1,t), yg(k,t)+(k-1)*ofs, '.','markersize',30,'color',[.6 .6 .6]); %Plot tangent plane xtmp = [-1, 1] * 4E-2; - msh = [xtmp; s(1).J(k,t)'*xtmp] + repmat([s(1).xg(:,t); s(1).yg(k,t)+(k-1)*ofs], 1, 2); + msh = [xtmp; J(k,t)'*xtmp] + repmat([xg(:,t); yg(k,t)+(k-1)*ofs], 1, 2); h = [h, plot(msh(1,:), msh(2,:), '-','linewidth',3,'color',[.3 .3 1])]; - h = [h, plot(s(1).xg(1,t), s(1).yg(k,t)+(k-1)*ofs, '.','markersize',30,'color',[0 0 0])]; + h = [h, plot(xg(1,t), yg(k,t)+(k-1)*ofs, '.','markersize',30,'color',[0 0 0])]; end %k - plot(s(1).xg(1,t), -.1, '.','markersize',30,'color',[.6 .6 .6]); - h = [h, plot2DArrow([s(1).xg(1,t); -.1], [s(1).xg(1,t+1)-s(1).xg(1,t); 0], [.3 .3 1], 3, 1E-2)]; - h = [h, plot(s(1).xg(1,t), -.1, '.','markersize',30,'color',[0 0 0])]; + plot(xg(1,t), -.1, '.','markersize',30,'color',[.6 .6 .6]); + h = [h, plot2DArrow([xg(1,t); -.1], [xg(1,t+1)-xg(1,t); 0], [.3 .3 1], 3, 1E-2)]; + h = [h, plot(xg(1,t), -.1, '.','markersize',30,'color',[0 0 0])]; % print('-dpng',['graphs/demo_multiOutputGradientDescent' num2str(t,'%.2d') '.png']); % pause(.1); % delete(h); end %t for k=1:2 - plot(s(1).xg(1,end), s(1).yg(k,end)+(k-1)*ofs, '.','markersize',40,'color',[.8 0 0]); + plot(xg(1,end), yg(k,end)+(k-1)*ofs, '.','markersize',40,'color',[.8 0 0]); end -plot(s(1).xg(1,end), -.1, '.','markersize',40,'color',[.8 0 0]); +plot(xg(1,end), -.1, '.','markersize',40,'color',[.8 0 0]); % print('-dpng',['graphs/demo_multiOutputGradientDescent' num2str(nbIter,'%.2d') '.png']); pause; diff --git a/demos/demo_gradientDescent04.m b/demos/demo_gradientDescent04.m index f0298a544a62560996c514f22f744276142d4e21..d2dfc488b1d79c007f8d5da98ac765a611a25a2f 100644 --- a/demos/demo_gradientDescent04.m +++ b/demos/demo_gradientDescent04.m @@ -1,5 +1,5 @@ function demo_gradientDescent04 -% Optimization with gradient descent for 2D input and 2D output depicting a planar robot IK problem (Gauss-Newton algorithm). +% Optimization with gradient descent for 2D input and 2D output depicting a planar robot IK problem (Newton's method for roots finding). % First run 'startup_rvc' from the robotics toolbox. % % Copyright (c) 2019 Idiap Research Institute, http://idiap.ch/ @@ -46,13 +46,13 @@ ym = fct(xm, xd, robot); %% Gradient descent %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -s(1).x0 = [.2; 2]; %Initial pose -[s(1).xg, s(1).yg, s(1).J] = findMin(s(1).x0, xd, robot, nbIter); +x0 = [.2; 2]; %Initial pose +[xg, yg, J] = findMin(x0, xd, robot, nbIter); %% Plots %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -figure('position',[10,10,2400,1000],'color',[1 1 1]); +figure('position',[10,10,1400,800],'color',[1 1 1]); subplot(1,2,1); hold on; axis off; rotate3d on; colormap([.7 .7 .7]); @@ -69,7 +69,7 @@ view(53,33); axis equal; axis vis3d; %axis([-.55,.55,-.55,.55,-.22,.7]); %plot robot subplot(1,2,2); hold on; axis off; plot3(xd(1), xd(2), 0, '.','markersize',50,'color',[.8 0 0]); -% plotArm(s(1).x0, ones(nbDOFs,1)*armLength, [0;0;-20], .02, [.6 .6 .6]); +% plotArm(x0, ones(nbDOFs,1)*armLength, [0;0;-20], .02, [.6 .6 .6]); axis equal; axis tight; axis([-.55,.45,-.1,.7]); % pause(.4); % print('-dpng',['graphs/demo_robotGradientDescent' num2str(0,'%.2d') '.png']); @@ -80,22 +80,22 @@ for t=1:nbIter-1 subplot(1,2,1); hold on; h=[]; for k=1:2 - plot3(s(1).xg(1,t), s(1).xg(2,t), s(1).yg(k,t)+(k-1)*ofs, '.','markersize',20,'color',[.6 .6 .6]); - plot3(s(1).xg(1,t), s(1).xg(2,t), -3, '.','markersize',20,'color',[.6 .6 .6]); + plot3(xg(1,t), xg(2,t), yg(k,t)+(k-1)*ofs, '.','markersize',20,'color',[.6 .6 .6]); + plot3(xg(1,t), xg(2,t), -3, '.','markersize',20,'color',[.6 .6 .6]); % %Plot tangent plane % xtmp = [1 1 -1 -1 1; 1 -1 -1 1 1] * 5E-1; -% msh = [xtmp; s(1).J(k,:,t)*xtmp] + repmat([s(1).xg(:,t); s(1).yg(k,t)+(k-1)*ofs], 1, 5); +% msh = [xtmp; J(k,:,t)*xtmp] + repmat([xg(:,t); yg(k,t)+(k-1)*ofs], 1, 5); % h = [h, patch(msh(1,:),msh(2,:),msh(3,:), [.3 .3 1],'edgecolor',[.6 .6 .6],'facealpha',.3,'edgealpha',.3)]; -% h = [h, plot3(s(1).xg(1,t), s(1).xg(2,t), s(1).yg(k,t)+(k-1)*ofs, '.','markersize',20,'color',[0 0 0])]; +% h = [h, plot3(xg(1,t), xg(2,t), yg(k,t)+(k-1)*ofs, '.','markersize',20,'color',[0 0 0])]; end %k - h = [h, mArrow3([s(1).xg(:,t); -3], [s(1).xg(:,t+1); -3],'tipWidth',6E-2,'stemWidth',2E-2,'color',[.3 .3 1])]; %*norm(s(1).J(:,t)) -% h = [h, plot3(s(1).xg(1,t), s(1).xg(2,t), -3, '.','markersize',20,'color',[0 0 0])]; -% h = [h, plot3([s(1).xg(1,t), s(1).xg(1,t)], [s(1).xg(2,t), s(1).xg(2,t)], [-3 s(1).yg(2,t)+ofs], '-','linewidth',1,'color',[.4 .4 .4])]; + h = [h, mArrow3([xg(:,t); -3], [xg(:,t+1); -3],'tipWidth',6E-2,'stemWidth',2E-2,'color',[.3 .3 1])]; %*norm(J(:,t)) +% h = [h, plot3(xg(1,t), xg(2,t), -3, '.','markersize',20,'color',[0 0 0])]; +% h = [h, plot3([xg(1,t), xg(1,t)], [xg(2,t), xg(2,t)], [-3 yg(2,t)+ofs], '-','linewidth',1,'color',[.4 .4 .4])]; %plot robot subplot(1,2,2); hold on; - plotArm(s(1).xg(:,t), ones(nbDOFs,1)*armLength, [0;0;-100+t], .02, [.7 .7 .7]); - % h = [h, plotArm(s(1).xg(:,t), ones(nbDOFs,1)*armLength, [0;0;-100+t], .02, [.2 .2 .2])]; + plotArm(xg(:,t), ones(nbDOFs,1)*armLength, [0;0;-100+t], .02, [.7 .7 .7]); + % h = [h, plotArm(xg(:,t), ones(nbDOFs,1)*armLength, [0;0;-100+t], .02, [.2 .2 .2])]; % pause(.4); % print('-dpng',['graphs/demo_robotGradientDescent' num2str(t,'%.2d') '.png']); @@ -105,12 +105,12 @@ end %t subplot(1,2,1); hold on; for k=1:2 - plot3(s(1).xg(1,end), s(1).xg(2,end), s(1).yg(k,end)+(k-1)*ofs, '.','markersize',40,'color',[.8 0 0]); + plot3(xg(1,end), xg(2,end), yg(k,end)+(k-1)*ofs, '.','markersize',40,'color',[.8 0 0]); end -plot3([s(1).xg(1,end), s(1).xg(1,end)], [s(1).xg(2,end), s(1).xg(2,end)], [-3 ofs], '-','linewidth',1,'color',[1 .2 .2]); -plot3(s(1).xg(1,end), s(1).xg(2,end), -3, '.','markersize',40,'color',[.8 0 0]); +plot3([xg(1,end), xg(1,end)], [xg(2,end), xg(2,end)], [-3 ofs], '-','linewidth',1,'color',[1 .2 .2]); +plot3(xg(1,end), xg(2,end), -3, '.','markersize',40,'color',[.8 0 0]); subplot(1,2,2); hold on; -plotArm(s(1).xg(:,t), ones(nbDOFs,1)*armLength, [0;0;-1], .02, [.2 .2 .2]); +plotArm(xg(:,t), ones(nbDOFs,1)*armLength, [0;0;-1], .02, [.2 .2 .2]); % pause(.4); % print('-dpng',['graphs/demo_robotGradientDescent' num2str(nbIter,'%.2d') '.png']); diff --git a/demos/m_fcts/angDiffFromQuat.m b/demos/m_fcts/angDiffFromQuat.m index 32c127d0391307e3dfc5584e3e2c147ede284b92..4d5b607cee6805f4b79a359c2217f698631ad22f 100644 --- a/demos/m_fcts/angDiffFromQuat.m +++ b/demos/m_fcts/angDiffFromQuat.m @@ -1,4 +1,4 @@ -function omega = angDiffFromQuat(Q1,Q2) +function omega = angDiffFromQuat(Q1, Q2) q1 = Quaternion(Q1); q2 = Quaternion(Q2); @@ -8,5 +8,4 @@ if(q1.inner(q2)<0) q2 = Quaternion(-q2.double); end -omega = 2 * quaternionLog(q1*q2.inv)'; - +omega = 2 * quaternionLog(q1 * q2.inv)'; \ No newline at end of file diff --git a/demos/m_fcts/plot2DArrow.m b/demos/m_fcts/plot2DArrow.m index bde939bbd2f4dc326ac20cc270027a9d4c6a4f13..7b995079146042e229ec81b0752782f03ee6fac3 100644 --- a/demos/m_fcts/plot2DArrow.m +++ b/demos/m_fcts/plot2DArrow.m @@ -1,4 +1,4 @@ -function h = plot2DArrow(pos,dir,col,lnw,sz,alpha) +function [h, msh] = plot2DArrow(pos, dir, col, lnw, sz, alpha) % Simple display of a 2D arrow % % Writing code takes time. Polishing it and making it available to others takes longer! @@ -39,7 +39,7 @@ if nargin<6 alpha = 1; end if nargin<5 - sz = 1E-1; + sz = norm(dir) .* 4E-2; end if nargin<4 lnw = 2; @@ -56,6 +56,6 @@ if norm(dir)>sz prp = [d(2); -d(1)]; d = d*sz; prp = prp*sz; - msh = [msh pos-d pos-d-prp/2 pos pos-d+prp/2 pos-d msh]; - h = patch(msh(1,:),msh(2,:),col,'edgecolor',col,'linewidth',lnw,'edgealpha',alpha,'facealpha',alpha); -end + msh = [msh, pos-d, pos-d-prp/2, pos, pos-d+prp/2, pos-d, msh]; + h = patch(msh(1,:), msh(2,:), col, 'edgecolor',col,'linewidth',lnw,'edgealpha',alpha,'facealpha',alpha); +end \ No newline at end of file diff --git a/demos/m_fcts/plotGMM.m b/demos/m_fcts/plotGMM.m index 1f20b1f37847bf1e494f93a9a42f7a4027484214..a2e0c1f4731487f8c79c4f52d0e456a4891484c6 100644 --- a/demos/m_fcts/plotGMM.m +++ b/demos/m_fcts/plotGMM.m @@ -63,9 +63,9 @@ for i=1:nbStates %h = [h patch(MuTmp(1,:), MuTmp(2,:), darkcolor, 'LineStyle', 'none', 'facealpha', valAlpha)]; h = [h plot(Mu(1,:), Mu(2,:), '.', 'markersize', 10, 'color', darkcolor)]; else %Plot without transparency - h = [h plot(Mu(1,:), Mu(2,:), '.', 'markersize', 10, 'color', darkcolor)]; %Standard plot h = [h patch(X(1,:,i), X(2,:,i), color, 'lineWidth', 1, 'EdgeColor', darkcolor)]; + h = [h plot(Mu(1,:), Mu(2,:), '.', 'markersize', 10, 'color', darkcolor)]; % %Plot only contours % h = [h plot(X(1,:,i), X(2,:,i), '-', 'color', color, 'lineWidth', 1)]; end diff --git a/demos/m_fcts/quaternionLog.m b/demos/m_fcts/quaternionLog.m index bc13743728f0dc6c3e881bb06e2658743e438192..2dc9a64e5e9b2ab0db3f0b8392e4badaee1398d5 100644 --- a/demos/m_fcts/quaternionLog.m +++ b/demos/m_fcts/quaternionLog.m @@ -15,5 +15,5 @@ end if norm(q.v)<realmin a = [0 0 0]; else - a = 2 * acos(q.s) * q.v/norm(q.v); + a = 2 * acos(q.s) * q.v / norm(q.v); end \ No newline at end of file