00001
00002 #include "VLCLineFinder_DeterministicApproach.h"
00003
00004 VLCLineFinder_DeterministicApproach::VLCLineFinder_DeterministicApproach(const ColorCorrector& colorCorrector, const ColorTable& colorTable)
00005 :colorCorrector(colorCorrector), colorTable(colorTable)
00006 {
00007 normDistance = 3.0;
00008 normProjection = 0.9925;
00009 normProjectionPerpendicularToHorizon = 0.97;
00010
00011 framesSinceLastSeen=1000;
00012 frameCount = 0;
00013 circleCount = 0;
00014 }
00015
00016 VLCLineFinder_DeterministicApproach::~VLCLineFinder_DeterministicApproach(void)
00017 {
00018 }
00019
00020 void VLCLineFinder_DeterministicApproach::reset()
00021 {
00022 numberOfLineFragments = 0;
00023 numberOfLines = 0;
00024 numberOfLinePoints = 0;
00025 foundByCircleFinder = false;
00026 foundByOwnHandling = false;
00027 framesSinceLastSeen++;
00028 frameCount++;
00029 if (frameCount>200)
00030 {
00031 if (circleCount>0)
00032 {
00033
00034 }
00035 frameCount = 0;
00036 circleCount = 0;
00037 }
00038 }
00039
00040 void VLCLineFinder_DeterministicApproach::considerLinePoint(Vector2<int> & pointOnLine, Vector2<double> & normalToLine)
00041 {
00042
00043 if (numberOfLinePoints < maxNumberOfLinePoints)
00044 {
00045 linePoints[numberOfLinePoints].pointOnLine = pointOnLine;
00046 linePoints[numberOfLinePoints].normalToLine = normalToLine;
00047 linePoints[numberOfLinePoints].belongsToLineNo = -1;
00048 numberOfLinePoints++;
00049 }
00050 else
00051 {
00052
00053 }
00054 }
00055
00056 void VLCLineFinder_DeterministicApproach::execute(LinesPercept & linesPercept, const CameraMatrix& cameraMatrix, const Image& image, const ImageInfo& imageInfo, const RobotPose & robotPose)
00057 {
00058 lines = new LineFragment[maxNumberOfLines];
00059 lineFragments = new LineFragment[maxNumberOfLines*2];
00060
00061 foundByCircleFinder = false;
00062
00063 findLineFragments();
00064 handleCenterCircle(cameraMatrix, image, robotPose);
00065 findLines(linesPercept, cameraMatrix, image, imageInfo);
00066 findIntersections(linesPercept, cameraMatrix, image, robotPose, imageInfo);
00067 addCenterCirclePercept(linesPercept, cameraMatrix, image);
00068
00069 delete[] lines;
00070 delete[] lineFragments;
00071
00072 DEBUG_DRAWING_FINISHED(lineCrossingsField);
00073 DEBUG_DRAWING_FINISHED(imageProcessor_lines);
00074 DEBUG_DRAWING_FINISHED(imageProcessor_linefragments);
00075 }
00076
00077 void VLCLineFinder_DeterministicApproach::execute(LinesPercept & linesPercept, const CameraMatrix& cameraMatrix, const Image& image, const ImageInfo& imageInfo, const RobotPose & robotPose, const bool circleFound, const Vector2<double> & circleOnField)
00078 {
00079 lines = new LineFragment[maxNumberOfLines];
00080 lineFragments = new LineFragment[maxNumberOfLines*2];
00081
00082 foundByCircleFinder = false;
00083 fromCircleFinder.x = (int)circleOnField.x;
00084 fromCircleFinder.y = (int)circleOnField.y;
00085
00086 if (foundByCircleFinder)
00087 {
00088 handleCenterCircle(circleOnField, cameraMatrix, image);
00089
00090
00091
00092
00093
00094
00095
00096 }
00097 findLineFragments();
00098 if (!foundByCircleFinder)
00099 {
00100 handleCenterCircle(cameraMatrix, image, robotPose);
00101 }
00102 findLines(linesPercept, cameraMatrix, image, imageInfo);
00103 findIntersections(linesPercept, cameraMatrix, image, robotPose, imageInfo);
00104 addCenterCirclePercept(linesPercept, cameraMatrix, image);
00105
00106 delete[] lines;
00107 delete[] lineFragments;
00108
00109 DEBUG_DRAWING_FINISHED(lineCrossingsField);
00110 DEBUG_DRAWING_FINISHED(imageProcessor_lines);
00111 DEBUG_DRAWING_FINISHED(imageProcessor_linefragments);
00112 }
00113
00114 void VLCLineFinder_DeterministicApproach::findLineFragments()
00115 {
00116 int i, j;
00117 Vector2<double> temp;
00118
00119
00120 bool similar[maxNumberOfLinePoints][maxNumberOfLinePoints];
00121 for(i = 0; i < numberOfLinePoints; i++)
00122 {
00123 similar[i][i] = true;
00124 for(j = i + 1; j < numberOfLinePoints; j++)
00125 {
00126
00127 bool sim = false;
00128 double projection = linePoints[i].normalToLine * linePoints[j].normalToLine;
00129 if(projection > normProjection)
00130 {
00131 temp.x = (double)(linePoints[j].pointOnLine.x - linePoints[i].pointOnLine.x);
00132 temp.y = (double)(linePoints[j].pointOnLine.y - linePoints[i].pointOnLine.y);
00133 double distance1 = fabs(temp * linePoints[i].normalToLine);
00134 if(distance1 < normDistance)
00135 {
00136 double distance2 = fabs(temp * linePoints[j].normalToLine);
00137 sim = (distance2 < normDistance);
00138 }
00139 }
00140 similar[i][j] = sim;
00141 similar[j][i] = sim;
00142 }
00143 }
00144
00145
00146 int maxWeight;
00147 int linePointWithHighestWeight;
00148
00149
00150 for(int n=0; n<maxNumberOfLines*2; n++)
00151 {
00152 maxWeight = 0;
00153 linePointWithHighestWeight = -1;
00154
00155
00156 int simCount[maxNumberOfLinePoints];
00157 for(i=0; i<numberOfLinePoints; i++)
00158 {
00159 simCount[i]=1;
00160 }
00161 for(i=0; i < numberOfLinePoints; i++)
00162 {
00163 if(linePoints[i].belongsToLineNo == -1)
00164 {
00165 for (j=i+1; j < numberOfLinePoints; j++)
00166 {
00167 if(linePoints[j].belongsToLineNo == -1)
00168 {
00169 if(similar[i][j])
00170 {
00171
00172 simCount[i]++;
00173 simCount[j]++;
00174
00175 if(simCount[i] > maxWeight)
00176 {
00177 maxWeight = simCount[i];
00178 linePointWithHighestWeight = i;
00179 }
00180 if(simCount[j] > maxWeight)
00181 {
00182 maxWeight = simCount[j];
00183 linePointWithHighestWeight = j;
00184 }
00185 }
00186 }
00187 }
00188 }
00189 }
00190 if (maxWeight<pointsNeededForLine)
00191 {
00192 break;
00193 }
00194
00195
00196 Vector2<int> start(300,300);
00197 Vector2<int> end(-1,-1);
00198
00199 double angle = atan2(linePoints[linePointWithHighestWeight].normalToLine.y,linePoints[linePointWithHighestWeight].normalToLine.x);
00200 if (angle <= pi_4 && angle >= -1*pi_4)
00201 {
00202 for (i=0; i<numberOfLinePoints; i++)
00203 {
00204 if (similar[i][linePointWithHighestWeight] && linePoints[i].belongsToLineNo==-1)
00205 {
00206 linePoints[i].belongsToLineNo=numberOfLineFragments;
00207 if (linePoints[i].pointOnLine.y < start.y)
00208 {
00209 start = linePoints[i].pointOnLine;
00210 }
00211 if (linePoints[i].pointOnLine.y > end.y)
00212 {
00213 end = linePoints[i].pointOnLine;
00214 }
00215 }
00216 }
00217 }
00218 else
00219 {
00220 for (i=0; i<numberOfLinePoints; i++)
00221 {
00222 if (similar[i][linePointWithHighestWeight] && linePoints[i].belongsToLineNo==-1)
00223 {
00224 linePoints[i].belongsToLineNo=numberOfLineFragments;
00225 if (linePoints[i].pointOnLine.x < start.x)
00226 {
00227 start = linePoints[i].pointOnLine;
00228 }
00229 if (linePoints[i].pointOnLine.x > end.x)
00230 {
00231 end = linePoints[i].pointOnLine;
00232 }
00233 }
00234 }
00235 }
00236
00237
00238 if (maxWeight==pointsNeededForLine)
00239 {
00240 Vector2<int> length = end - start;
00241 if ( length.abs() > 70 )
00242 {
00243 for (i=0; i<numberOfLinePoints; i++)
00244 {
00245 if (linePoints[i].belongsToLineNo==numberOfLineFragments)
00246 {
00247 linePoints[i].belongsToLineNo=-2;
00248 }
00249 }
00250 continue;
00251 }
00252 }
00253
00254
00255 Vector2<double> normalToLine((double)(end.x-start.x), (double)(end.y-start.y));
00256 normalToLine.rotateLeft();
00257 normalToLine.normalize();
00258 Vector2<int> middle((start.x+end.x)/2, (start.y+end.y)/2);
00259 lineFragments[numberOfLineFragments].base = middle;
00260 lineFragments[numberOfLineFragments].normal = normalToLine;
00261 lineFragments[numberOfLineFragments].start = start;
00262 lineFragments[numberOfLineFragments].end = end;
00263 lineFragments[numberOfLineFragments].lineFragmentAlreadyConsidered = false;
00264 lineFragments[numberOfLineFragments].averageStep = (end-start).abs() / maxWeight;
00265 LINE(imageProcessor_linefragments,start.x,start.y,end.x,end.y,1,1,numberOfLineFragments);
00266 numberOfLineFragments++;
00267 }
00268 }
00269
00270 void VLCLineFinder_DeterministicApproach::findLines(LinesPercept & linesPercept, const CameraMatrix& cameraMatrix, const Image& image, const ImageInfo& imageInfo)
00271 {
00272 int i, j;
00273 Vector2<double> temp, temp2;
00274 Vector2<double> horizonDirection = imageInfo.horizon.direction;
00275 horizonDirection.normalize();
00276
00277
00278
00279 for (i=0; i<numberOfLineFragments && numberOfLines<maxNumberOfLines; i++)
00280 {
00281 if (lineFragments[i].lineFragmentAlreadyConsidered)
00282 {
00283 continue;
00284 }
00285 lines[numberOfLines].base = lineFragments[i].base;
00286 lines[numberOfLines].normal = lineFragments[i].normal;
00287 lines[numberOfLines].start = lineFragments[i].start;
00288 lines[numberOfLines].end = lineFragments[i].end;
00289 lines[numberOfLines].averageStep = lineFragments[i].averageStep;
00290 int numberOfLineFragmentsUsed = 1;
00291 lineFragments[i].lineFragmentAlreadyConsidered = true;
00292
00293 double angle = atan2(lines[numberOfLines].normal.y,lines[numberOfLines].normal.x);
00294 bool sortByY = angle <= pi_4 && angle >= -1*pi_4;
00295
00296 for (j=i+1; j<numberOfLineFragments; j++)
00297 {
00298 if (lineFragments[j].lineFragmentAlreadyConsidered)
00299 {
00300 continue;
00301 }
00302 double p = lineFragments[i].normal * lineFragments[j].normal;
00303 Vector2<double> nij;
00304 if (p>0)
00305 {
00306 nij = lineFragments[i].normal + lineFragments[j].normal;
00307 }
00308 else
00309 {
00310 nij = lineFragments[i].normal - lineFragments[j].normal;
00311 }
00312 nij.normalize();
00313 bool perpendicularToHorizon = fabs(horizonDirection * nij) > 0.93;
00314
00315 if ( (perpendicularToHorizon || p>normProjection || p<-1*normProjection)
00316 && (!perpendicularToHorizon || p>normProjectionPerpendicularToHorizon || p<-1*normProjectionPerpendicularToHorizon))
00317 {
00318 temp.x = (double)(lineFragments[i].base.x-lineFragments[j].base.x);
00319 temp.y = (double)(lineFragments[i].base.y-lineFragments[j].base.y);
00320 int lineHeight = max( Geometry::calculateLineSize(lineFragments[i].base, cameraMatrix, image.cameraInfo),
00321 Geometry::calculateLineSize(lineFragments[j].base, cameraMatrix, image.cameraInfo));
00322 lineHeight = max( lineHeight, 2 );
00323
00324 if ( (fabs(temp * lineFragments[i].normal) < 1.5 * lineHeight) && (fabs(temp * lineFragments[j].normal) < 1.5 * lineHeight) )
00325 {
00326
00327 if (p<0)
00328 {
00329 lineFragments[j].normal *= -1.0;
00330 }
00331 lines[numberOfLines].base += lineFragments[j].base;
00332 lines[numberOfLines].normal += lineFragments[j].normal;
00333 lines[numberOfLines].averageStep += lineFragments[i].averageStep;
00334
00335 if (sortByY)
00336 {
00337 if (lineFragments[j].start.y < lines[numberOfLines].start.y)
00338 {
00339 lines[numberOfLines].start = lineFragments[j].start;
00340 }
00341 if (lineFragments[j].end.y > lines[numberOfLines].end.y)
00342 {
00343 lines[numberOfLines].end = lineFragments[j].end;
00344 }
00345 }
00346 else
00347 {
00348 if (lineFragments[j].start.x < lines[numberOfLines].start.x)
00349 {
00350 lines[numberOfLines].start = lineFragments[j].start;
00351 }
00352 if (lineFragments[j].end.x > lines[numberOfLines].end.x)
00353 {
00354 lines[numberOfLines].end = lineFragments[j].end;
00355 }
00356 }
00357
00358 numberOfLineFragmentsUsed++;
00359 lineFragments[j].lineFragmentAlreadyConsidered = true;
00360 }
00361 }
00362 }
00363
00364 lines[numberOfLines].base /= numberOfLineFragmentsUsed;
00365 lines[numberOfLines].averageStep /= numberOfLineFragmentsUsed;
00366 lines[numberOfLines].normal.normalize();
00367
00368 numberOfLines++;
00369 }
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400 Vector2<int> r1(0,0);
00401 Vector2<int> r2(image.cameraInfo.resolutionWidth-1,image.cameraInfo.resolutionHeight-1);
00402 for (i=0; i<numberOfLines; i++)
00403 {
00404
00405 Vector2<int> pointOnLine;
00406 Vector2<double> direction;
00407 getLine(i, pointOnLine, direction);
00408 direction.rotateLeft();
00409 Geometry::Line a(pointOnLine, direction);
00410 Vector2<int> point1, point2;
00411 Geometry::getIntersectionPointsOfLineAndRectangle(r1,r2,a,point1,point2);
00412 LINE(
00413 imageProcessor_lines,
00414 point1.x,
00415 point1.y,
00416 point2.x,
00417 point2.y,
00418 1,
00419 Drawings::ps_solid,
00420 Drawings::skyblue
00421 );
00422 }
00423 }
00424
00425 void VLCLineFinder_DeterministicApproach::findIntersections(LinesPercept & linesPercept, const CameraMatrix& cameraMatrix, const Image& image, const RobotPose & robotPose, const ImageInfo& imageInfo)
00426 {
00427 int i,j;
00428
00429 Geometry::Line lines2[maxNumberOfLines];
00430 Vector2<double> intersection;
00431 Vector2<int> intersectionOnField;
00432 for (i=0; i<numberOfLines; i++)
00433 {
00434 Vector2<double> direction(lines[i].normal);
00435 direction.rotateLeft();
00436 direction.normalize();
00437 lines2[i] = Geometry::Line(lines[i].base,direction);
00438 }
00439 for (i=0; i<numberOfLines; i++)
00440 {
00441 for (j=i+1; j<numberOfLines; j++)
00442 {
00443 if (linesPerpendicularOnField(i, j, cameraMatrix, image))
00444 {
00445 Geometry::getIntersectionOfLines(lines2[i],lines2[j],intersection);
00446 if (Geometry::calculatePointOnField((int)intersection.x,(int)intersection.y,cameraMatrix,image.cameraInfo,intersectionOnField))
00447 {
00448 if (intersectionOnField.abs() < 3600)
00449 {
00450 addCrossingsPercept(intersection, intersectionOnField, i, j, linesPercept, image, imageInfo, cameraMatrix, robotPose);
00451 }
00452 }
00453 }
00454 }
00455 }
00456
00457
00458 for (i=0; i<numberOfLines; i++)
00459 {
00460 Vector2<int> pointOnField1, pointOnField2, directionOnField;
00461 Geometry::calculatePointOnField(lines[i].base.x, lines[i].base.y, cameraMatrix, image.cameraInfo, pointOnField1);
00462 Geometry::calculatePointOnField((int)(lines[i].base.x+50*lines[i].normal.y), (int)(lines[i].base.y-50*lines[i].normal.x), cameraMatrix, image.cameraInfo, pointOnField2);
00463 directionOnField = pointOnField2-pointOnField1;
00464 pointOnField1 = pointOnField1 - directionOnField * 10;
00465 pointOnField2 = pointOnField2 + directionOnField * 10;
00466 Vector2<double> point1OnFieldGlobal, point2OnFieldGlobal;
00467 point1OnFieldGlobal = Geometry::relative2FieldCoord(robotPose, (double)pointOnField1.x, (double)pointOnField1.y);
00468 point2OnFieldGlobal = Geometry::relative2FieldCoord(robotPose, (double)pointOnField2.x, (double)pointOnField2.y);
00469
00470 }
00471 }
00472
00473 void VLCLineFinder_DeterministicApproach::addCrossingsPercept(const Vector2<double> & intersectionInImage, const Vector2<int> & intersectionOnField, int lineNumber1, int lineNumber2, LinesPercept & linesPercept, const Image& image, const ImageInfo& imageInfo, const CameraMatrix & cameraMatrix, const RobotPose & robotPose)
00474 {
00475
00476 Vector2<double> temp1,temp2, directionOnField1,directionOnField2;
00477 bool firstLineIsLeft;
00478 Vector2<double> directionOfLine1 = lines[lineNumber1].normal;
00479 directionOfLine1.rotateRight();
00480 Vector2<double> directionOfLine2 = lines[lineNumber2].normal;
00481 directionOfLine2.rotateRight();
00482 if ( !calculateLineOnField(lineNumber1,temp1,directionOnField1,cameraMatrix,image)
00483 || !calculateLineOnField(lineNumber2,temp1,directionOnField2,cameraMatrix,image) )
00484 {
00485
00486 return;
00487 }
00488 Vector2<double> bisectionOnField = directionOnField1 + directionOnField2;
00489 bisectionOnField.normalize();
00490 double angleOnField = atan2(bisectionOnField.y,bisectionOnField.x) + pi_4;
00491
00492
00493 Vector2<double> angleBisection = directionOfLine1 + directionOfLine2;
00494 angleBisection.normalize();
00495
00496 double angleOfBisection = atan2(angleBisection.y,angleBisection.x);
00497 double angleOfLine1 = atan2(directionOfLine1.y,directionOfLine1.x);
00498 double angleOfLine2 = atan2(directionOfLine2.y,directionOfLine2.x);
00499
00500 if ( ( angleOfLine1 < angleOfBisection + pi_2 && angleOfLine1 > angleOfBisection )
00501 || ( angleOfLine1 + pi2 < angleOfBisection + pi_2 && angleOfLine1 + pi2 > angleOfBisection )
00502 || ( angleOfLine1 - pi2 < angleOfBisection + pi_2 && angleOfLine1 - pi2 > angleOfBisection ) )
00503 {
00504 firstLineIsLeft=false;
00505 }
00506 else
00507 {
00508 firstLineIsLeft=true;
00509 }
00510
00511
00512
00513 bool bothSidesOfLine1,bothSidesOfLine2;
00514
00515 temp1.x = (double)lines[lineNumber1].start.x - intersectionInImage.x;
00516 temp1.y = (double)lines[lineNumber1].start.y - intersectionInImage.y;
00517 temp2.x = (double)lines[lineNumber1].end.x - intersectionInImage.x;
00518 temp2.y = (double)lines[lineNumber1].end.y - intersectionInImage.y;
00519 if ( temp1*temp2 < 0 && temp1.abs() > 10 && temp2.abs() > 10 )
00520 {
00521 bothSidesOfLine1=true;
00522 }
00523 else
00524 {
00525 bothSidesOfLine1=false;
00526 }
00527
00528 temp1.x = (double)lines[lineNumber2].start.x - intersectionInImage.x;
00529 temp1.y = (double)lines[lineNumber2].start.y - intersectionInImage.y;
00530 temp2.x = (double)lines[lineNumber2].end.x - intersectionInImage.x;
00531 temp2.y = (double)lines[lineNumber2].end.y - intersectionInImage.y;
00532 if ( temp1*temp2 < 0 && temp1.abs() > 10 && temp2.abs() > 10 )
00533 {
00534 bothSidesOfLine2=true;
00535 }
00536 else
00537 {
00538 bothSidesOfLine2=false;
00539 }
00540
00541
00542 LinesPercept::CrossingCharacteristic side1 = LinesPercept::dontKnow;
00543 LinesPercept::CrossingCharacteristic side2 = LinesPercept::dontKnow;
00544 LinesPercept::CrossingCharacteristic side3 = LinesPercept::dontKnow;
00545 LinesPercept::CrossingCharacteristic side4 = LinesPercept::dontKnow;
00546
00547 if ( intersectionInImage.x < 0 || intersectionInImage.y < 0 || intersectionInImage.x >= image.cameraInfo.resolutionWidth || intersectionInImage.y >= image.cameraInfo.resolutionHeight )
00548 {
00549 if (linesPercept.numberOfLineCrossings<linesPercept.maxNumberOfLineCrossings)
00550 {
00551 linesPercept.lineCrossings[linesPercept.numberOfLineCrossings].locationOnField = intersectionOnField;
00552 linesPercept.lineCrossings[linesPercept.numberOfLineCrossings].locationInImage = Vector2<int>((int)intersectionInImage.x,(int)intersectionInImage.y);
00553 linesPercept.lineCrossings[linesPercept.numberOfLineCrossings].angleOnField = angleOnField;
00554 linesPercept.lineCrossings[linesPercept.numberOfLineCrossings].angleInImage1 = angleOfLine1;
00555 linesPercept.lineCrossings[linesPercept.numberOfLineCrossings].angleInImage2 = angleOfLine2;
00556 linesPercept.lineCrossings[linesPercept.numberOfLineCrossings].side1 = side1;
00557 linesPercept.lineCrossings[linesPercept.numberOfLineCrossings].side2 = side2;
00558 linesPercept.lineCrossings[linesPercept.numberOfLineCrossings].side3 = side3;
00559 linesPercept.lineCrossings[linesPercept.numberOfLineCrossings].side4 = side4;
00560 linesPercept.lineCrossings[linesPercept.numberOfLineCrossings].outOfImage = true;
00561 linesPercept.numberOfLineCrossings++;
00562 }
00563 }
00564 else
00565 {
00566
00567
00568 Vector2<int> temp((int)intersectionInImage.x,(int)intersectionInImage.y);
00569 int lineSize = Geometry::calculateLineSize(temp, cameraMatrix, image.cameraInfo);
00570
00571 if (firstLineIsLeft)
00572 {
00573 if (bothSidesOfLine1)
00574 {
00575 side1 = LinesPercept::lineOnThisSide;
00576 side3 = LinesPercept::lineOnThisSide;
00577 }
00578 else
00579 {
00580 doVerificationScan(intersectionInImage, directionOfLine1, directionOfLine2, lineSize, side1, cameraMatrix, image);
00581 doVerificationScan(intersectionInImage, directionOfLine1 * -1.0, directionOfLine2, lineSize, side3, cameraMatrix, image);
00582 }
00583 if (bothSidesOfLine2)
00584 {
00585 side2 = LinesPercept::lineOnThisSide;
00586 side4 = LinesPercept::lineOnThisSide;
00587 }
00588 else
00589 {
00590 doVerificationScan(intersectionInImage, directionOfLine2 * -1.0, directionOfLine1, lineSize, side2, cameraMatrix, image);
00591 doVerificationScan(intersectionInImage, directionOfLine2, directionOfLine1, lineSize, side4, cameraMatrix, image);
00592 }
00593 }
00594 else
00595 {
00596
00597 if (bothSidesOfLine1)
00598 {
00599 side2 = LinesPercept::lineOnThisSide;
00600 side4 = LinesPercept::lineOnThisSide;
00601 }
00602 else
00603 {
00604 doVerificationScan(intersectionInImage, directionOfLine1 * -1.0, directionOfLine2, lineSize, side2, cameraMatrix, image);
00605 doVerificationScan(intersectionInImage, directionOfLine1, directionOfLine2, lineSize, side4, cameraMatrix, image);
00606 }
00607 if (bothSidesOfLine2)
00608 {
00609 side1 = LinesPercept::lineOnThisSide;
00610 side3 = LinesPercept::lineOnThisSide;
00611 }
00612 else
00613 {
00614 doVerificationScan(intersectionInImage, directionOfLine2, directionOfLine1, lineSize, side1, cameraMatrix, image);
00615 doVerificationScan(intersectionInImage, directionOfLine2 * -1.0, directionOfLine1, lineSize, side3, cameraMatrix, image);
00616 }
00617 }
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638 if (linesPercept.numberOfLineCrossings<linesPercept.maxNumberOfLineCrossings)
00639 {
00640 linesPercept.lineCrossings[linesPercept.numberOfLineCrossings].locationOnField = intersectionOnField;
00641 linesPercept.lineCrossings[linesPercept.numberOfLineCrossings].locationInImage = Vector2<int>((int)intersectionInImage.x,(int)intersectionInImage.y);
00642 linesPercept.lineCrossings[linesPercept.numberOfLineCrossings].angleOnField = angleOnField;
00643 linesPercept.lineCrossings[linesPercept.numberOfLineCrossings].angleInImage1 = angleOfLine1;
00644 linesPercept.lineCrossings[linesPercept.numberOfLineCrossings].angleInImage2 = angleOfLine2;
00645 linesPercept.lineCrossings[linesPercept.numberOfLineCrossings].side1 = side1;
00646 linesPercept.lineCrossings[linesPercept.numberOfLineCrossings].side2 = side2;
00647 linesPercept.lineCrossings[linesPercept.numberOfLineCrossings].side3 = side3;
00648 linesPercept.lineCrossings[linesPercept.numberOfLineCrossings].side4 = side4;
00649 linesPercept.lineCrossings[linesPercept.numberOfLineCrossings].outOfImage = false;
00650 linesPercept.numberOfLineCrossings++;
00651 }
00652 }
00653
00654
00655 #ifndef NODEBUGDRAWINGS
00656 Vector2<double> intersectionOnFieldGlobal = Geometry::relative2FieldCoord(robotPose,intersectionOnField.x,intersectionOnField.y);
00657 CIRCLE(lineCrossingsField,intersectionOnFieldGlobal.x,intersectionOnFieldGlobal.y,60,3,Drawings::ps_solid,Drawings::red);
00658
00659 double angleOnFieldGlobal = angleOnField + robotPose.rotation;
00660
00661
00662 LINE(
00663 lineCrossingsField,
00664 intersectionOnFieldGlobal.x,
00665 intersectionOnFieldGlobal.y,
00666 intersectionOnFieldGlobal.x + (int)(200.0*cos(angleOnFieldGlobal)),
00667 intersectionOnFieldGlobal.y + (int)(200.0*sin(angleOnFieldGlobal)),
00668 5,
00669 Drawings::ps_solid,
00670 (side1==LinesPercept::lineOnThisSide) ? Drawings::white : ((side1==LinesPercept::noLineOnThisSide) ? Drawings::black : Drawings::light_gray)
00671 );
00672 LINE(
00673 lineCrossingsField,
00674 intersectionOnFieldGlobal.x,
00675 intersectionOnFieldGlobal.y,
00676 intersectionOnFieldGlobal.x + (int)(200.0*cos(angleOnFieldGlobal+pi_2)),
00677 intersectionOnFieldGlobal.y + (int)(200.0*sin(angleOnFieldGlobal+pi_2)),
00678 5,
00679 Drawings::ps_solid,
00680 (side2==LinesPercept::lineOnThisSide) ? Drawings::white : ((side2==LinesPercept::noLineOnThisSide) ? Drawings::black : Drawings::light_gray)
00681 );
00682 LINE(
00683 lineCrossingsField,
00684 intersectionOnFieldGlobal.x,
00685 intersectionOnFieldGlobal.y,
00686 intersectionOnFieldGlobal.x + (int)(200.0*cos(angleOnFieldGlobal+pi)),
00687 intersectionOnFieldGlobal.y + (int)(200.0*sin(angleOnFieldGlobal+pi)),
00688 5,
00689 Drawings::ps_solid,
00690 (side3==LinesPercept::lineOnThisSide) ? Drawings::white : ((side3==LinesPercept::noLineOnThisSide) ? Drawings::black : Drawings::light_gray)
00691 );
00692 LINE(
00693 lineCrossingsField,
00694 intersectionOnFieldGlobal.x,
00695 intersectionOnFieldGlobal.y,
00696 intersectionOnFieldGlobal.x + (int)(200.0*cos(angleOnFieldGlobal+pi3_2)),
00697 intersectionOnFieldGlobal.y + (int)(200.0*sin(angleOnFieldGlobal+pi3_2)),
00698 5,
00699 Drawings::ps_solid,
00700 (side4==LinesPercept::lineOnThisSide) ? Drawings::white : ((side4==LinesPercept::noLineOnThisSide) ? Drawings::black : Drawings::light_gray)
00701 );
00702 #endif
00703
00704 }
00705
00706 bool VLCLineFinder_DeterministicApproach::handleCenterCircle(const Vector2<double> & centerOnField, const CameraMatrix& cameraMatrix, const Image& image)
00707 {
00708 int i;
00709 Vector2<int> pointOnField;
00710 Vector2<int> center2((int)centerOnField.x,(int)centerOnField.y);
00711 double distance;
00712 for (i=0; i<numberOfLinePoints; i++)
00713 {
00714 if (Geometry::calculatePointOnField(linePoints[i].pointOnLine.x, linePoints[i].pointOnLine.y, cameraMatrix, image.cameraInfo, pointOnField))
00715 {
00716 distance = (pointOnField-center2).abs();
00717 if ( distance > 80 && distance < 250 )
00718 {
00719 linePoints[i].belongsToLineNo = -2;
00720 }
00721 }
00722 }
00723 return true;
00724 }
00725
00726 bool VLCLineFinder_DeterministicApproach::handleCenterCircle(const CameraMatrix& cameraMatrix, const Image& image, const RobotPose & robotPose)
00727 {
00728 int i,j;
00729 Vector2<double> temp1,temp2;
00730 Vector2<int> temp3,temp4;
00731
00732 double orientationOfCircleCandidate1 = 0.0;
00733
00734 bool candidateFound1 = false;
00735 bool candidateFound2 = false;
00736
00737 double distanceToMiddleLine;
00738 int possibleMiddleLine = 0;
00739 int numberOfPointsOfPossibleMiddleLine;
00740 double bestDistanceToPossibleMiddleLine;
00741
00742 bool possibleTangent[maxNumberOfLines*2];
00743 for (i=0; i<numberOfLineFragments; i++)
00744 {
00745 possibleTangent[i]=false;
00746 }
00747 Geometry::Line linesOnField[maxNumberOfLines*2];
00748 bool onFieldAvailable[maxNumberOfLines*2];
00749 Vector2<double> base,direction;
00750 for (i=0; i<numberOfLineFragments; i++)
00751 {
00752 onFieldAvailable[i] = calculateLineOnField(lineFragments[i].base, lineFragments[i].normal, base, direction, cameraMatrix, image);
00753 linesOnField[i].base = base;
00754 linesOnField[i].direction = direction.rotateLeft();
00755 }
00756
00757
00758
00759
00760 int numberOfGoodCrossings = 0;
00761 double deviation1 = 0.0;
00762 double deviation2 = 0.0;
00763 Vector2<double> intersection,centerCandidate1,centerCandidate2;
00764 double distance1,distance2,projection;
00765 for (i=0; i<numberOfLineFragments; i++)
00766 {
00767 if (!onFieldAvailable[i])
00768 {
00769 continue;
00770 }
00771 for (j=i+1; j<numberOfLineFragments; j++)
00772 {
00773 if (!onFieldAvailable[j])
00774 {
00775 continue;
00776 }
00777 Geometry::getIntersectionOfLines(linesOnField[i], linesOnField[j], intersection);
00778 distance1 = (linesOnField[i].base-intersection).abs();
00779 distance2 = (linesOnField[j].base-intersection).abs();
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789 projection = fabs( linesOnField[i].direction * linesOnField[j].direction );
00790
00791
00792 if ( (distance1 < 260) && (distance1 > 130) && (distance2 < 260) && (distance2 > 130) )
00793 {
00794 if (projection < 0.4)
00795 {
00796 continue;
00797 }
00798 deviation1 += fabs(distance1-180) + fabs(distance2-180);
00799 if (numberOfGoodCrossings>0)
00800 {
00801 deviation2 += (centerCandidate1 - intersection).abs();
00802 }
00803 centerCandidate1 = (centerCandidate1 * (double)numberOfGoodCrossings + intersection) / (numberOfGoodCrossings+1.0);
00804 numberOfGoodCrossings++;
00805 possibleTangent[i]=true;
00806 possibleTangent[j]=true;
00807 }
00808 }
00809 }
00810 if (numberOfGoodCrossings>0)
00811 {
00812 deviation1 /= numberOfGoodCrossings*2;
00813 deviation2 /= numberOfGoodCrossings;
00814 }
00815
00816
00817 if (numberOfGoodCrossings>=1 && deviation1<100 && deviation2<200)
00818 {
00819 bestDistanceToPossibleMiddleLine = 10000.0;
00820 numberOfPointsOfPossibleMiddleLine = 0;
00821
00822 for (i=0; i<numberOfLineFragments; i++)
00823 {
00824 if (!onFieldAvailable[i])
00825 {
00826 continue;
00827 }
00828 distanceToMiddleLine = fabs( (centerCandidate1-linesOnField[i].base)*linesOnField[i].direction );
00829 if (distanceToMiddleLine < 60)
00830 {
00831
00832 if (lineFragments[i].numberOfPoints <= numberOfPointsOfPossibleMiddleLine)
00833 {
00834 continue;
00835 }
00836 if ( Geometry::calculatePointOnField(lineFragments[i].start.x,lineFragments[i].start.y,cameraMatrix,image.cameraInfo,temp3)
00837 && Geometry::calculatePointOnField(lineFragments[i].end.x,lineFragments[i].end.y,cameraMatrix,image.cameraInfo,temp4) )
00838 {
00839 temp1.x = centerCandidate1.x - (double)temp3.x;
00840 temp1.y = centerCandidate1.y - (double)temp3.y;
00841 temp2.x = centerCandidate1.x - (double)temp4.x;
00842 temp2.y = centerCandidate1.y - (double)temp4.y;
00843 if (temp1 * temp2 < 0)
00844 {
00845 candidateFound1=true;
00846 orientationOfCircleCandidate1 = pi_2 + atan2(linesOnField[i].direction.y,linesOnField[i].direction.x);
00847 bestDistanceToPossibleMiddleLine = distanceToMiddleLine;
00848 possibleMiddleLine = i;
00849 numberOfPointsOfPossibleMiddleLine = lineFragments[i].numberOfPoints;
00850 }
00851 }
00852 }
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873 }
00874 }
00875
00876
00877
00878 if (candidateFound1 && bestDistanceToPossibleMiddleLine > 1.0)
00879 {
00880 temp1 = centerCandidate1 - linesOnField[possibleMiddleLine].base;
00881 temp2 = linesOnField[possibleMiddleLine].direction;
00882 centerCandidate1 -= temp2*(temp1*temp2);
00883 }
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959 Vector2<int> circleCandidateInImage,temp;
00960 Vector2<double> circleOnFieldGlobal;
00961 if (candidateFound1)
00962 {
00963 for (i=0; i<numberOfLineFragments; i++)
00964 {
00965 distance1 = (centerCandidate1-linesOnField[i].base).abs();
00966 if ( possibleTangent[i] || (distance1<280 && distance1>120) )
00967 {
00968 lineFragments[i].lineFragmentAlreadyConsidered = true;
00969 }
00970 }
00971
00972
00973
00974
00975 fromOwnHandling.x = (int)centerCandidate1.x;
00976 fromOwnHandling.y = (int)centerCandidate1.y;
00977 centerCircleOrientation = orientationOfCircleCandidate1;
00978
00979
00980 foundByOwnHandling = doVerificationScanForCircle(fromOwnHandling,centerCircleOrientation,cameraMatrix,image);
00981
00982 if (foundByOwnHandling)
00983 {
00984 double orientationOnField = centerCircleOrientation + robotPose.rotation;
00985
00986 circleOnFieldGlobal = Geometry::relative2FieldCoord(robotPose,centerCandidate1.x,centerCandidate1.y);
00987
00988 lastSeenCircleGlobal = circleOnFieldGlobal;
00989 lastSeenCircleOrientationGlobal = orientationOnField;
00990 framesSinceLastSeen = 0;
00991
00992 CIRCLE(circlePoints_Field,circleOnFieldGlobal.x,circleOnFieldGlobal.y,180,3,Drawings::ps_solid,Drawings::skyblue);
00993 LINE(circlePoints_Field,(circleOnFieldGlobal.x+180*cos(orientationOnField)),(circleOnFieldGlobal.y+180*sin(orientationOnField)),(circleOnFieldGlobal.x-180*cos(orientationOnField)),(circleOnFieldGlobal.y-180*sin(orientationOnField)),3,Drawings::ps_solid,Drawings::skyblue);
00994
00995 temp.x = (int)centerCandidate1.x;
00996 temp.y = (int)centerCandidate1.y;
00997 Geometry::calculatePointInImage(temp,cameraMatrix,image.cameraInfo,circleCandidateInImage);
00998 CIRCLE(circlePoints_image,circleCandidateInImage.x,circleCandidateInImage.y,3,1,Drawings::ps_solid,Drawings::skyblue);
00999
01000
01001
01002
01003
01004
01005 }
01006
01007 }
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037 if (!candidateFound1 && framesSinceLastSeen<60)
01038 {
01039 Drawings::Color c;
01040 if (framesSinceLastSeen<2)
01041 {
01042 c = Drawings::white;
01043 }
01044 else if (framesSinceLastSeen<10)
01045 {
01046 c = Drawings::light_gray;
01047 }
01048 else if (framesSinceLastSeen<30)
01049 {
01050 c = Drawings::gray;
01051 }
01052 else
01053 {
01054 c = Drawings::dark_gray;
01055 }
01056 CIRCLE(circlePoints_Field,lastSeenCircleGlobal.x,lastSeenCircleGlobal.y,180,3,Drawings::ps_solid,c);
01057 LINE(circlePoints_Field,(lastSeenCircleGlobal.x+180*cos(lastSeenCircleOrientationGlobal)),(lastSeenCircleGlobal.y+180*sin(lastSeenCircleOrientationGlobal)),(lastSeenCircleGlobal.x-180*cos(lastSeenCircleOrientationGlobal)),(lastSeenCircleGlobal.y-180*sin(lastSeenCircleOrientationGlobal)),3,Drawings::ps_solid,c);
01058
01059 }
01060
01061
01062
01063
01064 return (candidateFound1 || candidateFound2);
01065 }
01066
01067 void VLCLineFinder_DeterministicApproach::addCenterCirclePercept(LinesPercept & linesPercept, const CameraMatrix& cameraMatrix, const Image& image)
01068 {
01069 int i;
01070 if (foundByCircleFinder)
01071 {
01072
01073 double orientation = 0.0;
01074 bool orientationFound = false;
01075
01076 Vector2<double> fromCircleFinder2((double)fromCircleFinder.x, (double)fromCircleFinder.y);
01077
01078 double distance;
01079 double smallestDistance = 10000.0;
01080
01081 Geometry::Line linesOnField[maxNumberOfLines];
01082 bool onFieldAvailable[maxNumberOfLines];
01083 Vector2<double> base,direction;
01084 for (i=0; i<numberOfLines; i++)
01085 {
01086 onFieldAvailable[i] = calculateLineOnField(i, base, direction, cameraMatrix, image);
01087 linesOnField[i].base = base;
01088 linesOnField[i].direction = direction.rotateLeft();
01089 }
01090 for (i=0; i<numberOfLines; i++)
01091 {
01092 distance = fabs( (fromCircleFinder2-linesOnField[i].base)*linesOnField[i].direction );
01093 if (distance < 80 && distance < smallestDistance)
01094 {
01095 orientationFound=true;
01096 orientation = atan2(linesOnField[i].direction.y, linesOnField[i].direction.x);
01097 orientation += pi_2;
01098 }
01099 }
01100
01101 linesPercept.centerCircle.location = fromCircleFinder;
01102 linesPercept.centerCircle.orientation = orientation;
01103 linesPercept.centerCircle.orientationKnown = orientationFound;
01104 linesPercept.centerCircleFound = true;
01105 }
01106 else if (foundByOwnHandling)
01107 {
01108 linesPercept.centerCircle.location = fromOwnHandling;
01109 linesPercept.centerCircle.orientation = centerCircleOrientation;
01110 linesPercept.centerCircle.orientationKnown = true;
01111 linesPercept.centerCircleFound = true;
01112 }
01113 }
01114
01115
01116 int VLCLineFinder_DeterministicApproach::getNumberOfLines()
01117 {
01118 return numberOfLines;
01119 }
01120
01121 void VLCLineFinder_DeterministicApproach::getLine(int number, Vector2<int> & pointOnLine, Vector2<double> & normalToLine)
01122 {
01123 pointOnLine.x = lines[number].base.x;
01124 pointOnLine.y = lines[number].base.y;
01125 normalToLine.x = lines[number].normal.x;
01126 normalToLine.y = lines[number].normal.y;
01127 }
01128
01129
01130 bool VLCLineFinder_DeterministicApproach::linesPerpendicularOnField(int lineNumber1, int lineNumber2, const CameraMatrix& cameraMatrix, const Image& image)
01131 {
01132 Vector2<double> justAPoint, direction1, direction2;
01133 if ( calculateLineOnField(lineNumber1, justAPoint, direction1, cameraMatrix, image)
01134 && calculateLineOnField(lineNumber2, justAPoint, direction2, cameraMatrix, image) )
01135 {
01136 if (fabs(direction1*direction2) < 0.5)
01137 {
01138 return true;
01139 }
01140 }
01141 return false;
01142 }
01143
01144 bool VLCLineFinder_DeterministicApproach::calculateLineOnField(int lineNumber, Vector2<double> & base, Vector2<double> & direction, const CameraMatrix& cameraMatrix, const Image& image)
01145 {
01146 Vector2<int> pointOnField1, pointOnField2, directionOnField;
01147 if ( Geometry::calculatePointOnField(lines[lineNumber].base.x, lines[lineNumber].base.y, cameraMatrix, image.cameraInfo, pointOnField1)
01148 && Geometry::calculatePointOnField((int)(lines[lineNumber].base.x+50*lines[lineNumber].normal.y), (int)(lines[lineNumber].base.y-50*lines[lineNumber].normal.x), cameraMatrix, image.cameraInfo, pointOnField2))
01149 {
01150 directionOnField = pointOnField2-pointOnField1;
01151 base.x = (double)pointOnField1.x;
01152 base.y = (double)pointOnField1.y;
01153 direction.x = (double)directionOnField.x;
01154 direction.y = (double)directionOnField.y;
01155 direction.normalize();
01156 return true;
01157 }
01158 return false;
01159 }
01160
01161
01162 bool VLCLineFinder_DeterministicApproach::calculateLineOnField(const Vector2<int> & baseInImage, const Vector2<double> & normalInImage, Vector2<double> & baseOnField, Vector2<double> & directionOnField, const CameraMatrix& cameraMatrix, const Image& image)
01163 {
01164 Vector2<int> pointOnField1, pointOnField2, directionOnFieldTemp;
01165 if ( Geometry::calculatePointOnField(baseInImage.x, baseInImage.y, cameraMatrix, image.cameraInfo, pointOnField1)
01166 && Geometry::calculatePointOnField((int)(baseInImage.x+50*normalInImage.y), (int)(baseInImage.y-50*normalInImage.x), cameraMatrix, image.cameraInfo, pointOnField2))
01167 {
01168 directionOnFieldTemp = pointOnField2-pointOnField1;
01169 baseOnField.x = (double)pointOnField1.x;
01170 baseOnField.y = (double)pointOnField1.y;
01171 directionOnField.x = (double)directionOnFieldTemp.x;
01172 directionOnField.y = (double)directionOnFieldTemp.y;
01173 directionOnField.normalize();
01174 return true;
01175 }
01176 return false;
01177 }
01178
01179 void VLCLineFinder_DeterministicApproach::doVerificationScan(const Vector2<double> & crossingPoint, const Vector2<double> & directionToScanAt, const Vector2<double> & scanningDirection, int lineSize, LinesPercept::CrossingCharacteristic & result, const CameraMatrix& cameraMatrix, const Image& image)
01180 {
01181
01182 int i,j;
01183 double scanningDistance = max(6.0, lineSize*1.5);
01184 double projection = fabs( sin( atan2(directionToScanAt.y,directionToScanAt.x) - atan2(scanningDirection.y,scanningDirection.x) ) );
01185 if (projection > 0)
01186 {
01187 scanningDistance /= projection;
01188 }
01189 double directionAngle = atan2(scanningDirection.y,scanningDirection.x);
01190
01191 int numberOfScanLines = 2;
01192 double distanceBetweenScanLines = 2.0;
01193 bool greenFound[2];
01194 bool whiteFound[2];
01195 bool robotColorFound[2];
01196 Vector2<int> actual;
01197 unsigned char y,u,v;
01198 colorClass color;
01199 Vector2<double> scanningStart;
01200 Vector2<int> scanningStart2;
01201
01202 for (i=0; i<numberOfScanLines; i++)
01203 {
01204 scanningStart = crossingPoint + directionToScanAt * (scanningDistance + i*distanceBetweenScanLines) - scanningDirection * scanningDistance;
01205 scanningStart2.x = (int)scanningStart.x;
01206 scanningStart2.y = (int)scanningStart.y;
01207 BresenhamLineScan bls(scanningStart2, directionAngle, image.cameraInfo);
01208 actual = scanningStart2;
01209
01210 greenFound[i]=false;
01211 whiteFound[i]=false;
01212 robotColorFound[i]=false;
01213
01214
01215 for (j=0; j<= (int)(2.0*scanningDistance); j++)
01216 {
01217 if ( actual.x < 0 || actual.y < 0 || actual.x >= image.cameraInfo.resolutionWidth || actual.y >= image.cameraInfo.resolutionHeight )
01218 {
01219 break;
01220 }
01221 y = colorCorrector.correct(actual.x, actual.y, 0, image.image[actual.y][0][actual.x]);
01222 u = colorCorrector.correct(actual.x, actual.y, 1, image.image[actual.y][1][actual.x]);
01223 v = colorCorrector.correct(actual.x, actual.y, 2, image.image[actual.y][2][actual.x]);
01224 color = COLOR_CLASS(y, u, v, (*bestColorTable));
01225
01226 switch (color)
01227 {
01228 case green:
01229 greenFound[i]=true;
01230 break;
01231 case white:
01232 whiteFound[i]=true;
01233 break;
01234 case red:
01235 case blue:
01236 robotColorFound[i]=true;
01237 default:
01238 break;
01239 }
01240
01241 bls.getNext(actual);
01242 }
01243 LINE(imageProcessor_lines,scanningStart2.x,scanningStart2.y,actual.x,actual.y,1,Drawings::ps_solid,Drawings::gray);
01244 }
01245
01246
01247 bool robotInTheWay = false;
01248 bool greenSeen = false;
01249 bool whiteSeen = false;
01250 bool whiteAlwaysSeen = true;
01251 for (i=0; i<numberOfScanLines; i++)
01252 {
01253 robotInTheWay = robotInTheWay || robotColorFound[i];
01254 greenSeen = greenSeen || greenFound[i];
01255 whiteSeen = whiteSeen || whiteFound[i];
01256 whiteAlwaysSeen = whiteAlwaysSeen && whiteFound[i];
01257 }
01258 if (robotInTheWay)
01259 {
01260 result = LinesPercept::dontKnow;
01261 }
01262 else
01263 {
01264 if ( lineSize > 4 )
01265 {
01266 if (!whiteAlwaysSeen)
01267 {
01268 if (greenSeen)
01269 {
01270 result = LinesPercept::noLineOnThisSide;
01271 }
01272 else
01273 {
01274 result = LinesPercept::dontKnow;
01275 }
01276 }
01277 else
01278 {
01279 if (greenSeen)
01280 {
01281 result = LinesPercept::lineOnThisSide;
01282 }
01283 else
01284 {
01285 result = LinesPercept::dontKnow;
01286 }
01287 }
01288 }
01289 else
01290 {
01291 if (!whiteSeen)
01292 {
01293 if (greenSeen)
01294 {
01295 result = LinesPercept::noLineOnThisSide;
01296 }
01297 else
01298 {
01299 result = LinesPercept::dontKnow;
01300 }
01301 }
01302 else
01303 {
01304 if (greenSeen)
01305 {
01306 result = LinesPercept::lineOnThisSide;
01307 }
01308 else
01309 {
01310 result = LinesPercept::dontKnow;
01311 }
01312 }
01313 }
01314 }
01315 }
01316
01317 bool VLCLineFinder_DeterministicApproach::doVerificationScanForCircle(
01318 const Vector2<int> & circleOnFieldRelative,
01319 double orientation,
01320 const CameraMatrix& cameraMatrix,
01321 const Image& image)
01322 {
01323 int i,j;
01324
01325 const int numberOfScanlines = 4;
01326
01327 bool imageBorderFound[numberOfScanlines], circleLineFound[numberOfScanlines], robotColorFound[numberOfScanlines];
01328
01329 double scanAngle[numberOfScanlines];
01330 scanAngle[0] = orientation + 0.33333 * pi;
01331 scanAngle[1] = orientation + 0.66666 * pi;
01332 scanAngle[2] = orientation - 0.33333 * pi;
01333 scanAngle[3] = orientation - 0.66666 * pi;
01334 Vector2<double> scanDirection[numberOfScanlines];
01335 Vector2<int> scanningStart[numberOfScanlines],scanningEnd[numberOfScanlines];
01336 Vector2<int> scanningStartOnField[numberOfScanlines],scanningEndOnField[numberOfScanlines];
01337 double scanDistance;
01338
01339 for (i=0; i<numberOfScanlines; i++)
01340 {
01341 imageBorderFound[i] = circleLineFound[i] = robotColorFound[i] = false;
01342
01343 scanDirection[i].x = cos(scanAngle[i]);
01344 scanDirection[i].y = sin(scanAngle[i]);
01345 scanAngle[i] = normalize(scanAngle[i]);
01346 if (scanAngle[i] > -1.0 * pi_2 && scanAngle[i] < pi_2)
01347 {
01348 scanDistance = 500.0;
01349 }
01350 else
01351 {
01352 scanDistance = 300.0;
01353 }
01354 scanningStartOnField[i].x = int(circleOnFieldRelative.x + 50.0*scanDirection[i].x);
01355 scanningStartOnField[i].y = int(circleOnFieldRelative.y + 50.0*scanDirection[i].y);
01356 scanningEndOnField[i].x = int(circleOnFieldRelative.x + scanDistance*scanDirection[i].x);
01357 scanningEndOnField[i].y = int(circleOnFieldRelative.y + scanDistance*scanDirection[i].y);
01358 Geometry::calculatePointInImage(scanningStartOnField[i],cameraMatrix,image.cameraInfo,scanningStart[i]);
01359 Geometry::calculatePointInImage(scanningEndOnField[i],cameraMatrix,image.cameraInfo,scanningEnd[i]);
01360
01361 Vector2<int> actual = scanningStart[i];
01362 unsigned char y,u,v;
01363 colorClass color;
01364
01365 BresenhamLineScan bls(scanningStart[i], scanningEnd[i]);
01366
01367 bool firstGreen = false;
01368 bool whiteFound = false;
01369
01370 int pixelsToScan = max(15,bls.numberOfPixels);
01371
01372 for (j=0; j<=pixelsToScan; j++)
01373 {
01374 if ( actual.x < 0 || actual.y < 0 || actual.x >= image.cameraInfo.resolutionWidth || actual.y >= image.cameraInfo.resolutionHeight )
01375 {
01376 imageBorderFound[i] = true;
01377 break;
01378 }
01379 y = colorCorrector.correct(actual.x, actual.y, 0, image.image[actual.y][0][actual.x]);
01380 u = colorCorrector.correct(actual.x, actual.y, 1, image.image[actual.y][1][actual.x]);
01381 v = colorCorrector.correct(actual.x, actual.y, 2, image.image[actual.y][2][actual.x]);
01382 color = COLOR_CLASS(y, u, v, (*bestColorTable));
01383
01384 switch (color)
01385 {
01386 case green:
01387 if (whiteFound)
01388 {
01389
01390 circleLineFound[i] = true;
01391 }
01392 else
01393 {
01394 firstGreen = true;
01395 }
01396 break;
01397 case white:
01398 if (firstGreen)
01399 {
01400 whiteFound=true;
01401 }
01402 break;
01403 case red:
01404 case blue:
01405 robotColorFound[i]=true;
01406 default:
01407 break;
01408 }
01409
01410 bls.getNext(actual);
01411 }
01412 LINE(circlePoints_image,scanningStart[i].x,scanningStart[i].y,actual.x,actual.y,1,Drawings::ps_solid,Drawings::gray);
01413 }
01414
01415
01416
01417
01418
01419
01420 bool result = (imageBorderFound[0] || circleLineFound[0])
01421 && (imageBorderFound[1] || circleLineFound[1])
01422 && (imageBorderFound[2] || circleLineFound[2])
01423 && (imageBorderFound[3] || circleLineFound[3]);
01424
01425
01426
01427 if (result)
01428 {
01429 circleCount++;
01430 }
01431
01432 return result;
01433 }
01434
01435
01436