00001 /*!@file Devices/BeeStemTiny.C Simple interface to beestem */ 00002 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the // 00005 // 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 // Primary maintainer for this file: Lior Elazary <elazary@usc.edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Devices/BeeStemTiny.C $ 00035 // $Id: BeeStemTiny.C 10794 2009-02-08 06:21:09Z itti $ 00036 // 00037 00038 #include "Devices/BeeStemTiny.H" 00039 00040 #include "Component/OptionManager.H" 00041 #include "Devices/Serial.H" 00042 #include <string> 00043 00044 #define BS_CMD_DELAY 5000000 00045 00046 // ###################################################################### 00047 BeeStemTiny::BeeStemTiny(OptionManager& mgr, const std::string& descrName, 00048 const std::string& tagName, const char *defdev, const char *defdev2) : 00049 ModelComponent(mgr, descrName, tagName), 00050 itsPort(new Serial(mgr)), 00051 itsCompassPort(new Serial(mgr)) 00052 { 00053 00054 00055 // set a default config for our serial port: 00056 itsPort->configure(defdev, 38400, "8N1", false, false, 1); 00057 00058 itsCompassPort->configure(defdev2, 2400, "8N1", false, false, 1); 00059 00060 // attach our port as a subcomponent: 00061 addSubComponent(itsPort); 00062 addSubComponent(itsCompassPort); 00063 00064 for (int i=0; i<5; i++) 00065 itsLastMotorCmd[i] = 0; 00066 00067 00068 pthread_mutex_init(&itsSerialLock, NULL); 00069 } 00070 00071 // ###################################################################### 00072 BeeStemTiny::~BeeStemTiny() 00073 { 00074 pthread_mutex_destroy(&itsSerialLock); 00075 } 00076 00077 // ###################################################################### 00078 //The crappyCompass functionality can map crappy compass values to real headings as long as the crappy input is consistent. 00079 // It does this by running a calibration routined which reads in as many value as possible and stores them in a 00080 // vector. Then, when a user asks the crappyCompass class for a real heading, they can pass in a crappy value, and 00081 // the BeeStem will map it to a point in its crappy vector, returning the index. 00082 //Just make sure to start the calibration at a value that doesn't get ever get crappy. 00083 //A better way to do this is to prompts for user input 00084 bool BeeStemTiny::calibrateCrappyCompass() { 00085 00086 00087 int starting_point; 00088 char sensor_reports[3]; 00089 char cmd = 102; 00090 00091 //char* values = NULL; 00092 pthread_mutex_lock(&itsSerialLock); 00093 itsCompassPort->write(&cmd, 1); 00094 pthread_mutex_unlock(&itsSerialLock); 00095 00096 if( itsCompassPort->read(sensor_reports, 3) != 3 ) { 00097 return false; 00098 } 00099 00100 //Get our starting point 00101 starting_point = sensor_reports[0]; 00102 00103 return true; 00104 00105 } 00106 00107 00108 // ###################################################################### 00109 bool BeeStemTiny::setThrusters(int &m1, int &m2, int &m3, 00110 int &m4, int &m5) 00111 { 00112 // Command Buffer: 00113 // [0] is start character 00114 // [1..5] is m1 m5 00115 00116 pthread_mutex_lock(&itsSerialLock); 00117 00118 if (m1 > MOTOR_MAX) m1 = MOTOR_MAX; if (m1 < -MOTOR_MAX) m1 = -MOTOR_MAX; 00119 if (m2 > MOTOR_MAX) m2 = MOTOR_MAX; if (m2 < -MOTOR_MAX) m2 = -MOTOR_MAX; 00120 if (m3 > MOTOR_MAX) m3 = MOTOR_MAX; if (m3 < -MOTOR_MAX) m3 = -MOTOR_MAX; 00121 if (m4 > MOTOR_MAX) m4 = MOTOR_MAX; if (m4 < -MOTOR_MAX) m4 = -MOTOR_MAX; 00122 if (m5 > MOTOR_MAX) m5 = MOTOR_MAX; if (m5 < -MOTOR_MAX) m5 = -MOTOR_MAX; 00123 00124 00125 00126 if (abs(itsLastMotorCmd[0] - m1) > 60 && itsLastMotorCmd[0]*m1 < 0) m1 = 0; 00127 if (abs(itsLastMotorCmd[1] - m2) > 60 && itsLastMotorCmd[1]*m2 < 0) m2 = 0; 00128 if (abs(itsLastMotorCmd[2] - m3) > 60 && itsLastMotorCmd[2]*m3 < 0) m3 = 0; 00129 if (abs(itsLastMotorCmd[3] - m4) > 60 && itsLastMotorCmd[3]*m4 < 0) m4 = 0; 00130 if (abs(itsLastMotorCmd[4] - m5) > 60 && itsLastMotorCmd[4]*m5 < 0) m5 = 0; 00131 00132 //LINFO("%i %i %i %i %i", m1, m2, m3, m4, m5); 00133 00134 itsLastMotorCmd[0] = m1; 00135 itsLastMotorCmd[1] = m2; 00136 itsLastMotorCmd[2] = m3; 00137 itsLastMotorCmd[3] = m4; 00138 itsLastMotorCmd[4] = m5; 00139 00140 00141 00142 char command[6]; 00143 command[0] = 101; 00144 command[1] = (signed char)m1; 00145 command[2] = (signed char)m2; 00146 command[3] = (signed char)m3; 00147 command[4] = (signed char)m4; 00148 command[5] = (signed char)m5; 00149 00150 // LINFO("%i %i %i %i %i", 00151 // command[0], command[1], command[2], command[3], command[4], command[5]); 00152 00153 for(int i = 0; i<6; i++) { 00154 itsPort->write(&command[i], 1); 00155 //usleep(BS_CMD_DELAY); 00156 } 00157 00158 pthread_mutex_unlock(&itsSerialLock); 00159 00160 return true; 00161 00162 00163 /* 00164 // write command buffer 00165 if (itsPort->write(command, 6) == 6) 00166 return true; 00167 else 00168 return false;*/ 00169 } 00170 00171 // ###################################################################### 00172 bool BeeStemTiny::getSensors(int &heading, int &pitch, int &roll, int &ext_pressure, int &int_pressure) 00173 { 00174 00175 00176 //First let's handle incoming compass data (not actually related to the BeeStem 00177 //at this point, but whatever. 00178 float h,p,r; 00179 static std::string compassValues; 00180 char compassBuffer[50]; 00181 00182 //Read as many bytes from the serial buffer as are available 00183 int size = itsCompassPort->read(&compassBuffer, 50); 00184 00185 if (size > 0) //only update if we have any values 00186 { 00187 compassBuffer[size] = 0; 00188 compassValues+=std::string(compassBuffer); 00189 } 00190 00191 //Once we have at least 30 bytes we know that we have a frame, so we can parse it. 00192 if(compassValues.size() > 30) { 00193 // LINFO("COMPASS VALUES: %s", compassValues.c_str()); 00194 int frameBegin = compassValues.find('\n'); 00195 int frameEnd = compassValues.find('\n', frameBegin+1); 00196 std::string compassFrame = compassValues.substr(frameBegin, frameEnd-frameBegin); 00197 sscanf(compassValues.substr(frameBegin).c_str(), "\r%f,%f,%f", &h, &p, &r); 00198 00199 heading = (int)h; 00200 pitch = (int)p; 00201 roll = (int)r; 00202 00203 compassValues.clear(); 00204 } 00205 00206 00207 //Now we deal with the actual BeeStem 00208 // Command Buffer: 00209 // [0] is start character 00210 // [1..5] is the data 00211 pthread_mutex_lock(&itsSerialLock); 00212 char cmd = 102; 00213 unsigned char presBuff[10]; 00214 itsPort->write(&cmd, 1); 00215 int presSize = itsPort->read(presBuff, 10); 00216 00217 if(presSize == 4) { 00218 itsAvgDepth.push_back(((unsigned int)presBuff[2] | ((unsigned int)presBuff[3] << 8))); 00219 00220 if (itsAvgDepth.size() > 40) 00221 { 00222 long avg = 0; 00223 for(std::list<int>::iterator itr=itsAvgDepth.begin(); 00224 itr != itsAvgDepth.end(); ++itr) 00225 avg += *itr; 00226 itsAvgDepth.pop_front(); 00227 00228 ext_pressure = (unsigned int)(avg/itsAvgDepth.size()); 00229 } 00230 00231 //ext_pressure = ((unsigned int)presBuff[2] | ((unsigned int)presBuff[3] << 8)); 00232 } 00233 00234 int_pressure = ((unsigned int)presBuff[0] | ((unsigned int)presBuff[1] << 8)); 00235 00236 00237 // for(int i=0; i<presSize; i++) 00238 // LINFO("presBuff[%d] = %d", i, presBuff[i]); 00239 00240 /*if (presSize > 4) 00241 { 00242 unsigned char val = ((unsigned char)presBuff[3])-227; 00243 int_pressure = val; 00244 00245 itsAvgDepth.push_back((unsigned char)presBuff[4]); 00246 if (itsAvgDepth.size() > 40) 00247 { 00248 long avg = 0; 00249 for(std::list<int>::iterator itr=itsAvgDepth.begin(); 00250 itr != itsAvgDepth.end(); ++itr) 00251 avg += *itr; 00252 itsAvgDepth.pop_front(); 00253 00254 ext_pressure = (int)(avg/itsAvgDepth.size()); 00255 } 00256 }*/ 00257 //LINFO("Ext Pressure: %d, Int Pressure: %d, presSize %d\n", ext_pressure, int_pressure, presSize); 00258 pthread_mutex_unlock(&itsSerialLock); 00259 00260 00261 00262 return true; 00263 } 00264 00265 bool BeeStemTiny::setHeartBeat() 00266 { 00267 pthread_mutex_lock(&itsSerialLock); 00268 char cmd = 103; 00269 00270 // write command buffer 00271 bool ret = (itsPort->write(&cmd, 1) == 1); 00272 00273 pthread_mutex_unlock(&itsSerialLock); 00274 00275 return ret; 00276 00277 } 00278 00279 00280 00281 // ###################################################################### 00282 /* So things look consistent in everyone's emacs... */ 00283 /* Local Variables: */ 00284 /* indent-tabs-mode: nil */ 00285 /* End: */