00001 /*!@file Devices/ssc.C Interface to a Serial Servo Controller */ 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: Jen Ng <jsn@usc.edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Devices/ssc.C $ 00035 // $Id: ssc.C 6990 2006-08-11 18:13:51Z rjpeters $ 00036 // 00037 00038 #include "Devices/ssc.H" 00039 00040 #include "Component/OptionManager.H" 00041 #include "Devices/Serial.H" 00042 00043 // ###################################################################### 00044 SSC::SSC(OptionManager& mgr, const std::string& descrName, 00045 const std::string& tagName, const char *defdev) : 00046 ModelComponent(mgr, descrName, tagName), 00047 itsPort(new Serial(mgr)) 00048 { 00049 // set a default config for our serial port: 00050 itsPort->configure(defdev, 9600, "8N1", false, false, 1); 00051 00052 // attach our port as a subcomponent: 00053 addSubComponent(itsPort); 00054 00055 // Initialize our internals: 00056 zero = new rutz::shared_ptr<NModelParam<float> >[SSCNUMSERVOS]; 00057 posmult = new rutz::shared_ptr<NModelParam<float> >[SSCNUMSERVOS]; 00058 negmult = new rutz::shared_ptr<NModelParam<float> >[SSCNUMSERVOS]; 00059 pos = new byte[SSCNUMSERVOS]; 00060 for (uint i = 0; i < SSCNUMSERVOS; i ++) 00061 { 00062 pos[i] = 127; char buf[20]; 00063 00064 sprintf(buf, "Zero%d", i); 00065 zero[i] = NModelParam<float>::make(buf, this, 0.0F); 00066 00067 sprintf(buf, "PosMult%d", i); 00068 posmult[i] = NModelParam<float>::make(buf, this, 1.0F); 00069 00070 sprintf(buf, "NegMult%d", i); 00071 negmult[i] = NModelParam<float>::make(buf, this, 1.0F); 00072 } 00073 } 00074 00075 // ###################################################################### 00076 SSC::~SSC() 00077 { } 00078 00079 // ###################################################################### 00080 bool SSC::move(const int servo, const float position) 00081 { return moveRaw(servo, calibToRaw(servo, position)); } 00082 00083 // ###################################################################### 00084 float SSC::getPosition(const int servo) const 00085 { 00086 if (servo < 0 || servo >= SSCNUMSERVOS) 00087 LFATAL("Invalid servo number %d", servo); 00088 return rawToCalib(servo, pos[servo]); 00089 } 00090 00091 // ###################################################################### 00092 void SSC::calibrate(const int servo, const byte neutralval, const byte minval, 00093 const byte maxval) 00094 { 00095 if (servo < 0 || servo >= SSCNUMSERVOS) 00096 LFATAL("Invalid servo number %d", servo); 00097 00098 zero[servo]->setVal(float(neutralval)); 00099 negmult[servo]->setVal(1.0F / (float(neutralval) - float(minval))); 00100 posmult[servo]->setVal(1.0F / (float(maxval) - float(neutralval))); 00101 } 00102 00103 // ###################################################################### 00104 bool SSC::moveRaw(const int servo, const byte rawpos) 00105 { 00106 // Command Buffer: 00107 // [0] is start character 00108 // [1] is which servo to move 00109 // [2] is position to move servo to (0 to MAX_POSITION) 00110 char command[3]; 00111 command[0] = 255; 00112 command[1] = servo; 00113 command[2] = rawpos; 00114 00115 // write command buffer 00116 if (itsPort->write(command, 3) == 3) 00117 { 00118 // update our position: 00119 pos[servo] = rawpos; 00120 return true; 00121 } 00122 else 00123 return false; 00124 } 00125 00126 // ###################################################################### 00127 bool SSC::moveRawHack(const int servo, const byte rawpos, const int port) 00128 { 00129 // Command Buffer: 00130 // [0] is start character 00131 // [1] is which servo to move 00132 // [2] is position to move servo to (0 to MAX_POSITION) 00133 char command[3]; 00134 command[0] = 255; 00135 command[1] = servo; 00136 command[2] = rawpos; 00137 int fd; 00138 if(port == 1) 00139 fd = open("/dev/ttyS0", O_RDWR); 00140 else 00141 fd = open("/dev/ttyS1", O_RDWR); 00142 if(fd==-1) LFATAL("open failed"); 00143 if(write(fd, command, 3)==-1){ 00144 perror("open"); 00145 LFATAL("write failed"); 00146 } 00147 close(fd); 00148 return true; 00149 } 00150 00151 // ###################################################################### 00152 byte SSC::getPositionRaw(const int servo) const 00153 { 00154 if (servo < 0 || servo >= SSCNUMSERVOS) 00155 LFATAL("Invalid servo number %d", servo); 00156 00157 return pos[servo]; 00158 } 00159 00160 // ###################################################################### 00161 float SSC::rawToCalib(const int servo, const byte rawpos) const 00162 { 00163 if (servo < 0 || servo >= SSCNUMSERVOS) 00164 LFATAL("Invalid servo number %d", servo); 00165 00166 float position; 00167 if (rawpos >= byte(zero[servo]->getVal())) 00168 position = (float(rawpos) - zero[servo]->getVal()) * 00169 posmult[servo]->getVal(); 00170 else 00171 position = (float(rawpos) - zero[servo]->getVal()) * 00172 negmult[servo]->getVal(); 00173 00174 if (position < -1.0F) position = -1.0F; 00175 else if (position > 1.0F) position = 1.0F; 00176 00177 return position; 00178 } 00179 00180 // ###################################################################### 00181 byte SSC::calibToRaw(const int servo, const float position) const 00182 { 00183 if (servo < 0 || servo >= SSCNUMSERVOS) 00184 LFATAL("Invalid servo number %d", servo); 00185 00186 if (position > 1.0F || position < -1.0F) 00187 LFATAL("Invalid position %f (range -1.0..1.0)", position); 00188 00189 int rawpos; 00190 if (position < 0.0F) 00191 rawpos = int(position / negmult[servo]->getVal() + 00192 zero[servo]->getVal() + 0.49999F); 00193 else 00194 rawpos = int(position / posmult[servo]->getVal() + 00195 zero[servo]->getVal() + 0.49999F); 00196 00197 if (rawpos < 0) rawpos = 0; else if (rawpos > 255) rawpos = 255; 00198 00199 return byte(rawpos); 00200 } 00201 00202 // ###################################################################### 00203 /* So things look consistent in everyone's emacs... */ 00204 /* Local Variables: */ 00205 /* indent-tabs-mode: nil */ 00206 /* End: */