tracker.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "tracker.h"
00020 #include <iostream>
00021 #include <fcntl.h>
00022 #include <errno.h>
00023
00024 #ifndef WIN32
00025 # include <sys/select.h>
00026 # include <sys/termios.h>
00027 #endif
00028
00029 #define COMMAND_POS_ANG "Y"
00030 #define COMMAND_POINT "B"
00031
00032 using namespace std;
00033
00034 namespace eqPly
00035 {
00036 Tracker::Tracker()
00037 : _running( false ),
00038 _worldToEmitter( eq::Matrix4f::IDENTITY ),
00039 _sensorToObject( eq::Matrix4f::IDENTITY )
00040 {
00041 }
00042
00043 bool Tracker::init( const std::string& port )
00044 {
00045 #ifdef WIN32
00046 return false;
00047 #else
00048 if( _running )
00049 {
00050 EQERROR << "Duplicate tracker initialisation" << endl;
00051 return false;
00052 }
00053
00054 _fd = open( port.c_str(), O_RDWR | O_EXCL );
00055 if( _fd < 0 )
00056 {
00057 EQERROR << "Failed to open " << port << ": " << strerror( errno ) << endl;
00058 return false;
00059 }
00060
00061
00062 struct termios termio;
00063 if( tcgetattr( _fd, &termio ) != 0 )
00064 {
00065 EQERROR << "tcgetattr failed: " << strerror( errno ) << endl;
00066 close( _fd );
00067 return false;
00068 }
00069
00070 termio.c_cflag &= ~(CSIZE|PARENB|CSTOPB|PARODD|HUPCL|CRTSCTS);
00071 termio.c_cflag |= CS8|CREAD|CLOCAL;
00072 termio.c_iflag &= ~(IXON|IXANY|IMAXBEL|BRKINT|IGNPAR|PARMRK|
00073 INPCK|ISTRIP|INLCR|IGNCR|ICRNL);
00074 #ifdef IUCLC
00075 termio.c_iflag &= ~IUCLC;
00076 #endif
00077
00078 termio.c_iflag |= IXOFF|IGNBRK;
00079 termio.c_oflag &= ~(OPOST|OCRNL|ONLCR|ONOCR|ONLRET|OFILL|OFDEL);
00080 #ifdef OLCUC
00081 termio.c_oflag &= ~OLCUC;
00082 #endif
00083
00084 termio.c_lflag &= ~(ISIG|ICANON|IEXTEN|ECHO|ECHOE|ECHOK|ECHONL|NOFLSH|
00085 TOSTOP|ECHOPRT|ECHOCTL|ECHOKE);
00086 #ifdef XCASE
00087 termio.c_lflag &= ~XCASE;
00088 #endif
00089
00090 cfsetspeed( &termio, B115200 );
00091 termio.c_cc[VMIN] = 26;
00092 termio.c_cc[VTIME] = 1;
00093
00094 if( tcsetattr( _fd, TCSANOW, &termio ) != 0)
00095 {
00096 EQERROR << "tcsetattr failed: " << strerror( errno ) << endl;
00097 close( _fd );
00098 return false;
00099 }
00100
00101
00102 int k = write( _fd, COMMAND_POS_ANG, 1 );
00103 if( k==-1 )
00104 EQERROR << "Write error: " << strerror( errno ) << endl;
00105
00106 usleep( 10000 );
00107
00108 if( _update( ))
00109 _running = true;
00110
00111 return _running;
00112 #endif
00113 }
00114
00115 bool Tracker::update()
00116 {
00117 if( !_running )
00118 {
00119 EQERROR << "Update error, tracker not running" << endl;
00120 return false;
00121 }
00122 else
00123 {
00124 bool b = _update();
00125 return b;
00126 }
00127 }
00128
00129 bool Tracker::_update()
00130 {
00131 #ifdef WIN32
00132 return false;
00133 #else
00134 const ssize_t wrote = write( _fd, COMMAND_POINT, 1 );
00135 if( wrote==-1 )
00136 {
00137 EQERROR << "Write error: " << strerror( errno ) << endl;
00138 return false;
00139 }
00140
00141 unsigned char buffer[12];
00142 if( !_read( buffer, 12, 500000 ))
00143 {
00144 EQERROR << "Read error" << endl;
00145 return false;
00146 }
00147
00148 const short xpos = (buffer[1]<<8 | buffer[0]);
00149 const short ypos = (buffer[3]<<8 | buffer[2]);
00150 const short zpos = (buffer[5]<<8 | buffer[4]);
00151
00152 const short head = (buffer[7]<<8 | buffer[6]);
00153 const short pitch = (buffer[9]<<8 | buffer[8]);
00154 const short roll = (buffer[11]<<8 | buffer[10]);
00155
00156
00157 const eq::Vector3f hpr( head / -5194.81734f + M_PI,
00158 pitch / -5194.81734f + 2.0f * M_PI,
00159 roll / -5194.81734f + 2.0f * M_PI );
00160
00161 eq::Vector3f pos;
00162
00163
00164
00165 pos.x() = ypos;
00166 if( pos.x() > 16320 )
00167 pos.x() -= 32640;
00168
00169 pos.y() = zpos;
00170 if( pos.y() > 16320 )
00171 pos.y() -= 32640;
00172
00173 pos.z() = xpos;
00174
00175 pos /= 18000.f;
00176
00177
00178
00179 _matrix = eq::Matrix4f::IDENTITY;
00180 _matrix.rotate_x( hpr.x() );
00181 _matrix.rotate_y( hpr.y() );
00182 _matrix.rotate_z( hpr.z() );
00183 _matrix.set_translation( pos );
00184
00185 EQINFO << "Tracker pos " << pos << " hpr " << hpr << " = " << _matrix;
00186
00187
00188 _matrix = _worldToEmitter * _matrix * _sensorToObject;
00189
00190 EQINFO << "Tracker matrix " << _matrix;
00191
00192 return true;
00193 #endif
00194 }
00195
00196 bool Tracker::_read( unsigned char* buffer, const size_t size,
00197 const unsigned long int timeout )
00198 {
00199 #ifdef WIN32
00200 return false;
00201 #else
00202 size_t remaining = size;
00203 struct timeval tv;
00204
00205 tv.tv_sec = timeout / 1000000;
00206 tv.tv_usec = timeout % 1000000;
00207
00208 while( remaining > 0 )
00209 {
00210
00211 fd_set readfds;
00212 FD_ZERO( &readfds );
00213 FD_SET( _fd, &readfds );
00214
00215 const int errCode = select( _fd+1, &readfds, 0, 0, &tv );
00216 if( errCode == 0 )
00217 {
00218 EQERROR << "Error: no data from tracker" << endl;
00219 return false;
00220 }
00221 if( errCode == -1 )
00222 {
00223 EQERROR << "Select error: " << strerror( errno ) << endl;
00224 return false;
00225 }
00226
00227
00228 const ssize_t received = read( _fd, &buffer[size-remaining], remaining );
00229 if( received == -1 )
00230 {
00231 EQERROR << "Read error: " << strerror( errno ) << endl;
00232 return false;
00233 }
00234
00235 EQASSERT( remaining >= (size_t)received );
00236 remaining -= received;
00237 }
00238 return true;
00239 #endif
00240 }
00241 }