Conflicts:
	interface/src/main.cpp
This commit is contained in:
Andrzej Kapolka 2013-05-14 11:32:43 -07:00
commit 174fdb8109
10 changed files with 1282 additions and 94 deletions

View file

@ -0,0 +1,44 @@
# Find the static PortAudio library
#
# You must provide a PORTAUDIO_ROOT_DIR which contains lib and include directories
#
# Once done this will define
#
# PORTAUDIO_FOUND - system found PortAudio
# PORTAUDIO_INCLUDE_DIRS - the PortAudio include directory
# PORTAUDIO_LIBRARY - Link this to use PortAudio
#
# Created on 5/14/2013 by Stephen Birarda
# Copyright (c) 2013 High Fidelity
#
if (PORTAUDIO_LIBRARY AND PORTAUDIO_INCLUDE_DIRS)
# in cache already
set(PORTAUDIO_FOUND TRUE)
else (PORTAUDIO_LIBRARY AND PORTAUDIO_INCLUDE_DIRS)
set(PORTAUDIO_INCLUDE_DIRS ${PORTAUDIO_ROOT_DIR}/include)
if (APPLE)
set(PORTAUDIO_LIBRARY ${PORTAUDIO_ROOT_DIR}/lib/MacOS/libportaudio.a)
else (WIN32)
set(PORTAUDIO_LIBRARY ${PORTAUDIO_ROOT_DIR}/lib/UNIX/libportaudio.a)
endif ()
if (PORTAUDIO_INCLUDE_DIRS AND PORTAUDIO_LIBRARY)
set(PORTAUDIO_FOUND TRUE)
endif (PORTAUDIO_INCLUDE_DIRS AND PORTAUDIO_LIBRARY)
if (PORTAUDIO_FOUND)
if (NOT PortAudio_FIND_QUIETLY)
message(STATUS "Found PortAudio: ${PORTAUDIO_LIBRARY}")
endif (NOT PortAudio_FIND_QUIETLY)
else (PORTAUDIO_FOUND)
if (PortAudio_FIND_REQUIRED)
message(FATAL_ERROR "Could not find PortAudio")
endif (PortAudio_FIND_REQUIRED)
endif (PORTAUDIO_FOUND)
# show the PORTAUDIO_INCLUDE_DIRS and PORTAUDIO_LIBRARY variables only in the advanced view
mark_as_advanced(PORTAUDIO_INCLUDE_DIRS PORTAUDIO_LIBRARY)
endif (PORTAUDIO_LIBRARY AND PORTAUDIO_INCLUDE_DIRS)

View file

@ -10,7 +10,7 @@ project(${TARGET_NAME})
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/modules/") set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/modules/")
set(LODEPNG_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/LodePNG) set(LODEPNG_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/LodePNG)
set(LIBOVR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/LibOVR) set(LIBOVR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/LibOVR)
set(PORTAUDIO_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/portaudio) set(PORTAUDIO_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/portaudio)
if (APPLE) if (APPLE)
set(GL_HEADERS "#include <GLUT/glut.h>\n#include <OpenGL/glext.h>") set(GL_HEADERS "#include <GLUT/glut.h>\n#include <OpenGL/glext.h>")
@ -131,28 +131,10 @@ if (WIN32)
else (WIN32) else (WIN32)
target_link_libraries(${TARGET_NAME} ${LODEPNG_LIBRARY}) target_link_libraries(${TARGET_NAME} ${LODEPNG_LIBRARY})
# include PortAudio as external project
include(ExternalProject)
set(PORTAUDIO_PROJ_DIR external/portaudio)
ExternalProject_Add(
portaudio
PREFIX ${PORTAUDIO_PROJ_DIR}
BINARY_DIR ${PORTAUDIO_PROJ_DIR}/src/portaudio
URL ${PORTAUDIO_DIR}/pa_snapshot_020813.tgz
CONFIGURE_COMMAND <SOURCE_DIR>/configure --prefix "${PROJECT_BINARY_DIR}/${PORTAUDIO_PROJ_DIR}"
BUILD_COMMAND make
)
# make PortAudio a dependency of the interface executable
add_dependencies(${TARGET_NAME} portaudio)
# include the PortAudio headers
ExternalProject_Get_Property(portaudio source_dir)
include_directories(${source_dir}/include)
# link the PortAudio library # link the PortAudio library
ExternalProject_Get_Property(portaudio binary_dir) find_package(PortAudio REQUIRED)
target_link_libraries(${TARGET_NAME} ${binary_dir}/lib/.libs/libportaudio.a) include_directories(${PORTAUDIO_INCLUDE_DIRS})
target_link_libraries(${TARGET_NAME} ${PORTAUDIO_LIBRARY})
# link required libraries on UNIX # link required libraries on UNIX
if (UNIX AND NOT APPLE) if (UNIX AND NOT APPLE)

File diff suppressed because it is too large Load diff

Binary file not shown.

Binary file not shown.

View file

@ -1900,6 +1900,9 @@ void Application::resetSensors() {
_headMouseX = _glWidget->width() / 2; _headMouseX = _glWidget->width() / 2;
_headMouseY = _glWidget->height() / 2; _headMouseY = _glWidget->height() / 2;
if (_serialPort.active) {
_serialPort.resetAverages();
}
_myAvatar.reset(); _myAvatar.reset();
} }

View file

@ -2,16 +2,7 @@
// SerialInterface.cpp // SerialInterface.cpp
// 2012 by Philip Rosedale for High Fidelity Inc. // 2012 by Philip Rosedale for High Fidelity Inc.
// //
// Read interface data from the gyros/accelerometer board using SerialUSB // Read interface data from the gyros/accelerometer Invensense board using the SerialUSB
//
// Channels are received in the following order (integer 0-4096 based on voltage 0-3.3v)
//
// 0 - AIN 15: Pitch Gyro (nodding your head 'yes')
// 1 - AIN 16: Yaw Gyro (shaking your head 'no')
// 2 - AIN 17: Roll Gyro (looking quizzical, tilting your head)
// 3 - AIN 18: Lateral acceleration (moving from side-to-side in front of your monitor)
// 4 - AIN 19: Up/Down acceleration (sitting up/ducking in front of your monitor)
// 5 - AIN 20: Forward/Back acceleration (Toward or away from your monitor)
// //
#include "SerialInterface.h" #include "SerialInterface.h"
@ -22,14 +13,8 @@
#include <string> #include <string>
#endif #endif
const int MAX_BUFFER = 255;
char serialBuffer[MAX_BUFFER];
int serialBufferPos = 0;
const int ZERO_OFFSET = 2048;
const short NO_READ_MAXIMUM_MSECS = 3000; const short NO_READ_MAXIMUM_MSECS = 3000;
const short SAMPLES_TO_DISCARD = 100; // Throw out the first few samples const int GRAVITY_SAMPLES = 60; // Use the first few samples to baseline values
const int GRAVITY_SAMPLES = 60; // Use the first samples to compute gravity vector
const bool USING_INVENSENSE_MPU9150 = 1; const bool USING_INVENSENSE_MPU9150 = 1;
@ -51,7 +36,7 @@ void SerialInterface::pair() {
char *serialPortname = new char[100]; char *serialPortname = new char[100];
sprintf(serialPortname, "/dev/%s", entry->d_name); sprintf(serialPortname, "/dev/%s", entry->d_name);
initializePort(serialPortname, 115200); initializePort(serialPortname);
delete [] serialPortname; delete [] serialPortname;
} }
@ -63,7 +48,7 @@ void SerialInterface::pair() {
} }
// connect to the serial port // connect to the serial port
void SerialInterface::initializePort(char* portname, int baud) { void SerialInterface::initializePort(char* portname) {
#ifdef __APPLE__ #ifdef __APPLE__
_serialDescriptor = open(portname, O_RDWR | O_NOCTTY | O_NDELAY); _serialDescriptor = open(portname, O_RDWR | O_NOCTTY | O_NDELAY);
@ -72,35 +57,20 @@ void SerialInterface::initializePort(char* portname, int baud) {
if (_serialDescriptor == -1) { if (_serialDescriptor == -1) {
printLog("Failed.\n"); printLog("Failed.\n");
return; return;
}
struct termios options;
tcgetattr(_serialDescriptor, &options);
switch(baud) {
case 9600: cfsetispeed(&options,B9600);
cfsetospeed(&options,B9600);
break;
case 19200: cfsetispeed(&options,B19200);
cfsetospeed(&options,B19200);
break;
case 38400: cfsetispeed(&options,B38400);
cfsetospeed(&options,B38400);
break;
case 115200: cfsetispeed(&options,B115200);
cfsetospeed(&options,B115200);
break;
default:cfsetispeed(&options,B9600);
cfsetospeed(&options,B9600);
break;
} }
options.c_cflag |= (CLOCAL | CREAD); struct termios options;
tcgetattr(_serialDescriptor, &options);
options.c_cflag |= (CLOCAL | CREAD | CS8);
options.c_cflag &= ~PARENB; options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB; options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE; options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
tcsetattr(_serialDescriptor, TCSANOW, &options); tcsetattr(_serialDescriptor, TCSANOW, &options);
cfsetispeed(&options,B115200);
cfsetospeed(&options,B115200);
if (USING_INVENSENSE_MPU9150) { if (USING_INVENSENSE_MPU9150) {
// block on invensense reads until there is data to read // block on invensense reads until there is data to read
int currentFlags = fcntl(_serialDescriptor, F_GETFL); int currentFlags = fcntl(_serialDescriptor, F_GETFL);
@ -140,11 +110,11 @@ void SerialInterface::renderLevels(int width, int height) {
const int LEVEL_CORNER_Y = 200; const int LEVEL_CORNER_Y = 200;
// Draw the numeric degree/sec values from the gyros // Draw the numeric degree/sec values from the gyros
sprintf(val, "Yaw %4.1f", _lastYawRate); sprintf(val, "Yaw %4.1f", getLastYawRate());
drawtext(LEVEL_CORNER_X, LEVEL_CORNER_Y, 0.10, 0, 1.0, 1, val, 0, 1, 0); drawtext(LEVEL_CORNER_X, LEVEL_CORNER_Y, 0.10, 0, 1.0, 1, val, 0, 1, 0);
sprintf(val, "Pitch %4.1f", _lastPitchRate); sprintf(val, "Pitch %4.1f", getLastPitchRate());
drawtext(LEVEL_CORNER_X, LEVEL_CORNER_Y + 15, 0.10, 0, 1.0, 1, val, 0, 1, 0); drawtext(LEVEL_CORNER_X, LEVEL_CORNER_Y + 15, 0.10, 0, 1.0, 1, val, 0, 1, 0);
sprintf(val, "Roll %4.1f", _lastRollRate); sprintf(val, "Roll %4.1f", getLastRollRate());
drawtext(LEVEL_CORNER_X, LEVEL_CORNER_Y + 30, 0.10, 0, 1.0, 1, val, 0, 1, 0); drawtext(LEVEL_CORNER_X, LEVEL_CORNER_Y + 30, 0.10, 0, 1.0, 1, val, 0, 1, 0);
sprintf(val, "X %4.3f", _lastAccelX); sprintf(val, "X %4.3f", _lastAccelX);
drawtext(LEVEL_CORNER_X, LEVEL_CORNER_Y + 45, 0.10, 0, 1.0, 1, val, 0, 1, 0); drawtext(LEVEL_CORNER_X, LEVEL_CORNER_Y + 45, 0.10, 0, 1.0, 1, val, 0, 1, 0);
@ -161,11 +131,11 @@ void SerialInterface::renderLevels(int width, int height) {
glBegin(GL_LINES); glBegin(GL_LINES);
// Gyro rates // Gyro rates
glVertex2f(LEVEL_CORNER_X + LEVEL_CENTER, LEVEL_CORNER_Y - 3); glVertex2f(LEVEL_CORNER_X + LEVEL_CENTER, LEVEL_CORNER_Y - 3);
glVertex2f(LEVEL_CORNER_X + LEVEL_CENTER + _lastYawRate, LEVEL_CORNER_Y - 3); glVertex2f(LEVEL_CORNER_X + LEVEL_CENTER + getLastYawRate(), LEVEL_CORNER_Y - 3);
glVertex2f(LEVEL_CORNER_X + LEVEL_CENTER, LEVEL_CORNER_Y + 12); glVertex2f(LEVEL_CORNER_X + LEVEL_CENTER, LEVEL_CORNER_Y + 12);
glVertex2f(LEVEL_CORNER_X + LEVEL_CENTER + _lastPitchRate, LEVEL_CORNER_Y + 12); glVertex2f(LEVEL_CORNER_X + LEVEL_CENTER + getLastPitchRate(), LEVEL_CORNER_Y + 12);
glVertex2f(LEVEL_CORNER_X + LEVEL_CENTER, LEVEL_CORNER_Y + 27); glVertex2f(LEVEL_CORNER_X + LEVEL_CENTER, LEVEL_CORNER_Y + 27);
glVertex2f(LEVEL_CORNER_X + LEVEL_CENTER + _lastRollRate, LEVEL_CORNER_Y + 27); glVertex2f(LEVEL_CORNER_X + LEVEL_CENTER + getLastRollRate(), LEVEL_CORNER_Y + 27);
// Acceleration // Acceleration
glVertex2f(LEVEL_CORNER_X + LEVEL_CENTER, LEVEL_CORNER_Y + 42); glVertex2f(LEVEL_CORNER_X + LEVEL_CENTER, LEVEL_CORNER_Y + 42);
glVertex2f(LEVEL_CORNER_X + LEVEL_CENTER + (int)((_lastAccelX - _gravity.x)* ACCEL_VIEW_SCALING), glVertex2f(LEVEL_CORNER_X + LEVEL_CENTER + (int)((_lastAccelX - _gravity.x)* ACCEL_VIEW_SCALING),
@ -232,26 +202,33 @@ void SerialInterface::readData() {
convertHexToInt(sensorBuffer + 30, pitchRate); convertHexToInt(sensorBuffer + 30, pitchRate);
// Convert the integer rates to floats // Convert the integer rates to floats
const float LSB_TO_DEGREES_PER_SECOND = 1.f / 16.4f; // From MPU-9150 register map, 2000 deg/sec. const float LSB_TO_DEGREES_PER_SECOND = 1.f / 16.4f; // From MPU-9150 register map, 2000 deg/sec.
const float PITCH_BIAS = 2.0; // Strangely, there is a small DC bias in the
// invensense pitch reading. Gravity?
_lastRollRate = ((float) rollRate) * LSB_TO_DEGREES_PER_SECOND; _lastRollRate = ((float) rollRate) * LSB_TO_DEGREES_PER_SECOND;
_lastYawRate = ((float) yawRate) * LSB_TO_DEGREES_PER_SECOND; _lastYawRate = ((float) yawRate) * LSB_TO_DEGREES_PER_SECOND;
_lastPitchRate = ((float) -pitchRate) * LSB_TO_DEGREES_PER_SECOND + PITCH_BIAS; _lastPitchRate = ((float) -pitchRate) * LSB_TO_DEGREES_PER_SECOND;
// Accumulate an initial reading for gravity // Accumulate a set of initial baseline readings for setting gravity
// Use a set of initial samples to compute gravity if (totalSamples == 0) {
if (totalSamples < GRAVITY_SAMPLES) { _averageGyroRates[0] = _lastRollRate;
_gravity.x += _lastAccelX; _averageGyroRates[1] = _lastYawRate;
_gravity.y += _lastAccelY; _averageGyroRates[2] = _lastPitchRate;
_gravity.z += _lastAccelZ; _gravity.x = _lastAccelX;
} _gravity.y = _lastAccelY;
if (totalSamples == GRAVITY_SAMPLES) { _gravity.z = _lastAccelZ;
_gravity /= (float) totalSamples;
printLog("Gravity: %f\n", glm::length(_gravity));
}
}
else if (totalSamples < GRAVITY_SAMPLES) {
_gravity = (1.f - 1.f/(float)GRAVITY_SAMPLES) * _gravity +
1.f/(float)GRAVITY_SAMPLES * glm::vec3(_lastAccelX, _lastAccelY, _lastAccelZ);
_averageGyroRates[0] = (1.f - 1.f/(float)GRAVITY_SAMPLES) * _averageGyroRates[0] +
1.f/(float)GRAVITY_SAMPLES * _lastRollRate;
_averageGyroRates[1] = (1.f - 1.f/(float)GRAVITY_SAMPLES) * _averageGyroRates[1] +
1.f/(float)GRAVITY_SAMPLES * _lastYawRate;
_averageGyroRates[2] = (1.f - 1.f/(float)GRAVITY_SAMPLES) * _averageGyroRates[2] +
1.f/(float)GRAVITY_SAMPLES * _lastPitchRate;
}
totalSamples++; totalSamples++;
} }
@ -269,14 +246,17 @@ void SerialInterface::readData() {
#endif #endif
} }
void SerialInterface::resetSerial() { void SerialInterface::resetAverages() {
#ifdef __APPLE__
active = false;
totalSamples = 0; totalSamples = 0;
_gravity = glm::vec3(0, 0, 0); _gravity = glm::vec3(0, 0, 0);
_averageGyroRates = glm::vec3(0, 0, 0);
}
void SerialInterface::resetSerial() {
#ifdef __APPLE__
resetAverages();
active = false;
gettimeofday(&lastGoodRead, NULL); gettimeofday(&lastGoodRead, NULL);
#endif #endif
} }

View file

@ -37,6 +37,8 @@ extern const bool USING_INVENSENSE_MPU9150;
class SerialInterface { class SerialInterface {
public: public:
SerialInterface() : active(false), SerialInterface() : active(false),
_gravity(0,0,0),
_averageGyroRates(0,0,0),
_lastAccelX(0), _lastAccelX(0),
_lastAccelY(0), _lastAccelY(0),
_lastAccelZ(0), _lastAccelZ(0),
@ -47,23 +49,25 @@ public:
void pair(); void pair();
void readData(); void readData();
float getLastYawRate() const { return _lastYawRate; } float getLastYawRate() const { return _lastYawRate - _averageGyroRates[1]; }
float getLastPitchRate() const { return _lastPitchRate; } float getLastPitchRate() const { return _lastPitchRate - _averageGyroRates[2]; }
float getLastRollRate() const { return _lastRollRate; } float getLastRollRate() const { return _lastRollRate - _averageGyroRates[0]; }
glm::vec3 getLastAcceleration() { return glm::vec3(_lastAccelX, _lastAccelY, _lastAccelZ); }; glm::vec3 getLastAcceleration() { return glm::vec3(_lastAccelX, _lastAccelY, _lastAccelZ); };
glm::vec3 getGravity() {return _gravity;}; glm::vec3 getGravity() {return _gravity;};
void renderLevels(int width, int height); void renderLevels(int width, int height);
void resetAverages();
bool active; bool active;
private: private:
void initializePort(char* portname, int baud); void initializePort(char* portname);
void resetSerial(); void resetSerial();
int _serialDescriptor; int _serialDescriptor;
int totalSamples; int totalSamples;
timeval lastGoodRead; timeval lastGoodRead;
glm::vec3 _gravity; glm::vec3 _gravity;
glm::vec3 _averageGyroRates;
float _lastAccelX; float _lastAccelX;
float _lastAccelY; float _lastAccelY;
float _lastAccelZ; float _lastAccelZ;

View file

@ -34,6 +34,7 @@ public:
_headRoll(0), _headRoll(0),
_headLeanSideways(0), _headLeanSideways(0),
_headLeanForward(0), _headLeanForward(0),
_audioLoudness(0),
_handState(0), _handState(0),
_cameraPosition(0,0,0), _cameraPosition(0,0,0),
_cameraDirection(0,0,0), _cameraDirection(0,0,0),