Part 4 – Data Glove Interaction

In this session, you are going to learn on how to setup the data glove and use it for interaction in OpenGL Performer. The 5DT Data Glove Ultra is a hand data motion capturing solution for animation and virtual reality. This glove measures finger flexure as well as the abduction between the fingers. Finger flexure is measured at two places (1st joint (knuckle), 2nd joint) on each finger.

Connecting the glove

Connect the glove to the PC as shown in the Figure above. You can use GloveManager (Start-> All Programs-> 5DT-> Data Glove Ultra-> Glove Manager) to test the operation of the glove. The details of the operation can be found in Section 4 of the 5DT Data Glove Ultra Manual, also available from the Start menu.

Setting up the glove

  1. After the data glove is connected, it is time to set it up for interaction in our program. First of all, the necessary header files need to be included.

#include <stdio.h>
#include <string.h>
#include <windows.h> // for Sleep
// --The data glove header file
#include "fglove.h"
  1. The variables are declared.

// Variable declarations
fdGlove *glove = NULL;//the dataglove
char *szPort = "USB";//type of port
char szPortToOpen[6];//string to store the port to open
int glovetype = FD_GLOVENONE;//glove type
  1. Next, the USB ports available on the computer are scanned to detect the available gloves. The number of gloves found during the scan will be returned as an integer value. The first parameter of

int fdScanUSB(unsigned short *aPID, int *nNumMax)

is a pointer to an unsigned short array of length nNumMax. The USB Product IDs of the gloves found are returned in this array of which the following PIDs are defined:

DG14U_R – Data Glove 14 Ultra Right-hand

DG14U_L – Data Glove 14 Ultra Left-hand

DG5U_R – Data Glove 5 Ultra Right-hand

DG5U_L – Data Glove 5 Ultra Left-hand

// Glove connected to USB port
strcpy(szPortToOpen, szPort);
//Test the USB port of which the glove is connected
if (strcmp(szPort,"USB") == 0)
{
unsignedshort aPID[4];//USB product ID of the gloves
int nNumFound = 4;//Number of USB port found
int nChosen = 0;//Glove chosen
// Scan the USB for the available glove
fdScanUSB(aPID,nNumFound);
// Print out the available gloves in the console
for (int c = 0; c < nNumFound; c++)
{
printf("Available USB Gloves:\n");
printf("%i - ",c);
switch (aPID[c])
{
case DG14U_R:
printf("Data Glove 14 Ultra Right\n");
break;
case DG14U_L:
printf("Data Glove 14 Ultra Left\n");
break;
case DG5U_R:
printf("Data Glove 5 Ultra Right\n");
break;
case DG5U_L:
printf("Data Glove 5 Ultra Left\n");
break;
default:
printf("Unknown\n");
}
}
// Getting user input
printf("Please enter option:");
scanf("%i",&nChosen);
sprintf(szPortToOpen,"USB%i",nChosen);
// Initialise the glove device on the specified port
fdOpen(szPortToOpen);
}

When the glove(s) is found, a prompt is displayed for the user to choose the desired glove to open.

  1. Test that the glove open process is carried out successfully. NULL is returned if an error occurred.

printf("Attempting to open glove on %s ..", szPortToOpen);
// Initialising glove and make sure that it is not NULL
if((glove = fdOpen(szPortToOpen)) == NULL)
{
printf("Failed!");
return -1;
}
else
printf("Succeeded!");
  1. Next, check the type of currently connected glove and print the details. The number of sensor is also obtained

// Obtains the type of the currently connected glove
char *szType = "?";
glovetype = fdGetGloveType(glove);
switch (glovetype)
{
case FD_GLOVENONE: szType = "None"; break;
case FD_GLOVE7: szType = "Glove7"; break;
case FD_GLOVE7W: szType = "Glove7W"; break;
case FD_GLOVE16: szType = "Glove16"; break;
case FD_GLOVE16W: szType = "Glove16W"; break;
case FD_GLOVE5U: szType = "DG5 Ultra serial"; break;
case FD_GLOVE5UW: szType = "DG5 Ultra serial, wireless"; break;
case FD_GLOVE5U_USB: szType = "DG5 Ultra USB"; break;
case FD_GLOVE14U: szType = "DG14 Ultra serial"; break;
case FD_GLOVE14UW: szType = "DG14 Ultra serial, wireless"; break;
case FD_GLOVE14U_USB: szType = "DG14 Ultra USB"; break;
}
// Print the glove type, indicating whether it is right- or left- handed
printf( "glove type: %s\n", szType );
printf( "glove handedness: %s\n",
fdGetGloveHand(glove)==FD_HAND_RIGHT?"Right":"Left" );
// Obtains the number of available sensors values
int iNumSensors = fdGetNumSensors(glove);
printf( "glove num sensors: %d\n", iNumSensors );

FD_GLOVE7 and FD_GLOVE7W refer to the original 5+2 (tilt angles) sensor glove(5DT Data Glove 5). The W suffix indicates a wireless model. FD_GLOVE16 andFD_GLOVE16W refer to the Data Glove 16. FD_GLOVE14, FD_GLOVE14W, andFD_GLOVE14_USB refer to the Data Glove 14 Ultra. The USB suffix refers to theUniversal Serial Bus interface. In order to accommodate all glove types thefdGetNumSensors() function currently returns 18 sensors. The additional twosensors are defined as the original tilt angles that are not present in the 16-sensor glove.

Although the 5-sensor glove can measure only average flexure, the driver will attempt to fill in missing values. The number of sensors returned can therefore be of higher dimension.

Sensor Positions for the 5DT Data Glove 5

Sensor Mappings for the 5DT Data Glove 5 and 5DT Data Glove 5 Ultra

* Both these driver sensor indices will return the same value when the 5DT Data

Glove 5 or Data Glove Ultra is used

+ Not available on the Data Glove 5 Ultra

  1. In the simulation loop, print the glove scaled values. The current gesture is also obtained and printed.

// Simulation loop
for (int i=0; i<10; i++ )
{
// Value for the current gesture
int gesture;
if (glovetype==FD_GLOVE7 || glovetype==FD_GLOVE7W)
{
// Display the glove scaled values
printf("Gloves scaled values");
printf("Thumb%.1f ",
fdGetSensorScaled(glove,FD_THUMBNEAR));
printf("Index%.1f ",
fdGetSensorScaled(glove,FD_INDEXNEAR));
printf("Middle%.1f ",
fdGetSensorScaled(glove,FD_MIDDLENEAR));
printf("Ring%.1f ",
fdGetSensorScaled(glove,FD_RINGNEAR));
printf("Little%.1f \n",
fdGetSensorScaled(glove,FD_LITTLENEAR));
printf( "roll=%.1f,pitch=%.1f\n",
fdGetSensorScaled(glove,FD_ROLL),
fdGetSensorScaled(glove,FD_PITCH));
}
else
{
// Display the glove scaled values
printf("Gloves scaled values");
printf("ThumbNear%.1f,",
fdGetSensorScaled(glove,FD_THUMBNEAR));
printf("ThumbFar%.1f,",
fdGetSensorScaled(glove,FD_THUMBFAR));
printf("ThumbIndex%.1f ",
fdGetSensorScaled(glove,FD_THUMBINDEX));
printf("IndexNear%.1f,",
fdGetSensorScaled(glove,FD_INDEXNEAR));
printf("IndexFar%.1f,",
fdGetSensorScaled(glove,FD_INDEXFAR));
printf("IndexMiddle%.1f ",
fdGetSensorScaled(glove,FD_INDEXMIDDLE));
printf("MiddleNear%.1f,",
fdGetSensorScaled(glove,FD_MIDDLENEAR));
printf("MiddleFar%.1f,",
fdGetSensorScaled(glove,FD_MIDDLEFAR));
printf("MiddleRing%.1f ",
fdGetSensorScaled(glove,FD_MIDDLERING));
printf("RingNear%.1f,",
fdGetSensorScaled(glove,FD_RINGNEAR));
printf("RingFar%.1f,",
fdGetSensorScaled(glove,FD_RINGFAR));
printf("RingLittle%.1f ",
fdGetSensorScaled(glove,FD_RINGLITTLE));
printf("LittleNear%.1f,",
fdGetSensorScaled(glove,FD_LITTLENEAR));
printf("LittleFar%.1f ",
fdGetSensorScaled(glove,FD_LITTLEFAR));
printf("ThumbPalm%.1f ",
fdGetSensorScaled(glove,FD_THUMBPALM));
printf("WristBend%.1f \n",
fdGetSensorScaled(glove,FD_WRISTBEND));
printf( "roll=%.1f,pitch=%.1f\n",
fdGetSensorScaled(glove,FD_ROLL),
fdGetSensorScaled(glove,FD_PITCH));
}
// Obtain the current gesture being performed
gesture = fdGetGesture(glove);
printf("Gesture %d\n", gesture);
// Wait for a while before the next iteration
Sleep(1000);
}

It is also possible to obtain the glove raw data by using

unsigned short fdGetSensorRaw(fdGlove *pFG, int nSensor)

Gesture Illustration

  1. Finally, close the glove device and frees the communication port

printf( "closing glove\n" );
// Frees the glove device and communications port
fdClose(glove);

Data Glove Interaction

Now, it is time to use the data glove as an interaction device in OpenGL Performer. A particular gesture will cause an operation to be carried out on the 3D model.

  1. Add Step 1 to 4 above to the basic model loading program that you have created earlier.
  1. Make the root node which is a type of pfNode to be the child of pfDCS, a branch of node that represents a dynamic coordinate system. It is used here as we want to change the transformation of the 3D model during the execution of the application. Remember to replace the child of pfScene with the dcs node instead of the pfNode node. The other part of the program remains the same.

// Add the 3D model as a child of pfDCS node
pfDCS *dcs = new pfDCS;
dcs->addChild(root);
scene->addChild(dcs);
  1. Put the statements that setthe viewpoint of the channel (previously in the simulation loop) before the simulation loop. Declare as well as initialise the variables to be used in the simulation loop.

// Set the initial viewpoint
view.hpr.set(45.0f, -10.0f, 0);
view.xyz.set(20.0f, -20.0f, 5.0f);
chan->setView(view.xyz, view.hpr);
// Variable declaration
float rotX=0.0f, scale=1.0f;
  1. In the simulation loop, detect the current gesture. Perform some action on the 3D model based on the gesture. Here, gesture 1 will cause the model to rotate along the X axis, while gesture 3 will enlarge the model. Gesture 15 will cause the scene to be reset to its original stage.

// Simulation loop
while (t < 40.0f)
{
int gesture;
pfSync();
// Obtain the current gesture being performed
gesture = fdGetGesture(glove);
printf("Gesture %d\n", gesture);
// Perform some action on the object based on the gesture
// performed
if(gesture == 1)
{
// Changing the pitch value - Rotation along X axis
dcs->setRot(0.0f, rotX, 0.0f);
rotX +=0.05f;
}
elseif(gesture == 3)
{
// Enlarge the model
dcs->setScale(scale);
scale += 0.01f;
}
elseif(gesture == 15)
{
// reset the model
rotX=0.0f;
scale=1.0f;
dcs->setRot(0.0f, rotX, 0.0f);
dcs->setScale(scale);
}
pfFrame();
}
  1. Now, you are ready to compile the program and interact with the model using the data glove!

Extra exercise for those interested

Add more interaction using the different available gesture. You can translate the 3D model, rotate it along other axes, etc.

Summary

In this session, you have learned how to setup and use the data glove. For more information about the data glove SDK, please refer to the 5DT Data Glove Ultra Manual found at Start-> All Programs-> 5DT-> Data Glove Ultra-> 5DT Data Glove Ultra Manual