Difference between revisions of "VPOD 3DOF Vibratory Device"
(New page: ''Last modified 10 June, 2009'' __TOC__ =Calibrating the High Speed Camera= thumb|200px|'''Figure 1:''' Calibration grid with distortion.|right Bef...) |
|||
(50 intermediate revisions by one other user not shown) | |||
Line 1: | Line 1: | ||
''Last modified 10 June, 2009'' |
|||
__TOC__ |
__TOC__ |
||
=Nondimensional 3DOF Bouncing Ball Simulator= |
|||
=Calibrating the High Speed Camera= |
|||
==Introduction== |
|||
[[image:Distorted_calibration_grid.jpg|thumb|200px|'''Figure 1:''' Calibration grid with distortion.|right]] |
|||
The Nondimensional 3DOF Bouncing Ball Simulator is a simple Matlab program meant to mimic the behavior of a bouncing ball on a vibratory device capable of sinusoidal motion in three degrees, such as the VPOD. The simulator uses a numerical method in which the equations of motion describing the ball's flight are determined from the state variables of the previous impact. The program uses a binary search to locate the time at which the ball's position in the x,z plane is equal to that of the oscillating bar. In short, it calculates the intersection of a parabola with a sinusoid, uses a simple impact model to compute the new state variables, and repeats this computation as many times as desired. |
|||
Before data can be collected from the HSV system, it is critical that the high speed camera be properly calibrated. In order to obtain accurate data, there is a series of intrinsic and extrinsic parameters that need to be taken into account. Intrinsic parameters include image distortion due to the camera itself, as shown in Figure 1. Extrinsic parameters account for any factors that are external to the camera. These include the orientation of the camera relative to the calibration grid as well as any scalar and translational factors. |
|||
The equations of motion for the oscillating bar are as follows: |
|||
: <math> x(t) = A_x \sin(\omega_xt+\phi_x)\, </math> |
|||
: <math> z(t) = A_z \sin(\omega_zt+\phi_z)\, </math> |
|||
: <math> \theta(t) = A_\theta \sin(\omega_\theta t+\phi_\theta)\, </math> |
|||
where A_x, A_z, A_theta represent the maximum x, z, and angular displacements of the bar's motion. The key input variables are the three position amplitudes, three frequencies, and three phase angles, as well as coefficients of restitution in the normal and tangential directions. |
|||
==Quick Start== |
|||
In order to calibrate the camera, download the [http://www.vision.caltech.edu/bouguetj/calib_doc/ Camera Calibration Toolbox for Matlab]. This resource includes detailed descriptions of how to use the various features of the toolbox as well as descriptions of the calibration parameters. |
|||
In order to run the simulator, first download the Matlab files by clicking on the link below: |
|||
==For Tracking Objects in 2D== |
|||
To calibrate the camera to track objects in a plane, first create a calibration grid. The Calibration Toolbox includes a calibration template of black and white squares of side length = 3cm. Print it off and mount it on a sheet of aluminum or PVC to create a stiff backing. This grid must be as flat and uniform as possible in order to obtain an accurate calibration. |
|||
[[Media:Bouncing Ball Simulator.zip|Download the simulator.]] |
|||
===Intrinsic Parameters=== |
|||
Following the model of the [http://www.vision.caltech.edu/bouguetj/calib_doc/ first calibration example] on the Calibration Toolbox website, use the high speed camera to capture 10-20 images, holding the calibration grid at various orientations relative to the camera. 1024x1024 images can be obtained using the "Moments" program. The source code can be checked out [http://code.google.com/p/lims-hsv-system/ here]. |
|||
===Description of Functions=== |
|||
[[image:Undistorted_calibration_grid.jpg|thumb|200px|'''Figure 2:''' Calibration grid undistorted.|right]] |
|||
The zipped folder contains 6 m-files: |
|||
Calibration Tips: |
|||
*bBallSim - This is the main m-file and likely the only one you will have to worry about. It contains a big for loop which takes the initial conditions for the ball's flight and calculates one bar impact, storing the data in the matrix 'P'. The post-impact conditions then become the new initial conditions. It loops as many times as indicated. |
|||
* One of the images must have the calibration grid in the tracking plane. This image is necessary for calculating the extrinsic parameters and will also be used for defining your origin. |
|||
*binSrch - Uses a binary search method to locate the time where in ball intersects the bar, based off of the initial flight conditions and parameters. It returns the time of intersection (denoted 't2'). |
|||
* The images must be saved in the same directory as the Calibration Toolbox. |
|||
*checkLocking - Determines whether or not the ball is locking. Locking is a phenomenon in which the ball's velocity decays to zero, undergoing an infinite number of bounces in the absorbing region of the bar's motion. If the flight time is less than an arbitrarily small value, the ball is determined to be locking, and a value of 1 is returned. |
|||
* Images must be saved under the same name, followed by the image number. (image1.jpg, image2.jpg...) |
|||
*impact - This function takes the initial conditions and time of impact as inputs. It uses a simple impact model to calculate the post-impact positions and velocities of the ball. |
|||
* The first calibration example on the Calibration Toolbox website uses 20 images to calibrate the camera. I have been using 12-15 images because sometimes the program is incapable of optimizing the calibration parameters if there are too many constraints. |
|||
*calculateLaunch - Determines whether or not the ball will be relaunched after locking. If the motion of the bar, and the position of the ball are such that the vertical acceleration of the bar will exceed gravity at some point during its periodic motion, then the ball will be relaunched. Otherwise, the ball will never be relaunched, and the simulation will terminate. |
|||
*plotTraj - This function is used only to plot the trajectories of the ball and the bar. This is only used as a visual aid and is helpful for debugging. It can easily be turned off to speed up the simulation. |
|||
===Explanation of Important Inputs & Parameters=== |
|||
The Calibration Toolbox can also be use to compute the undistorted images as shown in Figure 2. |
|||
First, open the bBallSim m-file. The first few lines will look like this: |
|||
<nowiki>function [P, N] = bBallSim(A_x, A_z, A_th, p) |
|||
After entering all the calibration images, the Calibration Toolbox will calculate the intrinsic parameters, including focal length, principal point, and undistortion coefficients. There is a complete description of the calibration parameters [http://www.vision.caltech.edu/bouguetj/calib_doc/htmls/parameters.html here]. |
|||
% SYSTEM PARAMETERS |
|||
===Extrinsic Parameters=== |
|||
num_impacts = 500; % Number of impacts simulator will calculate before terminating |
|||
In addition, the Toolbox will calculate rotation matrices for each image (saved as Rc_1, Rc_2...). These matrices reflect the orientation of the camera relative to the calibration grid for each image. |
|||
[[image:2D_imaging.jpg|thumb|500px|'''Figure 3:''' Projection of calibration grid onto the image plane.|center]] |
|||
A = [A_x; A_z; A_th]; % Position amplitude of bar, nondimensional [A_x, A_z, A_th] |
|||
Figure 3 is an illustration of the [http://en.wikipedia.org/wiki/Pinhole_camera_model pinhole camera model] that is used for camera calibration. Since the coordinates of an object captured by the camera are reported in terms of pixels (camera frame), these data have to be converted to metric units (world frame). |
|||
phi = [pi/2; pi/2; p]; % Phase angle of bar [phi_x, phi_z, phi_th] |
|||
f = [1; 2; 1]; % Frequencies of bar motions [f_x, f_z, f_th] |
|||
w = 2*pi.*f; % [w_x, w_z, w_th] |
|||
</nowiki> |
|||
There are four important inputs for this version of the program. |
|||
In order to solve for the extrinsic parameters, first use the 'normalize' function provided by the calibration toolbox: |
|||
*A_x is the nondimensionalized position amplitude of the bar in the x (horizontal) direction. |
|||
[xn] = normalize(x_1, fc, cc, kc, alpha_c); |
|||
*A_z is the nondimensionalized position amplitude of the bar in the z (vertical) direction. |
|||
where x_1 is a matrix containing the coordinates of the extracted grid corners in pixels for image1. |
|||
*A_th is the amplitude in the theta direction (angular about the y). It is already dimensionless. |
|||
The normalize function will apply any intrinsic parameters and return the (x,y) point coordinates free of lens distortion. These points will be dimensionless as they will all be divided by the focal length of the camera. Next, change the [2xn] matrix of points in (x,y) to a [3xn] matrix of points in (x,y,z) by adding a row of all ones. |
|||
*p is the relative phase between the theta motion and the other motions. |
|||
xn should now look something like this: |
|||
Nondimensionalizations are as follows: |
|||
<math>\mathbf{xn} = \begin{bmatrix} |
|||
Position: <math> p' = p*(f(1)^2/g)\, </math> where f(1) is equal to the first frequency in the vector f (or the horizontal frequency) and g is equal to the acceleration due to gravity |
|||
x_c1/z_c & x_c2/z_c &... & x_cn/z_c \\ |
|||
y_c1/z_c & y_c2/z_c &... & y_cn/z_c \\ |
|||
z_c/z_c & z_c/z_c &... & z_c/z_c \end{bmatrix}</math> |
|||
Where x_c, y_c, z_c, denote coordinates in the camera frame. z_c = focal length of the camera as calculated by the Calibration Toolbox. |
|||
Velocity: <math> v' = v*(f(1)/g)\, </math> |
|||
Then, apply the rotation matrix, Rc_1: |
|||
[xn] = Rc_1*x_n; |
|||
We now have a matrix of dimensionless coordinates describing the location of the grid corners after accounting for distortion and camera orientation. What remains is to apply scalar and translational factors to convert these coordinates to the world frame. To do so, we have the following equations: |
|||
: <math>X_1(1,1) = S1*xn(1,1) + T1 \, </math> |
|||
: <math>X_1(2,1) = S2*xn(2,1) + T2 \, </math> |
|||
Where: |
|||
: <math>S = (focallength)*(numberofmillimeters/pixel) \, </math> |
|||
X_1 is the matrix containing the real world coordinates of the grid corners and is provided by the Calibration Toolbox. |
|||
Cast these equations into a matrix equation of the form: |
|||
: <math>Ax = b \, </math> |
|||
Where: |
|||
Acceleration: <math> a' = a/g\, </math> |
|||
<math>\mathbf{A} = \begin{bmatrix} |
|||
xn(1,1) & 1 & 0 & 0 \\ |
|||
0 & 0 & xn(2,1) & 1 \\ |
|||
xn(1,2) & 1 & 0 & 0 \\ |
|||
0 & 0 & xn(2,2) & 1 \\ |
|||
. & . & . & . \\ |
|||
. & . & . & . \\ |
|||
. & . & . & . \\ |
|||
xn(1,n) & 1 & 0 & 0 \\ |
|||
0 & 0 & xn(2,n) & 1 \end{bmatrix}</math> |
|||
<math>\mathbf{x} = \begin{bmatrix} |
|||
S_1\\ |
|||
T_1\\ |
|||
S_2\\ |
|||
T_2\end{bmatrix}</math> |
|||
<math>\mathbf{b} = \begin{bmatrix} |
|||
X_1(1,1)\\ |
|||
X_1(2,1)\\ |
|||
X_1(1,2)\\ |
|||
X_1(2,2)\\ |
|||
.\\ |
|||
.\\ |
|||
.\\ |
|||
X_1(2,n)\\ |
|||
X_1(2,n)\end{bmatrix}</math> |
|||
===Simple Test=== |
|||
Finally, use the Matlab backslash command to compute the least squares approximation for the parameters S1, S2, T1, T1: |
|||
For example, if one were to input the following: |
|||
x = A\b |
|||
[P, N] = bBallSim(0, 0.0052, 0, 0); |
|||
Now that all the parameters have been calculated, percentage error can be calculated, by applying the entire transformation process to the x_1 matrix and comparing the results to the X_1 matrix. If carefully executed, this calibration method can yield percent errors as low as 0.01%. |
|||
This is setting a motion with zero amplitude in the x and theta directions. 0.0052 is the nondimensional equivalent of 8m/s^2 in the z direction. If this simulation is run for 100 impacts with e = [0.8 0.8], the following plot will be created: |
|||
==For Tracking Objects in 3D== |
|||
In order to obtain the coordinates of an object in three dimensions, a mirror can be used in order to create a "virtual camera," as shown in Figure 4. |
|||
[[image:3D_imaging.jpg|thumb|600px|'''Figure 4:''' Three dimensional imaging with mirror at 45 degrees.|center]] |
|||
Calibrating the camera to work in three dimensions is very similar to the two dimensional calibration. The main difference is the calibration grid itself. Instead of using a single flat plane for the calibration grid, an additional grid has to be constructed, consisting of two planes at 90 degrees as shown in the figure. This grid must be visible by both the "real" and "virtual" cameras. The purpose of this is to create a common origin. Having a common origin for both cameras will become critical in calculating an object's position in three dimensions. |
|||
[[image:VPODSimulatorSimpleTest.jpg|800px|center]] |
|||
Follow the steps for the 2D calibration and complete a separate calibration for each camera. The two sets of intrinsic parameters that are obtained should be identical in theory. In practice, they are likely to differ slightly. |
|||
=399 Write-up and Raw Data= |
|||
Once the real world coordinates of an object in the XZ and YZ planes are obtained, the 3D position of the object still has to be obtained. The raw data is inaccurate because it represents the projection of the object's position onto the calibration plane. For the methodology and code required to execute these calculations, refer to the section entitled "Calculating the Position of an Object in 3D." |
|||
The following is a 399 Write-up from a 2009-2010 independent study conducted by Undergraduate Eric Bell. The paper uses data from both physical experimentation as well as the simulator described above. |
|||
[[Media:EBell-399FinalWriteup.pdf|EBell-399FinalWriteup]] |
|||
The write-up is also available as a word document [[Media:EBell-399FinalWriteup.doc|EBell-399FinalWriteup Microsoft Word version]] |
|||
=Using the High Speed Vision System= |
|||
[[image:VPOD_Setup.jpg|thumb|300px|'''Figure 5:''' VPOD with high speed vision 3D setup.|right]] |
|||
Figure 5 shows the current setup for the high speed vision system. The high speed camera is mounted on a tripod. The three lights surrounding the setup are necessary due to the high frequency with which the images are taken. The resulting camera shutter time is very small, so it is important to provide lots of light. The high frequency performance also has to be taken into consideration when processing the images. Processing one thousand 1024x1024 pixel images in real time proves impossible as well as unnecessary. The accompanying C program works by selection one or several regions of interest to focus on. The program applies a threshold to these regions. It then calculates an area centroid based off of the number of white pixels and re-centers the region of interest by locating the boundaries between the white and black pixels. The complete code for this program can be found [http://code.google.com/p/lims-hsv-system/ here]. |
|||
Some of the data used in the write-up are included below: |
|||
I will include a brief description of some of the important constants, which can be found in the header file 'constants.h' |
|||
The following contains both the raw data from the real and virtual cameras as well as the calculated a workspace containing the calculated 3D coordinates. This data was used to create Figures 2.3 through 2.5: |
|||
EXPOSURE & FRAME_TIME: These parameters control number of images to be taken in one second, and are measured in microseconds. Frame time is the amount of time required to take on image. Exposure time is the amount of time the camera shutter is open, and should always be less than the frame time. A ratio of 5:2, FRAME:EXPOSURE seems to work well. To run the camera at 1000images/s for example, EXPOSURE and FRAME_TIME should be set to 400 and 1000, respectively. |
|||
[[Media:EBell-Fig2.3-2.5.zip|Figure2.3-2.5 Data]] |
|||
The zipped folder also contains the Matlab Figure files corresponding to the plots used in the paper. |
|||
The following contains the Matlab workspaces used to create Figures 3.1-3.5. The period 1 and period 2 examples were captured using 2D imaging, whereas the period 3 example uses 3D. Figure files are also included. |
|||
SEQ & SEQ_LEN: For multiple regions of interest, the sequence describes the order in which the regions of interest are addressed. The current setup has the program cycling through the regions in order, so for 1000Hz with two regions, each region would have a frequency for 500images/s, and the camera would alternate between the two regions. For such a setup, SEQ would be set to {ROI_0, ROI_1} and SEQ_LEN set to 2. |
|||
[[Media:EBell-P123v2.zip|Figures3.1-3.5 Data]] |
|||
The following is experimental data used to create the bifurcation diagrams shown in Figure 3.8 and 3.10. This data was also used for the examples of period 1 and period 2 m=2 behavior corresponding to Figures 3.6 and 3.7 in the write-up: |
|||
INITIAL_BLOB_XMIN, INITIAL_BLOB_YMIN, INITIAL_BLOB_WIDTH, INITIAL_BLOB_HEIGHT: These parameters describe the initial position and size of the blob surrounding your object of interest. These should be set such that the blob surrounds the initial position of the object. |
|||
[[Media:EBell-Bifurcationsv3.zip|Data for Bifurcation Diagrams]] |
|||
This data was collected using 3 regions of interest (XZ- raw data from real camera, YZ- raw data from "virtual" camera, bar_tracking- raw data for bar's motion using real camera). This workspace also contains the calculated 3D coordinates of the ball (XYZ_BALL) as well as the adjusted coordinates of the bar (XZ_BAR). The Matlab function used to calculate these coordinates is pasted below. |
|||
The data for the experiment shown in Figure 3.12 can be downloaded here along with the plot. |
|||
THRESHOLD: The threshold is the value (0-255) which is the cutoff value for the black/white boundary. The threshold will have to be adjusted depending on ambient light and the exposure time. It should be set such that the object of interest or fiduciary marker is in the white realm while everything in the background becomes black. |
|||
[[Media:EBell-Fig3.12.zip|Data for Figure 3.12]] |
|||
In the workspace, the variable referred to as tau in the plot is saved as "ndPhase." |
|||
Other figures included in the paper: |
|||
DISPLAY_TRACKING: This quantity should always be set to one or zero. When equal to one, it displays the region or regions of interest. This is convenient for setting the threshold and positioning the blobs. While taking data, however, this should be disabled in order to speed up the program. |
|||
[[Media:EBell-MiscFigures.zip|Miscellaneous Figures]] |
|||
DTIME: This value is the number of seconds of desired data collection. In order to collect data, run the program, wait for it to initialize, and then press 'd'. 'q' can be pressed at any time to exit the program. |
|||
=Post-Processing of Data= |
|||
==Calculating the Position of an Object in 3D== |
|||
By comparing the data captured by the "real" camera and the "virtual" camera, it is possible to triangulate the three dimensional position of an object. The calibration procedures discussed earlier provide the real world (x,y) coordinates of any object, projected onto the calibration plane. By determining the fixed location of the two cameras, it is possible to calculate two position vectors and then compute a least squares approximation for their intersection. |
|||
The Calibration Toolbox provides the principal point for each camera measured in pixels. The principal point is defined as the (x,y) position where the principal ray (or optical ray) intersects the image plane. This location is marked by a blue dot in Figure 4. The principal point can be converted to metric by applying the intrinsic and extrinsic parameters discussed in the section "Calibrating the High Speed Camera." |
|||
From here, the distance from the cameras to the origin can be determined from the relationship: |
|||
: <math>distance = (focallength)*(numberofmillimeters/pixel) \, </math> |
|||
Once this distance is calculated, the parallel equations can be obtained for a line in 3D with 2 known points: |
|||
: <math>(x-x_1)/(x_2-x_1)=(y-y_1)/(y_2-y_1)=(z-z_1)/(z_2-z_1) \, </math> |
|||
Which can be rearranged in order to obtain 3 relationships: |
|||
: <math>x*(y_2-y_1)+y*(x_1-x_2) = x_1*(y_2-y_1) + y_1*(x_1-x_2) \, </math> |
|||
: <math>x*(z_2-z_1)+z*(x_1-x_2) = x_1*(z_2-z_1) + z_1*(x_1-x_2) \, </math> |
|||
: <math>y*(z_2-z_1)+z*(y_1-y_2) = y_1*(z_2-z_1) + y_1*(y_1-y_2) \, </math> |
|||
These equations can be cast into matrix form: |
|||
<math>\mathbf{A} = \begin{bmatrix} |
|||
y_2-y_1 & x_1-x_2 & 0 \\ |
|||
z_2-z_1 & 0 & x_1-x_2 \\ |
|||
0 & z_2-z_1 & y_1-y_2 \end{bmatrix}</math> |
|||
<math>\mathbf{x} = \begin{bmatrix} |
|||
x\\ |
|||
y\\ |
|||
z\end{bmatrix}</math> |
|||
<math>\mathbf{b} = \begin{bmatrix} |
|||
x_1*(y_2-y_1) + y_1*(x_1-x_2)\\ |
|||
x_1*(z_2-z_1) + z_1*(x_1-x_2)\\ |
|||
y_1*(z_2-z_1) + y_1*(y_1-y_2)\end{bmatrix}</math> |
|||
There should be one set of equations for each vector, for a total of six equations. A should be a [6x3] matrix, and b should be a vector of length 6. Computing A\b in Matlab will yield the least squares approximation for the intersection of the two vectors. |
|||
<nowiki>% The function "calc_coords" takes as inputs, the raw data for vision in |
<nowiki>% The function "calc_coords" takes as inputs, the raw data for vision in |
||
Line 155: | Line 98: | ||
% Calibration Toolbox and should be left in pixels. |
% Calibration Toolbox and should be left in pixels. |
||
% The function returns a matrix of size [ |
% The function returns a matrix of size [nx5] containing the least squares |
||
% approximation of the (x,y,z) coordinates based off of the vectors from |
% approximation of the (x,y,z) coordinates based off of the vectors from |
||
% the two cameras |
% the two cameras, as well as the index and time at which these coordinates |
||
% occur. |
|||
% NOTES: |
% NOTES: |
||
Line 164: | Line 108: | ||
% - The YZ vision plane = "Virtual Camera" |
% - The YZ vision plane = "Virtual Camera" |
||
function |
function [XYZ_BALL, XZ_BAR] = calc_coords3ROI(XZ, YZ, bar_tracking); |
||
% Should be most recent calibration |
|||
w = cd; |
|||
calib = '8-17-09 Calibration Constants'; |
|||
cd('C:\Documents and Settings\John Shih\Desktop\VPOD- EBell\Calibration Constants\'); |
|||
load(calib); |
|||
% Change directory to regular working directory |
|||
cd(w); |
|||
matSize_xz = size(XZ); |
matSize_xz = size(XZ); |
||
num_datapoints_xz = matSize_xz(1,1); |
num_datapoints_xz = matSize_xz(1,1); |
||
Line 170: | Line 121: | ||
num_datapoints_yz = matSize_yz(1,1); |
num_datapoints_yz = matSize_yz(1,1); |
||
num_datapoints = min(num_datapoints_xz, num_datapoints_yz); |
num_datapoints = min(num_datapoints_xz, num_datapoints_yz); |
||
XYZ_BALL = zeros(num_datapoints-1, 5); % Initialize destination matrix |
|||
conv_xz = |
conv_xz = [FC_xz(1,1) + FC_xz(2,1)] / [CONSTANTS_xz(1,1) + CONSTANTS_xz(3,1)]; % Conversion factor (number of pixels / mm) for vision in XZ |
||
conv_yz = 3 |
conv_yz = [FC_yz(1,1) + FC_yz(2,1)] / [CONSTANTS_yz(1,1) + CONSTANTS_yz(3,1)];; % Conversion factor (number of pixels / mm) for vision in YZ |
||
dist_origin_xz = [(FC_xz(1,1) + FC_xz(2,1)) / 2] / [conv_xz]; % Taking an average of the two focal lengths, |
dist_origin_xz = [(FC_xz(1,1) + FC_xz(2,1)) / 2] / [conv_xz]; % Taking an average of the two focal lengths, |
||
dist_origin_yz = [(FC_yz(1,1) + FC_yz(2,1)) / 2] / [conv_yz]; % Multiplying by conversion factor to get |
dist_origin_yz = [(FC_yz(1,1) + FC_yz(2,1)) / 2] / [conv_yz]; % Multiplying by conversion factor to get |
||
Line 180: | Line 131: | ||
for i = [1 : 1 : num_datapoints - 1] |
for i = [1 : 1 : num_datapoints - 1] |
||
planeP_xz = [XZ(i,3); 0; XZ(i,4)]; % [3x1] vector containing the points in the plane of the calibration grid |
planeP_xz = [XZ(i,3); 0; XZ(i,4)]; % [3x1] vector containing the points in the plane of the calibration grid |
||
planeP_yz = [0; -(YZ(i+1,3) |
planeP_yz = [0; -(YZ(i,3)+(2/3)*[YZ(i+1,3) - YZ(i,3)]); (YZ(i,4)+(2/3)*[YZ(i+1,4) - YZ(i,4)])]; |
||
x1_xz = prinP_xz(1,1); |
x1_xz = prinP_xz(1,1); |
||
y1_xz = prinP_xz(2,1); |
y1_xz = prinP_xz(2,1); |
||
Line 209: | Line 160: | ||
b = [b_xz; b_yz]; |
b = [b_xz; b_yz]; |
||
c = A\b; % Solve for 3D coordinates |
c = A\b; % Solve for 3D coordinates |
||
XYZ_BALL(i, 1) = i; |
|||
XYZ_BALL(i, 2) = XZ(i,2); |
|||
XYZ_BALL(i, 3) = c(1,1); |
|||
XYZ_BALL(i, 4) = c(2,1); |
|||
XYZ_BALL(i, 5) = c(3,1); |
|||
end |
end |
||
num_datapoints_bar = size(bar_tracking, 1); |
|||
offset = 38.5; % Distance from the calibration plane to the plane, coinciding with the front face of the bar (in mm)% the distance to the calibration grid in metric. |
|||
XZ_BAR = zeros(num_datapoints_bar, 4); |
|||
for i = [1 : 1 : num_datapoints_bar] |
|||
XZ_BAR(i,1) = bar_tracking(i,1); |
|||
XZ_BAR(i,2) = bar_tracking(i,2); |
|||
XZ_BAR(i,3) = bar_tracking(i,3)*(dist_origin_xz - offset) / dist_origin_xz; |
|||
XZ_BAR(i,4) = bar_tracking(i,4)*(dist_origin_xz - offset) / dist_origin_xz; |
|||
end |
|||
%plot(XYZ_BALL(:,2)/(10^6), XYZ_BALL(:,5)-BALL0, XZ_BAR(:,2)/(10^6), XZ_BAR(:,4)-BAR0) |
|||
</nowiki> |
</nowiki> |
||
==Finding Maxes and Mins, Polyfits== |
|||
The following Matlab function was used to calculate the minima of a set of data: |
|||
% Function locates the minima of a function, based on the 3 previous and |
|||
% 3 future points. |
|||
% Function takes one input, an [nx4] matrix where: |
|||
% ydisp(1,:) = image number from which data was taken. |
|||
% ydisp(2,:) = time at which data was taken. |
|||
% ydisp(3,:) = x or y position of object. |
|||
% ydisp(4,:) = z position (height of object). |
|||
% The function returns a matrix of size [nx3] containing the image number, |
|||
% time, and value of each local minimum. |
|||
function Mins = calc_minima(ydisp); |
|||
Mins = zeros(10, 3); |
|||
mat_size = size(ydisp); |
|||
num_points = mat_size(1,1); |
|||
local_min = ydisp(1, 4); |
|||
time = ydisp(1, 1); |
|||
location = 1; |
|||
index = 1; |
|||
min_found = 0; |
|||
for i = [4 : 1 : num_points - 3] |
|||
% execute if three previous points are greater in value |
|||
if ( ydisp(i, 4) < ydisp(i - 1, 4) && ydisp(i, 4) < ydisp(i - 2, 4) && ydisp(i, 4) < ydisp(i - 3, 4)) |
|||
local_min = ydisp(i, 4); |
|||
time = ydisp(i, 1); |
|||
location = i; |
|||
% if next three points are also greater in value, must be a min |
|||
if ( ydisp(i, 4) < ydisp(i + 1, 4) && ydisp(i, 4) < ydisp(i + 2, 4) && ydisp(i, 4) < ydisp(i + 3, 4)) |
|||
min_found = 1; |
|||
end |
|||
end |
|||
if (min_found) |
|||
Mins(index, 1) = location; |
|||
Mins(index, 2) = time; |
|||
Mins(index, 3) = local_min; |
|||
index = index + 1; |
|||
min_found = 0; |
|||
end |
|||
end |
|||
Once the minima were located, the following was used to compute a second order polyfit between two consecutive minima: |
|||
% plot_polyfit calls on the function calc_minima to locate the local mins |
|||
% of the data, and then calculates a parabolic fit in between each of two |
|||
% consecutive minima. |
|||
% It takes in raw_data in the form of an [nx4] matrix and returns |
|||
% a matrix containing the fitted data, the matrix of calculated minima, and |
|||
% the matrix of calculated maxima. |
|||
function [fittedData, Maxima, Mins] = plot_polyfit(raw_data); |
|||
num_poly = 2; |
|||
timestep = 1000; |
|||
fittedData = zeros(100,3); |
|||
Mins = calc_minima(raw_data); % Calculate minima |
|||
Maxima = zeros(10,2); |
|||
mat_size = size(Mins); |
|||
num_mins = mat_size(1,1); |
|||
index = 1; |
|||
max_index = 1; |
|||
% For each min, up until the second to last min, execute the following... |
|||
for i = [1 : 1 : num_mins - 1] |
|||
% Calculate coefficients, scaling, and translational factors for polyfit |
|||
[p,S,mu] = polyfit(raw_data(Mins(i, 1) : Mins(i+1, 1), 2), raw_data(Mins(i, 1) : Mins(i+1, 1), 4), num_poly); |
|||
start = index; |
|||
% Given the parameters for the polyfit, compute the values of the |
|||
% function for (time at first min) -> (time at second min) |
|||
for time = [raw_data(Mins(i, 1), 2) : timestep : raw_data(Mins(i + 1, 1), 2)] |
|||
fittedData(index, 1) = time; |
|||
x = [time - mu(1,1)] / mu(2,1); |
|||
y = 0; |
|||
v = 0; |
|||
% For each term in the polynomial |
|||
for poly = [1 : 1 : num_poly + 1] |
|||
y = y + [ p(1, num_poly - poly + 2) ]*x^(poly-1); |
|||
v = v + (poly-1)*[ p(1, num_poly - poly + 2) ]*x^(poly-2); |
|||
end |
|||
fittedData(index, 2) = y; |
|||
fittedData(index, 3) = v; |
|||
index = index + 1; |
|||
end |
|||
t = -p(1,2)/(2*p(1,1)); |
|||
x = [t * mu(2,1)] + mu(1,1); |
|||
local_max = 0; |
|||
for poly = [1 : 1 : num_poly + 1] |
|||
local_max = local_max + [ p(1, num_poly - poly + 2) ]*t^(poly-1); |
|||
end |
|||
Maxima(max_index, 1) = x; |
|||
Maxima(max_index, 2) = local_max; |
|||
max_index = max_index + 1; |
|||
end |
Latest revision as of 17:19, 7 June 2010
Nondimensional 3DOF Bouncing Ball Simulator
Introduction
The Nondimensional 3DOF Bouncing Ball Simulator is a simple Matlab program meant to mimic the behavior of a bouncing ball on a vibratory device capable of sinusoidal motion in three degrees, such as the VPOD. The simulator uses a numerical method in which the equations of motion describing the ball's flight are determined from the state variables of the previous impact. The program uses a binary search to locate the time at which the ball's position in the x,z plane is equal to that of the oscillating bar. In short, it calculates the intersection of a parabola with a sinusoid, uses a simple impact model to compute the new state variables, and repeats this computation as many times as desired. The equations of motion for the oscillating bar are as follows:
where A_x, A_z, A_theta represent the maximum x, z, and angular displacements of the bar's motion. The key input variables are the three position amplitudes, three frequencies, and three phase angles, as well as coefficients of restitution in the normal and tangential directions.
Quick Start
In order to run the simulator, first download the Matlab files by clicking on the link below:
Description of Functions
The zipped folder contains 6 m-files:
- bBallSim - This is the main m-file and likely the only one you will have to worry about. It contains a big for loop which takes the initial conditions for the ball's flight and calculates one bar impact, storing the data in the matrix 'P'. The post-impact conditions then become the new initial conditions. It loops as many times as indicated.
- binSrch - Uses a binary search method to locate the time where in ball intersects the bar, based off of the initial flight conditions and parameters. It returns the time of intersection (denoted 't2').
- checkLocking - Determines whether or not the ball is locking. Locking is a phenomenon in which the ball's velocity decays to zero, undergoing an infinite number of bounces in the absorbing region of the bar's motion. If the flight time is less than an arbitrarily small value, the ball is determined to be locking, and a value of 1 is returned.
- impact - This function takes the initial conditions and time of impact as inputs. It uses a simple impact model to calculate the post-impact positions and velocities of the ball.
- calculateLaunch - Determines whether or not the ball will be relaunched after locking. If the motion of the bar, and the position of the ball are such that the vertical acceleration of the bar will exceed gravity at some point during its periodic motion, then the ball will be relaunched. Otherwise, the ball will never be relaunched, and the simulation will terminate.
- plotTraj - This function is used only to plot the trajectories of the ball and the bar. This is only used as a visual aid and is helpful for debugging. It can easily be turned off to speed up the simulation.
Explanation of Important Inputs & Parameters
First, open the bBallSim m-file. The first few lines will look like this:
function [P, N] = bBallSim(A_x, A_z, A_th, p) % SYSTEM PARAMETERS num_impacts = 500; % Number of impacts simulator will calculate before terminating A = [A_x; A_z; A_th]; % Position amplitude of bar, nondimensional [A_x, A_z, A_th] phi = [pi/2; pi/2; p]; % Phase angle of bar [phi_x, phi_z, phi_th] f = [1; 2; 1]; % Frequencies of bar motions [f_x, f_z, f_th] w = 2*pi.*f; % [w_x, w_z, w_th]
There are four important inputs for this version of the program.
- A_x is the nondimensionalized position amplitude of the bar in the x (horizontal) direction.
- A_z is the nondimensionalized position amplitude of the bar in the z (vertical) direction.
- A_th is the amplitude in the theta direction (angular about the y). It is already dimensionless.
- p is the relative phase between the theta motion and the other motions.
Nondimensionalizations are as follows:
Position: where f(1) is equal to the first frequency in the vector f (or the horizontal frequency) and g is equal to the acceleration due to gravity
Velocity:
Acceleration:
Simple Test
For example, if one were to input the following:
[P, N] = bBallSim(0, 0.0052, 0, 0);
This is setting a motion with zero amplitude in the x and theta directions. 0.0052 is the nondimensional equivalent of 8m/s^2 in the z direction. If this simulation is run for 100 impacts with e = [0.8 0.8], the following plot will be created:
399 Write-up and Raw Data
The following is a 399 Write-up from a 2009-2010 independent study conducted by Undergraduate Eric Bell. The paper uses data from both physical experimentation as well as the simulator described above. EBell-399FinalWriteup
The write-up is also available as a word document EBell-399FinalWriteup Microsoft Word version
Some of the data used in the write-up are included below:
The following contains both the raw data from the real and virtual cameras as well as the calculated a workspace containing the calculated 3D coordinates. This data was used to create Figures 2.3 through 2.5: Figure2.3-2.5 Data The zipped folder also contains the Matlab Figure files corresponding to the plots used in the paper.
The following contains the Matlab workspaces used to create Figures 3.1-3.5. The period 1 and period 2 examples were captured using 2D imaging, whereas the period 3 example uses 3D. Figure files are also included. Figures3.1-3.5 Data
The following is experimental data used to create the bifurcation diagrams shown in Figure 3.8 and 3.10. This data was also used for the examples of period 1 and period 2 m=2 behavior corresponding to Figures 3.6 and 3.7 in the write-up: Data for Bifurcation Diagrams This data was collected using 3 regions of interest (XZ- raw data from real camera, YZ- raw data from "virtual" camera, bar_tracking- raw data for bar's motion using real camera). This workspace also contains the calculated 3D coordinates of the ball (XYZ_BALL) as well as the adjusted coordinates of the bar (XZ_BAR). The Matlab function used to calculate these coordinates is pasted below.
The data for the experiment shown in Figure 3.12 can be downloaded here along with the plot. Data for Figure 3.12 In the workspace, the variable referred to as tau in the plot is saved as "ndPhase."
Other figures included in the paper: Miscellaneous Figures
% The function "calc_coords" takes as inputs, the raw data for vision in % the XZ and XY planes. % CC_xz and CC_yz are vectors of size [2x1] containing the principal points % for each vision plane. Coordinates for principal point should be computed beforehand and reported in % metric. % FC_xz and FC_yz are vectors of size [2x1] containing the two focal % lengths of the lens for each vision plane. These are obtained from the % Calibration Toolbox and should be left in pixels. % The function returns a matrix of size [nx5] containing the least squares % approximation of the (x,y,z) coordinates based off of the vectors from % the two cameras, as well as the index and time at which these coordinates % occur. % NOTES: % - All computations are done in metric. (Based off of calibration grid) % - The XZ vision plane = "Real Camera" % - The YZ vision plane = "Virtual Camera" function [XYZ_BALL, XZ_BAR] = calc_coords3ROI(XZ, YZ, bar_tracking); % Should be most recent calibration w = cd; calib = '8-17-09 Calibration Constants'; cd('C:\Documents and Settings\John Shih\Desktop\VPOD- EBell\Calibration Constants\'); load(calib); % Change directory to regular working directory cd(w); matSize_xz = size(XZ); num_datapoints_xz = matSize_xz(1,1); matSize_yz = size(YZ); num_datapoints_yz = matSize_yz(1,1); num_datapoints = min(num_datapoints_xz, num_datapoints_yz); XYZ_BALL = zeros(num_datapoints-1, 5); % Initialize destination matrix conv_xz = [FC_xz(1,1) + FC_xz(2,1)] / [CONSTANTS_xz(1,1) + CONSTANTS_xz(3,1)]; % Conversion factor (number of pixels / mm) for vision in XZ conv_yz = [FC_yz(1,1) + FC_yz(2,1)] / [CONSTANTS_yz(1,1) + CONSTANTS_yz(3,1)];; % Conversion factor (number of pixels / mm) for vision in YZ dist_origin_xz = [(FC_xz(1,1) + FC_xz(2,1)) / 2] / [conv_xz]; % Taking an average of the two focal lengths, dist_origin_yz = [(FC_yz(1,1) + FC_yz(2,1)) / 2] / [conv_yz]; % Multiplying by conversion factor to get % the distance to the calibration grid in metric. prinP_xz = [CC_xz(1,1); -dist_origin_xz; CC_xz(2,1)]; % [3X1] vector containing the coordinates of the principal points prinP_yz = [dist_origin_yz; -CC_yz(1,1); CC_yz(2,1)]; % for the "Real" and "Virtual" Cameras. for i = [1 : 1 : num_datapoints - 1] planeP_xz = [XZ(i,3); 0; XZ(i,4)]; % [3x1] vector containing the points in the plane of the calibration grid planeP_yz = [0; -(YZ(i,3)+(2/3)*[YZ(i+1,3) - YZ(i,3)]); (YZ(i,4)+(2/3)*[YZ(i+1,4) - YZ(i,4)])]; x1_xz = prinP_xz(1,1); y1_xz = prinP_xz(2,1); z1_xz = prinP_xz(3,1); x1_yz = prinP_yz(1,1); y1_yz = prinP_yz(2,1); z1_yz = prinP_yz(3,1); x2_xz = planeP_xz(1,1); y2_xz = planeP_xz(2,1); z2_xz = planeP_xz(3,1); x2_yz = planeP_yz(1,1); y2_yz = planeP_yz(2,1); z2_yz = planeP_yz(3,1); % Set up matrices to solve matrix equation Ac = b, where c = [x, y, z] A_xz = [ (y2_xz - y1_xz), (x1_xz - x2_xz), 0; (z2_xz - z1_xz), 0, (x1_xz - x2_xz); 0, (z2_xz - z1_xz), (y1_xz-y2_xz) ]; b_xz = [ x1_xz*(y2_xz - y1_xz) + y1_xz*(x1_xz - x2_xz); x1_xz*(z2_xz - z1_xz) + z1_xz*(x1_xz - x2_xz); y1_xz*(z2_xz - z1_xz) + z1_xz*(y1_xz - y2_xz) ]; A_yz = [ (y2_yz - y1_yz), (x1_yz - x2_yz), 0; (z2_yz - z1_yz), 0, (x1_yz - x2_yz); 0, (z2_yz - z1_yz), (y1_yz-y2_yz) ]; b_yz = [ x1_yz*(y2_yz - y1_yz) + y1_yz*(x1_yz - x2_yz); x1_yz*(z2_yz - z1_yz) + z1_yz*(x1_yz - x2_yz); y1_yz*(z2_yz - z1_yz) + z1_yz*(y1_yz - y2_yz) ]; A = [A_xz; A_yz]; b = [b_xz; b_yz]; c = A\b; % Solve for 3D coordinates XYZ_BALL(i, 1) = i; XYZ_BALL(i, 2) = XZ(i,2); XYZ_BALL(i, 3) = c(1,1); XYZ_BALL(i, 4) = c(2,1); XYZ_BALL(i, 5) = c(3,1); end num_datapoints_bar = size(bar_tracking, 1); offset = 38.5; % Distance from the calibration plane to the plane, coinciding with the front face of the bar (in mm)% the distance to the calibration grid in metric. XZ_BAR = zeros(num_datapoints_bar, 4); for i = [1 : 1 : num_datapoints_bar] XZ_BAR(i,1) = bar_tracking(i,1); XZ_BAR(i,2) = bar_tracking(i,2); XZ_BAR(i,3) = bar_tracking(i,3)*(dist_origin_xz - offset) / dist_origin_xz; XZ_BAR(i,4) = bar_tracking(i,4)*(dist_origin_xz - offset) / dist_origin_xz; end %plot(XYZ_BALL(:,2)/(10^6), XYZ_BALL(:,5)-BALL0, XZ_BAR(:,2)/(10^6), XZ_BAR(:,4)-BAR0)