00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "VLCRobotSpecialist.h"
00010
00011 #ifdef RS_DEBUG
00012 #ifndef APERIOS1_3_2
00013 #pragma message( "compiling VLCRobotSpecialist with debugging" )
00014 #endif
00015 #endif
00016
00017 #ifdef RS_DEBUG_CONSOLE
00018 #ifndef APERIOS1_3_2
00019 #pragma message( "compiling VLCRobotSpecialist with console outputs" )
00020 #endif
00021 #endif
00022
00023
00024 #define RS_RADIAL_ON_IMAGE
00025
00026
00027 #define min(a, b)(((a) < (b))?(a):(b))
00028 #define max(a, b)(((a) > (b))?(a):(b))
00029
00030 VLCRobotSpecialist::VLCRobotSpecialist
00031 (
00032 const ColorCorrector& colorCorrector_,
00033 const Image& image_,
00034 const ImageInfo& imageInfo_,
00035 const ColorTable& colorTable_,
00036 const CameraMatrix& cameraMatrix_,
00037 const CameraMatrix& prevCameraMatrix_,
00038 LinesPercept& linesPercept_,
00039 PlayersPercept& playersPercept_,
00040 const RobotPose& robotPose_,
00041 const List<GreenChangeEvent>& greenChangeEvents_)
00042 :
00043 colorCorrector(colorCorrector_),
00044 image(image_),
00045 imageInfo(imageInfo_),
00046 colorTable(colorTable_),
00047 cameraMatrix(cameraMatrix_),
00048 prevCameraMatrix(prevCameraMatrix_),
00049 linesPercept(linesPercept_),
00050 playersPercept(playersPercept_),
00051 robotPose(robotPose_),
00052 greenChangeEvents(greenChangeEvents_)
00053 {
00054 }
00055
00056 void VLCRobotSpecialist::reset ()
00057 {
00058
00059 topIndex = RS_NUM_CANDIDATES / 2 + 1;
00060 bottomIndex = RS_NUM_CANDIDATES / 2;
00061 }
00062
00063 void VLCRobotSpecialist::scan ()
00064 {
00065
00066 Geometry::Line scanLine;
00067 Geometry::Line clipLine;
00068
00069 #ifdef RS_RADIAL_ON_IMAGE
00070 Vector2<int> startPoint = Vector2<int>(image.cameraInfo.resolutionWidth / 2, image.cameraInfo.resolutionHeight - 1);
00071 #else
00072 Vector2<int> startPoint;
00073
00074 Geometry::calculatePointInImage (Vector2<int>(475, 0), cameraMatrix, CameraInfo::CameraInfo (), startPoint);
00075
00076 startPoint.y = startPoint.y;
00077 #endif
00078 Vector2<int> endPoint;
00079
00080
00081 reset ();
00082
00083
00084 scanLine.base.x = startPoint.x;
00085 scanLine.base.y = startPoint.y;
00086
00087 int i = -1;
00088 double startAngle = -pi_2;
00089 double stopAngle = pi_2;
00090 double stepAngle = (stopAngle - startAngle) / RS_NUM_SCAN_LINES;
00091
00092 for (double angle = startAngle; angle <= stopAngle; angle += stepAngle)
00093 {
00094 CRASH_CHECK(i); i++;
00095
00096
00097 startPoint.x = (int) scanLine.base.x;
00098 startPoint.y = (int) scanLine.base.y;
00099
00100
00101 #ifdef RS_RADIAL_ON_IMAGE
00102 scanLine.direction.x = sin (angle);
00103 scanLine.direction.y = cos (angle);
00104 #else
00105 Vector2<int>directionOnField;
00106 Vector2<int>directionInImage;
00107
00108 directionOnField.x = (int) (cos (angle) * 1000000);
00109 directionOnField.y = (int) (-sin (angle) * 1000000 + 475);
00110
00111
00112 Geometry::calculatePointInImage (directionOnField, cameraMatrix, CameraInfo::CameraInfo (), directionInImage);
00113
00114 scanLine.direction.x = directionInImage.x;
00115 scanLine.direction.y = directionInImage.y;
00116 #endif
00117 scanLine.normalizeDirection ();
00118
00119
00120 clipLine = imageInfo.horizon;
00121
00122 if ((scanLine.direction * clipLine.direction) == 1)
00123 continue;
00124
00125 Geometry::getIntersectionOfLines(clipLine, scanLine, endPoint);
00126
00127
00128 if (((endPoint.x < 0) || (endPoint.x >= image.cameraInfo.resolutionWidth)) || ((endPoint.y < 0) || (endPoint.y >= image.cameraInfo.resolutionHeight)))
00129 {
00130
00131 if (endPoint.x < 0)
00132 {
00133
00134 clipLine.base = Vector2<double> (0, 0);
00135 clipLine.direction = Vector2<double> (0, 1);
00136
00137 Geometry::getIntersectionOfLines(clipLine, scanLine, endPoint);
00138 }
00139 else
00140 if (endPoint.x >= image.cameraInfo.resolutionWidth)
00141 {
00142
00143 clipLine.base = Vector2<double> (image.cameraInfo.resolutionWidth, 0);
00144 clipLine.direction = Vector2<double> (0, 1);
00145
00146 Geometry::getIntersectionOfLines(clipLine, scanLine, endPoint);
00147 };
00148
00149 if (endPoint.y < 0)
00150 {
00151
00152 clipLine.base = Vector2<double> (0, 0);
00153 clipLine.direction = Vector2<double> (1, 0);
00154
00155 Geometry::getIntersectionOfLines(clipLine, scanLine, endPoint);
00156 }
00157
00158 if (endPoint.y >= image.cameraInfo.resolutionHeight)
00159 continue;
00160 };
00161
00162 if (((startPoint.x < 0) || (startPoint.x >= image.cameraInfo.resolutionWidth)) || ((startPoint.y < 0) || (startPoint.y >= image.cameraInfo.resolutionHeight)))
00163 {
00164
00165 if (startPoint.x < 0)
00166 {
00167
00168 clipLine.base = Vector2<double> (0, 0);
00169 clipLine.direction = Vector2<double> (0, 1);
00170
00171 Geometry::getIntersectionOfLines(clipLine, scanLine, startPoint);
00172 }
00173 else
00174 if (startPoint.x >= image.cameraInfo.resolutionWidth)
00175 {
00176
00177 clipLine.base = Vector2<double> (image.cameraInfo.resolutionWidth, 0);
00178 clipLine.direction = Vector2<double> (0, 1);
00179
00180 Geometry::getIntersectionOfLines(clipLine, scanLine, startPoint);
00181 };
00182
00183 if (startPoint.y >= image.cameraInfo.resolutionHeight)
00184 {
00185
00186 clipLine.base = Vector2<double> (0, image.cameraInfo.resolutionHeight - 1);
00187 clipLine.direction = Vector2<double> (1, 0);
00188
00189 Geometry::getIntersectionOfLines(clipLine, scanLine, startPoint);
00190 }
00191
00192 if (startPoint.y < 0)
00193 continue;
00194 };
00195
00196 #ifndef RS_UNIFORM_SCANLINES
00197 switch (i % 4)
00198 {
00199 case 0: {
00200 break;
00201 };
00202 case 1: {
00203 };
00204 case 3: {
00205
00206 startPoint.x = (startPoint.x + endPoint.x) / 2;
00207 startPoint.y = (startPoint.y + endPoint.y) / 2;
00208
00209 break;
00210 };
00211 case 2: {
00212
00213 startPoint.x = (startPoint.x + 3 * endPoint.x) / 4;
00214 startPoint.y = (startPoint.y + 3 * endPoint.y) / 4;
00215
00216 break;
00217 };
00218 };
00219 #endif
00220 scan (startPoint, endPoint);
00221 };
00222
00223 clusterCandidates ();
00224
00225 return;
00226 }
00227
00228 void VLCRobotSpecialist::scan (Vector2<int> startPoint)
00229 {
00230 unsigned char y, u, v;
00231 colorClass lastColor = noColor;
00232
00233 Vector2<int> endPoint;
00234 Geometry::Line scanLine;
00235
00236
00237 scanLine.base.x = startPoint.x;
00238 scanLine.base.y = startPoint.y;
00239 scanLine.direction.x = - imageInfo.horizon.direction.y;
00240 scanLine.direction.y = imageInfo.horizon.direction.x;
00241
00242
00243 Geometry::getIntersectionOfLines (imageInfo.horizon, scanLine, endPoint);
00244
00245
00246 BresenhamLineScan bresenhamScanLine = BresenhamLineScan (startPoint, endPoint);
00247 Vector2<int> actual = startPoint;
00248
00249 Vector2<int> footPoint = startPoint;
00250
00251 for (int i = 0; i <= bresenhamScanLine.numberOfPixels; ++i)
00252 {
00253 CRASH_CHECK(i);
00254
00255 if (actual.x < 0 || actual.x >= image.cameraInfo.resolutionWidth || actual.y < 0 || actual.y >= image.cameraInfo.resolutionHeight)
00256 y = u = v = 0;
00257 else
00258 {
00259 y = colorCorrector.correct(actual.x, actual.y, 0, image.image[actual.y][0][actual.x]);
00260 u = colorCorrector.correct(actual.x, actual.y, 1, image.image[actual.y][1][actual.x]);
00261 v = colorCorrector.correct(actual.x, actual.y, 2, image.image[actual.y][2][actual.x]);
00262 }
00263 colorClass color = COLOR_CLASS(y, u, v);
00264
00265 if ((color == green) || (color == orange))
00266 {
00267 footPoint = actual;
00268 };
00269
00270 if ((color == blue) || (color == red))
00271 {
00272 if ((color != lastColor) || (color == noColor))
00273 {
00274
00275 RobotCandidate candidate;
00276
00277 candidate.footPoint = footPoint;
00278 candidate.candidateStart = actual;
00279 candidate.color = color;
00280
00281 addCandidate (candidate);
00282
00283 lastColor = color;
00284 }
00285 }
00286
00287 bresenhamScanLine.getNext (actual);
00288 }
00289
00290 #ifdef RS_DEBUG
00291 LINE(imageProcessor_robot_detection,
00292 startPoint.x, startPoint.y, endPoint.x, endPoint.y,
00293 1, Drawings::ps_solid, Drawings::blue );
00294 #endif
00295
00296 return;
00297 }
00298
00299 void VLCRobotSpecialist::scan (Vector2<int> startPoint, Vector2<int> endPoint)
00300 {
00301
00302 BresenhamLineScan scanLine = BresenhamLineScan (startPoint, endPoint);
00303 Vector2<int> actual = startPoint;
00304
00305 unsigned char y, u, v;
00306
00307 Vector2<int> lastGreenPosition;
00308 int lastGreenCount = -1;
00309 bool searchForGreen = false;
00310
00311
00312 if (actual.x < 0 || actual.x >= image.cameraInfo.resolutionWidth || actual.y < 0 || actual.y >= image.cameraInfo.resolutionHeight)
00313 y = u = v = 0;
00314 else
00315 {
00316 y = colorCorrector.correct(actual.x, actual.y, 0, image.image[actual.y][0][actual.x]);
00317 u = colorCorrector.correct(actual.x, actual.y, 1, image.image[actual.y][1][actual.x]);
00318 v = colorCorrector.correct(actual.x, actual.y, 2, image.image[actual.y][2][actual.x]);
00319 }
00320 colorClass color = COLOR_CLASS(y, u, v);
00321
00322 if (color != green)
00323 return;
00324
00325 double threshold = RS_NGP_TH_START;
00326
00327 for (int i = 0; i <= scanLine.numberOfPixels; ++i)
00328 {
00329 CRASH_CHECK(i);
00330
00331
00332 if (actual.x < 0 || actual.x >= image.cameraInfo.resolutionWidth || actual.y < 0 || actual.y >= image.cameraInfo.resolutionHeight)
00333 y = u = v = 0;
00334 else
00335 {
00336 y = colorCorrector.correct(actual.x, actual.y, 0, image.image[actual.y][0][actual.x]);
00337 u = colorCorrector.correct(actual.x, actual.y, 1, image.image[actual.y][1][actual.x]);
00338 v = colorCorrector.correct(actual.x, actual.y, 2, image.image[actual.y][2][actual.x]);
00339 }
00340 colorClass color = COLOR_CLASS(y, u, v);
00341
00342
00343 #ifndef RS_DEBUG_DRAW_RADIAL_SCANLINES_ONLY
00344
00345 if ((color == green) || (color == noColor) || (searchForGreen))
00346 {
00347 if (color == green)
00348 {
00349 #ifdef RS_FIXED_NO_GREEN_THRESHOLD
00350 if (i - lastGreenCount < threshold)
00351 #else
00352 if (i - lastGreenCount < 2 + (1.0 - ((double) i / (double) scanLine.numberOfPixels)) * 7.5)
00353 #endif
00354 lastGreenCount = -1;
00355
00356 searchForGreen = false;
00357 }
00358 }
00359 else
00360 {
00361
00362 if (lastGreenCount < 0)
00363 {
00364 lastGreenCount = i;
00365 lastGreenPosition = actual;
00366 }
00367
00368 #ifdef RS_FIXED_NO_GREEN_THRESHOLD
00369 if (i - lastGreenCount >= RS_NO_GREEN_PIXEL_THRESHOLD)
00370 #else
00371 if (i - lastGreenCount >= threshold)
00372 #endif
00373 {
00374
00375 scan (lastGreenPosition);
00376
00377 searchForGreen = true;
00378 }
00379 }
00380 #endif
00381
00382 scanLine.getNext (actual);
00383
00384 threshold -= (RS_NGP_TH_START - RS_NGP_TH_STOP) / scanLine.numberOfPixels;
00385 };
00386
00387 #ifdef RS_DEBUG
00388 LINE(imageProcessor_robot_detection,
00389 startPoint.x, startPoint.y, endPoint.x, endPoint.y,
00390 1, Drawings::ps_solid, Drawings::blue );
00391 #endif
00392
00393 return;
00394 }
00395
00396 void VLCRobotSpecialist::addCandidate (RobotCandidate candidate)
00397 {
00398 int index;
00399
00400
00401 if (candidate.lineID > 0)
00402 index = topIndex;
00403 else
00404 index = bottomIndex;
00405
00406
00407 if ((index > 0) && (index < RS_NUM_CANDIDATES))
00408 {
00409
00410 candidates[index] = candidate;
00411
00412
00413 if (candidate.lineID > 0)
00414 topIndex++;
00415 else
00416 bottomIndex--;
00417 }
00418 else
00419 {
00420
00421 RECTANGLE (imageProcessor_robot_detection, candidate.footPoint.x - 2, candidate.footPoint.y - 2, candidate.footPoint.x + 2, candidate.footPoint.y + 2, 4, Drawings::ps_solid, Drawings::gray);
00422 }
00423
00424
00425 #ifdef RS_DEBUG
00426 {
00427 if (candidate.color == blue)
00428 {
00429 #ifdef RS_DEBUG_SHOW_START_RUN
00430 CIRCLE (imageProcessor_robot_detection, candidate.candidateStart.x, candidate.candidateStart.y, 1, 1, Drawings::ps_dot, Drawings::blue);
00431 #endif
00432
00433 #ifdef RS_DEBUG_SHOW_RUNS
00434 LINE (imageProcessor_robot_detection, candidate.candidateStart.x, candidate.candidateStart.y, candidate.candidateStop.x, candidate.candidateStop.y, 1, Drawings::ps_solid, Drawings::blue);
00435 #endif
00436 }
00437 else
00438 {
00439 #ifdef RS_DEBUG_SHOW_START_RUN
00440 CIRCLE (imageProcessor_robot_detection, candidate.candidateStart.x, candidate.candidateStart.y, 1, 1, Drawings::ps_dot, Drawings::red);
00441 #endif
00442
00443 #ifdef RS_DEBUG_SHOW_RUNS
00444 LINE (imageProcessor_robot_detection, candidate.candidateStart.x, candidate.candidateStart.y, candidate.candidateStop.x, candidate.candidateStop.y, 1, Drawings::ps_solid, Drawings::red);
00445 #endif
00446 }
00447 }
00448 #endif
00449 }
00450
00451 bool VLCRobotSpecialist::findNearestFootPoint (Vector2<int> &footPoint)
00452 {
00453 enum Gradient
00454 {
00455 equal,
00456 up,
00457 down
00458 };
00459
00460 Gradient leftGradient = equal, rightGradient = equal;
00461
00462 GreenChangeEvent lastLeft, lastRight;
00463 int delta;
00464
00465 int orgLineID;
00466
00467 bool nextLeftStepFound = false;
00468 bool nextRightStepFound = false;
00469
00470 Vector2<int> maxLeftPoint;
00471 int maxLeftDistance;
00472
00473 Vector2<int> maxRightPoint;
00474 int maxRightDistance;
00475
00476 GreenChangeEvent tmpEvent;
00477
00478 int i = 0;
00479
00480
00481 while (footIterator)
00482 {
00483 CRASH_CHECK(i); i++;
00484
00485 GreenChangeEvent event = greenChangeEvents[footIterator];
00486
00487
00488 if (event.startEvent)
00489 if (event.positionOnImage == footPoint)
00490 {
00491
00492 orgLineID = event.lineID;
00493
00494
00495 maxLeftPoint = footPoint;
00496 maxLeftDistance = event.distanceToHorizon;
00497
00498 maxRightPoint = footPoint;
00499 maxRightDistance = event.distanceToHorizon;
00500
00501 List<GreenChangeEvent>::Pos leftIter = footIterator;
00502 List<GreenChangeEvent>::Pos rightIter = footIterator;
00503
00504 lastLeft = event;
00505 lastRight = event;
00506
00507 leftIter--;
00508 rightIter++;
00509
00510 int j = 0;
00511
00512
00513 while (leftIter | rightIter)
00514 {
00515 CRASH_CHECK(j); j++;
00516
00517
00518 int k = 0;
00519
00520 while (leftIter)
00521 {
00522 CRASH_CHECK(k); k++;
00523 event = greenChangeEvents[leftIter];
00524
00525
00526 if (lastLeft.lineID > ((GreenChangeEvent)greenChangeEvents[leftIter]).lineID + 1)
00527 {
00528
00529 leftIter++;
00530
00531
00532 if (!((GreenChangeEvent)greenChangeEvents[leftIter]).startEvent ||
00533 (((GreenChangeEvent)greenChangeEvents[leftIter]).lineID == lastLeft.lineID))
00534 {
00535
00536 #ifdef RS_DEBUG_FEET
00537 LINE (imageProcessor_robot_detection, lastLeft.positionOnImage.x, lastLeft.positionOnImage.y, greenChangeEvents[leftIter].positionOnImage.x, greenChangeEvents[leftIter].positionOnImage.y, 1, Drawings::ps_solid, Drawings::orange);
00538 #endif
00539
00540
00541 leftIter = NULL;
00542
00543 continue;
00544 }
00545 else
00546 {
00547
00548 nextLeftStepFound = true;
00549 };
00550 };
00551
00552
00553 if (orgLineID - event.lineID > RS_FOOT_THRESHOLD)
00554 {
00555
00556 #ifdef RS_DEBUG_FEET
00557 LINE (imageProcessor_robot_detection, lastLeft.positionOnImage.x, lastLeft.positionOnImage.y, greenChangeEvents[leftIter].positionOnImage.x, greenChangeEvents[leftIter].positionOnImage.y, 1, Drawings::ps_solid, Drawings::white);
00558 #endif
00559
00560 leftIter = NULL;
00561
00562 continue;
00563 };
00564
00565 if ((((GreenChangeEvent)greenChangeEvents[leftIter]).distanceToHorizon <= lastLeft.distanceToHorizon) &&
00566 (((GreenChangeEvent)greenChangeEvents[leftIter]).lineID) < lastLeft.lineID)
00567 {
00568
00569 if (!((GreenChangeEvent)greenChangeEvents[leftIter]).startEvent)
00570 {
00571
00572 leftIter++;
00573
00574 tmpEvent = greenChangeEvents[leftIter];
00575
00576 if (lastLeft.lineID == ((GreenChangeEvent)greenChangeEvents[leftIter]).lineID)
00577 {
00578
00579 #ifdef RS_DEBUG_FEET
00580 LINE (imageProcessor_robot_detection, lastLeft.positionOnImage.x, lastLeft.positionOnImage.y, greenChangeEvents[leftIter].positionOnImage.x, greenChangeEvents[leftIter].positionOnImage.y, 1, Drawings::ps_solid, Drawings::red);
00581 #endif
00582
00583 leftIter = NULL;
00584
00585 continue;
00586 }
00587 else
00588 if (!((GreenChangeEvent)greenChangeEvents[leftIter]).startEvent)
00589 {
00590
00591 #ifdef RS_DEBUG_FEET
00592 LINE (imageProcessor_robot_detection, lastLeft.positionOnImage.x, lastLeft.positionOnImage.y, greenChangeEvents[leftIter].positionOnImage.x, greenChangeEvents[leftIter].positionOnImage.y, 1, Drawings::ps_solid, Drawings::black);
00593 #endif
00594
00595 leftIter = NULL;
00596
00597 continue;
00598 }
00599 }
00600
00601 nextLeftStepFound = true;
00602 }
00603
00604 if (nextLeftStepFound)
00605 {
00606
00607 delta = lastLeft.distanceToHorizon - ((GreenChangeEvent)greenChangeEvents[leftIter]).distanceToHorizon;
00608
00609 if (delta > RS_FOOT_GRADIENT)
00610 {
00611 switch (leftGradient)
00612 {
00613 case up:
00614 {
00615 leftGradient = up;
00616
00617 break;
00618 };
00619 case equal:
00620 case down:
00621 {
00622 footPoint = maxLeftPoint;
00623
00624 #ifdef RS_DEBUG_FEET
00625 CIRCLE (imageProcessor_robot_detection, footPoint.x, footPoint.y, 2, 1, Drawings::ps_solid, Drawings::pink);
00626 #endif
00627
00628 return true;
00629 };
00630 }
00631 }
00632 else
00633 {
00634 if (delta < -RS_FOOT_GRADIENT)
00635 {
00636 leftGradient = down;
00637 }
00638 else
00639 {
00640 leftGradient = equal;
00641 }
00642 }
00643
00644 #ifdef RS_DEBUG_FEET
00645 LINE (imageProcessor_robot_detection, lastLeft.positionOnImage.x, lastLeft.positionOnImage.y, greenChangeEvents[leftIter].positionOnImage.x, greenChangeEvents[leftIter].positionOnImage.y, 1, Drawings::ps_solid, Drawings::pink);
00646 #endif
00647
00648 lastLeft = greenChangeEvents[leftIter];
00649
00650 if (maxLeftDistance < lastLeft.distanceToHorizon)
00651 {
00652 maxLeftDistance = lastLeft.distanceToHorizon;
00653
00654 maxLeftPoint = lastLeft.positionOnImage;
00655 };
00656
00657 nextLeftStepFound = false;
00658
00659 leftIter--;
00660
00661 break;
00662 };
00663
00664 leftIter--;
00665 };
00666
00667
00668
00669 k = 0;
00670 while (rightIter)
00671 {
00672 CRASH_CHECK(k); k++;
00673 event = greenChangeEvents[rightIter];
00674
00675 if (lastRight.lineID + 1 < ((GreenChangeEvent)greenChangeEvents[rightIter]).lineID)
00676 {
00677
00678 rightIter--;
00679
00680 if (!((GreenChangeEvent)greenChangeEvents[rightIter]).startEvent ||
00681 (((GreenChangeEvent)greenChangeEvents[rightIter]).lineID == lastRight.lineID))
00682 {
00683
00684 #ifdef RS_DEBUG_FEET
00685 LINE (imageProcessor_robot_detection, lastRight.positionOnImage.x, lastRight.positionOnImage.y, greenChangeEvents[rightIter].positionOnImage.x, greenChangeEvents[rightIter].positionOnImage.y, 1, Drawings::ps_solid, Drawings::orange);
00686 #endif
00687
00688 rightIter = NULL;
00689
00690 continue;
00691 }
00692 else
00693 nextRightStepFound = true;
00694 };
00695
00696 if (event.lineID - orgLineID > RS_FOOT_THRESHOLD)
00697 {
00698
00699 #ifdef RS_DEBUG_FEET
00700 LINE (imageProcessor_robot_detection, lastRight.positionOnImage.x, lastRight.positionOnImage.y, greenChangeEvents[rightIter].positionOnImage.x, greenChangeEvents[rightIter].positionOnImage.y, 1, Drawings::ps_solid, Drawings::white);
00701 #endif
00702
00703 rightIter = NULL;
00704
00705 continue;
00706 };
00707
00708 if ((((GreenChangeEvent)greenChangeEvents[rightIter]).distanceToHorizon >= lastRight.distanceToHorizon) &&
00709 (((GreenChangeEvent)greenChangeEvents[rightIter]).lineID) > lastRight.lineID)
00710 {
00711
00712 if (!((GreenChangeEvent)greenChangeEvents[rightIter]).startEvent)
00713 {
00714
00715 rightIter--;
00716
00717 tmpEvent = greenChangeEvents[rightIter];
00718
00719 if (lastRight.lineID == ((GreenChangeEvent)greenChangeEvents[rightIter]).lineID)
00720 {
00721
00722 #ifdef RS_DEBUG_FEET
00723 LINE (imageProcessor_robot_detection, lastRight.positionOnImage.x, lastRight.positionOnImage.y, greenChangeEvents[rightIter].positionOnImage.x, greenChangeEvents[rightIter].positionOnImage.y, 1, Drawings::ps_solid, Drawings::red);
00724 #endif
00725
00726 rightIter = NULL;
00727
00728 continue;
00729 }
00730 else
00731 if (!((GreenChangeEvent)greenChangeEvents[rightIter]).startEvent)
00732 {
00733
00734 #ifdef RS_DEBUG_FEET
00735 LINE (imageProcessor_robot_detection, lastRight.positionOnImage.x, lastRight.positionOnImage.y, greenChangeEvents[rightIter].positionOnImage.x, greenChangeEvents[rightIter].positionOnImage.y, 1, Drawings::ps_solid, Drawings::black);
00736 #endif
00737
00738 rightIter = NULL;
00739
00740 continue;
00741 }
00742 }
00743
00744 nextRightStepFound = true;
00745 }
00746
00747 if (nextRightStepFound)
00748 {
00749
00750 delta = lastRight.distanceToHorizon - ((GreenChangeEvent)greenChangeEvents[rightIter]).distanceToHorizon;
00751
00752 if (delta > RS_FOOT_GRADIENT)
00753 {
00754 switch (rightGradient)
00755 {
00756 case up:
00757 {
00758 rightGradient = up;
00759
00760 break;
00761 };
00762 case equal:
00763 case down:
00764 {
00765 footPoint = maxRightPoint;
00766
00767 #ifdef RS_DEBUG_FEET
00768 CIRCLE (imageProcessor_robot_detection, footPoint.x, footPoint.y, 2, 1, Drawings::ps_solid, Drawings::pink);
00769 #endif
00770
00771 return true;
00772 };
00773 }
00774 }
00775 else
00776 {
00777 if (delta < -RS_FOOT_GRADIENT)
00778 {
00779 rightGradient = down;
00780 }
00781 else
00782 {
00783 rightGradient = equal;
00784 }
00785 }
00786
00787 #ifdef RS_DEBUG_FEET
00788 LINE (imageProcessor_robot_detection, lastRight.positionOnImage.x, lastRight.positionOnImage.y, greenChangeEvents[rightIter].positionOnImage.x, greenChangeEvents[rightIter].positionOnImage.y, 1, Drawings::ps_solid, Drawings::pink);
00789 #endif
00790
00791 lastRight = greenChangeEvents[rightIter];
00792
00793 if (maxRightDistance < lastRight.distanceToHorizon)
00794 {
00795 maxRightDistance = lastRight.distanceToHorizon;
00796
00797 maxRightPoint = lastRight.positionOnImage;
00798 };
00799
00800 nextRightStepFound = false;
00801
00802 break;
00803 };
00804
00805 rightIter++;
00806 };
00807 }
00808
00809 footPoint.x = -1;
00810 footPoint.y = -1;
00811
00812 return false;
00813 }
00814
00815 footIterator++;
00816 };
00817
00818 footIterator = greenChangeEvents.getFirst ();
00819
00820 footPoint.x = -1;
00821 footPoint.y = -1;
00822
00823 return false;
00824 };
00825
00826 void VLCRobotSpecialist::clusterCandidates (colorClass color)
00827 {
00828
00829 RobotCandidate *candidate = NULL, *lastCandidate = NULL;
00830
00831 int element = bottomIndex + 1;
00832
00833 CandidateCluster robotCluster;
00834
00835 robotCluster.startPosition = -1;
00836 robotCluster.stopPosition = -1;
00837
00838 #ifdef RS_DEBUG_CONSOLE
00839 OUTPUT (idText, text, "--------");
00840 #endif
00841
00842 #ifdef RS_DEBUG_SHOW_GREENCHANGE
00843
00844 dbg_PrintGreenchanges ();
00845 #endif
00846
00847 footIterator = greenChangeEvents.getFirst ();
00848
00849 if (element == topIndex)
00850 {
00851
00852 return;
00853 }
00854
00855 bool firstLoop = true;
00856
00857 int i = 0;
00858 while (element < topIndex)
00859 {
00860 CRASH_CHECK(i); i++;
00861
00862
00863 candidate = &candidates[element];
00864
00865
00866 if (candidate->color != color)
00867 {
00868
00869 element++;
00870
00871 continue;
00872 }
00873
00874
00875 if (!findNearestFootPoint (candidate->footPoint))
00876 {
00877
00878
00879
00880 element++;
00881
00882 #ifdef RS_DEBUG
00883 CIRCLE (imageProcessor_robot_detection, candidate->candidateStart.x, candidate->candidateStart.y, 3, 1, Drawings::ps_solid, Drawings::orange);
00884 #endif
00885
00886 continue;
00887 };
00888
00889
00890 if (firstLoop)
00891 {
00892
00893 robotCluster.startPosition = element;
00894 robotCluster.stopPosition = element;
00895
00896 element++;
00897 lastCandidate = candidate;
00898
00899
00900 firstLoop = false;
00901
00902 continue;
00903 };
00904
00905
00906 int distance = distanceOnField (lastCandidate->footPoint, candidate->footPoint, cameraMatrix, CameraInfo::CameraInfo ());
00907
00908
00909 ColorSpace colorSpace = generateColorspace (lastCandidate->candidateStart, candidate->candidateStart);
00910
00911
00912 colorSpace.Normalize ();
00913
00914
00915 if (
00916 ((colorSpace.colorCount[green] >= 0.1) && (candidate->lineID - lastCandidate->lineID >= 3))
00917 || (distance > 400)
00918 || ((candidate->color == red) && (colorSpace.colorCount[blue] >= 0.1))
00919 || ((candidate->color == blue) && (colorSpace.colorCount[red] >= 0.1))
00920 )
00921 {
00922
00923 #ifdef RS_DEBUG
00924
00925 #ifdef RS_DEBUG_SHOW_CLUSTER_INFO
00926 if (colorSpace.colorCount[green] >= 0.1)
00927 OUTPUT (idText, text, "clustering : too much green found: " << colorSpace.colorCount[green] << "; line " << candidate->lineID);
00928
00929 if (distance > 400)
00930 OUTPUT (idText, text, "clustering : too far away: " << distance << " ; line " << candidate->lineID);
00931
00932 if ((candidate->color == red) && (colorSpace.colorCount[blue] >= 0.1))
00933 OUTPUT (idText, text, "clustering : wrong color found : blue; line " << candidate->lineID);
00934
00935 if ((candidate->color == blue) && (colorSpace.colorCount[red] >= 0.1))
00936 OUTPUT (idText, text, "clustering : wrong color found : red; line " << candidate->lineID);
00937 #endif
00938
00939 #endif
00940
00941 if (lastCandidate->color == red || lastCandidate->color == blue)
00942 generatePercept (robotCluster);
00943
00944
00945 robotCluster.startPosition = element;
00946 robotCluster.stopPosition = element;
00947 }
00948 else
00949 {
00950
00951 robotCluster.stopPosition = element;
00952
00953 #ifdef RS_DEBUG
00954
00955 if (candidate->color == blue)
00956 {
00957 #ifdef RS_DEBUG_SHOW_CONNECTIONS
00958 LINE (imageProcessor_robot_detection, lastCandidate->candidateStart.x, lastCandidate->candidateStart.y,
00959 candidate->candidateStart.x, candidate->candidateStart.y, 2, Drawings::ps_dot, Drawings::blue);
00960 #endif
00961 }
00962 else
00963 {
00964 #ifdef RS_DEBUG_SHOW_CONNECTIONS
00965 LINE (imageProcessor_robot_detection, lastCandidate->candidateStart.x, lastCandidate->candidateStart.y,
00966 candidate->candidateStart.x, candidate->candidateStart.y, 2, Drawings::ps_dot, Drawings::red);
00967 #endif
00968 };
00969 #endif
00970 }
00971
00972
00973 element++;
00974 lastCandidate = candidate;
00975 };
00976
00977
00978 if (robotCluster.stopPosition != -1)
00979 generatePercept (robotCluster);
00980
00981 return;
00982 }
00983
00984 void VLCRobotSpecialist::generatePercept (CandidateCluster cluster)
00985 {
00986 int element;
00987
00988 Vector2<int> average = Vector2<int>(0, 0);
00989 Vector2<int> filter = Vector2<int>(0, 0);
00990 VLCRectangle body;
00991 VLCRectangle foot;
00992
00993 int count = 0;
00994
00995 int varianz = 0;
00996
00997 double aspectRatio = 0;
00998
00999 RobotCandidate candidate;
01000 RobotCandidate lastCandidate;
01001
01002 RobotDirection robotDirection;
01003
01004 int longestTrikotRun = 0;
01005
01006
01007 #ifdef RS_DEBUG_CONSOLE
01008 int dbg_i;
01009 #endif
01010
01011
01012 PerceptInfo perceptInfo;
01013
01014 perceptInfo.minBounding = Vector2<int>(1024, 1024);
01015 perceptInfo.maxBounding = Vector2<int>(0, 0);
01016 perceptInfo.bottomLine = Vector2<int>(0, 0);
01017 perceptInfo.flags = 0;
01018
01019
01020
01021
01022 perceptInfo.lines = cluster.stopPosition - cluster.startPosition + 1;
01023
01024
01025 count = generateBoundings (cluster, body, foot, filter);
01026
01027
01028 if (count > 0)
01029 {
01030 filter.x /= count;
01031 filter.y /= count;
01032
01033 varianz = foot.y2 - foot.y1;
01034
01035 int threshold = filter.y - (int) (varianz * 0.1);
01036
01037 count = 0;
01038
01039 lastCandidate.lineID = -1;
01040
01041
01042 int i = 0;
01043 for (element = cluster.startPosition; element <= cluster.stopPosition; element++)
01044 {
01045 CRASH_CHECK(i); i++;
01046
01047 candidate = candidates[element];
01048
01049 if (longestTrikotRun < (candidate.candidateStart.y - candidate.candidateStop.y))
01050 longestTrikotRun = candidate.candidateStart.y - candidate.candidateStop.y;
01051
01052 if (candidate.footPoint.y >= threshold)
01053 {
01054 average.x += candidate.footPoint.x;
01055 average.y += candidate.footPoint.y;
01056
01057 if (lastCandidate.lineID == -1)
01058 lastCandidate = candidate;
01059
01060 perceptInfo.bottomLine.x += candidate.footPoint.x - lastCandidate.footPoint.x;
01061 perceptInfo.bottomLine.y += candidate.footPoint.y - lastCandidate.footPoint.y;
01062
01063 count++;
01064 lastCandidate = candidate;
01065
01066 #ifdef RS_DEBUG
01067 CIRCLE (imageProcessor_robot_detection, candidate.footPoint.x, candidate.footPoint.y, 1, 1, Drawings::ps_solid, Drawings::black);
01068 #endif
01069 }
01070 else
01071 {
01072 #ifdef RS_DEBUG
01073 CIRCLE (imageProcessor_robot_detection, candidate.footPoint.x, candidate.footPoint.y, 1, 1, Drawings::ps_solid, Drawings::dark_gray);
01074 #endif
01075 }
01076 }
01077
01078 if (count > 0)
01079 {
01080
01081 average.x /= count;
01082 average.y /= count;
01083
01084
01085 {
01086 perceptInfo.minBounding.x = min (body.x1, body.x1);
01087 perceptInfo.minBounding.y = min (body.y1, body.y1);
01088 perceptInfo.maxBounding.x = max (body.x2, body.x2);
01089 perceptInfo.maxBounding.y = max (body.y2, average.y);
01090 }
01091
01092 unsigned char y, u, v, ly = 0;
01093
01094 #ifdef RS_GROW_BB
01095 {
01096 int xcoord, ycoord;
01097
01098 xcoord = minBounding.x;
01099 ycoord = (int)((double)((maxBounding.y - minBounding.y) * 0.8) + minBounding.y);
01100
01101 int k = 0;
01102 while (xcoord > 0)
01103 {
01104 CRASH_CHECK(k); k++;
01105
01106 if (xcoord < 0 || xcoord >= image.cameraInfo.resolutionWidth || ycoord < 0 || ycoord >= image.cameraInfo.resolutionHeight)
01107 y = u = v = 0;
01108 else
01109 {
01110 y = colorCorrector.correct(xcoord, ycoord, 0, image.image[ycoord][0][xcoord]);
01111 u = colorCorrector.correct(xcoord, ycoord, 1, image.image[ycoord][1][xcoord]);
01112 v = colorCorrector.correct(xcoord, ycoord, 2, image.image[ycoord][2][xcoord]);
01113 }
01114 colorClass color = COLOR_CLASS(y, u, v);
01115
01116
01117 if (color == green)
01118 break;
01119
01120 #ifdef RS_DEBUG
01121 DOT (imageProcessor_robot_detection, xcoord, ycoord, ColorClasses::colorClassToDrawingsColor (color), ColorClasses::colorClassToDrawingsColor (color));
01122 #endif
01123
01124 xcoord--;
01125 };
01126
01127 if (xcoord != 0)
01128 minBounding.x = xcoord + 1;
01129
01130 xcoord = maxBounding.x;
01131
01132 k = 0;
01133 while (xcoord < image.cameraInfo.resolutionWidth)
01134 {
01135 CRASH_CHECK(k); k++;
01136
01137 if (xcoord < 0 || xcoord >= image.cameraInfo.resolutionWidth || ycoord < 0 || ycoord >= image.cameraInfo.resolutionHeight)
01138 y = u = v = 0;
01139 else
01140 {
01141 y = colorCorrector.correct(xcoord, ycoord, 0, image.image[ycoord][0][xcoord]);
01142 u = colorCorrector.correct(xcoord, ycoord, 1, image.image[ycoord][1][xcoord]);
01143 v = colorCorrector.correct(xcoord, ycoord, 2, image.image[ycoord][2][xcoord]);
01144 }
01145 colorClass color = COLOR_CLASS(y, u, v);
01146
01147
01148 if (color == green)
01149 break;
01150
01151 #ifdef RS_DEBUG
01152 DOT (imageProcessor_robot_detection, xcoord, ycoord, ColorClasses::colorClassToDrawingsColor (color), ColorClasses::colorClassToDrawingsColor (color));
01153 #endif
01154
01155 xcoord++;
01156 };
01157
01158 if (xcoord != image.cameraInfo.resolutionWidth)
01159 maxBounding.x = xcoord - 1;
01160 }
01161 #endif
01162
01163 {
01164 Vector2<int> fieldPosition;
01165 Vector2<int> vec2;
01166
01167 Geometry::calculatePointOnField(perceptInfo.minBounding.x, perceptInfo.maxBounding.y, cameraMatrix, CameraInfo::CameraInfo (), fieldPosition);
01168 Geometry::calculatePointOnField(perceptInfo.maxBounding.x, perceptInfo.maxBounding.y, cameraMatrix, CameraInfo::CameraInfo (), vec2);
01169
01170 vec2.x -= fieldPosition.x;
01171 vec2.y -= fieldPosition.y;
01172
01173 if ((vec2.abs() < 100) || (vec2.abs() > 500))
01174 perceptInfo.flags |= MSHPPF::wrongSize;
01175 }
01176
01177
01178 #define NUMSUBSPACES 3
01179 ColorSpace colorSpace;
01180 ColorSpace subSpaces[NUMSUBSPACES];
01181 int subSpace;
01182 {
01183 int xcoord, ycoord;
01184
01185 int k = 0;
01186 for (xcoord = perceptInfo.minBounding.x; xcoord < perceptInfo.maxBounding.x; xcoord += max ((perceptInfo.maxBounding.x - perceptInfo.minBounding.x) / 9, 1))
01187 {
01188 CRASH_CHECK(k); k++;
01189 subSpace = (int)((xcoord - perceptInfo.minBounding.x) / (double)((perceptInfo.maxBounding.x - perceptInfo.minBounding.x) / (double)NUMSUBSPACES));
01190
01191 int l = 0;
01192 for (ycoord = perceptInfo.minBounding.y; ycoord < perceptInfo.maxBounding.y; ycoord += max ((perceptInfo.maxBounding.y - perceptInfo.minBounding.y) / 10, 1))
01193 {
01194 CRASH_CHECK(l); l++;
01195
01196 if (xcoord < 0 || xcoord >= image.cameraInfo.resolutionWidth || ycoord < 0 || ycoord >= image.cameraInfo.resolutionHeight)
01197 y = u = v = 0;
01198 else
01199 {
01200 y = colorCorrector.correct(xcoord, ycoord, 0, image.image[ycoord][0][xcoord]);
01201 u = colorCorrector.correct(xcoord, ycoord, 1, image.image[ycoord][1][xcoord]);
01202 v = colorCorrector.correct(xcoord, ycoord, 2, image.image[ycoord][2][xcoord]);
01203 }
01204 colorClass color = COLOR_CLASS(y, u, v);
01205
01206
01207 if (ycoord == perceptInfo.minBounding.y)
01208 ly = y;
01209
01210 subSpaces[subSpace].AddSample (color, y, y - ly);
01211 };
01212 };
01213
01214 for (subSpace = 0; subSpace < NUMSUBSPACES; subSpace++)
01215 {
01216 CRASH_CHECK(subSpace);
01217
01218 colorSpace += subSpaces[subSpace];
01219 };
01220 }
01221
01222
01223 {
01224 for (subSpace = 0; subSpace < NUMSUBSPACES; subSpace++)
01225 {
01226 CRASH_CHECK(subSpace);
01227
01228 subSpaces[subSpace].Normalize ();
01229
01230 #ifdef RS_DEBUG
01231
01232 #endif
01233 #ifdef RS_DEBUG_CONSOLE
01234 OUTPUT (idText, text, "y subspace " << subSpace << " : " << subSpaces[subSpace].y);
01235 #endif
01236 };
01237
01238 colorSpace.Normalize ();
01239 }
01240
01241
01242
01243 {
01244 #ifdef RS_DEBUG_CONSOLE
01245 for (dbg_i = 0; dbg_i < numOfColors; dbg_i++)
01246 {
01247 CRASH_CHECK(dbg_i);
01248
01249 OUTPUT (idText, text, ColorClasses::getColorName ((colorClass) dbg_i) << " : " << colorSpace.colorCount[dbg_i]);
01250 };
01251
01252 OUTPUT (idText, text, "brightness : " << colorSpace.y);
01253 OUTPUT (idText, text, "delta brightness : " << colorSpace.dY);
01254 #endif
01255 }
01256
01257
01258
01259 {
01260 unsigned int filterFlags = filterPercepts (colorSpace, candidate.color);
01261
01262 if (filterFlags)
01263 perceptInfo.flags |= filterFlags;
01264 }
01265
01266
01267
01268
01269 {
01270 if (perceptInfo.maxBounding.y != perceptInfo.minBounding.y)
01271 aspectRatio = (perceptInfo.maxBounding.x - perceptInfo.minBounding.x) / (perceptInfo.maxBounding.y - perceptInfo.minBounding.y);
01272 else
01273 aspectRatio = 0;
01274
01275 if (aspectRatio < 0)
01276 {
01277
01278 robotDirection.AddSample (0);
01279 robotDirection.AddSample (pi);
01280 }
01281 else
01282 {
01283
01284 robotDirection.AddSample (pi_2);
01285 robotDirection.AddSample (-pi_2);
01286 }
01287 }
01288
01289
01290 {
01291 if (colorSpace.colorCount[red] > 0.15)
01292 {
01293
01294 robotDirection.AddSample (0, 10);
01295
01296 #ifdef RS_DEBUG_CONSOLE
01297 OUTPUT (idText, text, "robot seen from back");
01298 #endif
01299 }
01300 }
01301
01302
01303
01304 {
01305 if ((subSpaces[0].y < subSpaces[1].y) && (subSpaces[0].y < subSpaces[2].y))
01306 {
01307 robotDirection.AddSample (pi + pi_4, 2);
01308 }
01309
01310 if ((subSpaces[1].y < subSpaces[0].y) && (subSpaces[1].y < subSpaces[2].y))
01311 {
01312 robotDirection.AddSample (pi, 2);
01313 robotDirection.AddSample (0, 1);
01314
01315 if (colorSpace.y < 75)
01316 {
01317
01318 robotDirection.AddSample (pi, 2);
01319
01320 #ifdef RS_DEBUG_CONSOLE
01321 OUTPUT (idText, text, "robot seen from front");
01322 #endif
01323 };
01324 }
01325
01326 if ((subSpaces[2].y < subSpaces[0].y) && (subSpaces[2].y < subSpaces[1].y))
01327 {
01328 robotDirection.AddSample (pi - pi_4, 2);
01329 }
01330 }
01331
01332
01333 {
01334 perceptInfo.position = average;
01335 perceptInfo.direction = robotDirection.getDirection ();
01336 perceptInfo.validity = robotDirection.getReliability ();
01337 perceptInfo.color = candidate.color;
01338 perceptInfo.count = count;
01339
01340 addPercept (perceptInfo);
01341 }
01342 }
01343 else
01344 if (longestTrikotRun > 25)
01345 {
01346 perceptInfo.position = Vector2<int> (candidate.candidateStop.x, image.cameraInfo.resolutionHeight);
01347 perceptInfo.direction = 0;
01348 perceptInfo.validity = 0.75;
01349 perceptInfo.color = candidate.color;
01350 perceptInfo.count = 0;
01351
01352 addPercept (perceptInfo);
01353 }
01354 };
01355 }
01356
01357 int VLCRobotSpecialist::noColorPixelsBetween (Vector2<int> startPoint, Vector2<int> endPoint, colorClass noColor)
01358 {
01359
01360 BresenhamLineScan scanLine = BresenhamLineScan (startPoint, endPoint);
01361 Vector2<int> actual = startPoint;
01362
01363 unsigned char y, u, v;
01364
01365 int result = 0;
01366
01367 for (int i = 0; i <= scanLine.numberOfPixels; ++i)
01368 {
01369 CRASH_CHECK(i);
01370
01371 if (actual.x < 0 || actual.x >= image.cameraInfo.resolutionWidth || actual.y < 0 || actual.y >= image.cameraInfo.resolutionHeight)
01372 y = u = v = 0;
01373 else
01374 {
01375 y = colorCorrector.correct(actual.x, actual.y, 0, image.image[actual.y][0][actual.x]);
01376 u = colorCorrector.correct(actual.x, actual.y, 1, image.image[actual.y][1][actual.x]);
01377 v = colorCorrector.correct(actual.x, actual.y, 2, image.image[actual.y][2][actual.x]);
01378 }
01379 colorClass color = COLOR_CLASS(y, u, v);
01380
01381
01382 if (color == noColor)
01383 result++;
01384
01385
01386 scanLine.getNext (actual);
01387 };
01388
01389 return result;
01390 }
01391
01392 ColorSpace VLCRobotSpecialist::generateColorspace (Vector2<int> startPoint, Vector2<int> endPoint)
01393 {
01394 ColorSpace colorSpace;
01395
01396
01397 BresenhamLineScan scanLine = BresenhamLineScan (startPoint, endPoint);
01398 Vector2<int> actual = startPoint;
01399
01400 unsigned char y, u, v, ly = 0;
01401
01402 int i;
01403
01404 for (i = 0; i < numOfColors; i++)
01405 {
01406 CRASH_CHECK(i);
01407
01408 colorSpace.colorCount[i] = 0;
01409 }
01410
01411 for (i = 0; i <= scanLine.numberOfPixels; ++i)
01412 {
01413 CRASH_CHECK(i);
01414
01415
01416 if (actual.x < 0 || actual.x >= image.cameraInfo.resolutionWidth || actual.y < 0 || actual.y >= image.cameraInfo.resolutionHeight)
01417 y = u = v = 0;
01418 else
01419 {
01420 y = colorCorrector.correct(actual.x, actual.y, 0, image.image[actual.y][0][actual.x]);
01421 u = colorCorrector.correct(actual.x, actual.y, 1, image.image[actual.y][1][actual.x]);
01422 v = colorCorrector.correct(actual.x, actual.y, 2, image.image[actual.y][2][actual.x]);
01423 }
01424 colorClass color = COLOR_CLASS(y, u, v);
01425
01426
01427 if (i == 0)
01428 ly = y;
01429
01430 colorSpace.colorCount[color]++;
01431 colorSpace.y += y;
01432 colorSpace.dY += y - ly;
01433
01434 #ifdef RS_DEBUG_SHOW_COLORSPACE_INFO
01435 LINE(imageProcessor_scanLines, actual.x, actual.y, actual.x, actual.y, 1, Drawings::ps_solid, ColorClasses::colorClassToDrawingsColor (color));
01436 #endif
01437
01438
01439 scanLine.getNext (actual);
01440 };
01441
01442 return colorSpace;
01443 }
01444
01445 unsigned int VLCRobotSpecialist::filterPercepts (ColorSpace colorSpace, colorClass candidateColor)
01446 {
01447 unsigned int result = 0;
01448
01449 if ((colorSpace.colorCount[red] < 0.01) && (colorSpace.colorCount[blue] < 0.01))
01450 {
01451 #ifdef RS_DEBUG_CONSOLE
01452 OUTPUT (idText, text, "too few trickot found, so asume as noise");
01453 OUTPUT (idText, text, "");
01454 #endif
01455
01456 result |= MSHPPF::fewTrickot;
01457 }
01458
01459 if ((candidateColor == red) && (colorSpace.colorCount[white] > 0.5))
01460 {
01461 #ifdef RS_DEBUG_CONSOLE
01462 OUTPUT (idText, text, "too much white, so asume something was seen on the wall");
01463 OUTPUT (idText, text, "");
01464 #endif
01465
01466 result |= MSHPPF::tooMuchWhite;
01467 }
01468
01469 if (colorSpace.colorCount[green] > 0.5)
01470 {
01471 #ifdef RS_DEBUG_CONSOLE
01472 OUTPUT (idText, text, "too much green, so asume a ball was seen on the field");
01473 OUTPUT (idText, text, "");
01474 #endif
01475
01476 result |= MSHPPF::tooMuchGreen;
01477 }
01478
01479 if (colorSpace.colorCount[skyblue] > 0.1)
01480 {
01481 #ifdef RS_DEBUG_CONSOLE
01482 OUTPUT (idText, text, "too much skyblue, so it seems to be a goal, or landmark");
01483 OUTPUT (idText, text, "");
01484 #endif
01485
01486 result |= MSHPPF::tooMuchSkyBlue;
01487 }
01488
01489 if (colorSpace.colorCount[orange] > 0.2)
01490 {
01491 #ifdef RS_DEBUG_CONSOLE
01492 OUTPUT (idText, text, "too much orange, so it seems to be a ball");
01493 OUTPUT (idText, text, "");
01494 #endif
01495
01496 result |= MSHPPF::tooMuchOrange;
01497 }
01498
01499 if (colorSpace.dY < 35)
01500 {
01501 #ifdef RS_DEBUG_CONSOLE
01502 OUTPUT (idText, text, "too few brightness changes");
01503 OUTPUT (idText, text, "");
01504 #endif
01505
01506 result |= MSHPPF::fewBrightnessChange;
01507 }
01508
01509 return result;
01510 }
01511
01512 void VLCRobotSpecialist::addPercept (PerceptInfo &perceptInfo)
01513 {
01514 Vector2<int> fieldPosition;
01515
01516 MSHSinglePlayerPercept percept;
01517
01518 percept.flags = perceptInfo.flags;
01519 percept.lines = perceptInfo.lines;
01520
01521
01522 Geometry::calculatePointOnField(perceptInfo.position.x, perceptInfo.position.y, cameraMatrix, CameraInfo::CameraInfo (), fieldPosition);
01523
01524
01525 Pose2D pose = Pose2D (fieldPosition);
01526
01527 Pose2D poseOnField = robotPose + pose;
01528
01529 percept.offset = poseOnField.translation;
01530
01531
01532 if (
01533 (percept.offset.x > xPosOpponentGoal) ||
01534 (percept.offset.x < -xPosOpponentGoal) ||
01535 (percept.offset.y > yPosLeftSideline) ||
01536 (percept.offset.y < -yPosLeftSideline)
01537 )
01538 {
01539
01540 percept.flags |= MSHPPF::outOfField;
01541
01542 #ifdef RS_DEBUG_CONSOLE
01543 OUTPUT (idText, text, "");
01544 OUTPUT (idText, text, "percept outside field");
01545 OUTPUT (idText, text, "");
01546 #endif
01547 }
01548
01549 percept.direction = robotPose.getAngle () + perceptInfo.direction;
01550 percept.validity = perceptInfo.validity;
01551
01552
01553 #ifdef RS_DEBUG_CONSOLE
01554 OUTPUT (idText, text, "robot at position : " << fieldPosition.x << " , " << fieldPosition.y);
01555 OUTPUT (idText, text, "distance : " << fieldPosition.abs ());
01556 OUTPUT (idText, text, "");
01557 #endif
01558
01559 #ifdef RS_DEBUG
01560 ARROW (percepts_robot, percept.offset.x, percept.offset.y, percept.offset.x + cos (percept.direction) * 200, percept.offset.y - sin (percept.direction) * 200, 1, Drawings::ps_solid, Drawings::black);
01561 #endif
01562
01563 if (perceptInfo.color == blue)
01564 {
01565 playersPercept.addBluePlayer (percept);
01566
01567 #ifdef RS_DEBUG
01568
01569
01570 #ifdef RS_DEBUG_SHOW_BOUNDINGBOX
01571 RECTANGLE (imageProcessor_robot_detection, perceptInfo.minBounding.x, perceptInfo.minBounding.y, perceptInfo.maxBounding.x, perceptInfo.maxBounding.y, 1, Drawings::ps_dot, Drawings::blue);
01572 #endif
01573
01574 perceptInfo.gradient = 0;
01575
01576 if (perceptInfo.bottomLine.x != 0)
01577 perceptInfo.gradient = (((double) perceptInfo.bottomLine.y) / ((double) perceptInfo.bottomLine.x)) / ((double)perceptInfo.count) * 2.0;
01578
01579 Vector2<int> start;
01580 Vector2<int> stop;
01581
01582 start.x = perceptInfo.minBounding.x;
01583 start.y = perceptInfo.position.y + ((int)((perceptInfo.minBounding.x - perceptInfo.position.x) * perceptInfo.gradient));
01584
01585 stop.x = perceptInfo.maxBounding.x;
01586 stop.y = perceptInfo.position.y + ((int)((perceptInfo.maxBounding.x - perceptInfo.position.x) * perceptInfo.gradient));
01587
01588 #ifdef RS_DEBUG_SHOW_PERCEPT
01589 LINE (imageProcessor_robot_detection, start.x, start.y, stop.x, stop.y, 1, Drawings::ps_dot, Drawings::blue);
01590
01591 CIRCLE (imageProcessor_robot_detection, perceptInfo.position.x, perceptInfo.position.y, 0, 1, Drawings::ps_solid, Drawings::blue);
01592 CIRCLE (percepts_robot, percept.offset.x, percept.offset.y, 50, 10, Drawings::ps_solid, Drawings::blue);
01593 #endif
01594 #endif
01595 }
01596 else
01597 {
01598 playersPercept.addRedPlayer (percept);
01599
01600 #ifdef RS_DEBUG
01601 #ifdef RS_DEBUG_SHOW_BOUNDINGBOX
01602 RECTANGLE (imageProcessor_robot_detection, perceptInfo.minBounding.x, perceptInfo.minBounding.y, perceptInfo.maxBounding.x, perceptInfo.maxBounding.y, 1, Drawings::ps_dot, Drawings::red);
01603 #endif
01604
01605 perceptInfo.gradient = 0;
01606
01607 if (perceptInfo.bottomLine.x != 0)
01608 perceptInfo.gradient = (((double) perceptInfo.bottomLine.y) / ((double) perceptInfo.bottomLine.x)) / ((double)perceptInfo.count) * 2.0;
01609
01610 Vector2<int> start;
01611 Vector2<int> stop;
01612
01613 start.x = perceptInfo.minBounding.x;
01614 start.y = perceptInfo.position.y + ((int)((perceptInfo.minBounding.x - perceptInfo.position.x) * perceptInfo.gradient));
01615
01616 stop.x = perceptInfo.maxBounding.x;
01617 stop.y = perceptInfo.position.y + ((int)((perceptInfo.maxBounding.x - perceptInfo.position.x) * perceptInfo.gradient));
01618
01619 #ifdef RS_DEBUG_SHOW_PERCEPT
01620 LINE (imageProcessor_robot_detection, start.x, start.y, stop.x, stop.y, 1, Drawings::ps_dot, Drawings::red);
01621
01622 CIRCLE (imageProcessor_robot_detection, perceptInfo.position.x, perceptInfo.position.y, 0, 1, Drawings::ps_solid, Drawings::orange);
01623 CIRCLE (percepts_robot, percept.offset.x, percept.offset.y, 50, 10, Drawings::ps_solid, Drawings::red);
01624 #endif
01625 #endif
01626 };
01627
01628 return;
01629 };
01630
01631
01632 void VLCRobotSpecialist::dbg_PrintGreenchanges (void)
01633 {
01634 List<GreenChangeEvent>::Pos iter = greenChangeEvents.getFirst ();
01635
01636 int i = 0;
01637 while (iter)
01638 {
01639 CRASH_CHECK(i); i++;
01640 GreenChangeEvent event = greenChangeEvents[iter];
01641
01642 if (event.startEvent)
01643 {
01644 CIRCLE (imageProcessor_robot_detection, event.positionOnImage.x, event.positionOnImage.y, 2, 1, Drawings::ps_dot, Drawings::gray);
01645 }
01646 else
01647 {
01648 CIRCLE (imageProcessor_robot_detection, event.positionOnImage.x, event.positionOnImage.y, 2, 1, Drawings::ps_dot, Drawings::dark_gray);
01649 }
01650
01651 iter++;
01652 };
01653 };
01654
01655 int VLCRobotSpecialist::distanceOnField (Vector2<int> vec1, Vector2<int> vec2, CameraMatrix cameraMatrix, CameraInfo cameraInfo)
01656 {
01657 Vector2<int> pointOnField1, pointOnField2;
01658
01659 Geometry::calculatePointOnField (vec1.x, vec1.y, cameraMatrix, cameraInfo, pointOnField1);
01660
01661 Geometry::calculatePointOnField (vec2.x, vec2.y, cameraMatrix, cameraInfo, pointOnField2);
01662
01663 pointOnField2 -= pointOnField1;
01664
01665 return pointOnField2.abs ();
01666 }
01667
01668 int VLCRobotSpecialist::generateBoundings (CandidateCluster cluster, VLCRectangle &body, VLCRectangle &foot, Vector2<int> &footAVG)
01669 {
01670 RobotCandidate candidate;
01671
01672 int element = 0;
01673 int count = 0;
01674
01675
01676 body.x1 = 1024; body.x2 = 0; body.y1 = 1024; body.y2 = 0;
01677 foot.x1 = 1024; foot.x2 = 0; foot.y1 = 1024; foot.y2 = 0;
01678
01679
01680 for (element = (int) cluster.startPosition; element <= (int)cluster.stopPosition; element++)
01681 {
01682 CRASH_CHECK(element);
01683
01684 candidate = candidates[element];
01685
01686 if (body.x2 < candidate.candidateStart.x)
01687 body.x2 = candidate.candidateStart.x;
01688
01689 if (body.x1 > candidate.candidateStart.x)
01690 body.x1 = candidate.candidateStart.x;
01691
01692 if (body.y2 < candidate.candidateStart.y)
01693 body.y2 = candidate.candidateStart.y;
01694
01695 if (body.y1 > candidate.candidateStart.y)
01696 body.y1 = candidate.candidateStart.y;
01697
01698 if ((candidate.footPoint.x != -1) &&
01699 (candidate.footPoint.y != -1)
01700 )
01701 {
01702 if (foot.x2 < candidate.footPoint.x)
01703 foot.x2 = candidate.footPoint.x;
01704
01705 if (foot.x1 > candidate.footPoint.x)
01706 foot.x1 = candidate.footPoint.x;
01707
01708 if (foot.y2 < candidate.footPoint.y)
01709 foot.y2 = candidate.footPoint.y;
01710
01711 if (foot.y1 > candidate.footPoint.y)
01712 foot.y1 = candidate.footPoint.y;
01713
01714 footAVG.x += candidate.footPoint.x;
01715 footAVG.y += candidate.footPoint.y;
01716 };
01717
01718 count++;
01719 };
01720
01721 return count;
01722 }
01723
01724 #undef min
01725 #undef max