00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "ArExport.h"
00027 #include "ariaOSDef.h"
00028 #include "ariaInternal.h"
00029 #include "ArMap.h"
00030 #include "ArFileParser.h"
00031 #include "ArArgumentBuilder.h"
00032 #include "ArLog.h"
00033 #include <ctype.h>
00034
00035
00036 const char *ArMap::ourInfoNames[INFO_COUNT] =
00037 {
00038 "MetaInfo:",
00039 "TaskInfo:",
00040 "RouteInfo:",
00041 "SchedTaskInfo:",
00042 "SchedInfo:"
00043 };
00044
00051 AREXPORT ArMap::ArMap(const char *baseDirectory, bool addToGlobalConfig,
00052 const char *configSection, const char *configParam,
00053 const char *configDesc, bool ignoreEmptyFileName) :
00054 myNumInfos(INFO_COUNT),
00055 my2DMapCB(this, &ArMap::handle2DMap),
00056 myMinPosCB(this, &ArMap::handleMinPos),
00057 myMaxPosCB(this, &ArMap::handleMaxPos),
00058 myNumPointsCB(this, &ArMap::handleNumPoints),
00059 myLineMinPosCB(this, &ArMap::handleLineMinPos),
00060 myLineMaxPosCB(this, &ArMap::handleLineMaxPos),
00061 myNumLinesCB(this, &ArMap::handleNumLines),
00062 myResolutionCB(this, &ArMap::handleResolution),
00063 myMapObjectCB(this, &ArMap::handleMapObject),
00064 myMapInfoCB(this, &ArMap::handleMapInfo),
00065 myInfoCBArray(),
00069 myDataCB(this, &ArMap::handleData),
00070 myLinesCB(this, &ArMap::handleLines),
00071 myPointCB(this, &ArMap::handlePoint),
00072 myLineCB(this, &ArMap::handleLine),
00073 myProcessFileCB(this, &ArMap::processFile)
00074 {
00075
00076 myLoadingInfoArray = new std::list<ArArgumentBuilder *>[myNumInfos];
00077 myInfoArray = new std::list<ArArgumentBuilder *> [myNumInfos];
00078 myInfoChangedArray = new ArTime[myNumInfos];
00079 myMapChangedInfoArray = new ArTime[myNumInfos];
00080 myInfoCBArray = new ArRetFunctor2C<bool, ArMap, ArArgumentBuilder *, int> *[myNumInfos];
00081 myResolution = -1;
00082
00083
00084 for (int i = 0; i < myNumInfos; i++) {
00085 myInfoCBArray[i] = new ArRetFunctor2C<bool, ArMap, ArArgumentBuilder *, int>
00086 (this,
00087 &ArMap::handleInfo,
00088 NULL, i);
00089 }
00090
00091 myProcessFileCB.setName("ArMap");
00092 myMapChangedLogLevel = ArLog::Verbose;
00093 myConfigParam = configParam;
00094 myIgnoreEmptyFileName = ignoreEmptyFileName;
00095
00096 #ifndef ARINTERFACE
00097 if (addToGlobalConfig)
00098 {
00099 myConfigMapName[0] = '\0';
00100 myConfigProcessedBefore = false;
00101
00102 const char *displayHint = "RobotFile:Map Files (*.map)|*.map";
00103
00104 Aria::getConfig()->addParam(ArConfigArg(configParam,
00105 myConfigMapName,
00106 configDesc,
00107 sizeof(myConfigMapName)),
00108 configSection,
00109 ArPriority::IMPORTANT,
00110 displayHint);
00111 Aria::getConfig()->addProcessFileWithErrorCB(&myProcessFileCB, 100);
00112 }
00113 #endif //ARINTERFACE
00114 myLoadingParser = NULL;
00115 setBaseDirectory(baseDirectory);
00116 reset();
00117
00118 }
00119
00120 AREXPORT ArMap::~ArMap()
00121 {
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134 ArUtil::deleteSet(myMapObjects.begin(), myMapObjects.end());
00135 ArUtil::deleteSet(myMapInfo.begin(), myMapInfo.end());
00136 if(myLoadingParser) delete myLoadingParser;
00137 }
00138
00139 bool ArMap::processFile(char *errorBuffer, size_t errorBufferLen)
00140 {
00141
00142 ArUtil::fixSlashes(myConfigMapName, MAX_MAP_NAME_LENGTH);
00143
00144 struct stat mapFileStat;
00145 stat(myConfigMapName, &mapFileStat);
00146
00147
00148 if (myIgnoreEmptyFileName && myConfigMapName[0] == '\0')
00149 {
00150 ArLog::log(ArLog::Normal, "Using an empty map since empty map file name");
00151 lock();
00152 reset();
00153 myFileName = "";
00154 setMapObjects(NULL);
00155 setPoints(NULL);
00156 setLines(NULL);
00157 setMapInfo(NULL);
00158
00159 for (int i = 0; i < myNumInfos; i++) {
00160 setInfo(i, NULL);
00161 }
00162
00163 myResolution = -1;
00164 mapChanged();
00165 unlock();
00166 return true;
00167 }
00168
00169
00170
00171 if (!myConfigProcessedBefore ||
00172 ArUtil::strcmp(myConfigMapName, myFileName.c_str()) != 0 ||
00173 mapFileStat.st_mtime != myReadFileStat.st_mtime)
00174 {
00175 ArLog::log(ArLog::Verbose, "ArMap: LOADINGMAP because configProcessedBefore %d myFileName \"%s\" configFileName \"%s\" mapFileTime %lu readFileTime %lu (Diff %ld)",
00176 myConfigProcessedBefore, myFileName.c_str(), myConfigMapName,
00177 mapFileStat.st_mtime, myReadFileStat.st_mtime, mapFileStat.st_mtime - myReadFileStat.st_mtime);
00178 myConfigProcessedBefore = true;
00179
00180 if(readFile(myConfigMapName, errorBuffer, errorBufferLen))
00181 {
00182 return true;
00183 }
00184 else
00185 {
00186 ArLog::log(ArLog::Terse, "ArMap: failed to read new map file \"%s\": %s.", myConfigMapName, errorBuffer);
00187
00188
00189 return false;
00190 }
00191 }
00192
00193
00194 return true;
00195 }
00196
00197 AREXPORT const char *ArMap::getBaseDirectory(void) const
00198 {
00199 return myBaseDirectory.c_str();
00200 }
00201
00202 AREXPORT const char *ArMap::getFileName(void) const
00203 {
00204 return myFileName.c_str();
00205 }
00206
00207 AREXPORT void ArMap::setBaseDirectory(const char *baseDirectory)
00208 {
00209 if (baseDirectory != NULL && strlen(baseDirectory) > 0)
00210 myBaseDirectory = baseDirectory;
00211 else
00212 myBaseDirectory = "";
00213 if (myLoadingParser != NULL)
00214 myLoadingParser->setBaseDirectory(myBaseDirectory.c_str());
00215 }
00216
00217 AREXPORT std::list<ArArgumentBuilder *> *ArMap::getInfo(int infoType)
00218 {
00219 if ((infoType >= 0) && (infoType < myNumInfos) && (myInfoArray != NULL)) {
00220 return &myInfoArray[infoType];
00221 }
00222 else {
00223 return NULL;
00224 }
00225 }
00226
00232 AREXPORT void ArMap::addMapChangedCB(ArFunctor *functor, ArListPos::Pos position)
00233 {
00234 if (position == ArListPos::FIRST)
00235 myMapChangedCBList.push_front(functor);
00236 else if (position == ArListPos::LAST)
00237 myMapChangedCBList.push_back(functor);
00238 else
00239 ArLog::log(ArLog::Terse,
00240 "ArMap::addMapChangedCB: Invalid position.");
00241 }
00242
00243 AREXPORT void ArMap::remMapChangedCB(ArFunctor *functor)
00244 {
00245 myMapChangedCBList.remove(functor);
00246 }
00247
00248
00257 AREXPORT void ArMap::addPreMapChangedCB(ArFunctor *functor, ArListPos::Pos position)
00258 {
00259 if (position == ArListPos::FIRST)
00260 myPreMapChangedCBList.push_front(functor);
00261 else if (position == ArListPos::LAST)
00262 myPreMapChangedCBList.push_back(functor);
00263 else
00264 ArLog::log(ArLog::Terse,
00265 "ArMap::addPreMapChangedCB: Invalid position.");
00266 }
00267
00268 AREXPORT void ArMap::remPreMapChangedCB(ArFunctor *functor)
00269 {
00270 myPreMapChangedCBList.remove(functor);
00271 }
00272
00273 AREXPORT bool ArMap::reset(void)
00274 {
00275
00276
00277
00278
00279 if (myLoadingParser != NULL)
00280 delete myLoadingParser;
00281 myLoadingParser = new ArFileParser;
00282 myLoadingParser->setBaseDirectory(myBaseDirectory.c_str());
00283 myLoadingGotMaxPos = false;
00284 myLoadingGotMinPos = false;
00285 myLoadingGot2DMap = false;
00286 myLoadingNumPoints = -1;
00287 myLoadingResolution = -1;
00288 myLoadingPointsRead = 0;
00289 myLoadingLinesRead = 0;
00290 myLoadingMax.setX(INT_MIN);
00291 myLoadingMax.setY(INT_MIN);
00292 myLoadingMin.setX(INT_MAX);
00293 myLoadingMin.setY(INT_MAX);
00294 ArUtil::deleteSet(myLoadingMapObjects.begin(), myLoadingMapObjects.end());
00295 myLoadingMapObjects.clear();
00296 myLoadingPoints.clear();
00297 myLoadingLines.clear();
00298 ArUtil::deleteSet(myLoadingMapInfo.begin(), myLoadingMapInfo.end());
00299 myLoadingMapInfo.clear();
00300
00301 for (int i = 0; i < myNumInfos; i++) {
00302
00303 ArUtil::deleteSet(myLoadingInfoArray[i].begin(), myLoadingInfoArray[i].end());
00304 myLoadingInfoArray[i].clear();
00305 }
00306
00307
00308
00309
00310
00311
00312 myLoadingDataStarted = false;
00313 myLoadingLinesAndDataStarted = false;
00314
00315 if (!myLoadingParser->addHandler("2D-Map", &my2DMapCB))
00316 {
00317 ArLog::log(ArLog::Terse, "ArMap::reset: could not add 2D-Map");
00318 return false;
00319 }
00320
00321 return true;
00322 }
00323
00324 bool ArMap::handle2DMap(ArArgumentBuilder *arg)
00325 {
00326 ArLog::log(ArLog::Verbose, "ArMap: got 2D-Map");
00327
00328 if (!myLoadingParser->addHandler("MinPos:", &myMinPosCB) ||
00329 !myLoadingParser->addHandler("MaxPos:", &myMaxPosCB) ||
00330 !myLoadingParser->addHandler("NumPoints:", &myNumPointsCB) ||
00331 !myLoadingParser->addHandler("LineMinPos:", &myMinPosCB) ||
00332 !myLoadingParser->addHandler("LineMaxPos:", &myMaxPosCB) ||
00333 !myLoadingParser->addHandler("NumLines:", &myNumPointsCB) ||
00334 !myLoadingParser->addHandler("Resolution:", &myResolutionCB) ||
00335 !myLoadingParser->addHandler("Cairn:", &myMapObjectCB) ||
00336 !myLoadingParser->addHandler("MapInfo:", &myMapInfoCB) ||
00337
00338
00339 !myLoadingParser->addHandler("LINES", &myLinesCB) ||
00340 !myLoadingParser->addHandler("DATA", &myDataCB))
00341 {
00342 ArLog::log(ArLog::Terse, "ArMap::handle2DMap: could not add handlers");
00343 return false;
00344 }
00345
00346 for (int i = 0; i < myNumInfos; i++) {
00347 if (!myLoadingParser->addHandler(getInfoName(i),
00348 myInfoCBArray[i])) {
00349 ArLog::log(ArLog::Terse, "ArMap::handle2DMap: could not add info handlers");
00350 return false;
00351 }
00352 }
00353
00354
00355 myLoadingParser->remHandler("2D-Map");
00356 myLoadingGot2DMap = true;
00357 return true;
00358
00359 }
00360
00361 bool ArMap::handleMinPos(ArArgumentBuilder *arg)
00362 {
00363 if (arg->getArgc() != 2 || !arg->isArgInt(0) || !arg->isArgInt(1))
00364 {
00365 ArLog::log(ArLog::Terse,
00366 "ArMap: 'MinPos:' bad arguments, should be two integers x y");
00367 return false;
00368 }
00369 myLoadingMinFromFile.setPose(arg->getArgInt(0), arg->getArgInt(1));
00370 myLoadingGotMinPos = true;
00371 return true;
00372 }
00373
00374 bool ArMap::handleMaxPos(ArArgumentBuilder *arg)
00375 {
00376 if (arg->getArgc() != 2 || !arg->isArgInt(0) || !arg->isArgInt(1))
00377 {
00378 ArLog::log(ArLog::Terse,
00379 "ArMap: 'MaxPos:' bad arguments, should be two integers x y");
00380 return false;
00381 }
00382 myLoadingMaxFromFile.setPose(arg->getArgInt(0), arg->getArgInt(1));
00383 myLoadingGotMaxPos = true;
00384 return true;
00385 }
00386
00387 bool ArMap::handleNumPoints(ArArgumentBuilder *arg)
00388 {
00389 if (arg->getArgc() != 1 || !arg->isArgInt(0))
00390 {
00391 ArLog::log(ArLog::Terse,
00392 "ArMap: 'NumPoints:' bad argument, should be one integer (number of data points)");
00393 return false;
00394 }
00395 myLoadingNumPoints = arg->getArgInt(0);
00396
00397 if (myLoadingNumPoints >= 0) {
00398 myLoadingPoints.reserve(myLoadingNumPoints);
00399 }
00400
00401 return true;
00402 }
00403
00404 bool ArMap::handleLineMinPos(ArArgumentBuilder *arg)
00405 {
00406 if (arg->getArgc() != 2 || !arg->isArgInt(0) || !arg->isArgInt(1))
00407 {
00408 ArLog::log(ArLog::Terse,
00409 "ArMap: 'LineMinPos:' bad arguments, should be two integers x y");
00410 return false;
00411 }
00412 myLoadingLineMinFromFile.setPose(arg->getArgInt(0), arg->getArgInt(1));
00413 myLoadingGotLineMinPos = true;
00414 return true;
00415 }
00416
00417 bool ArMap::handleLineMaxPos(ArArgumentBuilder *arg)
00418 {
00419 if (arg->getArgc() != 2 || !arg->isArgInt(0) || !arg->isArgInt(1))
00420 {
00421 ArLog::log(ArLog::Terse,
00422 "ArMap: 'LineMaxPos:' bad arguments, should be two integers x y");
00423 return false;
00424 }
00425 myLoadingLineMaxFromFile.setPose(arg->getArgInt(0), arg->getArgInt(1));
00426 myLoadingGotLineMaxPos = true;
00427 return true;
00428 }
00429
00430 bool ArMap::handleNumLines(ArArgumentBuilder *arg)
00431 {
00432 if (arg->getArgc() != 1 || !arg->isArgInt(0))
00433 {
00434 ArLog::log(ArLog::Terse,
00435 "ArMap: 'NumPoints:' bad argument, should be one integer (number of data points)");
00436 return false;
00437 }
00438 myLoadingNumLines = arg->getArgInt(0);
00439
00440 if (myLoadingNumLines >= 0) {
00441 myLoadingLines.reserve(myLoadingNumPoints);
00442 }
00443
00444 return true;
00445 }
00446
00447 bool ArMap::handleResolution(ArArgumentBuilder *arg)
00448 {
00449 if (arg->getArgc() != 1 || !arg->isArgInt(0))
00450 {
00451 ArLog::log(ArLog::Terse,
00452 "ArMap: 'Resolution:' bad argument, should be one integer (resolution in mm)");
00453 return false;
00454 }
00455 myLoadingResolution = arg->getArgInt(0);
00456 return true;
00457 }
00458
00459 bool ArMap::handleMapObject(ArArgumentBuilder *arg)
00460 {
00461 ArMapObject *object;
00462 ArPose pose;
00463 bool hasFromTo = false;
00464 ArPose fromPose;
00465 ArPose toPose;
00466
00467 if (arg->getArgc() < 7 || !arg->isArgDouble(1) || !arg->isArgDouble(2) ||
00468 !arg->isArgDouble(3))
00469 {
00470 ArLog::log(ArLog::Terse,
00471 "ArMap: 'Cairn:' bad format '%s'", arg->getFullString());
00472 return false;
00473 }
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485 arg->compressQuoted();
00486
00487
00488 size_t fileLen = strlen(arg->getArg(4)) + 1;
00489 char *fileBuffer = new char[fileLen];
00490
00491
00492
00493 if (!ArUtil::stripQuotes(fileBuffer, arg->getArg(4), fileLen))
00494 {
00495 ArLog::log(ArLog::Terse,
00496 "ArMap: 'Cairn:' couldn't strip quotes from fileName '%s'",
00497 arg->getArg(4));
00498 delete[] fileBuffer;
00499 return false;
00500 }
00501
00502
00503 size_t nameLen = strlen(arg->getArg(6)) + 1;
00504 char *nameBuffer = new char[nameLen];
00505 if (!ArUtil::stripQuotes(nameBuffer, arg->getArg(6), nameLen))
00506 {
00507 ArLog::log(ArLog::Terse,
00508 "ArMap: 'Cairn:' couldn't strip quotes from name '%s'",
00509 arg->getArg(6));
00510 delete[] fileBuffer;
00511 delete[] nameBuffer;
00512 return false;
00513 }
00514
00515 if (arg->getArgc() == 11 && arg->isArgInt(7) && arg->isArgInt(8) &&
00516 arg->isArgInt(9) && arg->isArgInt(10))
00517 {
00518 hasFromTo = true;
00519 fromPose.setPose(arg->getArgInt(7), arg->getArgInt(8));
00520 toPose.setPose(arg->getArgInt(9), arg->getArgInt(10));
00521
00522 }
00523 pose.setPose(arg->getArgDouble(1), arg->getArgDouble(2),
00524 arg->getArgDouble(3));
00525 object = new ArMapObject(arg->getArg(0), pose, fileBuffer,
00526 arg->getArg(5), nameBuffer, hasFromTo, fromPose,
00527 toPose);
00528 delete [] fileBuffer;
00529 delete [] nameBuffer;
00530 myLoadingMapObjects.push_back(object);
00531
00532
00533 return true;
00534 }
00535
00536 bool ArMap::handleMapInfo(ArArgumentBuilder *arg)
00537 {
00538 ArArgumentBuilder *mapInfo = NULL;
00539 mapInfo = new ArArgumentBuilder(*arg);
00540 myLoadingMapInfo.push_back(mapInfo);
00541 return true;
00542 }
00543
00544 bool ArMap::handleInfo(ArArgumentBuilder *arg, int info)
00545 {
00546 arg->compressQuoted();
00547
00548 if ((info < 0) || (info >= myNumInfos)) {
00549 return false;
00550 }
00551 ArArgumentBuilder *infoBuilder = new ArArgumentBuilder(*arg);
00552 myLoadingInfoArray[info].push_back(infoBuilder);
00553
00554 ArLog::log(ArLog::Verbose,
00555 "ArMap::handleInfo(%i) = %s",
00556 info,
00557 ((arg != NULL) ? arg->getFullString() : "NULL"));
00558
00559 return true;
00560 }
00561
00572 bool ArMap::handleData(ArArgumentBuilder *arg)
00573 {
00574
00575 if (!myLoadingGotMinPos || !myLoadingGotMaxPos || myLoadingNumPoints == -1)
00576 {
00577 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");
00578 }
00579
00580 myLoadingParser->remHandler(&myMinPosCB);
00581 myLoadingParser->remHandler(&myMaxPosCB);
00582 myLoadingParser->remHandler(&myNumPointsCB);
00583 myLoadingParser->remHandler(&myLineMinPosCB);
00584 myLoadingParser->remHandler(&myLineMaxPosCB);
00585 myLoadingParser->remHandler(&myNumLinesCB);
00586 myLoadingParser->remHandler(&myResolutionCB);
00587 myLoadingParser->remHandler(&myMapObjectCB);
00588 myLoadingParser->remHandler(&myMapInfoCB);
00589
00590 for (int i = 0; i < myNumInfos; i++) {
00591 myLoadingParser->remHandler(myInfoCBArray[i]);
00592 }
00593
00594 myLoadingParser->remHandler(&myResolutionCB);
00595
00596
00597
00598 myLoadingParser->remHandler(&myLineCB);
00599 myLoadingParser->remHandler(&myPointCB);
00600
00601
00602 if (!myLoadingParser->addHandler(NULL, &myPointCB))
00603 {
00604 ArLog::log(ArLog::Terse, "ArMap: could not add handler for data points");
00605 return false;
00606 }
00607 myLoadingDataStarted = true;
00608 myLoadingLinesAndDataStarted = false;
00609 return false;
00610
00611
00612 }
00613
00614 bool ArMap::handleLines(ArArgumentBuilder *arg)
00615 {
00616
00617 if (!myLoadingGotMinPos || !myLoadingGotMaxPos || myLoadingNumPoints == -1)
00618 {
00619 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");
00620 }
00621
00622 myLoadingParser->remHandler(&myMinPosCB);
00623 myLoadingParser->remHandler(&myMaxPosCB);
00624 myLoadingParser->remHandler(&myNumPointsCB);
00625 myLoadingParser->remHandler(&myLineMinPosCB);
00626 myLoadingParser->remHandler(&myLineMaxPosCB);
00627 myLoadingParser->remHandler(&myNumLinesCB);
00628 myLoadingParser->remHandler(&myResolutionCB);
00629 myLoadingParser->remHandler(&myMapObjectCB);
00630 myLoadingParser->remHandler(&myResolutionCB);
00631
00632 for (int i = 0; i < myNumInfos; i++) {
00633 myLoadingParser->remHandler(myInfoCBArray[i]);
00634 }
00635
00636
00637
00638
00639
00640 myLoadingParser->remHandler(&myPointCB);
00641 myLoadingParser->remHandler(&myLineCB);
00642
00643
00644 if (!myLoadingParser->addHandler(NULL, &myLineCB))
00645 {
00646 ArLog::log(ArLog::Terse, "ArMap: could not add handler for data lines");
00647 return false;
00648 }
00649 myLoadingLinesAndDataStarted = true;
00650 myLoadingDataStarted = false;
00651 return false;
00652
00653
00654 }
00655
00656 bool ArMap::handlePoint(ArArgumentBuilder *arg)
00657 {
00658 if (arg->getArgc() != 2 || !arg->isArgInt(0) || !arg->isArgInt(1))
00659 {
00660 ArLog::log(ArLog::Terse,
00661 "ArMap::handlePoint: map point wrong, should be x and y int coords (in mm) but is %s", arg->getFullString());
00662 return false;
00663 }
00664
00665 int x = arg->getArgInt(0);
00666 int y = arg->getArgInt(1);
00667
00668 loadDataPoint(x, y);
00669 return true;
00670
00671 }
00672
00673
00674 bool ArMap::handleLine(ArArgumentBuilder *arg)
00675 {
00676 if (arg->getArgc() != 4 || !arg->isArgInt(0) || !arg->isArgInt(1) ||
00677 !arg->isArgInt(2) || !arg->isArgInt(3))
00678 {
00679 ArLog::log(ArLog::Verbose,
00680 "ArMap::handleLine: line wrong, should be 2 x, y points (in mm) but is %s", arg->getFullString());
00681 return false;
00682 }
00683
00684 int x1 = arg->getArgInt(0);
00685 int y1 = arg->getArgInt(1);
00686 int x2 = arg->getArgInt(2);
00687 int y2 = arg->getArgInt(3);
00688
00689 loadLineSegment(x1, y1, x2, y2);
00690 return true;
00691
00692 }
00693
00694
00695 AREXPORT ArTime ArMap::getInfoChanged(int infoType)
00696 {
00697 if ((infoType >= 0) && (infoType < myNumInfos) && (myInfoChangedArray != NULL)) {
00698 return myInfoChangedArray[infoType];
00699 }
00700 else {
00701
00702 ArTime defaultTime;
00703 defaultTime.setSec(0);
00704 defaultTime.setMSec(0);
00705 return defaultTime;
00706 }
00707 }
00708
00715 AREXPORT void ArMap::setMapObjects(const std::list<ArMapObject *> *mapObjects)
00716 {
00717 std::list<ArMapObject *>::const_iterator it;
00718 ArUtil::deleteSet(myMapObjects.begin(), myMapObjects.end());
00719 myMapObjects.clear();
00720 myMapObjectsChanged.setToNow();
00721 if (mapObjects == NULL)
00722 return;
00723 for (it = mapObjects->begin(); it != mapObjects->end(); it++)
00724 {
00725 myMapObjects.push_back(new ArMapObject(*(*it)));
00726 }
00727 }
00728
00735 AREXPORT void ArMap::setPoints(const std::vector<ArPose> *points)
00736 {
00737 std::vector<ArPose>::const_iterator it;
00738 ArPose pose;
00739
00740 myPoints.clear();
00741 myMax.setX(INT_MIN);
00742 myMax.setY(INT_MIN);
00743 myMin.setX(INT_MAX);
00744 myMin.setY(INT_MAX);
00745 myNumPoints = 0;
00746
00747
00748 myPointsChanged.setToNow();
00749 if (points == NULL) {
00750 return;
00751 }
00752
00753
00754 myPoints.reserve(points->size());
00755
00756 for (it = points->begin(); it != points->end(); it++)
00757 {
00758 pose = (*it);
00759 if (pose.getX() > myMax.getX())
00760 myMax.setX(pose.getX());
00761 if (pose.getY() > myMax.getY())
00762 myMax.setY(pose.getY());
00763
00764 if (pose.getX() < myMin.getX())
00765 myMin.setX(pose.getX());
00766 if (pose.getY() < myMin.getY())
00767 myMin.setY(pose.getY());
00768
00769 myNumPoints++;
00770 myPoints.push_back(pose);
00771 }
00772
00773
00774 }
00775
00776
00782 AREXPORT void ArMap::setLines(const std::vector<ArLineSegment> *lines)
00783 {
00784 std::vector<ArLineSegment>::const_iterator it;
00785 ArLineSegment line;
00786
00787 myLines.clear();
00788 myLineMax.setX(INT_MIN);
00789 myLineMax.setY(INT_MIN);
00790 myLineMin.setX(INT_MAX);
00791 myLineMin.setY(INT_MAX);
00792 myNumLines = 0;
00793
00794
00795 myLinesChanged.setToNow();
00796 if (lines == NULL) {
00797 return;
00798 }
00799
00800
00801 myLines.reserve(lines->size());
00802
00803 for (it = lines->begin(); it != lines->end(); it++)
00804 {
00805 line = (*it);
00806
00807
00808 if (line.getX1() > myLineMax.getX())
00809 myLineMax.setX(line.getX1());
00810 if (line.getY1() > myLineMax.getY())
00811 myLineMax.setY(line.getY1());
00812
00813 if (line.getX1() < myLineMin.getX())
00814 myLineMin.setX(line.getX1());
00815 if (line.getY1() < myLineMin.getY())
00816 myLineMin.setY(line.getY1());
00817
00818
00819 if (line.getX2() > myLineMax.getX())
00820 myLineMax.setX(line.getX2());
00821 if (line.getY2() > myLineMax.getY())
00822 myLineMax.setY(line.getY2());
00823
00824 if (line.getX2() < myLineMin.getX())
00825 myLineMin.setX(line.getX2());
00826 if (line.getY2() < myLineMin.getY())
00827 myLineMin.setY(line.getY2());
00828
00829 myNumLines++;
00830 myLines.push_back(line);
00831 }
00832
00833
00834 }
00835
00842 AREXPORT void ArMap::setMapInfo(const std::list<ArArgumentBuilder *> *mapInfo)
00843 {
00844 std::list<ArArgumentBuilder *>::const_iterator it;
00845 ArUtil::deleteSet(myMapInfo.begin(), myMapInfo.end());
00846 myMapInfo.clear();
00847 myMapInfoChanged.setToNow();
00848 if (mapInfo == NULL)
00849 return;
00850 for (it = mapInfo->begin(); it != mapInfo->end(); it++)
00851 {
00852 myMapInfo.push_back(new ArArgumentBuilder(*(*it)));
00853 }
00854 }
00855
00856 AREXPORT bool ArMap::setInfo(int infoType,
00857 const std::list<ArArgumentBuilder *> *infoList)
00858 {
00859 if ((infoType < 0) || (infoType >= myNumInfos)) {
00860 return false;
00861 }
00862
00863 if ((myInfoArray == NULL) || (myInfoChangedArray == NULL)) {
00864 return false;
00865 }
00866 std::list<ArArgumentBuilder *>::const_iterator it;
00867 ArUtil::deleteSet(myInfoArray[infoType].begin(), myInfoArray[infoType].end());
00868 myInfoArray[infoType].clear();
00869 myInfoChangedArray[infoType].setToNow();
00870
00871 if (infoList == NULL)
00872 return true;
00873
00874 for (it = infoList->begin(); it != infoList->end(); it++)
00875 {
00876 myInfoArray[infoType].push_back(new ArArgumentBuilder(*(*it)));
00877 }
00878 return true;
00879 }
00880
00881 AREXPORT void ArMap::setResolution(int resolution)
00882 {
00883 myResolution = resolution;
00884 }
00885
00886
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00919 AREXPORT bool ArMap::readFile(const char *fileName,
00920 char *errorBuffer, size_t errorBufferLen)
00921 {
00922
00923 lock();
00924 stat(fileName, &myReadFileStat);
00925 FILE *file;
00926
00927 char line[10000];
00928 std::string realFileName;
00929 if (fileName[0] == '/' || fileName[0] == '\\' ||
00930 fileName[0] == '.')
00931 {
00932 realFileName = fileName;
00933 }
00934 else
00935 {
00936 realFileName = myBaseDirectory;
00937 realFileName += fileName;
00938 }
00939
00940 ArLog::log(ArLog::Verbose, "Opening file %s from fileName given %s", realFileName.c_str(), fileName);
00941
00942 if ((file = fopen(realFileName.c_str(), "r")) == NULL)
00943 {
00944 ArLog::log(ArLog::Terse, "Cannot open file '%s'", realFileName.c_str());
00945 if (errorBuffer != NULL)
00946 snprintf(errorBuffer, errorBufferLen,
00947 "%s invalid: cannot open file '%s'",
00948 myConfigParam.c_str(), fileName);
00949
00950
00951 unlock();
00952 return false;
00953 }
00954
00955 if (!reset() || !myLoadingParser->parseFile(file, line, 10000, false))
00956 {
00957
00958 if (!myLoadingDataStarted && !myLoadingLinesAndDataStarted)
00959 {
00960 reset();
00961 if (errorBuffer != NULL)
00962 snprintf(errorBuffer, errorBufferLen,
00963 "%s invalid: '%s' not a valid map",
00964 myConfigParam.c_str(), fileName);
00965 unlock();
00966 ArLog::log(ArLog::Terse, "Could not load map file '%s'", fileName);
00967
00968 return false;
00969 }
00970 }
00971
00972 if (!myLoadingGot2DMap)
00973 {
00974 reset();
00975 if (errorBuffer != NULL)
00976 snprintf(errorBuffer, errorBufferLen,
00977 "%s invalid, '%s' was not a map file",
00978 myConfigParam.c_str(), fileName);
00979
00980 unlock();
00981 ArLog::log(ArLog::Terse,
00982 "Could not load map file '%s' it was not a 2D-map", fileName);
00983 return false;
00984 }
00985
00986
00987 if (myLoadingLinesAndDataStarted)
00988 {
00989
00990 while (fgets(line, sizeof(line), file) != NULL)
00991 {
00992 if (strncasecmp(line, "DATA", strlen("DATA")) == 0)
00993 {
00994 myLoadingDataStarted = true;
00995 break;
00996 }
00997 if (!readLineSegment(line))
00998 {
00999 continue;
01000 }
01001 }
01002 }
01003
01004
01005
01006 while (fgets(line, sizeof(line), file) != NULL)
01007 {
01008 if (!readDataPoint(line))
01009 {
01010 continue;
01011 }
01012 }
01013
01014 fclose(file);
01015
01016
01017 myFileName = fileName;
01018 setMapObjects(&myLoadingMapObjects);
01019 setPoints(&myLoadingPoints);
01020 setLines(&myLoadingLines);
01021 setMapInfo(&myLoadingMapInfo);
01022
01023 for (int i = 0; i < myNumInfos; i++) {
01024 setInfo(i, &myLoadingInfoArray[i]);
01025 }
01026
01027
01028 myResolution = myLoadingResolution;
01029
01030 ArLog::log(ArLog::Terse, "Loaded map file '%s'", fileName);
01031
01032 reset();
01033
01034 mapChanged();
01035 unlock();
01036 return true;
01037 }
01038
01039 bool ArMap::readDataPoint(char *line)
01040 {
01041 if (line == NULL) {
01042 return false;
01043 }
01044
01045 bool isNumber = true;
01046 int firstSpace = -1;
01047
01048 unsigned int startNum = 0;
01049
01050 for (unsigned int i = 0; i < strlen(line); i++) {
01051 if (!isdigit(line[i]) && !(i == startNum && line[i] == '-')) {
01052
01053 if (isspace(line[i])) {
01054 line[i] = '\0';
01055 if (firstSpace < 0) {
01056 firstSpace = i;
01057 startNum = i + 1;
01058 }
01059 else {
01060 break;
01061 }
01062 }
01063 else {
01064 isNumber = false;
01065 }
01066 break;
01067 }
01068 }
01069
01070 int x = atoi(line);
01071 int y = atoi(&line[firstSpace + 1]);
01072
01073 loadDataPoint(x, y);
01074
01075 return true;
01076
01077 }
01078
01079
01080
01081
01082 void ArMap::loadDataPoint(double x, double y)
01083 {
01084 if (x > myLoadingMax.getX())
01085 myLoadingMax.setX(x);
01086 if (y > myLoadingMax.getY())
01087 myLoadingMax.setY(y);
01088
01089 if (x < myLoadingMin.getX())
01090 myLoadingMin.setX(x);
01091 if (y < myLoadingMin.getY())
01092 myLoadingMin.setY(y);
01093
01094 myLoadingPoints.push_back(ArPose(x, y));
01095 myLoadingPointsRead++;
01096
01097 }
01098
01099
01100 bool ArMap::readLineSegment(char *line)
01101 {
01102 if (line == NULL) {
01103 return false;
01104 }
01105
01106
01107 ArArgumentBuilder builder;
01108 builder.add(line);
01109
01110 if (builder.getArgc() < 4)
01111 return false;
01112
01113 loadLineSegment(builder.getArgInt(0), builder.getArgInt(1),
01114 builder.getArgInt(2), builder.getArgInt(3));
01115
01116 return true;
01117
01118 }
01119
01120 void ArMap::loadLineSegment(double x1, double y1, double x2, double y2)
01121 {
01122 if (x1 > myLoadingLineMax.getX())
01123 myLoadingLineMax.setX(x1);
01124 if (y1 > myLoadingLineMax.getY())
01125 myLoadingLineMax.setY(y1);
01126
01127 if (x1 < myLoadingLineMin.getX())
01128 myLoadingLineMin.setX(x1);
01129 if (y1 < myLoadingLineMin.getY())
01130 myLoadingMin.setY(y1);
01131
01132 if (x2 > myLoadingLineMax.getX())
01133 myLoadingLineMax.setX(x2);
01134 if (y2 > myLoadingLineMax.getY())
01135 myLoadingLineMax.setY(y2);
01136
01137 if (x2 < myLoadingLineMin.getX())
01138 myLoadingLineMin.setX(x2);
01139 if (y2 < myLoadingLineMin.getY())
01140 myLoadingMin.setY(y2);
01141
01142 myLoadingLines.push_back(ArLineSegment(x1, y1, x2, y2));
01143 myLoadingLinesRead++;
01144
01145 }
01146
01152 AREXPORT void ArMap::parsingComplete(void)
01153 {
01154 lock();
01155 setMapObjects(&myLoadingMapObjects);
01156 setPoints(&myLoadingPoints);
01157 setLines(&myLoadingLines);
01158 setMapInfo(&myLoadingMapInfo);
01159
01160 for (int i = 0; i < myNumInfos; i++) {
01161 setInfo(i, &myLoadingInfoArray[i]);
01162 }
01163
01164
01165 myResolution = myLoadingResolution;
01166 ArLog::log(ArLog::Normal, "Loaded map from parsing");
01167 myFileName = "";
01168
01169 reset();
01170
01171 mapChanged();
01172 unlock();
01173 }
01174
01175 AREXPORT void ArMap::mapChanged(void)
01176 {
01177 std::list<ArFunctor *>::iterator it;
01178
01179 ArLog::LogLevel level = myMapChangedLogLevel;
01180 ArFunctor *functor;
01181
01182 bool isAnyInfoChanged = false;
01183 for (int i = 0; i < myNumInfos; i++) {
01184 if (abs(myMapChangedInfoArray[i].mSecSince(myInfoChangedArray[i])) > 0) {
01185 isAnyInfoChanged = true;
01186 break;
01187 }
01188 }
01189 ArLog::log(level, "ArMap: Calling mapChanged callbacks");
01190 if (abs(myMapChangedMapObjects.mSecSince(myMapObjectsChanged)) > 0 ||
01191 abs(myMapChangedPoints.mSecSince(myPointsChanged)) > 0 ||
01192 abs(myMapChangedMapInfo.mSecSince(myMapInfoChanged)) > 0 ||
01193 isAnyInfoChanged)
01194
01195 {
01196 for (it = myPreMapChangedCBList.begin();
01197 it != myPreMapChangedCBList.end();
01198 it++)
01199 {
01200 functor = (*it);
01201 if (functor->getName() != NULL && functor->getName()[0] != '\0')
01202 ArLog::log(level, "ArMap: Calling preMapChanged functor '%s'",
01203 functor->getName());
01204 else
01205 ArLog::log(level, "ArMap: Calling unnamed preMapChanged functor");
01206
01207 functor->invoke();
01208 }
01209
01210 for (it = myMapChangedCBList.begin(); it != myMapChangedCBList.end(); it++)
01211 {
01212 functor = (*it);
01213 if (functor->getName() != NULL && functor->getName()[0] != '\0')
01214 ArLog::log(level, "ArMap: Calling mapChanged functor '%s'",
01215 functor->getName());
01216 else
01217 ArLog::log(level, "ArMap: Calling unnamed mapChanged functor");
01218
01219 functor->invoke();
01220 }
01221 }
01222 myMapChangedMapObjects = myMapObjectsChanged;
01223 myMapChangedPoints = myPointsChanged;
01224 myMapChangedMapInfo = myMapInfoChanged;
01225
01226 for (int i = 0; i < myNumInfos; i++) {
01227 myMapChangedInfoArray[i] = myInfoChangedArray[i];
01228 }
01229 ArLog::log(level, "ArMap: Done calling mapChanged callbacks");
01230 }
01231
01232
01237 AREXPORT void ArMap::writeToFunctor(ArFunctor1<const char *> *functor,
01238 const char *endOfLineChars)
01239 {
01240
01241 writeObjectsToFunctor(functor, endOfLineChars);
01242
01243 if (myLines.begin() != myLines.end())
01244 {
01245
01246 std::vector<ArLineSegment>::iterator lineIt;
01247
01248 ArUtil::functorPrintf(functor, "LINES%s", endOfLineChars);
01249
01250 for (lineIt = myLines.begin();
01251 lineIt != myLines.end();
01252 lineIt++)
01253 {
01254 ArUtil::functorPrintf(functor, "%.0f %.0f %.0f %.0f%s",
01255 (*lineIt).getX1(), (*lineIt).getY1(),
01256 (*lineIt).getX2(), (*lineIt).getY2(),
01257 endOfLineChars);
01258 }
01259 }
01260
01261 ArUtil::functorPrintf(functor, "DATA%s", endOfLineChars);
01262
01263 if (myPoints.begin() != myPoints.end())
01264 {
01265
01266 std::vector<ArPose>::iterator pointIt;
01267
01268 for (pointIt = myPoints.begin();
01269 pointIt != myPoints.end();
01270 pointIt++)
01271 {
01272 ArUtil::functorPrintf(functor, "%.0f %.0f%s", (*pointIt).getX(),
01273 (*pointIt).getY(), endOfLineChars);
01274 }
01275 }
01276 }
01277
01278
01279 void ArMap::writeObjectsToFunctor
01280 (ArFunctor1<const char *> *functor,
01281 const char *endOfLineChars)
01282 {
01283 std::list<ArMapObject *>::iterator mapObjectIt;
01284
01285 std::list<ArArgumentBuilder *>::iterator mapInfoIt;
01286
01287
01288
01289 ArUtil::functorPrintf(functor, "2D-Map%s", endOfLineChars);
01290 if (myNumPoints != 0)
01291 {
01292 ArUtil::functorPrintf(functor, "MinPos: %.0f %.0f%s",
01293 myMin.getX(), myMin.getY(), endOfLineChars);
01294 ArUtil::functorPrintf(functor, "MaxPos: %.0f %.0f%s",
01295 myMax.getX(), myMax.getY(), endOfLineChars);
01296 ArUtil::functorPrintf(functor, "NumPoints: %d%s",
01297 myNumPoints, endOfLineChars);
01298 }
01299 if (myResolution != -1)
01300 ArUtil::functorPrintf(functor, "Resolution: %d%s", myResolution,
01301 endOfLineChars);
01302 if (myNumLines != 0)
01303 {
01304 ArUtil::functorPrintf(functor, "LineMinPos: %.0f %.0f%s",
01305 myLineMin.getX(), myLineMin.getY(), endOfLineChars);
01306 ArUtil::functorPrintf(functor, "LineMaxPos: %.0f %.0f%s",
01307 myLineMax.getX(), myLineMax.getY(), endOfLineChars);
01308 ArUtil::functorPrintf(functor, "NumLines: %d%s",
01309 myNumLines, endOfLineChars);
01310 }
01311 for (mapInfoIt = myMapInfo.begin();
01312 mapInfoIt != myMapInfo.end();
01313 mapInfoIt++)
01314 ArUtil::functorPrintf(functor, "MapInfo: %s%s",
01315 (*mapInfoIt)->getFullString(),
01316 endOfLineChars);
01317
01318 for (int i = 0; i < myNumInfos; i++) {
01319 const char *infoName = getInfoName(i);
01320 if (infoName == NULL) {
01321 ArLog::log(ArLog::Normal, "ArMap: Cannot find Info tag for index %i, not saving...",
01322 i);
01323 continue;
01324 }
01325
01326 for (std::list<ArArgumentBuilder *>::iterator infoIt = myInfoArray[i].begin();
01327 infoIt != myInfoArray[i].end();
01328 infoIt++) {
01329
01330 ArUtil::functorPrintf(functor, "%s %s%s",
01331 infoName,
01332 (*infoIt)->getFullString(),
01333 endOfLineChars);
01334
01335 }
01336 }
01337
01347 for (mapObjectIt = myMapObjects.begin();
01348 mapObjectIt != myMapObjects.end();
01349 mapObjectIt++)
01350 {
01351 ArMapObject *object = (*mapObjectIt);
01352 if (object->hasFromTo())
01353 ArUtil::functorPrintf(functor,
01354 "Cairn: %s %g %g %g \"%s\" %s \"%s\" %.0f %.0f %.0f %.0f%s",
01355 object->getType(), object->getPose().getX(),
01356 object->getPose().getY(), object->getPose().getTh(),
01357 object->getFileName(), object->getIconName(),
01358 object->getName(), object->getFromPose().getX(),
01359 object->getFromPose().getY(),
01360 object->getToPose().getX(), object->getToPose().getY(),
01361 endOfLineChars);
01362 else
01363 ArUtil::functorPrintf(functor,
01364 "Cairn: %s %g %g %g \"%s\" %s \"%s\"%s",
01365 object->getType(), object->getPose().getX(),
01366 object->getPose().getY(), object->getPose().getTh(),
01367 object->getFileName(), object->getIconName(),
01368 object->getName(), endOfLineChars);
01369 }
01370
01371 }
01372
01373
01374 void ArMap::writePointsToFunctor
01375 (ArFunctor2<int, std::vector<ArPose> *> *functor)
01376 {
01377 functor->invoke(myNumPoints, &myPoints);
01378 }
01379
01380 void ArMap::writeLinesToFunctor
01381 (ArFunctor2<int, std::vector<ArLineSegment> *> *functor)
01382 {
01383 functor->invoke(myNumLines, &myLines);
01384 }
01385
01386
01387
01396 AREXPORT bool ArMap::writeFile(const char *fileName,
01397 bool internalCall)
01398 {
01399 FILE *file;
01400 if (!internalCall)
01401 lock();
01402
01403 std::string realFileName;
01404
01405 if (fileName[0] == '/' || fileName[0] == '\\')
01406 {
01407 realFileName = fileName;
01408 }
01409 else
01410 {
01411 realFileName = myBaseDirectory;
01412 realFileName += fileName;
01413 }
01414
01415
01416 if ((file = fopen(realFileName.c_str(), "w")) == NULL)
01417 {
01418 ArLog::log(ArLog::Terse, "ArMap: Cannot open file '%s' for writing",
01419 realFileName.c_str());
01420 if (!internalCall)
01421 unlock();
01422 return false;
01423 }
01424
01425 ArGlobalFunctor2<const char *, FILE *> functor(&ArUtil::writeToFile, "", file);
01426 writeToFunctor(&functor, "\n");
01427
01428 fclose(file);
01429 ArLog::log(ArLog::Normal, "Saved map file %s", fileName);
01430 if (!internalCall)
01431 unlock();
01432 return true;
01433 }
01434
01435 AREXPORT bool ArMap::parseLine(char *line)
01436 {
01437 return myLoadingParser->parseLine(line);
01438 }
01439
01441
01448 AREXPORT ArMapObject *ArMap::findMapObject(const char *name,
01449 const char *type)
01450 {
01451 std::list<ArMapObject *>::iterator objIt;
01452 ArMapObject* obj;
01453
01454 for (objIt = getMapObjects()->begin();
01455 objIt != getMapObjects()->end();
01456 objIt++)
01457 {
01458 obj = (*objIt);
01459 if(obj == NULL)
01460 return NULL;
01461
01462 if (type == NULL || strcasecmp(obj->getType(), type) == 0)
01463 {
01464 if(name == NULL || strcasecmp(obj->getName(), name) == 0)
01465 {
01466 return obj;
01467 }
01468 }
01469 }
01470
01471
01472 return NULL;
01473 }
01474
01475 const char *ArMap::getInfoName(int infoType)
01476 {
01477 if ((infoType >= 0) && (infoType < INFO_COUNT)) {
01478 return ourInfoNames[infoType];
01479 }
01480 else {
01481 return NULL;
01482 }
01483 }
01484
01493 AREXPORT ArMapObject *ArMap::findFirstMapObject(const char *name,
01494 const char *type)
01495 {
01496 std::list<ArMapObject *>::iterator objIt;
01497 ArMapObject* obj;
01498
01499 for (objIt = getMapObjects()->begin();
01500 objIt != getMapObjects()->end();
01501 objIt++)
01502 {
01503 obj = (*objIt);
01504 if(obj == NULL)
01505 return NULL;
01506
01507 if (type == NULL || strcasecmp(obj->getType(), type) == 0)
01508 {
01509 if(name == NULL || strcasecmp(obj->getName(), name) == 0)
01510 {
01511 return obj;
01512 }
01513 }
01514 }
01515
01516
01517 return NULL;
01518 }