Nicholas Chiarulli - 14:332:476 Virtual Reality
Click here to open the Virtual Reality Piano

Goals:

The goal of my project is to rehabilitate patients with hand injury due to stroke in a fun effective manner.

Through the use of my VR Piano I plan to improve the motion of fingers through repeated exercises. The user will follow a ball corresponding to the correct key on the piano. One benefit of using my VR Piano is that it can be customized to focus on individual finger (fractionation) or the whole hand. Also the range and speed can be adjusted accordingly to the patients needs. For example a song that can be designed to maximize duration of finger bending by strategically positioning the keys to be further apart causing the user to hold a position for a longer period of time. This could also be achieved by changing the speed at which the glove moves across the screen increasing the time that the user has to hold a position. One inclination is that the strengthening has a limitation because there is no force feedback (but it could be added with the use of the Rutgers Glove).

All the code, state machine design, and objects used in my project are my own work and have been created from scratch. In this project I used the concept of hierarchy, state machine design, and plenty of route statements. The nodes that I used were the AudioClip node, Script node, Text node, ImageTexture node, Viewpoint node, and the IndexedFaceSet node.

Figure 1.1

Figure 1.1 is the opening scene that the user is faced with. The first task is to press the red button
that says off in order to turn on the piano.

Figure 1.2 User can choose a different predefined viewpoint by clicking on the "View" button in the web browser.

Figure 2.1
Figure 2.1 represents the user turned the keyboard ON and pressed the correct key, which displays "Good, now press the next key." This is also good because if the next key is the same key the user will know to press the key again.

Figure 2.2
Figure 2.2 represents the user pressing the wrong key and with an encouraging message to "Try again."

 

Problems I was faced with:

The two biggest problems that I was faced with were the fact that collision detection was not available for us to use and to involve the other fingers with the rehabilitation exercise. Two smaller problems that I encountered were how to implement the songs and how to perform an operation on a constantly updated value.

My whole project was based on the interaction/collision of the glove’s fingers and the keys on the VR Piano. The way that I went about solving this problem was to determine the gloves position on the screen and if the user was bending the correct finger over the correct key. These are the conditions that need to be satisfied in order for the sound to be played.

Example pseudocode to solve collision detection:

If (user is bending finger at the correct angle && if the finger is on top of the key && if correct key to be pressed) then play sound corresponding to that key.

By using gesture recognition techniques I was able to involve not only the index finger but also the thumb and pinky finger. When the thumb is bent the glove will move to the left and while the pinky is bent the glove will move to the right. The position that the glove is in is stored in a variable called NewMove. This variable is used to test if the glove is over the correct key.

Example pseudopodia used in pinky gesture recognition:

if (NewMove < max length of keyboard) then increment the x position of the glove

Example pseudocode used in thumb gesture recognition:

if (NewMove > min length of keyboard) then decrement the x position of the glove

One of the smaller problems that I was faced with is how to implement the songs that the user would play and how would they know what key to press. I solved this by using a single array of values that range from 1 to 4, each one representing a key on the VR Piano. With this flexibility the doctor can change the song to allow the user to follow a predefined song that can be designed to maximize duration of finger bending. For example if the array is array[1 4 1 4 ….] then the patient will have to hold down his/her pinky and thumb to reach the far ends of the piano. A ball was placed over the correct key that the user was to press. This was accomplished by using the song array to determine which key the ball was to be placed on. Each key has a known position so I used switch( key that the ball was to be on)

Example pseudocode to solve learning ball placement:

Switch( key where ball needs to be placed){

case key 1 :

x position of key 1 = 3;

y position of key 1 = 8;

break;

.

.

}

The other small problem that I was faced with was the fact that the value of the finger was constantly changing. In order to solve this I used Semaphores to lock the value, perform the correct operation, and then grab the next value. The lock was based off a specific value and would only open if it was at the specific value.

Example pseudocode for semaphore used in program:

If ( lock == open ) enter critical section and perform the task

else wait for lock to open.

State Machine Diagram:

 

The following pseudo code is based off the state machine design for the Virtual Reality Piano.

Inside the function Index() you will find the actual code developed from this pseudo code:

 

Function Index(){

Lock = closed

cur_state = next_state

switch(cur_state){

idle state:

wait for lock to open

if finger is above key next_state = key pressed

and close lock.

--------------------------------------------------------------------

key pressed state:

if key 1 is keypressed = key1

if key 2 is keypressed = key2

if key 3 is keypressed = key3

if key 4 is keypressed = key4

next_state = correct key pressed

---------------------------------------------------------------------

correct key pressed state:

if keypressed = array[array of keys] then next_state = display good

else next_state = display try again

---------------------------------------------------------------------

display try again state:

change the z coordinate of text to display try again

change the z coordinate of text to hide good job, press next key

next_state = key pressed state

---------------------------------------------------------------------

display good state:

change the z coordinate of text to hide try again

change the z coordinate of text to display good job, press next key

next_state = play sound

---------------------------------------------------------------------

play sound state:

switch(keypressed){

case 1:

startKey1Time = eventTime;

case 2:

startKey2Time = eventTime;

case 3:

startKey4Time = eventTime;

case 4:

startKey4Time = eventTime;

default:}

next_state = update

---------------------------------------------------------------------

update state:

get next beat from array

switch(beat from array){

case 1 :

put ball on top of key 1

case 2 :

put ball on top of key 2

case 3 :

put ball on top of key 3

case 4 :

put ball on top of key 4

case 5:

END OF SONG

default:

reset array counter back to zero to get first element of array.

next_state = start

}

Variables needed:

int counter for array

int keypressed

int states (i.e. start,..update)