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

Modules/SelfLocator/LinesTables2004.h

Go to the documentation of this file.
00001 /**
00002 * @file Modules/SelfLocator/LinesTables2004.h
00003 * 
00004 * This file contains a class that represents the tables used for localization based on field lines.
00005 *
00006 * @author <A href=mailto:roefer@tzi.de>Thomas Röfer</A>
00007 */
00008 
00009 #ifndef __LinesTables2004_h_
00010 #define __LinesTables2004_h_
00011 
00012 #include "Tools/Debugging/DebugDrawings.h"
00013 #include "Tools/Streams/InOut.h"
00014 #include "Tools/Field.h"
00015 #include "Platform/GTAssert.h"
00016 
00017 /**
00018 * @class ObservationTableBase
00019 * The class is a helper to support streaming of template class ObservationTable.
00020 */
00021 class ObservationTableBase
00022 {
00023   public:
00024     /**
00025     * The function writes the contents of an object to a stream.
00026     * @param stream The stream the data is written to.
00027     */
00028     virtual void write(Out& stream) const = 0;
00029   
00030     /**
00031     * The function reads the contents of an object from a stream.
00032     * @param stream The stream the data is read from.
00033     */
00034     virtual void read(In& stream) = 0;
00035 };
00036 
00037 /**
00038 * @class ObservationTable
00039 * The class realizes a table of closest distances to lines of a certain type.
00040 */
00041 template<int xSize,int ySize,int cellSize> class ObservationTable : public ObservationTableBase
00042 {
00043   private:
00044     char point[ySize][xSize][2];
00045 
00046   public:
00047     void create(const Field& field,LinesPercept::LineType type)
00048     {
00049       for(int y = 0; y < ySize; ++y)
00050         for(int x = 0; x < xSize; ++x)
00051         {
00052           Vector2<double> p = field.getClosestPoint(
00053             Vector2<double>((x + 0.5 - xSize / 2) * cellSize,
00054             (y + 0.5 - ySize / 2) * cellSize),
00055             type);
00056           point[y][x][0] = char(sgn(p.x) * int(fabs(p.x / 20 + 0.5)));
00057           point[y][x][1] = char(sgn(p.y) * int(fabs(p.y / 20 + 0.5)));
00058         }
00059     }
00060   
00061     Vector2<double> getClosestPoint(const Vector2<double>& v) const
00062     {
00063       int x = int(v.x / cellSize + xSize / 2),
00064           y = int(v.y / cellSize + ySize / 2);
00065       if(x < 0 || x >= xSize || y < 0 || y >= ySize)
00066         return Vector2<double>(1e6,1e6);
00067       else
00068         return Vector2<double>(point[y][x][0] * 20,point[y][x][1] * 20);
00069     }
00070   
00071     void draw()
00072     {
00073       for(int y = 0; y < ySize; y += 5)
00074         for(int x = 0; x < xSize; x += 5)
00075         {
00076           double x1 = (x + 0.5 - xSize / 2) * cellSize,
00077                  y1 = (y + 0.5 - ySize / 2) * cellSize,
00078                  x2 = point[y][x][0] * 20,
00079                  y2 = point[y][x][1] * 20;
00080           if(sqrt(sqr(x1 - x2) + sqr(y1 - y2)) > 40)
00081           {
00082             LINE(selfLocatorMonteCarlo,x1,y1,x2,y2,
00083               0, Drawings::ps_solid,
00084               Drawings::gray);
00085             Pose2D p(atan2(y2-y1,x2-x1),Vector2<double>(x2,y2)),
00086                    p2 = p + Pose2D(Vector2<double>(-50,-50)),
00087                    p3 = p + Pose2D(Vector2<double>(-50,50));
00088             LINE(selfLocatorMonteCarlo,x2,y2,p2.translation.x,p2.translation.y,
00089               1, Drawings::ps_solid,
00090               Drawings::gray);
00091             LINE(selfLocatorMonteCarlo,x2,y2,p3.translation.x,p3.translation.y,
00092               1, Drawings::ps_solid,
00093               Drawings::gray);
00094           }
00095         }
00096     }
00097 
00098     void write(Out& stream) const 
00099     {
00100       stream.write(point,sizeof(point));
00101     }
00102 
00103     void read(In& stream) 
00104     {
00105       stream.read(point,sizeof(point));
00106     }
00107   };
00108 
00109 inline Out& operator<<(Out& stream,const ObservationTableBase& table)
00110 {
00111   table.write(stream);
00112   return stream;
00113 }
00114 
00115 inline In& operator>>(In& stream,ObservationTableBase& table)
00116 {
00117   table.read(stream);
00118   return stream;
00119 }
00120 
00121 /**
00122 * @class TemplateTableBase
00123 * The class is a helper to support streaming of template class TemplateTable.
00124 */
00125 class TemplateTableBase
00126 {
00127   public:
00128     /**
00129     * The function writes the contents of an object to a stream.
00130     * @param stream The stream the data is written to.
00131     */
00132     virtual void write(Out& stream) const = 0;
00133   
00134     /**
00135     * The function reads the contents of an object from a stream.
00136     * @param stream The stream the data is read from.
00137     */
00138     virtual void read(In& stream) = 0;
00139 };
00140 
00141 /**
00142 * The operator writes the template table into a stream.
00143 * @param stream The stream the table is written into.
00144 * @param table The table to be written.
00145 * @return The stream.
00146 */
00147 inline Out& operator<<(Out& stream,const TemplateTableBase& table)
00148 {
00149   table.write(stream);
00150   return stream;
00151 }
00152 
00153 /**
00154 * The operator reads the template table from a stream.
00155 * @param stream The stream the table is read from.
00156 * @param table The table to be read.
00157 * @return The stream.
00158 */
00159 inline In& operator>>(In& stream,TemplateTableBase& table)
00160 {
00161   table.read(stream);
00162   return stream;
00163 }
00164 
00165 
00166 /**
00167 * The class realizes a table of template poses.
00168 */
00169 template<int TEMPLATES_MAX> class TemplateTable : public TemplateTableBase
00170 {
00171   private:
00172     /**
00173     * The class is required for sorting the template table by the distances to lines.
00174     */
00175     class Temp : public Pose2D
00176     {
00177       public:
00178         int distance; /**< The distance to the closest line in direction of the pose. */
00179     };
00180 
00181     enum 
00182     {
00183       DISTANCE_MAX = 500 /**< The number of distances. */
00184     };
00185 
00186     char templates[TEMPLATES_MAX][3]; /**< The template poses sorted by distance. */
00187     unsigned short distance[DISTANCE_MAX + 1]; /**< Indices into the template table depending on the distance. */
00188 
00189     /**
00190     * The function is required for sorting the template poses.
00191     * It is used as compare function for qsort.
00192     * @param t1 The first element to compare.
00193     * @param t2 The second element to compare.
00194     * @return -1, 0, or 1 according to the specification required by qsort.
00195     */
00196     static int compare(const Temp* t1,const Temp* t2)
00197     {
00198       return t1->distance == t2->distance ? 0 : t1->distance < t2->distance ? -1 : 1;
00199     }
00200 
00201   public:
00202     /**
00203     * The function creates the table.
00204     * It must be called for construction.
00205     * @param field The field.
00206     * @param type The line type the table will be constructed for.
00207     */
00208     void create(const Field& field,LinesPercept::LineType type)
00209     {
00210       Temp* temp = new Temp[TEMPLATES_MAX];
00211       int i;
00212       double dist;
00213       for(i = 0; i < TEMPLATES_MAX; ++i)
00214         for(;;)
00215         {
00216           (Pose2D&) temp[i] = field.randomPose();
00217           dist = field.getDistance(temp[i],type);
00218           if(dist < 0)
00219             continue; // no line in that direction
00220           if(type == LinesPercept::skyblueGoal || type == LinesPercept::yellowGoal)
00221           {
00222             double distToBorder = field.getDistance(temp[i],LinesPercept::border);
00223             if(distToBorder > 0 && distToBorder < dist)
00224               continue; // goal line is hidden by border
00225           }
00226           temp[i].distance = (int) dist / 10;
00227           break; // everything all right -> leave loop
00228         }
00229       qsort(temp,TEMPLATES_MAX,sizeof(Temp),(int (*)(const void *,const void*)) compare);
00230       i = 0;
00231       int j = 0;
00232       distance[j] = i;
00233       while(i < TEMPLATES_MAX && j < DISTANCE_MAX)
00234       {
00235         while(i < TEMPLATES_MAX && j < DISTANCE_MAX && temp[i].distance == j)
00236         {
00237           char* t = templates[i];
00238           t[0] = char(temp[i].translation.x / 20);
00239           t[1] = char(temp[i].translation.y / 20);
00240           t[2] = char(temp[i].getAngle() * 127 / pi);
00241           ++i;
00242         }
00243         distance[++j] = i;
00244       }
00245       while(j < DISTANCE_MAX)
00246         distance[++j] = i;
00247       delete [] temp;
00248     }
00249 
00250     /**
00251     * The function draws a pose from the templates for a certain distance.
00252     * @param realDist The distance in which a line starting from the pose 
00253     *             should cut the closest field line.
00254     * @return A pose drawn from the table.
00255     */
00256     Pose2D sample(double realDist) const
00257     {
00258       realDist /= 10;
00259       int dist = (int) (realDist * (0.9 + 0.2 * random()));
00260       if(dist < 0)
00261         dist = 0;
00262       else if(dist >= DISTANCE_MAX)
00263         dist = DISTANCE_MAX - 1;
00264       int index = distance[dist] + int((distance[dist + 1] - distance[dist]) * random());
00265       const char* t = templates[index < TEMPLATES_MAX ? index : TEMPLATES_MAX - 1];
00266       ASSERT(t[1] < 68 && t[1] > -68);
00267       return Pose2D(t[2] * pi / 127,Vector2<double>(t[0] * 20,t[1] * 20));
00268     }
00269 
00270     void write(Out& stream) const 
00271     {
00272       stream.write(templates,sizeof(templates));
00273       stream.write(distance,sizeof(distance));
00274     }
00275 
00276     void read(In& stream) 
00277     {
00278       stream.read(templates,sizeof(templates));
00279       stream.read(distance,sizeof(distance));
00280     }
00281 };
00282 
00283 /**
00284 * The class implements a lines-based Monte Carlo self-localization.
00285 */
00286 class LinesTables2004
00287 {
00288   protected:
00289     static Field field; /**< The field. */
00290     static ObservationTable<280,200,25>* observationTable; /**< The table maps points to closest edges. */
00291     static TemplateTable<50000>* templateTable; /**< The table contains candidate poses for certain distance measurements. */
00292     static int refCount; /**< A reference counter that ensures that the tables are only (de)allocated once. */
00293 
00294   public:
00295     /** 
00296     * Constructor.
00297     */
00298     LinesTables2004();
00299 
00300     /** 
00301     * Destructor.
00302     */
00303     ~LinesTables2004();
00304 };
00305 
00306 #endif// __LinesTables2004_h_
00307 
00308 /*
00309 * Change log :
00310 * 
00311 * $Log: LinesTables2004.h,v $
00312 * Revision 1.5  2004/09/09 11:37:39  wachter
00313 * - Fixed some more doxygen-errors
00314 *
00315 * Revision 1.4  2004/09/09 10:15:58  spranger
00316 * fixed doxygen-errors
00317 *
00318 * Revision 1.3  2004/07/16 07:19:32  roefer
00319 * LinesTables removed (it was replaced by LinesTables2004)
00320 *
00321 * Revision 1.2  2004/06/24 18:26:38  roefer
00322 * Lines table redesign, should not influence the performance of GT2003SL
00323 *
00324 * Revision 1.1.1.1  2004/05/22 17:20:46  cvsadm
00325 * created new repository GT2004_WM
00326 *
00327 * Revision 1.2  2004/03/08 01:09:34  roefer
00328 * Use of LinesTables2004 restructured
00329 *
00330 * Revision 1.1  2003/10/06 14:10:14  cvsadm
00331 * Created GT2004 (M.J.)
00332 *
00333 * Revision 1.1.1.1  2003/07/02 09:40:24  cvsadm
00334 * created new repository for the competitions in Padova from the 
00335 * tamara CVS (Tuesday 2:00 pm)
00336 *
00337 * removed unused solutions
00338 *
00339 * Revision 1.1  2003/05/22 07:53:05  roefer
00340 * GT2003SelfLocator added
00341 *
00342 */

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