00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "RBridgeSpecialist.h"
00010 #include "Tools/ColorClasses.h"
00011 #include "Tools/Location.h"
00012
00013 RBridgeSpecialist::SegmentInfo::SegmentInfo():
00014 lmValidityOrange(0),
00015 lmValidityYellow(0),
00016 orange(0),
00017 yellow(0),
00018 skyblue(0)
00019 {
00020
00021 }
00022
00023
00024
00025 RBridgeSpecialist::RBridgeSpecialist(RasterImageProcessor &processor,RasterStrategy &strat):
00026 RasterSpecialist(processor),edgeScanner(processor)
00027 {
00028
00029 lineColor=red;
00030 strategy = &strat;
00031 preScanNeeded = true;
00032 postScanNeeded = false;
00033 }
00034
00035
00036 RBridgeSpecialist::~RBridgeSpecialist(){}
00037
00038
00039 int RBridgeSpecialist::getType() {
00040 return __RBridgeSpecialist;
00041 }
00042
00043 void RBridgeSpecialist::init() {
00044 segments_img.clear();
00045 infos_img.clear();
00046 lst_pts.clear();
00047
00048 edgeScanner.threshold = 20;
00049 }
00050
00051
00052 void RBridgeSpecialist::createBBox() {
00053
00054 SVector::iterator sit;
00055 list<LinePair>::iterator l_it;
00056
00057 double dist, p_dist;
00058
00059
00060 for (sit = segments_img.begin();sit != segments_img.end();sit++){
00061 if (sit->size() < 1) continue;
00062
00063
00064 Geometry::Line top,bottom,left,right;
00065 Vector2<int> minHor,maxHor,minPHor,maxPHor;
00066 SegmentInfo si;
00067 double min_dist = 20000, max_dist = -20000, min_p_dist = 20000, max_p_dist = -20000;
00068
00069 for (l_it = sit->begin();l_it!=sit->end();++l_it) {
00070
00071 dist = getDistanceToLine(horizon,l_it->v1);
00072 p_dist = getDistanceToLine(pHorizon,l_it->v1);
00073
00074 if (dist < min_dist) {
00075 min_dist = dist;
00076 minHor = l_it->v1;
00077
00078 }
00079 if (dist > max_dist) {
00080 max_dist = dist;
00081 maxHor = l_it->v1;
00082 }
00083
00084 if (p_dist < min_p_dist) {
00085 min_p_dist = p_dist;
00086 minPHor = l_it->v1;
00087 }
00088 if (p_dist > max_p_dist) {
00089 max_p_dist = p_dist;
00090 maxPHor = l_it->v1;
00091 }
00092
00093 dist = getDistanceToLine(horizon,l_it->v2);
00094 p_dist = getDistanceToLine(pHorizon,l_it->v2);
00095
00096 if (dist < min_dist) {
00097 min_dist = dist;
00098 minHor = l_it->v2;
00099
00100 }
00101 if (dist > max_dist) {
00102 max_dist = dist;
00103 maxHor = l_it->v2;
00104 }
00105
00106 if (p_dist < min_p_dist) {
00107 min_p_dist = p_dist;
00108 minPHor = l_it->v2;
00109 }
00110 if (p_dist > max_p_dist) {
00111 max_p_dist = p_dist;
00112 maxPHor = l_it->v2;
00113 }
00114 }
00115 top.base = Vector2<double>(
00116 (double)maxHor.x,
00117 (double)maxHor.y);
00118 top.direction = horizon.direction;
00119
00120 bottom.base = Vector2<double>(
00121 (double)minHor.x,
00122 (double)minHor.y);
00123 bottom.direction = horizon.direction;
00124
00125 left.base = Vector2<double>(
00126 (double)minPHor.x,
00127 (double)minPHor.y);
00128 left.direction = pHorizon.direction;
00129
00130 right.base = Vector2<double>(
00131 (double)maxPHor.x,
00132 (double)maxPHor.y);
00133 right.direction = pHorizon.direction;
00134
00135 Geometry::getIntersectionOfLines(top,left,si.rect.upperLeft);
00136 Geometry::getIntersectionOfLines(top,right,si.rect.upperRight);
00137 Geometry::getIntersectionOfLines(bottom,left,si.rect.bottomLeft);
00138 Geometry::getIntersectionOfLines(bottom,right,si.rect.bottomRight);
00139 si.rect.center = (si.rect.upperLeft + si.rect.bottomRight)/2;
00140 si.size = sit->size();
00141 si.segment = &(*sit);
00142
00143 countColors(si,*(si.segment));
00144 createValidities(si);
00145 infos_img.push_back(si);
00146 }
00147 }
00148
00149
00150
00151 void RBridgeSpecialist::invokeOnPreScan(int x, int y){
00152
00153 Vector2 <int> cur_pt = Vector2<int>(x,y);
00154
00155 if (!strategy->insideBridge) left_border = cur_pt;
00156 else {
00157 LinePair lp(left_border,cur_pt);
00158 lp.color = getColor(lp.v1.x,lp.v1.y);
00159
00160 lp.v1 = scanWest(lp.v1.x,lp.v1.y);
00161 lp.v2 = scanEast(lp.v2.x,lp.v2.y);
00162
00163
00164 if ((lp.v2.x-lp.v1.x)>1) {
00165
00166 edgeScanner.scanWest(lp.v1.x,lp.v2.y);
00167 edgeScanner.scanEast(lp.v2.x,lp.v2.y);
00168
00169 lst_pts.push_back(lp);
00170
00171 LINE(imageProcessor_general,
00172 lp.v1.x,lp.v1.y,
00173 lp.v2.x,lp.v2.y,
00174 0.5, Drawings::ps_solid, Drawings::red);
00175
00176 }
00177 }
00178 }
00179
00180 void RBridgeSpecialist::invokeOnPostScan(int x,int y) {
00181
00182 }
00183
00184 void RBridgeSpecialist::executePostProcessing() {
00185
00186 if (lst_pts.size() < 2) return;
00187
00188 int allowedXSpace = 2;
00189 int allowedYSpace = 2;
00190
00191 horizon = rip->getHorizon();
00192
00193 pHorizon.base = horizon.base;
00194 pHorizon.direction = horizon.direction;
00195 pHorizon.direction.rotateLeft();
00196
00197 createSegmentsFromLines2(lst_pts,segments_img,allowedXSpace,allowedYSpace);
00198
00199
00200
00201
00202 sort<SVector::iterator>(segments_img.begin(),segments_img.end(),ListSizeOrder());
00203 createBBox();
00204
00205 vector<SegmentInfo>::iterator it;
00206 for(it = infos_img.begin();it != infos_img.end();++it) {
00207 double width = 0.5;
00208 double boxWidth;
00209 findBridgeMark(*it);
00210
00211 if ((it->lmValidityOrange > 0.3 || it->lmValidityYellow > 0.3) &&
00212 (boxWidth = (it->rect.bottomRight - it->rect.bottomLeft).abs()) > 5 &&
00213 (it->rect.upperLeft - it->rect.bottomLeft).abs() * 3 < boxWidth)
00214 {
00215 width = 1;
00216 LINE(imageProcessor_general,
00217 it->rect.upperLeft.x,it->rect.upperLeft.y,it->rect.upperRight.x,it->rect.upperRight.y,
00218 width, Drawings::ps_solid, Drawings::white);
00219 LINE(imageProcessor_general,
00220 it->rect.bottomLeft.x,it->rect.bottomLeft.y,it->rect.bottomRight.x,it->rect.bottomRight.y,
00221 width, Drawings::ps_solid, Drawings::green);
00222 LINE(imageProcessor_general,
00223 it->rect.upperLeft.x,it->rect.upperLeft.y,it->rect.bottomLeft.x,it->rect.bottomLeft.y,
00224 width, Drawings::ps_solid, Drawings::yellow);
00225 LINE(imageProcessor_general,
00226 it->rect.upperRight.x,it->rect.upperRight.y,it->rect.bottomRight.x,it->rect.bottomRight.y,
00227 width, Drawings::ps_solid, Drawings::blue);
00228
00229 }
00230 }
00231
00232 }
00233
00234 void RBridgeSpecialist::countColors(RBridgeSpecialist::SegmentInfo& si, list<LinePair>& segment){
00235 list<LinePair>::iterator lines;
00236 si.orange = 0;
00237 si.yellow =0;
00238 si.skyblue = 0;
00239 for(lines = segment.begin();lines != segment.end();++lines){
00240 LinePair& line = *lines;
00241 switch(line.color){
00242 case orange:
00243 si.orange += line.v2.x - line.v1.x;
00244 break;
00245 case yellow:
00246 si.yellow += line.v2.x - line.v1.x;
00247 break;
00248 case skyblue:
00249 si.skyblue += line.v2.x - line.v1.x;
00250 break;
00251 }
00252 }
00253
00254 int max = 0;
00255 int min = 0;
00256 si.orange > si.skyblue? max = si.orange : max = si.skyblue;
00257 if (si.yellow > max) max = si.yellow;
00258
00259 min = max/8;
00260
00261 if (si.orange < min) si.orange = 0;
00262 if (si.yellow < min) si.yellow = 0;
00263 if (si.skyblue < min) si.skyblue = 0;
00264 }
00265
00266 void RBridgeSpecialist::calculateAnglesForPoint
00267 (
00268 const Vector2<double>& point,
00269 const CameraMatrix& cameraMatrix,
00270 const CameraInfo& cameraInfo,
00271 Vector2<double>& angles
00272 )
00273 {
00274 double factor = ((double)cameraInfo.resolutionWidth / 2.0) / tan(cameraInfo.openingAngleWidth / 2.0);
00275
00276 Vector3<double> vectorToPoint(
00277 factor,
00278 cameraInfo.resolutionWidth / 2 - point.x,
00279 cameraInfo.resolutionHeight / 2 - point.y);
00280
00281 Vector3<double> vectorToPointWorld =
00282 cameraMatrix.rotation * vectorToPoint;
00283
00284 angles.x =
00285 atan2(vectorToPointWorld.y,vectorToPointWorld.x);
00286
00287 angles.y =
00288 atan2(
00289 vectorToPointWorld.z,
00290 sqrt(sqr(vectorToPointWorld.x) + sqr(vectorToPointWorld.y))
00291 );
00292 }
00293
00294 bool RBridgeSpecialist::calculatePointOnField
00295 (
00296 const double x,
00297 const double y,
00298 const CameraMatrix& cameraMatrix,
00299 const CameraInfo& cameraInfo,
00300 Vector2<int>& pointOnField
00301 )
00302 {
00303 #ifndef _WIN32 // don't recalculate on real robot
00304 static
00305 #endif
00306 double xFactor = tan(cameraInfo.openingAngleWidth / 2) / (cameraInfo.resolutionWidth / 2),
00307 yFactor = tan(cameraInfo.openingAngleHeight / 2) / (cameraInfo.resolutionHeight / 2);
00308
00309 Vector3<double>
00310 vectorToCenter(1, (cameraInfo.resolutionWidth / 2 - 0.5 - x) * xFactor, (cameraInfo.resolutionHeight / 2 - 0.5 - y) * yFactor);
00311 Vector3<double>
00312 vectorToCenterWorld = cameraMatrix.rotation * vectorToCenter;
00313
00314
00315 if(vectorToCenterWorld.z > -5 * yFactor) return false;
00316
00317 double a1 = cameraMatrix.translation.x,
00318 a2 = cameraMatrix.translation.y,
00319 a3 = cameraMatrix.translation.z,
00320 b1 = vectorToCenterWorld.x,
00321 b2 = vectorToCenterWorld.y,
00322 b3 = vectorToCenterWorld.z;
00323
00324 pointOnField.x = int((a1 * b3 - a3 * b1) / b3 + 0.5);
00325 pointOnField.y = int((a2 * b3 - a3 * b2) / b3 + 0.5);
00326
00327 return abs(pointOnField.x) < 10000 && abs(pointOnField.y) < 10000;
00328 }
00329
00330 void RBridgeSpecialist::createValidities(RBridgeSpecialist::SegmentInfo& info){
00331
00332 if (info.skyblue== 0 || info.yellow == 0) info.lmValidityYellow = 0;
00333 else info.lmValidityYellow = 1- 2 * (fabs((double) info.yellow/(double)(info.yellow + info.skyblue) - 0.5) );
00334
00335 if (info.orange== 0 || info.skyblue == 0) info.lmValidityOrange = 0;
00336 else info.lmValidityOrange = 1- 2 * (fabs((double) info.skyblue/(double)(info.skyblue + info.orange) - 0.5) );
00337 }
00338
00339 void RBridgeSpecialist::findBridgeMark(RBridgeSpecialist::SegmentInfo& si){
00340
00341 double boxWidth;
00342
00343 bool isMark = (si.lmValidityOrange > 0.3 || si.lmValidityYellow > 0.3) &&
00344 (boxWidth = (si.rect.bottomRight - si.rect.bottomLeft).abs()) > 5 &&
00345 (si.rect.upperLeft - si.rect.bottomLeft).abs() * 3 < boxWidth;
00346
00347 if (!isMark) return;
00348 BitePoint::Position pos = getPosition(si);
00349 if (pos == BitePoint::numOfPositions) return;
00350 Vector2<int> markCenter;
00351
00352 Rectangle& r = si.rect;
00353
00354 Vector2<double> leftCenter = (r.upperLeft + r.bottomLeft)/2;
00355 Vector2<double> rightCenter = (r.upperRight + r.bottomRight)/2;
00356 Vector2<double> leftToRight = (rightCenter - leftCenter)/6;
00357 Vector2<int> leftStart(
00358 (int)(leftCenter.x + leftToRight.x),
00359 (int)(leftCenter.y + leftToRight.y));
00360 Vector2<int> rightStart(
00361 (int)(rightCenter.x - leftToRight.x),
00362 (int)(rightCenter.y - leftToRight.y));
00363
00364 if (boxWidth < 60)
00365 {
00366 markCenter.x = (int)((leftCenter.x + rightCenter.x)/2);
00367 markCenter.y = (int)((leftCenter.y + rightCenter.y)/2);
00368 }
00369 else
00370 {
00371 colorClass c = noColor;
00372 Vector2<int> temp;
00373 edgeScanner.setDirection(leftToRight);
00374 DOT(imageProcessor_general, leftStart.x,leftStart.y,
00375 Drawings::white, Drawings::green);
00376 RasterSpecialist::Box b(1,1,imageWidth-2,imageWidth-2);
00377 while (b.inside(leftStart.x,leftStart.y)){
00378 c = getColor(leftStart);
00379 if (c == si.rightColor){
00380 markCenter = leftStart;
00381 break;
00382 }
00383 edgeScanner.skip(leftStart.x,leftStart.y);
00384 }
00385 }
00386
00387 DOT(imageProcessor_general, markCenter.x,markCenter.y,
00388 Drawings::white, Drawings::blue);
00389 Vector2<int> up;
00390 up.x = (int)(rightCenter.y - leftCenter.y);
00391 up.y = (int) -(rightCenter.x - (int)leftCenter.x);
00392 up = up/5;
00393
00394
00395
00396 Vector2<int> upper(markCenter + up);
00397 Vector2<int> lower(markCenter - up);
00398 OUTPUT(idText,text,"up: " << up.x << " " << up.y);
00399
00400 DOT(imageProcessor_general, upper.x,upper.y,
00401 Drawings::white, Drawings::blue);
00402 DOT(imageProcessor_general, lower.x,lower.y,
00403 Drawings::white, Drawings::red);
00404
00405 Geometry::Line perp;
00406 perp.base.x = (double)markCenter.x;
00407 perp.base.y = (double)markCenter.y;
00408 perp.direction = pHorizon.direction;
00409
00410 Vector2<int> lScan,rScan,lineCenter;
00411 int leftAbs = 10000,rightAbs = 10000;
00412 float offset = 0;
00413 lScan = lower;
00414 rScan = lower;
00415 Vector2<int> temp;
00416 if (getColor(lScan.x,lScan.y) == lineColor)
00417 {
00418 edgeScanner.scan(lScan.x,lScan.y,-leftToRight);
00419 edgeScanner.scan(rScan.x,rScan.y,leftToRight);
00420 lineCenter = (lScan + rScan)/2;
00421 offset = getDistanceToLine(perp,lineCenter);
00422 }
00423 else
00424 {
00425 colorClass c;
00426 edgeScanner.setDirection(-leftToRight);
00427 while(edgeScanner.colorScan(lScan.x,lScan.y,c)){
00428 if (c == lineColor)
00429 {
00430 lScan = (lScan + temp)/2;
00431 leftAbs = (lScan - lower).abs();
00432 break;
00433 }
00434
00435 temp = lScan;
00436 }
00437
00438 c = noColor;
00439 edgeScanner.setDirection(leftToRight);
00440 while(edgeScanner.colorScan(rScan.x,rScan.y,c)){
00441 if (c == lineColor)
00442 {
00443 rScan = (rScan + temp)/2;
00444 rightAbs = (rScan - lower).abs();
00445
00446 break;
00447 }
00448
00449 temp = rScan;
00450 }
00451
00452 if (leftAbs < rightAbs)
00453 {
00454 offset = (float)leftAbs;
00455 lineCenter = lScan;
00456 }
00457 else
00458 {
00459 offset = (float)-rightAbs;
00460 lineCenter = rScan;
00461 }
00462 }
00463
00464 offset = offset*100/(float)boxWidth;
00465 DOT(imageProcessor_general, lineCenter.x,lineCenter.y,
00466 Drawings::white, Drawings::pink);
00467 OUTPUT(idText,text,"offset: " << offset);
00468 double distance;
00469 double height = (r.upperLeft -r.bottomLeft).abs();
00470 if (boxWidth > 120)
00471 distance = Geometry::getDistanceBySize(
00472 rip->image.cameraInfo,133,boxWidth,markCenter.x,markCenter.y);
00473 else
00474 distance = Geometry::getDistanceBySize(
00475 rip->image.cameraInfo,13,height,markCenter.x,markCenter.y);
00476 OUTPUT(idText,text,"distance: " << distance);
00477 Vector2<double> angles;
00478 Vector2<double> inImage((double)markCenter.x,(double)markCenter.y);
00479 calculateAnglesForPoint(
00480 inImage,rip->cameraMatrix,rip->image.cameraInfo,angles);
00481 OUTPUT(idText,text,"angle: " << angles.x);
00482 rip->specialPercept.ocBridge.bitePoint[pos].addPercept(angles.x,distance,offset);
00483 }
00484
00485 BitePoint::Position RBridgeSpecialist::getPosition(RBridgeSpecialist::SegmentInfo& mark){
00486 edgeScanner.setDirection(horizon.direction);
00487 colorClass c,comp;
00488 Vector2<int> scan;
00489 mark.leftColor = noColor;
00490 mark.rightColor = noColor;
00491 Vector2<double> toRight = (mark.rect.upperRight - mark.rect.upperLeft)/7;
00492 scan.x = (int)(mark.rect.upperLeft.x + mark.rect.bottomLeft.x)/2 + (int)toRight.x;
00493 scan.y = (int)(mark.rect.upperLeft.y + mark.rect.bottomLeft.y)/2 + (int)toRight.y;
00494 DOT(imageProcessor_general, scan.x,scan.y,
00495 Drawings::white, Drawings::red);
00496 if (mark.lmValidityOrange > mark.lmValidityYellow)
00497 comp = orange;
00498 else comp = yellow;
00499 c = getColor(scan.x,scan.y);
00500 do{
00501 if(c == skyblue)
00502 {
00503 mark.leftColor = skyblue;
00504 mark.rightColor = comp;
00505 break;
00506 }
00507 else if (c == comp)
00508 {
00509 mark.leftColor = comp;
00510 mark.rightColor = skyblue;
00511 break;
00512 }
00513 }while (edgeScanner.colorScan(scan.x,scan.y,c));
00514
00515 if (mark.leftColor == noColor) return BitePoint::numOfPositions;
00516 OUTPUT(idText,text,"finished type:" <<
00517 ColorClasses::getColorName(mark.leftColor) << " " <<
00518 ColorClasses::getColorName(mark.rightColor));
00519 if (comp == yellow)
00520 {
00521 if(mark.leftColor == skyblue)
00522 return BitePoint::frontleft;
00523 else
00524 return BitePoint::behindleft;
00525 }
00526 else
00527 {
00528 if(mark.leftColor == skyblue)
00529 return BitePoint::behindright;
00530 else
00531 return BitePoint::frontright;
00532 }
00533 }