function [TE,YE,IE] = learntouseevents(pos1,pos2,distance,speed1,speed2); %learntouseevents(pos1,pos2,distance,speed1,speed2); %This program shows how to use events in ode integrators to keep track of %user-defined significant time-points % %In this example, two cars are RACING and when either crosses the finish %line the odeintegrator ends and the winner is announced % % { pos1 } % ------------------------------------------------------------------------- % >1> X % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -X % >2> X % ------------------------------------------------------------------------- % { pos2 } % { distance } % %EXAMPLE %car1 gets a head start but car2 is faster...for the win! %[TE,YE,IE] = learntouseevents(10,0,100,1,5) % %WARNING: MATLAB's event handling doesn't seem as robust as I'd like it as %I have had program failure when more than one event triggers at a time... %such as when both cars start at the same position and when both cars %finish at the same time %I have heard that this bug has been fixed in some verisons of Matlab tmax = 100000; %maximum integration time x0 = [pos1,pos2]; %initial car positions param.finish = 100; %distance raced to param.v1 = speed1; param.v2 = speed2; options = odeset('Events',@playbyplay); [t,x,TE,YE,IE] = ode45(@speedfunction,[0,tmax],x0,options,param); %[t,x] = ode45(fun,[0,tmax],x0); numberofevents = length(IE); %determine what happened, event information is stored in TE, YE, and IE %TE stores the times events happened %YE stores the function values f at each event %IE stores the index of the event function triggered for(i = 1:numberofevents); switch IE(i); case 1; disp(['The Race is on! at t =',num2str(TE(i))]); disp(['Car1 and Car2 are in positions ',num2str(YE(i,1)),... ' and ',num2str(YE(i,2))]); case 2; disp(['The Race is over at t =',num2str(TE(i))]); disp(['Car1 WINS!!!!!!']); disp(['Car1 and Car2 are in positions ',num2str(YE(i,1)),... ' and ',num2str(YE(i,2))]); case 3; disp(['The Race is over at t =',num2str(TE(i))]); disp(['Car2 WINS!!!!!!']); disp(['Car1 and Car2 are in positions ',num2str(YE(i,1)),... ' and ',num2str(YE(i,2))]); case 4; disp(['Car1 passes Car2 at t =',num2str(TE(i))]); disp(['Car1 and Car2 are in positions ',num2str(YE(i,1)),... ' and ',num2str(YE(i,2))]); case 5; disp(['Car2 passes Car1 at t =',num2str(TE(i))]); disp(['Car1 and Car2 are in positions ',num2str(YE(i,1)),... ' and ',num2str(YE(i,2))]); otherwise; error('illegal case value'); end end plot(x,t); xlabel('position'); ylabel('time'); legend('car1','car2'); return; %in this simple example, the two cars move at constant speeds for all %times (acceleration and time/position dependence could easily be added) function velocities = speedfunction(t,x,param); velocities = [0 0]'; velocities(1) = param.v1; velocities(2) = param.v2; return; function [value,isterminal,direction]=playbyplay(t,x,param); %The events function is triggered whenever a zero is reached %We will have five functions, one for the beginning of the race, %one for car 1, one for car 2, and two for cars passing each other car1position = x(1); car2position = x(2); %these are our four possible events. The last two look the same, but we %will distinguish between them later by looking at the direction zero is %approached from and left from racestarted = t; car1finished = car1position - param.finish; car2finished = car2position - param.finish; car1passedcar2 = car1position - car2position; car2passedcar1 = car1position - car2position; %value is the result returned by the event function, zeros => events value = [racestarted; car1finished; car2finished; car1passedcar2; car2passedcar1;]; %isterminal tells whether a given event causes the integrator to stop % we want to stop when a racer finishes but not when a racer passes isterminal = [ 0; 1; 1; 0; 0;]; %direction acts as a filter to distinguish between some zeros % if direction is zero, we care about all zeros % if +1, we care about cases where the event function increases % if -1, we care about cases where the event function decreases direction = [ 0; 0; 0; 1; -1;]; return;