Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

Modules/SelfLocator/GT2004SelfLocator.cpp

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

Generated on Thu Sep 23 19:57:31 2004 for GT2004 by doxygen 1.3.6