//## begin module%1.4%.codegen_version preserve=yes // Read the documentation to learn more about C++ code generator // versioning. //## end module%1.4%.codegen_version //## begin module%3D86D3570320.cm preserve=no // %X% %Q% %Z% %W% //## end module%3D86D3570320.cm //## begin module%3D86D3570320.cp preserve=no //## end module%3D86D3570320.cp //## Module: SIR%3D86D3570320; Pseudo Package body //## Source file: C:\Program Files\Rational\Rose\C++\source\SIR.cpp //## begin module%3D86D3570320.additionalIncludes preserve=no //## end module%3D86D3570320.additionalIncludes //## begin module%3D86D3570320.includes preserve=yes #include #include #include "Version.h" //## end module%3D86D3570320.includes // SIR #include "SIR.h" //## begin module%3D86D3570320.additionalDeclarations preserve=yes //## end module%3D86D3570320.additionalDeclarations // Class SIR SIR SIR::sirs[NUMBER_OF_ROBOTS]; //tables diff. sim. - physical robots const double SIR::row2Meter[] = {1.000, //border of image, not used 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 0.9000, 0.9000, 0.9000, 0.8000, //rows 1 0.8000, 0.7500, 0.7000, 0.6500, 0.6000, 0.5500, 0.5250, 0.5000, 0.4830, 0.4670, 0.8000, 0.8000, 0.8000, 0.8000, 0.8000, 0.8000, 0.8000, 0.7300, 0.6600, 0.6200, //to 30 not used, too inaccurate 0.5800, 0.5400, 0.5000, 0.4700, 0.4400, 0.4100, 0.3900, 0.3700, 0.3500, 0.3300, 0.3050, 0.2900, 0.2750, 0.2550, 0.2400, 0.2300, 0.2200, 0.2150, 0.2100, 0.2000, 0.1950, 0.1900, 0.1800, 0.1700, 0.1600, 0.1550, 0.1500, 0.1400, 0.1350, 0.0650, 0.065}; //border of image, not used const double SIR::yFactor[] = {0.0200, //border of image, not used 0.0200, 0.0200, 0.0200, 0.0200, 0.0200, 0.0200, 0.0200, 0.0200, 0.0200, 0.0200, //rows 1 0.0180, 0.0140, 0.0105, 0.0095, 0.0090, 0.0085, 0.0080, 0.0073, 0.0069, 0.0067, 0.0095, 0.0095, 0.0095, 0.0095, 0.0095, 0.0075, 0.0075, 0.0075, 0.0075, 0.0075, //to 30 not used, too inaccurate 0.0055, 0.0039, 0.0039, 0.0037, 0.0036, 0.0036, 0.0035, 0.0034, 0.0034, 0.0033, 0.0033, 0.0032, 0.0030, 0.0028, 0.0026, 0.0025, 0.0026, 0.0027, 0.0028, 0.0029, 0.0030, 0.0029, 0.0028, 0.0026, 0.0023, 0.0022, 0.0020, 0.0018, 0.0016, 0.0015, 0.0100}; //border of image, not used const double SIR::yFactorMinus[] = {0.0100, //border of image, not used 0.0100, 0.0100, 0.0100, 0.0100, 0.0100, 0.0100, 0.0100, 0.0100, 0.0100, 0.0100, //rows 1 0.0059, 0.0055, 0.0053, 0.0047, 0.0045, 0.0042, 0.0040, 0.0036, 0.0034, 0.0033, 0.0015, 0.0015, 0.0014, 0.0014, 0.0013, 0.0013, 0.0013, 0.0013, 0.0013, 0.0013, //to 30 not used, too inaccurate 0.0026, 0.0025, 0.0024, 0.0023, 0.0022, 0.0021, 0.0019, 0.0018, 0.0017, 0.0016, 0.0015, 0.0014, 0.0013, 0.0012, 0.0011, 0.0011, 0.0010, 0.0011, 0.0010, 0.0010, 0.0010, 0.0010, 0.0010, 0.0010, 0.0010, 0.0010, 0.0010, 0.0009, 0.0008, 0.0007, 0.0010}; //border of image, not used SIR::SIR () : robotDetectedFlag(false), cubeDetectedFlag(false), minimumCubeSize(0.03), #ifndef EYESIM_CUBECLUSTERING_PARAMETERS cubeColor(65), allowedCubeColorDeviation(15), obstacleThresholdSides(0.15) #else cubeColor(42), allowedCubeColorDeviation(0), obstacleThresholdSides(0.25) #endif #ifdef EYEBOT8_CUBECLUSTERING_PARAMETERS ,obstacleThresholdFront(0.175) #endif #ifdef EYEBOT3_CUBECLUSTERING_PARAMETERS ,obstacleThresholdFront(0.11) #endif #ifdef EYESIM_CUBECLUSTERING_PARAMETERS ,obstacleThresholdFront(0.11) #endif ,Thread("sir", 256*1024, MAX_PRI, 0) { cubePositionX = 0.0; cubePositionY = 0.0; } void SIR::initialize(void) { mes[OSMachineID()] = this; camera = Camera::getCamera(); psds = PSDs::getPSDs(); drive = Drive::getDrive(); } //## Other Operations (implementation) bool SIR::obstacleLeft () { //## begin SIR::obstacleLeft%3D9296DA015E.body preserve=yes return (getLeftMargin()readLeft(); //## end SIR::getLeftMargin%3D99481C028A.body } double SIR::getRightMargin () { //## begin SIR::getRightMargin%3D9948230082.body preserve=yes return psds->readRight(); //## end SIR::getRightMargin%3D9948230082.body } double SIR::getFrontMargin () { //## begin SIR::getFrontMargin%3D99482B0096.body preserve=yes return psds->readFront(); //## end SIR::getFrontMargin%3D99482B0096.body } bool SIR::robotDetected () { //## begin SIR::robotDetected%3D99453C024E.body preserve=yes return robotDetectedFlag; //## end SIR::robotDetected%3D99453C024E.body } bool SIR::cubeDetected () { //## begin SIR::cubeDetected%3D994557000A.body preserve=yes return cubeDetectedFlag; //## end SIR::cubeDetected%3D994557000A.body } void SIR::takePicture () { //## begin SIR::takePicture%3D9948FB03D4.body preserve=yes camera->getFrame(currentImage); //## end SIR::takePicture%3D9948FB03D4.body } void SIR::takeColorPicture () { //## begin SIR::takeColorPicture%3D9FC00D014A.body preserve=yes camera->getColorFrame(currentColorImage); //## end SIR::takeColorPicture%3D9FC00D014A.body } bool SIR::detectCubes () { //## begin SIR::detectCubes%3D99479F0168.body preserve=yes image hues; //to store the hues of the currentColorImage takeColorPicture(); double robotPositionXAtPictureTime, robotPositionYAtPictureTime, phiAtPictureTime; drive->getPosition(robotPositionXAtPictureTime, robotPositionYAtPictureTime, phiAtPictureTime); //used to set up tables (row2Meter, yFactor, yFactorMinus) //also uncomment code below /*for (int row = 1; row <=imagerows-2; row++) imageFilter.calculateHue(currentColorImage, row, hues); for (int row = 1; row <=imagerows-2; row++) for (int column = 1; column <=imagecolumns-2; column++) if (hasCubeColor(hues[row][column])) hues[row][column] = 30; else hues[row][column] = 255; LCDPutGraphic(&hues);*/ //LCDPutColorGraphic(¤tColorImage); int row = imagerows-2; //start at the bottom row while(row>=31) //rows 1 to 30 are not considered, the results are too inaccurate //diff. sim. - physical robots { //the desired cube size in pixel is calculated //(it depends on minimum cube size in meter and distance to robot) int minimumSize = 0; if (yFactor[row] != 0.0) { minimumSize = (int) (minimumCubeSize / yFactor[row]); if (minimumSize > imagecolumns - 2) minimumSize = imagecolumns - 2; } else minimumSize = imagecolumns - 2; if (minimumSize < 8) //enough?? //Note: minumumSize must be >= 1, see code below (first+=minimumSize) minimumSize = 8; imageFilter.calculateHue(currentColorImage, row, hues); int first = 1; //index of first pixel with object color int last = -1; //used to store: (index of last pixel with object color)+1 while(first<=(imagecolumns-2)-minimumSize+1) //this while loop must have the same exit criterion as the (next) inner while loop, otherwise this method might not terminate { // find left 'edge', first pixel with object color in the current row while ((first<=(imagecolumns-2)-minimumSize+1) && !hasCubeColor(hues[row][first])) //this while loop must have the same exit criterion as the (previous) outer while loop, otherwise this method might not terminate first+=minimumSize; // //Note: minumumSize must be >= 1 //check if we really found a 'first' pixel if ((first<=(imagecolumns-2)-minimumSize+1) && hasCubeColor(hues[row][first])) { while ((first-1>=1) && hasCubeColor(hues[row][first-1])) first--; //we found a 'first' pixel, now we want to know the size of the object //find right 'edge' last = first + 1; while ((last<=imagecolumns-2) && hasCubeColor(hues[row][last])) last++; if ((last - first) >= minimumSize) // check if object big enough { //int cubeMiddleY = first + (last-first)/2; //add up all pixels in this row with cube color. //Maybe a better estimation for cubeMiddleY then //first+(last-first)/2? //Problems occur if two cubes are in the same row and far apart int sum = 0; int numberOfCubePixels = 0; for (int column = 1; column <= imagecolumns-2; column++) { if (hasCubeColor(hues[row][column])) { sum += column; numberOfCubePixels++; } } int cubeMiddleY = (int)floor(sum/numberOfCubePixels + 0.5); int deviationFromImageMiddleY = (imagecolumns-2)/2 - cubeMiddleY; //Note: as the robot coordinate system (x up, y to the left) and the image coordinate system (x down, y to the right) have opposite orientations, we turn around y by calculating imageMiddleY-cubeMiddleY instead of cubeMiddleY-imageMiddleY #ifdef EYEBOT8_CUBECLUSTERING_PARAMETERS cubeDistanceX = row2Meter[row]; #endif #ifdef EYEBOT3_CUBECLUSTERING_PARAMETERS cubeDistanceX = row2Meter[row]; #endif #ifdef EYESIM_CUBECLUSTERING_PARAMETERS cubeDistanceX = row2Meter[row]; #endif if (deviationFromImageMiddleY >=0) #ifdef EYEBOT8_CUBECLUSTERING_PARAMETERS cubeDistanceY = double(deviationFromImageMiddleY) * yFactor[row] * 0.33; #endif #ifdef EYEBOT3_CUBECLUSTERING_PARAMETERS cubeDistanceY = double(deviationFromImageMiddleY) * yFactor[row]; #endif #ifdef EYESIM_CUBECLUSTERING_PARAMETERS cubeDistanceY = double(deviationFromImageMiddleY) * yFactor[row] * 2; #endif else #ifdef EYEBOT8_CUBECLUSTERING_PARAMETERS cubeDistanceY = double(deviationFromImageMiddleY) * yFactorMinus[row] * 2.5; #endif #ifdef EYEBOT3_CUBECLUSTERING_PARAMETERS cubeDistanceY = double(deviationFromImageMiddleY) * yFactorMinus[row]; #endif #ifdef EYESIM_CUBECLUSTERING_PARAMETERS cubeDistanceY = double(deviationFromImageMiddleY) * yFactorMinus[row] * 4; #endif cubePositionX = robotPositionXAtPictureTime + cos(2*PI*phiAtPictureTime/360.0)*cubeDistanceX + sin(2*PI*phiAtPictureTime/360.0)*cubeDistanceY; cubePositionY = robotPositionYAtPictureTime + cos(2*PI*phiAtPictureTime/360.0)*cubeDistanceY + sin(2*PI*phiAtPictureTime/360.0)*cubeDistanceX; cubeDetectedFlag = true; //Note: needs to be set after the cube position to prevent race conditions //used to set up tables (row2Meter, yFactor, yFactorMinus) /*LCDSetPos(0,0); LCDPrintf("row %d\n", row); LCDPrintf("rel x %f\n", cubeDistanceX); LCDPrintf("rel y %f\n", cubeDistanceY); for (int jj=1; jj<=imagecolumns-2; jj++) LCDSetPixel(row, jj, 2); for (int jj=1; jj<=imagerows-2; jj++) LCDSetPixel(jj, cubeMiddleY, 2);*/ return cubeDetectedFlag; } //found object too small first = last + 1; //we know that last does not have cube color } //no 'first' pixel found } //while(first<=imagecolumns-2) row--; } //while(row>=1) cubeDetectedFlag = false; return cubeDetectedFlag; //no cube found //## end SIR::detectCubes%3D99479F0168.body } bool SIR::detectRobots () { //## begin SIR::detectRobots%3D9947AD00C8.body preserve=yes return false; //## end SIR::detectRobots%3D9947AD00C8.body } void SIR::getRobotPosition (double& x, double& y, double& phi) { //## begin SIR::getRobotPosition%3D99488A033E.body preserve=yes //## end SIR::getRobotPosition%3D99488A033E.body } void SIR::getGlobalCubePosition (double& x, double& y) { //## begin SIR::getGlobalCubePosition%3D9948740168.body preserve=yes x = cubePositionX; y = cubePositionY; //## end SIR::getGlobalCubePosition%3D9948740168.body } void SIR::getDensity (double& density, double& centerOfDensityX, double& centerOfDensityY) { //## begin SIR::getDensity%3D9948C90294.body preserve=yes image hues; colimage aColorImage; camera->getColorFrame(aColorImage); //LCDPutColorGraphic(&aColorImage); int numberOfCubePixels = 0; int rowSum = 0; int columnSum = 0; for (int row=21; row<=imagerows-2; row++) //the camera tables for rows < 21 are unreliable, so we might underestimate the distances. But we will approach the correct values steadily as the robot will make a better estimation next time when it is closer to the new cluster point, and so on { imageFilter.calculateHue(aColorImage, row, hues); for (int column=11; column<=imagecolumns-12; column++) //from 11 to 70 //diff. sim. - physical robots if (hasCubeColor(hues[row][column])) { numberOfCubePixels++; rowSum += row; columnSum += column; } } density = double(numberOfCubePixels)/double((imagerows-2)*(imagecolumns-2)); if (density != 0.0) { int centerRow = rowSum/numberOfCubePixels; int centerColumn = columnSum/numberOfCubePixels; int deviationFromImageMiddleY = (imagecolumns-2)/2 - centerColumn; //Note: as the robot coordinate system (x up, y to the left) and the image coordinate system (x down, y to the right) have opposite orientations, we turn around y by calculating imageMiddleY-centerMiddleY instead of centerMiddleY-imageMiddleY if (centerRow<31) centerRow = 31; //the camera tables for rows < 31 are unreliable, so we might underestimate the distances. But we will approach the correct values steadily as the robot will make a better estimation next time when it is closer to the new cluster point, and so on #ifdef EYEBOT8_CUBECLUSTERING_PARAMETERS centerOfDensityX = row2Meter[centerRow] * 0.8; //as we use the whole cubes instead of just the cube bottom to estimate the position here in this method the estimations for the x positions are generally to high, we correct them by a factor #endif #ifdef EYEBOT3_CUBECLUSTERING_PARAMETERS centerOfDensityX = row2Meter[centerRow] * 0.8; //as we use the whole cubes instead of just the cube bottom to estimate the position here in this method the estimations for the x positions are generally to high, we correct them by a factor #endif #ifdef EYESIM_CUBECLUSTERING_PARAMETERS centerOfDensityX = row2Meter[centerRow] * 0.8; //as we use the whole cubes instead of just the cube bottom to estimate the position here in this method the estimations for the x positions are generally to high, we correct them by a factor #endif if (deviationFromImageMiddleY >=0) #ifdef EYEBOT8_CUBECLUSTERING_PARAMETERS centerOfDensityY = double(deviationFromImageMiddleY) * yFactor[centerRow] * 0.33; #endif #ifdef EYEBOT3_CUBECLUSTERING_PARAMETERS centerOfDensityY = double(deviationFromImageMiddleY) * yFactor[centerRow]; #endif #ifdef EYESIM_CUBECLUSTERING_PARAMETERS centerOfDensityY = double(deviationFromImageMiddleY) * yFactor[centerRow] * 2; #endif else #ifdef EYEBOT8_CUBECLUSTERING_PARAMETERS centerOfDensityY = double(deviationFromImageMiddleY) * yFactorMinus[centerRow] * 2.5; #endif #ifdef EYEBOT3_CUBECLUSTERING_PARAMETERS centerOfDensityY = double(deviationFromImageMiddleY) * yFactorMinus[centerRow]; #endif #ifdef EYESIM_CUBECLUSTERING_PARAMETERS centerOfDensityY = double(deviationFromImageMiddleY) * yFactorMinus[centerRow] * 4; #endif } else { centerOfDensityX = 0; centerOfDensityY = 0; } //## end SIR::getDensity%3D9948C90294.body } void SIR::setCubeSize (int size) { //## begin SIR::setCubeSize%3D9972CE0334.body preserve=yes //## end SIR::setCubeSize%3D9972CE0334.body } void SIR::setCubeColor (int color) { //## begin SIR::setCubeColor%3D9972EE00F0.body preserve=yes //## end SIR::setCubeColor%3D9972EE00F0.body } // Additional Declarations //## begin SIR%3D86D3570320.declarations preserve=yes SIR* SIR::getSIR () { return &sirs[OSMachineID()]; } bool SIR::hasCubeColor (BYTE hue) { if (hue != imageFilter.NO_HUE) { //hue and cubeColor can have values between 0..252 //we have 253 hues in total and 126 is the //middle //we need to calculate the 'distance' between //these two hues int distance = abs((int)hue-cubeColor); //if the distance is larger than 126 than the other //way round is shorter if (distance > 126) distance = 253 - distance; if (distance <= allowedCubeColorDeviation) { return true; } } return false; } void SIR::run (void) { //int oldCount = 0; //int newCount = 0; while(1) { //newCount = OSGetCount(); //LCDPrintf("sir %d\n", newCount-oldCount); //oldCount = newCount; detectCubes(); //reschedule(); //detectRobots(); //reschedule(); } } bool SIR::obstacle () { return (obstacleFront() || obstacleRight() || obstacleLeft()); } bool SIR::spawn () { threadControlBlock = OSSpawn(name, staticRun, stackSize, priority, OSMachineID()*10+id); if (threadControlBlock) return true; else return false; } void SIR::staticRun () { mes[OSMachineID()]->run(); } SIR* SIR::mes[NUMBER_OF_ROBOTS]; void SIR::getLocalCubePosition (double& x, double& y) { x = cubeDistanceX; y = cubeDistanceY; } //## end SIR%3D86D3570320.declarations //## begin module%3D86D3570320.epilog preserve=yes //## end module%3D86D3570320.epilog