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
00007
00008
00009
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
00071
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
00085
00086
00087
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
00098
00099
00100 NEW_SKETCH(diff, uint, (((Sketch<uint>)on)+offset) - (Sketch<uint>)off);
00101
00102
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
00120 BlobData led = possible_leds[0];
00121
00122 std::cout << "Led located at (" << led.getCentroid().coordX()
00123 << "," << led.getCentroid().coordY() << ")" << std::endl;
00124
00125
00126
00127 if ( fabs(led.getCentroid().coordX() - 160) < 16 &&
00128 fabs(led.getCentroid().coordY() - 120) < 12) {
00129
00130
00131 std::cout << "Led locked on!" << std::endl;
00132
00133 if (currentLEDMask == LEFT_LED_MASK) {
00134
00135 leftLEDPan = state->outputs[HeadOffset + PanOffset];
00136 leftLEDTilt = state->outputs[HeadOffset + TiltOffset];
00137
00138
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
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
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
00169 MMAccessor<HeadPointerMC>(headpointer_id)->setJoints(0,0,0);
00170 MMAccessor<LedMC>(leds_id)->set(AllLEDMask, 0);
00171
00172
00173 erouter->addTimer(this, STOP_TIMER_ID, STOP_TIME_INTERVAL, false);
00174 return;
00175 }
00176
00177 } else {
00178
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
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
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
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) {
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 {
00217 moveToNextSearchPoint();
00218 }
00219 }
00220 }
00221 }
00222
00223 #endif