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,int pointRes> 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 / pointRes + 0.5)));
00057           point[y][x][1] = char(sgn(p.y) * int(fabs(p.y / pointRes + 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] * pointRes,point[y][x][1] * pointRes);
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] * pointRes,
00079                  y2 = point[y][x][1] * pointRes;
00080           if(sqrt(sqr(x1 - x2) + sqr(y1 - y2)) > 40)
00081           {
00082             LINE(selfLocatorField,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(selfLocatorField,x2,y2,p2.translation.x,p2.translation.y,
00089               1, Drawings::ps_solid,
00090               Drawings::gray);
00091             LINE(selfLocatorField,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, int POINT_RES> 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 #ifdef HUGE_FIELD
00184       DISTANCE_MAX = 650 /**< The number of distances. */
00185 #else
00186       DISTANCE_MAX = 500 /**< The number of distances. */
00187 #endif
00188     };
00189 
00190     char templates[TEMPLATES_MAX][3]; /**< The template poses sorted by distance. */
00191     unsigned short distance[DISTANCE_MAX + 1]; /**< Indices into the template table depending on the distance. */
00192 
00193     /**
00194     * The function is required for sorting the template poses.
00195     * It is used as compare function for qsort.
00196     * @param t1 The first element to compare.
00197     * @param t2 The second element to compare.
00198     * @return -1, 0, or 1 according to the specification required by qsort.
00199     */
00200     static int compare(const Temp* t1,const Temp* t2)
00201     {
00202       return t1->distance == t2->distance ? 0 : t1->distance < t2->distance ? -1 : 1;
00203     }
00204 
00205   public:
00206     /**
00207     * The function creates the table.
00208     * It must be called for construction.
00209     * @param field The field.
00210     * @param type The line type the table will be constructed for.
00211     */
00212     void create(const Field& field,LinesPercept::LineType type)
00213     {
00214       Temp* temp = new Temp[TEMPLATES_MAX];
00215       int i;
00216       double dist;
00217       for(i = 0; i < TEMPLATES_MAX; ++i)
00218         for(;;)
00219         {
00220           (Pose2D&) temp[i] = field.randomPose();
00221           dist = field.getDistance(temp[i],type);
00222           if(dist < 0)
00223             continue; // no line in that direction
00224           //if(type == LinesPercept::skyblueGoal || type == LinesPercept::yellowGoal)
00225           //{
00226           //  double distToBorder = field.getDistance(temp[i],LinesPercept::border);
00227           //  if(distToBorder > 0 && distToBorder < dist)
00228           //    continue; // goal line is hidden by border
00229           //}
00230           temp[i].distance = (int) dist / 10;
00231           break; // everything all right -> leave loop
00232         }
00233       qsort(temp,TEMPLATES_MAX,sizeof(Temp),(int (*)(const void *,const void*)) compare);
00234       i = 0;
00235       int j = 0;
00236       distance[j] = i;
00237       while(i < TEMPLATES_MAX && j < DISTANCE_MAX)
00238       {
00239         while(i < TEMPLATES_MAX && j < DISTANCE_MAX && temp[i].distance == j)
00240         {
00241           char* t = templates[i];
00242           t[0] = char(temp[i].translation.x / POINT_RES);
00243           t[1] = char(temp[i].translation.y / POINT_RES);
00244           t[2] = char(temp[i].getAngle() * 127 / pi);
00245           ++i;
00246         }
00247         distance[++j] = i;
00248       }
00249       while(j < DISTANCE_MAX)
00250         distance[++j] = i;
00251       delete [] temp;
00252     }
00253 
00254     /**
00255     * The function draws a pose from the templates for a certain distance.
00256     * @param realDist The distance in which a line starting from the pose should cut the closest field line.
00257     * @return A pose drawn from the table.
00258     */
00259     Pose2D sample(double realDist) const
00260     {
00261       realDist /= 10;
00262       int dist = (int) (realDist * (0.9 + 0.2 * random()));
00263       if(dist < 0)
00264         dist = 0;
00265       else if(dist >= DISTANCE_MAX)
00266         dist = DISTANCE_MAX - 1;
00267       int index = distance[dist] + int((distance[dist + 1] - distance[dist]) * random());
00268       const char* t = templates[index < TEMPLATES_MAX ? index : TEMPLATES_MAX - 1];
00269       return Pose2D(t[2] * pi / 127,Vector2<double>(t[0] * POINT_RES,t[1] * POINT_RES));
00270     }
00271 
00272     void write(Out& stream) const 
00273     {
00274       stream.write(templates,sizeof(templates));
00275       stream.write(distance,sizeof(distance));
00276     }
00277 
00278     void read(In& stream) 
00279     {
00280       stream.read(templates,sizeof(templates));
00281       stream.read(distance,sizeof(distance));
00282     }
00283 };
00284 
00285 /**
00286 * The class implements a lines-based Monte Carlo self-localization.
00287 */
00288 class LinesTables2004
00289 {
00290   public:
00291     static Field field; /**< The field. */
00292 #ifdef HUGE_FIELD
00293     typedef ObservationTable<320,240,25,25> ObsTable;
00294     typedef TemplateTable<65000, 25> TempTable;
00295 #else
00296     typedef ObservationTable<280,200,25,20> ObsTable;
00297     typedef TemplateTable<50000, 20> TempTable;
00298 #endif
00299     static ObsTable* observationTable; /**< The table maps points to closest edges. */
00300     static TempTable* templateTable; /**< The table contains candidate poses for certain distance measurements. */
00301     static int refCount; /**< A reference counter that ensures that the tables are only (de)allocated once. */
00302 
00303     /** 
00304     * Constructor.
00305     */
00306     LinesTables2004();
00307 
00308     /** 
00309     * Destructor.
00310     */
00311     ~LinesTables2004();
00312 };
00313 
00314 #endif// __LinesTables2004_h_

Generated on Mon Mar 20 21:59:56 2006 for GT2005 by doxygen 1.3.6