tracker.cpp

00001 
00002 /* Copyright (c) 2006, Dustin Wueest <wueest@dustin.ch> 
00003    Copyright (c) 2006-2007, Stefan Eilemann <eile@equalizergraphics.com>
00004  *
00005  * This library is free software; you can redistribute it and/or modify it under
00006  * the terms of the GNU Lesser General Public License version 2.1 as published
00007  * by the Free Software Foundation.
00008  *  
00009  * This library is distributed in the hope that it will be useful, but WITHOUT
00010  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00011  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
00012  * details.
00013  * 
00014  * You should have received a copy of the GNU Lesser General Public License
00015  * along with this library; if not, write to the Free Software Foundation, Inc.,
00016  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
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    // configure serial port
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    // tell the tracker what kind of data to prepare
00102    int k = write( _fd, COMMAND_POS_ANG, 1 ); //take data
00103    if( k==-1 )
00104       EQERROR << "Write error: " << strerror( errno ) << endl;
00105 
00106    usleep( 10000 ); //give enough time for initializing
00107    
00108    if( _update( )) //try an update to see if it works
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 ); // send data
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    // 32640 is 360 degrees (2pi) -> scale is 1/5194.81734
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    // highest value for y and z position of the tracker sensor is 32639,
00164    // after that it switches back to zero (and vice versa if descending values).
00165    pos.x() = ypos;
00166    if( pos.x() > 16320 )             //32640 / 2 = 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; // scale to meter
00176 
00177    // position and rotation are stored in transformation matrix
00178    // and matrix is scaled to the application's units
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     // M = M_world_emitter * M_emitter_sensor * M_sensor_object
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       // wait for data
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       // try to read remaining bytes, returns # of read bytes
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 }
Generated on Mon Aug 10 18:58:41 2009 for Equalizer 0.9 by  doxygen 1.5.8