00001
00002
00003
00004
00005
00006
00007
00008 #include "ObstaclesModel.h"
00009 #include "Tools/Math/Geometry.h"
00010 #include "Tools/Debugging/DebugDrawings.h"
00011 #include "Tools/RingBufferWithSum.h"
00012
00013 ObstaclesModel::ObstaclesModel()
00014 {
00015 for(int i = 0; i < numOfSectors; i++)
00016 {
00017 distance[i] = maxDistance;
00018 }
00019 corridorInFront = maxDistance;
00020 angleToFreePartOfGoalWasDetermined[0] = false;
00021 angleToFreePartOfGoalWasDetermined[1] = false;
00022 angleToNextFreeTeammateWasDetermined = false;
00023 bodyPSD = 0;
00024 }
00025
00026 ObstaclesModel::~ObstaclesModel()
00027 {
00028 }
00029
00030 int ObstaclesModel::getDistanceInMajorDirection(Directions direction) const
00031 {
00032 int numberOfMicrosPerMacro = numOfSectors/numberOfDirections;
00033 int macroSector = (int)direction;
00034 int sector;
00035 int endSector = ((macroSector+1)*numberOfMicrosPerMacro-numberOfMicrosPerMacro/2)%numOfSectors;
00036
00037 int minDistance = maxDistance;
00038
00039 for(
00040 sector = macroSector*numberOfMicrosPerMacro-numberOfMicrosPerMacro/2;
00041 sector != endSector;
00042 sector = (sector + 1) % numOfSectors)
00043 if(distance[sector] < minDistance)
00044 minDistance = distance[sector];
00045
00046 return minDistance;
00047 }
00048
00049
00050
00051 int ObstaclesModel::getDistanceInDirection(double direction, double openingAngle) const
00052 {
00053 int sector;
00054 int minDistance = maxDistance;
00055 int endSector = getSectorFromAngle(direction + openingAngle);
00056
00057 for (
00058 sector = getSectorFromAngle(direction - openingAngle);
00059 sector != endSector;
00060 sector = (sector + 1) % numOfSectors)
00061 if (distance[sector] < minDistance)
00062 minDistance = distance[sector];
00063
00064 return minDistance;
00065 }
00066
00067
00068 double ObstaclesModel::getTotalFreeSpaceInSector(double direction, double openingAngle, double maxDist) const
00069 {
00070 int sector;
00071 int endSector = getSectorFromAngle(direction + openingAngle/2);
00072 double sum = 0.0;
00073
00074 for (sector = getSectorFromAngle(direction - openingAngle/2);
00075 sector != endSector; sector = (sector + 1) % numOfSectors)
00076 {
00077 if (distance[sector] < maxDist)
00078 sum += distance[sector];
00079 else
00080 sum += maxDist;
00081 }
00082
00083 return sum;
00084 }
00085
00086
00087 double ObstaclesModel::getDistanceInCorridor(double angle, double width) const
00088 {
00089 double minDistance = maxDistance;
00090
00091 int minSector = ObstaclesModel::getSectorFromAngle(angle-pi_2);
00092 int maxSector = ObstaclesModel::getSectorFromAngle(angle+pi_2);
00093
00094 Geometry::Line centerLine, leftLine, rightLine;
00095 leftLine.direction.x = cos(angle);
00096 leftLine.direction.y = sin(angle);
00097
00098 leftLine.base.y = leftLine.direction.x * width / 2;
00099 leftLine.base.x = -leftLine.direction.y * width / 2;
00100
00101 rightLine.direction = leftLine.direction;
00102 rightLine.base = -leftLine.base;
00103
00104 centerLine.base.x = 0; centerLine.base.y = 0;
00105 centerLine.direction = leftLine.direction;
00106
00107 for(int i = minSector; i < maxSector; i++)
00108 {
00109 int currentSector = i%numOfSectors;
00110 Vector2<double> point;
00111 point.x = cos(getAngleOfSector(currentSector)) * distance[currentSector];
00112 point.y = sin(getAngleOfSector(currentSector)) * distance[currentSector];
00113 if(
00114 distance[currentSector] < minDistance &&
00115 distance[currentSector] > 10 &&
00116 abs((int)Geometry::getDistanceToLine(centerLine, point)) < width / 2.0
00117 )
00118 minDistance = distance[currentSector];
00119 }
00120
00121 LINE(models_corridorsRadar,
00122 leftLine.base.x, leftLine.base.y,
00123 leftLine.base.x + leftLine.direction.x * minDistance,
00124 leftLine.base.y + leftLine.direction.y * minDistance,
00125 2, Drawings::ps_solid, Drawings::red
00126 );
00127 LINE(models_corridorsRadar,
00128 rightLine.base.x, rightLine.base.y,
00129 rightLine.base.x + rightLine.direction.x * minDistance,
00130 rightLine.base.y + rightLine.direction.y * minDistance,
00131 2, Drawings::ps_solid, Drawings::green
00132 );
00133 LINE(models_corridorsRadar,
00134 leftLine.base.x + leftLine.direction.x * minDistance,
00135 leftLine.base.y + leftLine.direction.y * minDistance,
00136 rightLine.base.x + rightLine.direction.x * minDistance,
00137 rightLine.base.y + rightLine.direction.y * minDistance,
00138 2, Drawings::ps_solid, Drawings::blue
00139 );
00140 return minDistance;
00141 }
00142
00143 double ObstaclesModel::getAngleOfNextFreeSectorLeft(double sizeOfGap, double angle, int minDistance) const
00144 {
00145 double direction = 0;
00146 int numberOfSectorsOfGap = (int)(sizeOfGap * numOfSectors / pi2);
00147
00148 int startSector = getSectorFromAngle(angle);
00149 int leftCounter = 0;
00150
00151 for(int i = -numberOfSectorsOfGap / 2; i < numOfSectors / 2; i++)
00152 {
00153 int leftSector = (startSector+i)%numOfSectors;
00154
00155 if(distance[leftSector] > minDistance)
00156 leftCounter++;
00157 else leftCounter = 0;
00158
00159 if(leftCounter == numberOfSectorsOfGap)
00160 {
00161 direction = getAngleOfSector((startSector+i-numberOfSectorsOfGap/2)%numOfSectors);
00162 break;
00163 }
00164
00165 }
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187 return direction;
00188 }
00189
00190
00191 double ObstaclesModel::getAngleOfNextFreeSectorRight(double sizeOfGap, double angle, int minDistance) const
00192 {
00193 double direction = 0;
00194 int numberOfSectorsOfGap = (int)(sizeOfGap * numOfSectors / pi2);
00195
00196 int startSector = getSectorFromAngle(angle);
00197 int rightCounter = 0;
00198
00199 for(int i = -numberOfSectorsOfGap / 2; i < numOfSectors / 2; i++)
00200 {
00201 int rightSector = (startSector-i)%numOfSectors;
00202
00203 if(distance[rightSector] > minDistance)
00204 rightCounter++;
00205 else rightCounter = 0;
00206
00207 if(rightCounter == numberOfSectorsOfGap)
00208 {
00209 direction = getAngleOfSector((startSector-i+numberOfSectorsOfGap/2)%numOfSectors);
00210 break;
00211 }
00212
00213 }
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235 return direction;
00236 }
00237 double ObstaclesModel::getAngleOfNextFreeSector(double sizeOfGap, double angle, int minDistance) const
00238 {
00239 double direction = 0;
00240 int numberOfSectorsOfGap = (int)(sizeOfGap * numOfSectors / pi2);
00241
00242 int startSector = getSectorFromAngle(angle);
00243 int leftCounter = 0;
00244 int rightCounter = 0;
00245
00246 for(int i = -numberOfSectorsOfGap / 2; i < numOfSectors / 2; i++)
00247 {
00248 int leftSector = (startSector+i)%numOfSectors;
00249
00250 if(distance[leftSector] > minDistance)
00251 leftCounter++;
00252 else leftCounter = 0;
00253
00254 int rightSector = (startSector-i)%numOfSectors;
00255
00256 if(distance[rightSector] > minDistance)
00257 rightCounter++;
00258 else rightCounter = 0;
00259
00260 if(leftCounter == numberOfSectorsOfGap)
00261 {
00262 direction = getAngleOfSector((startSector+i-numberOfSectorsOfGap/2)%numOfSectors);
00263 break;
00264 }
00265
00266 if(rightCounter == numberOfSectorsOfGap)
00267 {
00268 direction = getAngleOfSector((startSector-i+numberOfSectorsOfGap/2)%numOfSectors);
00269 break;
00270 }
00271 }
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291 return direction;
00292 }
00293
00294
00295 int ObstaclesModel::getMinimalDistanceInRange
00296 (
00297 double centerAngle,
00298 double openingAngle,
00299 double& angleWithMinimalDistance
00300 ) const
00301 {
00302 int centerSector = getSectorFromAngle(centerAngle);
00303 int endSector = getSectorFromAngle(centerAngle + openingAngle / 2.0);
00304
00305 int minDistance = 10000;
00306 int sectorWithMinimalDistance = centerSector;
00307
00308 for(int i = 0; centerSector + i < endSector; i++)
00309 {
00310 if(distance[centerSector + i] < minDistance)
00311 {
00312 minDistance = distance[centerSector + i];
00313 sectorWithMinimalDistance = centerSector + i;
00314 }
00315 if(distance[centerSector - i] < minDistance)
00316 {
00317 minDistance = distance[centerSector - i];
00318 sectorWithMinimalDistance = centerSector - i;
00319 }
00320 }
00321 angleWithMinimalDistance = getAngleOfSector(sectorWithMinimalDistance);
00322 return minDistance;
00323 }
00324
00325 int ObstaclesModel::getMinimalDistanceInRange
00326 (
00327 double centerAngle,
00328 double openingAngle,
00329 double& angleWithMinimalDistance,
00330 ObstaclesPercept::ObstacleType obstacleType
00331 ) const
00332 {
00333 int centerSector = getSectorFromAngle(centerAngle);
00334 int endSector = getSectorFromAngle(centerAngle + openingAngle / 2.0);
00335
00336 int minDistance = 10000;
00337 int sectorWithMinimalDistance = centerSector;
00338
00339 for(int i = 0; centerSector + i < endSector; i++)
00340 {
00341 if(this->obstacleType[centerSector + i] == obstacleType && distance[centerSector + i] < minDistance)
00342 {
00343 minDistance = distance[centerSector + i];
00344 sectorWithMinimalDistance = centerSector + i;
00345 }
00346 if(this->obstacleType[centerSector - i] == obstacleType && distance[centerSector - i] < minDistance)
00347 {
00348 minDistance = distance[centerSector - i];
00349 sectorWithMinimalDistance = centerSector - i;
00350 }
00351 }
00352 angleWithMinimalDistance = getAngleOfSector(sectorWithMinimalDistance);
00353 return minDistance;
00354 }
00355
00356 double ObstaclesModel::getPercentageOfLowDistanceObstaclesInRange
00357 (
00358 double centerAngle,
00359 double openingAngle,
00360 int maxDistance
00361 ) const
00362 {
00363 int beginSector = getSectorFromAngle(centerAngle - openingAngle / 2.0);
00364 int endSector = getSectorFromAngle(centerAngle + openingAngle / 2.0);
00365
00366 int numberOfSectorsWithCloseObstacle = 0;
00367
00368 for(int i = beginSector; i <= endSector; i++)
00369 {
00370 if(distance[i] < maxDistance)
00371 {
00372 numberOfSectorsWithCloseObstacle++;
00373 }
00374 }
00375 return (double)(numberOfSectorsWithCloseObstacle) / (double)(endSector - beginSector + 1);
00376 }
00377
00378
00379 double ObstaclesModel::getAngleOfLargeGapInRange(double centerAngle, double openingAngle, SearchDirections searchDirection) const
00380 {
00381 int centerSector = getSectorFromAngle(centerAngle);
00382 int endSectorLeft = getSectorFromAngle(centerAngle + openingAngle / 2.0);
00383
00384 int numberOfSectorsOnOneSide = endSectorLeft - centerSector + 1;
00385
00386 int bestSector;
00387
00388 int maxSumOfDistances = 0;
00389 enum {numberOfSectorsOfGap = 7};
00390
00391 RingBufferWithSum<numberOfSectorsOfGap> bufferMovingRight;
00392 RingBufferWithSum<numberOfSectorsOfGap> bufferMovingLeft;
00393
00394 int i;
00395 for(i = 0; i < numberOfSectorsOfGap; i++)
00396 {
00397 bufferMovingLeft.add(min(1000, distance[i + centerSector - numberOfSectorsOfGap / 2]) );
00398 bufferMovingRight.add(min(1000, distance[-i + centerSector + numberOfSectorsOfGap / 2]) );
00399 }
00400 maxSumOfDistances = bufferMovingLeft.getSum();
00401 bestSector = centerSector;
00402
00403 for(i = numberOfSectorsOfGap / 2 + 1; i < numberOfSectorsOnOneSide; i++)
00404 {
00405 bufferMovingLeft.add(min(1000, distance[centerSector + i]) );
00406 bufferMovingRight.add(min(1000, distance[centerSector - i]) );
00407
00408 int newSum;
00409 int newSector;
00410 if(
00411 (
00412 bufferMovingLeft.getSum() > bufferMovingRight.getSum() &&
00413 searchDirection != searchRight)
00414 ||
00415 searchDirection == searchLeft
00416 )
00417 {
00418 newSum = bufferMovingLeft.getSum();
00419 newSector = centerSector + i - (numberOfSectorsOfGap / 2);
00420 }
00421 else
00422 {
00423 newSum = bufferMovingRight.getSum();
00424 newSector = centerSector - i + (numberOfSectorsOfGap / 2);
00425 }
00426
00427 if(newSum > maxSumOfDistances + 80 * numberOfSectorsOfGap)
00428 {
00429 maxSumOfDistances = newSum;
00430 bestSector = newSector;
00431 }
00432 }
00433 return getAngleOfSector(bestSector);
00434 }
00435
00436 double ObstaclesModel::getAngleOfLargeGapInRange2(double centerAngle, double openingAngle, SearchDirections searchDirection) const
00437 {
00438 int centerSector = getSectorFromAngle(centerAngle);
00439 int endSectorLeft = getSectorFromAngle(centerAngle + openingAngle / 2.0);
00440
00441 int numberOfSectorsOnOneSide = endSectorLeft - centerSector + 1;
00442
00443 int bestSector;
00444
00445 int maxMinOfDistances = 0;
00446 enum {numberOfSectorsOfGap = 7};
00447
00448 RingBufferWithSum<numberOfSectorsOfGap> bufferMovingRight;
00449 RingBufferWithSum<numberOfSectorsOfGap> bufferMovingLeft;
00450
00451 int i;
00452 for(i = 0; i < numberOfSectorsOfGap; i++)
00453 {
00454 bufferMovingLeft.add(min(1000, distance[i + centerSector - numberOfSectorsOfGap / 2]) );
00455 bufferMovingRight.add(min(1000, distance[-i + centerSector + numberOfSectorsOfGap / 2]) );
00456 }
00457 maxMinOfDistances = bufferMovingLeft.getMinimum();
00458 bestSector = centerSector;
00459
00460 for(i = numberOfSectorsOfGap / 2 + 1; i < numberOfSectorsOnOneSide; i++)
00461 {
00462 bufferMovingLeft.add(min(1000, distance[centerSector + i]) );
00463 bufferMovingRight.add(min(1000, distance[centerSector - i]) );
00464
00465 int newMin;
00466 int newSector;
00467 if(
00468 (
00469 bufferMovingLeft.getSum() > bufferMovingRight.getSum() &&
00470 searchDirection != searchRight)
00471 ||
00472 searchDirection == searchLeft
00473 )
00474 {
00475 newMin = bufferMovingLeft.getMinimum();
00476 newSector = centerSector + i - (numberOfSectorsOfGap / 2);
00477 }
00478 else
00479 {
00480 newMin = bufferMovingRight.getMinimum();
00481 newSector = centerSector - i + (numberOfSectorsOfGap / 2);
00482 }
00483
00484 if(newMin > maxMinOfDistances + 80)
00485 {
00486 maxMinOfDistances = newMin;
00487 bestSector = newSector;
00488 }
00489 }
00490 return getAngleOfSector(bestSector);
00491 }
00492
00493
00494 void ObstaclesModel::operator=(const ObstaclesModel& other)
00495 {
00496 for(int i = 0; i < numOfSectors; i++)
00497 {
00498 distance[i] = other.distance[i];
00499 obstacleType[i] = other.obstacleType[i];
00500 }
00501 corridorInFront = other.corridorInFront;
00502 }
00503
00504 In& operator>>(In& stream,ObstaclesModel& obstaclesModel)
00505 {
00506 stream >> obstaclesModel.frameNumber;
00507 stream.read(&obstaclesModel,sizeof(ObstaclesModel));
00508 return stream;
00509 }
00510
00511 Out& operator<<(Out& stream, const ObstaclesModel& obstaclesModel)
00512 {
00513 stream << obstaclesModel.frameNumber;
00514 stream.write(&obstaclesModel,sizeof(ObstaclesModel));
00515 return stream;
00516 }
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649