Main Page | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages | Examples

ArServerHandlerMap.cpp

Go to the documentation of this file.
00001 /*
00002 MobileRobots Advanced Robotics Interface for Applications (ARIA)
00003 Copyright (C) 2004, 2005 ActivMedia Robotics LLC
00004 Copyright (C) 2006, 2007 MobileRobots Inc.
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 MobileRobots for information about a commercial version of ARIA at 
00022 robots@mobilerobots.com or 
00023 MobileRobots Inc, 19 Columbia Drive, Amherst, NH 03031; 800-639-9481
00024 */
00025 
00026 #include "Aria.h"
00027 #include "ArExport.h"
00028 #include "ArServerHandlerMap.h"
00029 #ifdef WIN32
00030 #include <sys/types.h>
00031 #include <sys/stat.h>
00032 #endif
00033 
00034 
00045 AREXPORT ArServerHandlerMap::ArServerHandlerMap(ArServerBase *server, 
00046                                                 ArMap *arMap,
00047                                                 DataToSend dataToSend) :
00048   myGetMapNameCB(this, &ArServerHandlerMap::serverGetMapName),
00049   myGetMapCB(this, &ArServerHandlerMap::serverGetMap),
00050   myGetMapBinaryCB(this, &ArServerHandlerMap::serverGetMapBinary),
00051   myGetGoalsCB(this, &ArServerHandlerMap::serverGetGoals),
00052   myProcessFileCB(this, &ArServerHandlerMap::processFile),
00053   myMapChangedCB(this, &ArServerHandlerMap::mapChanged)
00054 {
00055   myServer = server;
00056   myOwnMap = false;
00057   myMap = arMap;
00058   setDataToSend(dataToSend);
00059   myMapChangedCB.setName("ArServerHandlerMap");
00060   myProcessFileCB.setName("ArServerHandlerMap");
00061   if (myMap != NULL)
00062   {
00063     strcpy(myMapFileName, myMap->getFileName());
00064     myAlreadyLoaded = false;
00065     myOwnMap = false;
00066     myMap->addMapChangedCB(&myMapChangedCB, ArListPos::FIRST);
00067   }
00068   else
00069   {
00070     myMapFileName[0] = '\0';
00071     Aria::getConfig()->addParam(ArConfigArg("Map", myMapFileName, 
00072                                             "map file to load", 
00073                                             sizeof(myMapFileName)),
00074               "Files", 
00075               ArPriority::IMPORTANT);
00076     Aria::getConfig()->setSectionComment("Files", 
00077                                          "The files where important data is stored");
00078     Aria::getConfig()->addProcessFileCB(&myProcessFileCB, 95);
00079   }
00080 
00081 
00082   if (myServer != NULL)
00083   {
00084     myServer->addData("getMapName", "gets the name of the map being used",
00085                       &myGetMapNameCB, "none", "string: map name (empty string if no maps)", "Map", "RETURN_SINGLE");
00086 
00087     // The "getMapBinary" request replaces the old text-based "getMap" request.
00088     myServer->addData("getMapBinary", "gets the map objects as ascii and the data points as binary", 
00089                       &myGetMapBinaryCB, 
00090                       "none", 
00091                       "packets of '<string>: line' for header, followed by packets of '<byte4>: numPtsInPacket, (<double>:x, <double>:y)*' until numPtsInPacket == 0",
00092                       "Map", "RETURN_UNTIL_EMPTY");
00093         myServer->addData("getMap", "gets the map as a set of ascii lines", 
00094                             &myGetMapCB, "none", 
00095                           "packets of '<string>: line' followed by a packet with an empty string to denote end (if only empty string then no map)",
00096                           "Map", "RETURN_UNTIL_EMPTY");
00097     myServer->addData("mapUpdated", "a single packet is sent to this when the map is updated and this denotes a new getMap and getMapName should be requested", 
00098                       NULL, "none", "none", 
00099                       "Map", "RETURN_SINGLE");
00100     myServer->addData("getGoals", "gets the list of goals", 
00101                       &myGetGoalsCB, "none", 
00102                       "<repeat> string: goal", "Map", "RETURN_SINGLE");
00103     myServer->addData("goalsUpdated", "a single packet is sent to this when the goals are updated and this denotes a new getGoals should be requested", 
00104                       NULL, "none", "none", 
00105                       "Map", "RETURN_SINGLE");
00106 
00107   }
00108 }
00109 
00110 AREXPORT ArServerHandlerMap::~ArServerHandlerMap()
00111 {
00112   
00113 }
00114 
00115 AREXPORT bool ArServerHandlerMap::loadMap(const char *mapFile)
00116 {
00117   bool ret;
00118   ArNetPacket emptyPacket;
00119   if (myMap != NULL)
00120   {
00121     if (myOwnMap)
00122       delete myMap;
00123     myMap = NULL;
00124   }
00125   myMap = new ArMap(NULL, false);
00126   myMapName = mapFile;
00127   myOwnMap = true;
00128   ret = myMap->readFile(mapFile);
00129   myServer->broadcastPacketTcp(&emptyPacket, "mapUpdated");
00130   myServer->broadcastPacketTcp(&emptyPacket, "goalsUpdated");
00131   return ret;
00132 }
00133 
00137 AREXPORT void ArServerHandlerMap::useMap(ArMap *mapObj, 
00138                                          bool takeOwnershipOfMap)
00139 {
00140   ArNetPacket emptyPacket;
00141   if (myMap != NULL)
00142   {
00143     if (myOwnMap)
00144       delete myMap;
00145     myMap = NULL;
00146   }
00147   myMap = mapObj;
00148   myMapName = myMap->getFileName();
00149   myOwnMap = takeOwnershipOfMap;
00150   myServer->broadcastPacketTcp(&emptyPacket, "mapUpdated");
00151   myServer->broadcastPacketTcp(&emptyPacket, "goalsUpdated");
00152 }
00153 
00154 AREXPORT ArMap *ArServerHandlerMap::getMap(void)
00155 {
00156   return myMap;
00157 }
00158 
00160 AREXPORT void ArServerHandlerMap::serverGetMapName(ArServerClient *client, 
00161                                             ArNetPacket *packet)
00162 {
00163   ArNetPacket sendPacket;
00164   if (myMap == NULL)
00165   {
00166     sendPacket.strToBuf("");
00167     client->sendPacketTcp(&sendPacket);
00168   }
00169   else
00170   {
00171     sendPacket.strToBuf(myMap->getFileName());
00172     client->sendPacketTcp(&sendPacket);
00173   }
00174 }
00175 
00177 AREXPORT void ArServerHandlerMap::writeMapToClient(const char *line,
00178                                          ArServerClient *client)
00179 {
00180   ArNetPacket sendPacket;
00181   sendPacket.strToBuf(line);
00182   client->sendPacketTcp(&sendPacket);
00183 }
00184 
00186 AREXPORT void ArServerHandlerMap::writePointsToClient(
00187         int pointCount,
00188         std::vector<ArPose> *points,
00189         ArServerClient *client)
00190 {
00191   ArNetPacket sendPacket;
00192   
00193   // Should never happen...
00194   if (points == NULL) {
00195     // Send 0 points just so the client doesn't hang
00196     sendPacket.byte4ToBuf(0);
00197     client->sendPacketTcp(&sendPacket);
00198     return;
00199   }
00200   
00201   ArLog::log(ArLog::Verbose, 
00202              "ArServerHandlerMap::writePointsToClient() pointCount = %i, vector size = %i", 
00203              pointCount, (int) points->size());
00204   
00205   // Neither should this, but just in case...
00206   if (pointCount > (int) points->size()) {
00207     pointCount = points->size();
00208   }
00209   
00210   int maxInPacketCount = 1000; // Maximum number of points sent in a packet
00211   int currentCount = 0;         // Number put into the current packet 
00212   int remainingCount = pointCount; // Total number of points remaining to be sent
00213   bool isStartPacket = true;    // Whether a new packet is being started
00214   
00215   int totalCount = 0;
00216   
00217   for (std::vector<ArPose>::iterator pointIt = points->begin(); 
00218        pointIt != points->end();
00219        pointIt++) {
00220     
00221     // Start a new packet if the previous one was sent (or there is no 
00222     // previous one)
00223     if (isStartPacket) {
00224       
00225       isStartPacket = false;
00226       
00227       sendPacket.empty();
00228       currentCount = 0;
00229       
00230       // Leftover points...
00231       if (maxInPacketCount > remainingCount) {
00232         maxInPacketCount = remainingCount;
00233       }
00234       
00235       // The first item in the packet is the number of points contained
00236       sendPacket.byte4ToBuf(maxInPacketCount);
00237       
00238     } // end if starting a new packet
00239     
00240     // Add the current point to the packet (think that the test should 
00241     // always be true)
00242     if (currentCount < maxInPacketCount) {
00243       
00244       currentCount++;
00245       remainingCount--;
00246       
00247       sendPacket.byte4ToBuf(
00248               ArMath::roundInt((*pointIt).getX()));
00249       sendPacket.byte4ToBuf(
00250               ArMath::roundInt((*pointIt).getY()));
00251     }
00252     
00253     // If the packet is full, send it and then start a new one
00254     if (currentCount == maxInPacketCount) {
00255       
00256       totalCount += currentCount;
00257       
00258       client->sendPacketTcp(&sendPacket);
00259       //ArUtil::sleep(1);
00260       
00261       isStartPacket = true;
00262     }
00263     
00264   } // end for each point
00265   
00266   ArLog::log(ArLog::Verbose, 
00267              "ArServerHandlerMap::writePointsToClient() totalCount = %i", 
00268              totalCount);
00269   
00270   // Send 0 points to indicate that all have been sent
00271   sendPacket.empty();
00272   sendPacket.byte4ToBuf(0);
00273   client->sendPacketTcp(&sendPacket);
00274   
00275 } // end writePointsToClient
00276 
00278 AREXPORT void ArServerHandlerMap::writeLinesToClient(
00279         int lineCount,
00280         std::vector<ArLineSegment> *lines,
00281         ArServerClient *client)
00282 {
00283   ArNetPacket sendPacket;
00284   
00285   // Should never happen...
00286   if (lines == NULL) {
00287     // Send 0 points just so the client doesn't hang
00288     sendPacket.byte4ToBuf(0);
00289     client->sendPacketTcp(&sendPacket);
00290     return;
00291   }
00292   
00293   ArLog::log(ArLog::Verbose, 
00294              "ArServerHandlerMap::writeLinesToClient() pointCount = %i, vector size = %i", 
00295              lineCount, (int) lines->size());
00296   
00297   // Neither should this, but just in case...
00298   if (lineCount > (int) lines->size()) {
00299     lineCount = lines->size();
00300   }
00301   
00302   int maxInPacketCount = 1000; // Maximum number of points sent in a packet
00303   int currentCount = 0;         // Number put into the current packet 
00304   int remainingCount = lineCount; // Total number of points remaining to be sent
00305   bool isStartPacket = true;    // Whether a new packet is being started
00306   
00307   int totalCount = 0;
00308   
00309   for (std::vector<ArLineSegment>::iterator lineIt = lines->begin(); 
00310        lineIt != lines->end();
00311        lineIt++) 
00312   {
00313     
00314     // Start a new packet if the previous one was sent (or there is no 
00315     // previous one)
00316     if (isStartPacket) {
00317       
00318       isStartPacket = false;
00319       
00320       sendPacket.empty();
00321       currentCount = 0;
00322       
00323       // Leftover points...
00324       if (maxInPacketCount > remainingCount) {
00325         maxInPacketCount = remainingCount;
00326       }
00327       
00328       // The first item in the packet is the number of points contained
00329       sendPacket.byte4ToBuf(maxInPacketCount);
00330       
00331     } // end if starting a new packet
00332     
00333     // Add the current point to the packet (think that the test should 
00334     // always be true)
00335     if (currentCount < maxInPacketCount) {
00336       
00337       currentCount++;
00338       remainingCount--;
00339       
00340       sendPacket.byte4ToBuf(
00341               ArMath::roundInt((*lineIt).getX1()));
00342       sendPacket.byte4ToBuf(
00343               ArMath::roundInt((*lineIt).getY1()));
00344       sendPacket.byte4ToBuf(
00345               ArMath::roundInt((*lineIt).getX2()));
00346       sendPacket.byte4ToBuf(
00347               ArMath::roundInt((*lineIt).getY2()));
00348     }
00349     
00350     // If the packet is full, send it and then start a new one
00351     if (currentCount == maxInPacketCount) {
00352       
00353       totalCount += currentCount;
00354       
00355       client->sendPacketTcp(&sendPacket);
00356       //ArUtil::sleep(1);
00357       
00358       isStartPacket = true;
00359     }
00360     
00361   } // end for each point
00362   
00363   ArLog::log(ArLog::Verbose, 
00364              "ArServerHandlerMap::writePointsToClient() totalCount = %i", 
00365              totalCount);
00366   
00367   // Send 0 points to indicate that all have been sent
00368   sendPacket.empty();
00369   sendPacket.byte4ToBuf(0);
00370   client->sendPacketTcp(&sendPacket);
00371   
00372 } // end writePointsToClient
00373 
00374 
00376 AREXPORT void ArServerHandlerMap::serverGetMap(ArServerClient *client, 
00377                                         ArNetPacket *packet)
00378 {
00379   ArLog::log(ArLog::Verbose, "Starting sending map to client");
00380   if (myMap == NULL)
00381   {
00382     writeMapToClient("", client);
00383     return;
00384   }
00385 
00386   myMap->lock();
00387   // This functor is used to send the entire map in text format.
00388   ArFunctor1<const char *> *functor = 
00389                 new ArFunctor2C<ArServerHandlerMap, const char *, ArServerClient *>
00390                                         (this, 
00391                                          &ArServerHandlerMap::writeMapToClient,
00392                                          NULL,
00393                                          client);
00394   // Send the map 
00395   myMap->writeToFunctor(functor, "");
00396 
00397   delete functor;
00398   // Send an empty packet to indicate the end of the map.
00399   writeMapToClient("", client);
00400 
00401   // send an empty packet to say we're done
00402   ArNetPacket emptyPacket;
00403   client->sendPacketTcp(&emptyPacket);
00404 
00405   myMap->unlock();
00406   ArLog::log(ArLog::Verbose, "Finished sending map to client");
00407 
00408 }
00409 
00410 AREXPORT void ArServerHandlerMap::serverGetMapBinary(ArServerClient *client, 
00411                                                                                                          ArNetPacket *packet)
00412 {
00413   ArLog::log(ArLog::Verbose, "Starting sending map (binary) to client");
00414   if (myMap == NULL)
00415   {
00416     writeMapToClient("", client);
00417     return;
00418   }
00419 
00420   myMap->lock();
00421   // This functor is used to send the map header and objects in text format.
00422   ArFunctor1<const char *> *textFunctor = 
00423                 new ArFunctor2C<ArServerHandlerMap, const char *, ArServerClient *>
00424                                         (this, 
00425                                          &ArServerHandlerMap::writeMapToClient,
00426                                          NULL,
00427                                          client);
00428 
00429   // This functor is used to send the map data points in binary format (since
00430   // it is faster).
00431   ArFunctor2<int, std::vector<ArLineSegment> *> *linesFunctor =
00432           new ArFunctor3C<ArServerHandlerMap, int, std::vector<ArLineSegment> *, ArServerClient *>
00433                                    (this,
00434                                     &ArServerHandlerMap::writeLinesToClient,
00435                                     0,
00436                                     NULL,
00437                                     client);
00438 
00439   // This functor is used to send the map data points in binary format (since
00440   // it is faster).
00441   ArFunctor2<int, std::vector<ArPose> *> *pointsFunctor =
00442           new ArFunctor3C<ArServerHandlerMap, int, std::vector<ArPose> *, ArServerClient *>
00443                                    (this,
00444                                     &ArServerHandlerMap::writePointsToClient,
00445                                     0,
00446                                     NULL,
00447                                     client);
00448 
00449   // Send the map up to and including the DATA tag.
00450   myMap->writeObjectsToFunctor(textFunctor, "");
00451 
00452   // see if we want to send the lines and make sure we have lines
00453   if ((myDataToSend == LINES || myDataToSend == BOTH) && 
00454       myMap->getLines()->begin() != myMap->getLines()->end())
00455   {
00456     writeMapToClient("LINES", client);
00457     myMap->writeLinesToFunctor(linesFunctor);
00458   }
00459 
00460   // Always write the points (even if empty) because this signifies
00461   // the end of the map for the client.
00462   //if (myMap->getPoints()->begin() != myMap->getPoints()->end())
00463   //{
00464   writeMapToClient("DATA", client);
00465   // if we want to send points then send 'em
00466   if (myDataToSend == POINTS || myDataToSend == BOTH)
00467     myMap->writePointsToFunctor(pointsFunctor);
00468   // if not just say we're done
00469   else
00470     writeMapToClient("", client);
00471   //}
00472 
00473   // send an empty packet to say we're done
00474   ArNetPacket emptyPacket;
00475   client->sendPacketTcp(&emptyPacket);
00476 
00477   myMap->unlock();
00478   ArLog::log(ArLog::Verbose, "Finished sending map (binary) to client");
00479 
00480 }
00481 
00482 
00484 AREXPORT void ArServerHandlerMap::serverGetGoals(ArServerClient *client, 
00485                                                  ArNetPacket *packet)
00486 {
00487   std::list<ArMapObject *>::iterator objIt;
00488   ArMapObject* obj;
00489   ArPose goal;  
00490   ArNetPacket sendPacket;
00491 
00492   for (objIt = myMap->getMapObjects()->begin(); 
00493        objIt != myMap->getMapObjects()->end(); 
00494        objIt++)
00495   {
00496     //
00497     // Get the forbidden lines and fill the occupancy grid there.
00498     //
00499     obj = (*objIt);
00500     if (obj == NULL)
00501       break;
00502     if (strcasecmp(obj->getType(), "GoalWithHeading") == 0 ||
00503         strcasecmp(obj->getType(), "Goal") == 0)
00504     {
00505       sendPacket.strToBuf(obj->getName());
00506     }
00507   }
00508   client->sendPacketTcp(&sendPacket);
00509 }
00510 
00511 AREXPORT void ArServerHandlerMap::mapChanged(void)
00512 {
00513   ArNetPacket emptyPacket;
00514   strcpy(myMapFileName, myMap->getFileName());
00515   myServer->broadcastPacketTcp(&emptyPacket, "mapUpdated");
00516   myServer->broadcastPacketTcp(&emptyPacket, "goalsUpdated");
00517 }
00518 
00520 AREXPORT bool ArServerHandlerMap::processFile(void)
00521 {
00522   struct stat mapFileStat;
00523 
00524   if (myMapFileName[0] == '\0')
00525   {
00526     ArLog::log(ArLog::Verbose, "ArServerHandlerMap::processFile: No map file");
00527     return true;
00528   }
00529 
00530   if (stat(myMapFileName, &mapFileStat) != 0)
00531   {
00532     ArLog::log(ArLog::Terse, "Cannot stat file");
00533     return false;
00534   }
00535  // see if we need to load the map file
00536   if (!myAlreadyLoaded || strcmp(myMapFileName, myLastMapFile) != 0 ||
00537       mapFileStat.st_mtime != myLastMapFileStat.st_mtime || 
00538       mapFileStat.st_ctime != myLastMapFileStat.st_ctime)
00539   {
00540     myAlreadyLoaded = true; 
00541     strcpy(myLastMapFile, myMapFileName);
00542     memcpy(&myLastMapFileStat, &mapFileStat, sizeof(mapFileStat));
00543 
00544     ArLog::log(ArLog::Terse, "Loading map %s", myMapFileName);
00545     if (!loadMap(myMapFileName))
00546     {
00547       ArLog::log(ArLog::Terse, "Failed loading map %s", myMapFileName);
00548       return false;
00549     }
00550     ArLog::log(ArLog::Terse, "Loaded map %s", myMapFileName);
00551     return true;
00552   }
00553   myAlreadyLoaded = true;
00554   ArLog::log(ArLog::Normal, "ArServerHandlerMapConfig: File did not need reloading");
00555   return true;
00556 }
00557 

Generated on Tue Feb 20 10:51:50 2007 for ArNetworking by  doxygen 1.4.0