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
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),
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
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
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
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123 }
00124
00125 bool ArMap::processFile(char *errorBuffer, size_t errorBufferLen)
00126 {
00127 struct stat mapFileStat;
00128 stat(myConfigMapName, &mapFileStat);
00129
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
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
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
00216
00217
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
00247
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
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
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
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
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424 arg->compressQuoted();
00425
00426
00427 size_t fileLen = strlen(arg->getArg(4)) + 1;
00428 char *fileBuffer = new char[fileLen];
00429
00430
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
00467
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
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
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
00523 myLoadingParser->remHandler(&myResolutionCB);
00524
00525
00526
00527 myLoadingParser->remHandler(&myLineCB);
00528
00529
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
00540 }
00541
00542 bool ArMap::handleLines(ArArgumentBuilder *arg)
00543 {
00544
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
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
00561
00562
00563 myLoadingParser->remHandler(&myPointCB);
00564
00565
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
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 {
00623
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
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
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
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
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 }
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
00910 if (myLoadingLinesAndDataStarted)
00911 {
00912
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
00928
00929 while (fgets(line, sizeof(line), file) != NULL)
00930 {
00931 if (!readDataPoint(line))
00932 {
00933 continue;
00934 }
00935 }
00936
00937 fclose(file);
00938
00939
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
00950
00951 myResolution = myLoadingResolution;
00952
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 }
00992
00993 int x = atoi(line);
00994 int y = atoi(&line[firstSpace + 1]);
00995
00996 loadDataPoint(x, y);
00997
00998 return true;
00999
01000 }
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 }
01021
01022
01023 bool ArMap::readLineSegment(char *line)
01024 {
01025 if (line == NULL) {
01026 return false;
01027 }
01028
01029
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
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
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
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
01150 writeObjectsToFunctor(functor, endOfLineChars);
01151
01152 if (myLines.begin() != myLines.end())
01153 {
01154
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
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
01194 std::list<ArArgumentBuilder *>::iterator mapInfoIt;
01195
01196
01197
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 }
01245 }
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
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
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
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
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 }