Курсовая работа_ф_3 / FreematPrimerV4e1
.pdf
Figure 133: General overview of the Tower of Doom ride.
As part of their outing, they collected four sets of data. This data was acceleration data (using accelerometers) in three axes (x, y and z, which I believe corresponds to forward/backward, up/down and left/right), and altitude (height). It's the altitude data that we're going to use for this example.
Here's a short script that will read in the altitude data, plot it and label the important parts of the graph.
% plotToDAltitude.m clear all; close('all')
oldDir=pwd; % Store the current directory so that we can return to it. cd('/home/gary/Freemat/Data'); % Change to the directory holding the data files. data=real(dlmread('todAltitude.txt',char(9))); % Read in the data. accelToD=real(dlmread('todAccelY.txt',char(9))); % Read acceleration data. cd(oldDir); % Now that the data is read in, return to the old directory. t=data(3:length(data),1);
altitude=data(3:length(data),2);
plot(t,altitude);
%sizefig(1200,700);
xDataset;
The Freemat Primer
Page 201 of 218
grid on;
title('Altitude on Tower of Doom Ride','fontsize',16); xlabel('Time (sec)','fontsize',12);
ylabel('Altitude (meters)','fontsize',12); labelSet;
text(18,45,'Seats rising up tower','horizontalalignment','center','rotation',60) text(40,45,'Seats falling down tower','horizontalalignment','center','rotation',- 85)
Running this script, we get this graph.
Figure 134: This is the data from the Tower of Doom ride at Six Flags America in Largo, Maryland (Courtesy of the American Physical Society Public Outreach Program). The lefthand slope is relatively shallow, showing the slow movement up the tower. The slope on the right is steep due to the fact that the altitude changes quickly when the seats are dropped.
We can now use this data to calculate velocity and acceleration. Let's make sure we understand the basics, though. Velocity is the change of distance over time. Acceleration is the change of velocity over time. Putting this into equations, it would appear like this:
v=dydt a= dvdt
If you're not deep into math and these equations cause you to hyperventilate, try looking at them a little differently. The change of position, labeled "dy", is nothing more than the difference between two successive position points. The change in time, "dt", is the difference between two successive time points. Look at Figure 135 which shows this concept graphically.
The Freemat Primer
Page 202 of 218
Figure 135: The velocity of the ride is the change in position over time. All we have to do to calculate this is to calculate the difference in position, then divide that by the difference in time.
We'll create a short script that makes use of the diff function (FD, p. 202) to calculate the difference in successive points of the position. Then we'll divide that by the difference in time samples to calculate
the velocity over time.
% ToDVelocity.m clear all; close('all')
oldDir=pwd; % Store the current directory so that we can return to it. cd('/home/gary/Freemat/Data'); % Change to the directory holding the data files. data=real(dlmread('todAltitude.txt',char(9))); % Read in the data. accelToD=real(dlmread('todAccelY.txt',char(9))); % Read acceleration data. cd(oldDir); % Now that the data is read in, return to the old directory. t=data(3:length(data),1);
altitude=data(3:length(data),2);
% Calculate velocity altDiff=diff(altitude); timeDelta=diff(t); timeDiff=timeDelta(1); dataVel=altDiff/timeDiff;
The Freemat Primer
Page 203 of 218
t2=t(1:length(dataVel));
plot(t2,dataVel);
xDataset; grid on;
title('Vertical Velocity on Tower of Doom Ride','fontsize',16); xlabel('Time (sec)','fontsize',12);
ylabel('Velocity (m/sec)','fontsize',12); labelSet;
This results in the graph shown in .
Figure 136: Calculated velocity on the Six Flags Tower of Doom ride. Note that due to the noise in the measurements, it's very difficult to see subtle changes in the velocity.
Looking at the calculated velocity, there appears to be a lot of noise in the data. We can clean this up
somewhat using a simple moving average. This function is provided below.
% Calculate a simple moving average % moveAve.m
%
% x = the array over which the moving average % will be calculated.
% n = the number of points to calculate the average.
% (the default = 3)
function returnArray=moveAve(x,n);
% Check to see if an array has been provided.
% If not, print an error and quit the function. if(nargin==0);
printf('ERROR: You have to supply an array.'); return
end arraySize=size(x); if(min(arraySize)>1);
printf('ERROR: The provided array is has a minimum\n');
printf('dimension of %d. It requires a one-dimensional vector.\n',min(arraySize)); return
end
% Check to see if an amount of averaging has been
% provided. If not, set a default value. if(nargin==1);
n=3;
The Freemat Primer
Page 204 of 218
end
% If for some reason the average is set to 1,
% just return the original array. if(n==1);
returnArray=x; return
end
% Set the array to determine if it needs to be % flipped.
flipFlag=0;
if(arraySize(1)>arraySize(2))
x=x';
flipFlag=1; end sumX=0;
for(ii=1:n);
sumX=sumX+x; x=circshift(x,[0 -1]); end
if(flipFlag==1)
sumX=sumX'; end
returnArray=(sumX(1:length(x)-n))/n;
Now we'll add this function to our previous script. That script now appears as follows:
% ToDVelocity.m clear all; close('all')
oldDir=pwd; % Store the current directory so that we can return to it. cd('/home/gary/Freemat/Data'); % Change to the directory holding the data files. data=real(dlmread('todAltitude.txt',char(9))); % Read in the data. accelToD=real(dlmread('todAccelY.txt',char(9))); % Read acceleration data. cd(oldDir); % Now that the data is read in, return to the old directory. t=data(3:length(data),1);
altitude=data(3:length(data),2); % Calculate velocity altDiff=diff(altitude); timeDelta=diff(t); timeDiff=timeDelta(1); dataVel=altDiff/timeDiff; velAve=moveAve(dataVel,30); tvA=t(1:length(velAve)); plot(tvA,velAve);
xDataset; grid on;
title('Vertical Velocity on Tower of Doom Ride','fontsize',16); xlabel('Time (sec)','fontsize',12);
ylabel('Velocity (m/sec)','fontsize',12); labelSet;
Here's how the smoothed data appears:
The Freemat Primer
Page 205 of 218
Figure 137: This is the velocity data, but after having been passed through a smoothing function to "clean up" some the noise of the original graph. Note how the ride starts up at about the 10 second mark. Also note how the velocity changes at roughly the 16 second mark, then goes down to a very slow crawl roughly the 23 second mark. Finally, it drops at roughly the 35 second mark.
Next, we'll calculate the numeric differential of the velocity data, which will tell use the acceleration of the ride. We'll expand on our previous script and use another diff command to calculate the
acceleration over time.
% ToDAcceleration.m clear all; close('all')
oldDir=pwd; % Store the current directory so that we can return to it. cd('/home/gary/Freemat/Data'); % Change to the directory holding the data files. data=real(dlmread('todAltitude.txt',char(9))); % Read in the data. accelToD=real(dlmread('todAccelY.txt',char(9))); % Read acceleration data. cd(oldDir); % Now that the data is read in, return to the old directory. t=data(3:length(data),1);
altitude=data(3:length(data),2);
altAve=moveAve(altitude,20); % Calculate the velocity. altDiff=diff(altAve); timeDelta=diff(t); timeDiff=timeDelta(1); dataVel=altDiff/timeDiff; t2=t(1:length(dataVel)); velAve=moveAve(dataVel,20); tvA=t(1:length(velAve));
% Calculate acceleration velDiff=diff(velAve); dataAccel=velDiff/timeDiff/1; aveAccel=moveAve(dataAccel,10); t3=t(1:length(aveAccel));
The Freemat Primer
Page 206 of 218
plot(t3,aveAccel,'linewidth',2);
xDataset; grid on;
title('Vertical Acceleration on Tower of Doom Ride','fontsize',16); xlabel('Time (sec)','fontsize',12);
ylabel('Acceleration (m/s/s)','fontsize',12); labelSet;
This results in the acceleration graph shown below.
Figure 138: This shows the calculated acceleration of the Tower of Doom ride. Note that the data has been smoothed using a simple moving average.
Since another one of the data sets is the y-axis (up/down) acceleration (using accelerometers), we can
plot these two data sets together to see how well they match. We showed this data set in Figure 90.
% ToDAcceleration.m clear all; close('all')
data=real(dlmread('todAltitude.txt',char(9))); % Read in the data. t=data(3:length(data),1);
altitude=data(3:length(data),2);
altAve=moveAve(altitude,20); % Calculate the velocity. altDiff=diff(altAve); timeDelta=diff(t); timeDiff=timeDelta(1); dataVel=altDiff/timeDiff; t2=t(1:length(dataVel)); velAve=moveAve(dataVel,20); tvA=t(1:length(velAve));
% Calculate acceleration velDiff=diff(velAve); dataAccel=velDiff/timeDiff/1; aveAccel=moveAve(dataAccel,10); t3=t(1:length(aveAccel));
The Freemat Primer
Page 207 of 218
plot(t3,aveAccel,'linewidth',2);
xDataset; grid on;
title('Vertical Acceleration on Tower of Doom Ride','fontsize',16); xlabel('Time (sec)','fontsize',12);
ylabel('Acceleration (m/s/s)','fontsize',12); labelSet;
% Plot y-axis accelerometer data accelToD=real(dlmread('todAccelY.txt',char(9))); % Read acceleration data. ta=accelToD(3:length(accelToD),1);
accel=accelToD(3:length(accelToD),2)-9.80655; % Normalize the acceleration to zero. accelAve=moveAve(accel,10); % Smooth out the accelerometer data. accelAve=circshift(accelAve,[-18 0]); % Shift the data sets so that they line up in time.
taAve=ta(1:length(accelAve));
line(taAve,accelAve,zeros(1,length(taAve)),'color','r','linewidth',2); legend('Differentiation of Altitude Data','Accelerometer Data','location','northwest')
The result is shown in Figure 139.
Figure 139: This is the y-axis accelerometer data plotted over the calculated acceleration data. Note the excellent match between the two, with the exception of the sharp drop near the 37 second mark). This difference probably has to do with the smoothing used on the altitude and velocity data.
Note that, with the exception of the acceleration when the chairs are dropped, the two data sets match pretty well. While I don't know for certain, I believe that the reason for the difference is due to the moving average filter applied to the data sets.
The Freemat Primer
Page 208 of 218
Topic 9.3.2.3: Finding the Maxima and Minima
A maxima or a minima is a point on a graph where the slope goes to zero. A maxima or minima is where the slope (the first derivate) goes to zero. This is shown in Figure 140.
Figure 140: Overview of maxima and minima.
That means that if we plot the first differential, any points where this plot goes through zero will be points at which the original graph has a maxima or minima. This is shown below.
Figure 141: This shows how an original graph compares with a differential graph.
We can find the actual zero-crossing points using numerical differentiation. To do that, we can use the
diff command (FD, p. ). Here's a short bit of code to provide an example. x=linspace(-2,3,1000); % Create the x-axis range. y=x.*cos(x.^2); % Create the points of the graph. plot(x,y,'linewidth',2); % Plot the original function graph yLimits=get(gca,'ylim'); % Save the y-axis limits for later.
dx=x(1:end-1); % Create an x-axis range for the differential graph. diffX=x(2)-x(1); % Create the differential graph. dy=diff(y)/diffX; % Calculate the slope of the differential graph. % The next line plots the differential graph. line(dx,dy,zeros(1,length(dx)),'linewidth',2,'color','r');
% Create and plot the zero line.
The Freemat Primer
Page 209 of 218
line([-2 3],[0 0],[0 0],'linewidth',2,'color','k','linestyle','--'); ylim(yLimits); % Reset the y-axis limits to the original levels. legend('Original graph','Differential graph','location','southwest');
Here's the result of running this script.
Figure 142: This shows a graph comparing the original graph (in blue) with the differential graph (the green, dotted line). Note that the maxima and minima of the original graph occur at the same points as when the differential graph passes through zero. These zero-crossing ponts of the differential are marked with a red "X". Also note that a negative slope on the differential graph means a maxima on the original graph; a positive slope means a minima.
We can use this differential graph along with the circshift function (FD, p. 269) to get a better idea of
where the differential graph passes through zero.
% Script to demonstrate how to calculate where zero crossings occur.
% zeroCross.m
f=@(x) (x.*cos(x.^2)); % Equation to graph x=linspace(-2,3,1024);
y=f(x); % graph of original equation dx=x(1:end-1);
diffX=x(2)-x(1); dy=diff(y)/diffX;
ys=circshift(dy,[0,-1]); % this creates the shifted version of the % original graph. The shifted version will % be shifted to the left (-1) compared to
% the original.
yz=(dy.*ys)<0; % This looks for only points that are negative (less
% than zero). plot(x,y,'linewidth',2);
% plot zero crossings in red line(dx,yz,zeros(1,length(dx)),'color','r'); legend('Original Graph','Maxima / Minima Points','location',
'southwest');
This results in the figure shown in Figure 143.
The Freemat Primer
Page 210 of 218
