Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

CameraCalibrationBehavior.cc

Go to the documentation of this file.
00001 #include "Shared/RobotInfo.h"
00002 #if defined(TGT_IS_QWERK) && defined(TGT_HAS_HEAD)
00003 
00004 #include "Motion/LedMC.h"
00005 #include "Motion/MMAccessor.h"
00006 //#include "Motion/MotionManager.h"
00007 
00008 //#include "DualCoding/DualCoding.h"
00009 //using namespace DualCoding;
00010 
00011 #include "CameraCalibrationBehavior.h"
00012 
00013 void CameraCalibrationBehavior::doStart() {
00014   VisualRoutinesBehavior::doStart();
00015 #ifdef TGT_QBOTPLUS
00016   SharedObject<LedMC> leds_mc;
00017   leds_mc->set(currentLEDMask, 100);
00018   leds_mc->set(~currentLEDMask, 0);
00019   leds_id = motman->addPersistentMotion(leds_mc);
00020   
00021   SharedObject<HeadPointerMC> head_mc;
00022   head_mc->setJoints(0, currentPan, currentTilt);
00023   headpointer_id = motman->addPersistentMotion(head_mc);
00024   
00025   erouter->addTimer(this, SEARCH_TIMER_ID, SEARCH_TIME_INTERVAL, false);
00026 #else
00027   std::cout << "Calibration routine enabled for non-QBotPlus robot." << std::endl;
00028   std::cout << "Stopping routine." << std::endl;
00029   doStop();
00030 #endif
00031 
00032 }
00033 
00034 void CameraCalibrationBehavior::doStop() {
00035 #ifdef TGT_QBOTPLUS
00036   motman->removeMotion(leds_id);
00037   motman->removeMotion(headpointer_id);
00038 #endif
00039 
00040   VisualRoutinesBehavior::doStop();
00041 }
00042 
00043 void CameraCalibrationBehavior::moveToNextSearchPoint() {
00044   if ( (currentPan+=SEARCH_PAN_INCREMENT) <
00045        RobotInfo::outputRanges[HeadOffset + PanOffset][MinRange]) {
00046     currentPan = RobotInfo::outputRanges[HeadOffset + PanOffset][MaxRange];
00047     currentTilt += SEARCH_TILT_INCREMENT;
00048   }
00049   if (currentTilt > RobotInfo::outputRanges[HeadOffset + TiltOffset][MaxRange]) {
00050     std::cout << "COMPLETE FAILURE!"<<std::endl
00051               <<"NO LED COULD BE FOUND!"<<std::endl;
00052     stop();
00053   }
00054   partial_vision_count = 0;
00055   diffThreshold = STARTING_DIFF_THRESHOLD;
00056   
00057   std::cout << "Checking joint values (" << currentPan
00058             << "," <<currentTilt << ")" << std::endl;
00059   MMAccessor<HeadPointerMC>(headpointer_id)->
00060     setJoints(0, currentPan, currentTilt);
00061   erouter->addTimer(this, SEARCH_TIMER_ID, SEARCH_TIME_INTERVAL, false);
00062 }
00063 
00064 void CameraCalibrationBehavior::doEvent() {
00065   if (event->getGeneratorID() == EventBase::timerEGID) {
00066     if (event->getSourceID() == STOP_TIMER_ID) {
00067       stop();
00068       return;
00069     } else if (event->getSourceID() ==  SEARCH_TIMER_ID) {
00070       //we have just moved to a new search point
00071       //(or this search point again)
00072 
00073       std::cout << "Grabbing frame" << std::endl;
00074       camSkS.clear();
00075       
00076       NEW_SKETCH(on, uchar, sketchFromRawY());
00077       on->retain();
00078       
00079       MMAccessor<LedMC>(leds_id)->set(currentLEDMask, 0);
00080       erouter->addTimer(this, CHECK_IS_LED_TIMER_ID,
00081                         CHECK_IS_LED_TIMER_INVERVAL, false);
00082       
00083     } else if (event->getSourceID() == CHECK_IS_LED_TIMER_ID) {
00084       //we haven't moved, but now the led is off, so we can compare
00085       //intensity sketches
00086       
00087       //turn the led back on
00088       MMAccessor<LedMC>(leds_id)->set(currentLEDMask, 100);
00089       
00090       
00091       const uint offset = 256;
00092       
00093       NEW_SKETCH(off, uchar, sketchFromRawY());
00094       GET_SKETCH(on, uchar, camSkS);
00095       on->retain(false);
00096       
00097       //add offset to the on sketch so that a pixel that is
00098       //slightly brighter in the off sketch does not appear as a 
00099       //large difference (because 100-101 = 254 in unsigned subtraction)
00100       NEW_SKETCH(diff, uint, (((Sketch<uint>)on)+offset) - (Sketch<uint>)off);
00101       
00102       //This does not scale properly
00103       diff->setColorMap(jetMapScaled);
00104       
00105       NEW_SKETCH(diffThresh , bool, diff > diffThreshold+offset);
00106       
00107       NEW_SKETCH(areas, DualCoding::uint, visops::areacc(diffThresh));
00108       std::cout << "Largest area found is " << areas->max() << std::endl;
00109       std::cout << "  Threshold used is " << diffThreshold << std::endl;
00110       
00111       NEW_SHAPEVEC(too_big_leds, BlobData,
00112                    BlobData::extractBlobs(diffThresh, MAX_LED_AREA_THRESHOLD));
00113       NEW_SHAPEVEC(possible_leds, BlobData,
00114                    BlobData::extractBlobs(diffThresh, LED_AREA_THRESHOLD));
00115       NEW_SHAPEVEC(too_small_leds, BlobData,
00116                    BlobData::extractBlobs(diffThresh, WEAK_LED_AREA_THRESHOLD));
00117       
00118       if (possible_leds.size() == 1 && too_big_leds.size() == 0) {
00119         //The led is in the vision frame, its homing time.
00120         BlobData led = possible_leds[0];
00121         
00122         std::cout << "Led located at (" << led.getCentroid().coordX()
00123                   << "," << led.getCentroid().coordY() << ")" << std::endl;
00124         //center at 160,120 and upper left is 0 0
00125         
00126         //if head close enough to center
00127         if ( fabs(led.getCentroid().coordX() - 160) < 16 &&
00128              fabs(led.getCentroid().coordY() - 120) < 12) {
00129           
00130           //store point and switch target led
00131           std::cout << "Led locked on!" << std::endl;
00132           
00133           if (currentLEDMask == LEFT_LED_MASK) {
00134             //found left led
00135             leftLEDPan = state->outputs[HeadOffset + PanOffset];
00136             leftLEDTilt = state->outputs[HeadOffset + TiltOffset];
00137             
00138             //cheat a little, jump right to the next led (hopefully)
00139             currentPan = leftLEDPan + SEARCH_PAN_INCREMENT * 3;
00140             currentTilt = leftLEDTilt;
00141             
00142             currentLEDMask = RIGHT_LED_MASK;
00143             MMAccessor<LedMC>(leds_id)->set(currentLEDMask, 100);
00144             
00145             moveToNextSearchPoint();
00146             return;
00147           } else {
00148             //found right led
00149             float rightLEDPan = state->outputs[HeadOffset + PanOffset];
00150             float rightLEDTilt = state->outputs[HeadOffset + TiltOffset];
00151             float avgPan = (leftLEDPan+rightLEDPan)/2;
00152             float avgTilt = (leftLEDTilt+rightLEDTilt)/2;
00153             
00154             std::cout << "Pan difference is " << leftLEDPan-rightLEDPan
00155                       << ". Average is " << avgPan << std::endl;
00156             std::cout << "Tilt difference is " << leftLEDTilt-rightLEDTilt
00157                       << ". Average is " << avgTilt << std::endl;
00158             
00159             std::string filename = "ms/config/tekkotsu.xml";
00160             
00161             //expect averages to be 0 and -1.15
00162             config->motion.calibration_offset[HeadOffset+PanOffset] += avgPan;
00163             config->motion.calibration_offset[HeadOffset+TiltOffset]  += avgTilt + 1.15f;
00164             config->saveFile(filename.c_str());
00165             
00166             std::cout << "Changes saved to file:" << filename << std::endl;
00167             
00168             //reset and zero
00169             MMAccessor<HeadPointerMC>(headpointer_id)->setJoints(0,0,0);
00170             MMAccessor<LedMC>(leds_id)->set(AllLEDMask, 0);
00171             
00172             //let our motion commands complete before we stop
00173             erouter->addTimer(this, STOP_TIMER_ID, STOP_TIME_INTERVAL, false);
00174             return;
00175           }
00176           
00177         } else {//led not centered in vision frame
00178           //otherwise move head closer to led
00179           float xdiff = (led.getCentroid().coordX() - CameraResolutionX/2)/(CameraResolutionX/2);
00180           float ydiff = (led.getCentroid().coordY() - CameraResolutionY/2)/CameraResolutionY/2;
00181           std::cout << "Adjusting by " << xdiff << "(" 
00182                     << xdiff*SEARCH_PAN_INCREMENT
00183                     << "), " << ydiff << "(" 
00184                     << ydiff*SEARCH_TILT_INCREMENT << ")" << std::endl;
00185           MMAccessor<HeadPointerMC>(headpointer_id)->
00186             setJoints(0,
00187                       state->outputs[HeadOffset + PanOffset] + xdiff*SEARCH_PAN_INCREMENT, 
00188                       state->outputs[HeadOffset + TiltOffset] + -1*ydiff*SEARCH_TILT_INCREMENT);
00189         }
00190         
00191         //check this point again
00192         erouter->addTimer(this, SEARCH_TIMER_ID, SEARCH_TIME_INTERVAL, false);
00193         
00194       } else if (possible_leds.size() > 0 || too_small_leds.size() > 0) {
00195         //something is not right with the vision frame
00196         std::cout << "I see multiple LEDS or something that might be an LED!"
00197                   << "  I'm going to look again." << std::endl;
00198         
00199         //there are too many small dots
00200         if (too_small_leds.size() > 0 && too_big_leds.size() == 0) {
00201           if (++partial_vision_count >= PARTIAL_VISION_THRESHOLD) {
00202             std::cout << "reducing diff threshold" << std::endl;
00203             partial_vision_count = 0;
00204             diffThreshold = (diffThreshold * 3)/4;
00205           }
00206         } else if (too_big_leds.size() > 0) { //we see a plob too large
00207           if (--partial_vision_count <= -1 * PARTIAL_VISION_THRESHOLD) {
00208             std::cout << "increasing diff threshold" << std::endl;
00209             partial_vision_count = 0;
00210             diffThreshold = (diffThreshold * 3)/2;
00211           }
00212         }
00213         
00214         erouter->addTimer(this, SEARCH_TIMER_ID, SEARCH_TIME_INTERVAL, false);
00215         
00216       } else { //0 blobs of size > LED_AREA_THRESHOLD, go to next point
00217         moveToNextSearchPoint();
00218       }
00219     }
00220   }
00221 }
00222 
00223 #endif

Tekkotsu v5.1CVS
Generated Mon May 9 04:58:36 2016 by Doxygen 1.6.3