| META TOPICPARENT |
name="WiiLabMATLABDemos" |
WiiLab Example Code - Spinning Disk
Note: MATLAB R2007a or greater is required for this code to run correctly. The program uses the Wiimote class, along with the UND function set EG111-H.
Annotations
This program simulates a spinning disk. The program uses the Wiimotes acceleration to determine the speed and direction of the disk.
One thing to note is that the most complicated part of this demo's code is not associated with the Wiimote interaction but in determining the direction and speed of the disk.
Program Breakdown
The program is fairly large so I have broken it down into its vital blocks to describe each in detail. The complete file is attached at the bottom of the page.
Initialization
The program starts by connecting to the Wiimote. This is a very simple task using the global functions.
% Create an instance of the wiimote and connect
initializeWiimote()
After the Wiimote is connected we are going to initialize the game window. This involves the following:
- Creating the local variables for the program
- Creating the main window
- Creating the labels to display the acceleration values
- Drawing the disk
% Constants
diskRadius = 100; % # indicating the radius of the disk
diskCenter = [150 150];
cursorRadius = 2; % # indicating the radius of the cursor
frictionCoef = .02;
wedges = 8;
wedgeColors = ['b' 'g' 'r' 'y' 'b' 'g' 'r' 'y'];
% Variables
posTheta = 0;
posQuad = 0;
velTheta = 0;
velQuad = 0;
% Initialize Window
% -----------------------------------------------------------------
% Init basic window
initializeWindow(0);
%initialize text display
x_accelDispLbl = writeText(20,280,'X accel = ');
y_accelDispLbl = writeText(20,270,'Y accel = ');
diskVelDispLbl = writeText(20,260,'Disk vel = ');
x_accelDisp = writeText(50, 280, 'xx');
y_accelDisp = writeText(50, 270, 'xx');
diskVelDisp = writeText(50, 260, 'xx');
% Init the wiimote cursor
wiimoteCursor = drawCircle(150, 150, cursorRadius, 'black');
% Init the main disk
disk = drawCircleWedges(diskCenter(1), diskCenter(2), diskRadius, wedges, wedgeColors);
% Local Variables
onDisk = false;
prevAttached = false;
attached = false;
diskVel = 0;
% -----------------------------------------------------------------
Main Loop
For the Spinning Disk program, our main loop will execute until "HOME" is pressed on the Wiimote.
Inside the loop the following things are done:
- Move the user cursor based on the Wiimote's Acceleration.
- If the Wiimote is on the Disk and the User is pressing "B", then record the Acceleration values to spin the disk when the User releases the disk.
- Calculating the disks direction and speed based on the recorded acceleration (detailed in the next section)
- Redraw and Pause. This is one of the most important pieces of any program like this. You need to make sure that you have a pause(xx) at the end of every loop that uses the Wiimote or EG111-H functions. MATLAB will not execute any callback functions until it reaches a pause(xx). If the pause is omitted you will begin to experience unusual behavior from the Wiimote class.
% While "Home" is not pressed
while (~isButtonPressed('HOME'))
% Determine if the wiimoteCursor is on the disk
% ---------------------------------------------
[xc yc] = getCenter(wiimoteCursor);
distanceFromDiskCenter = sqrt((xc-diskCenter(1))^2 + (yc-diskCenter(2))^2);
if(distanceFromDiskCenter <= diskRadius)
onDisk = true;
else
onDisk = false;
end
% ---------------------------------------------
if(isButtonPressed('B'))
% if the cursor is on the disk
if(onDisk)
attached = true;
else
attached = false;
end
else
if(attached)
attached = false;
prevAttached = true;
else
prevAttached = false;
end
end
if(prevAttached)
[x_accel y_accel] = getWiimoteAccel();
% Calculate Disk Velocity
% -----------------------------------------------------
set(x_accelDisp, 'String', x_accel);
set(y_accelDisp, 'String', y_accel);
set(diskVelDisp, 'String', diskVel);
% Draw Vector
try
hide(vector);
hide(arrow);
catch me
end
vector = drawLine(xc, yc, xc+(2*x_accel), yc+(2*y_accel), 'k');
%------------------------------------------------------
end
% If the Wiimote is "attached" to the disk
% don't move the wiimote
if(~attached)
rotate(disk, [0 0 1], diskVel);
% If the disk is rotating decrease its speed according to
% the "frictionCoef"
if(diskVel ~= 0)
diskVel = diskVel - diskVel * frictionCoef;
end
% Update the wiimote cursor position
moveObjectWithWiimote(wiimoteCursor, 1, false);
end
redraw();
pause(.01);
end % while
Calculate the Disk Speed and Direction
As stated before, the speed and direction the Disk spins in is based off of the Wiimote's Acceleration when the user releases the disk. There are two things that influence the speed, The Wiimotes Acceleration and where the cursor is positioned on the disk at the time it is released.
- if the paddle will end up inside the bounds * then move the paddle as normal
- if the paddle will end up above the upper bound * then move the paddle the rest of the distance to the boundary and no further
- if the paddle will end up below the lower bound * then move the paddle the rest of the distance to the boundary and no further
% Calculate position and acceleration angles (0 >< 90)
posTheta = atan(abs(yc-diskCenter(2))/abs(xc-diskCenter(1))) * (180/pi);
velTheta = atan(abs(y_accel)/abs(x_accel)) * (180/pi);
% Calc quadrent
if((xc - diskCenter(1) > 0) && (yc - diskCenter(2) > 0))
posQuad = 1;
elseif ((xc - diskCenter(1) > 0) && (yc - diskCenter(2) < 0))
posQuad = 4;
elseif ((xc - diskCenter(1) < 0) && (yc - diskCenter(2) < 0))
posQuad = 3;
elseif ((xc - diskCenter(1) < 0) && (yc - diskCenter(2) > 0))
posQuad = 2;
end
if (x_accel > 0 && y_accel > 0)
velQuad = 1;
elseif (x_accel > 0 && y_accel < 0)
velQuad = 4;
elseif (x_accel < 0 && y_accel < 0)
velQuad = 3;
elseif (x_accel < 0 && y_accel > 0)
velQuad = 2;
end
switch (velQuad)
case 2
velTheta = 180 - velTheta;
case 3
velTheta = 180 + velTheta;
case 4
velTheta = 360 - velTheta;
end
switch (posQuad)
case 1
theta = (90 - posTheta) + velTheta;
case 2
theta = -1*(90 - posTheta) + velTheta;
case 3
theta = (90 - posTheta) + velTheta;
case 4
theta = -1*(90 - posTheta) + velTheta;
end
diskVel = cos((theta*pi/180)) * sqrt(x_accel^2 + y_accel^2);
% factor in distance from the center
diskVel = 2 * diskVel * (distanceFromDiskCenter/diskRadius);
if(posQuad < 3)
diskVel = -1*diskVel;
end
%--------------------------------------------------------------
Raw Source Code
The source code is available as a .m file download at the bottom of the page.
-- JordanBrindza - 31 Jul 2008
| META FILEATTACHMENT |
attachment="spinning_disk.bmp" attr="h" comment="" date="1217523289" name="spinning_disk.bmp" path="C:\Documents and Settings\brindza\My Documents\REU_SVN\trunk\Documentation\Pictures\MATLAB Demos\spinning_disk.bmp" size="1150294" stream="C:\Documents and Settings\brindza\My Documents\REU_SVN\trunk\Documentation\Pictures\MATLAB Demos\spinning_disk.bmp" tmpFilename="/usr/tmp/CGItemp39508" user="JordanBrindza" version="1" |
| META FILEATTACHMENT |
attachment="SpinningDisk.m" attr="" comment="" date="1217523312" name="SpinningDisk.m" path="C:\Documents and Settings\brindza\My Documents\REU_SVN\trunk\Matlab\SpinningDisk.m" size="7125" stream="C:\Documents and Settings\brindza\My Documents\REU_SVN\trunk\Matlab\SpinningDisk.m" tmpFilename="/usr/tmp/CGItemp39263" user="JordanBrindza" version="1" |
|