00001 /*!@file BeoSub/BeoSubIMU.C class for interfacing with the IMU */ 00002 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2003 // 00005 // by the University of Southern California (USC) and the iLab at USC. // 00006 // See http://iLab.usc.edu for information about this project. // 00007 // //////////////////////////////////////////////////////////////////// // 00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00010 // in Visual Environments, and Applications'' by Christof Koch and // 00011 // Laurent Itti, California Institute of Technology, 2001 (patent // 00012 // pending; application number 09/912,225 filed July 23, 2001; see // 00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00014 // //////////////////////////////////////////////////////////////////// // 00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00016 // // 00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00018 // redistribute it and/or modify it under the terms of the GNU General // 00019 // Public License as published by the Free Software Foundation; either // 00020 // version 2 of the License, or (at your option) any later version. // 00021 // // 00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00025 // PURPOSE. See the GNU General Public License for more details. // 00026 // // 00027 // You should have received a copy of the GNU General Public License // 00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00030 // Boston, MA 02111-1307 USA. // 00031 // //////////////////////////////////////////////////////////////////// // 00032 // 00033 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/BeoSub/BeoSubIMU.C $ 00034 // $Id: BeoSubIMU.C 6990 2006-08-11 18:13:51Z rjpeters $ 00035 // 00036 00037 #include "BeoSub/BeoSubIMU.H" 00038 #include <string> 00039 00040 void *IMU_run(void *c); 00041 00042 // ###################################################################### 00043 void *IMU_run(void *c) 00044 { 00045 BeoSubIMU *d = (BeoSubIMU *) c; 00046 d ->run(); 00047 return NULL; 00048 } 00049 00050 // ###################################################################### 00051 BeoSubIMUListener::~BeoSubIMUListener() 00052 { } 00053 00054 // ###################################################################### 00055 BeoSubIMU::BeoSubIMU(OptionManager& mgr, const std::string& descrName, 00056 const std::string& tagName, const char *dev) : 00057 ModelComponent(mgr, descrName, tagName), 00058 itsSerial(new Serial(mgr, descrName+" Serial Port", tagName+"SerialPort")), 00059 itsKeepgoing(true) 00060 { 00061 itsSerial->configure(dev, 115200, "8N1", false, true, 0); 00062 addSubComponent(itsSerial); 00063 pthread_mutex_init(&itsLock, NULL); 00064 } 00065 00066 // ###################################################################### 00067 void BeoSubIMU::start2() 00068 { pthread_create(&itsRunner, NULL, &IMU_run, (void *) this); } 00069 00070 // ###################################################################### 00071 void BeoSubIMU::stop1() 00072 { 00073 itsKeepgoing = false; 00074 usleep(300000); // make sure thread has exited 00075 } 00076 00077 // ###################################################################### 00078 void BeoSubIMU::setListener(rutz::shared_ptr<BeoSubIMUListener> listener) 00079 { itsListener = listener; } 00080 00081 // ###################################################################### 00082 BeoSubIMU::~BeoSubIMU() 00083 { 00084 pthread_mutex_destroy(&itsLock); 00085 } 00086 00087 // ###################################################################### 00088 void BeoSubIMU::run() 00089 { 00090 while(itsKeepgoing) 00091 { 00092 const int psize = 22; 00093 unsigned char packet[psize]; 00094 packet[0] = 0x7F; packet[1] = 0xFF; 00095 int checksum; 00096 00097 do 00098 { 00099 // initialize variables: 00100 int count = 2; checksum = 0x7FFF; 00101 bool tagFound = false, FFFound = false; 00102 00103 while (count < psize) 00104 { 00105 // read one byte from serial port: 00106 unsigned char c; int size = itsSerial->read(&c, 1); 00107 if (size != 1) { PLERROR("Serial port read error"); continue; } 00108 00109 // if we have already found the tag, just fill the packet in: 00110 if (tagFound) 00111 { 00112 packet[count] = c; 00113 if (count % 2 == 0) checksum += int(c); 00114 else checksum += ((int(c)) << (sizeof(char)*8)); 00115 ++ count; 00116 } 00117 00118 // finding the first byte of the tag: 00119 if (c == 0xFF) FFFound = true; 00120 00121 // trigger tag found when a complete tag is detected: 00122 if (FFFound && c == 0x7F) tagFound = true; 00123 } 00124 } while ((checksum & 0x0000FFFF)); // exit iff checksum correct 00125 00126 // get the data: 00127 pthread_mutex_lock(&itsLock); 00128 itsXaccel = accelConvert((packet[5] << 8) + packet[4]); 00129 itsYaccel = accelConvert((packet[9] << 8) + packet[8]); 00130 itsZaccel = accelConvert((packet[13] << 8) + packet[12]); 00131 itsXvel = rateConvert((packet[7] << 8) + packet[6]); 00132 itsYvel = rateConvert((packet[11] << 8) + packet[10]); 00133 itsZvel = rateConvert((packet[15] << 8) + packet[14]); 00134 00135 // if we have a listener, let's notify it: 00136 if (itsListener.is_valid()) 00137 itsListener->newData(itsXaccel, itsYaccel, itsZaccel, 00138 itsXvel, itsYvel, itsZvel); 00139 pthread_mutex_unlock(&itsLock); 00140 } 00141 00142 pthread_exit(0); 00143 } 00144 00145 // ###################################################################### 00146 float BeoSubIMU::accelConvert(int data) 00147 { 00148 if (data > 0x7FFF) 00149 { 00150 int temp = (((~data)+1) & 0x0000FFFF); 00151 return -temp / 326.3F; 00152 } 00153 else return data / 326.3F; // scale factor 00154 } 00155 00156 // ###################################################################### 00157 float BeoSubIMU::rateConvert(int data) 00158 { 00159 if (data > 0x7FFF) 00160 { 00161 int temp = (((~data)+1) & 0x0000FFFF); // 2's complement 00162 return -temp / 100.0F; 00163 } 00164 else return data / 100.0F; // scale factor 00165 } 00166 00167 // ###################################################################### 00168 float BeoSubIMU::getXaccel() 00169 { 00170 pthread_mutex_lock(&itsLock); 00171 const float ret = itsXaccel; 00172 pthread_mutex_unlock(&itsLock); 00173 return ret; 00174 } 00175 00176 // ###################################################################### 00177 float BeoSubIMU::getYaccel() 00178 { 00179 pthread_mutex_lock(&itsLock); 00180 const float ret = itsYaccel; 00181 pthread_mutex_unlock(&itsLock); 00182 return ret; 00183 } 00184 00185 // ###################################################################### 00186 float BeoSubIMU::getZaccel() 00187 { 00188 pthread_mutex_lock(&itsLock); 00189 const float ret = itsZaccel; 00190 pthread_mutex_unlock(&itsLock); 00191 return ret; 00192 } 00193 00194 // ###################################################################### 00195 Angle BeoSubIMU::getXvel() 00196 { 00197 pthread_mutex_lock(&itsLock); 00198 const Angle ret = itsXvel; 00199 pthread_mutex_unlock(&itsLock); 00200 return ret; 00201 } 00202 00203 // ###################################################################### 00204 Angle BeoSubIMU::getYvel() 00205 { 00206 pthread_mutex_lock(&itsLock); 00207 const Angle ret = itsYvel; 00208 pthread_mutex_unlock(&itsLock); 00209 return ret; 00210 } 00211 00212 // ###################################################################### 00213 Angle BeoSubIMU::getZvel() 00214 { 00215 pthread_mutex_lock(&itsLock); 00216 const Angle ret = itsZvel; 00217 pthread_mutex_unlock(&itsLock); 00218 return ret; 00219 } 00220 00221 // ###################################################################### 00222 /* So things look consistent in everyone's emacs... */ 00223 /* Local Variables: */ 00224 /* indent-tabs-mode: nil */ 00225 /* End: */