%  Mouse-driven motion planning
%      for  the doucble pendulum at the "musée des sciences de la Villette"
%  mai 99
%  Ecole des Mines de Paris, 
%  Centre Automatique et Systemes
%  60 Bd St Michel 
%  75272 Paris
%    Pierre Rouchon: rouchon@cas.ensmp.fr
% 
% Linear approximation 
% 1 homogeneous beams of length l 
% vertical deviation th
% troley abscissa  D  is the control 
%  Motion planning based on the flat output: 
%         z= D + (2/3)*th*l,  abscisse of the oscillation center,  is the flat output
% g gravity
%
%  th= z^(2)/g  
%  D  = z - (2/3)*z^(2)/g  * l 
%
%      
%
% 
%     
clear all;

L=1.;  % beam length 
g=9.81; % gravity in  m/s^2
scale=10.8825;

A = 0.75; th= 0; 

D=A; 

z= D + (2/3)*th*L  ;


dtmin=0.0005;
dtmax=0.1;

dt=0.02/10;
n=min(1000,floor(5/dt));
Dr=D*ones(1,n);thr=th*ones(1,n);zr=z*ones(1,n);

nn=[1:n-1];
tr=0*Dr;

figure(1),clf;
go=1;
mouse=0;
set(gca,'position',[0 0 1 1],'visible','off','Xlim',[0 19],'Ylim',[0 14]....
   ,'nextplot','add')
set(gcf,'CloseRequestFcn','go=0; closereq;',...
	'WindowButtonUpFcn',['mouse=0;set(ref,''facecolor'',''y'') ;'...
		'set(gcf,''WindowButtonMotionFcn'','''');']);
          


%  trolley
Xt=1+[0   1  1  0  ] + scale*D;
Yt=1+[0   0  1/2  1/2  ];
trol=fill(Xt,Yt,'g','EraseMode','background');

%  ref
Xr=1+[0   1  0.5  0  ] + scale*D;
Yr=0.3+[0   0  1/2  0  ];
ref=fill(Xr,Yr,'y', 'EraseMode','xor',...
        'ButtonDownFcn',['mouse=1; set(ref,''facecolor'',''r'');' ...
           'set(gcf,''WindowButtonMotionFcn'',''1;'')']);

% pendule 1 et 2 avec les deux articulations
Xp=1.5 + scale*[ D  D+L*sin(th)   ];
Yp=1.5+scale*[0  L*cos(th)   ];

Xj=1.5 + scale*(D + L*cos(0:(2*pi/10):(2*pi))/50 );
Yj=1.5+scale*(L*sin(0:(2*pi/10):(2*pi))/50);

P=line(Xp,Yp,'EraseMode','background','LineWidth', 4, 'Color', [0 0 1 ]);
J=fill(Xj,Yj,'k','EraseMode','background','Facecolor',[0 0 1 ]);



% title
text(9.5,13.5,'INVERTED PENDULUM: MOUSE-DRIVEN MOTION PLANNING','color',[0 0 0],...
   'EraseMode','background','HorizontalAlignment','center');
text(9.5,13,'display speed slider','color',[0 0 0],'EraseMode','background','HorizontalAlignment','center');
p1=[7.5/19 12.6/14 4/19 0.2/14];
Hslider=uicontrol(figure(1),'units','normalized','style','slider','position',p1,...
			'min',log(dtmin),'max',log(dtmax),'value',log(dt),...
         'callback',['buf=get(Hslider,''value'');dt=exp(buf);']); 
      









i=0;

ts=0.25;

seuil=0.4;

z1=z;
z2=z;
z3=z;






Hplay=uicontrol('style','push',...
                'units','normalized','position',[15/19 12.7/14 2/19 .5/14], ....
                'string','Plot','callback',[ ...
                'figure(2);clf;' ...
                'subplot(211);plot(tr,zr); zoom on;' ...
                'title(''flat output  (m) versus time (s)'');' ...
                'subplot(212);plot(tr,Dr);zoom on;'...
                'title(''troley position (m) versus time (s)'');'...
                'figure(3);clf;plot(tr,thr,''-'');zoom on;' ...
                'title(''pendulum angle (rd) versus time (s)'');' ...
                'pause;figure(1);' ...
                ]);
            
                           
set(Hplay,'visible','off');
             
Hrun=uicontrol('style','push',...
                'units','normalized','position',[1/19 12.7/14 2/19 .5/14], ....
                'string','stop','callback', ...
                ' go=0;' );
set(Hrun,'visible','off');

figure(1);
pause(1)
set(Hplay,'visible','on')
set(Hrun,'visible','on')
Tini=2;
tt=0;
buf(1,1)=1.5 + z*scale;
while (go >0)
   tt=tt+dt;
   if  (tt > Tini)
    if mouse > 0 
       buf=get(gca,'CurrentPoint');
    end
     A=(buf(1,1)-1.5)/scale;
     A=max(0,A);
     A=min(1.4,A); 
   end;
   z1=(z1+dt*z2/ts)/(1+dt/ts);
   z2=(z2+dt*z3/ts)/(1+dt/ts);
   tb=ts;
   sat=A-z2;
   if(tt > Tini)
     tb=ts*max(1,abs(sat)/seuil);
   end;
   z3=(z3+dt*A/tb)/(1+dt/tb);
 
   z=z1;
   dz=(z2-z1)/ts; 
   dz2=(z3-z2)/ts;
   d2z=(dz2-dz)/ts;
   
   th= d2z/g ;
   D  = z - (2/3)*th  * L ;
   
   Xt=1+[0   1  1  0  ] + scale*D;
   Xr=1+[0   1  0.5  0  ] + scale*A;

   Xp=1.5 + scale*[ D  D+L*sin(th)   ];
   Yp=1.5+scale*[0  L*cos(th)   ];

   Xj=1.5 + scale*(D + L*cos(0:(2*pi/10):(2*pi))/50 );
   Yj=1.5+scale*(L*sin(0:(2*pi/10):(2*pi))/50);
   
   set(trol, 'XData',Xt); 
   set(ref, 'XData',Xr); 
   set(P,'XData',Xp,'Ydata',Yp);
   set(J,'XData',Xj,'Ydata',Yj); 
   drawnow;
   Dr(nn)=Dr(nn+1); Dr(n)=D;
   zr(nn)=zr(nn+1); zr(n)=z;
   thr(nn)=thr(nn+1); thr(n)=th;
    tr(nn)=tr(nn+1);tr(n)=tt;
   

  
end;


close(figure(1));
close(figure(2));
close(figure(3));


return
