Pursuit Curves in Matlab

The pursuit m-file numerically calculates the pursuit curve and animates it






function varargout=pursuit(varargin);

if nargin==0
Hf=findobj(get(0,'Children'),'Tag','PursuitMainFig');
if isempty(Hf) %Check for multiple instances
status='init';
else
status='wait';
end
else
status=varargin{1};
end

%Goto correct function
switch status
case 'wait'
shg;
%Wait for user....



%Initialize
case 'init'
%Set up main figure window
s = get(0,'ScreenSize');
w=500; %Width of figure window
h=420; %Height of figure window
HfMain = figure('Units','pixels', ...
'Position',[(s(3)-w)/2 (s(4)-h)/2 w h], ...
'NumberTitle','off', ...
'Name','Pursuit Curve', ...
'Tag','PursuitMainFig');

%Set background color for ui control text
Color = get(HfMain,'Color');

%Hide Help menu and show Gallery
HmG = uimenu(HfMain,'Label','&Gallery', ...
'Tag', 'GalleryMenu');
uimenu(HmG,'Label','&Astroid', ...
'Tag', 'AstroidGalleryMenu', ...
'Callback', 'pursuit(''Gallery'',''Astroid'')');
uimenu(HmG,'Label','C&ardioid', ...
'Tag', 'CardioidGalleryMenu', ...
'Callback', 'pursuit(''Gallery'',''Cardioid'')');
uimenu(HmG,'Label','&Circle', ...
'Tag', 'CircleGalleryMenu', ...
'Callback', 'pursuit(''Gallery'',''Circle'')');
uimenu(HmG,'Label','F&reeth''s Nephroid', ...
'Tag', 'FreethGalleryMenu', ...
'Callback', 'pursuit(''Gallery'',''Freeth'')');
uimenu(HmG,'Label','&Hypocycloid', ...
'Tag', 'HypocycloidGalleryMenu', ...
'Callback', 'pursuit(''Gallery'',''Hypocycloid'')');
uimenu(HmG,'Label','&Line', ...
'Tag', 'LineGalleryMenu', ...
'Callback', 'pursuit(''Gallery'',''Line'')');
uimenu(HmG,'Label','&Nephroid', ...
'Tag', 'NephroidGalleryMenu', ...
'Callback', 'pursuit(''Gallery'',''Nephroid'')');
uimenu(HmG,'Label','&Warren''s Curve', ...
'Tag', 'WarrenGalleryMenu', ...
'Callback', 'pursuit(''Gallery'',''Warren'')');
uimenu(HmG,'Label','W&ierd', ...
'Tag', 'WierdGalleryMenu', ...
'Callback', 'pursuit(''Gallery'',''Wierd'')');

%Set up axes
HaMain=pursuit('SetAxes',HfMain);

%Set up start button
H = uicontrol('Parent',HfMain, ...
'Units','pixels', ...
'Position',[385 80 75 24], ...
'Callback','pursuit(''intpplot'')', ...
'String','Start', ...
'Style','pushbutton', ...
'Tag','PursuitStartButton');

%Set up close button
H = uicontrol('Parent',HfMain, ...
'Units','pixels', ...
'Position',[385 40 75 24], ...
'Callback','close(''Pursuit Curve'')', ...
'String','Close', ...
'Style','pushbutton', ...
'Tag','PursuitCloseButton');

%Set up edit boxes for Pursued equations
H = uicontrol('Parent',HfMain, ...
'Units','pixels', ...
'Position',[45 385 300 15], ...
'String','Pursued Curve''s Parametric Equations', ...
'Style', 'Text', ...
'BackgroundColor',Color,...
'Tag', 'PursuitCurveText');
H = uicontrol('Parent',HfMain, ...
'Units','pixels', ...
'Position',[23 362.5 25 15], ...
'String','x(t)', ...
'Style', 'Text', ...
'BackgroundColor',Color,...
'Tag', 'xPursuitCurveText');
H = uicontrol('Parent',HfMain, ...
'Units','pixels', ...
'Position',[45 360 130 20], ...
'String','cos(t)', ...
'BackgroundColor',[1 1 1], ...
'Style','edit', ...
'Tag','xPursuedEdit');
H = uicontrol('Parent',HfMain, ...
'Units','pixels', ...
'Position',[193 362.5 25 15], ...
'String','y(t)', ...
'Style', 'Text', ...
'BackgroundColor',Color,...
'Tag', 'yPursuitCurveText');
H = uicontrol('Parent',HfMain, ...
'Units','pixels', ...
'Position',[215 360 130 20], ...
'BackgroundColor',[1 1 1], ...
'String','sin(t)', ...
'Style','edit', ...
'Tag','yPursuedEdit');

%Set up t values edit
H = uicontrol('Parent',HfMain, ...
'Units','pixels', ...
'Position',[370 385 105 15], ...
'String','t Values', ...
'Style', 'Text', ...
'BackgroundColor',Color,...
'Tag', 'tValuesText');
H = uicontrol('Parent',HfMain, ...
'Units','pixels', ...
'BackgroundColor',[1 1 1], ...
'Position',[370 360 43 20], ...
'String', '0', ...
'Style','edit', ...
'Tag','tInitEdit');
H = uicontrol('Parent',HfMain, ...
'Units','pixels', ...
'Position',[415 362.5 15 15], ...
'String','to', ...
'Style', 'Text', ...
'BackgroundColor',Color,...
'Tag', 'totValuesText');
H = uicontrol('Parent',HfMain, ...
'Units','pixels', ...
'BackgroundColor',[1 1 1], ...
'Position',[432 360 42 20], ...
'String', '5*pi', ...
'Style','edit', ...
'Tag','tFinalEdit');

%Set up step size edit
H = uicontrol('Parent',HfMain, ...
'Units','pixels', ...
'Position',[350 300 145 15], ...
'String','Step Size', ...
'Style', 'Text', ...
'BackgroundColor',Color,...
'Tag', 'StepSizeText');
H = uicontrol('Parent',HfMain, ...
'Units','pixels', ...
'BackgroundColor',[1 1 1], ...
'Position',[390 275 65 20], ...
'String', '.1', ...
'Style','edit', ...
'Tag','StepSizeEdit');

%Set up pursuer's starting point edit
H = uicontrol('Parent',HfMain, ...
'Units','pixels', ...
'Position',[350 225 145 15], ...
'String','Pursuer''s Starting Point', ...
'Style', 'Text', ...
'BackgroundColor',Color,...
'Tag', 'PursuerStartText');
H = uicontrol('Parent',HfMain, ...
'Units','pixels', ...
'Position',[358 202.5 10 15], ...
'String','(', ...
'HorizontalAlignment','Right', ...
'Style', 'Text', ...
'BackgroundColor',Color,...
'Tag', 'LParPursuerStartText');
H = uicontrol('Parent',HfMain, ...
'Units','pixels', ...
'BackgroundColor',[1 1 1], ...
'Position',[370 200 43 20], ...
'String', '0', ...
'Style','edit', ...
'Tag','xPursuerInitEdit');
H = uicontrol('Parent',HfMain, ...
'Units','pixels', ...
'Position',[415 202.5 15 15], ...
'String',',', ...
'Style', 'Text', ...
'BackgroundColor',Color,...
'Tag', 'CommaPursuerStartText');
H = uicontrol('Parent',HfMain, ...
'Units','pixels', ...
'BackgroundColor',[1 1 1], ...
'Position',[432 200 43 20], ...
'String', '0', ...
'Style','edit', ...
'Tag','yPursuerInitEdit');
H = uicontrol('Parent',HfMain, ...
'Units','pixels', ...
'Position',[477 202.5 10 15], ...
'String',')', ...
'HorizontalAlignment','Left', ...
'Style', 'Text', ...
'BackgroundColor',Color,...
'Tag', 'RParPursuerStartText');

%Set up relative speed edit
H = uicontrol('Parent',HfMain, ...
'Units','pixels', ...
'Position',[350 150 145 15], ...
'String','Pursuer''s Relative Speed', ...
'Style', 'Text', ...
'BackgroundColor',Color,...
'Tag', 'tValuesText');
H = uicontrol('Parent',HfMain, ...
'Units','pixels', ...
'BackgroundColor',[1 1 1], ...
'Position',[390 125 65 20], ...
'String', '.75', ...
'Style','edit', ...
'Tag','RelativeSpeedEdit');
refresh(HfMain);


%Initialize Axes
case 'SetAxes'
SAxes=struct('Parent',varargin{2}, ...
'Units','pixels', ...
'Position',[45 45 300 300], ...
'Box','on', ...
'DataAspectRatio',[1 1 1], ...
'PlotBoxAspectRatio',[1 1 1], ...
'Tag','PursuitMainAxes');
H=gca;
set(H,SAxes);
xlabel('x-axis');
ylabel('y-axis');
varargout{1}=H;



%Plot Curves
case 'intpplot'

%Get figure handle
Hf=findobj(get(0,'Children'),'Tag','PursuitMainFig');

%Get Children
Hc=get(Hf,'Children');

%Change start to stop
%Hstart=findobj(Hf,'flat','Tag','PursuitStartButton');
%set(Hstart,'String','Stop', ...
% 'Callback', '');
%refresh(Hf);

%Get axes handle
Ha=findobj(Hc,'flat','Tag','PursuitMainAxes');

%Get parameters
H=findobj(Hc,'flat','Tag','RelativeSpeedEdit');
k=eval(get(H,'String'));
H=findobj(Hc,'flat','Tag','xPursuedEdit');
p=get(H,'String');
H=findobj(Hc,'flat','Tag','yPursuedEdit');
q=get(H,'String');
H=findobj(Hc,'flat','Tag','tInitEdit');
ti=eval(get(H,'String'));
H=findobj(Hc,'flat','Tag','tFinalEdit');
tf=eval(get(H,'String'));
H=findobj(Hc,'flat','Tag','xPursuerInitEdit');
xi=eval(get(H,'String'));
H=findobj(Hc,'flat','Tag','yPursuerInitEdit');
yi=eval(get(H,'String'));
H=findobj(Hc,'flat','Tag','StepSizeEdit');
s=eval(get(H,'String'));

%Call internal pursuit curve calculater
[pursuer,pursued]=pursuit('calc',k,p,q,[ti,tf],[xi;yi],s);

%Clear Axes
cla;

%Comet pursuit curve
pursuit('comet', Ha, ...
pursuer.x, pursuer.y, ...
pursued.x, pursued.y);

%Plot approximate pursuit curve
H = plot(pursuer.x,pursuer.y,'r', ...
pursued.x,pursued.y,'b');

%Reinitialize Axes
pursuit('SetAxes',Hf);



%Change stop to start
%set(Hstart,'String','Start', ...
% 'Callback', 'pursuit(''intpplot'')');
%refresh(Hf);



%Calculate x and y of pursuer and pursued
case 'calc'
%Set variables from input args
k=varargin{2};
pfunc=varargin{3};
qfunc=varargin{4};
bounds=varargin{5};
xyinit=varargin{6};
s=varargin{7};

%Make p and q vector safe
pfunc = strrep(pfunc,'.','');
qfunc = strrep(qfunc,'.','');
pfunc = strrep(pfunc,'*','.*');
qfunc = strrep(qfunc,'*','.*');
pfunc = strrep(pfunc,'/','./');
qfunc = strrep(qfunc,'/','./');
pfunc = strrep(pfunc,'^','.^');
qfunc = strrep(qfunc,'^','.^');

%Calculate t based on bounds and step size.
ns=round(100/abs(s));
t=linspace(bounds(1),bounds(2),ns);

%Delcare more variables
x=zeros(size(t));
y=zeros(size(t));
p=zeros(size(t));
q=zeros(size(t));
d=0;
u=0;

%Set intitial conditions
x(1)=xyinit(1);
y(1)=xyinit(2);

%Evaluate p(t) and q(t)
p=eval(pfunc).*ones(size(t));
q=eval(qfunc).*ones(size(t));

%Approximate x and y
for n=1:ns-1
d = sqrt( (p(n+1)-p(n))^2 + (q(n+1)-q(n))^2 );
pn=p(n); %+ (p(n+1)-p(n))/2;
qn=q(n); %+ (q(n+1)-q(n))/2;
u = sqrt( (pn-x(n))^2 + (qn-y(n))^2 );
x(n+1) = x(n) + k*d*(pn-x(n))/u;
y(n+1) = y(n) + k*d*(qn-y(n))/u;
end

%If no arguments out, plot curves, arrange figure window
if nargout == 0
h=plot(p,q,'b',x,y,'r',x(1),y(1),'*r');
legend(h,'Pursued','Pursuer');
set(gcf,'NumberTitle','off','Name','Pursuit Curves in MATLAB');
xlabel('x-axis');
ylabel('y-axis');
axis equal;
shg;

%Else return calculations
else
varargout{1} = struct('t',t, ...
'x', x, ...
'y', y);
varargout{2} = struct('t',t, ...
'x', p, ...
'y', q);
end




case 'comet'
%(h,x1,y1,x2,y2,p)
if nargin == 1, error('Not enough input arguments.'); end
if nargin < 7
p = 0.05;
end

ax = varargin{2};
x1=varargin{3};
y1=varargin{4};
x2=varargin{5};
y2=varargin{6};

if ~ishold,
xmax = max( [x1(isfinite(x1)), x2(isfinite(x2))] );
xmin = min( [x1(isfinite(x1)), x2(isfinite(x2))] );
ymax = max( [y1(isfinite(y1)), y2(isfinite(y2))] );
ymin = min( [y1(isfinite(y1)), y2(isfinite(y2))] );
if (xmax-xmin) > (ymax-ymin)
xdiff = ( xmax-xmin - (ymax-ymin) )/2;
ymax = ymax + xdiff;
ymin = ymin - xdiff;
elseif (xmax-xmin) < (ymax-ymin)
ydiff = ( ymax-ymin - (xmax-xmin) )/2;
xmax = xmax + ydiff;
xmin = xmin - ydiff;
end
axis([xmin xmax ymin ymax]);
end

% Choose first three colors for head, body, and tail
head1 = line('color','m','marker','o','erase','xor', ...
'xdata',x1(1),'ydata',y1(1));
body1 = line('color','m','linestyle','-','erase','none', ...
'xdata',[],'ydata',[]);
tail1 = line('color','r','linestyle','-','erase','none', ...
'xdata',[],'ydata',[]);
head2 = line('color','k','marker','o','erase','xor', ...
'xdata',x2(1),'ydata',y2(1));
body2 = line('color','k','linestyle','-','erase','none', ...
'xdata',[],'ydata',[]);
tail2 = line('color','b','linestyle','-','erase','none', ...
'xdata',[],'ydata',[]);

m = length(x1);
k = round(p*m);

% Grow the body
for i = 2:k+1
j = i-1:i;
set(head1,'xdata',x1(i),'ydata',y1(i))
set(body1,'xdata',x1(j),'ydata',y1(j))
set(head2,'xdata',x2(i),'ydata',y2(i))
set(body2,'xdata',x2(j),'ydata',y2(j))
drawnow
end

% Primary loop
for i = k+2:m
j = i-1:i;
set(head1,'xdata',x1(i),'ydata',y1(i))
set(body1,'xdata',x1(j),'ydata',y1(j))
set(tail1,'xdata',x1(j-k),'ydata',y1(j-k))
set(head2,'xdata',x2(i),'ydata',y2(i))
set(body2,'xdata',x2(j),'ydata',y2(j))
set(tail2,'xdata',x2(j-k),'ydata',y2(j-k))
drawnow
end

% Clean up the tail
for i = m+1:m+k
j = i-1:i;
set(tail1,'xdata',x1(j-k),'ydata',y1(j-k))
set(tail2,'xdata',x2(j-k),'ydata',y2(j-k))
drawnow
end

%Gallery Menu
case 'Gallery'

%Get handles
Hf=findobj(get(0,'Children'),'Tag','PursuitMainFig');
Hc=get(Hf,'Children');
Hp=findobj(Hc,'flat','Tag','xPursuedEdit');
Hq=findobj(Hc,'flat','Tag','yPursuedEdit');
HtInit=findobj(Hc,'flat','Tag','tInitEdit');
HtFinal=findobj(Hc,'flat','Tag','tFinalEdit');
Hspeed=findobj(Hc,'flat','Tag','RelativeSpeedEdit');
HxInit=findobj(Hc,'flat','Tag','xPursuerInitEdit');
HyInit=findobj(Hc,'flat','Tag','yPursuerInitEdit');
HStep=findobj(Hc,'flat','Tag','StepSizeEdit');

%Set values used to change edit boxes
switch varargin{2}
case 'Astroid'
pstring = 'cos(t)^3';
qstring = 'sin(t)^3';
ti = '0'; tf = '5*pi';
xi = '0'; yi = '0';
case 'Cardioid'
pstring = '2*cos(t)+cos(2*t)';
qstring = '2*sin(t)+sin(2*t)';
ti = '0'; tf = '5*pi';
xi = '.8'; yi = '.9';
case 'Circle'
pstring = 'cos(t)';
qstring = 'sin(t)';
ti = '0'; tf = '5*pi';
xi = '0'; yi = '0';
case 'Freeth'
pstring = 'cos(t)+cos(2*t)+cos(3*t)';
qstring = 'sin(t)+sin(2*t)+sin(3*t)';
ti = '0'; tf = '5*pi';
xi = '0'; yi = '0';
case 'Hypocycloid'
pstring = '(3-2)*cos(t)+cos((3-2)*t/2)';
qstring = '(3-2)*sin(t)-sin((3-2)*t/2)';
ti = '0'; tf = '5*pi';
xi = '0'; yi = '0';
case 'Line'
pstring = '5';
qstring = 't';
ti = '0'; tf = '7';
xi = '0'; yi = '0';
case 'Nephroid'
pstring = '3*cos(t)-cos(3*t)';
qstring = '3*sin(t)-sin(3*t)';
ti = '0'; tf = '5*pi';
xi = '0'; yi = '0';
case 'Warren'
pstring = '3*cos(t)-cos(3*t)';
qstring = '5*sin(t)-sin(7*t)';
ti = '0'; tf = '5*pi';
xi = '0'; yi = '0';
case 'Wierd'
pstring = '7*cos(t)-cos(7*t)';
qstring = '5*sin(5*t)+1';
ti = '0'; tf = '5*pi';
xi = '0'; yi = '0';
otherwise
error('An error has been found in the code!');
end

%Change edit box
set(Hp,'string',pstring);
set(Hq,'string',qstring);
set(HtInit,'string',ti);
set(HtFinal,'string',tf);
set(HxInit,'string',xi);
set(HyInit,'string',yi);



%Case of Incorrect input arguments
otherwise
error('Invalid Argument');
end
thumbnail
About The Author

Ut dignissim aliquet nibh tristique hendrerit. Donec ullamcorper nulla quis metus vulputate id placerat augue eleifend. Aenean venenatis consectetur orci, sit amet ultricies magna sagittis vel. Nulla non diam nisi, ut ultrices massa. Pellentesque sed nisl metus. Praesent a mi vel ante molestie venenatis.

0 comments