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