00001 /*!@file Devices/BeoMonkey.C Interfaces to robot monkey head, derived from 00002 BeoChip which is an to interface Brian Hudson's BeoChip .*/ 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: Laurent Itti <itti@usc.edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Devices/BeoMonkey.C $ 00035 // $Id: BeoMonkey.C 6795 2006-06-29 20:45:32Z rjpeters $ 00036 // 00037 00038 #include "Devices/BeoMonkey.H" 00039 #include "Component/OptionManager.H" 00040 #include "Util/Assert.H" 00041 #include "rutz/compat_snprintf.h" 00042 00043 // ###################################################################### 00044 BeoMonkey::BeoMonkey(OptionManager& mgr, const std::string& descrName, 00045 const std::string& tagName) : BeoChip(mgr,descrName,tagName) 00046 { 00047 //setup Servos 00048 calibrateServo(H_EYE,H_EYE_MID,H_EYE_MIN,H_EYE_MAX); 00049 calibrateServo(V_EYE,V_EYE_MID,V_EYE_MIN,V_EYE_MAX); 00050 calibrateServo(H_HEAD,H_HEAD_MID,H_HEAD_MIN,H_HEAD_MAX); 00051 calibrateServo(V_HEAD,V_HEAD_MID,V_HEAD_MIN,V_HEAD_MAX); 00052 calibrateServo(EYELIDS,EYELIDS_MID,EYELIDS_MIN,EYELIDS_MAX); 00053 calibrateServo(EYEBROW,EYEBROW_MID,EYEBROW_MIN,EYEBROW_MAX); 00054 calibrateServo(MOUTH,MOUTH_MID,MOUTH_MIN,MOUTH_MAX); 00055 calibrateServo(MUZZLE,MUZZLE_MID,MUZZLE_MIN,MUZZLE_MAX); 00056 } 00057 00058 00059 // ###################################################################### 00060 void BeoMonkey::setHEyePos(const float position, 00061 const int velocity) 00062 { 00063 setServo(H_EYE,position,velocity); 00064 } 00065 // ###################################################################### 00066 std::deque<Position> BeoMonkey::getPathHEyePos(const float position, 00067 const int velocity, 00068 const float startpos) 00069 { 00070 return getPathServo(H_EYE,position,velocity,startpos); 00071 } 00072 00073 // ###################################################################### 00074 void BeoMonkey::setHEyePosRel(const float offset, 00075 const int velocity) 00076 { 00077 setHEyePos(getServo(H_EYE)+offset,velocity); 00078 00079 } 00080 00081 // ###################################################################### 00082 void BeoMonkey::setVEyePos(const float position, 00083 const int velocity) 00084 { 00085 setServo(V_EYE,position,velocity); 00086 } 00087 00088 // ###################################################################### 00089 std::deque<Position> BeoMonkey::getPathVEyePos(const float position, 00090 const int velocity, 00091 const float startpos) 00092 { 00093 return getPathServo(V_EYE,position,velocity,startpos); 00094 } 00095 00096 // ###################################################################### 00097 void BeoMonkey::setVEyePosRel(const float offset, 00098 const int velocity) 00099 { 00100 setVEyePos(getServo(V_EYE)+offset,velocity); 00101 } 00102 00103 // ###################################################################### 00104 void BeoMonkey::setEyeLidsPos(const float position, 00105 const int velocity) 00106 { 00107 setServo(EYELIDS,position,velocity); 00108 } 00109 00110 // ###################################################################### 00111 std::deque<Position> BeoMonkey::getPathEyeLidsPos(const float position, 00112 const int velocity 00113 , 00114 const float startpos) 00115 { 00116 return getPathServo(EYELIDS,position,velocity,startpos); 00117 } 00118 00119 // ###################################################################### 00120 void BeoMonkey::setEyeLidsRel(const float offset, 00121 const int velocity) 00122 { 00123 setEyeLidsPos(getServo(EYELIDS)+offset,velocity); 00124 } 00125 00126 // ###################################################################### 00127 void BeoMonkey::setEyeBrowPos(const float position, 00128 const int velocity) 00129 { 00130 setServo(EYEBROW,position,velocity); 00131 } 00132 00133 // ###################################################################### 00134 std::deque<Position> BeoMonkey::getPathEyeBrowPos(const float position, 00135 const int velocity, 00136 const float startpos) 00137 { 00138 return getPathServo(EYEBROW,position,velocity,startpos); 00139 } 00140 00141 // ###################################################################### 00142 void BeoMonkey::setEyeBrowPosRel(const float offset, 00143 const int velocity) 00144 { 00145 setEyeBrowPos(getServo(EYEBROW)+offset,velocity); 00146 } 00147 00148 // ###################################################################### 00149 void BeoMonkey::setMouthPos(const float position, 00150 const int velocity) 00151 { 00152 setServo(MOUTH,position,velocity); 00153 } 00154 00155 // ###################################################################### 00156 std::deque<Position> BeoMonkey::getPathMouthPos(const float position, 00157 const int velocity, 00158 const float startpos) 00159 { 00160 return getPathServo(MOUTH,position,velocity,startpos); 00161 } 00162 00163 // ###################################################################### 00164 void BeoMonkey::setMouthPosRel(const float offset, 00165 const int velocity) 00166 { 00167 setMouthPos(getServo(MOUTH)+offset,velocity); 00168 } 00169 00170 // ###################################################################### 00171 void BeoMonkey::setMuzzlePos(const float position, 00172 const int velocity) 00173 { 00174 setServo(MUZZLE,position,velocity); 00175 } 00176 00177 // ###################################################################### 00178 std::deque<Position> BeoMonkey::getPathMuzzlePos(const float position, 00179 const int velocity, 00180 const float startpos) 00181 { 00182 return getPathServo(MUZZLE,position,velocity,startpos); 00183 } 00184 00185 // ###################################################################### 00186 void BeoMonkey::setMuzzlePosRel(const float offset, 00187 const int velocity) 00188 { 00189 setMuzzlePos(getServo(MUZZLE)+offset,velocity); 00190 } 00191 00192 // ###################################################################### 00193 void BeoMonkey::setHHeadPos(const float position, 00194 const int velocity) 00195 { 00196 setServo(H_HEAD,position,velocity); 00197 } 00198 // ###################################################################### 00199 std::deque<Position> BeoMonkey::getPathHHeadPos(const float position, 00200 const int velocity, 00201 const float startpos) 00202 { 00203 return getPathServo(H_HEAD,position,velocity,startpos); 00204 } 00205 00206 // ###################################################################### 00207 void BeoMonkey::setHHeadPosRel(const float offset, 00208 const int velocity) 00209 { 00210 setHHeadPos(getServo(H_HEAD)+offset,velocity); 00211 } 00212 00213 00214 00215 // ###################################################################### 00216 void BeoMonkey::setVHeadPos(const float position, 00217 const int velocity) 00218 { 00219 setServo(V_HEAD,position,velocity); 00220 } 00221 00222 // ###################################################################### 00223 std::deque<Position> BeoMonkey::getPathVHeadPos(const float position, 00224 const int velocity, 00225 const float startpos) 00226 { 00227 return getPathServo(V_HEAD,position,velocity,startpos); 00228 } 00229 00230 // ###################################################################### 00231 void BeoMonkey::setVHeadPosRel(const float offset, 00232 const int velocity) 00233 { 00234 setVHeadPos(getServo(V_HEAD)+offset,velocity); 00235 } 00236 00237 // ###################################################################### 00238 void BeoMonkey::start2() 00239 { 00240 initializeServos(); 00241 } 00242 00243 // ###################################################################### 00244 void BeoMonkey::initializeServos() 00245 { 00246 LINFO("Initializing Servos..."); 00247 //set servos to center 00248 setServo(H_EYE,0.0F,1); 00249 setServo(V_EYE,0.0F,1); 00250 setServo(H_HEAD,0.0F,1); 00251 setServo(V_HEAD,0.0F,1); 00252 setServo(EYELIDS,0.0F,1); 00253 setServo(EYEBROW,0.0F,1); 00254 setServo(MOUTH,0.0F,1); 00255 setServo(MUZZLE,0.0F,1); 00256 nextTimeStep(); 00257 LINFO("Initialization Complete"); 00258 } 00259 00260 //set the servos and add blend to the current movement que 00261 //####################################################################### 00262 void BeoMonkey::setServo(const byte servo, const float position, 00263 const int velocity) 00264 { 00265 addSequence(getPathServo(servo,position,velocity)); 00266 } 00267 00268 //return the path created from setting a servo to a particular pos and vel 00269 //####################################################################### 00270 std::deque<Position> BeoMonkey::getPathServo(const byte servo, 00271 const float position, 00272 const int velocity, 00273 const float startpos) 00274 00275 { 00276 std::deque<Position> pos; 00277 float cur; 00278 if (startpos > -999) 00279 cur = startpos; 00280 else 00281 { 00282 cur = isServoInQue(servo); //shhould switch this burdain to add toend? 00283 if (cur < -2) 00284 cur = getServo(servo); 00285 } 00286 00287 float step = (position - cur)/(float)velocity; 00288 for (int ii = 1; ii <= velocity; ii++) 00289 { 00290 Position p(servo,cur+step*ii,ii); 00291 pos.push_back(p); 00292 } 00293 //should add a function to change the velocty profile so its smooth 00294 return pos; 00295 } 00296 00297 //add sequence and blend with current movement que 00298 //####################################################################### 00299 void BeoMonkey::addSequence(const byte servo, 00300 std::deque<float> sequence) 00301 { 00302 addSequence(getSequence(servo,sequence)); 00303 } 00304 00305 //add sequencey and blend to current movement que 00306 //####################################################################### 00307 void BeoMonkey::addSequence(std::deque<Position> element) 00308 { 00309 moveQue = blend(moveQue,element); 00310 } 00311 00312 //add sequencey to the end of the movement que 00313 //####################################################################### 00314 void BeoMonkey::addEndSequence(std::deque<Position> pos) 00315 { 00316 std::deque<Position>::iterator ii; 00317 if (moveQue.empty()) 00318 moveQue = pos; 00319 else 00320 { 00321 for (ii = pos.begin(); ii != pos.end(); ii++) 00322 ii->time+= moveQue.back().time; 00323 moveQue.insert(moveQue.end(),pos.begin(),pos.end()); 00324 } 00325 } 00326 00327 //add sequencey to the end of the movement que 00328 //####################################################################### 00329 std::deque<Position> BeoMonkey::addEndSequence(std::deque<Position> seq, 00330 std::deque<Position> pos) 00331 { 00332 std::deque<Position>::iterator ii; 00333 if (seq.empty()) 00334 seq = pos; 00335 else 00336 { 00337 for (ii = pos.begin(); ii != pos.end(); ii++) 00338 ii->time+= seq.back().time; 00339 seq.insert(seq.end(),pos.begin(),pos.end()); 00340 } 00341 return seq; 00342 } 00343 00344 //create a position sequence from a deque of servo positions 00345 //####################################################################### 00346 std::deque<Position> BeoMonkey::getSequence(const byte servo, 00347 std::deque<float> sequence) 00348 { 00349 std::deque<Position> out; 00350 std::deque<float>::iterator ii; 00351 int time = 1; 00352 for(ii = sequence.begin(); ii != sequence.end(); ii++) 00353 { 00354 Position p(servo,*(ii),time); 00355 out.push_back(p); 00356 time++; 00357 } 00358 return out; 00359 } 00360 00361 //take a deque of sequences and blend them togeather them with the current que 00362 //####################################################################### 00363 void BeoMonkey::blendSequence(std::deque< std::deque<Position> > elements) 00364 { 00365 elements.push_back(moveQue); 00366 moveQue = getBlendSequence(elements); 00367 } 00368 00369 //blend a series of sequences togeather and return a deque 00370 //fix this to use an iterator 00371 //####################################################################### 00372 std::deque<Position> BeoMonkey::getBlendSequence(std::deque< 00373 std::deque<Position> 00374 > elements) 00375 { 00376 std::deque<Position> b; 00377 if (elements.size() > 1) 00378 { 00379 b = blend(elements.at(0),elements.at(1)); 00380 00381 for (uint ii = 2; ii < elements.size(); ii++) 00382 { 00383 b = blend(b,elements.at(ii)); 00384 } 00385 } 00386 return b; 00387 } 00388 00389 //blend two sequences 00390 //####################################################################### 00391 std::deque<Position> BeoMonkey::blend(std::deque<Position> p1, 00392 std::deque<Position> p2) 00393 { 00394 std::deque<Position> p; 00395 std::deque<Position>::iterator ii,jj; 00396 int time; 00397 if (p1.empty()) 00398 { 00399 p1.insert(p1.end(),p2.begin(),p2.end()); 00400 return p1; 00401 } 00402 else 00403 { 00404 time = p1.back().time; 00405 if (p2.back().time > time) 00406 time = p2.back().time; 00407 ii = p1.begin(); 00408 jj = p2.begin(); 00409 00410 for (int k = 1; k <= time; k++) 00411 { 00412 for (; ii != p1.end(); ii++) 00413 { 00414 if (ii->time == k) 00415 p.push_back(*ii); 00416 else 00417 break; 00418 } 00419 for (; jj != p2.end(); jj++) 00420 { 00421 if (jj->time == k) 00422 p.push_back(*jj); 00423 else 00424 break; 00425 } 00426 } 00427 } 00428 return p; 00429 } 00430 00431 //####################################################################### 00432 bool BeoMonkey::isQueEmpty() 00433 { 00434 return moveQue.empty(); 00435 } 00436 00437 //####################################################################### 00438 bool BeoMonkey::nextTimeStep() 00439 { 00440 if (moveQue.empty() ) 00441 return false; 00442 00443 else 00444 { 00445 while (moveQue.front().time == 1) 00446 { 00447 if (!BeoChip::setServo(moveQue.front().servo, 00448 moveQue.front().position)) 00449 return false; 00450 moveQue.pop_front(); 00451 } 00452 std::deque<Position>::iterator ii; 00453 for (ii = moveQue.begin(); ii != moveQue.end(); ii++) 00454 ii->time--; 00455 } 00456 return true; 00457 } 00458 00459 //####################################################################### 00460 std::deque<Position> BeoMonkey::concatSequence(std::deque< 00461 std::deque<Position> > e) 00462 { 00463 std::deque<Position> f; 00464 std::deque< std::deque<Position> >::iterator ii; 00465 for (ii = e.begin(); ii != e.end(); ii++) 00466 { 00467 if (f.size() > 0) 00468 for (std::deque<Position>::iterator jj = ii->begin(); 00469 jj != ii->end(); jj++) 00470 jj->time+= f.back().time; 00471 00472 f.insert(f.end(),ii->begin(),ii->end()); 00473 } 00474 return f; 00475 } 00476 00477 //####################################################################### 00478 void BeoMonkey::clearQue() 00479 { 00480 moveQue.clear(); 00481 } 00482 00483 std::deque<Position> BeoMonkey::getQue() 00484 { 00485 return moveQue; 00486 } 00487 00488 void BeoMonkey::removeServo(const byte servo) 00489 { 00490 //doesn't make sure times are all ok 00491 std::deque<Position>::iterator ii; 00492 for (ii = moveQue.begin(); ii != moveQue.end(); ) 00493 { 00494 if (ii->servo == servo) 00495 ii = moveQue.erase(ii); 00496 else 00497 ii++; 00498 } 00499 } 00500 00501 //###################################################################### 00502 void BeoMonkey::surpriseFace(float surprise) 00503 { 00504 // setEyeLidsPos(1.0,25); 00505 //setEyeBrowPos(1.0,25); 00506 00507 std::deque< std::deque<Position> > p; 00508 p.push_back(getPathMouthPos(-1.0,2)); 00509 p.push_back(getPathMouthPos(1.0,4,-1.0)); 00510 p.push_back(getPathMouthPos(-1.0,4,1.0)); 00511 p.push_back(getPathMouthPos(.5,2,-1.0)); 00512 addSequence(concatSequence(p)); 00513 } 00514 00515 //###################################################################### 00516 void BeoMonkey::printPath(std::deque<Position> pr) 00517 { 00518 std::deque<Position>::iterator ii; 00519 for (ii = pr.begin(); ii != pr.end(); ii++) 00520 LINFO("Servo: %d Position: %f Time: %d\n",ii->servo, 00521 ii->position,ii->time); 00522 } 00523 00524 //###################################################################### 00525 float BeoMonkey::isServoInQue(byte servo) 00526 { 00527 if (moveQue.empty()) 00528 return -999; 00529 00530 float temp = -999; 00531 std::deque<Position>::reverse_iterator ii; 00532 00533 for (ii = moveQue.rbegin(); ii != moveQue.rend(); ii++) 00534 { 00535 if (ii->servo == servo) 00536 { 00537 temp = ii->position; 00538 return temp; 00539 } 00540 } 00541 return temp; 00542 00543 } 00544 00545 //###################################################################### 00546 int BeoMonkey::queSize() 00547 { 00548 return moveQue.size(); 00549 } 00550 00551 // ###################################################################### 00552 /* So things look consistent in everyone's emacs... */ 00553 /* Local Variables: */ 00554 /* indent-tabs-mode: nil */ 00555 /* End: */