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

ArMap.cpp

00001 /*
00002 ActivMedia Robotics Interface for Applications (ARIA)
00003 Copyright (C) 2004,2005 ActivMedia Robotics, LLC
00004 
00005 
00006      This program is free software; you can redistribute it and/or modify
00007      it under the terms of the GNU General Public License as published by
00008      the Free Software Foundation; either version 2 of the License, or
00009      (at your option) any later version.
00010 
00011      This program is distributed in the hope that it will be useful,
00012      but WITHOUT ANY WARRANTY; without even the implied warranty of
00013      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014      GNU General Public License for more details.
00015 
00016      You should have received a copy of the GNU General Public License
00017      along with this program; if not, write to the Free Software
00018      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 
00020 If you wish to redistribute ARIA under different terms, contact 
00021 ActivMedia Robotics for information about a commercial version of ARIA at 
00022 robots@activmedia.com or 
00023 ActivMedia Robotics, 19 Columbia Drive, Amherst, NH 03031; 800-639-9481
00024 
00025 */
00026 
00027 #include "ArExport.h"
00028 #include "ariaOSDef.h"
00029 #include "ariaInternal.h"
00030 #include "ArMap.h"
00031 #include "ArFileParser.h"
00032 #include "ArArgumentBuilder.h"
00033 #include "ArLog.h"
00034 #include <ctype.h>
00035 
00036 
00037 const char *ArMap::ourInfoNames[INFO_COUNT] = 
00038 {
00039         "TaskInfo:",
00040         "RouteInfo:"
00041 };
00042 
00049 ArMap::ArMap(const char *baseDirectory, bool addToGlobalConfig,
00050                       const char *configSection, const char *configParam,
00051                       const char *configDesc, bool ignoreEmptyFileName) :
00052   myNumInfos(INFO_COUNT), // Consider adding this to the ctor so subclasses could increase...
00053   my2DMapCB(this, &ArMap::handle2DMap),
00054   myMinPosCB(this, &ArMap::handleMinPos),
00055   myMaxPosCB(this, &ArMap::handleMaxPos),
00056   myNumPointsCB(this, &ArMap::handleNumPoints),
00057   myLineMinPosCB(this, &ArMap::handleLineMinPos),
00058   myLineMaxPosCB(this, &ArMap::handleLineMaxPos),
00059   myNumLinesCB(this, &ArMap::handleNumLines),
00060   myResolutionCB(this, &ArMap::handleResolution),
00061   myMapObjectCB(this, &ArMap::handleMapObject),
00062   myMapInfoCB(this, &ArMap::handleMapInfo),
00063   myInfoCBArray(),
00067   myDataCB(this, &ArMap::handleData),
00068   myLinesCB(this, &ArMap::handleLines),
00069   myPointCB(this, &ArMap::handlePoint),
00070   myLineCB(this, &ArMap::handleLine),
00071   myProcessFileCB(this, &ArMap::processFile)
00072 {
00073   // Allocate the arrays in which to store data for the Info lines
00074   myLoadingInfoArray = new std::list<ArArgumentBuilder *>[myNumInfos];
00075   myInfoArray = new std::list<ArArgumentBuilder *> [myNumInfos];
00076   myInfoChangedArray = new ArTime[myNumInfos];
00077   myMapChangedInfoArray = new ArTime[myNumInfos];
00078   myInfoCBArray = new ArRetFunctor2C<bool, ArMap, ArArgumentBuilder *, int> *[myNumInfos];
00079   myResolution = -1;
00080 
00081   // Create the callbacks for the Info lines
00082   for (int i = 0; i < myNumInfos; i++) {
00083         myInfoCBArray[i] = new ArRetFunctor2C<bool, ArMap, ArArgumentBuilder *, int>
00084                                                            (this,
00085                                                             &ArMap::handleInfo,
00086                                                                 NULL, i);
00087   }
00088 
00089   myProcessFileCB.setName("ArMap");
00090   myMapChangedLogLevel = ArLog::Verbose;
00091   myConfigParam = configParam;
00092   myIgnoreEmptyFileName = ignoreEmptyFileName;
00093   if (addToGlobalConfig)
00094   {
00095     myConfigMapName[0] = '\0';
00096     myConfigProcessedBefore = false;
00097     Aria::getConfig()->addParam(ArConfigArg(configParam, myConfigMapName, 
00098                                             configDesc,
00099                                             sizeof(myConfigMapName)), 
00100                                 configSection, 
00101                                 ArPriority::IMPORTANT);
00102     Aria::getConfig()->addProcessFileWithErrorCB(&myProcessFileCB, 100);
00103   }
00104   myLoadingParser = NULL;
00105   setBaseDirectory(baseDirectory);
00106   reset();
00107 
00108 }
00109 
00110 ArMap::~ArMap()
00111 {
00112   /*
00113   delete [] myLoadingInfoArray;
00114   delete [] myInfoArray;
00115   delete [] myInfoChangedArray;
00116   delete [] myMapChangedInfoArray;
00117   for (int i = 0; i < myNumInfos; i++) {
00118     delete myInfoCBArray[i];
00119   }
00120   delete [] myInfoCBArray;
00121   */
00122 
00123 }
00124 
00125 bool ArMap::processFile(char *errorBuffer, size_t errorBufferLen)
00126 {
00127   struct stat mapFileStat;
00128   stat(myConfigMapName, &mapFileStat);
00129   // if we need to read it then read it
00130   if (myIgnoreEmptyFileName && myConfigMapName[0] == '\0')
00131   {
00132     ArLog::log(ArLog::Normal, "Using an empty map since empty map file name");
00133     lock();
00134     reset();
00135     myFileName = "";
00136     setMapObjects(NULL);
00137     setPoints(NULL);
00138     setLines(NULL);
00139     setMapInfo(NULL);
00140     // Clear all of the Info information
00141         for (int i = 0; i < myNumInfos; i++) {
00142                 setInfo(i, NULL);
00143         }
00144 
00145     myResolution = -1;
00146     mapChanged();
00147     unlock();
00148     return true;
00149   }
00150   if (!myConfigProcessedBefore || 
00151       ArUtil::strcmp(myConfigMapName, myFileName) != 0 ||
00152       mapFileStat.st_mtime != myReadFileStat.st_mtime)
00153   {
00154     myConfigProcessedBefore = true; 
00155     return readFile(myConfigMapName, errorBuffer, errorBufferLen);
00156   }
00157   // otherwise we're good
00158   return true;
00159 }
00160 
00161 const char *ArMap::getBaseDirectory(void) const
00162 {
00163   return myBaseDirectory.c_str();
00164 }
00165 
00166 const char *ArMap::getFileName(void) const 
00167 {
00168   return myFileName.c_str();
00169 }
00170 
00171 void ArMap::setBaseDirectory(const char *baseDirectory)
00172 {
00173   if (baseDirectory != NULL && strlen(baseDirectory) > 0)
00174     myBaseDirectory = baseDirectory;
00175   else
00176     myBaseDirectory = "";  
00177   if (myLoadingParser != NULL)
00178     myLoadingParser->setBaseDirectory(myBaseDirectory.c_str());
00179 }
00180 
00181 std::list<ArArgumentBuilder *> *ArMap::getInfo(int infoType) 
00182 { 
00183         if ((infoType >= 0) && (infoType < myNumInfos) && (myInfoArray != NULL)) {
00184                 return &myInfoArray[infoType]; 
00185         }
00186         else {
00187                 return NULL;
00188         }
00189 }
00190 
00196 void ArMap::addMapChangedCB(ArFunctor *functor, ArListPos::Pos position)
00197 {
00198   if (position == ArListPos::FIRST)
00199     myMapChangedCBList.push_front(functor);
00200   else if (position == ArListPos::LAST)
00201     myMapChangedCBList.push_back(functor);
00202   else
00203     ArLog::log(ArLog::Terse, 
00204                "ArMap::addMapChangedCB: Invalid position.");
00205 }
00206 
00207 void ArMap::remMapChangedCB(ArFunctor *functor)
00208 {
00209   myMapChangedCBList.remove(functor);
00210 }
00211 
00212 bool ArMap::reset(void)
00213 {
00214 
00215   // clear out the reading in copy
00216 
00217   // get rid of the old parser (cleaner than trying to clear it up)
00218   if (myLoadingParser != NULL)
00219     delete myLoadingParser;
00220   myLoadingParser = new ArFileParser;
00221   myLoadingParser->setBaseDirectory(myBaseDirectory.c_str());
00222   myLoadingGotMaxPos = false;
00223   myLoadingGotMinPos = false;
00224   myLoadingGot2DMap = false;
00225   myLoadingNumPoints = -1;
00226   myLoadingResolution = -1;
00227   myLoadingPointsRead = 0;
00228   myLoadingLinesRead = 0;
00229   myLoadingMax.setX(INT_MIN);
00230   myLoadingMax.setY(INT_MIN);
00231   myLoadingMin.setX(INT_MAX);
00232   myLoadingMin.setY(INT_MAX);
00233   ArUtil::deleteSet(myLoadingMapObjects.begin(), myLoadingMapObjects.end());
00234   myLoadingMapObjects.clear();
00235   myLoadingPoints.clear();
00236   myLoadingLines.clear();
00237   ArUtil::deleteSet(myLoadingMapInfo.begin(), myLoadingMapInfo.end());
00238   myLoadingMapInfo.clear();
00239 
00240   for (int i = 0; i < myNumInfos; i++) {
00241           
00242     ArUtil::deleteSet(myLoadingInfoArray[i].begin(), myLoadingInfoArray[i].end());
00243     myLoadingInfoArray[i].clear();
00244   }
00245 /***
00246   ArUtil::deleteSet(myLoadingRouteInfo.begin(), myLoadingRouteInfo.end());
00247   myLoadingRouteInfo.clear();
00248 ***/
00249 
00250   // ??
00251   myLoadingDataStarted = false;
00252   myLoadingLinesAndDataStarted = false;
00253 
00254   if (!myLoadingParser->addHandler("2D-Map", &my2DMapCB))
00255   {
00256     ArLog::log(ArLog::Terse, "ArMap::reset: could not add 2D-Map");
00257     return false;
00258   }
00259 
00260   return true;
00261 }
00262 
00263 bool ArMap::handle2DMap(ArArgumentBuilder *arg)
00264 {
00265   ArLog::log(ArLog::Verbose, "ArMap: got 2D-Map");
00266   // make sure we can add all our handlers
00267   if (!myLoadingParser->addHandler("MinPos:", &myMinPosCB) ||
00268       !myLoadingParser->addHandler("MaxPos:", &myMaxPosCB) ||
00269       !myLoadingParser->addHandler("NumPoints:", &myNumPointsCB) ||
00270       !myLoadingParser->addHandler("LineMinPos:", &myMinPosCB) ||
00271       !myLoadingParser->addHandler("LineMaxPos:", &myMaxPosCB) ||
00272       !myLoadingParser->addHandler("NumLines:", &myNumPointsCB) ||
00273       !myLoadingParser->addHandler("Resolution:", &myResolutionCB) ||
00274       !myLoadingParser->addHandler("Cairn:", &myMapObjectCB) ||
00275       !myLoadingParser->addHandler("MapInfo:", &myMapInfoCB) ||
00276 
00277       // !myLoadingParser->addHandler("RouteInfo:", &myRouteInfoCB) ||
00278       !myLoadingParser->addHandler("LINES", &myLinesCB) ||
00279       !myLoadingParser->addHandler("DATA", &myDataCB))      
00280   {
00281     ArLog::log(ArLog::Terse, "ArMap::handle2DMap: could not add handlers");
00282     return false;
00283   }  
00284 
00285   for (int i = 0; i < myNumInfos; i++) {
00286         if (!myLoadingParser->addHandler(getInfoName(i), 
00287                                                                          myInfoCBArray[i])) {
00288           ArLog::log(ArLog::Terse, "ArMap::handle2DMap: could not add info handlers");
00289           return false;
00290         }
00291   }
00292 
00293   // we added 'em all, remove the 2D-Map handler and return
00294   myLoadingParser->remHandler("2D-Map");
00295   myLoadingGot2DMap = true;
00296   return true;
00297   
00298 }
00299 
00300 bool ArMap::handleMinPos(ArArgumentBuilder *arg)
00301 {
00302   if (arg->getArgc() != 2 || !arg->isArgInt(0) || !arg->isArgInt(1))
00303   {
00304     ArLog::log(ArLog::Terse, 
00305                "ArMap: 'MinPos:' bad arguments, should be two integers x y");
00306     return false;
00307   }
00308   myLoadingMinFromFile.setPose(arg->getArgInt(0), arg->getArgInt(1));
00309   myLoadingGotMinPos = true;
00310   return true;
00311 }
00312 
00313 bool ArMap::handleMaxPos(ArArgumentBuilder *arg)
00314 {
00315   if (arg->getArgc() != 2 || !arg->isArgInt(0) || !arg->isArgInt(1))
00316   {
00317     ArLog::log(ArLog::Terse, 
00318                "ArMap: 'MaxPos:' bad arguments, should be two integers x y");
00319     return false;
00320   }
00321   myLoadingMaxFromFile.setPose(arg->getArgInt(0), arg->getArgInt(1));
00322   myLoadingGotMaxPos = true;
00323   return true;
00324 }
00325 
00326 bool ArMap::handleNumPoints(ArArgumentBuilder *arg)
00327 {
00328   if (arg->getArgc() != 1 || !arg->isArgInt(0))
00329   {
00330     ArLog::log(ArLog::Terse, 
00331                "ArMap: 'NumPoints:' bad argument, should be one integer (number of data points)");
00332     return false;
00333   }
00334   myLoadingNumPoints = arg->getArgInt(0);
00335 
00336   if (myLoadingNumPoints >= 0) {
00337           myLoadingPoints.reserve(myLoadingNumPoints);
00338   }
00339 
00340   return true;
00341 }
00342 
00343 bool ArMap::handleLineMinPos(ArArgumentBuilder *arg)
00344 {
00345   if (arg->getArgc() != 2 || !arg->isArgInt(0) || !arg->isArgInt(1))
00346   {
00347     ArLog::log(ArLog::Terse, 
00348        "ArMap: 'LineMinPos:' bad arguments, should be two integers x y");
00349     return false;
00350   }
00351   myLoadingLineMinFromFile.setPose(arg->getArgInt(0), arg->getArgInt(1));
00352   myLoadingGotLineMinPos = true;
00353   return true;
00354 }
00355 
00356 bool ArMap::handleLineMaxPos(ArArgumentBuilder *arg)
00357 {
00358   if (arg->getArgc() != 2 || !arg->isArgInt(0) || !arg->isArgInt(1))
00359   {
00360     ArLog::log(ArLog::Terse, 
00361        "ArMap: 'LineMaxPos:' bad arguments, should be two integers x y");
00362     return false;
00363   }
00364   myLoadingLineMaxFromFile.setPose(arg->getArgInt(0), arg->getArgInt(1));
00365   myLoadingGotLineMaxPos = true;
00366   return true;
00367 }
00368 
00369 bool ArMap::handleNumLines(ArArgumentBuilder *arg)
00370 {
00371   if (arg->getArgc() != 1 || !arg->isArgInt(0))
00372   {
00373     ArLog::log(ArLog::Terse, 
00374                "ArMap: 'NumPoints:' bad argument, should be one integer (number of data points)");
00375     return false;
00376   }
00377   myLoadingNumLines = arg->getArgInt(0);
00378 
00379   if (myLoadingNumLines >= 0) {
00380           myLoadingLines.reserve(myLoadingNumPoints);
00381   }
00382 
00383   return true;
00384 }
00385 
00386 bool ArMap::handleResolution(ArArgumentBuilder *arg)
00387 {
00388   if (arg->getArgc() != 1 || !arg->isArgInt(0))
00389   {
00390     ArLog::log(ArLog::Terse, 
00391                "ArMap: 'Resolution:' bad argument, should be one integer (resolution in mm)");
00392     return false;
00393   }
00394   myLoadingResolution = arg->getArgInt(0);
00395   return true;
00396 }
00397 
00398 bool ArMap::handleMapObject(ArArgumentBuilder *arg)
00399 {
00400   ArMapObject *object;
00401   ArPose pose;
00402   bool hasFromTo = false;
00403   ArPose fromPose;
00404   ArPose toPose;
00405 
00406   if (arg->getArgc() < 7 || !arg->isArgDouble(1) || !arg->isArgDouble(2) ||
00407       !arg->isArgDouble(3))
00408   {
00409     ArLog::log(ArLog::Terse, 
00410                "ArMap: 'Cairn:' bad format '%s'", arg->getFullString());
00411     return false;
00412   }
00413   // this next block strips out the end quotes of the name
00414   /*
00415   char *nameBuffer;
00416   const char *namePtr;
00417   size_t nameLen;
00418   namePtr = arg->getArg(6);
00419   nameLen = strlen(namePtr);
00420   nameBuffer = new char[strlen(arg->getArg(6)) + 1];
00421   strncpy(nameBuffer, &namePtr[1], nameLen - 1);
00422   nameBuffer[nameLen - 1] = '\0';
00423   */
00424   arg->compressQuoted();
00425 
00426   
00427   size_t fileLen = strlen(arg->getArg(4)) + 1;
00428   char *fileBuffer = new char[fileLen];
00429   
00430   //char *fileBuffer = NULL;
00431 /***/
00432   if (!ArUtil::stripQuotes(fileBuffer, arg->getArg(4), fileLen))
00433   {
00434     ArLog::log(ArLog::Terse, 
00435                "ArMap: 'Cairn:' couldn't strip quotes from fileName '%s'", 
00436                arg->getArg(4));
00437     return false;
00438   }
00439 
00440 
00441   size_t nameLen = strlen(arg->getArg(6)) + 1;
00442   char *nameBuffer = new char[nameLen];
00443   if (!ArUtil::stripQuotes(nameBuffer, arg->getArg(6), nameLen))
00444   {
00445     ArLog::log(ArLog::Terse, 
00446                "ArMap: 'Cairn:' couldn't strip quotes from name '%s'", 
00447                arg->getArg(6));
00448     return false;
00449   }
00450   
00451   if (arg->getArgc() == 11 && arg->isArgInt(7) && arg->isArgInt(8) && 
00452       arg->isArgInt(9) && arg->isArgInt(10))
00453   {
00454     hasFromTo = true;
00455     fromPose.setPose(arg->getArgInt(7), arg->getArgInt(8));
00456     toPose.setPose(arg->getArgInt(9), arg->getArgInt(10));
00457                      
00458   }
00459   pose.setPose(arg->getArgDouble(1), arg->getArgDouble(2), 
00460                arg->getArgDouble(3));
00461   object = new ArMapObject(arg->getArg(0), pose, fileBuffer,
00462                            arg->getArg(5), nameBuffer, hasFromTo, fromPose, 
00463                            toPose);
00464   delete [] nameBuffer;
00465   myLoadingMapObjects.push_back(object);
00466   //object->log();
00467   //arg->log();
00468   return true;
00469 }
00470 
00471 bool ArMap::handleMapInfo(ArArgumentBuilder *arg)
00472 {
00473   ArArgumentBuilder *mapInfo = NULL;
00474   mapInfo = new ArArgumentBuilder(*arg);
00475   myLoadingMapInfo.push_back(mapInfo);
00476   return true;
00477 }
00478 
00479 bool ArMap::handleInfo(ArArgumentBuilder *arg, int info) 
00480 {
00481   arg->compressQuoted();
00482   
00483   if ((info < 0) || (info >= myNumInfos)) {
00484     return false;
00485   }
00486   ArArgumentBuilder *infoBuilder = new ArArgumentBuilder(*arg);
00487   myLoadingInfoArray[info].push_back(infoBuilder);
00488   return true;
00489 }
00490 
00501 bool ArMap::handleData(ArArgumentBuilder *arg)
00502 {
00503   // make sure we got all the important data
00504   if (!myLoadingGotMinPos || !myLoadingGotMaxPos || myLoadingNumPoints == -1)
00505   {
00506     ArLog::log(ArLog::Verbose, "ArMap: got to DATA but didn't get all the important information, using our own anyways, but something is probably wrong");
00507   }
00508   // get rid of the old handlers
00509   myLoadingParser->remHandler(&myMinPosCB);
00510   myLoadingParser->remHandler(&myMaxPosCB);
00511   myLoadingParser->remHandler(&myNumPointsCB);
00512   myLoadingParser->remHandler(&myLineMinPosCB);
00513   myLoadingParser->remHandler(&myLineMaxPosCB);
00514   myLoadingParser->remHandler(&myNumLinesCB);
00515   myLoadingParser->remHandler(&myResolutionCB);
00516   myLoadingParser->remHandler(&myMapObjectCB);
00517   myLoadingParser->remHandler(&myMapInfoCB);
00518 
00519   for (int i = 0; i < myNumInfos; i++) {
00520           myLoadingParser->remHandler(myInfoCBArray[i]);
00521   }
00522   // myLoadingParser->remHandler(&myRouteInfoCB);
00523   myLoadingParser->remHandler(&myResolutionCB);
00524 
00525   //myLoadingParser->remHandler(&myDataCB);
00526   //myLoadingParser->remHandler(&myLinesCB);
00527   myLoadingParser->remHandler(&myLineCB);
00528 
00529   // now we add our handler for the points
00530   if (!myLoadingParser->addHandler(NULL, &myPointCB))
00531   {
00532     ArLog::log(ArLog::Terse, "ArMap: could not add handler for data points");
00533     return false;
00534   }
00535   myLoadingDataStarted = true;
00536   myLoadingLinesAndDataStarted = false;
00537   return false;
00538 
00539   // return true;
00540 }
00541 
00542 bool ArMap::handleLines(ArArgumentBuilder *arg)
00543 {
00544   // make sure we got all the important data
00545   if (!myLoadingGotMinPos || !myLoadingGotMaxPos || myLoadingNumPoints == -1)
00546   {
00547     ArLog::log(ArLog::Verbose, "ArMap: got to DATA but didn't get all the important information, using our own anyways, but something is probably wrong");
00548   }
00549   // get rid of the old handlers
00550   myLoadingParser->remHandler(&myMinPosCB);
00551   myLoadingParser->remHandler(&myMaxPosCB);
00552   myLoadingParser->remHandler(&myNumPointsCB);
00553   myLoadingParser->remHandler(&myLineMinPosCB);
00554   myLoadingParser->remHandler(&myLineMaxPosCB);
00555   myLoadingParser->remHandler(&myNumLinesCB);
00556   myLoadingParser->remHandler(&myResolutionCB);
00557   myLoadingParser->remHandler(&myMapObjectCB);
00558   myLoadingParser->remHandler(&myResolutionCB);
00559 
00560   // Don't remove the data cb because the points follow...
00561   //myLoadingParser->remHandler(&myDataCB);
00562   //myLoadingParser->remHandler(&myLinesCB);  
00563   myLoadingParser->remHandler(&myPointCB);  
00564 
00565   // now we add our handler for the points
00566   if (!myLoadingParser->addHandler(NULL, &myLineCB))
00567   {
00568     ArLog::log(ArLog::Terse, "ArMap: could not add handler for data points");
00569     return false;
00570   }
00571   myLoadingLinesAndDataStarted = true;
00572   myLoadingDataStarted = false;
00573   return false;
00574 
00575   // return true;
00576 }
00577 
00578 bool ArMap::handlePoint(ArArgumentBuilder *arg)
00579 {
00580   if (arg->getArgc() != 2 || !arg->isArgInt(0) || !arg->isArgInt(1))
00581   {
00582     ArLog::log(ArLog::Terse, 
00583            "ArMap::handlePoint: map point wrong, should be x and y int coords (in mm) but is %s", arg->getFullString());
00584     return false;
00585   }
00586 
00587   int x = arg->getArgInt(0);
00588   int y = arg->getArgInt(1);
00589 
00590   loadDataPoint(x, y);
00591   return true;
00592 
00593 }
00594 
00595 
00596 bool ArMap::handleLine(ArArgumentBuilder *arg)
00597 {
00598   if (arg->getArgc() != 4 || !arg->isArgInt(0) || !arg->isArgInt(1) || 
00599       !arg->isArgInt(2) || !arg->isArgInt(3))
00600   {
00601     ArLog::log(ArLog::Verbose, 
00602            "ArMap::handleLine: line wrong, should be 2 x, y points (in mm) but is %s", arg->getFullString());
00603     return false;
00604   }
00605 
00606   int x1 = arg->getArgInt(0);
00607   int y1 = arg->getArgInt(1);
00608   int x2 = arg->getArgInt(2);
00609   int y2 = arg->getArgInt(3);
00610 
00611   loadLineSegment(x1, y1, x2, y2);
00612   return true;
00613 
00614 }
00615 
00616 
00617 ArTime ArMap::getInfoChanged(int infoType)
00618 {
00619   if ((infoType >= 0) && (infoType < myNumInfos) && (myInfoChangedArray != NULL)) {
00620         return myInfoChangedArray[infoType]; 
00621   }
00622   else { // invalid info type
00623     // ArTime is initialized to now.  Set the secs and msecs to 0 for default value.
00624     ArTime defaultTime;
00625         defaultTime.setSec(0);
00626         defaultTime.setMSec(0);
00627         return defaultTime;
00628   }
00629 }
00630 
00637 void ArMap::setMapObjects(const std::list<ArMapObject *> *mapObjects)
00638 {
00639   std::list<ArMapObject *>::const_iterator it;
00640   ArUtil::deleteSet(myMapObjects.begin(), myMapObjects.end());
00641   myMapObjects.clear();
00642   myMapObjectsChanged.setToNow();
00643   if (mapObjects == NULL)
00644     return;
00645   for (it = mapObjects->begin(); it != mapObjects->end(); it++)
00646   {
00647     myMapObjects.push_back(new ArMapObject(*(*it)));
00648   }
00649 }
00650 
00657 void ArMap::setPoints(const std::vector<ArPose> *points)
00658 {
00659   std::vector<ArPose>::const_iterator it;
00660   ArPose pose;
00661   /***/
00662   myPoints.clear();
00663   myMax.setX(INT_MIN);
00664   myMax.setY(INT_MIN);
00665   myMin.setX(INT_MAX);
00666   myMin.setY(INT_MAX);
00667   myNumPoints = 0;
00668 
00669 
00670   myPointsChanged.setToNow();
00671   if (points == NULL) {
00672     return;
00673   }
00674 
00675 
00676   myPoints.reserve(points->size());
00677 
00678   for (it = points->begin(); it != points->end(); it++)
00679   {
00680     pose = (*it);
00681     if (pose.getX() > myMax.getX())
00682       myMax.setX(pose.getX());
00683     if (pose.getY() > myMax.getY())
00684       myMax.setY(pose.getY());
00685 
00686     if (pose.getX() < myMin.getX())
00687       myMin.setX(pose.getX());
00688     if (pose.getY() < myMin.getY())
00689       myMin.setY(pose.getY());
00690     
00691     myNumPoints++;
00692     myPoints.push_back(pose);
00693   }
00694   
00695 
00696 }
00697 
00698 
00705 void ArMap::setLines(const std::vector<ArLineSegment> *lines)
00706 {
00707   std::vector<ArLineSegment>::const_iterator it;
00708   ArLineSegment line;
00709   /***/
00710   myLines.clear();
00711   myLineMax.setX(INT_MIN);
00712   myLineMax.setY(INT_MIN);
00713   myLineMin.setX(INT_MAX);
00714   myLineMin.setY(INT_MAX);
00715   myNumLines = 0;
00716 
00717 
00718   myLinesChanged.setToNow();
00719   if (lines == NULL) {
00720     return;
00721   }
00722 
00723 
00724   myLines.reserve(lines->size());
00725 
00726   for (it = lines->begin(); it != lines->end(); it++)
00727   {
00728     line = (*it);
00729 
00730 
00731     if (line.getX1() > myLineMax.getX())
00732       myLineMax.setX(line.getX1());
00733     if (line.getY1() > myLineMax.getY())
00734       myLineMax.setY(line.getY1());
00735 
00736     if (line.getX1() < myLineMin.getX())
00737       myLineMin.setX(line.getX1());
00738     if (line.getY1() < myLineMin.getY())
00739       myLineMin.setY(line.getY1());
00740 
00741 
00742     if (line.getX2() > myLineMax.getX())
00743       myLineMax.setX(line.getX2());
00744     if (line.getY2() > myLineMax.getY())
00745       myLineMax.setY(line.getY2());
00746 
00747     if (line.getX2() < myLineMin.getX())
00748       myLineMin.setX(line.getX2());
00749     if (line.getY2() < myLineMin.getY())
00750       myLineMin.setY(line.getY2());
00751     
00752     myNumLines++;
00753     myLines.push_back(line);
00754   }
00755   
00756 
00757 }
00758 
00765 void ArMap::setMapInfo(const std::list<ArArgumentBuilder *> *mapInfo)
00766 {
00767   std::list<ArArgumentBuilder *>::const_iterator it;
00768   ArUtil::deleteSet(myMapInfo.begin(), myMapInfo.end());
00769   myMapInfo.clear();
00770   myMapInfoChanged.setToNow();
00771   if (mapInfo == NULL)
00772     return;
00773   for (it = mapInfo->begin(); it != mapInfo->end(); it++)
00774   {
00775     myMapInfo.push_back(new ArArgumentBuilder(*(*it)));
00776   }  
00777 }
00778 
00779 bool ArMap::setInfo(int infoType,
00780                                                          const std::list<ArArgumentBuilder *> *infoList)
00781 {
00782   if ((infoType < 0) || (infoType >= myNumInfos)) {
00783     return false;
00784   }
00785   // Should never happen, but check just in case...
00786   if ((myInfoArray == NULL) || (myInfoChangedArray == NULL)) {
00787           return false;
00788   }
00789   std::list<ArArgumentBuilder *>::const_iterator it;
00790   ArUtil::deleteSet(myInfoArray[infoType].begin(), myInfoArray[infoType].end());
00791   myInfoArray[infoType].clear();
00792   myInfoChangedArray[infoType].setToNow();
00793 
00794   if (infoList == NULL)
00795     return true;
00796 
00797   for (it = infoList->begin(); it != infoList->end(); it++)
00798   {
00799     myInfoArray[infoType].push_back(new ArArgumentBuilder(*(*it)));
00800   }
00801   return true;
00802 }
00803 
00804 void ArMap::setResolution(int resolution)
00805 {
00806         myResolution = resolution;
00807 }
00808 
00809 
00816 /***
00817 void ArMap::setRouteInfo(const std::list<ArArgumentBuilder *> *routeInfo)
00818 {
00819   std::list<ArArgumentBuilder *>::const_iterator it;
00820   ArUtil::deleteSet(myRouteInfo.begin(), myRouteInfo.end());
00821   myRouteInfo.clear();
00822   myRouteInfoChanged.setToNow();
00823   if (routeInfo == NULL)
00824     return;
00825   for (it = routeInfo->begin(); it != routeInfo->end(); it++)
00826   {
00827     myRouteInfo.push_back(new ArArgumentBuilder(*(*it)));
00828   }  
00829 }
00830 **/
00831 
00842 bool ArMap::readFile(const char *fileName, 
00843                               char *errorBuffer, size_t errorBufferLen)
00844 {
00845  
00846   lock();
00847   stat(fileName, &myReadFileStat);
00848   FILE *file;
00849 
00850   char line[10000];
00851   std::string realFileName;
00852   if (fileName[0] == '/' || fileName[0] == '\\' || 
00853       fileName[0] == '.')
00854   {
00855     realFileName = fileName;
00856   }
00857   else
00858   {
00859     realFileName = myBaseDirectory;
00860     realFileName += fileName;
00861   }
00862 
00863   ArLog::log(ArLog::Verbose, "Opening file %s from fileName given %s", realFileName.c_str(), fileName);
00864     
00865   if ((file = fopen(realFileName.c_str(), "r")) == NULL)
00866   {
00867     ArLog::log(ArLog::Terse, "Cannot open file '%s'", realFileName.c_str());
00868     if (errorBuffer != NULL)
00869       snprintf(errorBuffer, errorBufferLen, 
00870                "%s invalid: cannot open file '%s'",
00871                myConfigParam.c_str(), fileName);
00872     //printf("!     %s\n", errorBuffer);
00873 
00874     unlock();
00875     return false;
00876   }
00877 
00878   if (!reset() || !myLoadingParser->parseFile(file, line, 10000, false))
00879   {
00880     
00881     if (!myLoadingDataStarted && !myLoadingLinesAndDataStarted) 
00882     {
00883       reset();
00884       if (errorBuffer != NULL)
00885         snprintf(errorBuffer, errorBufferLen, 
00886                  "%s invalid: '%s' not a valid map",
00887                  myConfigParam.c_str(), fileName);
00888       unlock();
00889       ArLog::log(ArLog::Terse, "Could not load map file '%s'", fileName);
00890       
00891       return false;
00892     }
00893   } // end if parse success
00894   
00895   if (!myLoadingGot2DMap)
00896   {
00897     reset();
00898     if (errorBuffer != NULL)
00899       snprintf(errorBuffer, errorBufferLen, 
00900                "%s invalid, '%s' was not a map file",
00901                myConfigParam.c_str(), fileName);
00902     
00903     unlock();
00904     ArLog::log(ArLog::Terse, 
00905                "Could not load map file '%s' it was not a 2D-map", fileName);
00906     return false;
00907   }
00908 
00909   // if we're on the lines, read until the end of lines or end of file
00910   if (myLoadingLinesAndDataStarted)
00911   {
00912     //printf("Reading lines\n");
00913     while (fgets(line, sizeof(line), file) != NULL)
00914     {
00915       if (strncasecmp(line, "DATA", strlen("DATA")) == 0)
00916       {
00917         myLoadingDataStarted = true;
00918         break;
00919       }
00920       if (!readLineSegment(line))
00921       {
00922         continue;
00923       }
00924     }
00925   }
00926 
00927   //printf("reading data\n");
00928   // read until the end of the file
00929   while (fgets(line, sizeof(line), file) != NULL)
00930   {
00931     if (!readDataPoint(line))
00932     {
00933       continue;
00934     }
00935   }
00936   
00937   fclose(file);
00938   
00939   // move the stuff over from reading to new
00940   myFileName = fileName;
00941   setMapObjects(&myLoadingMapObjects);
00942   setPoints(&myLoadingPoints);
00943   setLines(&myLoadingLines);
00944   setMapInfo(&myLoadingMapInfo);
00945   
00946   for (int i = 0; i < myNumInfos; i++) {
00947           setInfo(i, &myLoadingInfoArray[i]);
00948   }
00949   // setRouteInfo(&myLoadingRouteInfo);
00950 
00951   myResolution = myLoadingResolution;
00952   // call our callbacks
00953   ArLog::log(ArLog::Terse, "Loaded map file '%s'", fileName);
00954 
00955   reset();
00956   
00957   mapChanged();
00958   unlock();
00959   return true;
00960 }
00961 
00962 bool ArMap::readDataPoint(char *line) 
00963 {
00964   if (line == NULL) {
00965     return false;
00966   }
00967   
00968   bool isNumber = true;
00969   int firstSpace = -1;
00970   
00971   unsigned int startNum = 0;
00972   
00973   for (unsigned int i = 0; i < strlen(line); i++) {
00974     if (!isdigit(line[i]) && !(i == startNum && line[i] == '-')) {
00975       
00976       if (isspace(line[i])) {
00977         line[i] = '\0';
00978         if (firstSpace < 0) {
00979           firstSpace = i;
00980           startNum = i + 1;
00981         }
00982         else {
00983           break;
00984         }
00985       }
00986       else {
00987         isNumber = false;
00988       }
00989       break;
00990     }
00991   } // end for each
00992   
00993   int x = atoi(line);
00994   int y = atoi(&line[firstSpace + 1]);
00995   
00996   loadDataPoint(x, y);
00997 
00998   return true;
00999 
01000 } // end method readDataPoint
01001 
01002 
01003 
01004 
01005 void ArMap::loadDataPoint(double x, double y)
01006 {
01007   if (x > myLoadingMax.getX())
01008     myLoadingMax.setX(x);
01009   if (y > myLoadingMax.getY())
01010     myLoadingMax.setY(y);
01011   
01012   if (x < myLoadingMin.getX())
01013     myLoadingMin.setX(x);
01014   if (y < myLoadingMin.getY())
01015     myLoadingMin.setY(y);
01016   
01017   myLoadingPoints.push_back(ArPose(x, y));
01018   myLoadingPointsRead++;
01019   
01020 } // end method loadDataPoint
01021 
01022 
01023 bool ArMap::readLineSegment(char *line) 
01024 {
01025   if (line == NULL) {
01026     return false;
01027   }
01028   
01029   /* MPL optomize this like kathleen did above, later */
01030   ArArgumentBuilder builder;
01031   builder.add(line);
01032   
01033   if (builder.getArgc() < 4)
01034     return false;
01035 
01036   loadLineSegment(builder.getArgInt(0), builder.getArgInt(1),
01037                   builder.getArgInt(2), builder.getArgInt(3));
01038 
01039   return true;
01040 
01041 } 
01042 
01043 void ArMap::loadLineSegment(double x1, double y1, double x2, double y2)
01044 {
01045   if (x1 > myLoadingLineMax.getX())
01046     myLoadingLineMax.setX(x1);
01047   if (y1 > myLoadingLineMax.getY())
01048     myLoadingLineMax.setY(y1);
01049   
01050   if (x1 < myLoadingLineMin.getX())
01051     myLoadingLineMin.setX(x1);
01052   if (y1 < myLoadingLineMin.getY())
01053     myLoadingMin.setY(y1);
01054 
01055   if (x2 > myLoadingLineMax.getX())
01056     myLoadingLineMax.setX(x2);
01057   if (y2 > myLoadingLineMax.getY())
01058     myLoadingLineMax.setY(y2);
01059   
01060   if (x2 < myLoadingLineMin.getX())
01061     myLoadingLineMin.setX(x2);
01062   if (y2 < myLoadingLineMin.getY())
01063     myLoadingMin.setY(y2);
01064   
01065   myLoadingLines.push_back(ArLineSegment(x1, y1, x2, y2));
01066   myLoadingLinesRead++;
01067   
01068 } 
01069 
01075 void ArMap::parsingComplete(void)
01076 {
01077   lock();
01078   setMapObjects(&myLoadingMapObjects);
01079   setPoints(&myLoadingPoints);
01080   setLines(&myLoadingLines);
01081   setMapInfo(&myLoadingMapInfo);
01082 
01083   for (int i = 0; i < myNumInfos; i++) {
01084           setInfo(i, &myLoadingInfoArray[i]);
01085   }
01086   //setRouteInfo(&myLoadingRouteInfo);
01087 
01088   myResolution = myLoadingResolution;
01089   ArLog::log(ArLog::Normal, "Loaded map from parsing");
01090   myFileName = "";
01091 
01092   reset();
01093 
01094   mapChanged();
01095   unlock();
01096 }
01097 
01098 void ArMap::mapChanged(void)
01099 {
01100   std::list<ArFunctor *>::iterator it;
01101 
01102   ArLog::LogLevel level = myMapChangedLogLevel;
01103   ArFunctor *functor;
01104 
01105   bool isAnyInfoChanged = false;
01106   for (int i = 0; i < myNumInfos; i++) {
01107           if (abs(myMapChangedInfoArray[i].mSecSince(myInfoChangedArray[i])) > 0) {
01108                   isAnyInfoChanged = true;
01109                   break;
01110           }
01111   }
01112   ArLog::log(level, "ArMap: Calling mapChanged callbacks");
01113   if (abs(myMapChangedMapObjects.mSecSince(myMapObjectsChanged)) > 0 || 
01114       abs(myMapChangedPoints.mSecSince(myPointsChanged)) > 0 || 
01115       abs(myMapChangedMapInfo.mSecSince(myMapInfoChanged)) > 0 ||
01116           isAnyInfoChanged) 
01117       //abs(myMapChangedRouteInfo.mSecSince(myRouteInfoChanged)) > 0)
01118   {
01119     for (it = myMapChangedCBList.begin(); it != myMapChangedCBList.end(); it++)
01120     {
01121       functor = (*it);
01122       if (functor->getName() != NULL && functor->getName()[0] != '\0')
01123         ArLog::log(level, "ArMap: Calling mapChanged functor '%s'", 
01124                    functor->getName());
01125       else
01126         ArLog::log(level, "ArMap: Calling unnamed mapChanged functor");
01127       
01128       functor->invoke();
01129     }
01130   }
01131   myMapChangedMapObjects = myMapObjectsChanged;
01132   myMapChangedPoints = myPointsChanged;
01133   myMapChangedMapInfo = myMapInfoChanged;
01134   //myMapChangedRouteInfo = myRouteInfoChanged;
01135   for (int i = 0; i < myNumInfos; i++) {
01136           myMapChangedInfoArray[i] = myInfoChangedArray[i];
01137   }
01138   ArLog::log(level, "ArMap: Done calling mapChanged callbacks");
01139 }
01140 
01141 
01146 void ArMap::writeToFunctor(ArFunctor1<const char *> *functor,
01147                                         const char *endOfLineChars)
01148 {
01149   // Write the header information and Cairn objects...
01150   writeObjectsToFunctor(functor, endOfLineChars);
01151 
01152   if (myLines.begin() != myLines.end())
01153   {
01154     // Write the map data points in text format....
01155     std::vector<ArLineSegment>::iterator lineIt;
01156     
01157     ArUtil::functorPrintf(functor, "LINES%s", endOfLineChars);
01158     
01159     for (lineIt = myLines.begin(); 
01160          lineIt != myLines.end();
01161          lineIt++)
01162     {
01163       ArUtil::functorPrintf(functor, "%.0f %.0f %.0f %.0f%s", 
01164                             (*lineIt).getX1(), (*lineIt).getY1(), 
01165                             (*lineIt).getX2(), (*lineIt).getY2(),
01166                             endOfLineChars);
01167     }
01168   }
01169   
01170   ArUtil::functorPrintf(functor, "DATA%s", endOfLineChars);
01171   
01172   if (myPoints.begin() != myPoints.end())
01173   {
01174     // Write the map data points in text format....
01175     std::vector<ArPose>::iterator pointIt;
01176     
01177     for (pointIt = myPoints.begin(); 
01178          pointIt != myPoints.end();
01179          pointIt++)
01180     {
01181       ArUtil::functorPrintf(functor, "%.0f %.0f%s", (*pointIt).getX(), 
01182                             (*pointIt).getY(), endOfLineChars);
01183     }
01184   }
01185 }
01186 
01187 
01188 void ArMap::writeObjectsToFunctor
01189                                 (ArFunctor1<const char *> *functor, 
01190                                 const char *endOfLineChars)
01191 {
01192   std::list<ArMapObject *>::iterator mapObjectIt;
01193   //std::vector<ArPose>::iterator pointIt;
01194   std::list<ArArgumentBuilder *>::iterator mapInfoIt;
01195   //std::list<ArArgumentBuilder *>::iterator routeInfoIt;
01196 
01197   // toss out the general data
01198   ArUtil::functorPrintf(functor, "2D-Map%s", endOfLineChars);
01199   if (myNumPoints != 0)
01200   {
01201     ArUtil::functorPrintf(functor, "MinPos: %.0f %.0f%s", 
01202                           myMin.getX(), myMin.getY(),  endOfLineChars);
01203     ArUtil::functorPrintf(functor, "MaxPos: %.0f %.0f%s", 
01204                           myMax.getX(), myMax.getY(),  endOfLineChars);
01205     ArUtil::functorPrintf(functor, "NumPoints: %d%s", 
01206                           myNumPoints, endOfLineChars);
01207   }
01208   if (myResolution != -1)
01209     ArUtil::functorPrintf(functor, "Resolution: %d%s", myResolution, 
01210                           endOfLineChars);
01211   if (myNumLines != 0)
01212   {
01213     ArUtil::functorPrintf(functor, "LineMinPos: %.0f %.0f%s", 
01214                           myLineMin.getX(), myLineMin.getY(),  endOfLineChars);
01215     ArUtil::functorPrintf(functor, "LineMaxPos: %.0f %.0f%s", 
01216                           myLineMax.getX(), myLineMax.getY(),  endOfLineChars);
01217     ArUtil::functorPrintf(functor, "NumLines: %d%s", 
01218                           myNumLines, endOfLineChars);
01219   }
01220   for (mapInfoIt = myMapInfo.begin(); 
01221        mapInfoIt != myMapInfo.end(); 
01222        mapInfoIt++)
01223     ArUtil::functorPrintf(functor, "MapInfo: %s%s", 
01224                           (*mapInfoIt)->getFullString(), 
01225             endOfLineChars);
01226 
01227   for (int i = 0; i < myNumInfos; i++) {
01228           const char *infoName = getInfoName(i);
01229           if (infoName == NULL) {
01230                 ArLog::log(ArLog::Normal, "ArMap: Cannot find Info tag for index %i, not saving...",
01231                                    i);
01232                 continue;
01233           }
01234 
01235           for (std::list<ArArgumentBuilder *>::iterator infoIt = myInfoArray[i].begin();
01236                    infoIt != myInfoArray[i].end();
01237                    infoIt++) {
01238 
01239                 ArUtil::functorPrintf(functor, "%s %s%s", 
01240                                                           infoName,
01241                                                           (*infoIt)->getFullString(), 
01242                                                           endOfLineChars);
01243 
01244           } // end for each info in list
01245   } // end for each info type
01246 
01256   for (mapObjectIt = myMapObjects.begin(); 
01257        mapObjectIt != myMapObjects.end(); 
01258        mapObjectIt++)
01259   {
01260     ArMapObject *object = (*mapObjectIt);
01261     if (object->hasFromTo())
01262       ArUtil::functorPrintf(functor, 
01263               "Cairn: %s %g %g %g \"%s\" %s \"%s\" %.0f %.0f %.0f %.0f%s",
01264               object->getType(), object->getPose().getX(), 
01265               object->getPose().getY(), object->getPose().getTh(), 
01266               object->getFileName(), object->getIconName(), 
01267               object->getName(), object->getFromPose().getX(),
01268               object->getFromPose().getY(),
01269               object->getToPose().getX(), object->getToPose().getY(), 
01270               endOfLineChars);
01271     else
01272       ArUtil::functorPrintf(functor, 
01273               "Cairn: %s %g %g %g \"%s\" %s \"%s\"%s",
01274               object->getType(), object->getPose().getX(), 
01275               object->getPose().getY(), object->getPose().getTh(), 
01276               object->getFileName(), object->getIconName(), 
01277               object->getName(), endOfLineChars);
01278   }
01279  
01280 }
01281 
01282 
01283 void ArMap::writePointsToFunctor
01284 (ArFunctor2<int, std::vector<ArPose> *> *functor)
01285 {
01286         functor->invoke(myNumPoints, &myPoints);
01287 }
01288 
01289 void ArMap::writeLinesToFunctor
01290 (ArFunctor2<int, std::vector<ArLineSegment> *> *functor)
01291 {
01292         functor->invoke(myNumLines, &myLines);
01293 }
01294 
01295 
01296 
01304 bool ArMap::writeFile(const char *fileName)
01305 {
01306   FILE *file;
01307   lock();
01308   // later this'll have a prefix
01309   std::string realFileName;
01310 
01311   if (fileName[0] == '/' || fileName[0] == '\\')
01312   {
01313     realFileName = fileName;
01314   }
01315   else
01316   {
01317     realFileName = myBaseDirectory;
01318     realFileName += fileName;
01319   }
01320   
01321   // make sure its there
01322   if ((file = fopen(realFileName.c_str(), "w")) == NULL)
01323   {
01324     ArLog::log(ArLog::Terse, "ArMap: Cannot open file '%s' for writing",
01325                realFileName.c_str());
01326     unlock();
01327     return false;
01328   }
01329 
01330   ArGlobalFunctor2<const char *, FILE *> functor(&ArUtil::writeToFile, "", file);
01331   writeToFunctor(&functor, "\n");
01332   
01333   fclose(file);
01334   unlock();
01335   return true;
01336 }
01337 
01338 bool ArMap::parseLine(char *line)
01339 {
01340   return myLoadingParser->parseLine(line);
01341 }
01342 
01344 
01351 ArMapObject *ArMap::findMapObject(const char *name, 
01352                                            const char *type)
01353 {
01354   std::list<ArMapObject *>::iterator objIt;
01355   ArMapObject* obj;
01356 
01357   for (objIt = getMapObjects()->begin(); 
01358        objIt != getMapObjects()->end(); 
01359        objIt++)
01360   {
01361     obj = (*objIt);
01362     if(obj == NULL)
01363       return NULL;
01364     // if we're searching any type or its the right type then check the name
01365     if (type == NULL || strcasecmp(obj->getType(), type) == 0)
01366     {
01367       if(name == NULL || strcasecmp(obj->getName(), name) == 0)
01368       {
01369         return obj;
01370       }
01371     }
01372   }
01373 
01374   // if we get down here we didn't find it
01375   return NULL;
01376 }
01377 
01378 const char *ArMap::getInfoName(int infoType)
01379 {
01380         if ((infoType >= 0) && (infoType < INFO_COUNT)) {
01381                 return ourInfoNames[infoType];
01382         }
01383         else {
01384                 return NULL;
01385         }
01386 }

Generated on Wed Oct 19 12:56:36 2005 for Aria by  doxygen 1.4.0