00001 /* 00002 * Atomic6DOF.cc 00003 * 00004 * Created on: Feb 18, 2010 00005 * Author: uscr 00006 */ 00007 00008 #include "Atomic6DOF.h" 00009 00010 #include <cstdio> 00011 #include <cstring> 00012 #include <cstdlib> 00013 #include <cmath> 00014 #include <termio.h> 00015 #include <sys/fcntl.h> 00016 #include <sys/file.h> 00017 #include <unistd.h> 00018 00019 #define MAX_SERIAL_BUF_LENGTH 1024 00020 int serialCon; 00021 struct currentIMUData curIMUData; 00022 unsigned char serialBuf[MAX_SERIAL_BUF_LENGTH]; 00023 int serialBufLength = 0; 00024 00025 bool initializeAtomic6DOF() { 00026 00027 memset(serialBuf, 0, MAX_SERIAL_BUF_LENGTH); 00028 00029 if ((serialCon = open (SERIAL_PORT, O_RDWR | O_NOCTTY | O_NDELAY)) < 0) 00030 return false; 00031 00032 struct termios attr; 00033 00034 if (tcgetattr(serialCon, &attr) < 0) 00035 return false; 00036 00037 /* 8 bits + baud rate + local control */ 00038 attr.c_cflag = SERIAL_BAUD|CLOCAL|CREAD; 00039 attr.c_cflag &= ~CRTSCTS; 00040 00041 attr.c_iflag = IXOFF; 00042 attr.c_iflag |= ~( IGNBRK | BRKINT | ISTRIP | IGNCR | ICRNL | IXON | INLCR | PARMRK); 00043 attr.c_oflag = 0; 00044 attr.c_lflag = 0; 00045 /* set output and input baud rates */ 00046 cfsetospeed(&attr, SERIAL_BAUD); 00047 cfsetispeed(&attr, SERIAL_BAUD); 00048 if (tcsetattr(serialCon, TCSANOW, &attr) < 0) 00049 return false; 00050 00051 if (write(serialCon, "*#", 2) != 2) 00052 return false; 00053 00054 return true; 00055 00056 } 00057 00058 void shutdownAtomic6DOF() { 00059 close(serialCon); 00060 00061 } 00062 00063 bool isIMUDataReady() { 00064 00065 unsigned char buffer[801]; 00066 int numRead = read(serialCon, buffer, 800); 00067 00068 //if we didn't read anything then don't continue 00069 if (numRead < 1) 00070 return false; 00071 00072 //copy what we read into our long-term buffer 00073 memcpy(serialBuf + serialBufLength, buffer, numRead); 00074 serialBufLength += numRead; 00075 00076 //if we have more than two packets in our buffer, then 00077 // we should disregard our first ones and look at the last 00078 if (serialBufLength > 32) { 00079 int lastAPos = serialBufLength - 1; 00080 00081 //find the position of the last "Z" 00082 while (lastAPos >= 0 && serialBuf[lastAPos] != 'Z') {lastAPos--;} 00083 //find the start of the last complete packet 00084 while (lastAPos >= 0 && serialBuf[lastAPos] != 'A') {lastAPos--;} 00085 00086 unsigned char tempBuf[32]; 00087 serialBufLength -= lastAPos; 00088 if (serialBufLength <= 32) { 00089 memcpy (tempBuf, serialBuf + lastAPos, serialBufLength); 00090 memcpy (serialBuf, tempBuf, serialBufLength); 00091 memset (serialBuf + serialBufLength, 0, MAX_SERIAL_BUF_LENGTH - serialBufLength); 00092 } 00093 } 00094 00095 //if we still don't have enough to form a complete packet 00096 // or if our packet is bad, then don't continue 00097 if (serialBufLength < 16 || serialBuf[0] != 'A' || serialBuf[15] != 'Z') 00098 return false; 00099 00100 // printf("%02X %02X%02X %02X%02X %02X%02X %02X%02X %02X%02X %02X%02X %02X%02X %02X\n", 00101 // serialBuf[0], serialBuf[1], serialBuf[2], serialBuf[3], serialBuf[4], serialBuf[5], 00102 // serialBuf[6], serialBuf[7], serialBuf[8], serialBuf[9], serialBuf[10], serialBuf[11], 00103 // serialBuf[12], serialBuf[13], serialBuf[14], serialBuf[15]); 00104 //throw the data into the currentIMUData structure 00105 curIMUData.count = (double) (( ((serialBuf[1]&0x7F) << 8) | (serialBuf[2]&0xFF) ) & 0x7FFF); 00106 curIMUData.accel_x = (double) (( ((serialBuf[3]&0x3) << 8) | (serialBuf[4]&0xFF) ) & 0x3FF); 00107 curIMUData.accel_y = (double) (( ((serialBuf[5]&0x3) << 8) | (serialBuf[6]&0xFF) ) & 0x3FF); 00108 curIMUData.accel_z = (double) (( ((serialBuf[7]&0x3) << 8) | (serialBuf[8]&0xFF) ) & 0x3FF); 00109 curIMUData.gyro_pitch = (double) (( ((serialBuf[9]&0x3) << 8) | (serialBuf[10]&0xFF) ) & 0x3FF); 00110 curIMUData.gyro_roll = (double) (( ((serialBuf[11]&0x3) << 8) | (serialBuf[12]&0xFF) ) & 0x3FF); 00111 curIMUData.gyro_yaw = (double) (( ((serialBuf[13]&0x3) << 8) | (serialBuf[14]&0xFF) ) & 0x3FF); 00112 00113 //adjust the data (i.e., accel raw -> angle and gyro raw -> angular velocity) 00114 curIMUData.adj_accel_x = curIMUData.accel_x*X_ACCEL_COEFF - X_ACCEL_OFFSET; 00115 curIMUData.adj_accel_y = curIMUData.accel_y*Y_ACCEL_COEFF - Y_ACCEL_OFFSET; 00116 curIMUData.adj_accel_z = curIMUData.accel_z*Z_ACCEL_COEFF - Z_ACCEL_OFFSET; 00117 curIMUData.adj_gyro_pitch = curIMUData.gyro_pitch*GYRO_COEFF - GYRO_OFFSET; 00118 curIMUData.adj_gyro_roll = curIMUData.gyro_roll*GYRO_COEFF - GYRO_OFFSET; 00119 curIMUData.adj_gyro_yaw = curIMUData.gyro_yaw*GYRO_COEFF - GYRO_OFFSET; 00120 curIMUData.adj_accel_pitch = asin(curIMUData.adj_accel_y)*RAD_TO_DEG; 00121 if (isnan(curIMUData.adj_accel_pitch)) 00122 curIMUData.adj_accel_pitch = (curIMUData.adj_accel_y < 0 ? -1 : 1) * 90.0; 00123 curIMUData.adj_accel_roll = asin(curIMUData.adj_accel_x)*RAD_TO_DEG; 00124 if (isnan(curIMUData.adj_accel_roll)) 00125 curIMUData.adj_accel_roll = (curIMUData.adj_accel_x < 0 ? -1 : 1) * 90.0; 00126 00127 00128 //shift the data over in the long-term buffer so we get new data next time 00129 serialBufLength -= 16; 00130 if (serialBufLength > 0) { 00131 for (int i = 0; i < serialBufLength; i++) 00132 serialBuf[i] = serialBuf[i + 16]; 00133 } 00134 00135 //we need this because of the occasional bad packet :*( 00136 memset(serialBuf + serialBufLength, 0, MAX_SERIAL_BUF_LENGTH - serialBufLength); 00137 00138 return true; 00139 }