00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "Platform/GTAssert.h"
00011 #include "GT2004SelfLocator.h"
00012 #include "Platform/SystemCall.h"
00013 #include "Tools/FieldDimensions.h"
00014 #include "Tools/Player.h"
00015 #include "Tools/Debugging/Debugging.h"
00016 #include "Tools/Math/Geometry.h"
00017 #include "Tools/Streams/InStreams.h"
00018 #include "Tools/Debugging/GenericDebugData.h"
00019
00020 double GT2004SelfLocator::paramUp = 0.01,
00021 GT2004SelfLocator::paramDown = 0.005,
00022 GT2004SelfLocator::paramDelay = 3,
00023 GT2004SelfLocator::paramHeight = 150,
00024 GT2004SelfLocator::paramZ = 10,
00025 GT2004SelfLocator::paramY = 2;
00026
00027 GT2004SelfLocator::Sample::Sample()
00028 {
00029 for(int i = 0; i < numberOfQualities; ++i)
00030 quality[i] = 0.5;
00031 probability = 2;
00032 }
00033
00034 GT2004SelfLocator::Sample::Sample(const Pose2D& pose,const double* quality)
00035 : PoseSample(pose)
00036 {
00037 for(int i = 0; i < numberOfQualities; ++i)
00038 this->quality[i] = 2;
00039 probability = 2;
00040 }
00041
00042 void GT2004SelfLocator::Sample::updateQuality(const double* average)
00043 {
00044 probability = 1;
00045 for(int i = 0; i < numberOfQualities; ++i)
00046 probability *= quality[i] == 2 ? max(average[i] - paramDelay * paramUp, 0.000001) : quality[i];
00047 }
00048
00049 void GT2004SelfLocator::Sample::setProbability(LinesPercept::LineType type,double value)
00050 {
00051 double& q = quality[type > LinesPercept::yellowGoal ? type - 1 : type];
00052 if(type > LinesPercept::yellowGoal)
00053 {
00054 if(q == 2)
00055 q = value;
00056 else if(value < q)
00057 if(value < q - 0.05)
00058 q -= 0.05;
00059 else
00060 q = value;
00061 else
00062 if(value > q + 0.1)
00063 q += 0.1;
00064 else
00065 q = value;
00066 }
00067 else
00068 {
00069 if(q == 2)
00070 q = max(value - paramDelay * paramUp, 0.000001);
00071 else if(value < q)
00072 if(value < q - paramDown)
00073 q -= paramDown;
00074 else
00075 q = value;
00076 else
00077 if(value > q + paramUp)
00078 q += paramUp;
00079 else
00080 q = value;
00081 }
00082 }
00083
00084 GT2004SelfLocator::GT2004SelfLocator(const SelfLocatorInterfaces& interfaces)
00085 : SelfLocator(interfaces)
00086 {
00087 int i;
00088 for(i = 0; i < Sample::numberOfQualities; ++i)
00089 average[i] = 0.5;
00090 for(i = 0; i < SAMPLES_MAX; ++i)
00091 (Pose2D&) sampleSet[i] = field.randomPose();
00092 numberOfTypes = 0;
00093 numOfFlags = 0;
00094 sensorUpdated = false;
00095 timeStamp = 0;
00096 speed = 0;
00097 }
00098
00099 void GT2004SelfLocator::execute()
00100 {
00101 NDECLARE_DEBUGDRAWING( "gt04-sl" , "drawingOnField" , "GT2004SelfLocator debug drawings");
00102 const int maxPercepts = 3;
00103
00104
00105
00106 robotPose.setFrameNumber(landmarksPercept.frameNumber);
00107 robotPose.setTimestamp(SystemCall::getCurrentSystemTime());
00108
00109 Pose2D odometry = odometryData - lastOdometry;
00110 lastOdometry = odometryData;
00111 if(SystemCall::getTimeSince(timeStamp) > 500)
00112 {
00113 speed = (odometryData - lastOdometry2).translation.abs() / SystemCall::getTimeSince(timeStamp) * 1000.0;
00114 lastOdometry2 = odometryData;
00115 timeStamp = SystemCall::getCurrentSystemTime();
00116 }
00117 paramZ = 10 - 9 * speed / 400;
00118
00119
00120 updateByOdometry(odometry,
00121 Pose2D(landmarksPercept.cameraOffset.x,
00122 landmarksPercept.cameraOffset.y),
00123 sensorUpdated);
00124
00125
00126 numberOfTypes = 0;
00127 sensorUpdated = false;
00128 if(cameraMatrix.isValid)
00129 {
00130 int i;
00131 for(i = 0; i < 2; ++i)
00132 for(int j = 0; j < linesPercept.points[i].numberOfPoints && j < maxPercepts; ++j)
00133 {
00134 updateByPoint(linesPercept.points[i].pointsOnField[rand() % linesPercept.points[i].numberOfPoints],
00135 LinesPercept::LineType(i));
00136 sensorUpdated = true;
00137 }
00138
00139 if(linesPercept.points[LinesPercept::yellowGoal].numberOfPoints)
00140 types[numberOfTypes++] = LinesPercept::yellowGoal;
00141 if(linesPercept.points[LinesPercept::skyblueGoal].numberOfPoints)
00142 types[numberOfTypes++] = LinesPercept::skyblueGoal;
00143
00144 if(linesPercept.points[LinesPercept::yellowGoal].numberOfPoints ||
00145 linesPercept.points[LinesPercept::skyblueGoal].numberOfPoints)
00146 for(int j = 0; j < linesPercept.points[LinesPercept::yellowGoal].numberOfPoints +
00147 linesPercept.points[LinesPercept::skyblueGoal].numberOfPoints && j < maxPercepts; ++j)
00148 {
00149 LinesPercept::LineType select = (random() + 1e-6) * linesPercept.points[LinesPercept::yellowGoal].numberOfPoints >
00150 linesPercept.points[LinesPercept::skyblueGoal].numberOfPoints
00151 ? LinesPercept::yellowGoal
00152 : LinesPercept::skyblueGoal;
00153 updateByPoint(linesPercept.points[select].pointsOnField[rand() % linesPercept.points[select].numberOfPoints],
00154 select);
00155 sensorUpdated = true;
00156 }
00157 for(i = 0; i < landmarksPercept.numberOfFlags; ++i)
00158 {
00159 const Flag& flag = landmarksPercept.flags[i];
00160 if(!flag.isOnBorder(flag.x.max))
00161 updateByFlag(flag.position,
00162 LEFT_SIDE_OF_FLAG,
00163 flag.x.max);
00164 if(!flag.isOnBorder(flag.x.min))
00165 updateByFlag(flag.position,
00166 RIGHT_SIDE_OF_FLAG,
00167 flag.x.min);
00168 }
00169 for(i = 0; i < landmarksPercept.numberOfGoals; ++i)
00170 {
00171 const Goal& goal = landmarksPercept.goals[i];
00172 if(!goal.isOnBorder(goal.x.max))
00173 updateByGoalPost(goal.leftPost,
00174 goal.x.max);
00175 if(!goal.isOnBorder(goal.x.min))
00176 updateByGoalPost(goal.rightPost,
00177 goal.x.min);
00178 }
00179
00180 if(sensorUpdated)
00181 {
00182
00183 generatePoseTemplates(landmarksPercept,odometry);
00184 resample();
00185 }
00186 }
00187
00188 Pose2D pose;
00189 double validity;
00190 calcPose(pose,validity);
00191 robotPose.setPose(pose);
00192 robotPose.setValidity(validity);
00193 sampleSet.link(selfLocatorSamples);
00194
00195
00196
00197
00198 DEBUG_DRAWING_FINISHED(selfLocatorField);
00199 DEBUG_DRAWING_FINISHED(selfLocator);
00200
00201 landmarksState.update(landmarksPercept);
00202 }
00203
00204 static double fmax(double a,double b)
00205 {
00206 return a> b ? a : b;
00207 }
00208
00209 void GT2004SelfLocator::updateByOdometry(const Pose2D& odometry,
00210 const Pose2D& camera,
00211 bool noise)
00212 {
00213 double transNoise = noise ? 200 : 0,
00214 rotNoise = noise ? 0.5 : 0;
00215 double dist = odometry.translation.abs();
00216 double angle = fabs(odometry.getAngle());
00217 double f;
00218
00219 for(int i = 0; i < SAMPLES_MAX; ++i)
00220 {
00221 Sample& s = sampleSet[i];
00222 s += odometry;
00223 if(s.probability == 2)
00224 f = 0;
00225 else
00226 f = (1 - s.probability) * (1 - s.probability);
00227 double rotError = ((random() * 2 - 1) * fmax(fmax(dist * 0.002,angle * 0.2),rotNoise * f));
00228 Vector2<double> transError((random() * 2 - 1) * max(fmax(fabs(odometry.translation.x) * 0.1,
00229 fabs(odometry.translation.y) * 0.02),
00230 transNoise * f),
00231 (random() * 2 - 1) * max(fmax(fabs(odometry.translation.y) * 0.1,
00232 fabs(odometry.translation.x) * 0.02),
00233 transNoise * f));
00234 s += Pose2D(rotError,transError);
00235 s.camera = s + camera;
00236 }
00237 }
00238
00239 void GT2004SelfLocator::updateByPoint(const LinesPercept::LinePoint& point,LinesPercept::LineType type)
00240 {
00241 NCOMPLEX_DRAWING("gt04-sl", draw(point,type));
00242
00243 int index = type;
00244 if(getPlayer().getTeamColor() == Player::blue && type >= LinesPercept::yellowGoal)
00245 index = LinesPercept::yellowGoal + LinesPercept::skyblueGoal - type;
00246 double d = point.abs();
00247 double zObs = atan2(paramHeight,d),
00248 yObs = atan2((double)point.y,(double)point.x);
00249 Pose2D point2(point.angle, Vector2<double>(point.x, point.y));
00250 for(int i = 0; i < SAMPLES_MAX; ++i)
00251 {
00252 Sample& s = sampleSet[i];
00253 Pose2D p = s + point2;
00254 Vector2<double> vMin;
00255 bool isY = index == LinesPercept::field && (fabs(p.getAngle()) < pi / 4 || fabs(p.getAngle()) > 3 * pi / 4);
00256 if(isY)
00257 vMin = observationTable[LinesPercept::numberOfLineTypes].getClosestPoint(p.translation);
00258 else
00259 vMin = observationTable[index].getClosestPoint(p.translation);
00260 if(vMin.x != 1000000)
00261 {
00262 Vector2<double> diff = vMin - p.translation;
00263 Vector2<double> v = (Pose2D(vMin) - s).translation;
00264 double zModel = atan2(paramHeight,v.abs()),
00265 yModel = atan2(v.y,v.x);
00266 s.setProbability(isY ? LinesPercept::LineType(LinesPercept::numberOfLineTypes + 1) : type, sigmoid((zModel - zObs) * paramZ) * sigmoid((yModel - yObs) * paramY));
00267 }
00268 else
00269 s.setProbability(type,0.000001);
00270 }
00271 }
00272
00273 void GT2004SelfLocator::updateByFlag(const Vector2<double>& flag,
00274 FlagSides sideOfFlag,
00275 double measuredBearing)
00276 {
00277 sensorUpdated = true;
00278 for(int i = 0; i < SAMPLES_MAX; ++i)
00279 {
00280 Sample& s = sampleSet[i];
00281 Pose2D p(flag.x,flag.y);
00282 p -= s.camera;
00283 if (p.translation.abs() > flagRadius)
00284 {
00285 double assumedBearing = atan2(p.translation.y,p.translation.x) + sideOfFlag * asin(flagRadius / p.translation.abs());
00286 double similarity = fabs((assumedBearing - measuredBearing)) / pi;
00287 if(similarity > 1)
00288 similarity = 2.0 - similarity;
00289 s.setProbability(LinesPercept::numberOfLineTypes,sigmoid(similarity * 7));
00290 }
00291 else
00292 s.setProbability(LinesPercept::numberOfLineTypes,0.000001);
00293 }
00294 }
00295
00296 void GT2004SelfLocator::updateByGoalPost(const Vector2<double>& goalPost,
00297 double measuredBearing)
00298 {
00299 sensorUpdated = true;
00300 for(int i = 0; i < SAMPLES_MAX; ++i)
00301 {
00302 Sample& s = sampleSet[i];
00303 Pose2D p(goalPost.x,goalPost.y);
00304 p -= s.camera;
00305 double assumedBearing = atan2(p.translation.y,p.translation.x);
00306 double similarity = fabs((assumedBearing - measuredBearing)) / pi;
00307 if(similarity > 1)
00308 similarity = 2 - similarity;
00309 s.setProbability(LinesPercept::numberOfLineTypes,sigmoid(similarity * 7));
00310 }
00311 }
00312
00313 void GT2004SelfLocator::resample()
00314 {
00315 int i,j,
00316 count[Sample::numberOfQualities];
00317
00318 for(i = 0; i < Sample::numberOfQualities; ++i)
00319 {
00320 average[i] = 0;
00321 count[i] = 0;
00322 }
00323
00324 for(i = 0; i < SAMPLES_MAX; ++i)
00325 {
00326 Sample& s = sampleSet[i];
00327 for(j = 0; j < Sample::numberOfQualities; ++j)
00328 if(s.quality[j] != 2)
00329 {
00330 average[j] += s.quality[j];
00331 ++count[j];
00332 }
00333 }
00334
00335 double average2 = 1;
00336 for(i = 0; i < Sample::numberOfQualities; ++i)
00337 {
00338 if(count[i])
00339 average[i] /= count[i];
00340 else
00341 average[i] = 0.5;
00342 average2 *= average[i];
00343 }
00344
00345
00346 for(i = 0; i < SAMPLES_MAX; ++i)
00347 sampleSet[i].updateQuality(average);
00348
00349
00350 Sample* oldSet = sampleSet.swap();
00351
00352 double probSum = 0;
00353 for(i = 0; i < SAMPLES_MAX; ++i)
00354 probSum += oldSet[i].getQuality();
00355 double prob2Index = (double) SAMPLES_MAX / probSum;
00356
00357 double indexSum = 0;
00358 j = 0;
00359 for(i = 0; i < SAMPLES_MAX; ++i)
00360 {
00361 indexSum += oldSet[i].getQuality() * prob2Index;
00362 while(j < SAMPLES_MAX && j < indexSum - 0.5)
00363 sampleSet[j++] = oldSet[i];
00364 }
00365
00366 for(i = 0; i < SAMPLES_MAX; ++i)
00367 {
00368 Sample& s = sampleSet[i];
00369
00370 if(numOfTemplates && random() * average2 > s.getQuality())
00371 s = getTemplate();
00372 else
00373 {
00374 NCOMPLEX_DRAWING("gt04-sl",draw(s));
00375 }
00376 }
00377 }
00378
00379 void GT2004SelfLocator::calcPose(Pose2D& pose,double& validity)
00380 {
00381 Cell cells[GRID_MAX][GRID_MAX][GRID_MAX];
00382 double width = field.x.getSize(),
00383 height = field.y.getSize();
00384
00385
00386 for(int i = 0; i < SAMPLES_MAX; ++i)
00387 {
00388 Sample& p = sampleSet[i];
00389 if(p.isValid())
00390 {
00391 int r = static_cast<int>((p.getAngle() / pi2 + 0.5) * GRID_MAX),
00392 y = static_cast<int>((p.translation.y / height + 0.5) * GRID_MAX),
00393 x = static_cast<int>((p.translation.x / width + 0.5) * GRID_MAX);
00394 if(x < 0)
00395 x = 0;
00396 else if(x >= GRID_MAX)
00397 x = GRID_MAX-1;
00398 if(y < 0)
00399 y = 0;
00400 else if(y >= GRID_MAX)
00401 y = GRID_MAX-1;
00402 if(r < 0)
00403 r = GRID_MAX-1;
00404 else if(r >= GRID_MAX)
00405 r = 0;
00406 Cell& c = cells[r][y][x];
00407 p.next = c.first;
00408 c.first = &p;
00409 ++c.count;
00410 }
00411 }
00412
00413
00414 int rMax = 0,
00415 yMax = 0,
00416 xMax = 0,
00417 countMax = 0,
00418 r;
00419 for(r = 0; r < GRID_MAX; ++r)
00420 {
00421 int rNext = (r + 1) % GRID_MAX;
00422 for(int y = 0; y < GRID_MAX - 1; ++y)
00423 for(int x = 0; x < GRID_MAX - 1; ++x)
00424 {
00425 int count = cells[r][y][x].count +
00426 cells[r][y][x+1].count +
00427 cells[r][y+1][x].count +
00428 cells[r][y+1][x+1].count +
00429 cells[rNext][y][x].count +
00430 cells[rNext][y][x+1].count +
00431 cells[rNext][y+1][x].count +
00432 cells[rNext][y+1][x+1].count;
00433 if(count > countMax)
00434 {
00435 countMax = count;
00436 rMax = r;
00437 yMax = y;
00438 xMax = x;
00439 }
00440 }
00441 }
00442
00443 if(countMax > 0)
00444 {
00445
00446 double xSum = 0,
00447 ySum = 0,
00448 cosSum = 0,
00449 sinSum = 0,
00450 qualitySum = 0;
00451 for(r = 0; r < 2; ++r)
00452 {
00453 int r2 = (rMax + r) % GRID_MAX;
00454 for(int y = 0; y < 2; ++y)
00455 for(int x = 0; x < 2; ++x)
00456 {
00457 for(Sample* p = cells[r2][yMax + y][xMax + x].first; p; p = p->next)
00458 if(p->isValid())
00459 {
00460 xSum += p->translation.x * p->getQuality();
00461 ySum += p->translation.y * p->getQuality();
00462 cosSum += p->getCos() * p->getQuality();
00463 sinSum += p->getSin() * p->getQuality();
00464 qualitySum += p->getQuality();
00465 }
00466 }
00467 }
00468 if(qualitySum)
00469 {
00470 pose = Pose2D(atan2(sinSum,cosSum),
00471 Vector2<double>(xSum / qualitySum,ySum / qualitySum));
00472 validity = qualitySum / SAMPLES_MAX;
00473 double diff = field.clip(pose.translation);
00474 if(diff > 1)
00475 validity /= sqrt(diff);
00476 return;
00477 }
00478 }
00479 validity = 0;
00480 }
00481
00482
00483
00484
00485 bool GT2004SelfLocator::poseFromBearings(double dir0,double dir1,double dir2,
00486 const Vector2<double>& mark0,
00487 const Vector2<double>& mark1,
00488 const Vector2<double>& mark2,
00489 const Vector2<double>& cameraOffset,
00490 Pose2D& resultingPose) const
00491 {
00492 double w1 = dir1 - dir0,
00493 w2 = dir2 - dir1;
00494 if(sin(w1) != 0 && sin(w2) != 0)
00495 {
00496 Vector2<double> p = mark2 - mark1;
00497 double a2 = p.abs();
00498 p = (Pose2D(mark0) - Pose2D(atan2(p.y,p.x),mark1)).translation;
00499 double a1 = p.abs();
00500 if(a1 > 0 && a2 > 0)
00501 {
00502 double w3 = pi2 - w1 - w2 - atan2(p.y,p.x);
00503 double t = a1 * sin(w2) / (a2 * sin(w1)) + cos(w3);
00504 if(t != 0)
00505 {
00506 double w = atan(sin(w3) / t);
00507 double b = a1 * sin(w) / sin(w1);
00508 w = pi - w1 - w;
00509 p = mark0 - mark1;
00510 resultingPose = Pose2D(atan2(p.y,p.x) - w,mark1)
00511 + Pose2D(Vector2<double>(b,0));
00512 p = (Pose2D(mark1) - resultingPose).translation;
00513 resultingPose += Pose2D(atan2(p.y,p.x) - dir1);
00514 resultingPose += Pose2D(Vector2<double>(-cameraOffset.x,
00515 -cameraOffset.y));
00516 return true;
00517 }
00518 }
00519 }
00520 return false;
00521 }
00522
00523 int GT2004SelfLocator::poseFromBearingsAndDistance(
00524 double dir0,double dir1,double dist,
00525 const Vector2<double>& mark0,
00526 const Vector2<double>& mark1,
00527 const Vector2<double>& cameraOffset,
00528 Pose2D& resultingPose1,
00529 Pose2D& resultingPose2) const
00530 {
00531 double alpha = dir0 - dir1;
00532 Vector2<double> diff = mark0 - mark1;
00533 double dir10 = atan2(diff.y,diff.x);
00534 double f = dist * sin(alpha) / diff.abs();
00535 if(fabs(f) <= 1)
00536 {
00537 double gamma = asin(f),
00538 beta = pi - alpha - gamma;
00539 resultingPose1 = Pose2D(dir10 + beta,mark1) +
00540 Pose2D(pi - dir1,Vector2<double>(dist,0)) +
00541 Pose2D(Vector2<double>(-cameraOffset.x,
00542 -cameraOffset.y));
00543 if(fabs(alpha) < pi_2 || fabs(alpha) > 3 * pi_2)
00544 {
00545 if(gamma > 0)
00546 gamma = pi - gamma;
00547 else
00548 gamma = -pi - gamma;
00549 beta = pi - alpha - gamma;
00550 resultingPose2 = Pose2D(dir10 + beta,mark1) +
00551 Pose2D(pi - dir1,Vector2<double>(dist,0)) +
00552 Pose2D(Vector2<double>(-cameraOffset.x,
00553 -cameraOffset.y));
00554 return 2;
00555 }
00556 else
00557 return 1;
00558 }
00559 else
00560 return 0;
00561 }
00562
00563 bool GT2004SelfLocator::getBearing(const LandmarksPercept& landmarksPercept,int i,
00564 Vector2<double>& mark,
00565 double& dir,double& dist) const
00566 {
00567 if(i < numOfFlags)
00568 {
00569 const Flag& flag = flags[i];
00570 mark = flag.position;
00571 dir = flag.angle;
00572 dist = flag.distance;
00573 return true;
00574 }
00575 else
00576 {
00577 i -= numOfFlags;
00578 const Goal& goal = landmarksPercept.goals[i >> 1];
00579 if((i & 1) == 0 && !goal.isOnBorder(goal.x.min))
00580 {
00581 mark = goal.rightPost;
00582 dir = goal.x.min;
00583 dist = goal.distance;
00584 return true;
00585 }
00586 else if((i & 1) == 1 && !goal.isOnBorder(goal.x.max))
00587 {
00588 mark = goal.leftPost;
00589 dir = goal.x.max;
00590 dist = goal.distance;
00591 return true;
00592 }
00593 else
00594 return false;
00595 }
00596 }
00597
00598 void GT2004SelfLocator::addFlag(const Flag& flag)
00599 {
00600 if(!flag.isOnBorder(flag.x.min) && !flag.isOnBorder(flag.x.max))
00601 {
00602 int i;
00603 for(i = 0; i < numOfFlags && flags[i].type != flag.type; ++i)
00604 ;
00605 if(i < numOfFlags)
00606 --numOfFlags;
00607 if(i < FLAGS_MAX)
00608 ++i;
00609 while(--i > 0)
00610 flags[i] = flags[i - 1];
00611 flags[0] = flag;
00612 if(numOfFlags < FLAGS_MAX)
00613 ++numOfFlags;
00614 }
00615 }
00616
00617 void GT2004SelfLocator::generatePoseTemplates(const LandmarksPercept& landmarksPercept,
00618 const Pose2D& odometry)
00619 {
00620 randomFactor = 0;
00621 int i;
00622 for(i = 0; i < numOfFlags; ++i)
00623 {
00624 Flag& flag = flags[i];
00625 Vector2<double> p = (Pose2D(flag.angle)
00626 + Pose2D(Vector2<double>(flag.distance,0)) - odometry).translation;
00627 flag.angle = atan2(p.y,p.x);
00628 flag.distance = p.abs();
00629 }
00630 for(i = 0; i < landmarksPercept.numberOfFlags; ++i)
00631 addFlag(landmarksPercept.flags[i]);
00632
00633 numOfTemplates = 0;
00634 nextTemplate = 0;
00635 double dir0,
00636 dir1,
00637 dir2;
00638 double dist0,
00639 dist1;
00640 Vector2<double> mark0,
00641 mark1,
00642 mark2,
00643 cameraOffset(landmarksPercept.cameraOffset.x,
00644 landmarksPercept.cameraOffset.y);
00645 int n = numOfFlags + 2 * landmarksPercept.numberOfGoals;
00646 for(i = 0; i < n - 2; ++i)
00647 if(getBearing(landmarksPercept,i,mark0,dir0,dist0))
00648 for(int j = i + 1; j < n - 1; ++j)
00649 if(getBearing(landmarksPercept,j,mark1,dir1,dist1))
00650 {
00651 if(numOfTemplates >= SAMPLES_MAX - 4)
00652 return;
00653 numOfTemplates += poseFromBearingsAndDistance(dir0,dir1,dist1,mark0,mark1,cameraOffset,
00654 templates[numOfTemplates],templates[numOfTemplates + 1]);
00655 numOfTemplates += poseFromBearingsAndDistance(dir1,dir0,dist0,mark1,mark0,cameraOffset,
00656 templates[numOfTemplates],templates[numOfTemplates + 1]);
00657 for(int k = j + 1; k < n; ++k)
00658 if(getBearing(landmarksPercept,k,mark2,dir2,dist0))
00659 if(poseFromBearings(dir0,dir1,dir2,mark0,mark1,mark2,cameraOffset,
00660 templates[numOfTemplates]))
00661 if(++numOfTemplates == SAMPLES_MAX)
00662 return;
00663 }
00664 for(i = 0; i < numberOfTypes; ++i)
00665 {
00666 LinesPercept::LineType type = types[i];
00667 for(int j = 0; j < linesPercept.points[type].numberOfPoints; ++j)
00668 {
00669 const Vector2<int>& point = linesPercept.points[type].pointsOnField[j];
00670 int index = type;
00671 if(getPlayer().getTeamColor() == Player::blue && type >= LinesPercept::yellowGoal)
00672 index = LinesPercept::yellowGoal + LinesPercept::skyblueGoal - type;
00673 templates[numOfTemplates++] = templateTable[index - LinesPercept::yellowGoal].sample(point.abs()) + Pose2D(-atan2((double)point.y,(double)point.x));
00674 if(numOfTemplates == SAMPLES_MAX)
00675 return;
00676 }
00677 }
00678 }
00679
00680 GT2004SelfLocator::Sample GT2004SelfLocator::getTemplate()
00681 {
00682 if(nextTemplate >= numOfTemplates)
00683 {
00684 nextTemplate = 0;
00685 ++randomFactor;
00686 }
00687 while(nextTemplate < numOfTemplates)
00688 {
00689 const Pose2D& t = templates[nextTemplate++];
00690 if(field.isInside(t.translation))
00691 {
00692 return Sample(Pose2D::random(Range<double>(t.translation.x - randomFactor * 50,
00693 t.translation.x + randomFactor * 50),
00694 Range<double>(t.translation.y - randomFactor * 50,
00695 t.translation.y + randomFactor * 50),
00696 Range<double>(t.getAngle() - randomFactor * 0.1,
00697 t.getAngle() + randomFactor * 0.1)),
00698 average);
00699 }
00700 }
00701 return Sample(field.randomPose(),average);
00702 }
00703
00704
00705
00706
00707 void GT2004SelfLocator::draw(const Sample& pose) const
00708 {
00709 Drawings::Color color;
00710
00711 if (pose.probability == 2 || pose.probability == 0)
00712 color = Drawings::black;
00713 else if (pose.probability < 0.1)
00714 color = Drawings::blue;
00715 else if (pose.probability < 0.2)
00716 color = Drawings::yellow;
00717 else if (pose.probability < 0.5)
00718 color = Drawings::orange;
00719 else if (pose.probability < 0.8)
00720 color = Drawings::red;
00721 else
00722 color = Drawings::pink;
00723
00724 Pose2D p = pose + Pose2D(-100,0);
00725 NLINE("gt04-sl",
00726 pose.translation.x,
00727 pose.translation.y,
00728 p.translation.x,
00729 p.translation.y,
00730 1,
00731 Drawings::ps_solid,
00732 color);
00733 p = pose + Pose2D(-40,-40);
00734 NLINE("gt04-sl",
00735 pose.translation.x,
00736 pose.translation.y,
00737 p.translation.x,
00738 p.translation.y,
00739 1,
00740 Drawings::ps_solid,
00741 color);
00742 p = pose + Pose2D(-40,40);
00743 NLINE("gt04-sl",
00744 pose.translation.x,
00745 pose.translation.y,
00746 p.translation.x,
00747 p.translation.y,
00748 1,
00749 Drawings::ps_solid,
00750 color);
00751 }
00752
00753 void GT2004SelfLocator::draw(const Vector2<int>& point,LinesPercept::LineType type) const
00754 {
00755 static const Drawings::Color colors[] =
00756 {
00757 Drawings::red,
00758 Drawings::green,
00759 Drawings::yellow,
00760 Drawings::skyblue
00761 };
00762
00763 CameraInfo cameraInfo(getRobotConfiguration().getRobotDesign());
00764
00765 Vector2<int> p;
00766 Geometry::calculatePointInImage(
00767 point,
00768 cameraMatrix, cameraInfo,
00769 p);
00770 NCIRCLE("gt04-sl",p.x,p.y,3,1,Drawings::ps_solid,colors[type]);
00771 }
00772
00773 void GT2004SelfLocator::drawEllipse()
00774 {
00775
00776
00777 double mx,my,sxx,sxy,syy;
00778 mx = my = sxx = sxy = syy = 0;
00779 double l1, l2, ev1x, ev1y, ev2x, ev2y;
00780 l1 = l2 = ev1x = ev1y = ev2x = ev2y = 0;
00781
00782 int i ;
00783
00784 for (i = 0; i < selfLocatorSamples.getNumberOfSamples(); i++)
00785 {
00786 mx += selfLocatorSamples[i].translation.x;
00787 my += selfLocatorSamples[i].translation.y;
00788 }
00789 mx /= selfLocatorSamples.getNumberOfSamples();
00790 my /= selfLocatorSamples.getNumberOfSamples();
00791
00792
00793 for (i = 0; i < selfLocatorSamples.getNumberOfSamples(); i++)
00794 {
00795 sxx += (selfLocatorSamples[i].translation.x - mx) * (selfLocatorSamples[i].translation.x - mx);
00796 sxy += (selfLocatorSamples[i].translation.x - mx) * (selfLocatorSamples[i].translation.y - my);
00797 syy += (selfLocatorSamples[i].translation.y - my) * (selfLocatorSamples[i].translation.y - my);
00798 }
00799
00800 sxx /= selfLocatorSamples.getNumberOfSamples();
00801 sxy /= selfLocatorSamples.getNumberOfSamples();
00802 syy /= selfLocatorSamples.getNumberOfSamples();
00803
00804 l1 = (sxx + syy)/2 + sqrt((sxx + syy)/2*(sxx + syy)/2 - sxx * syy + sxy * sxy);
00805 l2 = (sxx + syy)/2 - sqrt((sxx + syy)/2*(sxx + syy)/2 - sxx * syy + sxy * sxy);
00806
00807
00808 double amount;
00809 ev1x = (syy - l1 - sxy) / (sxx - l1 - sxy);
00810 amount = sqrt(ev1x*ev1x + 1);
00811
00812 ev1x /= amount;
00813 ev1y = 1.0 / amount;
00814
00815 ev2x = (syy - l2 - sxy) / (sxx - l2 - sxy);
00816 amount = sqrt(ev2x*ev2x + 1);
00817
00818 ev2x /= amount;
00819 ev2y = 1.0 / amount;
00820
00821 double alpha = atan2(ev1y,ev1x);
00822
00823 double a = sqrt(l1*1);
00824 double b = sqrt(l2*1);
00825 double x = 0;
00826 double y = 0;
00827 int step = (int)(a/200);
00828 if (!step)
00829 {
00830 step = 1;
00831 }
00832
00833 for (int xc = 0; xc < a; xc += step)
00834 {
00835 x = xc;
00836 y = (sqrt(1-sqr(x/a))* b);
00837
00838 NDOT("gt04-sl", cos(alpha)*(x + mx) - sin(alpha)*(y + my),
00839 sin(alpha)*(x + mx) + cos(alpha)*(y + my),
00840 2, Drawings::red);
00841 NDOT("gt04-sl", cos(alpha)*(x + mx) - sin(alpha)*(-y + my),
00842 sin(alpha)*(x + mx) + cos(alpha)*(-y + my),
00843 2, Drawings::red);
00844 NDOT("gt04-sl", cos(alpha)*(-x + mx) - sin(alpha)*(y + my),
00845 sin(alpha)*(-x + mx) + cos(alpha)*(y + my),
00846 2, Drawings::red);
00847 NDOT("gt04-sl", cos(alpha)*(-x + mx) - sin(alpha)*(-y + my),
00848 sin(alpha)*(-x + mx) + cos(alpha)*(-y + my),
00849 2, Drawings::red);
00850
00851 }
00852
00853 }
00854
00855
00856 bool GT2004SelfLocator::handleMessage(InMessage& message)
00857 {
00858 switch(message.getMessageID())
00859 {
00860 case idLinesSelfLocatorParameters:
00861 GenericDebugData d;
00862 message.bin >> d;
00863 paramUp = d.data[0];
00864 paramDown = d.data[1];
00865 paramDelay = d.data[2];
00866 paramHeight = d.data[3];
00867 paramZ = d.data[4];
00868 paramY = d.data[5];
00869 return true;
00870 }
00871 return false;
00872 }