Exemple #1
0
void vrpn_Freespace::mainloop(void) 
{
	server_mainloop();
    struct freespace_message s;

    /*
     * Send configuration information to the device repeatedly to force the
     * device into the correct mode.  This method ensures the correct mode 
     * even if the Freespace device was asleep during initialization or if
     * the tracker resets.
     */
    struct timeval timestamp;
    vrpn_gettimeofday(&timestamp, NULL);
    if (_timestamp.tv_sec != timestamp.tv_sec) {
        _timestamp.tv_sec = timestamp.tv_sec;
        deviceConfigure();
    }

	// Do not block, read as many messages as 
    while (FREESPACE_SUCCESS == freespace_readMessage(_freespaceDevice, &s, 0)) {
	    switch(s.messageType) {
		    case FREESPACE_MESSAGE_LINKSTATUS:
			    handleLinkStatus(s.linkStatus);
			    break;
		    case FREESPACE_MESSAGE_BODYFRAME:
			    handleBodyFrame(s.bodyFrame);
			    break;
		    case FREESPACE_MESSAGE_USERFRAME:
			    handleUserFrame(s.userFrame);
			    break;
            case FREESPACE_MESSAGE_ALWAYSONRESPONSE:
                break;
            case FREESPACE_MESSAGE_DATAMODERESPONSE:
                break;
		    default:
                send_text_message("Received an unhandled message from freespace device", timestamp, vrpn_TEXT_WARNING);
			    break;
	    }
    }
}
int FreeSpaceTracker::getOrientationFromDevice(float* yaw, float* pitch, float* roll) 
{
	//OutputDebugString("Free Tracker getOrient\n");

	freespace_message msg;

	int err = freespace_readMessage(DeviceID, &msg, 10);

	/*
	char errChar[512];
	sprintf_s(errChar, "devID = %d, err == %d", DeviceID, err);
	OutputDebugString(errChar);
	OutputDebugString("\n");
	*/

	if (err == 0) 
	{
        // Check if this is a user frame message.
        if (msg.messageType == FREESPACE_MESSAGE_USERFRAME) 
		{
			// Convert from quaternion to Euler angles

			// Get the quaternion vector
			float w = msg.userFrame.angularPosA;
			float x = msg.userFrame.angularPosB;
			float y = msg.userFrame.angularPosC;
			float z = msg.userFrame.angularPosD;

			// normalize the vector
			float len = sqrtf((w*w) + (x*x) + (y*y) + (z*z));
			w /= len;
			x /= len;
			y /= len;
			z /= len;

			// The Freespace quaternion gives the rotation in terms of
			// rotating the world around the object. We take the conjugate to
			// get the rotation in the object's reference frame.
			w = w;
			x = -x;
			y = -y;
			z = -z;
      
			// Convert to angles in radians
			float m11 = (2.0f * w * w) + (2.0f * x * x) - 1.0f;
			float m12 = (2.0f * x * y) + (2.0f * w * z);
			float m13 = (2.0f * x * z) - (2.0f * w * y);
			float m23 = (2.0f * y * z) + (2.0f * w * x);
			float m33 = (2.0f * w * w) + (2.0f * z * z) - 1.0f;

			*roll = RADIANS_TO_DEGREES(atan2f(m23, m33));
			*pitch = RADIANS_TO_DEGREES(asinf(-m13));
			*yaw = RADIANS_TO_DEGREES(atan2f(m12, m11));



			return 0;   
        }

        // any other message types will just fall through and keep looping until the timeout is reached
    }
    else
        return err;  // return on timeouts or serious errors

   return FREESPACE_ERROR_TIMEOUT;  // The function returns gracefully without values
}
Exemple #3
0
//-----------------------------------------------------------------------------
int GetOrientation(float* yaw, float* pitch, float* roll) {

   
   int duration = 0;
   int timeout = 250;       // 1/4 second max time in this function

   long start = clock();

   freespace_message msg;
   while (duration < timeout) {
   
      int err = freespace_readMessage(DeviceID, &msg, timeout - duration);
      if (err == 0) {
         // Check if this is a user frame message.
         if (msg.messageType == FREESPACE_MESSAGE_USERFRAME) {
            // Convert from quaternion to Euler angles

            // Get the quaternion vector
            float w = msg.userFrame.angularPosA;
            float x = msg.userFrame.angularPosB;
            float y = msg.userFrame.angularPosC;
            float z = msg.userFrame.angularPosD;

            // normalize the vector
            float len = sqrtf((w*w) + (x*x) + (y*y) + (z*z));
            w /= len;
            x /= len;
            y /= len;
            z /= len;

            // The Freespace quaternion gives the rotation in terms of
            // rotating the world around the object. We take the conjugate to
            // get the rotation in the object's reference frame.
            w = w;
            x = -x;
            y = -y;
            z = -z;
      
            // Convert to angles in radians
            float m11 = (2.0f * w * w) + (2.0f * x * x) - 1.0f;
            float m12 = (2.0f * x * y) + (2.0f * w * z);
            float m13 = (2.0f * x * z) - (2.0f * w * y);
            float m23 = (2.0f * y * z) + (2.0f * w * x);
            float m33 = (2.0f * w * w) + (2.0f * z * z) - 1.0f;

            if (bRawFeed) {
               // Just return the raw samples
               *roll = atan2f(m23, m33);
               *pitch = asinf(-m13);
               *yaw = atan2f(m12, m11);
               return 0;
            }
            else {
               // Run the new sample through the smoothing filter

               // Find the index into the rotating sample window
               CurSample++;
               if (CurSample >= SMOOTHING_WINDOW_SIZE)
                  CurSample = 0;

               // Add the new sample
               RollWindow[CurSample] = atan2f(m23, m33);
               PitchWindow[CurSample] = asinf(-m13);
               YawWindow[CurSample] = atan2f(m12, m11);

               if (NumSamples < SMOOTHING_WINDOW_SIZE) {
                  // At startup, don't return a value until the window is full
                  NumSamples++;
               }
               else {
                  // Average all the samples in the sample window

                  float roll_sum = RollWindow[CurSample];
                  float pitch_sum = PitchWindow[CurSample];
                  float yaw_sum = YawWindow[CurSample];

                  int i = CurSample+1;
                  if (i >= SMOOTHING_WINDOW_SIZE)
                     i = 0;
                  
                  while (i != CurSample) {
                     roll_sum += RollWindow[i];
                     pitch_sum += PitchWindow[i];

                     if (fabs(YawWindow[CurSample] - YawWindow[i]) > PI) {
                        // If the yaw samples cross a discontinuity, then make the angles
                        // all positive or all negative so averaging works
                        if (YawWindow[CurSample] > 0)
                           yaw_sum += (YawWindow[i] + (2 * PI));
                        else
                           yaw_sum += (YawWindow[i] + (-2 * PI));
                     }
                     else
                        yaw_sum += YawWindow[i];

                     i++;
                     if (i >= SMOOTHING_WINDOW_SIZE)
                        i = 0;
                  }

                  // Compute the smoothed values
                  float next_roll = roll_sum / SMOOTHING_WINDOW_SIZE;
                  float next_pitch = pitch_sum / SMOOTHING_WINDOW_SIZE;
                  float next_yaw = yaw_sum / SMOOTHING_WINDOW_SIZE;

                  // correct yaw angles
                  if (next_yaw > PI)
                     next_yaw -= (2 * PI);
                  else if (next_yaw < -PI)
                     next_yaw += (2 * PI);

                  // Put a speed limit on pitch changes to minimize violent
                  // pitch recalibrations
                  if (Pitch == ANGLE_UNDEFINED) {
                     Pitch = next_pitch;    // initial value
                  }
                  else {
                     // Limit any large angular changes
                     if (next_pitch < Pitch)
                        Pitch = max(next_pitch, Pitch - MAX_ANGULAR_CHANGE);
                     else if (next_pitch > Pitch)
                        Pitch = min(next_pitch, Pitch + MAX_ANGULAR_CHANGE);
                  }

                  // return the adjusted values
                  *roll = next_roll;
                  *pitch = Pitch;
                  *yaw = next_yaw;        
                  return 0;
               }
            }
         }

         // any other message types will just fall through and keep looping until the timeout is reached
      }
      else
         return err;  // return on timeouts or serious errors

      duration += clock() - start;
   }

   return FREESPACE_ERROR_TIMEOUT;  // The function returns gracefully without values
}
/**
 * main
 * This example uses the synchronous API to 
 *  - find a device
 *  - open the device found
 *  - send a message
 *  - look for a response
 * This example assumes that the device is already connected.
 */
int main(int argc, char* argv[]) {
    FreespaceDeviceId device;                       // Keep track of the device you are talking to
    struct freespace_message send;                  // A place to create messages to send to the device
    struct freespace_message receive;               // A place to put a message received from the device
    int numIds;                                     // Keep track of how many devices are available
    int rc;                                         // Return Code
    int retryCount = 0;                             // How many times tried so far to get a response

    // Flag to indicate that the application should quit
    // Set by the control signal handler
    int quit = 0;

    printVersionInfo(argv[0]);

    addControlHandler(&quit);

    // Initialize the freespace library
    rc = freespace_init();
    if (rc != FREESPACE_SUCCESS) {
        printf("Initialization error. rc=%d\n", rc);
	    return 1;
    }

    printf("Scanning for Freespace devices...\n");
    // Get the ID of the first device in the list of availble devices
    rc = freespace_getDeviceList(&device, 1, &numIds);
    if (numIds == 0) {
        printf("Didn't find any devices.\n");
        return 1;
    }

    printf("Found a device. Trying to open it...\n");
    // Prepare to communicate with the device found above
    rc = freespace_openDevice(device);
    if (rc != FREESPACE_SUCCESS) {
        printf("Error opening device: %d\n", rc);
        return 1;
    }

    // Display the device information.
    printDeviceInfo(device);

    // Make sure any old messages are cleared out of the system
    rc = freespace_flush(device);
    if (rc != FREESPACE_SUCCESS) {
        printf("Error flushing device: %d\n", rc);
        return 1;
    }

    printf("Requesting battery level messages.\n");

    memset(&send, 0, sizeof(send)); // Start with a clean message struct
    // Populate the message fields. Two options are shown below. Uncomment one desired
    // and comment out the one not desired.
    //send.messageType = FREESPACE_MESSAGE_BATTERYLEVELREQUEST; // To send a battery level request
    send.messageType = FREESPACE_MESSAGE_PRODUCTIDREQUEST;    // To send a product ID request

    while (!quit) {
        if (retryCount < RETRY_COUNT_LIMIT) {
            retryCount++;
            // Send the message constructed above.
            rc = freespace_sendMessage(device, &send);
            if (rc != FREESPACE_SUCCESS) {
                printf("Could not send message: %d.\n", rc);
            }

            // Read the response message.
            rc = freespace_readMessage(device, &receive, 100);
            if (rc == FREESPACE_SUCCESS) {
                // Print the received message
                freespace_printMessage(stdout, &receive);
                retryCount = 0;
            } else if (rc == FREESPACE_ERROR_TIMEOUT) {
                printf("<timeout>  Try moving the Freespace device to wake it up.\n");
            } else if (rc == FREESPACE_ERROR_INTERRUPTED) {
                printf("<interrupted>\n");
            } else {
                printf("Error reading: %d. Quitting...\n", rc);
                break;
            }
        } else {
            printf("Did not receive response after %d trials\n", RETRY_COUNT_LIMIT);
            quit = 1;
        }
        SLEEP;
    }

    printf("Cleaning up...\n");
    freespace_closeDevice(device);

    freespace_exit();

    return 0;
}