Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

VisualOdometry.cc

Go to the documentation of this file.
00001 #include "VisualOdometry.h"
00002 #include "Behaviors/StateMachine.h"
00003 #include "DualCoding/VRmixin.h"
00004 
00005 //================ Optical Flow Odometry ================
00006 
00007 void OpticalFlowOdometry::update(bool sleepOverride) {
00008   if ( !sleepOverride && !VRmixin::isWalkingFlag ) {
00009     sleeping = true;
00010     lastTranslation = 0;
00011     lastAngle = 0;
00012     return;
00013   }
00014   float lastFlow = integratedFlow;  // only valid if not sleeping
00015   updateFlow();
00016   if ( ! sleeping ) {
00017     lastTranslation = integratedFlow - lastFlow;
00018     lastAngle = lastTranslation / scalingFactor;
00019   } else {
00020     lastTranslation = 0;
00021     lastAngle = 0;
00022     sleeping = false;
00023     // std::cout << "Was Sleeping" << std::endl;
00024   }
00025 }
00026 
00027 /*
00028 void OpticalFlowOdometry::update(bool ignoreSleep) {
00029   if(ignoreSleep) {
00030     float lastFlow = integratedFlow;
00031     updateFlow();
00032     lastTranslation = integratedFlow - lastFlow;
00033     lastAngle = lastTranslation / scalingFactor;
00034   } else {
00035     update();
00036   }
00037 }
00038 */
00039 
00040 void OpticalFlowOdometry::setConversionParameters(float slope, float offset) {
00041   scalingFactor = slope;
00042 }
00043 
00044 
00045 //================ Image Profile Odometry ================
00046 
00047 void ImageProfileOdometry::update(bool sleepOverride) {
00048   if ( !sleepOverride && !VRmixin::isWalkingFlag ) {
00049     sleeping = true;
00050     lastTranslation = 0;
00051     lastAngle = 0;
00052     return;
00053   }
00054   buildImageProfile();
00055   if ( ! sleeping ) {
00056     lastTranslation = minTranslation();
00057     lastAngle = translationToAngle(lastTranslation);
00058   } else {
00059     lastTranslation = 0;
00060     lastAngle = 0;
00061     sleeping = false;
00062     // std::cout << "Was Sleeping" << std::endl;
00063   }
00064   displayImageProfile();
00065   displayTranslationProfile(); // note: currently no call to buildTranslationProfile
00066   swapCurrentProfile();
00067 }
00068 
00069 
00070 /*
00071 void ImageProfileOdometry::update() {
00072   if (VRmixin::isWalkingFlag) {
00073     buildImageProfile();
00074 
00075     if(sleeping) {
00076       lastTranslation = 0;
00077       lastAngle = 0;
00078       sleeping = false;
00079       std::cout << "Was Sleeping" << std::endl;
00080     } else {
00081       lastTranslation = minTranslation();
00082       lastAngle = translationToAngle(lastTranslation);
00083     }
00084 
00085     swapCurrentProfile();
00086   } else {
00087     sleeping = true;
00088   }
00089 }
00090 */
00091 
00092 void ImageProfileOdometry::buildImageProfile() {
00093   static Sketch<uchar> rawY(VRmixin::sketchFromRawY(), "rawY", true);
00094   rawY = VRmixin::sketchFromRawY();
00095 
00096   for(unsigned int i = 0; i < currImageProfile->size(); i++) {
00097     (*currImageProfile)[i] = 0;
00098   }
00099 
00100   for(unsigned int i = 0; i < currImageProfile->size(); i++) {
00101     for(unsigned int j = 0; j < RobotInfo::CameraResolutionY; j++) {
00102       (*currImageProfile)[i] += rawY(i,j);
00103     }
00104   }
00105 }
00106 
00107 void ImageProfileOdometry::swapCurrentProfile() {
00108   if ( currImageProfile == &profile1 )
00109     currImageProfile = &profile2;
00110   else
00111     currImageProfile = &profile1;
00112 }
00113 
00114 void ImageProfileOdometry::buildTranslationProfile() {
00115   int upper = RobotInfo::CameraResolutionX/2;
00116   int lower = -upper;
00117 
00118   float currDistance;
00119   int index = 0;
00120   for(int i = lower; i < upper; i++, index++) {
00121     if(currImageProfile == &profile1)
00122       currDistance = differenceMeasure(i);
00123     else
00124       currDistance = differenceMeasure(i);
00125 
00126     translationProfile[index] = currDistance;
00127   }
00128 
00129   float maxElement = *(max_element(translationProfile.begin(), translationProfile.end()));
00130 
00131   const unsigned int width = RobotInfo::CameraResolutionX;
00132   const unsigned int height = RobotInfo::CameraResolutionY;
00133   for(unsigned int i = 0; i < width; i++) {
00134     translationProfile[i] = width - floor(translationProfile[i] / (maxElement/height));
00135   }
00136 }
00137 
00138 float ImageProfileOdometry::translationToAngle(int translation) {
00139   if ( slope == 0.0f )
00140     return 0.0f;
00141   else
00142     return ((float)translation + offset)/slope;
00143 }
00144 
00145 void ImageProfileOdometry::setConversionParameters(float tSlope, float tOffset) {
00146   this->slope = tSlope;
00147   this->offset = tOffset;
00148 }
00149 
00150 
00151 /**
00152    Calculate the difference between the current image profile and the previous one
00153    shifted to the right by s.
00154  */
00155 float ImageProfileOdometry::differenceMeasure(int s) {
00156   bool direction = currImageProfile == &profile1;
00157   int bounds = RobotInfo::CameraResolutionX - fabs(s) - 1;
00158     
00159   float manDifference = 0.0f;
00160   float differenceComponent = 0.0f;
00161   for(int i = 0; i < bounds; i++) {
00162     int currIndex = i + std::max(0,s);
00163     int prevIndex = i - std::min(0,s);
00164     
00165     if(direction)
00166       differenceComponent = profile1[currIndex] - profile2[prevIndex];
00167     else
00168       differenceComponent = profile1[prevIndex] - profile2[currIndex];
00169 
00170     manDifference += fabs(differenceComponent);
00171   }
00172 
00173   return manDifference / (bounds + 1);
00174 }
00175 
00176 
00177 
00178 /**
00179    Returns the translation that minimizes the differenceMeasure
00180    between the two stored image profiles.
00181  */
00182 int ImageProfileOdometry::minTranslation() {
00183   int upper = RobotInfo::CameraResolutionX/2;
00184   int lower = -upper;
00185 
00186   int minTrans = lower;
00187   float minDistance = 255 * RobotInfo::CameraResolutionX;
00188   float currDistance;
00189   for (int i = lower; i < upper; i++) {
00190     currDistance = differenceMeasure(i);
00191     if(currDistance < minDistance) {
00192       minDistance = currDistance;
00193       minTrans = i;
00194     }
00195   }
00196 
00197   return minTrans;
00198 }
00199 
00200 void ImageProfileOdometry::displayImageProfile() {
00201   static Sketch<bool> hist(visops::zeros(VRmixin::camSkS), "imageProfile", true);
00202   hist = false;
00203 
00204   const unsigned int MAX_INTENSITY = 255; // assume one-byte pixels
00205   const unsigned int height = RobotInfo::CameraResolutionY;
00206   for(unsigned int i = 0; i < RobotInfo::CameraResolutionX; i++) {
00207     float scaledHeight = (float)(*currImageProfile)[i] / MAX_INTENSITY;
00208     for(int j = height-1; j > height-scaledHeight-1; j--) {
00209       hist(i,j) = true;
00210     }
00211   }
00212 }
00213 
00214 void ImageProfileOdometry::displayTranslationProfile() {
00215   static Sketch<bool> transDisp(visops::zeros(VRmixin::camSkS), "translationProfile", true);
00216 
00217   transDisp = false;
00218 
00219   int scaledValue;
00220   const unsigned int width = RobotInfo::CameraResolutionX;
00221   for(unsigned int bin = 0; bin < width; bin++) {
00222     scaledValue = translationProfile[bin];
00223     for(unsigned int j = width-1; j > width-scaledValue-1; j--) {
00224       transDisp(bin,j) = true;
00225     }
00226   }
00227 }
00228 
00229 const float VisualOdometry::ANGULAR_RESOLUTION =
00230   RobotInfo::CameraResolutionX / (RobotInfo::CameraHorizFOV / M_PI * 180);

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