00001 #include <cstdlib>
00002 #include <limits.h>
00003 #include <scanmatcher/scanmatcher.h>
00004 #include <gridfastslam/gfsreader.h>
00005 #include <qpixmap.h>
00006 #include <qpainter.h>
00007 #include <qimage.h>
00008 #include <qapplication.h>
00009 #include <utils/commandline.h>
00010
00011 #define MAX_LASER_BEAMS 1024
00012 #define MAX_FILENAME 1024
00013
00014 using namespace std;
00015 using namespace GMapping;
00016 using namespace GMapping::GFSReader;
00017
00018 inline double min(double a, double b){
00019 return (a<b)?a:b;
00020 }
00021
00022 inline double max(double a, double b){
00023 return (a>b)?a:b;
00024 }
00025
00026 void computeBoundingBox(double& xmin, double& ymin, double& xmax, double& ymax, const LaserRecord& laser, const OrientedPoint& pose, double maxrange){
00027 double theta=-M_PI/2+pose.theta;
00028 double theta_step=(laser.readings.size()==180||laser.readings.size()==181)?M_PI/180:M_PI/360;
00029 for (std::vector<double>::const_iterator it=laser.readings.begin(); it!=laser.readings.end(); it++){
00030 if (*it<maxrange){
00031 xmin=min(xmin,pose.x+*it*cos(theta));
00032 ymin=min(ymin,pose.y+*it*sin(theta));
00033 xmax=max(xmax,pose.x+*it*cos(theta));
00034 ymax=max(ymax,pose.y+*it*sin(theta));
00035 }
00036 theta+=theta_step;
00037 }
00038 }
00039
00040 void computeBoundingBox(double& xmin, double& ymin, double& xmax, double& ymax, const RecordList& rl, double maxrange){
00041 xmin = ymin = MAXDOUBLE;
00042 xmax = ymax =-MAXDOUBLE;
00043 const LaserRecord* lastLaser=0;
00044 for (RecordList::const_iterator it=rl.begin(); it!=rl.end(); it++){
00045 const LaserRecord* lr= dynamic_cast<const LaserRecord*>(*it);
00046 if (lr){
00047 lastLaser=lr;
00048 continue;
00049 }
00050 const ScanMatchRecord* smr= dynamic_cast<const ScanMatchRecord*>(*it);
00051 if (smr && lastLaser){
00052 for (std::vector<OrientedPoint>::const_iterator pit=smr->poses.begin(); pit!=smr->poses.end(); pit++){
00053 computeBoundingBox(xmin, ymin, xmax, ymax, *lastLaser, *pit, maxrange);
00054 }
00055 }
00056 }
00057 }
00058 int main(int argc, char** argv){
00059 QApplication app(argc, argv);
00060 double maxrange=50;
00061 double delta=0.1;
00062 int scanSkip=5;
00063 const char* filename=0;
00064 const char* format="PNG";
00065 CMD_PARSE_BEGIN(1, argc)
00066 parseDouble("-maxrange", maxrange);
00067 parseDouble("-delta", delta);
00068 parseInt("-skip", scanSkip);
00069 parseString("-filename",filename);
00070 parseString("-format",format);
00071 CMD_PARSE_END
00072
00073 double maxUrange=maxrange;
00074 if (! filename){
00075 cout << " supply a gfs file, please" << endl;
00076 cout << " usage gfs2img [options] -filename <gfs_file>" << endl;
00077 cout << " [options]:" << endl;
00078 cout << " -maxrange <range>" << endl;
00079 cout << " -delta <map cell size>" << endl;
00080 cout << " -skip <frames to skip among images>" << endl;
00081 cout << " -format <image format in capital letters>" << endl;
00082 return -1;
00083 }
00084 ifstream is(filename);
00085 if (!is){
00086 cout << " supply an EXISTING gfs file, please" << endl;
00087 return -1;
00088 }
00089 RecordList rl;
00090 rl.read(is);
00091
00092 int particles=0;
00093 int beams=0;
00094 for (RecordList::const_iterator it=rl.begin(); it!=rl.end(); it++){
00095 const OdometryRecord* odometry=dynamic_cast<const OdometryRecord*>(*it);
00096 if (odometry){
00097 particles=odometry->dim;
00098 }
00099 const LaserRecord* s=dynamic_cast<const LaserRecord*>(*it);
00100 if (s){
00101 beams=s->readings.size();
00102 }
00103 if (particles && beams)
00104 break;
00105 }
00106 cout << "Particles from gfs=" << particles << endl;
00107 if (! particles){
00108 cout << "no particles found, terminating" << endl;
00109 return -1;
00110 }
00111 cout << "Laser beams from gfs=" << beams << endl;
00112 if (! beams){
00113 cout << "0 beams found, terminating" << endl;
00114 return -1;
00115 }
00116
00117
00118 double laserBeamStep=0;
00119 if (beams==180||beams==181){
00120 laserBeamStep=M_PI/180;
00121 } else if (beams==360||beams==361){
00122 laserBeamStep=M_PI/360;
00123 }
00124 cout << "Laser beam step" << laserBeamStep << endl;
00125 if (laserBeamStep==0){
00126 cout << "Invalid Beam Step, terminating" << endl;
00127 return -1;
00128 }
00129 double laserAngles[MAX_LASER_BEAMS];
00130 double theta=-M_PI/2;
00131 for (int i=0; i<beams; i++){
00132 laserAngles[i]=theta;
00133 theta+=laserBeamStep;
00134 }
00135
00136 ScanMatcher matcher;
00137 matcher.setLaserParameters(beams, laserAngles, OrientedPoint(0,0,0));
00138 matcher.setlaserMaxRange(maxrange);
00139 matcher.setusableRange(maxUrange);
00140 matcher.setgenerateMap(true);
00141
00142 double xmin, ymin, xmax, ymax;
00143 cout << "computing bounding box" << endl;
00144 computeBoundingBox(xmin, ymin, xmax, ymax, rl, maxrange);
00145 cout << "DONE" << endl << "BBOX= " << xmin << " " << ymin << " " << xmax << " " << ymax << endl;
00146
00147 Point center;
00148 center.x=(xmin+xmax)/2.;
00149 center.y=(ymin+ymax)/2.;
00150
00151 cout << "computing paths" << endl;
00152 unsigned int frame=0;
00153 int scanCount=0;
00154
00155 for (RecordList::const_iterator it=rl.begin(); it!=rl.end(); it++){
00156 const ScanMatchRecord* s=dynamic_cast<const ScanMatchRecord*>(*it);
00157 if (!s)
00158 continue;
00159 scanCount++;
00160 if (scanCount%scanSkip)
00161 continue;
00162 cout << "Frame " << frame << " ";
00163 std::vector<RecordList> paths(particles);
00164 int bestIdx=0;
00165 double bestWeight=-MAXDOUBLE;
00166 for (int p=0; p<particles; p++){
00167 paths[p]=rl.computePath(p,it);
00168 double w=rl.getLogWeight(p,it);
00169 if (w>bestWeight){
00170 bestWeight=w;
00171 bestIdx=p;
00172 }
00173 }
00174 cout << "bestIdx=" << bestIdx << " bestWeight=" << bestWeight << endl;
00175
00176 cout << "computing best map" << endl;
00177 ScanMatcherMap smap(center, xmin, ymin, xmax, ymax, delta);
00178 int count=0;
00179 for (RecordList::const_iterator mt=paths[bestIdx].begin(); mt!=paths[bestIdx].end(); mt++){
00180 const LaserRecord* s=dynamic_cast<const LaserRecord*>(*mt);
00181 if (s){
00182 double rawreadings[MAX_LASER_BEAMS];
00183 for (uint i=0; i<s->readings.size(); i++)
00184 rawreadings[i]=s->readings[i];
00185 matcher.invalidateActiveArea();
00186 matcher.computeActiveArea(smap, s->pose, rawreadings);
00187
00188 matcher.registerScan(smap, s->pose, rawreadings);
00189 count++;
00190 }
00191 }
00192 cout << "DONE " << count <<endl;
00193
00194 QPixmap pixmap(smap.getMapSizeX(), smap.getMapSizeY());
00195 pixmap.fill(QColor(200, 200, 255));
00196 QPainter painter(&pixmap);
00197 for (int x=0; x<smap.getMapSizeX(); x++)
00198 for (int y=0; y<smap.getMapSizeY(); y++){
00199 double v=smap.cell(x,y);
00200 if (v>=0){
00201 int grayValue=255-(int)(255.*v);
00202 painter.setPen(QColor(grayValue, grayValue, grayValue));
00203 painter.drawPoint(x,smap.getMapSizeY()-y-1);
00204 }
00205 }
00206
00207
00208
00209
00210
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
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246 cout << " DONE" << endl;
00247 cout << "writing image" << endl;
00248 QImage img=pixmap.convertToImage();
00249 char ofilename[MAX_FILENAME];
00250 sprintf(ofilename,"%s-%.4d.%s",filename, frame, format);
00251 cout << ofilename << endl;
00252 img.save(QString(ofilename), format,0);
00253 frame++;
00254
00255 }
00256 cout << "For Cyrill: \"The Evil is Outside\"" << endl;
00257 }
00258